http://git-wip-us.apache.org/repos/asf/knox/blob/e5fd0622/gateway-server/src/test/java/org/apache/knox/gateway/topology/monitor/ZooKeeperConfigurationMonitorTest.java ---------------------------------------------------------------------- diff --cc gateway-server/src/test/java/org/apache/knox/gateway/topology/monitor/ZooKeeperConfigurationMonitorTest.java index 75cd5d0,0000000..2e753f1 mode 100644,000000..100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/topology/monitor/ZooKeeperConfigurationMonitorTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/topology/monitor/ZooKeeperConfigurationMonitorTest.java @@@ -1,355 -1,0 +1,368 @@@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.knox.gateway.topology.monitor; + +import org.apache.commons.io.FileUtils; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.curator.test.InstanceSpec; +import org.apache.curator.test.TestingCluster; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.service.config.remote.zk.ZooKeeperClientService; +import org.apache.knox.gateway.service.config.remote.zk.ZooKeeperClientServiceProvider; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.knox.test.TestUtils; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.data.ACL; +import org.easymock.EasyMock; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Test the ZooKeeperConfigMonitor WITHOUT SASL configured or znode ACLs applied. + * The implementation of the monitor is the same regardless, since the ACLs are defined by the ZooKeeper znode + * creator, and the SASL config is purely JAAS (and external to the implementation). + */ +public class ZooKeeperConfigurationMonitorTest { + + private static final String PATH_KNOX = "/knox"; + private static final String PATH_KNOX_CONFIG = PATH_KNOX + "/config"; + private static final String PATH_KNOX_PROVIDERS = PATH_KNOX_CONFIG + "/shared-providers"; + private static final String PATH_KNOX_DESCRIPTORS = PATH_KNOX_CONFIG + "/descriptors"; + + private static File testTmp; + private static File providersDir; + private static File descriptorsDir; + + private static TestingCluster zkCluster; + + private static CuratorFramework client; + + private GatewayConfig gc; + + + @BeforeClass + public static void setupSuite() throws Exception { + testTmp = TestUtils.createTempDir(ZooKeeperConfigurationMonitorTest.class.getName()); + File confDir = TestUtils.createTempDir(testTmp + "/conf"); + providersDir = TestUtils.createTempDir(confDir + "/shared-providers"); + descriptorsDir = TestUtils.createTempDir(confDir + "/descriptors"); + + configureAndStartZKCluster(); + } + + private static void configureAndStartZKCluster() throws Exception { + // Configure security for the ZK cluster instances + Map<String, Object> customInstanceSpecProps = new HashMap<>(); + customInstanceSpecProps.put("authProvider.1", "org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + customInstanceSpecProps.put("requireClientAuthScheme", "sasl"); + + // Define the test cluster + List<InstanceSpec> instanceSpecs = new ArrayList<>(); + for (int i = 0 ; i < 3 ; i++) { + InstanceSpec is = new InstanceSpec(null, -1, -1, -1, false, (i+1), -1, -1, customInstanceSpecProps); + instanceSpecs.add(is); + } + zkCluster = new TestingCluster(instanceSpecs); + + // Start the cluster + zkCluster.start(); + + // Create the client for the test cluster + client = CuratorFrameworkFactory.builder() + .connectString(zkCluster.getConnectString()) + .retryPolicy(new ExponentialBackoffRetry(100, 3)) + .build(); + assertNotNull(client); + client.start(); + + // Create the knox config paths with an ACL for the sasl user configured for the client + List<ACL> acls = new ArrayList<>(); + acls.add(new ACL(ZooDefs.Perms.ALL, ZooDefs.Ids.ANYONE_ID_UNSAFE)); + + client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_DESCRIPTORS); + assertNotNull("Failed to create node:" + PATH_KNOX_DESCRIPTORS, - client.checkExists().forPath(PATH_KNOX_DESCRIPTORS)); ++ client.checkExists().forPath(PATH_KNOX_DESCRIPTORS)); + client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_PROVIDERS); + assertNotNull("Failed to create node:" + PATH_KNOX_PROVIDERS, - client.checkExists().forPath(PATH_KNOX_PROVIDERS)); ++ client.checkExists().forPath(PATH_KNOX_PROVIDERS)); + } + + @AfterClass + public static void tearDownSuite() throws Exception { + // Clean up the ZK nodes, and close the client + if (client != null) { + client.delete().deletingChildrenIfNeeded().forPath(PATH_KNOX); + client.close(); + } + + // Shutdown the ZK cluster + zkCluster.close(); + + // Delete the working dir + testTmp.delete(); + } + + @Test + public void testZooKeeperConfigMonitor() throws Exception { + String configMonitorName = "remoteConfigMonitorClient"; + + // Setup the base GatewayConfig mock + gc = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes(); + EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes(); + EasyMock.expect(gc.getRemoteRegistryConfigurationNames()) + .andReturn(Collections.singletonList(configMonitorName)) + .anyTimes(); + final String registryConfig = + GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString(); + EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName)) + .andReturn(registryConfig) + .anyTimes(); + EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes(); + EasyMock.replay(gc); + + AliasService aliasService = EasyMock.createNiceMock(AliasService.class); + EasyMock.replay(aliasService); + + RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance(); + clientService.setAliasService(aliasService); + clientService.init(gc, Collections.emptyMap()); + clientService.start(); + + DefaultRemoteConfigurationMonitor cm = new DefaultRemoteConfigurationMonitor(gc, clientService); + ++ // Create a provider configuration in the test ZK, prior to starting the monitor, to make sure that the monitor ++ // will download existing entries upon starting. ++ final String preExistingProviderConfig = getProviderPath("pre-existing-providers.xml"); ++ client.create().withMode(CreateMode.PERSISTENT).forPath(preExistingProviderConfig, ++ TEST_PROVIDERS_CONFIG_1.getBytes()); ++ File preExistingProviderConfigLocalFile = new File(providersDir, "pre-existing-providers.xml"); ++ assertFalse("This file should not exist locally prior to monitor starting.", ++ preExistingProviderConfigLocalFile.exists()); ++ + try { + cm.start(); + } catch (Exception e) { + fail("Failed to start monitor: " + e.getMessage()); + } + ++ assertTrue("This file should exist locally immediately after monitor starting.", ++ preExistingProviderConfigLocalFile.exists()); ++ ++ + try { + final String pc_one_znode = getProviderPath("providers-config1.xml"); + final File pc_one = new File(providersDir, "providers-config1.xml"); + final String pc_two_znode = getProviderPath("providers-config2.xml"); + final File pc_two = new File(providersDir, "providers-config2.xml"); + + client.create().withMode(CreateMode.PERSISTENT).forPath(pc_one_znode, TEST_PROVIDERS_CONFIG_1.getBytes()); + Thread.sleep(100); + assertTrue(pc_one.exists()); + assertEquals(TEST_PROVIDERS_CONFIG_1, FileUtils.readFileToString(pc_one)); + + client.create().withMode(CreateMode.PERSISTENT).forPath(getProviderPath("providers-config2.xml"), TEST_PROVIDERS_CONFIG_2.getBytes()); + Thread.sleep(100); + assertTrue(pc_two.exists()); + assertEquals(TEST_PROVIDERS_CONFIG_2, FileUtils.readFileToString(pc_two)); + + client.setData().forPath(pc_two_znode, TEST_PROVIDERS_CONFIG_1.getBytes()); + Thread.sleep(100); + assertTrue(pc_two.exists()); + assertEquals(TEST_PROVIDERS_CONFIG_1, FileUtils.readFileToString(pc_two)); + + client.delete().forPath(pc_two_znode); + Thread.sleep(100); + assertFalse(pc_two.exists()); + + client.delete().forPath(pc_one_znode); + Thread.sleep(100); + assertFalse(pc_one.exists()); + + final String desc_one_znode = getDescriptorPath("test1.json"); + final String desc_two_znode = getDescriptorPath("test2.json"); + final String desc_three_znode = getDescriptorPath("test3.json"); + final File desc_one = new File(descriptorsDir, "test1.json"); + final File desc_two = new File(descriptorsDir, "test2.json"); + final File desc_three = new File(descriptorsDir, "test3.json"); + + client.create().withMode(CreateMode.PERSISTENT).forPath(desc_one_znode, TEST_DESCRIPTOR_1.getBytes()); + Thread.sleep(100); + assertTrue(desc_one.exists()); + assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_one)); + + client.create().withMode(CreateMode.PERSISTENT).forPath(desc_two_znode, TEST_DESCRIPTOR_1.getBytes()); + Thread.sleep(100); + assertTrue(desc_two.exists()); + assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_two)); + + client.setData().forPath(desc_two_znode, TEST_DESCRIPTOR_2.getBytes()); + Thread.sleep(100); + assertTrue(desc_two.exists()); + assertEquals(TEST_DESCRIPTOR_2, FileUtils.readFileToString(desc_two)); + + client.create().withMode(CreateMode.PERSISTENT).forPath(desc_three_znode, TEST_DESCRIPTOR_1.getBytes()); + Thread.sleep(100); + assertTrue(desc_three.exists()); + assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_three)); + + client.delete().forPath(desc_two_znode); + Thread.sleep(100); + assertFalse("Expected test2.json to have been deleted.", desc_two.exists()); + + client.delete().forPath(desc_three_znode); + Thread.sleep(100); + assertFalse(desc_three.exists()); + + client.delete().forPath(desc_one_znode); + Thread.sleep(100); + assertFalse(desc_one.exists()); + } finally { + cm.stop(); + } + } + + private static String getDescriptorPath(String descriptorName) { + return PATH_KNOX_DESCRIPTORS + "/" + descriptorName; + } + + private static String getProviderPath(String providerConfigName) { + return PATH_KNOX_PROVIDERS + "/" + providerConfigName; + } + + + private static final String TEST_PROVIDERS_CONFIG_1 = + "<gateway>\n" + + " <provider>\n" + + " <role>identity-assertion</role>\n" + + " <name>Default</name>\n" + + " <enabled>true</enabled>\n" + + " </provider>\n" + + " <provider>\n" + + " <role>hostmap</role>\n" + + " <name>static</name>\n" + + " <enabled>true</enabled>\n" + + " <param><name>localhost</name><value>sandbox,sandbox.hortonworks.com</value></param>\n" + + " </provider>\n" + + "</gateway>\n"; + + private static final String TEST_PROVIDERS_CONFIG_2 = + "<gateway>\n" + + " <provider>\n" + + " <role>authentication</role>\n" + + " <name>ShiroProvider</name>\n" + + " <enabled>true</enabled>\n" + + " <param>\n" + + " <name>sessionTimeout</name>\n" + + " <value>30</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>main.ldapRealm</name>\n" + + " <value>org.apache.knox.gateway.shirorealm.KnoxLdapRealm</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>main.ldapContextFactory</name>\n" + + " <value>org.apache.knox.gateway.shirorealm.KnoxLdapContextFactory</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>main.ldapRealm.contextFactory</name>\n" + + " <value>$ldapContextFactory</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>main.ldapRealm.userDnTemplate</name>\n" + + " <value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>main.ldapRealm.contextFactory.url</name>\n" + + " <value>ldap://localhost:33389</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>main.ldapRealm.contextFactory.authenticationMechanism</name>\n" + + " <value>simple</value>\n" + + " </param>\n" + + " <param>\n" + + " <name>urls./**</name>\n" + + " <value>authcBasic</value>\n" + + " </param>\n" + + " </provider>\n" + + "</gateway>\n"; + + private static final String TEST_DESCRIPTOR_1 = + "{\n" + + " \"discovery-type\":\"AMBARI\",\n" + + " \"discovery-address\":\"http://sandbox.hortonworks.com:8080\",\n" + + " \"discovery-user\":\"maria_dev\",\n" + + " \"discovery-pwd-alias\":\"sandbox.ambari.discovery.password\",\n" + + " \"provider-config-ref\":\"sandbox-providers.xml\",\n" + + " \"cluster\":\"Sandbox\",\n" + + " \"services\":[\n" + + " {\"name\":\"NODEUI\"},\n" + + " {\"name\":\"YARNUI\"},\n" + + " {\"name\":\"HDFSUI\"},\n" + + " {\"name\":\"OOZIEUI\"},\n" + + " {\"name\":\"HBASEUI\"},\n" + + " {\"name\":\"NAMENODE\"},\n" + + " {\"name\":\"JOBTRACKER\"},\n" + + " {\"name\":\"WEBHDFS\"},\n" + + " {\"name\":\"WEBHCAT\"},\n" + + " {\"name\":\"OOZIE\"},\n" + + " {\"name\":\"WEBHBASE\"},\n" + + " {\"name\":\"RESOURCEMANAGER\"},\n" + + " {\"name\":\"AMBARI\", \"urls\":[\"http://c6401.ambari.apache.org:8080\"]},\n" + + " {\"name\":\"AMBARIUI\", \"urls\":[\"http://c6401.ambari.apache.org:8080\"]}\n" + + " ]\n" + + "}\n"; + + private static final String TEST_DESCRIPTOR_2 = + "{\n" + + " \"discovery-type\":\"AMBARI\",\n" + + " \"discovery-address\":\"http://sandbox.hortonworks.com:8080\",\n" + + " \"discovery-user\":\"maria_dev\",\n" + + " \"discovery-pwd-alias\":\"sandbox.ambari.discovery.password\",\n" + + " \"provider-config-ref\":\"sandbox-providers.xml\",\n" + + " \"cluster\":\"Sandbox\",\n" + + " \"services\":[\n" + + " {\"name\":\"NAMENODE\"},\n" + + " {\"name\":\"JOBTRACKER\"},\n" + + " {\"name\":\"WEBHDFS\"},\n" + + " {\"name\":\"WEBHCAT\"},\n" + + " {\"name\":\"OOZIE\"},\n" + + " {\"name\":\"WEBHBASE\"},\n" + + " {\"name\":\"RESOURCEMANAGER\"}\n" + + " ]\n" + + "}\n"; + +}
http://git-wip-us.apache.org/repos/asf/knox/blob/e5fd0622/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java ---------------------------------------------------------------------- diff --cc gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java index b768937,0000000..116b8dd mode 100644,000000..100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java @@@ -1,1032 -1,0 +1,1048 @@@ +/** + * 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.knox.gateway.util; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.knox.gateway.config.impl.GatewayConfigImpl; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.knox.gateway.services.security.MasterService; +import org.apache.knox.test.TestUtils; +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URL; +import java.util.UUID; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +/** + * @author larry + * + */ +public class KnoxCLITest { + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + + @Before + public void setup() throws Exception { + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } + + @Test + public void testRemoteConfigurationRegistryClientService() throws Exception { + outContent.reset(); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=/test"); + cli.setConf(config); + + // This is only to get the gateway services initialized + cli.run(new String[]{"version"}); + + RemoteConfigurationRegistryClientService service = + cli.getGatewayServices().getService(GatewayServices.REMOTE_REGISTRY_CLIENT_SERVICE); + assertNotNull(service); + RemoteConfigurationRegistryClient client = service.get("test_client"); + assertNotNull(client); + + assertNull(service.get("bogus")); + } + + @Test + public void testListRemoteConfigurationRegistryClients() throws Exception { + outContent.reset(); + + KnoxCLI cli = new KnoxCLI(); + String[] args = { "list-registry-clients", "--master","master" }; + + Configuration config = new GatewayConfigImpl(); + cli.setConf(config); + + // Test with no registry clients configured + int rc = cli.run(args); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().isEmpty()); + + // Test with a single client configured + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=/test1"); + cli.setConf(config); + outContent.reset(); + rc = cli.run(args); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("test_client")); + + // Configure another client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.another_client", "type=LocalFileSystem;address=/test2"); + cli.setConf(config); + outContent.reset(); + rc = cli.run(args); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("test_client")); + assertTrue(outContent.toString(), outContent.toString().contains("another_client")); + } + + @Test + public void testRemoteConfigurationRegistryGetACLs() throws Exception { + outContent.reset(); + + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + + final String providerConfigName = "my-provider-config.xml"; + final String providerConfigContent = "<gateway/>\n"; + final File testProviderConfig = new File(testRoot, providerConfigName); + final String[] uploadArgs = {"upload-provider-config", testProviderConfig.getAbsolutePath(), + "--registry-client", "test_client", + "--master", "master"}; + FileUtils.writeStringToFile(testProviderConfig, providerConfigContent); + + + final String[] args = {"get-registry-acl", "/knox/config/shared-providers", + "--registry-client", "test_client", + "--master", "master"}; + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + int rc = cli.run(uploadArgs); + assertEquals(0, rc); + + // Run the test command + rc = cli.run(args); + + // Validate the result + assertEquals(0, rc); + String result = outContent.toString(); + assertEquals(result, 3, result.split("\n").length); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + + @Test + public void testRemoteConfigurationRegistryUploadProviderConfig() throws Exception { + outContent.reset(); + + final String providerConfigName = "my-provider-config.xml"; + final String providerConfigContent = "<gateway/>\n"; + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + final File testProviderConfig = new File(testRoot, providerConfigName); + + final String[] args = {"upload-provider-config", testProviderConfig.getAbsolutePath(), + "--registry-client", "test_client", + "--master", "master"}; + + FileUtils.writeStringToFile(testProviderConfig, providerConfigContent); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + // Run the test command + int rc = cli.run(args); + + // Validate the result + assertEquals(0, rc); ++ ++ outContent.reset(); ++ final String[] listArgs = {"list-provider-configs", "--registry-client", "test_client"}; ++ cli.run(listArgs); ++ String outStr = outContent.toString().trim(); ++ assertTrue(outStr.startsWith("Provider Configurations")); ++ assertTrue(outStr.endsWith(")\n"+providerConfigName)); ++ + File registryFile = new File(testRegistry, "knox/config/shared-providers/" + providerConfigName); + assertTrue(registryFile.exists()); + assertEquals(FileUtils.readFileToString(registryFile), providerConfigContent); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + + @Test + public void testRemoteConfigurationRegistryUploadProviderConfigWithDestinationOverride() throws Exception { + outContent.reset(); + + final String providerConfigName = "my-provider-config.xml"; + final String entryName = "my-providers.xml"; + final String providerConfigContent = "<gateway/>\n"; + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + final File testProviderConfig = new File(testRoot, providerConfigName); + + final String[] args = {"upload-provider-config", testProviderConfig.getAbsolutePath(), + "--entry-name", entryName, + "--registry-client", "test_client", + "--master", "master"}; + + FileUtils.writeStringToFile(testProviderConfig, providerConfigContent); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + // Run the test command + int rc = cli.run(args); + + // Validate the result + assertEquals(0, rc); + assertFalse((new File(testRegistry, "knox/config/shared-providers/" + providerConfigName)).exists()); + File registryFile = new File(testRegistry, "knox/config/shared-providers/" + entryName); + assertTrue(registryFile.exists()); + assertEquals(FileUtils.readFileToString(registryFile), providerConfigContent); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + + @Test + public void testRemoteConfigurationRegistryUploadDescriptor() throws Exception { + outContent.reset(); + + final String descriptorName = "my-topology.json"; + final String descriptorContent = testDescriptorContentJSON; + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + final File testDescriptor = new File(testRoot, descriptorName); + + final String[] args = {"upload-descriptor", testDescriptor.getAbsolutePath(), + "--registry-client", "test_client", + "--master", "master"}; + + FileUtils.writeStringToFile(testDescriptor, descriptorContent); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + // Run the test command + int rc = cli.run(args); + + // Validate the result + assertEquals(0, rc); ++ ++ outContent.reset(); ++ final String[] listArgs = {"list-descriptors", "--registry-client", "test_client"}; ++ cli.run(listArgs); ++ String outStr = outContent.toString().trim(); ++ assertTrue(outStr.startsWith("Descriptors")); ++ assertTrue(outStr.endsWith(")\n"+descriptorName)); ++ + File registryFile = new File(testRegistry, "knox/config/descriptors/" + descriptorName); + assertTrue(registryFile.exists()); + assertEquals(FileUtils.readFileToString(registryFile), descriptorContent); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + @Test + public void testRemoteConfigurationRegistryUploadDescriptorWithDestinationOverride() throws Exception { + outContent.reset(); + + final String descriptorName = "my-topology.json"; + final String entryName = "different-topology.json"; + final String descriptorContent = testDescriptorContentJSON; + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + final File testDescriptor = new File(testRoot, descriptorName); + + final String[] args = {"upload-descriptor", testDescriptor.getAbsolutePath(), + "--entry-name", entryName, + "--registry-client", "test_client", + "--master", "master"}; + + FileUtils.writeStringToFile(testDescriptor, descriptorContent); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + // Run the test command + int rc = cli.run(args); + + // Validate the result + assertEquals(0, rc); + assertFalse((new File(testRegistry, "knox/config/descriptors/" + descriptorName)).exists()); + File registryFile = new File(testRegistry, "knox/config/descriptors/" + entryName); + assertTrue(registryFile.exists()); + assertEquals(FileUtils.readFileToString(registryFile), descriptorContent); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + @Test + public void testRemoteConfigurationRegistryDeleteProviderConfig() throws Exception { + outContent.reset(); + + // Create a provider config + final String providerConfigName = "my-provider-config.xml"; + final String providerConfigContent = "<gateway/>\n"; + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + final File testProviderConfig = new File(testRoot, providerConfigName); + + final String[] createArgs = {"upload-provider-config", testProviderConfig.getAbsolutePath(), + "--registry-client", "test_client", + "--master", "master"}; + + FileUtils.writeStringToFile(testProviderConfig, providerConfigContent); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + // Run the test command + int rc = cli.run(createArgs); + + // Validate the result + assertEquals(0, rc); + File registryFile = new File(testRegistry, "knox/config/shared-providers/" + providerConfigName); + assertTrue(registryFile.exists()); + + outContent.reset(); + + // Delete the created provider config + final String[] deleteArgs = {"delete-provider-config", providerConfigName, + "--registry-client", "test_client", + "--master", "master"}; + rc = cli.run(deleteArgs); + assertEquals(0, rc); + assertFalse(registryFile.exists()); + + // Try to delete a provider config that does not exist + rc = cli.run(new String[]{"delete-provider-config", "imaginary-providers.xml", + "--registry-client", "test_client", + "--master", "master"}); + assertEquals(0, rc); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + @Test + public void testRemoteConfigurationRegistryDeleteDescriptor() throws Exception { + outContent.reset(); + + final String descriptorName = "my-topology.json"; + final String descriptorContent = testDescriptorContentJSON; + + final File testRoot = TestUtils.createTempDir(this.getClass().getName()); + try { + final File testRegistry = new File(testRoot, "registryRoot"); + final File testDescriptor = new File(testRoot, descriptorName); + + final String[] createArgs = {"upload-descriptor", testDescriptor.getAbsolutePath(), + "--registry-client", "test_client", + "--master", "master"}; + + FileUtils.writeStringToFile(testDescriptor, descriptorContent); + + KnoxCLI cli = new KnoxCLI(); + Configuration config = new GatewayConfigImpl(); + // Configure a client for the test local filesystem registry implementation + config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry); + cli.setConf(config); + + // Run the test command + int rc = cli.run(createArgs); + + // Validate the result + assertEquals(0, rc); + File registryFile = new File(testRegistry, "knox/config/descriptors/" + descriptorName); + assertTrue(registryFile.exists()); + + outContent.reset(); + + // Delete the created provider config + final String[] deleteArgs = {"delete-descriptor", descriptorName, + "--registry-client", "test_client", + "--master", "master"}; + rc = cli.run(deleteArgs); + assertEquals(0, rc); + assertFalse(registryFile.exists()); + + // Try to delete a descriptor that does not exist + rc = cli.run(new String[]{"delete-descriptor", "bogus.json", + "--registry-client", "test_client", + "--master", "master"}); + assertEquals(0, rc); + } finally { + FileUtils.forceDelete(testRoot); + } + } + + @Test + public void testSuccessfulAliasLifecycle() throws Exception { + outContent.reset(); + String[] args1 = {"create-alias", "alias1", "--value", "testvalue1", "--master", "master"}; + int rc = 0; + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + rc = cli.run(args1); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " + + "created.")); + + outContent.reset(); + String[] args2 = {"list-alias", "--master", + "master"}; + rc = cli.run(args2); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias1")); + + outContent.reset(); + String[] args4 = {"delete-alias", "alias1", "--master", + "master"}; + rc = cli.run(args4); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " + + "deleted.")); + + outContent.reset(); + rc = cli.run(args2); + assertEquals(0, rc); + assertFalse(outContent.toString(), outContent.toString().contains("alias1")); + } + + @Test + public void testListAndDeleteOfAliasForInvalidClusterName() throws Exception { + outContent.reset(); + String[] args1 = + { "create-alias", "alias1", "--cluster", "cluster1", "--value", "testvalue1", "--master", + "master" }; + int rc = 0; + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + rc = cli.run(args1); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains( + "alias1 has been successfully " + "created.")); + + outContent.reset(); + String[] args2 = { "list-alias", "--cluster", "Invalidcluster1", "--master", "master" }; + rc = cli.run(args2); + assertEquals(0, rc); + System.out.println(outContent.toString()); + assertTrue(outContent.toString(), + outContent.toString().contains("Invalid cluster name provided: Invalidcluster1")); + + outContent.reset(); + String[] args4 = + { "delete-alias", "alias1", "--cluster", "Invalidcluster1", "--master", "master" }; + rc = cli.run(args4); + assertEquals(0, rc); + assertTrue(outContent.toString(), + outContent.toString().contains("Invalid cluster name provided: Invalidcluster1")); + + } + + @Test + public void testDeleteOfNonExistAliasFromUserDefinedCluster() throws Exception { + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + try { + int rc = 0; + outContent.reset(); + String[] args1 = + { "create-alias", "alias1", "--cluster", "cluster1", "--value", "testvalue1", "--master", + "master" }; + cli.run(args1); + + // Delete invalid alias from the cluster + outContent.reset(); + String[] args2 = { "delete-alias", "alias2", "--cluster", "cluster1", "--master", "master" }; + rc = cli.run(args2); + assertEquals(0, rc); + assertTrue(outContent.toString().contains("No such alias exists in the cluster.")); + } finally { + outContent.reset(); + String[] args1 = { "delete-alias", "alias1", "--cluster", "cluster1", "--master", "master" }; + cli.run(args1); + } + } + + @Test + public void testDeleteOfNonExistAliasFromDefaultCluster() throws Exception { + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + try { + int rc = 0; + outContent.reset(); + String[] args1 = { "create-alias", "alias1", "--value", "testvalue1", "--master", "master" }; + cli.run(args1); + + // Delete invalid alias from the cluster + outContent.reset(); + String[] args2 = { "delete-alias", "alias2", "--master", "master" }; + rc = cli.run(args2); + assertEquals(0, rc); + assertTrue(outContent.toString().contains("No such alias exists in the cluster.")); + } finally { + outContent.reset(); + String[] args1 = { "delete-alias", "alias1", "--master", "master" }; + cli.run(args1); + } + } + + @Test + public void testForInvalidArgument() throws Exception { + outContent.reset(); + String[] args1 = { "--value", "testvalue1", "--master", "master" }; + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + int rc = cli.run(args1); + assertEquals(-2, rc); + assertTrue(outContent.toString().contains("ERROR: Invalid Command")); + } + + @Test + public void testListAndDeleteOfAliasForValidClusterName() throws Exception { + outContent.reset(); + String[] args1 = + { "create-alias", "alias1", "--cluster", "cluster1", "--value", "testvalue1", "--master", + "master" }; + int rc = 0; + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + rc = cli.run(args1); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains( + "alias1 has been successfully " + "created.")); + + outContent.reset(); + String[] args2 = { "list-alias", "--cluster", "cluster1", "--master", "master" }; + rc = cli.run(args2); + assertEquals(0, rc); + System.out.println(outContent.toString()); + assertTrue(outContent.toString(), outContent.toString().contains("alias1")); + + outContent.reset(); + String[] args4 = + { "delete-alias", "alias1", "--cluster", "cluster1", "--master", "master" }; + rc = cli.run(args4); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains( + "alias1 has been successfully " + "deleted.")); + + outContent.reset(); + rc = cli.run(args2); + assertEquals(0, rc); + assertFalse(outContent.toString(), outContent.toString().contains("alias1")); + + } + + @Test + public void testGatewayAndClusterStores() throws Exception { + GatewayConfigImpl config = new GatewayConfigImpl(); + FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) ); + + outContent.reset(); + String[] gwCreateArgs = {"create-alias", "alias1", "--value", "testvalue1", "--master", "master"}; + int rc = 0; + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + rc = cli.run(gwCreateArgs); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " + + "created.")); + + AliasService as = cli.getGatewayServices().getService(GatewayServices.ALIAS_SERVICE); + + outContent.reset(); + String[] clusterCreateArgs = {"create-alias", "alias2", "--value", "testvalue1", "--cluster", "test", + "--master", "master"}; + cli = new KnoxCLI(); + cli.setConf( config ); + rc = cli.run(clusterCreateArgs); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias2 has been successfully " + + "created.")); + + outContent.reset(); + String[] args2 = {"list-alias", "--master", "master"}; + cli = new KnoxCLI(); + rc = cli.run(args2); + assertEquals(0, rc); + assertFalse(outContent.toString(), outContent.toString().contains("alias2")); + assertTrue(outContent.toString(), outContent.toString().contains("alias1")); + + char[] passwordChars = as.getPasswordFromAliasForCluster("test", "alias2"); + assertNotNull(passwordChars); + assertTrue(new String(passwordChars), "testvalue1".equals(new String(passwordChars))); + + outContent.reset(); + String[] args1 = {"list-alias", "--cluster", "test", "--master", "master"}; + cli = new KnoxCLI(); + rc = cli.run(args1); + assertEquals(0, rc); + assertFalse(outContent.toString(), outContent.toString().contains("alias1")); + assertTrue(outContent.toString(), outContent.toString().contains("alias2")); + + outContent.reset(); + String[] args4 = {"delete-alias", "alias1", "--master", "master"}; + cli = new KnoxCLI(); + rc = cli.run(args4); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " + + "deleted.")); + + outContent.reset(); + String[] args5 = {"delete-alias", "alias2", "--cluster", "test", "--master", "master"}; + cli = new KnoxCLI(); + rc = cli.run(args5); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("alias2 has been successfully " + + "deleted.")); + } + + private void createTestMaster() throws Exception { + outContent.reset(); + String[] args = new String[]{ "create-master", "--master", "master", "--force" }; + KnoxCLI cli = new KnoxCLI(); + int rc = cli.run(args); + assertThat( rc, is( 0 ) ); + MasterService ms = cli.getGatewayServices().getService("MasterService"); + String master = String.copyValueOf( ms.getMasterSecret() ); + assertThat( master, is( "master" ) ); + assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) ); + } + + @Test + public void testCreateSelfSignedCert() throws Exception { + GatewayConfigImpl config = new GatewayConfigImpl(); + FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) ); + createTestMaster(); + outContent.reset(); + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + String[] gwCreateArgs = {"create-cert", "--hostname", "hostname1", "--master", "master"}; + int rc = 0; + rc = cli.run(gwCreateArgs); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity has been successfully " + + "created.")); + } + + @Test + public void testExportCert() throws Exception { + GatewayConfigImpl config = new GatewayConfigImpl(); + FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) ); + createTestMaster(); + outContent.reset(); + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + String[] gwCreateArgs = {"create-cert", "--hostname", "hostname1", "--master", "master"}; + int rc = 0; + rc = cli.run(gwCreateArgs); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity has been successfully " + + "created.")); + + outContent.reset(); + String[] gwCreateArgs2 = {"export-cert", "--type", "PEM"}; + rc = 0; + rc = cli.run(gwCreateArgs2); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("Certificate gateway-identity has been successfully exported to")); + assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity.pem")); + + outContent.reset(); + String[] gwCreateArgs2_5 = {"export-cert"}; + rc = 0; + rc = cli.run(gwCreateArgs2_5); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("Certificate gateway-identity has been successfully exported to")); + assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity.pem")); + + outContent.reset(); + String[] gwCreateArgs3 = {"export-cert", "--type", "JKS"}; + rc = 0; + rc = cli.run(gwCreateArgs3); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("Certificate gateway-identity has been successfully exported to")); + assertTrue(outContent.toString(), outContent.toString().contains("gateway-client-trust.jks")); + + outContent.reset(); + String[] gwCreateArgs4 = {"export-cert", "--type", "invalid"}; + rc = 0; + rc = cli.run(gwCreateArgs4); + assertEquals(0, rc); + assertTrue(outContent.toString(), outContent.toString().contains("Invalid type for export file provided.")); + } + + @Test + public void testCreateMaster() throws Exception { + GatewayConfigImpl config = new GatewayConfigImpl(); + FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) ); + outContent.reset(); + String[] args = {"create-master", "--master", "master"}; + int rc = 0; + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + rc = cli.run(args); + assertEquals(0, rc); + MasterService ms = cli.getGatewayServices().getService("MasterService"); + // assertTrue(ms.getClass().getName(), ms.getClass().getName().equals("kjdfhgjkhfdgjkh")); + assertTrue( new String( ms.getMasterSecret() ), "master".equals( new String( ms.getMasterSecret() ) ) ); + assertTrue(outContent.toString(), outContent.toString().contains("Master secret has been persisted to disk.")); + } + + @Test + public void testCreateMasterGenerate() throws Exception { + String[] args = {"create-master", "--generate" }; + int rc = 0; + GatewayConfigImpl config = new GatewayConfigImpl(); + File masterFile = new File( config.getGatewaySecurityDir(), "master" ); + + // Need to delete the master file so that the change isn't ignored. + if( masterFile.exists() ) { + assertThat( "Failed to delete existing master file.", masterFile.delete(), is( true ) ); + } + outContent.reset(); + KnoxCLI cli = new KnoxCLI(); + cli.setConf(config); + rc = cli.run(args); + assertThat( rc, is( 0 ) ); + MasterService ms = cli.getGatewayServices().getService("MasterService"); + String master = String.copyValueOf( ms.getMasterSecret() ); + assertThat( master.length(), is( 36 ) ); + assertThat( master.indexOf( '-' ), is( 8 ) ); + assertThat( master.indexOf( '-', 9 ), is( 13 ) ); + assertThat( master.indexOf( '-', 14 ), is( 18 ) ); + assertThat( master.indexOf( '-', 19 ), is( 23 ) ); + assertThat( UUID.fromString( master ), notNullValue() ); + assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) ); + + // Need to delete the master file so that the change isn't ignored. + if( masterFile.exists() ) { + assertThat( "Failed to delete existing master file.", masterFile.delete(), is( true ) ); + } + outContent.reset(); + cli = new KnoxCLI(); + rc = cli.run(args); + ms = cli.getGatewayServices().getService("MasterService"); + String master2 = String.copyValueOf( ms.getMasterSecret() ); + assertThat( master2.length(), is( 36 ) ); + assertThat( UUID.fromString( master2 ), notNullValue() ); + assertThat( master2, not( is( master ) ) ); + assertThat( rc, is( 0 ) ); + assertThat(outContent.toString(), containsString("Master secret has been persisted to disk.")); + } + + @Test + public void testCreateMasterForce() throws Exception { + GatewayConfigImpl config = new GatewayConfigImpl(); + File masterFile = new File( config.getGatewaySecurityDir(), "master" ); + + // Need to delete the master file so that the change isn't ignored. + if( masterFile.exists() ) { + assertThat( "Failed to delete existing master file.", masterFile.delete(), is( true ) ); + } + + KnoxCLI cli = new KnoxCLI(); + cli.setConf(config); + MasterService ms; + int rc = 0; + outContent.reset(); + + String[] args = { "create-master", "--master", "test-master-1" }; + + rc = cli.run(args); + assertThat( rc, is( 0 ) ); + ms = cli.getGatewayServices().getService("MasterService"); + String master = String.copyValueOf( ms.getMasterSecret() ); + assertThat( master, is( "test-master-1" ) ); + assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) ); + + outContent.reset(); + rc = cli.run(args); + assertThat( rc, is(0 ) ); + assertThat( outContent.toString(), containsString( "Master secret is already present on disk." ) ); + + outContent.reset(); + args = new String[]{ "create-master", "--master", "test-master-2", "--force" }; + rc = cli.run(args); + assertThat( rc, is( 0 ) ); + ms = cli.getGatewayServices().getService("MasterService"); + master = String.copyValueOf( ms.getMasterSecret() ); + assertThat( master, is( "test-master-2" ) ); + assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) ); + } + + @Test + public void testListTopology() throws Exception { + + GatewayConfigMock config = new GatewayConfigMock(); + URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml"); + config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() ); + String args[] = {"list-topologies", "--master", "knox"}; + + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + + cli.run( args ); + assertThat(outContent.toString(), containsString("sandbox")); + assertThat(outContent.toString(), containsString("admin")); + } + + private class GatewayConfigMock extends GatewayConfigImpl{ + private String confDir; + public void setConfDir(String location) { + confDir = location; + } + + @Override + public String getGatewayConfDir(){ + return confDir; + } + } + + private static XMLTag createBadTopology() { + XMLTag xml = XMLDoc.newDocument(true) + .addRoot( "topology" ) + .addTag( "gateway" ) + + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "123" ) + .addTag( "param" ) + .addTag( "name" ).addText( "" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( "ldap://localhost:8443" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ).gotoParent().gotoParent() + .addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "vvv" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + .addTag( "provider" ) + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-service-role" ) + .gotoRoot(); + return xml; + } + + private static XMLTag createGoodTopology() { + XMLTag xml = XMLDoc.newDocument( true ) + .addRoot( "topology" ) + .addTag( "gateway" ) + + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( "ldap://localhost:8443").gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ).gotoParent().gotoParent() + .addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + .addTag( "provider" ) + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-service-role" ) + .gotoRoot(); + return xml; + } + + private File writeTestTopology( String name, XMLTag xml ) throws IOException { + // Create the test topology. + + GatewayConfigMock config = new GatewayConfigMock(); + URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml"); + config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() ); + + File tempFile = new File( config.getGatewayTopologyDir(), name + ".xml." + UUID.randomUUID() ); + FileOutputStream stream = new FileOutputStream( tempFile ); + xml.toStream( stream ); + stream.close(); + File descriptor = new File( config.getGatewayTopologyDir(), name + ".xml" ); + tempFile.renameTo( descriptor ); + return descriptor; + } + + @Test + public void testValidateTopology() throws Exception { + + GatewayConfigMock config = new GatewayConfigMock(); + URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml"); + config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() ); + String args[] = {"validate-topology", "--master", "knox", "--cluster", "sandbox"}; + + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + cli.run( args ); + + assertThat(outContent.toString(), containsString(config.getGatewayTopologyDir())); + assertThat(outContent.toString(), containsString("sandbox")); + assertThat(outContent.toString(), containsString("success")); + outContent.reset(); + + + String args2[] = {"validate-topology", "--master", "knox", "--cluster", "NotATopology"}; + cli.run(args2); + + assertThat(outContent.toString(), containsString("NotATopology")); + assertThat(outContent.toString(), containsString("does not exist")); + outContent.reset(); + + String args3[] = {"validate-topology", "--master", "knox", "--path", config.getGatewayTopologyDir() + "/admin.xml"}; + cli.run(args3); + + assertThat(outContent.toString(), containsString("admin")); + assertThat(outContent.toString(), containsString("success")); + outContent.reset(); + + String args4[] = {"validate-topology", "--master", "knox", "--path", "not/a/path"}; + cli.run(args4); + assertThat(outContent.toString(), containsString("does not exist")); + assertThat(outContent.toString(), containsString("not/a/path")); + } + + @Test + public void testValidateTopologyOutput() throws Exception { + + File bad = writeTestTopology( "test-cluster-bad", createBadTopology() ); + File good = writeTestTopology( "test-cluster-good", createGoodTopology() ); + + GatewayConfigMock config = new GatewayConfigMock(); + URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml"); + config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() ); + String args[] = {"validate-topology", "--master", "knox", "--cluster", "test-cluster-bad"}; + + KnoxCLI cli = new KnoxCLI(); + cli.setConf( config ); + cli.run( args ); + + assertThat(outContent.toString(), containsString(config.getGatewayTopologyDir())); + assertThat(outContent.toString(), containsString("test-cluster-bad")); + assertThat(outContent.toString(), containsString("unsuccessful")); + assertThat(outContent.toString(), containsString("Invalid content")); + assertThat(outContent.toString(), containsString("Line")); + + + outContent.reset(); + + String args2[] = {"validate-topology", "--master", "knox", "--cluster", "test-cluster-good"}; + + cli.run(args2); + + assertThat(outContent.toString(), containsString(config.getGatewayTopologyDir())); + assertThat(outContent.toString(), containsString("success")); + assertThat(outContent.toString(), containsString("test-cluster-good")); + + + } + + private static final String testDescriptorContentJSON = "{\n" + + " \"discovery-address\":\"http://localhost:8080\",\n" + + " \"discovery-user\":\"maria_dev\",\n" + + " \"discovery-pwd-alias\":\"sandbox.discovery.password\",\n" + + " \"provider-config-ref\":\"my-provider-config\",\n" + + " \"cluster\":\"Sandbox\",\n" + + " \"services\":[\n" + + " {\"name\":\"NAMENODE\"},\n" + + " {\"name\":\"JOBTRACKER\"},\n" + + " {\"name\":\"WEBHDFS\"},\n" + + " {\"name\":\"WEBHCAT\"},\n" + + " {\"name\":\"OOZIE\"},\n" + + " {\"name\":\"WEBHBASE\"},\n" + + " {\"name\":\"HIVE\"},\n" + + " {\"name\":\"RESOURCEMANAGER\"}\n" + + " ]\n" + + "}"; +} http://git-wip-us.apache.org/repos/asf/knox/blob/e5fd0622/pom.xml ----------------------------------------------------------------------