http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/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 4c4d419,0000000..902327c 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,649 -1,0 +1,1032 @@@ +/** + * 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.knox.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 testSuccessfulAlaisLifecycle() throws Exception { ++ 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); ++ 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); ++ 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/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java ---------------------------------------------------------------------- diff --cc gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java index 3aceadd,0000000..2ca5ede mode 100644,000000..100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java @@@ -1,309 -1,0 +1,320 @@@ +/** + * 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.websockets; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; ++import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.websocket.CloseReason; +import javax.websocket.ContainerProvider; +import javax.websocket.WebSocketContainer; + +import org.apache.commons.io.FileUtils; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.config.impl.GatewayConfigImpl; +import org.apache.knox.gateway.deploy.DeploymentFactory; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.knox.gateway.services.topology.TopologyService; +import org.apache.knox.gateway.topology.TopologyEvent; +import org.apache.knox.gateway.topology.TopologyListener; +import org.apache.knox.test.TestUtils; +import org.easymock.EasyMock; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.hamcrest.CoreMatchers; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; + +/** + * Test for bad URLs. + * <p> + * This test will set up a bad URL through the topology, so this test case will + * attempt to test the bad url case and also the plumbing around it. + * @since 0.10 + */ +public class BadUrlTest { + + /** + * Non-existant backend websocket server + */ + private static String BACKEND = "http://localhost:9999"; + + /** + * Mock Gateway server + */ + private static Server gatewayServer; + + /** + * Mock gateway config + */ + private static GatewayConfig gatewayConfig; + + private static GatewayServices services; + + /** + * URI for gateway server + */ + private static URI serverUri; + + private static File topoDir; + + public BadUrlTest() { + super(); + } + + @BeforeClass + public static void startServers() throws Exception { + + startGatewayServer(); + + } + + @AfterClass + public static void stopServers() { + try { + gatewayServer.stop(); + } catch (final Exception e) { + e.printStackTrace(System.err); + } + + /* Cleanup the created files */ + FileUtils.deleteQuietly(topoDir); + + } + + /** + * Test websocket proxying through gateway. + * + * @throws Exception + */ + + @Test + public void testBadUrl() throws Exception { + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + + WebsocketClient client = new WebsocketClient(); + + container.connectToServer(client, + new URI(serverUri.toString() + "gateway/websocket/ws")); + + client.awaitClose(CloseReason.CloseCodes.UNEXPECTED_CONDITION.getCode(), + 1000, TimeUnit.MILLISECONDS); + + Assert.assertThat(client.close.getCloseCode().getCode(), + CoreMatchers.is(CloseReason.CloseCodes.UNEXPECTED_CONDITION.getCode())); + + } + + + /** + * Start Gateway Server. + * + * @throws Exception + */ + private static void startGatewayServer() throws Exception { + gatewayServer = new Server(); + final ServerConnector connector = new ServerConnector(gatewayServer); + gatewayServer.addConnector(connector); + + /* workaround so we can add our handler later at runtime */ + HandlerCollection handlers = new HandlerCollection(true); + + /* add some initial handlers */ + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + handlers.addHandler(context); + + gatewayServer.setHandler(handlers); + + // Start Server + gatewayServer.start(); + + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + serverUri = new URI(String.format("ws://%s:%d/", host, port)); + + /* Setup websocket handler */ + setupGatewayConfig(BACKEND); + + final GatewayWebsocketHandler gatewayWebsocketHandler = new GatewayWebsocketHandler( + gatewayConfig, services); + handlers.addHandler(gatewayWebsocketHandler); + gatewayWebsocketHandler.start(); + } + + /** + * Initialize the configs and components required for this test. + * + * @param backend + * @throws IOException + */ + private static void setupGatewayConfig(final String backend) + throws IOException { + services = new DefaultGatewayServices(); + + topoDir = createDir(); + URL serviceUrl = ClassLoader.getSystemResource("websocket-services"); + + final File descriptor = new File(topoDir, "websocket.xml"); + final FileOutputStream stream = new FileOutputStream(descriptor); + createKnoxTopology(backend).toStream(stream); + stream.close(); + + final TestTopologyListener topoListener = new TestTopologyListener(); + + final Map<String, String> options = new HashMap<>(); + options.put("persist-master", "false"); + options.put("master", "password"); + + gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.expect(gatewayConfig.getGatewayTopologyDir()) + .andReturn(topoDir.toString()).anyTimes(); + ++ EasyMock.expect(gatewayConfig.getGatewayProvidersConfigDir()) ++ .andReturn(topoDir.getAbsolutePath() + "/shared-providers").anyTimes(); ++ ++ EasyMock.expect(gatewayConfig.getGatewayDescriptorsDir()) ++ .andReturn(topoDir.getAbsolutePath() + "/descriptors").anyTimes(); ++ + EasyMock.expect(gatewayConfig.getGatewayServicesDir()) + .andReturn(serviceUrl.getFile()).anyTimes(); + + EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048") + .anyTimes(); + + EasyMock.expect(gatewayConfig.getGatewaySecurityDir()) + .andReturn(topoDir.toString()).anyTimes(); + + /* Websocket configs */ + EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageBufferSize()) + .andReturn( + GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageBufferSize()) + .andReturn( + GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketInputBufferSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_INPUT_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketAsyncWriteTimeout()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketIdleTimeout()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_IDLE_TIMEOUT).anyTimes(); + ++ EasyMock.expect(gatewayConfig.getRemoteRegistryConfigurationNames()) ++ .andReturn(Collections.emptyList()) ++ .anyTimes(); ++ + EasyMock.replay(gatewayConfig); + + try { + services.init(gatewayConfig, options); + } catch (ServiceLifecycleException e) { + e.printStackTrace(); + } + + DeploymentFactory.setGatewayServices(services); + final TopologyService monitor = services + .getService(GatewayServices.TOPOLOGY_SERVICE); + monitor.addTopologyChangeListener(topoListener); + monitor.reloadTopologies(); + + } + + private static File createDir() throws IOException { + return TestUtils + .createTempDir(WebsocketEchoTest.class.getSimpleName() + "-"); + } + + /** + * Intentionally add bad URL + * + * @param backend + * @return + */ + private static XMLTag createKnoxTopology(final String backend) { + XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("service") + .addTag("role").addText("WEBSOCKET").addTag("url").addText(backend) + .gotoParent().gotoRoot(); + // System.out.println( "GATEWAY=" + xml.toString() ); + return xml; + } + + private static class TestTopologyListener implements TopologyListener { + + public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>(); + + @Override + public void handleTopologyEvent(List<TopologyEvent> events) { + this.events.add(events); + + synchronized (this) { + for (TopologyEvent event : events) { + if (!event.getType().equals(TopologyEvent.Type.DELETED)) { + + /* for this test we only care about this part */ + DeploymentFactory.createDeployment(gatewayConfig, + event.getTopology()); + + } + } + + } + + } + + } +} http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java ---------------------------------------------------------------------- diff --cc gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java index 268e14b,0000000..64ad87c mode 100644,000000..100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java @@@ -1,388 -1,0 +1,399 @@@ +/** + * 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.websockets; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; ++import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.websocket.ContainerProvider; +import javax.websocket.Session; +import javax.websocket.WebSocketContainer; + +import org.apache.commons.io.FileUtils; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.config.impl.GatewayConfigImpl; +import org.apache.knox.gateway.deploy.DeploymentFactory; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.knox.gateway.services.topology.TopologyService; +import org.apache.knox.gateway.topology.TopologyEvent; +import org.apache.knox.gateway.topology.TopologyListener; +import org.apache.knox.test.TestUtils; +import org.easymock.EasyMock; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; + +/** + * A basic test that attempts to proxy websocket connections through Knox + * gateway. + * <p> + * The way the test is set up is as follows: <br/> + * <ul> + * <li>A Mock Websocket server is setup which simply echos the responses sent by + * client. + * <li>Knox Gateway is set up with websocket handler + * {@link GatewayWebsocketHandler} that can proxy the requests. + * <li>Appropriate Topology and service definition files are set up with the + * address of the Websocket server. + * <li>A mock client is setup to connect to gateway. + * </ul> + * + * The test is to confirm whether the message is sent all the way to the backend + * Websocket server through Knox and back. + * + * + * @since 0.10 + */ +public class WebsocketEchoTest { + + /** + * Simulate backend websocket + */ + private static Server backendServer; + /** + * URI for backend websocket server + */ + private static URI backendServerUri; + + /** + * Mock Gateway server + */ + private static Server gatewayServer; + + /** + * Mock gateway config + */ + private static GatewayConfig gatewayConfig; + + private static GatewayServices services; + + /** + * URI for gateway server + */ + private static URI serverUri; + + private static File topoDir; + + public WebsocketEchoTest() { + super(); + } + + @BeforeClass + public static void startServers() throws Exception { + + startWebsocketServer(); + startGatewayServer(); + + } + + @AfterClass + public static void stopServers() { + try { + gatewayServer.stop(); + backendServer.stop(); + } catch (final Exception e) { + e.printStackTrace(System.err); + } + + /* Cleanup the created files */ + FileUtils.deleteQuietly(topoDir); + + } + + /** + * Test direct connection to websocket server without gateway + * + * @throws Exception + */ + @Test + public void testDirectEcho() throws Exception { + + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + WebsocketClient client = new WebsocketClient(); + + Session session = container.connectToServer(client, backendServerUri); + + session.getBasicRemote().sendText("Echo"); + client.messageQueue.awaitMessages(1, 1000, TimeUnit.MILLISECONDS); + + } + + /** + * Test websocket proxying through gateway. + * + * @throws Exception + */ + @Test + public void testGatewayEcho() throws Exception { + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + + WebsocketClient client = new WebsocketClient(); + Session session = container.connectToServer(client, + new URI(serverUri.toString() + "gateway/websocket/ws")); + + session.getBasicRemote().sendText("Echo"); + client.messageQueue.awaitMessages(1, 1000, TimeUnit.MILLISECONDS); + + assertThat(client.messageQueue.get(0), is("Echo")); + + } + + /** + * Test websocket rewrite rules proxying through gateway. + * + * @throws Exception + */ + @Test + public void testGatewayRewriteEcho() throws Exception { + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + + WebsocketClient client = new WebsocketClient(); + Session session = container.connectToServer(client, + new URI(serverUri.toString() + "gateway/websocket/123foo456bar/channels")); + + session.getBasicRemote().sendText("Echo"); + client.messageQueue.awaitMessages(1, 1000, TimeUnit.MILLISECONDS); + + assertThat(client.messageQueue.get(0), is("Echo")); + + } + + /** + * Start Mock Websocket server that acts as backend. + * + * @throws Exception + */ + private static void startWebsocketServer() throws Exception { + + backendServer = new Server(); + ServerConnector connector = new ServerConnector(backendServer); + backendServer.addConnector(connector); + + final WebsocketEchoHandler handler = new WebsocketEchoHandler(); + + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + context.setHandler(handler); + backendServer.setHandler(context); + + // Start Server + backendServer.start(); + + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + backendServerUri = new URI(String.format("ws://%s:%d/ws", host, port)); + + } + + /** + * Start Gateway Server. + * + * @throws Exception + */ + private static void startGatewayServer() throws Exception { + gatewayServer = new Server(); + final ServerConnector connector = new ServerConnector(gatewayServer); + gatewayServer.addConnector(connector); + + /* workaround so we can add our handler later at runtime */ + HandlerCollection handlers = new HandlerCollection(true); + + /* add some initial handlers */ + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + handlers.addHandler(context); + + gatewayServer.setHandler(handlers); + + // Start Server + gatewayServer.start(); + + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + serverUri = new URI(String.format("ws://%s:%d/", host, port)); + + /* Setup websocket handler */ + setupGatewayConfig(backendServerUri.toString()); + + final GatewayWebsocketHandler gatewayWebsocketHandler = new GatewayWebsocketHandler( + gatewayConfig, services); + handlers.addHandler(gatewayWebsocketHandler); + gatewayWebsocketHandler.start(); + } + + /** + * Initialize the configs and components required for this test. + * + * @param backend + * @throws IOException + */ + private static void setupGatewayConfig(final String backend) + throws IOException { + services = new DefaultGatewayServices(); + + topoDir = createDir(); + URL serviceUrl = ClassLoader.getSystemResource("websocket-services"); + + final File descriptor = new File(topoDir, "websocket.xml"); + final FileOutputStream stream = new FileOutputStream(descriptor); + createKnoxTopology(backend).toStream(stream); + stream.close(); + + final TestTopologyListener topoListener = new TestTopologyListener(); + + final Map<String, String> options = new HashMap<>(); + options.put("persist-master", "false"); + options.put("master", "password"); + + gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.expect(gatewayConfig.getGatewayTopologyDir()) + .andReturn(topoDir.toString()).anyTimes(); + ++ EasyMock.expect(gatewayConfig.getGatewayProvidersConfigDir()) ++ .andReturn(topoDir.getAbsolutePath() + "/shared-providers").anyTimes(); ++ ++ EasyMock.expect(gatewayConfig.getGatewayDescriptorsDir()) ++ .andReturn(topoDir.getAbsolutePath() + "/descriptors").anyTimes(); ++ + EasyMock.expect(gatewayConfig.getGatewayServicesDir()) + .andReturn(serviceUrl.getFile()).anyTimes(); + + EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048") + .anyTimes(); + + EasyMock.expect(gatewayConfig.getGatewaySecurityDir()) + .andReturn(topoDir.toString()).anyTimes(); + + /* Websocket configs */ + EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageBufferSize()) + .andReturn( + GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageBufferSize()) + .andReturn( + GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketInputBufferSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_INPUT_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketAsyncWriteTimeout()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketIdleTimeout()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_IDLE_TIMEOUT).anyTimes(); + ++ EasyMock.expect(gatewayConfig.getRemoteRegistryConfigurationNames()) ++ .andReturn(Collections.emptyList()) ++ .anyTimes(); ++ + EasyMock.replay(gatewayConfig); + + try { + services.init(gatewayConfig, options); + } catch (ServiceLifecycleException e) { + e.printStackTrace(); + } + + DeploymentFactory.setGatewayServices(services); + final TopologyService monitor = services + .getService(GatewayServices.TOPOLOGY_SERVICE); + monitor.addTopologyChangeListener(topoListener); + monitor.reloadTopologies(); + + } + + private static File createDir() throws IOException { + return TestUtils + .createTempDir(WebsocketEchoTest.class.getSimpleName() + "-"); + } + + private static XMLTag createKnoxTopology(final String backend) { + XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("service") + .addTag("role").addText("WEBSOCKET").addTag("url").addText(backend) + .gotoParent().gotoRoot(); + // System.out.println( "GATEWAY=" + xml.toString() ); + return xml; + } + + private static class TestTopologyListener implements TopologyListener { + + public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>(); + + @Override + public void handleTopologyEvent(List<TopologyEvent> events) { + this.events.add(events); + + synchronized (this) { + for (TopologyEvent event : events) { + if (!event.getType().equals(TopologyEvent.Type.DELETED)) { + + /* for this test we only care about this part */ + DeploymentFactory.createDeployment(gatewayConfig, + event.getTopology()); + + } + } + + } + + } + + } +} http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java ---------------------------------------------------------------------- diff --cc gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java index 42bc9c3,0000000..5e5006c mode 100644,000000..100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java @@@ -1,389 -1,0 +1,400 @@@ +/** + * 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.websockets; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; ++import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.websocket.ContainerProvider; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.MessageHandler; +import javax.websocket.Session; +import javax.websocket.WebSocketContainer; + +import org.apache.commons.io.FileUtils; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.config.impl.GatewayConfigImpl; +import org.apache.knox.gateway.deploy.DeploymentFactory; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.knox.gateway.services.topology.TopologyService; +import org.apache.knox.gateway.topology.TopologyEvent; +import org.apache.knox.gateway.topology.TopologyListener; +import org.apache.knox.test.TestUtils; +import org.easymock.EasyMock; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; + +/** + * Test how Knox holds up under multiple concurrent connections. + * + */ +public class WebsocketMultipleConnectionTest { + /** + * Simulate backend websocket + */ + private static Server backendServer; + /** + * URI for backend websocket server + */ + private static URI backendServerUri; + + /** + * Mock Gateway server + */ + private static Server gatewayServer; + + /** + * Mock gateway config + */ + private static GatewayConfig gatewayConfig; + + private static GatewayServices services; + + /** + * URI for gateway server + */ + private static URI serverUri; + + private static File topoDir; + + /** + * Maximum number of open connections to test. + */ + private static int MAX_CONNECTIONS = 100; + + public WebsocketMultipleConnectionTest() { + super(); + } + + @BeforeClass + public static void startServers() throws Exception { + + startWebsocketServer(); + startGatewayServer(); + + } + + @AfterClass + public static void stopServers() { + try { + gatewayServer.stop(); + backendServer.stop(); + } catch (final Exception e) { + e.printStackTrace(System.err); + } + + /* Cleanup the created files */ + FileUtils.deleteQuietly(topoDir); + + } + + /** + * Test websocket proxying through gateway. + * + * @throws Exception + */ + @Test + public void testMultipleConnections() throws Exception { + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + + final CountDownLatch latch = new CountDownLatch(MAX_CONNECTIONS); + + Session[] sessions = new Session[MAX_CONNECTIONS]; + + MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + + System.gc(); + final long heapt1 = memoryMXBean.getHeapMemoryUsage().getUsed(); + final long nonHeapt1 = memoryMXBean.getNonHeapMemoryUsage().getUsed(); + + for (int i = 0; i < MAX_CONNECTIONS; i++) { + + sessions[i] = container.connectToServer(new WebsocketClient() { + + @Override + public void onMessage(String message) { + latch.countDown(); + + } + + }, new URI(serverUri.toString() + "gateway/websocket/ws")); + + } + + for (int i = 0; i < MAX_CONNECTIONS; i++) { + /* make sure the session is active and valid before trying to connect */ + if(sessions[i].isOpen() && sessions[i].getBasicRemote() != null) { + sessions[i].getBasicRemote().sendText("OK"); + } + } + + latch.await(5 * MAX_CONNECTIONS, TimeUnit.MILLISECONDS); + + System.gc(); + + final long heapUsed = memoryMXBean.getHeapMemoryUsage().getUsed() - heapt1; + final long nonHeapUsed = memoryMXBean.getNonHeapMemoryUsage().getUsed() + - nonHeapt1; + + System.out.println("heapUsed = " + heapUsed); + System.out.println("nonHeapUsed = " + nonHeapUsed); + + /* 90 KB per connection */ + /* + long expected = 90 * 1024 * MAX_CONNECTIONS; + assertThat("heap used", heapUsed, lessThan(expected)); + */ + } + + /** + * Start Mock Websocket server that acts as backend. + * + * @throws Exception + */ + private static void startWebsocketServer() throws Exception { + + backendServer = new Server(new QueuedThreadPool(254)); + ServerConnector connector = new ServerConnector(backendServer); + backendServer.addConnector(connector); + + final WebsocketEchoHandler handler = new WebsocketEchoHandler(); + + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + context.setHandler(handler); + backendServer.setHandler(context); + + // Start Server + backendServer.start(); + + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + backendServerUri = new URI(String.format("ws://%s:%d/ws", host, port)); + + } + + /** + * Start Gateway Server. + * + * @throws Exception + */ + private static void startGatewayServer() throws Exception { + /* use default Max threads */ + gatewayServer = new Server(new QueuedThreadPool(254)); + final ServerConnector connector = new ServerConnector(gatewayServer); + gatewayServer.addConnector(connector); + + /* workaround so we can add our handler later at runtime */ + HandlerCollection handlers = new HandlerCollection(true); + + /* add some initial handlers */ + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + handlers.addHandler(context); + + gatewayServer.setHandler(handlers); + + // Start Server + gatewayServer.start(); + + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + serverUri = new URI(String.format("ws://%s:%d/", host, port)); + + /* Setup websocket handler */ + setupGatewayConfig(backendServerUri.toString()); + + final GatewayWebsocketHandler gatewayWebsocketHandler = new GatewayWebsocketHandler( + gatewayConfig, services); + handlers.addHandler(gatewayWebsocketHandler); + gatewayWebsocketHandler.start(); + } + + /** + * Initialize the configs and components required for this test. + * + * @param backend + * @throws IOException + */ + private static void setupGatewayConfig(final String backend) + throws IOException { + services = new DefaultGatewayServices(); + + topoDir = createDir(); + URL serviceUrl = ClassLoader.getSystemResource("websocket-services"); + + final File descriptor = new File(topoDir, "websocket.xml"); + final FileOutputStream stream = new FileOutputStream(descriptor); + createKnoxTopology(backend).toStream(stream); + stream.close(); + + final TestTopologyListener topoListener = new TestTopologyListener(); + + final Map<String, String> options = new HashMap<>(); + options.put("persist-master", "false"); + options.put("master", "password"); + + gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.expect(gatewayConfig.getGatewayTopologyDir()) + .andReturn(topoDir.toString()).anyTimes(); + ++ EasyMock.expect(gatewayConfig.getGatewayProvidersConfigDir()) ++ .andReturn(topoDir.getAbsolutePath() + "/shared-providers").anyTimes(); ++ ++ EasyMock.expect(gatewayConfig.getGatewayDescriptorsDir()) ++ .andReturn(topoDir.getAbsolutePath() + "/descriptors").anyTimes(); ++ + EasyMock.expect(gatewayConfig.getGatewayServicesDir()) + .andReturn(serviceUrl.getFile()).anyTimes(); + + EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048") + .anyTimes(); + + EasyMock.expect(gatewayConfig.getGatewaySecurityDir()) + .andReturn(topoDir.toString()).anyTimes(); + + /* Websocket configs */ + EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageBufferSize()) + .andReturn( + GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageBufferSize()) + .andReturn( + GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketInputBufferSize()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_INPUT_BUFFER_SIZE) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketAsyncWriteTimeout()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT) + .anyTimes(); + + EasyMock.expect(gatewayConfig.getWebsocketIdleTimeout()) + .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_IDLE_TIMEOUT).anyTimes(); + ++ EasyMock.expect(gatewayConfig.getRemoteRegistryConfigurationNames()) ++ .andReturn(Collections.emptyList()) ++ .anyTimes(); ++ + EasyMock.replay(gatewayConfig); + + try { + services.init(gatewayConfig, options); + } catch (ServiceLifecycleException e) { + e.printStackTrace(); + } + + DeploymentFactory.setGatewayServices(services); + final TopologyService monitor = services + .getService(GatewayServices.TOPOLOGY_SERVICE); + monitor.addTopologyChangeListener(topoListener); + monitor.reloadTopologies(); + + } + + private static File createDir() throws IOException { + return TestUtils + .createTempDir(WebsocketEchoTest.class.getSimpleName() + "-"); + } + + private static XMLTag createKnoxTopology(final String backend) { + XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("service") + .addTag("role").addText("WEBSOCKET").addTag("url").addText(backend) + .gotoParent().gotoRoot(); + // System.out.println( "GATEWAY=" + xml.toString() ); + return xml; + } + + private static class TestTopologyListener implements TopologyListener { + + public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>(); + + @Override + public void handleTopologyEvent(List<TopologyEvent> events) { + this.events.add(events); + + synchronized (this) { + for (TopologyEvent event : events) { + if (!event.getType().equals(TopologyEvent.Type.DELETED)) { + + /* for this test we only care about this part */ + DeploymentFactory.createDeployment(gatewayConfig, + event.getTopology()); + + } + } + + } + + } + + } + + private static abstract class WebsocketClient extends Endpoint + implements MessageHandler.Whole<String> { + @Override + public void onOpen(Session session, EndpointConfig config) { + session.addMessageHandler(this); + } + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml ---------------------------------------------------------------------- diff --cc gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml index c6135ae,0000000..e69de29 mode 100644,000000..100644 --- a/gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml +++ b/gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml