This is an automated email from the ASF dual-hosted git repository. lgallinat pushed a commit to branch feature/GEODE-4017 in repository https://gitbox.apache.org/repos/asf/geode.git
commit a27b7ca6026238af91c5b7b9aadd777a2fd4e881 Author: Lynn Gallinat <lgalli...@pivotal.io> AuthorDate: Thu Dec 7 17:43:07 2017 -0800 GEODE-4017 Add alter connection command --- .../jdbc/internal/ConnectionConfigBuilder.java | 12 +- ...java => ConnectionConfigNotFoundException.java} | 26 +-- .../jdbc/internal/ConnectionConfiguration.java | 11 +- .../internal/InternalJdbcConnectorService.java | 3 + .../jdbc/internal/JdbcConnectorService.java | 13 ++ .../jdbc/internal/cli/AlterConnectionCommand.java | 139 +++++++++++++ .../jdbc/internal/cli/AlterConnectionFunction.java | 116 +++++++++++ .../org.springframework.shell.core.CommandMarker | 3 +- .../jdbc/internal/JdbcConnectorServiceTest.java | 11 ++ .../cli/AlterConnectionCommandDUnitTest.java | 132 +++++++++++++ .../cli/AlterConnectionCommandIntegrationTest.java | 79 ++++++++ .../internal/cli/AlterConnectionFunctionTest.java | 220 +++++++++++++++++++++ .../internal/cli/CreateConnectionFunctionTest.java | 4 + 13 files changed, 745 insertions(+), 24 deletions(-) diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigBuilder.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigBuilder.java index c03034b..480517f 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigBuilder.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigBuilder.java @@ -48,10 +48,14 @@ public class ConnectionConfigBuilder { } public ConnectionConfigBuilder withParameters(String[] params) { - for (String param : params) { - String[] keyValuePair = param.split(PARAMS_DELIMITER); - if (keyValuePair.length == 2) { - parameters.put(keyValuePair[0], keyValuePair[1]); + if (params == null) { + parameters = null; + } else { + for (String param : params) { + String[] keyValuePair = param.split(PARAMS_DELIMITER); + if (keyValuePair.length == 2) { + parameters.put(keyValuePair[0], keyValuePair[1]); + } } } return this; diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigNotFoundException.java similarity index 56% copy from geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java copy to geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigNotFoundException.java index c242255..0c74d3b 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfigNotFoundException.java @@ -14,24 +14,18 @@ */ package org.apache.geode.connectors.jdbc.internal; -import java.util.Set; +public class ConnectionConfigNotFoundException extends Exception { -import org.apache.geode.cache.Cache; -import org.apache.geode.internal.cache.CacheService; -import org.apache.geode.internal.cache.extension.Extension; + public ConnectionConfigNotFoundException() { + super(); + } -public interface InternalJdbcConnectorService extends Extension<Cache>, CacheService { + public ConnectionConfigNotFoundException(String message) { + super(message); + } - void createConnectionConfig(ConnectionConfiguration config) - throws ConnectionConfigExistsException; + public ConnectionConfigNotFoundException(String message, Throwable cause) { + super(message, cause); + } - void destroyConnectionConfig(String connectionName); - - ConnectionConfiguration getConnectionConfig(String connectionName); - - Set<ConnectionConfiguration> getConnectionConfigs(); - - void addOrUpdateRegionMapping(RegionMapping mapping); - - RegionMapping getMappingForRegion(String regionName); } diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfiguration.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfiguration.java index 72b4aa8..0254817 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfiguration.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/ConnectionConfiguration.java @@ -36,8 +36,7 @@ public class ConnectionConfiguration implements Serializable { this.url = url; this.user = user; this.password = password; - this.parameters = - parameters == null ? new HashMap<>() : Collections.unmodifiableMap(parameters); + this.parameters = parameters == null ? null : Collections.unmodifiableMap(parameters); } public String getName() { @@ -56,10 +55,16 @@ public class ConnectionConfiguration implements Serializable { return password; } + public Map<String, String> getParameters() { + return parameters; + } + public Properties getConnectionProperties() { Properties properties = new Properties(); - properties.putAll(parameters); + if (parameters != null) { + properties.putAll(parameters); + } if (user != null) { properties.put(USER, user); } diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java index c242255..8241c66 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java @@ -25,6 +25,9 @@ public interface InternalJdbcConnectorService extends Extension<Cache>, CacheSer void createConnectionConfig(ConnectionConfiguration config) throws ConnectionConfigExistsException; + void replaceConnectionConfig(ConnectionConfiguration config) + throws ConnectionConfigNotFoundException; + void destroyConnectionConfig(String connectionName); ConnectionConfiguration getConnectionConfig(String connectionName); diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java index 8192c75..b6b2f07 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java @@ -46,6 +46,19 @@ public class JdbcConnectorService implements InternalJdbcConnectorService { } @Override + public void replaceConnectionConfig(ConnectionConfiguration alteredConfig) + throws ConnectionConfigNotFoundException { + registerAsExtension(); + ConnectionConfiguration existingConfig = connectionsByName.get(alteredConfig.getName()); + if (existingConfig == null) { + throw new ConnectionConfigNotFoundException( + "ConnectionConfiguration " + alteredConfig.getName() + " was not found"); + } + + connectionsByName.put(existingConfig.getName(), alteredConfig); + } + + @Override public void destroyConnectionConfig(String connectionName) { registerAsExtension(); connectionsByName.remove(connectionName); diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommand.java new file mode 100644 index 0000000..bace38d --- /dev/null +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommand.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.connectors.jdbc.internal.cli; + +import java.util.List; +import java.util.Set; + +import org.springframework.shell.core.annotation.CliCommand; +import org.springframework.shell.core.annotation.CliOption; + +import org.apache.geode.cache.execute.ResultCollector; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfigBuilder; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration; +import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.management.cli.CliMetaData; +import org.apache.geode.management.cli.Result; +import org.apache.geode.management.internal.cli.commands.GfshCommand; +import org.apache.geode.management.internal.cli.functions.CliFunctionResult; +import org.apache.geode.management.internal.cli.i18n.CliStrings; +import org.apache.geode.management.internal.cli.result.ResultBuilder; +import org.apache.geode.management.internal.cli.result.TabularResultData; +import org.apache.geode.management.internal.configuration.domain.XmlEntity; +import org.apache.geode.management.internal.security.ResourceOperation; +import org.apache.geode.security.ResourcePermission; + +public class AlterConnectionCommand implements GfshCommand { + static final String ALTER_JDBC_CONNECTION = "alter jdbc-connection"; + static final String ALTER_JDBC_CONNECTION__HELP = + "Alter properties for an existing jdbc connection."; + + static final String ALTER_CONNECTION__NAME = "name"; + static final String ALTER_CONNECTION__NAME__HELP = "Name of the connection to be altered."; + static final String ALTER_CONNECTION__URL = "url"; + static final String ALTER_CONNECTION__URL__HELP = "New URL location for the database."; + static final String ALTER_CONNECTION__USER = "user"; + static final String ALTER_CONNECTION__USER__HELP = + "New user name to use when connecting to database."; + static final String ALTER_CONNECTION__PASSWORD = "password"; + static final String ALTER_CONNECTION__PASSWORD__HELP = + "New password to use when connecting to database."; + static final String ALTER_CONNECTION__PARAMS = "params"; + static final String ALTER_CONNECTION__PARAMS__HELP = + "New additional parameters to use when connecting to the database. This replaces all previously existing parameters."; + + private static final String ERROR_PREFIX = "ERROR: "; + + @CliCommand(value = ALTER_JDBC_CONNECTION, help = ALTER_JDBC_CONNECTION__HELP) + @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE) + @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER, + operation = ResourcePermission.Operation.MANAGE) + public Result alterConnection( + @CliOption(key = ALTER_CONNECTION__NAME, mandatory = true, + help = ALTER_CONNECTION__NAME__HELP) String name, + @CliOption(key = ALTER_CONNECTION__URL, specifiedDefaultValue = "", + help = ALTER_CONNECTION__URL__HELP) String url, + @CliOption(key = ALTER_CONNECTION__USER, specifiedDefaultValue = "", + help = ALTER_CONNECTION__USER__HELP) String user, + @CliOption(key = ALTER_CONNECTION__PASSWORD, specifiedDefaultValue = "", + help = ALTER_CONNECTION__PASSWORD__HELP) String password, + @CliOption(key = ALTER_CONNECTION__PARAMS, specifiedDefaultValue = "", + help = ALTER_CONNECTION__PARAMS__HELP) String[] params) { + // input + Set<DistributedMember> targetMembers = getMembers(null, null); + ConnectionConfiguration configuration = getArguments(name, url, user, password, params); + + // action + ResultCollector<CliFunctionResult, List<CliFunctionResult>> resultCollector = + execute(new AlterConnectionFunction(), configuration, targetMembers); + + // output + TabularResultData tabularResultData = ResultBuilder.createTabularResultData(); + XmlEntity xmlEntity = fillTabularResultData(resultCollector, tabularResultData); + Result result = ResultBuilder.buildResult(tabularResultData); + updateClusterConfiguration(result, xmlEntity); + return result; + } + + ResultCollector<CliFunctionResult, List<CliFunctionResult>> execute( + AlterConnectionFunction function, ConnectionConfiguration configuration, + Set<DistributedMember> targetMembers) { + return (ResultCollector<CliFunctionResult, List<CliFunctionResult>>) executeFunction(function, + configuration, targetMembers); + } + + private ConnectionConfiguration getArguments(String name, String url, String user, + String password, String[] params) { + ConnectionConfigBuilder builder = new ConnectionConfigBuilder().withName(name).withUrl(url) + .withUser(user).withPassword(password).withParameters(params); + return builder.build(); + } + + private XmlEntity fillTabularResultData( + ResultCollector<CliFunctionResult, List<CliFunctionResult>> resultCollector, + TabularResultData tabularResultData) { + XmlEntity xmlEntity = null; + + for (CliFunctionResult oneResult : resultCollector.getResult()) { + if (oneResult.isSuccessful()) { + xmlEntity = addSuccessToResults(tabularResultData, oneResult); + } else { + addErrorToResults(tabularResultData, oneResult); + } + } + + return xmlEntity; + } + + private XmlEntity addSuccessToResults(TabularResultData tabularResultData, + CliFunctionResult oneResult) { + tabularResultData.accumulate("Member", oneResult.getMemberIdOrName()); + tabularResultData.accumulate("Status", oneResult.getMessage()); + return oneResult.getXmlEntity(); + } + + private void addErrorToResults(TabularResultData tabularResultData, CliFunctionResult oneResult) { + tabularResultData.accumulate("Member", oneResult.getMemberIdOrName()); + tabularResultData.accumulate("Status", ERROR_PREFIX + oneResult.getMessage()); + tabularResultData.setStatus(Result.Status.ERROR); + } + + private void updateClusterConfiguration(final Result result, final XmlEntity xmlEntity) { + if (xmlEntity != null) { + persistClusterConfiguration(result, + () -> getSharedConfiguration().addXmlEntity(xmlEntity, null)); + } + } +} diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunction.java new file mode 100644 index 0000000..c6316a2 --- /dev/null +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunction.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.connectors.jdbc.internal.cli; + +import java.util.Map; + +import org.apache.geode.cache.execute.Function; +import org.apache.geode.cache.execute.FunctionContext; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfigNotFoundException; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration; +import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService; +import org.apache.geode.internal.InternalEntity; +import org.apache.geode.management.internal.cli.functions.CliFunctionResult; +import org.apache.geode.management.internal.configuration.domain.XmlEntity; + +public class AlterConnectionFunction implements Function<ConnectionConfiguration>, InternalEntity { + + private static final String ID = AlterConnectionFunction.class.getName(); + + private final FunctionContextArgumentProvider argumentProvider; + private final ExceptionHandler exceptionHandler; + + AlterConnectionFunction() { + this(new FunctionContextArgumentProvider(), new ExceptionHandler()); + } + + private AlterConnectionFunction(FunctionContextArgumentProvider argumentProvider, + ExceptionHandler exceptionHandler) { + this.argumentProvider = argumentProvider; + this.exceptionHandler = exceptionHandler; + } + + @Override + public boolean isHA() { + return false; + } + + @Override + public String getId() { + return ID; + } + + @Override + public void execute(FunctionContext<ConnectionConfiguration> context) { + try { + // input + ConnectionConfiguration connectionConfig = context.getArguments(); + InternalJdbcConnectorService service = argumentProvider.getJdbcConnectorService(context); + ConnectionConfiguration existingConfig = + service.getConnectionConfig(connectionConfig.getName()); + if (existingConfig == null) { + throw new ConnectionConfigNotFoundException( + "ConnectionConfiguration " + connectionConfig.getName() + " was not found"); + } + + // action + ConnectionConfiguration alteredConfig = + alterConnectionConfig(connectionConfig, existingConfig); + service.replaceConnectionConfig(alteredConfig); + + // output + String member = argumentProvider.getMember(context); + XmlEntity xmlEntity = argumentProvider.createXmlEntity(context); + CliFunctionResult result = createSuccessResult(connectionConfig.getName(), member, xmlEntity); + context.getResultSender().lastResult(result); + + } catch (Exception e) { + exceptionHandler.handleException(context, e); + } + } + + /** + * Creates the named connection configuration + */ + ConnectionConfiguration alterConnectionConfig(ConnectionConfiguration connectionConfig, + ConnectionConfiguration existingConfig) throws ConnectionConfigNotFoundException { + String url = getValue(connectionConfig.getUrl(), existingConfig.getUrl()); + String user = getValue(connectionConfig.getUser(), existingConfig.getUser()); + String password = getValue(connectionConfig.getPassword(), existingConfig.getPassword()); + + Map<String, String> parameters = connectionConfig.getParameters(); + if (parameters == null) { + parameters = existingConfig.getParameters(); + } + ConnectionConfiguration alteredConfig = + new ConnectionConfiguration(existingConfig.getName(), url, user, password, parameters); + return alteredConfig; + } + + private String getValue(String newValue, String existingValue) { + // if newValue is null use the value already in the config + // if newValue is the empty string, then "unset" it by returning null + if (newValue == null) { + return existingValue; + } + return newValue.isEmpty() ? null : newValue; + } + + private CliFunctionResult createSuccessResult(String connectionName, String member, + XmlEntity xmlEntity) { + String message = "Altered JDBC connection " + connectionName + " on " + member; + return new CliFunctionResult(member, xmlEntity, message); + } +} diff --git a/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker b/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker index 60e3207..b9e2a72 100644 --- a/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker +++ b/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker @@ -14,7 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Lucene Extensions command +# JDBC Connector Extension commands org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand org.apache.geode.connectors.jdbc.internal.cli.DestroyConnectionCommand org.apache.geode.connectors.jdbc.internal.cli.ListConnectionCommand +org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand \ No newline at end of file diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorServiceTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorServiceTest.java index 0a85da9..85f719f 100644 --- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorServiceTest.java +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorServiceTest.java @@ -16,9 +16,13 @@ package org.apache.geode.connectors.jdbc.internal; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.entry; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.HashMap; +import java.util.Map; + import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -35,6 +39,7 @@ public class JdbcConnectorServiceTest { private ConnectionConfiguration config; private ConnectionConfiguration config2; + private ConnectionConfiguration configToAlter; private RegionMapping mapping; private JdbcConnectorService service; @@ -45,6 +50,11 @@ public class JdbcConnectorServiceTest { config = mock(ConnectionConfiguration.class); mapping = mock(RegionMapping.class); config2 = mock(ConnectionConfiguration.class); + Map<String, String> parameters = new HashMap<>(); + parameters.put("key1", "value1"); + parameters.put("key2", "value2"); + configToAlter = new ConnectionConfiguration(TEST_CONFIG_NAME, "originalUrl", "originalUser", + "originalPassword", parameters); when(cache.getExtensionPoint()).thenReturn(mock(ExtensionPoint.class)); when(config.getName()).thenReturn(TEST_CONFIG_NAME); @@ -102,4 +112,5 @@ public class JdbcConnectorServiceTest { assertThatThrownBy(() -> service.createConnectionConfig(config2)) .isInstanceOf(ConnectionConfigExistsException.class).hasMessageContaining(TEST_CONFIG_NAME); } + } diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommandDUnitTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommandDUnitTest.java new file mode 100644 index 0000000..836029c --- /dev/null +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommandDUnitTest.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.connectors.jdbc.internal.cli; + +import static org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand.ALTER_CONNECTION__NAME; +import static org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand.ALTER_CONNECTION__PARAMS; +import static org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand.ALTER_CONNECTION__PASSWORD; +import static org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand.ALTER_CONNECTION__URL; +import static org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand.ALTER_CONNECTION__USER; +import static org.apache.geode.connectors.jdbc.internal.cli.AlterConnectionCommand.ALTER_JDBC_CONNECTION; +import static org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION; +import static org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__NAME; +import static org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__PARAMS; +import static org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__PASSWORD; +import static org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__URL; +import static org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__USER; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration; +import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService; +import org.apache.geode.distributed.internal.InternalLocator; +import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.management.internal.cli.util.CommandStringBuilder; +import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; +import org.apache.geode.test.dunit.rules.MemberVM; +import org.apache.geode.test.junit.rules.GfshCommandRule; +import org.apache.geode.test.junit.rules.serializable.SerializableTestName; + +public class AlterConnectionCommandDUnitTest { + + @Rule + public transient GfshCommandRule gfsh = new GfshCommandRule(); + + @Rule + public LocatorServerStartupRule startupRule = new LocatorServerStartupRule(); + + @Rule + public SerializableTestName testName = new SerializableTestName(); + + private MemberVM locator; + private MemberVM server; + + @Before + public void before() throws Exception { + locator = startupRule.startLocatorVM(0); + server = startupRule.startServerVM(1, locator.getPort()); + + gfsh.connectAndVerify(locator); + + CommandStringBuilder csb = new CommandStringBuilder(CREATE_CONNECTION); + csb.addOption(CREATE_CONNECTION__NAME, "name"); + csb.addOption(CREATE_CONNECTION__URL, "url"); + csb.addOption(CREATE_CONNECTION__USER, "username"); + csb.addOption(CREATE_CONNECTION__PASSWORD, "secret"); + csb.addOption(CREATE_CONNECTION__PARAMS, "param1:value1,param2:value2"); + + gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess(); + } + + @Test + public void altersConnectionWithNewValues() throws Exception { + CommandStringBuilder csb = new CommandStringBuilder(ALTER_JDBC_CONNECTION); + csb.addOption(ALTER_CONNECTION__NAME, "name"); + csb.addOption(ALTER_CONNECTION__URL, "newUrl"); + csb.addOption(ALTER_CONNECTION__USER, "newUsername"); + csb.addOption(ALTER_CONNECTION__PASSWORD, "newPassword"); + csb.addOption(ALTER_CONNECTION__PARAMS, "Key1:Value1,Key22:Value22"); + gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess(); + + + locator.invoke(() -> { + String xml = InternalLocator.getLocator().getSharedConfiguration().getConfiguration("cluster") + .getCacheXmlContent(); + assertThat(xml).isNotNull().contains("jdbc:connector-service"); + }); + + server.invoke(() -> { + InternalCache cache = LocatorServerStartupRule.getCache(); + ConnectionConfiguration config = + cache.getService(InternalJdbcConnectorService.class).getConnectionConfig("name"); + assertThat(config.getUrl()).isEqualTo("newUrl"); + assertThat(config.getUser()).isEqualTo("newUsername"); + assertThat(config.getPassword()).isEqualTo("newPassword"); + assertThat(config.getConnectionProperties()).containsEntry("Key1", "Value1") + .containsEntry("Key22", "Value22"); + }); + } + + @Test + public void altersConnectionByRemovingValues() { + CommandStringBuilder csb = new CommandStringBuilder(ALTER_JDBC_CONNECTION); + csb.addOption(ALTER_CONNECTION__NAME, "name"); + csb.addOption(ALTER_CONNECTION__URL, ""); + csb.addOption(ALTER_CONNECTION__USER, ""); + csb.addOption(ALTER_CONNECTION__PASSWORD, ""); + csb.addOption(ALTER_CONNECTION__PARAMS, ""); + + gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess(); + + locator.invoke(() -> { + String xml = InternalLocator.getLocator().getSharedConfiguration().getConfiguration("cluster") + .getCacheXmlContent(); + assertThat(xml).isNotNull().contains("jdbc:connector-service"); + }); + + server.invoke(() -> { + InternalCache cache = LocatorServerStartupRule.getCache(); + ConnectionConfiguration config = + cache.getService(InternalJdbcConnectorService.class).getConnectionConfig("name"); + assertThat(config.getUrl()).isNull(); + assertThat(config.getUser()).isNull(); + assertThat(config.getPassword()).isNull(); + assertThat(config.getConnectionProperties()).hasSize(0); + }); + } +} diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommandIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommandIntegrationTest.java new file mode 100644 index 0000000..bc00618 --- /dev/null +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionCommandIntegrationTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.connectors.jdbc.internal.cli; + +import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.apache.geode.cache.CacheFactory; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration; +import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService; +import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.management.cli.Result; + +public class AlterConnectionCommandIntegrationTest { + + private InternalCache cache; + private AlterConnectionCommand alterConnectionCommand; + + private String name; + + @Before + public void setup() throws Exception { + name = "name"; + String url = "url"; + String user = "user"; + String password = "password"; + String[] params = new String[] {"param1:value1", "param2:value2"}; + + cache = (InternalCache) new CacheFactory().set(ENABLE_CLUSTER_CONFIGURATION, "true").create(); + (new CreateConnectionCommand()).createConnection(name, url, user, password, params); + + alterConnectionCommand = new AlterConnectionCommand(); + } + + @After + public void tearDown() { + cache.close(); + } + + @Test + public void altersConnectionConfigurationInService() throws Exception { + String[] newParams = new String[] {"key1:value1", "key2:value2"}; + Result result = + alterConnectionCommand.alterConnection(name, "newUrl", "newUser", "newPassword", newParams); + + assertThat(result.getStatus()).isSameAs(Result.Status.OK); + + InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class); + ConnectionConfiguration connectionConfig = service.getConnectionConfig(name); + + assertThat(connectionConfig).isNotNull(); + assertThat(connectionConfig.getName()).isEqualTo(name); + assertThat(connectionConfig.getUrl()).isEqualTo("newUrl"); + assertThat(connectionConfig.getUser()).isEqualTo("newUser"); + assertThat(connectionConfig.getPassword()).isEqualTo("newPassword"); + assertThat(connectionConfig.getConnectionProperties()).containsEntry("key1", "value1") + .containsEntry("key2", "value2"); + } + +} diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunctionTest.java new file mode 100644 index 0000000..4b4aa06 --- /dev/null +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunctionTest.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.connectors.jdbc.internal.cli; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.entry; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.SerializationUtils; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import org.apache.geode.cache.execute.FunctionContext; +import org.apache.geode.cache.execute.ResultSender; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfigBuilder; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfigExistsException; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfigNotFoundException; +import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration; +import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService; +import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.distributed.DistributedSystem; +import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.management.internal.cli.functions.CliFunctionResult; + +public class AlterConnectionFunctionTest { + + private static final String CONNECTION_NAME = "theConnection"; + + private ConnectionConfiguration connectionConfig; + private ConnectionConfiguration existingConfig; + private ConnectionConfiguration configToAlter; + private FunctionContext<ConnectionConfiguration> context; + private ResultSender<Object> resultSender; + private InternalJdbcConnectorService service; + + private AlterConnectionFunction function; + + @Before + public void setUp() throws Exception { + context = mock(FunctionContext.class); + resultSender = mock(ResultSender.class); + InternalCache cache = mock(InternalCache.class); + DistributedSystem system = mock(DistributedSystem.class); + DistributedMember distributedMember = mock(DistributedMember.class); + service = mock(InternalJdbcConnectorService.class); + + connectionConfig = new ConnectionConfigBuilder().withName(CONNECTION_NAME).build(); + existingConfig = new ConnectionConfigBuilder().withName(CONNECTION_NAME).build(); + Map<String, String> parameters = new HashMap<>(); + parameters.put("key1", "value1"); + parameters.put("key2", "value2"); + configToAlter = new ConnectionConfiguration(CONNECTION_NAME, "originalUrl", "originalUser", + "originalPassword", parameters); + + when(context.getResultSender()).thenReturn(resultSender); + when(context.getCache()).thenReturn(cache); + when(cache.getDistributedSystem()).thenReturn(system); + when(system.getDistributedMember()).thenReturn(distributedMember); + when(context.getArguments()).thenReturn(connectionConfig); + when(cache.getService(eq(InternalJdbcConnectorService.class))).thenReturn(service); + + function = new AlterConnectionFunction(); + } + + @Test + public void isHAReturnsFalse() throws Exception { + assertThat(function.isHA()).isFalse(); + } + + @Test + public void getIdReturnsNameOfClass() throws Exception { + assertThat(function.getId()).isEqualTo(function.getClass().getName()); + } + + @Test + public void serializes() throws Exception { + Serializable original = function; + + Object copy = SerializationUtils.clone(original); + + assertThat(copy).isNotSameAs(original).isInstanceOf(AlterConnectionFunction.class); + } + + @Test + public void alterConnectionConfigThrowsConnectionNotFound() throws Exception { + AlterConnectionFunction alterFunction = mock(AlterConnectionFunction.class); + doThrow(ConnectionConfigNotFoundException.class).when(alterFunction) + .alterConnectionConfig(any(), any()); + + assertThatThrownBy(() -> alterFunction.alterConnectionConfig(connectionConfig, existingConfig)) + .isInstanceOf(ConnectionConfigNotFoundException.class); + } + + @Test + public void executeInvokesReplaceOnService() throws Exception { + when(service.getConnectionConfig(CONNECTION_NAME)).thenReturn(existingConfig); + function.execute(context); + + verify(service, times(1)).replaceConnectionConfig(any()); + } + + @Test + public void executeReportsErrorIfConnectionConfigNotFound() throws Exception { + doThrow(ConnectionConfigNotFoundException.class).when(service) + .replaceConnectionConfig(eq(connectionConfig)); + + function.execute(context); + + ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class); + verify(resultSender, times(1)).lastResult(argument.capture()); + assertThat(argument.getValue().getErrorMessage()).contains(CONNECTION_NAME); + } + + @Test + public void alterConnectionConfigUrl() throws Exception { + ConnectionConfiguration newConfigValues = + new ConnectionConfiguration(CONNECTION_NAME, "newUrl", null, null, null); + + ConnectionConfiguration alteredConfig = + function.alterConnectionConfig(newConfigValues, configToAlter); + + assertThat(alteredConfig.getName()).isEqualTo(CONNECTION_NAME); + assertThat(alteredConfig.getUrl()).isEqualTo("newUrl"); + assertThat(alteredConfig.getUser()).isEqualTo("originalUser"); + assertThat(alteredConfig.getPassword()).isEqualTo("originalPassword"); + Map<String, String> parameters = alteredConfig.getParameters(); + assertThat(parameters).containsOnly(entry("key1", "value1"), entry("key2", "value2")); + } + + @Test + public void alterConnectionConfigUser() throws Exception { + ConnectionConfiguration newConfigValues = + new ConnectionConfiguration(CONNECTION_NAME, null, "newUser", null, null); + + ConnectionConfiguration alteredConfig = + function.alterConnectionConfig(newConfigValues, configToAlter); + + assertThat(alteredConfig.getName()).isEqualTo(CONNECTION_NAME); + assertThat(alteredConfig.getUrl()).isEqualTo("originalUrl"); + assertThat(alteredConfig.getUser()).isEqualTo("newUser"); + assertThat(alteredConfig.getPassword()).isEqualTo("originalPassword"); + assertThat(alteredConfig.getParameters()).containsOnly(entry("key1", "value1"), + entry("key2", "value2")); + } + + @Test + public void alterConnectionConfigPassword() throws Exception { + ConnectionConfiguration newConfigValues = + new ConnectionConfiguration(CONNECTION_NAME, null, null, "newPassword", null); + + ConnectionConfiguration alteredConfig = + function.alterConnectionConfig(newConfigValues, configToAlter); + + assertThat(alteredConfig.getName()).isEqualTo(CONNECTION_NAME); + assertThat(alteredConfig.getUrl()).isEqualTo("originalUrl"); + assertThat(alteredConfig.getUser()).isEqualTo("originalUser"); + assertThat(alteredConfig.getPassword()).isEqualTo("newPassword"); + assertThat(alteredConfig.getParameters()).containsOnly(entry("key1", "value1"), + entry("key2", "value2")); + } + + @Test + public void alterConnectionConfigParameters() throws Exception { + Map<String, String> newParameters = new HashMap<>(); + newParameters.put("key1", "anotherValue1"); + newParameters.put("key8", "value8"); + ConnectionConfiguration newConfigValues = + new ConnectionConfiguration(CONNECTION_NAME, null, null, null, newParameters); + + ConnectionConfiguration alteredConfig = + function.alterConnectionConfig(newConfigValues, configToAlter); + + assertThat(alteredConfig.getName()).isEqualTo(CONNECTION_NAME); + assertThat(alteredConfig.getUrl()).isEqualTo("originalUrl"); + assertThat(alteredConfig.getUser()).isEqualTo("originalUser"); + assertThat(alteredConfig.getPassword()).isEqualTo("originalPassword"); + assertThat(alteredConfig.getParameters()).containsOnly(entry("key1", "anotherValue1"), + entry("key8", "value8")); + } + + @Test + public void alterConnectionConfigWithNothingToAlter() throws Exception { + ConnectionConfiguration newConfigValues = + new ConnectionConfiguration(CONNECTION_NAME, null, null, null, null); + + ConnectionConfiguration alteredConfig = + function.alterConnectionConfig(newConfigValues, configToAlter); + + assertThat(alteredConfig.getName()).isEqualTo(CONNECTION_NAME); + assertThat(alteredConfig.getUrl()).isEqualTo("originalUrl"); + assertThat(alteredConfig.getUser()).isEqualTo("originalUser"); + assertThat(alteredConfig.getPassword()).isEqualTo("originalPassword"); + assertThat(alteredConfig.getParameters()).containsOnly(entry("key1", "value1"), + entry("key2", "value2")); + } +} diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java index 882a8d0..228d58b 100644 --- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java @@ -16,6 +16,7 @@ package org.apache.geode.connectors.jdbc.internal.cli; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.entry; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -24,6 +25,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; import org.apache.commons.lang.SerializationUtils; import org.junit.Before; @@ -133,4 +136,5 @@ public class CreateConnectionFunctionTest { assertThat(argument.getValue().getErrorMessage()) .contains(ConnectionConfigExistsException.class.getName()); } + } -- To stop receiving notification emails like this one, please contact "commits@geode.apache.org" <commits@geode.apache.org>.