| /* |
| * 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.AssertionsForInterfaceTypes.assertThat; |
| |
| import java.io.File; |
| import java.util.List; |
| |
| import org.assertj.core.api.Assertions; |
| import org.junit.BeforeClass; |
| import org.junit.ClassRule; |
| import org.junit.Test; |
| |
| import org.apache.geode.cache.configuration.CacheConfig; |
| import org.apache.geode.cache.configuration.JndiBindingsType.JndiBinding; |
| import org.apache.geode.distributed.internal.InternalConfigurationPersistenceService; |
| import org.apache.geode.internal.jndi.JNDIInvoker; |
| import org.apache.geode.logging.internal.log4j.api.LogService; |
| import org.apache.geode.test.dunit.IgnoredException; |
| import org.apache.geode.test.dunit.SerializableRunnableIF; |
| import org.apache.geode.test.dunit.rules.ClusterStartupRule; |
| import org.apache.geode.test.dunit.rules.MemberVM; |
| import org.apache.geode.test.junit.rules.GfshCommandRule; |
| import org.apache.geode.test.junit.rules.VMProvider; |
| import org.apache.geode.util.test.TestUtil; |
| |
| public class CreateDataSourceCommandDUnitTest { |
| |
| private static MemberVM locator, server1, server2; |
| |
| @ClassRule |
| public static ClusterStartupRule cluster = new ClusterStartupRule(); |
| |
| @ClassRule |
| public static GfshCommandRule gfsh = new GfshCommandRule(); |
| |
| |
| @BeforeClass |
| public static void before() throws Exception { |
| locator = cluster.startLocatorVM(0); |
| server1 = cluster.startServerVM(1, "group1", locator.getPort()); |
| server2 = cluster.startServerVM(2, "group1", locator.getPort()); |
| |
| gfsh.connectAndVerify(locator); |
| } |
| |
| @Test |
| public void testCreateDataSource() throws Exception { |
| VMProvider.invokeInEveryMember( |
| () -> assertThat(JNDIInvoker.getNoOfAvailableDataSources()).isEqualTo(0), server1, server2); |
| |
| String URL = "jdbc:derby:memory:newDB;create=true"; |
| // create the data-source |
| gfsh.executeAndAssertThat( |
| "create data-source --name=jndi1 --username=myuser --password=mypass --pooled=false --url=\"" |
| + URL + "\"") |
| .statusIsSuccess().tableHasColumnOnlyWithValues("Member", "server-1", "server-2"); |
| |
| // verify cluster config is updated |
| locator.invoke(() -> { |
| InternalConfigurationPersistenceService ccService = |
| ClusterStartupRule.getLocator().getConfigurationPersistenceService(); |
| CacheConfig cacheConfig = ccService.getCacheConfig("cluster"); |
| List<JndiBinding> jndiBindings = cacheConfig.getJndiBindings(); |
| assertThat(jndiBindings.size()).isEqualTo(1); |
| JndiBinding jndiBinding = jndiBindings.get(0); |
| assertThat(jndiBinding.getJndiName()).isEqualTo("jndi1"); |
| assertThat(jndiBinding.getUserName()).isEqualTo("myuser"); |
| assertThat(jndiBinding.getPassword()).isEqualTo("mypass"); |
| assertThat(jndiBinding.getConnectionUrl()).isEqualTo(URL); |
| assertThat(jndiBinding.getType()).isEqualTo("SimpleDataSource"); |
| }); |
| |
| // verify datasource exists |
| VMProvider.invokeInEveryMember( |
| () -> assertThat(JNDIInvoker.getNoOfAvailableDataSources()).isEqualTo(1), server1, server2); |
| |
| // bounce server1 |
| server1.stop(false); |
| server1 = cluster.startServerVM(1, locator.getPort()); |
| |
| // verify it has recreated the datasource from cluster config |
| server1.invoke(() -> { |
| assertThat(JNDIInvoker.getNoOfAvailableDataSources()).isEqualTo(1); |
| assertThat(JNDIInvoker.getDataSource("jndi1")).isNotNull(); |
| }); |
| |
| verifyThatNonExistentClassCausesGfshToError(); |
| } |
| |
| @Test |
| public void testCreateDataSourceWithJarOptionDoesNotThrowDriverError() { |
| String URL = "jdbc:mysql://localhost/"; |
| IgnoredException.addIgnoredException( |
| "No suitable driver"); |
| IgnoredException.addIgnoredException( |
| "create data-source failed"); |
| IgnoredException.addIgnoredException( |
| "Failed to connect to \"mySqlDataSource\""); |
| |
| // aquire the jar to be used |
| final String jdbcJarName = "mysql-connector-java-8.0.15.jar"; |
| final String jdbcDriverClassName = "com.mysql.cj.jdbc.Driver"; |
| File mySqlDriverFile = loadTestResource("/" + jdbcJarName); |
| assertThat(mySqlDriverFile).exists(); |
| String jarFile = mySqlDriverFile.getAbsolutePath(); |
| |
| // attempt to create the data source without a deployed jar or a --driver-jar |
| gfsh.executeAndAssertThat( |
| "create data-source --name=mySqlDataSource --username=mySqlUser --password=mySqlPass --pooled=false --url=\"" |
| + URL + "\"") |
| .statusIsError(); |
| |
| gfsh.executeAndAssertThat("deploy --jar=" + jarFile).statusIsSuccess(); |
| |
| IgnoredException.removeAllExpectedExceptions(); |
| IgnoredException.addIgnoredException( |
| "create data-source failed"); |
| IgnoredException.addIgnoredException( |
| "Communications link failure"); |
| IgnoredException.addIgnoredException( |
| "Access denied for user 'mySqlUser'@'localhost'"); |
| IgnoredException.addIgnoredException( |
| "Failed to connect to \"mySqlDataSource\""); |
| |
| gfsh.executeAndAssertThat( |
| "create data-source --name=mySqlDataSource --username=mySqlUser --password=mySqlPass --url=\"" |
| + URL + "\" --jdbc-driver-class=" + jdbcDriverClassName) |
| .statusIsError().doesNotContainOutput("No suitable driver"); |
| |
| } |
| |
| private void verifyThatNonExistentClassCausesGfshToError() { |
| SerializableRunnableIF IgnoreClassNotFound = () -> { |
| IgnoredException ex = |
| new IgnoredException("non_existent_class_name"); |
| LogService.getLogger().info(ex.getAddMessage()); |
| }; |
| |
| server1.invoke(IgnoreClassNotFound); |
| server2.invoke(IgnoreClassNotFound); |
| |
| // create the binding |
| gfsh.executeAndAssertThat( |
| "create data-source --name=jndiBad --username=myuser --password=mypass --pooled --pooled-data-source-factory-class=non_existent_class_name --url=\"jdbc:derby:memory:newDB;create=true\"") |
| .statusIsError(); |
| } |
| |
| private File loadTestResource(String fileName) { |
| String filePath = TestUtil.getResourcePath(this.getClass(), fileName); |
| Assertions.assertThat(filePath).isNotNull(); |
| |
| return new File(filePath); |
| } |
| } |