You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/11/13 15:48:04 UTC
[14/16] knox git commit: Merge branch 'master' into
KNOX-998-Package_Restructuring
http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-server/src/main/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorImpl.java
----------------------------------------------------------------------
diff --cc gateway-server/src/main/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorImpl.java
index 4eb1954,0000000..f3288fd
mode 100644,000000..100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorImpl.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorImpl.java
@@@ -1,123 -1,0 +1,163 @@@
+/**
+ * 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.topology.simple;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+class SimpleDescriptorImpl implements SimpleDescriptor {
+
+ @JsonProperty("discovery-type")
+ private String discoveryType;
+
+ @JsonProperty("discovery-address")
+ private String discoveryAddress;
+
+ @JsonProperty("discovery-user")
+ private String discoveryUser;
+
+ @JsonProperty("discovery-pwd-alias")
+ private String discoveryPasswordAlias;
+
+ @JsonProperty("provider-config-ref")
+ private String providerConfig;
+
+ @JsonProperty("cluster")
+ private String cluster;
+
+ @JsonProperty("services")
+ private List<ServiceImpl> services;
+
++ @JsonProperty("applications")
++ private List<ApplicationImpl> applications;
++
+ private String name = null;
+
+ void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDiscoveryType() {
+ return discoveryType;
+ }
+
+ @Override
+ public String getDiscoveryAddress() {
+ return discoveryAddress;
+ }
+
+ @Override
+ public String getDiscoveryUser() {
+ return discoveryUser;
+ }
+
+ @Override
+ public String getDiscoveryPasswordAlias() {
+ return discoveryPasswordAlias;
+ }
+
+ @Override
+ public String getClusterName() {
+ return cluster;
+ }
+
+ @Override
+ public String getProviderConfig() {
+ return providerConfig;
+ }
+
+ @Override
+ public List<Service> getServices() {
+ List<Service> result = new ArrayList<>();
- result.addAll(services);
++ if (services != null) {
++ result.addAll(services);
++ }
++ return result;
++ }
++
++ @Override
++ public List<Application> getApplications() {
++ List<Application> result = new ArrayList<>();
++ if (applications != null) {
++ result.addAll(applications);
++ }
+ return result;
+ }
+
+ public static class ServiceImpl implements Service {
+ @JsonProperty("name")
+ private String name;
+
+ @JsonProperty("params")
+ private Map<String, String> params;
+
+ @JsonProperty("urls")
+ private List<String> urls;
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Map<String, String> getParams() {
+ return params;
+ }
+
+ @Override
+ public List<String> getURLs() {
+ return urls;
+ }
+ }
+
++ public static class ApplicationImpl implements Application {
++ @JsonProperty("name")
++ private String name;
++
++ @JsonProperty("params")
++ private Map<String, String> params;
++
++ @JsonProperty("urls")
++ private List<String> urls;
++
++ @Override
++ public String getName() {
++ return name;
++ }
++
++ @Override
++ public Map<String, String> getParams() {
++ return params;
++ }
++
++ @Override
++ public List<String> getURLs() {
++ return urls;
++ }
++ }
++
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-server/src/main/java/org/apache/knox/gateway/topology/xml/KnoxFormatXmlTopologyRules.java
----------------------------------------------------------------------
diff --cc gateway-server/src/main/java/org/apache/knox/gateway/topology/xml/KnoxFormatXmlTopologyRules.java
index 81aedec,0000000..a1fcb6d
mode 100644,000000..100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/topology/xml/KnoxFormatXmlTopologyRules.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/topology/xml/KnoxFormatXmlTopologyRules.java
@@@ -1,95 -1,0 +1,97 @@@
+/**
+ * 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.topology.xml;
+
+import org.apache.commons.digester3.Rule;
+import org.apache.commons.digester3.binder.AbstractRulesModule;
+import org.apache.knox.gateway.topology.Application;
+import org.apache.knox.gateway.topology.Param;
+import org.apache.knox.gateway.topology.Provider;
+import org.apache.knox.gateway.topology.Service;
+import org.apache.knox.gateway.topology.Version;
+import org.apache.knox.gateway.topology.builder.BeanPropertyTopologyBuilder;
+import org.xml.sax.Attributes;
+
+public class KnoxFormatXmlTopologyRules extends AbstractRulesModule {
+
+ private static final String ROOT_TAG = "topology";
+ private static final String NAME_TAG = "name";
+ private static final String VERSION_TAG = "version";
+ private static final String DEFAULT_SERVICE_TAG = "path";
++ private static final String GENERATED_TAG = "generated";
+ private static final String APPLICATION_TAG = "application";
+ private static final String SERVICE_TAG = "service";
+ private static final String ROLE_TAG = "role";
+ private static final String URL_TAG = "url";
+ private static final String PROVIDER_TAG = "gateway/provider";
+ private static final String ENABLED_TAG = "enabled";
+ private static final String PARAM_TAG = "param";
+ private static final String VALUE_TAG = "value";
+
+ private static final Rule paramRule = new ParamRule();
+
+ @Override
+ protected void configure() {
+ forPattern( ROOT_TAG ).createObject().ofType( BeanPropertyTopologyBuilder.class );
+ forPattern( ROOT_TAG + "/" + NAME_TAG ).callMethod("name").usingElementBodyAsArgument();
+ forPattern( ROOT_TAG + "/" + VERSION_TAG ).callMethod("version").usingElementBodyAsArgument();
+ forPattern( ROOT_TAG + "/" + DEFAULT_SERVICE_TAG ).callMethod("defaultService").usingElementBodyAsArgument();
++ forPattern( ROOT_TAG + "/" + GENERATED_TAG ).callMethod("generated").usingElementBodyAsArgument();
+
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG ).createObject().ofType( Application.class ).then().setNext( "addApplication" );
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + ROLE_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + NAME_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + VERSION_TAG ).createObject().ofType(Version.class).then().setBeanProperty().then().setNext("setVersion");
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + URL_TAG ).callMethod( "addUrl" ).usingElementBodyAsArgument();
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + PARAM_TAG ).createObject().ofType( Param.class ).then().addRule( paramRule ).then().setNext( "addParam" );
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + PARAM_TAG + "/" + NAME_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + APPLICATION_TAG + "/" + PARAM_TAG + "/" + VALUE_TAG ).setBeanProperty();
+
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG ).createObject().ofType( Service.class ).then().setNext( "addService" );
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + ROLE_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + NAME_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + VERSION_TAG ).createObject().ofType(Version.class).then().setBeanProperty().then().setNext("setVersion");
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + URL_TAG ).callMethod( "addUrl" ).usingElementBodyAsArgument();
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + PARAM_TAG ).createObject().ofType( Param.class ).then().addRule( paramRule ).then().setNext( "addParam" );
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + PARAM_TAG + "/" + NAME_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + PARAM_TAG + "/" + VALUE_TAG ).setBeanProperty();
+
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG ).createObject().ofType( Provider.class ).then().setNext( "addProvider" );
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + ROLE_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + ENABLED_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + NAME_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + PARAM_TAG ).createObject().ofType( Param.class ).then().addRule( paramRule ).then().setNext( "addParam" );
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + PARAM_TAG + "/" + NAME_TAG ).setBeanProperty();
+ forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + PARAM_TAG + "/" + VALUE_TAG ).setBeanProperty();
+ }
+
+ private static class ParamRule extends Rule {
+
+ @Override
+ public void begin( String namespace, String name, Attributes attributes ) {
+ Param param = getDigester().peek();
+ String paramName = attributes.getValue( "name" );
+ if( paramName != null ) {
+ param.setName( paramName );
+ param.setValue( attributes.getValue( "value" ) );
+ }
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorFactoryTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorFactoryTest.java
index 41a7c10,0000000..df31f3d
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorFactoryTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorFactoryTest.java
@@@ -1,422 -1,0 +1,681 @@@
+/**
+ * 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.topology.simple;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.*;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class SimpleDescriptorFactoryTest {
+
++ private enum FileType {
++ JSON,
++ YAML
++ }
+
+ @Test
+ public void testParseJSONSimpleDescriptor() throws Exception {
++ testParseSimpleDescriptor(FileType.JSON);
++ }
++
++ @Test
++ public void testParseYAMLSimpleDescriptor() throws Exception {
++ testParseSimpleDescriptor(FileType.YAML);
++ }
++
++ @Test
++ public void testParseJSONSimpleDescriptorWithServiceParams() throws Exception {
++ testParseSimpleDescriptorWithServiceParams(FileType.JSON);
++ }
++
++ @Test
++ public void testParseYAMLSimpleDescriptorWithServiceParams() throws Exception {
++ testParseSimpleDescriptorWithServiceParams(FileType.YAML);
++ }
++
++ @Test
++ public void testParseJSONSimpleDescriptorWithApplications() throws Exception {
++ testParseSimpleDescriptorWithApplications(FileType.JSON);
++ }
++
++ @Test
++ public void testParseYAMLSimpleDescriptorApplications() throws Exception {
++ testParseSimpleDescriptorWithApplications(FileType.YAML);
++ }
++
++
++ @Test
++ public void testParseJSONSimpleDescriptorWithServicesAndApplications() throws Exception {
++ testParseSimpleDescriptorWithServicesAndApplications(FileType.JSON);
++ }
++
++ @Test
++ public void testParseYAMLSimpleDescriptorWithServicesAndApplications() throws Exception {
++ testParseSimpleDescriptorWithServicesAndApplications(FileType.YAML);
++ }
++
+
++ private void testParseSimpleDescriptor(FileType type) throws Exception {
+ final String discoveryType = "AMBARI";
+ final String discoveryAddress = "http://c6401.ambari.apache.org:8080";
- final String discoveryUser = "admin";
++ final String discoveryUser = "joeblow";
+ final String providerConfig = "ambari-cluster-policy.xml";
+ final String clusterName = "myCluster";
+
+ final Map<String, List<String>> services = new HashMap<>();
+ services.put("NODEMANAGER", null);
+ services.put("JOBTRACKER", null);
+ services.put("RESOURCEMANAGER", null);
+ services.put("HIVE", Arrays.asList("http://c6401.ambari.apache.org", "http://c6402.ambari.apache.org", "http://c6403.ambari.apache.org"));
- services.put("AMBARIUI", Arrays.asList("http://c6401.ambari.apache.org:8080"));
++ services.put("AMBARIUI", Collections.singletonList("http://c6401.ambari.apache.org:8080"));
+
- String fileName = "test-topology.json";
- File testJSON = null;
++ String fileName = "test-topology." + getFileExtensionForType(type);
++ File testFile = null;
+ try {
- testJSON = writeJSON(fileName, discoveryType, discoveryAddress, discoveryUser, providerConfig, clusterName, services);
- SimpleDescriptor sd = SimpleDescriptorFactory.parse(testJSON.getAbsolutePath());
++ testFile = writeDescriptorFile(type,
++ fileName,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services);
++ SimpleDescriptor sd = SimpleDescriptorFactory.parse(testFile.getAbsolutePath());
+ validateSimpleDescriptor(sd, discoveryType, discoveryAddress, providerConfig, clusterName, services);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
- if (testJSON != null) {
++ if (testFile != null) {
+ try {
- testJSON.delete();
++ testFile.delete();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
- @Test
- public void testParseJSONSimpleDescriptorWithServiceParams() throws Exception {
++ private void testParseSimpleDescriptorWithServiceParams(FileType type) throws Exception {
+
+ final String discoveryType = "AMBARI";
+ final String discoveryAddress = "http://c6401.ambari.apache.org:8080";
+ final String discoveryUser = "admin";
+ final String providerConfig = "ambari-cluster-policy.xml";
+ final String clusterName = "myCluster";
+
+ final Map<String, List<String>> services = new HashMap<>();
+ services.put("NODEMANAGER", null);
+ services.put("JOBTRACKER", null);
+ services.put("RESOURCEMANAGER", null);
+ services.put("HIVE", Arrays.asList("http://c6401.ambari.apache.org", "http://c6402.ambari.apache.org", "http://c6403.ambari.apache.org"));
+ services.put("AMBARIUI", Collections.singletonList("http://c6401.ambari.apache.org:8080"));
+ services.put("KNOXSSO", null);
+ services.put("KNOXTOKEN", null);
+ services.put("CustomRole", Collections.singletonList("http://c6402.ambari.apache.org:1234"));
+
+ final Map<String, Map<String, String>> serviceParams = new HashMap<>();
+ Map<String, String> knoxSSOParams = new HashMap<>();
+ knoxSSOParams.put("knoxsso.cookie.secure.only", "true");
+ knoxSSOParams.put("knoxsso.token.ttl", "100000");
+ serviceParams.put("KNOXSSO", knoxSSOParams);
+
+ Map<String, String> knoxTokenParams = new HashMap<>();
+ knoxTokenParams.put("knox.token.ttl", "36000000");
+ knoxTokenParams.put("knox.token.audiences", "tokenbased");
+ knoxTokenParams.put("knox.token.target.url", "https://localhost:8443/gateway/tokenbased");
+ serviceParams.put("KNOXTOKEN", knoxTokenParams);
+
+ Map<String, String> customRoleParams = new HashMap<>();
+ customRoleParams.put("custom.param.1", "value1");
+ customRoleParams.put("custom.param.2", "value2");
+ serviceParams.put("CustomRole", customRoleParams);
+
- String fileName = "test-topology.json";
- File testJSON = null;
++ String fileName = "test-topology." + getFileExtensionForType(type);
++ File testFile = null;
+ try {
- testJSON = writeJSON(fileName,
- discoveryType,
- discoveryAddress,
- discoveryUser,
- providerConfig,
- clusterName,
- services,
- serviceParams);
- SimpleDescriptor sd = SimpleDescriptorFactory.parse(testJSON.getAbsolutePath());
++ testFile = writeDescriptorFile(type,
++ fileName,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services,
++ serviceParams);
++ SimpleDescriptor sd = SimpleDescriptorFactory.parse(testFile.getAbsolutePath());
+ validateSimpleDescriptor(sd, discoveryType, discoveryAddress, providerConfig, clusterName, services, serviceParams);
- } catch (Exception e) {
- e.printStackTrace();
+ } finally {
- if (testJSON != null) {
++ if (testFile != null) {
+ try {
- testJSON.delete();
++ testFile.delete();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
- @Test
- public void testParseYAMLSimpleDescriptor() throws Exception {
++ private void testParseSimpleDescriptorWithApplications(FileType type) throws Exception {
+
+ final String discoveryType = "AMBARI";
+ final String discoveryAddress = "http://c6401.ambari.apache.org:8080";
- final String discoveryUser = "joeblow";
++ final String discoveryUser = "admin";
+ final String providerConfig = "ambari-cluster-policy.xml";
+ final String clusterName = "myCluster";
+
- final Map<String, List<String>> services = new HashMap<>();
- services.put("NODEMANAGER", null);
- services.put("JOBTRACKER", null);
- services.put("RESOURCEMANAGER", null);
- services.put("HIVE", Arrays.asList("http://c6401.ambari.apache.org", "http://c6402.ambari.apache.org", "http://c6403.ambari.apache.org"));
- services.put("AMBARIUI", Arrays.asList("http://c6401.ambari.apache.org:8080"));
-
- String fileName = "test-topology.yml";
- File testYAML = null;
++ final Map<String, List<String>> apps = new HashMap<>();
++ apps.put("app-one", null);
++ apps.put("appTwo", null);
++ apps.put("thirdApps", null);
++ apps.put("appfour", Arrays.asList("http://host1:1234", "http://host2:5678", "http://host1:1357"));
++ apps.put("AppFive", Collections.singletonList("http://host5:8080"));
++
++ final Map<String, Map<String, String>> appParams = new HashMap<>();
++ Map<String, String> oneParams = new HashMap<>();
++ oneParams.put("appone.cookie.secure.only", "true");
++ oneParams.put("appone.token.ttl", "100000");
++ appParams.put("app-one", oneParams);
++ Map<String, String> fiveParams = new HashMap<>();
++ fiveParams.put("myproperty", "true");
++ fiveParams.put("anotherparam", "100000");
++ appParams.put("AppFive", fiveParams);
++
++ String fileName = "test-topology." + getFileExtensionForType(type);
++ File testFile = null;
+ try {
- testYAML = writeYAML(fileName, discoveryType, discoveryAddress, discoveryUser, providerConfig, clusterName, services);
- SimpleDescriptor sd = SimpleDescriptorFactory.parse(testYAML.getAbsolutePath());
- validateSimpleDescriptor(sd, discoveryType, discoveryAddress, providerConfig, clusterName, services);
- } catch (Exception e) {
- e.printStackTrace();
++ testFile = writeDescriptorFile(type,
++ fileName,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ null,
++ null,
++ apps,
++ appParams);
++ SimpleDescriptor sd = SimpleDescriptorFactory.parse(testFile.getAbsolutePath());
++ validateSimpleDescriptor(sd,
++ discoveryType,
++ discoveryAddress,
++ providerConfig,
++ clusterName,
++ null,
++ null,
++ apps,
++ appParams);
+ } finally {
- if (testYAML != null) {
++ if (testFile != null) {
+ try {
- testYAML.delete();
++ testFile.delete();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
-
- @Test
- public void testParseYAMLSimpleDescriptorWithServiceParams() throws Exception {
++ private void testParseSimpleDescriptorWithServicesAndApplications(FileType type) throws Exception {
+
+ final String discoveryType = "AMBARI";
+ final String discoveryAddress = "http://c6401.ambari.apache.org:8080";
- final String discoveryUser = "joeblow";
++ final String discoveryUser = "admin";
+ final String providerConfig = "ambari-cluster-policy.xml";
+ final String clusterName = "myCluster";
+
+ final Map<String, List<String>> services = new HashMap<>();
+ services.put("NODEMANAGER", null);
+ services.put("JOBTRACKER", null);
+ services.put("RESOURCEMANAGER", null);
+ services.put("HIVE", Arrays.asList("http://c6401.ambari.apache.org", "http://c6402.ambari.apache.org", "http://c6403.ambari.apache.org"));
- services.put("AMBARIUI", Arrays.asList("http://c6401.ambari.apache.org:8080"));
++ services.put("AMBARIUI", Collections.singletonList("http://c6401.ambari.apache.org:8080"));
+ services.put("KNOXSSO", null);
+ services.put("KNOXTOKEN", null);
+ services.put("CustomRole", Collections.singletonList("http://c6402.ambari.apache.org:1234"));
+
+ final Map<String, Map<String, String>> serviceParams = new HashMap<>();
+ Map<String, String> knoxSSOParams = new HashMap<>();
+ knoxSSOParams.put("knoxsso.cookie.secure.only", "true");
+ knoxSSOParams.put("knoxsso.token.ttl", "100000");
+ serviceParams.put("KNOXSSO", knoxSSOParams);
+
+ Map<String, String> knoxTokenParams = new HashMap<>();
+ knoxTokenParams.put("knox.token.ttl", "36000000");
+ knoxTokenParams.put("knox.token.audiences", "tokenbased");
+ knoxTokenParams.put("knox.token.target.url", "https://localhost:8443/gateway/tokenbased");
+ serviceParams.put("KNOXTOKEN", knoxTokenParams);
+
+ Map<String, String> customRoleParams = new HashMap<>();
+ customRoleParams.put("custom.param.1", "value1");
+ customRoleParams.put("custom.param.2", "value2");
+ serviceParams.put("CustomRole", customRoleParams);
+
- String fileName = "test-topology.yml";
- File testYAML = null;
++ final Map<String, List<String>> apps = new HashMap<>();
++ apps.put("app-one", null);
++ apps.put("appTwo", null);
++ apps.put("thirdApps", null);
++ apps.put("appfour", Arrays.asList("http://host1:1234", "http://host2:5678", "http://host1:1357"));
++ apps.put("AppFive", Collections.singletonList("http://host5:8080"));
++
++ final Map<String, Map<String, String>> appParams = new HashMap<>();
++ Map<String, String> oneParams = new HashMap<>();
++ oneParams.put("appone.cookie.secure.only", "true");
++ oneParams.put("appone.token.ttl", "100000");
++ appParams.put("app-one", oneParams);
++ Map<String, String> fiveParams = new HashMap<>();
++ fiveParams.put("myproperty", "true");
++ fiveParams.put("anotherparam", "100000");
++ appParams.put("AppFive", fiveParams);
++
++ String fileName = "test-topology." + getFileExtensionForType(type);
++ File testFile = null;
+ try {
- testYAML = writeYAML(fileName, discoveryType, discoveryAddress, discoveryUser, providerConfig, clusterName, services, serviceParams);
- SimpleDescriptor sd = SimpleDescriptorFactory.parse(testYAML.getAbsolutePath());
- validateSimpleDescriptor(sd, discoveryType, discoveryAddress, providerConfig, clusterName, services, serviceParams);
- } catch (Exception e) {
- e.printStackTrace();
++ testFile = writeDescriptorFile(type,
++ fileName,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services,
++ serviceParams,
++ apps,
++ appParams);
++ SimpleDescriptor sd = SimpleDescriptorFactory.parse(testFile.getAbsolutePath());
++ validateSimpleDescriptor(sd,
++ discoveryType,
++ discoveryAddress,
++ providerConfig,
++ clusterName,
++ services,
++ serviceParams,
++ apps,
++ appParams);
+ } finally {
- if (testYAML != null) {
++ if (testFile != null) {
+ try {
- testYAML.delete();
++ testFile.delete();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
-
- private void validateSimpleDescriptor(SimpleDescriptor sd,
- String discoveryType,
- String discoveryAddress,
- String providerConfig,
- String clusterName,
- Map<String, List<String>> expectedServices) {
- validateSimpleDescriptor(sd, discoveryType, discoveryAddress, providerConfig, clusterName, expectedServices, null);
- }
-
-
- private void validateSimpleDescriptor(SimpleDescriptor sd,
- String discoveryType,
- String discoveryAddress,
- String providerConfig,
- String clusterName,
- Map<String, List<String>> expectedServices,
- Map<String, Map<String, String>> expectedServiceParameters) {
- assertNotNull(sd);
- assertEquals(discoveryType, sd.getDiscoveryType());
- assertEquals(discoveryAddress, sd.getDiscoveryAddress());
- assertEquals(providerConfig, sd.getProviderConfig());
- assertEquals(clusterName, sd.getClusterName());
-
- List<SimpleDescriptor.Service> actualServices = sd.getServices();
-
- assertEquals(expectedServices.size(), actualServices.size());
-
- for (SimpleDescriptor.Service actualService : actualServices) {
- assertTrue(expectedServices.containsKey(actualService.getName()));
- assertEquals(expectedServices.get(actualService.getName()), actualService.getURLs());
-
- // Validate service parameters
- if (expectedServiceParameters != null) {
- if (expectedServiceParameters.containsKey(actualService.getName())) {
- Map<String, String> expectedParams = expectedServiceParameters.get(actualService.getName());
-
- Map<String, String> actualServiceParams = actualService.getParams();
- assertNotNull(actualServiceParams);
-
- // Validate the size of the service parameter set
- assertEquals(expectedParams.size(), actualServiceParams.size());
-
- // Validate the parameter contents
- for (String paramName : actualServiceParams.keySet()) {
- assertTrue(expectedParams.containsKey(paramName));
- assertEquals(expectedParams.get(paramName), actualServiceParams.get(paramName));
- }
- }
- }
++ private String getFileExtensionForType(FileType type) {
++ String extension = null;
++ switch (type) {
++ case JSON:
++ extension = "json";
++ break;
++ case YAML:
++ extension = "yml";
++ break;
+ }
++ return extension;
+ }
+
++ private File writeDescriptorFile(FileType type,
++ String path,
++ String discoveryType,
++ String discoveryAddress,
++ String discoveryUser,
++ String providerConfig,
++ String clusterName,
++ Map<String, List<String>> services) throws Exception {
++ return writeDescriptorFile(type,
++ path,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services,
++ null);
++ }
+
- private File writeJSON(String path, String content) throws Exception {
- File f = new File(path);
-
- Writer fw = new FileWriter(f);
- fw.write(content);
- fw.flush();
- fw.close();
-
- return f;
++ private File writeDescriptorFile(FileType type,
++ String path,
++ String discoveryType,
++ String discoveryAddress,
++ String discoveryUser,
++ String providerConfig,
++ String clusterName,
++ Map<String, List<String>> services,
++ Map<String, Map<String, String>> serviceParams) throws Exception {
++ return writeDescriptorFile(type,
++ path,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services,
++ serviceParams,
++ null,
++ null);
+ }
+
+
- private File writeJSON(String path,
- String discoveryType,
- String discoveryAddress,
- String discoveryUser,
- String providerConfig,
- String clusterName,
- Map<String, List<String>> services) throws Exception {
- return writeJSON(path, discoveryType, discoveryAddress, discoveryUser, providerConfig, clusterName, services, null);
++ private File writeDescriptorFile(FileType type,
++ String path,
++ String discoveryType,
++ String discoveryAddress,
++ String discoveryUser,
++ String providerConfig,
++ String clusterName,
++ Map<String, List<String>> services,
++ Map<String, Map<String, String>> serviceParams,
++ Map<String, List<String>> apps,
++ Map<String, Map<String, String>> appParams) throws Exception {
++ File result = null;
++ switch (type) {
++ case JSON:
++ result = writeJSON(path,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services,
++ serviceParams,
++ apps,
++ appParams);
++ break;
++ case YAML:
++ result = writeYAML(path,
++ discoveryType,
++ discoveryAddress,
++ discoveryUser,
++ providerConfig,
++ clusterName,
++ services,
++ serviceParams,
++ apps,
++ appParams);
++ break;
++ }
++ return result;
+ }
+
++
+ private File writeJSON(String path,
+ String discoveryType,
+ String discoveryAddress,
+ String discoveryUser,
+ String providerConfig,
+ String clusterName,
+ Map<String, List<String>> services,
- Map<String, Map<String, String>> serviceParams) throws Exception {
++ Map<String, Map<String, String>> serviceParams,
++ Map<String, List<String>> apps,
++ Map<String, Map<String, String>> appParams) throws Exception {
+ File f = new File(path);
+
+ Writer fw = new FileWriter(f);
+ fw.write("{" + "\n");
+ fw.write("\"discovery-type\":\"" + discoveryType + "\",\n");
+ fw.write("\"discovery-address\":\"" + discoveryAddress + "\",\n");
+ fw.write("\"discovery-user\":\"" + discoveryUser + "\",\n");
+ fw.write("\"provider-config-ref\":\"" + providerConfig + "\",\n");
- fw.write("\"cluster\":\"" + clusterName + "\",\n");
- fw.write("\"services\":[\n");
-
- int i = 0;
- for (String name : services.keySet()) {
- fw.write("{\"name\":\"" + name + "\"");
-
- // Service params
- if (serviceParams != null && !serviceParams.isEmpty()) {
- Map<String, String> params = serviceParams.get(name);
- if (params != null && !params.isEmpty()) {
- fw.write(",\n\"params\":{\n");
- Iterator<String> paramNames = params.keySet().iterator();
- while (paramNames.hasNext()) {
- String paramName = paramNames.next();
- String paramValue = params.get(paramName);
- fw.write("\"" + paramName + "\":\"" + paramValue + "\"");
- fw.write(paramNames.hasNext() ? ",\n" : "");
- }
- fw.write("\n}");
- }
- }
++ fw.write("\"cluster\":\"" + clusterName + "\"");
+
- // Service URLs
- List<String> urls = services.get(name);
- if (urls != null) {
- fw.write(",\n\"urls\":[");
- Iterator<String> urlIter = urls.iterator();
- while (urlIter.hasNext()) {
- fw.write("\"" + urlIter.next() + "\"");
- if (urlIter.hasNext()) {
- fw.write(", ");
- }
- }
- fw.write("]\n");
- }
++ if (services != null && !services.isEmpty()) {
++ fw.write(",\n\"services\":[\n");
++ writeServiceOrApplicationJSON(fw, services, serviceParams);
++ fw.write("]\n");
++ }
+
- fw.write("}");
- if (i++ < services.size() - 1) {
- fw.write(",");
- }
- fw.write("\n");
++ if (apps != null && !apps.isEmpty()) {
++ fw.write(",\n\"applications\":[\n");
++ writeServiceOrApplicationJSON(fw, apps, appParams);
++ fw.write("]\n");
+ }
- fw.write("]\n");
++
+ fw.write("}\n");
+ fw.flush();
+ fw.close();
+
+ return f;
+ }
+
++ private void writeServiceOrApplicationJSON(Writer fw,
++ Map<String, List<String>> elementURLs,
++ Map<String, Map<String, String>> elementParams) throws Exception {
++ if (elementURLs != null) {
++ int i = 0;
++ for (String name : elementURLs.keySet()) {
++ fw.write("{\"name\":\"" + name + "\"");
++
++ // Service params
++ if (elementParams != null && !elementParams.isEmpty()) {
++ Map<String, String> params = elementParams.get(name);
++ if (params != null && !params.isEmpty()) {
++ fw.write(",\n\"params\":{\n");
++ Iterator<String> paramNames = params.keySet().iterator();
++ while (paramNames.hasNext()) {
++ String paramName = paramNames.next();
++ String paramValue = params.get(paramName);
++ fw.write("\"" + paramName + "\":\"" + paramValue + "\"");
++ fw.write(paramNames.hasNext() ? ",\n" : "");
++ }
++ fw.write("\n}");
++ }
++ }
+
- private File writeYAML(String path,
- String discoveryType,
- String discoveryAddress,
- String discoveryUser,
- String providerConfig,
- String clusterName,
- Map<String, List<String>> services) throws Exception {
- return writeYAML(path, discoveryType, discoveryAddress, discoveryUser, providerConfig, clusterName, services, null);
- }
++ // Service URLs
++ List<String> urls = elementURLs.get(name);
++ if (urls != null) {
++ fw.write(",\n\"urls\":[");
++ Iterator<String> urlIter = urls.iterator();
++ while (urlIter.hasNext()) {
++ fw.write("\"" + urlIter.next() + "\"");
++ if (urlIter.hasNext()) {
++ fw.write(", ");
++ }
++ }
++ fw.write("]\n");
++ }
+
++ fw.write("}");
++ if (i++ < elementURLs.size() - 1) {
++ fw.write(",");
++ }
++ fw.write("\n");
++ }
++ }
++ }
+
+ private File writeYAML(String path,
+ String discoveryType,
+ String discoveryAddress,
+ String discoveryUser,
+ String providerConfig,
+ String clusterName,
+ Map<String, List<String>> services,
- Map<String, Map<String, String>> serviceParams) throws Exception {
++ Map<String, Map<String, String>> serviceParams,
++ Map<String, List<String>> apps,
++ Map<String, Map<String, String>> appParams) throws Exception {
++
+ File f = new File(path);
+
+ Writer fw = new FileWriter(f);
+ fw.write("---" + "\n");
+ fw.write("discovery-type: " + discoveryType + "\n");
+ fw.write("discovery-address: " + discoveryAddress + "\n");
+ fw.write("discovery-user: " + discoveryUser + "\n");
+ fw.write("provider-config-ref: " + providerConfig + "\n");
+ fw.write("cluster: " + clusterName+ "\n");
- fw.write("services:\n");
- for (String name : services.keySet()) {
++
++ if (services != null && !services.isEmpty()) {
++ fw.write("services:\n");
++ writeServiceOrApplicationYAML(fw, services, serviceParams);
++ }
++
++ if (apps != null && !apps.isEmpty()) {
++ fw.write("applications:\n");
++ writeServiceOrApplicationYAML(fw, apps, appParams);
++ }
++
++ fw.flush();
++ fw.close();
++
++ return f;
++ }
++
++ private void writeServiceOrApplicationYAML(Writer fw,
++ Map<String, List<String>> elementURLs,
++ Map<String, Map<String, String>> elementParams) throws Exception {
++ for (String name : elementURLs.keySet()) {
+ fw.write(" - name: " + name + "\n");
+
+ // Service params
- if (serviceParams != null && !serviceParams.isEmpty()) {
- if (serviceParams.containsKey(name)) {
- Map<String, String> params = serviceParams.get(name);
++ if (elementParams != null && !elementParams.isEmpty()) {
++ if (elementParams.containsKey(name)) {
++ Map<String, String> params = elementParams.get(name);
+ fw.write(" params:\n");
+ for (String paramName : params.keySet()) {
+ fw.write(" " + paramName + ": " + params.get(paramName) + "\n");
+ }
+ }
+ }
+
+ // Service URLs
- List<String> urls = services.get(name);
++ List<String> urls = elementURLs.get(name);
+ if (urls != null) {
+ fw.write(" urls:\n");
+ for (String url : urls) {
+ fw.write(" - " + url + "\n");
+ }
+ }
+ }
- fw.flush();
- fw.close();
++ }
+
- return f;
++
++ private void validateSimpleDescriptor(SimpleDescriptor sd,
++ String discoveryType,
++ String discoveryAddress,
++ String providerConfig,
++ String clusterName,
++ Map<String, List<String>> expectedServices) {
++ validateSimpleDescriptor(sd, discoveryType, discoveryAddress, providerConfig, clusterName, expectedServices, null);
++ }
++
++
++ private void validateSimpleDescriptor(SimpleDescriptor sd,
++ String discoveryType,
++ String discoveryAddress,
++ String providerConfig,
++ String clusterName,
++ Map<String, List<String>> expectedServices,
++ Map<String, Map<String, String>> expectedServiceParameters) {
++ validateSimpleDescriptor(sd,
++ discoveryType,
++ discoveryAddress,
++ providerConfig,
++ clusterName,
++ expectedServices,
++ expectedServiceParameters,
++ null,
++ null);
+ }
+
++ private void validateSimpleDescriptor(SimpleDescriptor sd,
++ String discoveryType,
++ String discoveryAddress,
++ String providerConfig,
++ String clusterName,
++ Map<String, List<String>> expectedServices,
++ Map<String, Map<String, String>> expectedServiceParameters,
++ Map<String, List<String>> expectedApps,
++ Map<String, Map<String, String>> expectedAppParameters) {
++ assertNotNull(sd);
++ assertEquals(discoveryType, sd.getDiscoveryType());
++ assertEquals(discoveryAddress, sd.getDiscoveryAddress());
++ assertEquals(providerConfig, sd.getProviderConfig());
++ assertEquals(clusterName, sd.getClusterName());
++
++ List<SimpleDescriptor.Service> actualServices = sd.getServices();
++
++ if (expectedServices == null) {
++ assertTrue(actualServices.isEmpty());
++ } else {
++ assertEquals(expectedServices.size(), actualServices.size());
++
++ for (SimpleDescriptor.Service actualService : actualServices) {
++ assertTrue(expectedServices.containsKey(actualService.getName()));
++ assertEquals(expectedServices.get(actualService.getName()), actualService.getURLs());
++
++ // Validate service parameters
++ if (expectedServiceParameters != null) {
++ if (expectedServiceParameters.containsKey(actualService.getName())) {
++ Map<String, String> expectedParams = expectedServiceParameters.get(actualService.getName());
++
++ Map<String, String> actualServiceParams = actualService.getParams();
++ assertNotNull(actualServiceParams);
++
++ // Validate the size of the service parameter set
++ assertEquals(expectedParams.size(), actualServiceParams.size());
++
++ // Validate the parameter contents
++ for (String paramName : actualServiceParams.keySet()) {
++ assertTrue(expectedParams.containsKey(paramName));
++ assertEquals(expectedParams.get(paramName), actualServiceParams.get(paramName));
++ }
++ }
++ }
++ }
++ }
++
++ List<SimpleDescriptor.Application> actualApps = sd.getApplications();
++
++ if (expectedApps == null) {
++ assertTrue(actualApps.isEmpty());
++ } else {
++ assertEquals(expectedApps.size(), actualApps.size());
++
++ for (SimpleDescriptor.Application actualApp : actualApps) {
++ assertTrue(expectedApps.containsKey(actualApp.getName()));
++ assertEquals(expectedApps.get(actualApp.getName()), actualApp.getURLs());
++
++ // Validate service parameters
++ if (expectedServiceParameters != null) {
++ if (expectedAppParameters.containsKey(actualApp.getName())) {
++ Map<String, String> expectedParams = expectedAppParameters.get(actualApp.getName());
++
++ Map<String, String> actualAppParams = actualApp.getParams();
++ assertNotNull(actualAppParams);
++
++ // Validate the size of the service parameter set
++ assertEquals(expectedParams.size(), actualAppParams.size());
++
++ // Validate the parameter contents
++ for (String paramName : actualAppParams.keySet()) {
++ assertTrue(expectedParams.containsKey(paramName));
++ assertEquals(expectedParams.get(paramName), actualAppParams.get(paramName));
++ }
++ }
++ }
++ }
++ }
++ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorHandlerTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorHandlerTest.java
index f40fad7,0000000..575b68a
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorHandlerTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorHandlerTest.java
@@@ -1,447 -1,0 +1,455 @@@
+/**
+ * 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.topology.simple;
+
+import org.apache.knox.gateway.topology.validation.TopologyValidator;
+import org.apache.knox.gateway.util.XmlUtils;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.io.FileUtils;
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
++import static org.hamcrest.Matchers.hasXPath;
++import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
++import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+
+public class SimpleDescriptorHandlerTest {
+
+ private static final String TEST_PROVIDER_CONFIG =
+ " <gateway>\n" +
+ " <provider>\n" +
+ " <role>authentication</role>\n" +
+ " <name>ShiroProvider</name>\n" +
+ " <enabled>true</enabled>\n" +
+ " <param>\n" +
+ " <!-- \n" +
+ " session timeout in minutes, this is really idle timeout,\n" +
+ " defaults to 30mins, if the property value is not defined,, \n" +
+ " current client authentication would expire if client idles contiuosly for more than this value\n" +
+ " -->\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" +
+ "\n" +
+ " <provider>\n" +
+ " <role>identity-assertion</role>\n" +
+ " <name>Default</name>\n" +
+ " <enabled>true</enabled>\n" +
+ " </provider>\n" +
+ "\n" +
+ " <!--\n" +
+ " Defines rules for mapping host names internal to a Hadoop cluster to externally accessible host names.\n" +
+ " For example, a hadoop service running in AWS may return a response that includes URLs containing the\n" +
+ " some AWS internal host name. If the client needs to make a subsequent request to the host identified\n" +
+ " in those URLs they need to be mapped to external host names that the client Knox can use to connect.\n" +
+ "\n" +
+ " If the external hostname and internal host names are same turn of this provider by setting the value of\n" +
+ " enabled parameter as false.\n" +
+ "\n" +
+ " The name parameter specifies the external host names in a comma separated list.\n" +
+ " The value parameter specifies corresponding internal host names in a comma separated list.\n" +
+ "\n" +
+ " Note that when you are using Sandbox, the external hostname needs to be localhost, as seen in out\n" +
+ " of box sandbox.xml. This is because Sandbox uses port mapping to allow clients to connect to the\n" +
+ " Hadoop services using localhost. In real clusters, external host names would almost never be localhost.\n" +
+ " -->\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";
+
+
+ /**
+ * KNOX-1006
+ *
+ * N.B. This test depends on the PropertiesFileServiceDiscovery extension being configured:
+ * org.apache.knox.gateway.topology.discovery.test.extension.PropertiesFileServiceDiscovery
+ */
+ @Test
+ public void testSimpleDescriptorHandler() throws Exception {
+
+ final String type = "PROPERTIES_FILE";
+ final String clusterName = "dummy";
+
+ // Create a properties file to be the source of service discovery details for this test
+ final File discoveryConfig = File.createTempFile(getClass().getName() + "_discovery-config", ".properties");
+
+ final String address = discoveryConfig.getAbsolutePath();
+
+ final Properties DISCOVERY_PROPERTIES = new Properties();
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".name", clusterName);
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".NAMENODE", "hdfs://namenodehost:8020");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".JOBTRACKER", "rpc://jobtrackerhostname:8050");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".WEBHDFS", "http://webhdfshost:1234");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".WEBHCAT", "http://webhcathost:50111/templeton");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".OOZIE", "http://ooziehost:11000/oozie");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".WEBHBASE", "http://webhbasehost:1234");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".HIVE", "http://hivehostname:10001/clipath");
+ DISCOVERY_PROPERTIES.setProperty(clusterName + ".RESOURCEMANAGER", "http://remanhost:8088/ws");
+
+ try {
+ DISCOVERY_PROPERTIES.store(new FileOutputStream(discoveryConfig), null);
+ } catch (FileNotFoundException e) {
+ fail(e.getMessage());
+ }
+
+ final Map<String, List<String>> serviceURLs = new HashMap<>();
+ serviceURLs.put("NAMENODE", null);
+ serviceURLs.put("JOBTRACKER", null);
+ serviceURLs.put("WEBHDFS", null);
+ serviceURLs.put("WEBHCAT", null);
+ serviceURLs.put("OOZIE", null);
+ serviceURLs.put("WEBHBASE", null);
+ serviceURLs.put("HIVE", null);
+ serviceURLs.put("RESOURCEMANAGER", null);
+ serviceURLs.put("AMBARIUI", Collections.singletonList("http://c6401.ambari.apache.org:8080"));
+ serviceURLs.put("KNOXSSO", null);
+
+ // Write the externalized provider config to a temp file
+ File providerConfig = new File(System.getProperty("java.io.tmpdir"), "ambari-cluster-policy.xml");
+ FileUtils.write(providerConfig, TEST_PROVIDER_CONFIG);
+
+ File topologyFile = null;
+ try {
+ File destDir = new File(System.getProperty("java.io.tmpdir")).getCanonicalFile();
+
+ Map<String, Map<String, String>> serviceParameters = new HashMap<>();
+ Map<String, String> knoxssoParams = new HashMap<>();
+ knoxssoParams.put("knoxsso.cookie.secure.only", "true");
+ knoxssoParams.put("knoxsso.token.ttl", "100000");
+ serviceParameters.put("KNOXSSO", knoxssoParams);
+
+ // Mock out the simple descriptor
+ SimpleDescriptor testDescriptor = EasyMock.createNiceMock(SimpleDescriptor.class);
+ EasyMock.expect(testDescriptor.getName()).andReturn("mysimpledescriptor").anyTimes();
+ EasyMock.expect(testDescriptor.getDiscoveryAddress()).andReturn(address).anyTimes();
+ EasyMock.expect(testDescriptor.getDiscoveryType()).andReturn(type).anyTimes();
+ EasyMock.expect(testDescriptor.getDiscoveryUser()).andReturn(null).anyTimes();
+ EasyMock.expect(testDescriptor.getProviderConfig()).andReturn(providerConfig.getAbsolutePath()).anyTimes();
+ EasyMock.expect(testDescriptor.getClusterName()).andReturn(clusterName).anyTimes();
+ List<SimpleDescriptor.Service> serviceMocks = new ArrayList<>();
+ for (String serviceName : serviceURLs.keySet()) {
+ SimpleDescriptor.Service svc = EasyMock.createNiceMock(SimpleDescriptor.Service.class);
+ EasyMock.expect(svc.getName()).andReturn(serviceName).anyTimes();
+ EasyMock.expect(svc.getURLs()).andReturn(serviceURLs.get(serviceName)).anyTimes();
+ EasyMock.expect(svc.getParams()).andReturn(serviceParameters.get(serviceName)).anyTimes();
+ EasyMock.replay(svc);
+ serviceMocks.add(svc);
+ }
+ EasyMock.expect(testDescriptor.getServices()).andReturn(serviceMocks).anyTimes();
+ EasyMock.replay(testDescriptor);
+
+ // Invoke the simple descriptor handler
+ Map<String, File> files =
+ SimpleDescriptorHandler.handle(testDescriptor,
+ providerConfig.getParentFile(), // simple desc co-located with provider config
+ destDir);
+ topologyFile = files.get("topology");
+
+ // Validate the resulting topology descriptor
+ assertTrue(topologyFile.exists());
+
+ // Validate the topology descriptor's correctness
+ TopologyValidator validator = new TopologyValidator( topologyFile.getAbsolutePath() );
+ if( !validator.validateTopology() ){
+ throw new SAXException( validator.getErrorString() );
+ }
+
+ XPathFactory xPathfactory = XPathFactory.newInstance();
+ XPath xpath = xPathfactory.newXPath();
+
+ // Parse the topology descriptor
+ Document topologyXml = XmlUtils.readXml(topologyFile);
+
++ // KNOX-1105 Mark generated topology files
++ assertThat("Expected the \"generated\" marker element in the topology XML, with value of \"true\".",
++ topologyXml,
++ hasXPath("/topology/generated", is("true")));
++
+ // Validate the provider configuration
+ Document extProviderConf = XmlUtils.readXml(new ByteArrayInputStream(TEST_PROVIDER_CONFIG.getBytes()));
+ Node gatewayNode = (Node) xpath.compile("/topology/gateway").evaluate(topologyXml, XPathConstants.NODE);
+ assertTrue("Resulting provider config should be identical to the referenced content.",
+ extProviderConf.getDocumentElement().isEqualNode(gatewayNode));
+
+ // Validate the service declarations
+ Map<String, List<String>> topologyServiceURLs = new HashMap<>();
+ NodeList serviceNodes =
+ (NodeList) xpath.compile("/topology/service").evaluate(topologyXml, XPathConstants.NODESET);
+ for (int serviceNodeIndex=0; serviceNodeIndex < serviceNodes.getLength(); serviceNodeIndex++) {
+ Node serviceNode = serviceNodes.item(serviceNodeIndex);
+
+ // Validate the role
+ Node roleNode = (Node) xpath.compile("role/text()").evaluate(serviceNode, XPathConstants.NODE);
+ assertNotNull(roleNode);
+ String role = roleNode.getNodeValue();
+
+ // Validate the URLs
+ NodeList urlNodes = (NodeList) xpath.compile("url/text()").evaluate(serviceNode, XPathConstants.NODESET);
+ for(int urlNodeIndex = 0 ; urlNodeIndex < urlNodes.getLength(); urlNodeIndex++) {
+ Node urlNode = urlNodes.item(urlNodeIndex);
+ assertNotNull(urlNode);
+ String url = urlNode.getNodeValue();
+
+ // If the service should have a URL (some don't require it)
+ if (serviceURLs.containsKey(role)) {
+ assertNotNull("Declared service should have a URL.", url);
+ if (!topologyServiceURLs.containsKey(role)) {
+ topologyServiceURLs.put(role, new ArrayList<>());
+ }
+ topologyServiceURLs.get(role).add(url); // Add it for validation later
+ }
+ }
+
+ // If params were declared in the descriptor, then validate them in the resulting topology file
+ Map<String, String> params = serviceParameters.get(role);
+ if (params != null) {
+ NodeList paramNodes = (NodeList) xpath.compile("param").evaluate(serviceNode, XPathConstants.NODESET);
+ for (int paramNodeIndex = 0; paramNodeIndex < paramNodes.getLength(); paramNodeIndex++) {
+ Node paramNode = paramNodes.item(paramNodeIndex);
+ String paramName = (String) xpath.compile("name/text()").evaluate(paramNode, XPathConstants.STRING);
+ String paramValue = (String) xpath.compile("value/text()").evaluate(paramNode, XPathConstants.STRING);
+ assertTrue(params.keySet().contains(paramName));
+ assertEquals(params.get(paramName), paramValue);
+ }
+ }
+
+ }
+ assertEquals("Unexpected number of service declarations.", (serviceURLs.size() - 1), topologyServiceURLs.size());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ providerConfig.delete();
+ discoveryConfig.delete();
+ if (topologyFile != null) {
+ topologyFile.delete();
+ }
+ }
+ }
+
+
+ /**
+ * KNOX-1006
+ *
+ * Verify the behavior of the SimpleDescriptorHandler when service discovery fails to produce a valid URL for
+ * a service.
+ *
+ * N.B. This test depends on the PropertiesFileServiceDiscovery extension being configured:
+ * org.apache.knox.gateway.topology.discovery.test.extension.PropertiesFileServiceDiscovery
+ */
+ @Test
+ public void testInvalidServiceURLFromDiscovery() throws Exception {
+ final String CLUSTER_NAME = "myproperties";
+
+ // Configure the PropertiesFile Service Discovery implementation for this test
+ final String DEFAULT_VALID_SERVICE_URL = "http://localhost:9999/thiswillwork";
+ Properties serviceDiscoverySourceProps = new Properties();
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".NAMENODE",
+ DEFAULT_VALID_SERVICE_URL.replace("http", "hdfs"));
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".JOBTRACKER",
+ DEFAULT_VALID_SERVICE_URL.replace("http", "rpc"));
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".WEBHDFS", DEFAULT_VALID_SERVICE_URL);
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".WEBHCAT", DEFAULT_VALID_SERVICE_URL);
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".OOZIE", DEFAULT_VALID_SERVICE_URL);
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".WEBHBASE", DEFAULT_VALID_SERVICE_URL);
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".HIVE", "{SCHEME}://localhost:10000/");
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".RESOURCEMANAGER", DEFAULT_VALID_SERVICE_URL);
+ serviceDiscoverySourceProps.setProperty(CLUSTER_NAME + ".AMBARIUI", DEFAULT_VALID_SERVICE_URL);
+ File serviceDiscoverySource = File.createTempFile("service-discovery", ".properties");
+ serviceDiscoverySourceProps.store(new FileOutputStream(serviceDiscoverySource),
+ "Test Service Discovery Source");
+
+ // Prepare a mock SimpleDescriptor
+ final String type = "PROPERTIES_FILE";
+ final String address = serviceDiscoverySource.getAbsolutePath();
+ final Map<String, List<String>> serviceURLs = new HashMap<>();
+ serviceURLs.put("NAMENODE", null);
+ serviceURLs.put("JOBTRACKER", null);
+ serviceURLs.put("WEBHDFS", null);
+ serviceURLs.put("WEBHCAT", null);
+ serviceURLs.put("OOZIE", null);
+ serviceURLs.put("WEBHBASE", null);
+ serviceURLs.put("HIVE", null);
+ serviceURLs.put("RESOURCEMANAGER", null);
+ serviceURLs.put("AMBARIUI", Collections.singletonList("http://c6401.ambari.apache.org:8080"));
+
+ // Write the externalized provider config to a temp file
+ File providerConfig = writeProviderConfig("ambari-cluster-policy.xml", TEST_PROVIDER_CONFIG);
+
+ File topologyFile = null;
+ try {
+ File destDir = (new File(".")).getCanonicalFile();
+
+ // Mock out the simple descriptor
+ SimpleDescriptor testDescriptor = EasyMock.createNiceMock(SimpleDescriptor.class);
+ EasyMock.expect(testDescriptor.getName()).andReturn("mysimpledescriptor").anyTimes();
+ EasyMock.expect(testDescriptor.getDiscoveryAddress()).andReturn(address).anyTimes();
+ EasyMock.expect(testDescriptor.getDiscoveryType()).andReturn(type).anyTimes();
+ EasyMock.expect(testDescriptor.getDiscoveryUser()).andReturn(null).anyTimes();
+ EasyMock.expect(testDescriptor.getProviderConfig()).andReturn(providerConfig.getAbsolutePath()).anyTimes();
+ EasyMock.expect(testDescriptor.getClusterName()).andReturn(CLUSTER_NAME).anyTimes();
+ List<SimpleDescriptor.Service> serviceMocks = new ArrayList<>();
+ for (String serviceName : serviceURLs.keySet()) {
+ SimpleDescriptor.Service svc = EasyMock.createNiceMock(SimpleDescriptor.Service.class);
+ EasyMock.expect(svc.getName()).andReturn(serviceName).anyTimes();
+ EasyMock.expect(svc.getURLs()).andReturn(serviceURLs.get(serviceName)).anyTimes();
+ EasyMock.replay(svc);
+ serviceMocks.add(svc);
+ }
+ EasyMock.expect(testDescriptor.getServices()).andReturn(serviceMocks).anyTimes();
+ EasyMock.replay(testDescriptor);
+
+ // Invoke the simple descriptor handler
+ Map<String, File> files =
+ SimpleDescriptorHandler.handle(testDescriptor,
+ providerConfig.getParentFile(), // simple desc co-located with provider config
+ destDir);
+
+ topologyFile = files.get("topology");
+
+ // Validate the resulting topology descriptor
+ assertTrue(topologyFile.exists());
+
+ // Validate the topology descriptor's correctness
+ TopologyValidator validator = new TopologyValidator( topologyFile.getAbsolutePath() );
+ if( !validator.validateTopology() ){
+ throw new SAXException( validator.getErrorString() );
+ }
+
+ XPathFactory xPathfactory = XPathFactory.newInstance();
+ XPath xpath = xPathfactory.newXPath();
+
+ // Parse the topology descriptor
+ Document topologyXml = XmlUtils.readXml(topologyFile);
+
+ // Validate the provider configuration
+ Document extProviderConf = XmlUtils.readXml(new ByteArrayInputStream(TEST_PROVIDER_CONFIG.getBytes()));
+ Node gatewayNode = (Node) xpath.compile("/topology/gateway").evaluate(topologyXml, XPathConstants.NODE);
+ assertTrue("Resulting provider config should be identical to the referenced content.",
+ extProviderConf.getDocumentElement().isEqualNode(gatewayNode));
+
+ // Validate the service declarations
+ List<String> topologyServices = new ArrayList<>();
+ Map<String, List<String>> topologyServiceURLs = new HashMap<>();
+ NodeList serviceNodes =
+ (NodeList) xpath.compile("/topology/service").evaluate(topologyXml, XPathConstants.NODESET);
+ for (int serviceNodeIndex=0; serviceNodeIndex < serviceNodes.getLength(); serviceNodeIndex++) {
+ Node serviceNode = serviceNodes.item(serviceNodeIndex);
+ Node roleNode = (Node) xpath.compile("role/text()").evaluate(serviceNode, XPathConstants.NODE);
+ assertNotNull(roleNode);
+ String role = roleNode.getNodeValue();
+ topologyServices.add(role);
+ NodeList urlNodes = (NodeList) xpath.compile("url/text()").evaluate(serviceNode, XPathConstants.NODESET);
+ for(int urlNodeIndex = 0 ; urlNodeIndex < urlNodes.getLength(); urlNodeIndex++) {
+ Node urlNode = urlNodes.item(urlNodeIndex);
+ assertNotNull(urlNode);
+ String url = urlNode.getNodeValue();
+ assertNotNull("Every declared service should have a URL.", url);
+ if (!topologyServiceURLs.containsKey(role)) {
+ topologyServiceURLs.put(role, new ArrayList<>());
+ }
+ topologyServiceURLs.get(role).add(url);
+ }
+ }
+
+ // There should not be a service element for HIVE, since it had no valid URLs
+ assertEquals("Unexpected number of service declarations.", serviceURLs.size() - 1, topologyServices.size());
+ assertFalse("The HIVE service should have been omitted from the generated topology.", topologyServices.contains("HIVE"));
+
+ assertEquals("Unexpected number of service URLs.", serviceURLs.size() - 1, topologyServiceURLs.size());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ serviceDiscoverySource.delete();
+ providerConfig.delete();
+ if (topologyFile != null) {
+ topologyFile.delete();
+ }
+ }
+ }
+
+
+ private File writeProviderConfig(String path, String content) throws IOException {
+ File f = new File(path);
+ FileUtils.write(f, content);
+ return f;
+ }
+
+}