Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

Commit

Permalink
[#370] Add option to configure database instance name
Browse files Browse the repository at this point in the history
Fixes #370
  • Loading branch information
Maxime Blais authored and Florent Biville committed Apr 24, 2020
1 parent e58c4c6 commit f16bd35
Show file tree
Hide file tree
Showing 16 changed files with 193 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public class LiquigraphCli {
)
private String graphDbUri;

@Parameter(
names = {"--database", "-db"},
description = "Graph DB database (remote only)"
)
private String database;

@Parameter(
names = {"--username", "-u"},
description = "Graph DB username (remote only)"
Expand Down Expand Up @@ -119,6 +125,7 @@ public static void main(String[] args) {
ConfigurationBuilder builder = new ConfigurationBuilder()
.withMasterChangelogLocation(fileName(cli.changelog))
.withUri(cli.graphDbUri)
.withDatabase(cli.database)
.withUsername(cli.username)
.withPassword(cli.password)
.withExecutionContexts(executionContexts(cli.executionContexts))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,21 @@ public final class Configuration {
private final ConnectionConfiguration connectionConfiguration;
private final ExecutionContexts executionContexts;
private final ExecutionMode executionMode;
private final String database;

Configuration(ChangelogLoader changelogLoader,
String masterChangelog,
ConnectionConfiguration connectionConfiguration,
ExecutionContexts executionContexts,
ExecutionMode executionMode) {
ExecutionMode executionMode,
String database) {

this.changelogLoader = changelogLoader;
this.masterChangelog = masterChangelog;
this.connectionConfiguration = connectionConfiguration;
this.executionContexts = executionContexts;
this.executionMode = executionMode;
this.database = database;
}

/**
Expand Down Expand Up @@ -98,7 +101,7 @@ public ChangelogWriter resolveWriter(Connection writeConnection,
}
if (executionMode instanceof DryRunMode) {
DryRunMode dryRunMode = (DryRunMode) executionMode;
return new ChangelogFileWriter(conditionPrinter, dryRunMode.getOutputFile());
return new ChangelogFileWriter(conditionPrinter, database, dryRunMode.getOutputFile());
}
throw new IllegalStateException("Unsupported <executionMode>: " + executionMode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public final class ConfigurationBuilder {
private String masterChangelog;
private Optional<DataSource> dataSource = Optional.empty();
private Optional<String> uri = Optional.empty();
private Optional<String> database = Optional.empty();
private Optional<String> username = Optional.empty();
private Optional<String> password = Optional.empty();
private ExecutionContexts executionContexts = ExecutionContexts.DEFAULT_CONTEXT;
Expand Down Expand Up @@ -86,6 +87,18 @@ public ConfigurationBuilder withDataSource(DataSource dataSource) {
return this;
}

/**
* Specifies the database to run changes on.
* If not specified, the driver will select the default instance.
*
* @param database database
* @return itself for chaining purposes
*/
public ConfigurationBuilder withDatabase(String database) {
this.database = Optional.ofNullable(database);
return this;
}

/**
* Specifies the username allowed to connect to the remote graph database instance.
* Please be sure to provide a password, if you provide a username, too.
Expand Down Expand Up @@ -197,7 +210,7 @@ public ConfigurationBuilder withChangelogLoader(ChangelogLoader changelogLoader)
public Configuration build() {
Collection<String> errors = new ArrayList<>();
errors.addAll(mandatoryOptionValidator.validate(changelogLoader, masterChangelog));
errors.addAll(datasourceConnectionValidator.validate(uri, dataSource));
errors.addAll(datasourceConnectionValidator.validate(uri, dataSource, database));
errors.addAll(executionModeValidator.validate(executionMode));
errors.addAll(userCredentialsOptionValidator.validate(username.orElse(null), password.orElse(null)));

Expand All @@ -210,13 +223,14 @@ public Configuration build() {
masterChangelog,
dataSourceConfiguration(),
executionContexts,
executionMode
executionMode,
database.orElse(null)
);
}

private ConnectionConfiguration dataSourceConfiguration() {
if (uri.isPresent()) {
return new ConnectionConfigurationByUri(uri.get(), username, password);
return new ConnectionConfigurationByUri(uri.get(), database, username, password);
}
return new ConnectionConfigurationByDataSource(dataSource.get(), username, password);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,70 +20,66 @@
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Optional;
import java.util.Properties;

import static org.liquigraph.core.exception.Throwables.propagate;

public class ConnectionConfigurationByUri implements ConnectionConfiguration {

private final String uri;
private final Optional<String> username;
private final Optional<String> password;
private final Properties properties;
private final UriConnectionSupplier connectionSupplier;

public ConnectionConfigurationByUri(String uri,
Optional<String> database,
Optional<String> username,
Optional<String> password) {

this(uri, username, password, DefaultUriConnectionSupplier.INSTANCE);
this(uri, database, username, password, DefaultUriConnectionSupplier.INSTANCE);
}

// visible for testing
ConnectionConfigurationByUri(String uri,
Optional<String> database,
Optional<String> username,
Optional<String> password,
UriConnectionSupplier connectionSupplier) {

this.uri = uri;
this.username = username;
this.password = password;
this.connectionSupplier = connectionSupplier;
this.properties = createProperties(database, username, password);
}

@Override
public Connection get() {
if (username.isPresent()) {
return connectionSupplier.getConnection(uri, username.get(), password.orElse(""));
}
return connectionSupplier.getConnection(uri);
return connectionSupplier.getConnection(uri, properties);
}


private static Properties createProperties(Optional<String> database, Optional<String> username, Optional<String> password) {
Properties props = new Properties();
username.ifPresent(user -> props.setProperty("user", user));
password.ifPresent(pw -> props.setProperty("password", pw));
database.ifPresent(db -> props.setProperty("database", db));
return props;
}

private enum DefaultUriConnectionSupplier implements UriConnectionSupplier {
INSTANCE;

@Override
public Connection getConnection(String uri) {
public Connection getConnection(String uri, Properties properties) {
try {
return DriverManager.getConnection(uri);
return DriverManager.getConnection(uri, properties);
} catch (SQLException e) {
throw propagate(e);
}
}

@Override
public Connection getConnection(String uri, String username, String password) {
try {
return DriverManager.getConnection(uri, username, password);
} catch (SQLException e) {
throw propagate(e);
}
}
}

// visible for testing
interface UriConnectionSupplier {
Connection getConnection(String uri);

Connection getConnection(String uri, String username, String password);
Connection getConnection(String uri, Properties properties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@

public class DatasourceConfigurationValidator {

public Collection<String> validate(Optional<String> uri, Optional<DataSource> dataSource) {
public Collection<String> validate(Optional<String> uri, Optional<DataSource> dataSource, Optional<String> database) {
if (uri.isPresent() == dataSource.isPresent()) {
return Collections.singletonList("Exactly one of JDBC URI or DataSource need to be configured");
}
if (database.isPresent() && dataSource.isPresent()) {
return Collections.singletonList("Database instance cannot be configured when configuring a DataSource");
}
return uri.map(DatasourceConfigurationValidator::validateConnectionString).orElse(emptyList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

public class UserCredentialsOptionValidator {

Expand All @@ -32,8 +33,23 @@ public class UserCredentialsOptionValidator {
public Collection<String> validate(String username, String password) {
if (username != null ^ password != null) {
return Collections.singletonList("Please provide both username and password, or none.");
} else {
}
return Collections.emptyList();
}


/**
* Validates the given user credentials are provided; username and password
*
* @param username the username to use to connect
* @param password the password corresponding to {@code username}
* @return a collection of Strings describing possible errors, an empty
* collection if no errors
*/
public Collection<String> validate(Optional<String> username, Optional<String> password) {
if (username.isPresent() && password.isPresent()) {
return Collections.emptyList();
}
return Collections.singletonList("Please provide username and password when providing a database.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ public class ChangelogFileWriter implements ChangelogWriter {
private static final Logger LOGGER = LoggerFactory.getLogger(ChangelogFileWriter.class);

private final ConditionPrinter conditionPrinter;
private final String database;
private final File outputFile;

public ChangelogFileWriter(ConditionPrinter conditionPrinter, File outputFile) {
public ChangelogFileWriter(ConditionPrinter conditionPrinter, String database, File outputFile) {
this.conditionPrinter = conditionPrinter;
this.database = database;
this.outputFile = outputFile;
}

Expand All @@ -56,6 +58,7 @@ public void write(Collection<Changeset> changelogsToInsert) {
writeNothingToPersist(path);
return;
}
writeHeaderMaybe(path);
for (Changeset changeset : changelogsToInsert) {
writeChangeset(changeset, path);
}
Expand All @@ -70,7 +73,20 @@ private void reinitializeFile(Path path) throws IOException {
}

private void writeNothingToPersist(Path path) throws IOException {
Files.write(path, Collections.singletonList("//Liquigraph: nothing to persist!"), StandardCharsets.UTF_8);
String nothingToDoMessage = String.format("//Liquigraph%s: nothing to persist!", databaseInstanceOrEmpty());
Files.write(path, Collections.singletonList(nothingToDoMessage), StandardCharsets.UTF_8);
}

private void writeHeaderMaybe(Path path) throws IOException {
if (database == null) {
return;
}
String header = String.format("//Liquigraph (instance: %s)", database);
Files.write(path, Collections.singletonList(header), StandardCharsets.UTF_8);
}

private String databaseInstanceOrEmpty() {
return database == null ? "" : " (instance " + database + ")";
}

private void writeChangeset(Changeset changeset, Path path) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.Properties;

import org.junit.rules.ExternalResource;
import org.liquigraph.core.exception.Throwables;
Expand All @@ -46,7 +47,7 @@ public BoltGraphDatabaseRule() {
@Override
public Connection newConnection() {
try {
Connection connection = DriverManager.getConnection(uri());
Connection connection = DriverManager.getConnection(uri(), props());
connection.setAutoCommit(false);
connections.add(connection);
return connection;
Expand All @@ -61,6 +62,18 @@ public String uri() {
return "jdbc:neo4j:" + controls.boltURI() + "?noSsl";
}

public Properties props() {
Properties props = new Properties();
username().ifPresent(user -> props.setProperty("user", user));
password().ifPresent(pw -> props.setProperty("password", pw));
return props;
}

@Override
public Optional<String> database() {
return Optional.empty();
}

@Override
public Optional<String> username() {
return Optional.empty();
Expand All @@ -71,6 +84,7 @@ public Optional<String> password() {
return Optional.empty();
}


protected void before() {
controls = builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public interface GraphDatabaseRule extends TestRule {

Connection newConnection();
String uri();
Optional<String> database();
Optional<String> username();
Optional<String> password();
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.Properties;

import static org.assertj.core.api.Assertions.assertThat;
import static org.liquigraph.core.exception.Throwables.propagate;
Expand Down Expand Up @@ -62,7 +63,7 @@ public Statement apply(Statement base, Description description) {
@Override
public Connection newConnection() {
try {
Connection connection = DriverManager.getConnection(uri, username, password);
Connection connection = DriverManager.getConnection(uri, props());
connection.setAutoCommit(false);
connections.add(connection);
return connection;
Expand All @@ -76,6 +77,18 @@ public String uri() {
return uri;
}

public Properties props() {
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
return props;
}

@Override
public Optional<String> database() {
return Optional.empty();
}

@Override
public Optional<String> username() {
return Optional.of(username);
Expand Down
Loading

0 comments on commit f16bd35

Please sign in to comment.