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 2018/01/11 17:39:01 UTC

[34/53] [abbrv] knox git commit: Merge branch 'master' into KNOX-998-Package_Restructuring

http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
index 06da13d,0000000..4187214
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
@@@ -1,220 -1,0 +1,263 @@@
 +package org.apache.knox.gateway.config.impl;
 +
 +import org.apache.knox.test.TestUtils;
 +import org.hamcrest.CoreMatchers;
 +import org.junit.Test;
 +
 +import java.util.List;
++import java.util.concurrent.TimeUnit;
 +
 +import static org.hamcrest.CoreMatchers.is;
 +import static org.hamcrest.CoreMatchers.notNullValue;
 +import static org.hamcrest.MatcherAssert.assertThat;
 +import static org.hamcrest.Matchers.hasItems;
 +import static org.hamcrest.Matchers.nullValue;
++import static org.junit.Assert.assertNotEquals;
++import static org.junit.Assert.assertTrue;
++import static org.testng.Assert.assertEquals;
++import static org.testng.Assert.assertFalse;
++import static org.testng.Assert.assertNotNull;
 +
 +/**
 + * 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.
 + */
 +public class GatewayConfigImplTest {
 +
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testHttpServerSettings() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +
 +    // Check the defaults.
 +    assertThat( config.getHttpServerRequestBuffer(), is( 16*1024 ) );
 +    assertThat( config.getHttpServerRequestHeaderBuffer(), is( 8*1024 ) );
 +    assertThat( config.getHttpServerResponseBuffer(), is( 32*1024 ) );
 +    assertThat( config.getHttpServerResponseHeaderBuffer(), is( 8*1024 ) );
 +
 +    assertThat( GatewayConfigImpl.HTTP_SERVER_REQUEST_BUFFER, is( "gateway.httpserver.requestBuffer" ) );
 +    assertThat( GatewayConfigImpl.HTTP_SERVER_REQUEST_HEADER_BUFFER, is( "gateway.httpserver.requestHeaderBuffer" ) );
 +    assertThat( GatewayConfigImpl.HTTP_SERVER_RESPONSE_BUFFER, is( "gateway.httpserver.responseBuffer" ) );
 +    assertThat( GatewayConfigImpl.HTTP_SERVER_RESPONSE_HEADER_BUFFER, is( "gateway.httpserver.responseHeaderBuffer" ) );
 +
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_REQUEST_BUFFER, 32*1024 );
 +    assertThat( config.getHttpServerRequestBuffer(), is( 32*1024 ) );
 +
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_REQUEST_HEADER_BUFFER, 4*1024 );
 +    assertThat( config.getHttpServerRequestHeaderBuffer(), is( 4*1024 ) );
 +
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_RESPONSE_BUFFER, 16*1024 );
 +    assertThat( config.getHttpServerResponseBuffer(), is( 16*1024 ) );
 +
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_RESPONSE_HEADER_BUFFER, 6*1024 );
 +    assertThat( config.getHttpServerResponseHeaderBuffer(), is( 6*1024 ) );
 +
 +    // Restore the defaults.
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_REQUEST_BUFFER, 16*1024 );
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_REQUEST_HEADER_BUFFER, 8*1024 );
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_RESPONSE_BUFFER, 32*1024 );
 +    config.setInt( GatewayConfigImpl.HTTP_SERVER_RESPONSE_HEADER_BUFFER, 8*1024 );
 +  }
 +
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testGetGatewayDeploymentsBackupVersionLimit() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    assertThat( config.getGatewayDeploymentsBackupVersionLimit(), is(5) );
 +
 +    config.setInt( config.DEPLOYMENTS_BACKUP_VERSION_LIMIT, 3 );
 +    assertThat( config.getGatewayDeploymentsBackupVersionLimit(), is(3) );
 +
 +    config.setInt( config.DEPLOYMENTS_BACKUP_VERSION_LIMIT, -3 );
 +    assertThat( config.getGatewayDeploymentsBackupVersionLimit(), is(-1) );
 +
 +    config.setInt( config.DEPLOYMENTS_BACKUP_VERSION_LIMIT, 0 );
 +    assertThat( config.getGatewayDeploymentsBackupVersionLimit(), is(0) );
 +  }
 +
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testGetGatewayDeploymentsBackupAgeLimit() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    assertThat( config.getGatewayDeploymentsBackupAgeLimit(), is(-1L) );
 +
 +    config.set( config.DEPLOYMENTS_BACKUP_AGE_LIMIT, "1" );
 +    assertThat( config.getGatewayDeploymentsBackupAgeLimit(), is(86400000L) );
 +
 +    config.set( config.DEPLOYMENTS_BACKUP_AGE_LIMIT, "2" );
 +    assertThat( config.getGatewayDeploymentsBackupAgeLimit(), is(86400000L*2L) );
 +
 +    config.set( config.DEPLOYMENTS_BACKUP_AGE_LIMIT, "0" );
 +    assertThat( config.getGatewayDeploymentsBackupAgeLimit(), is(0L) );
 +
 +    config.set( config.DEPLOYMENTS_BACKUP_AGE_LIMIT, "X" );
 +    assertThat( config.getGatewayDeploymentsBackupAgeLimit(), is(-1L) );
 +  }
 +
 +
 +  @Test
 +  public void testSSLCiphers() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    List<String> list;
 +
 +    list = config.getIncludedSSLCiphers();
 +    assertThat( list, is(nullValue()) );
 +
 +    config.set( "ssl.include.ciphers", "none" );
 +    assertThat( config.getIncludedSSLCiphers(), is(nullValue()) );
 +
 +    config.set( "ssl.include.ciphers", "" );
 +    assertThat( config.getIncludedSSLCiphers(), is(nullValue()) );
 +
 +    config.set( "ssl.include.ciphers", "ONE" );
 +    assertThat( config.getIncludedSSLCiphers(), is(hasItems("ONE")) );
 +
 +    config.set( "ssl.include.ciphers", " ONE " );
 +    assertThat( config.getIncludedSSLCiphers(), is(hasItems("ONE")) );
 +
 +    config.set( "ssl.include.ciphers", "ONE,TWO" );
 +    assertThat( config.getIncludedSSLCiphers(), is(hasItems("ONE","TWO")) );
 +
 +    config.set( "ssl.include.ciphers", "ONE,TWO,THREE" );
 +    assertThat( config.getIncludedSSLCiphers(), is(hasItems("ONE","TWO","THREE")) );
 +
 +    config.set( "ssl.include.ciphers", " ONE , TWO , THREE " );
 +    assertThat( config.getIncludedSSLCiphers(), is(hasItems("ONE","TWO","THREE")) );
 +
 +    list = config.getExcludedSSLCiphers();
 +    assertThat( list, is(nullValue()) );
 +
 +    config.set( "ssl.exclude.ciphers", "none" );
 +    assertThat( config.getExcludedSSLCiphers(), is(nullValue()) );
 +
 +    config.set( "ssl.exclude.ciphers", "" );
 +    assertThat( config.getExcludedSSLCiphers(), is(nullValue()) );
 +
 +    config.set( "ssl.exclude.ciphers", "ONE" );
 +    assertThat( config.getExcludedSSLCiphers(), is(hasItems("ONE")) );
 +
 +    config.set( "ssl.exclude.ciphers", " ONE " );
 +    assertThat( config.getExcludedSSLCiphers(), is(hasItems("ONE")) );
 +
 +    config.set( "ssl.exclude.ciphers", "ONE,TWO" );
 +    assertThat( config.getExcludedSSLCiphers(), is(hasItems("ONE","TWO")) );
 +
 +    config.set( "ssl.exclude.ciphers", "ONE,TWO,THREE" );
 +    assertThat( config.getExcludedSSLCiphers(), is(hasItems("ONE","TWO","THREE")) );
 +
 +    config.set( "ssl.exclude.ciphers", " ONE , TWO , THREE " );
 +    assertThat( config.getExcludedSSLCiphers(), is(hasItems("ONE","TWO","THREE")) );
 +  }
 +
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testGlobalRulesServices() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    List<String> list;
 +
 +    list = config.getGlobalRulesServices();
 +    assertThat( list, is(notNullValue()) );
 +
 +    assertThat( list, is( CoreMatchers.hasItems("NAMENODE","JOBTRACKER", "WEBHDFS", "WEBHCAT", "OOZIE", "WEBHBASE", "HIVE", "RESOURCEMANAGER")));
 +
 +
 +    config.set( GatewayConfigImpl.GLOBAL_RULES_SERVICES, "none" );
 +    assertThat( config.getGlobalRulesServices(), is( CoreMatchers.hasItems("NAMENODE","JOBTRACKER", "WEBHDFS", "WEBHCAT", "OOZIE", "WEBHBASE", "HIVE", "RESOURCEMANAGER")) );
 +
 +    config.set( GatewayConfigImpl.GLOBAL_RULES_SERVICES, "" );
 +    assertThat( config.getGlobalRulesServices(), is( CoreMatchers.hasItems("NAMENODE","JOBTRACKER", "WEBHDFS", "WEBHCAT", "OOZIE", "WEBHBASE", "HIVE", "RESOURCEMANAGER")) );
 +
 +    config.set( GatewayConfigImpl.GLOBAL_RULES_SERVICES, "ONE" );
 +    assertThat( config.getGlobalRulesServices(), is(hasItems("ONE")) );
 +
 +    config.set( GatewayConfigImpl.GLOBAL_RULES_SERVICES, "ONE,TWO,THREE" );
 +    assertThat( config.getGlobalRulesServices(), is(hasItems("ONE","TWO","THREE")) );
 +
 +    config.set( GatewayConfigImpl.GLOBAL_RULES_SERVICES, " ONE , TWO , THREE " );
 +    assertThat( config.getGlobalRulesServices(), is(hasItems("ONE","TWO","THREE")) );
 +  }
 +
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testMetricsSettings() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    //test defaults
 +    assertThat(config.isMetricsEnabled(), is(false));
 +    assertThat(config.isJmxMetricsReportingEnabled(), is(false));
 +    assertThat(config.isGraphiteMetricsReportingEnabled(), is(false));
 +    assertThat(config.getGraphiteHost(), is("localhost"));
 +    assertThat(config.getGraphitePort(), is(32772));
 +  }
 +  
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testGatewayIdleTimeout() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    long idleTimeout = 0l;
 +    
 +    idleTimeout = config.getGatewayIdleTimeout();
 +    assertThat( idleTimeout, is(300000L));
 +
 +    config.set( GatewayConfigImpl.GATEWAY_IDLE_TIMEOUT, "15000" );
 +    idleTimeout = config.getGatewayIdleTimeout();
 +    assertThat( idleTimeout, is(15000L));
 +  }
 +  
 +  @Test( timeout = TestUtils.SHORT_TIMEOUT )
 +  public void testGatewayServerHeaderEnabled() {
 +    GatewayConfigImpl config = new GatewayConfigImpl();
 +    boolean serverHeaderEnabled = true;
 +    
 +    serverHeaderEnabled = config.isGatewayServerHeaderEnabled();
 +    assertThat( serverHeaderEnabled, is(true));
 +
 +    config.set( GatewayConfigImpl.SERVER_HEADER_ENABLED, "false");
 +    serverHeaderEnabled = config.isGatewayServerHeaderEnabled();
 +    assertThat( serverHeaderEnabled, is(false));
 +  }
 +
++
++  @Test
++  public void testGetRemoteConfigurationRegistryNames() {
++    GatewayConfigImpl config = new GatewayConfigImpl();
++
++    List<String> registryNames = config.getRemoteRegistryConfigurationNames();
++    assertNotNull(registryNames);
++    assertTrue(registryNames.isEmpty());
++
++    config.set(GatewayConfigImpl.CONFIG_REGISTRY_PREFIX + ".test1",
++               "type=ZooKeeper;address=host1:2181;authType=digest;principal=itsme;credentialAlias=testAlias");
++    registryNames = config.getRemoteRegistryConfigurationNames();
++    assertNotNull(registryNames);
++    assertFalse(registryNames.isEmpty());
++    assertEquals(1, registryNames.size());
++
++    config.set(GatewayConfigImpl.CONFIG_REGISTRY_PREFIX + ".test2",
++               "type=ZooKeeper;address=host2:2181,host3:2181,host4:2181");
++    registryNames = config.getRemoteRegistryConfigurationNames();
++    assertNotNull(registryNames);
++    assertFalse(registryNames.isEmpty());
++    assertEquals(registryNames.size(), 2);
++  }
++
++
++  @Test
++  public void testHTTPDefaultTimeouts() {
++    final GatewayConfigImpl config = new GatewayConfigImpl();
++
++    assertNotEquals(config.getHttpClientConnectionTimeout(), -1);
++    assertNotEquals(config.getHttpClientSocketTimeout(), -1);
++
++    assertEquals(TimeUnit.SECONDS.toMillis(20), config.getHttpClientConnectionTimeout());
++    assertEquals(TimeUnit.SECONDS.toMillis(20), config.getHttpClientSocketTimeout());
++
++  }
++
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/services/topology/DefaultTopologyServiceTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/services/topology/DefaultTopologyServiceTest.java
index 408d396,0000000..60cf633
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/services/topology/DefaultTopologyServiceTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/services/topology/DefaultTopologyServiceTest.java
@@@ -1,610 -1,0 +1,618 @@@
 +/**
 + * 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.services.topology;
 +
 +import org.apache.commons.io.FileUtils;
 +import org.apache.commons.io.FilenameUtils;
 +import org.apache.commons.io.IOUtils;
 +import org.apache.commons.io.monitor.FileAlterationListener;
 +import org.apache.commons.io.monitor.FileAlterationMonitor;
 +import org.apache.commons.io.monitor.FileAlterationObserver;
 +import org.apache.knox.gateway.config.GatewayConfig;
 +import org.apache.knox.gateway.services.topology.impl.DefaultTopologyService;
 +import org.apache.knox.gateway.services.security.AliasService;
 +import org.apache.knox.test.TestUtils;
 +import org.apache.knox.gateway.topology.Param;
 +import org.apache.knox.gateway.topology.Provider;
 +import org.apache.knox.gateway.topology.Topology;
 +import org.apache.knox.gateway.topology.TopologyEvent;
 +import org.apache.knox.gateway.topology.TopologyListener;
 +import org.easymock.EasyMock;
 +import org.junit.After;
 +import org.junit.Before;
 +import org.junit.Test;
 +
 +import java.io.File;
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.io.OutputStream;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.Collection;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +
 +import static org.easymock.EasyMock.anyObject;
 +import static org.hamcrest.CoreMatchers.is;
 +import static org.hamcrest.Matchers.hasItem;
 +import static org.hamcrest.core.IsNull.notNullValue;
 +import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertFalse;
 +import static org.junit.Assert.assertNotEquals;
 +import static org.junit.Assert.assertNotNull;
 +import static org.junit.Assert.assertThat;
 +import static org.junit.Assert.assertTrue;
 +
 +public class DefaultTopologyServiceTest {
 +
 +  @Before
 +  public void setUp() throws Exception {
 +  }
 +
 +  @After
 +  public void tearDown() throws Exception {
 +  }
 +
 +  private File createDir() throws IOException {
 +    return TestUtils.createTempDir(this.getClass().getSimpleName() + "-");
 +  }
 +
 +  private File createFile(File parent, String name, String resource, long timestamp) throws IOException {
 +    File file = new File(parent, name);
 +    if (!file.exists()) {
 +      FileUtils.touch(file);
 +    }
 +    InputStream input = ClassLoader.getSystemResourceAsStream(resource);
 +    OutputStream output = FileUtils.openOutputStream(file);
 +    IOUtils.copy(input, output);
 +    //KNOX-685: output.flush();
 +    input.close();
 +    output.close();
 +    file.setLastModified(timestamp);
 +    assertTrue("Failed to create test file " + file.getAbsolutePath(), file.exists());
 +    assertTrue("Failed to populate test file " + file.getAbsolutePath(), file.length() > 0);
 +
 +    return file;
 +  }
 +
 +  @Test
 +  public void testGetTopologies() throws Exception {
 +
 +    File dir = createDir();
 +    File topologyDir = new File(dir, "topologies");
 +
++    File descriptorsDir = new File(dir, "descriptors");
++    descriptorsDir.mkdirs();
++
++    File sharedProvidersDir = new File(dir, "shared-providers");
++    sharedProvidersDir.mkdirs();
++
 +    long time = topologyDir.lastModified();
 +    try {
 +      createFile(topologyDir, "one.xml", "org/apache/knox/gateway/topology/file/topology-one.xml", time);
 +
 +      TestTopologyListener topoListener = new TestTopologyListener();
 +      FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
 +
 +      TopologyService provider = new DefaultTopologyService();
 +      Map<String, String> c = new HashMap<>();
 +
 +      GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
 +      EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
-       EasyMock.expect(config.getGatewayConfDir()).andReturn(topologyDir.getParentFile().getAbsolutePath()).anyTimes();
++      EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
++      EasyMock.expect(config.getGatewayProvidersConfigDir()).andReturn(sharedProvidersDir.getAbsolutePath()).anyTimes();
++      EasyMock.expect(config.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
 +      EasyMock.replay(config);
 +
 +      provider.init(config, c);
 +
 +      provider.addTopologyChangeListener(topoListener);
 +
 +      provider.reloadTopologies();
 +
 +      Collection<Topology> topologies = provider.getTopologies();
 +      assertThat(topologies, notNullValue());
 +      assertThat(topologies.size(), is(1));
 +      Topology topology = topologies.iterator().next();
 +      assertThat(topology.getName(), is("one"));
 +      assertThat(topology.getTimestamp(), is(time));
 +      assertThat(topoListener.events.size(), is(1));
 +      topoListener.events.clear();
 +
 +      // Add a file to the directory.
 +      File two = createFile(topologyDir, "two.xml",
 +          "org/apache/knox/gateway/topology/file/topology-two.xml", 1L);
 +      provider.reloadTopologies();
 +      topologies = provider.getTopologies();
 +      assertThat(topologies.size(), is(2));
 +      Set<String> names = new HashSet<>(Arrays.asList("one", "two"));
 +      Iterator<Topology> iterator = topologies.iterator();
 +      topology = iterator.next();
 +      assertThat(names, hasItem(topology.getName()));
 +      names.remove(topology.getName());
 +      topology = iterator.next();
 +      assertThat(names, hasItem(topology.getName()));
 +      names.remove(topology.getName());
 +      assertThat(names.size(), is(0));
 +      assertThat(topoListener.events.size(), is(1));
 +      List<TopologyEvent> events = topoListener.events.get(0);
 +      assertThat(events.size(), is(1));
 +      TopologyEvent event = events.get(0);
 +      assertThat(event.getType(), is(TopologyEvent.Type.CREATED));
 +      assertThat(event.getTopology(), notNullValue());
 +
 +      // Update a file in the directory.
 +      two = createFile(topologyDir, "two.xml",
 +          "org/apache/knox/gateway/topology/file/topology-three.xml", 2L);
 +      provider.reloadTopologies();
 +      topologies = provider.getTopologies();
 +      assertThat(topologies.size(), is(2));
 +      names = new HashSet<>(Arrays.asList("one", "two"));
 +      iterator = topologies.iterator();
 +      topology = iterator.next();
 +      assertThat(names, hasItem(topology.getName()));
 +      names.remove(topology.getName());
 +      topology = iterator.next();
 +      assertThat(names, hasItem(topology.getName()));
 +      names.remove(topology.getName());
 +      assertThat(names.size(), is(0));
 +
 +      // Remove a file from the directory.
 +      two.delete();
 +      provider.reloadTopologies();
 +      topologies = provider.getTopologies();
 +      assertThat(topologies.size(), is(1));
 +      topology = topologies.iterator().next();
 +      assertThat(topology.getName(), is("one"));
 +      assertThat(topology.getTimestamp(), is(time));
 +
 +    } finally {
 +      FileUtils.deleteQuietly(dir);
 +    }
 +  }
 +
 +  /**
 +   * KNOX-1014
 +   *
 +   * Test the lifecycle relationship between simple descriptors and topology files.
 +   *
 +   * N.B. This test depends on the DummyServiceDiscovery extension being configured:
 +   *        org.apache.knox.gateway.topology.discovery.test.extension.DummyServiceDiscovery
 +   */
 +  @Test
 +  public void testSimpleDescriptorsTopologyGeneration() throws Exception {
 +
 +    File dir = createDir();
 +    File topologyDir = new File(dir, "topologies");
 +    topologyDir.mkdirs();
 +
 +    File descriptorsDir = new File(dir, "descriptors");
 +    descriptorsDir.mkdirs();
 +
 +    File sharedProvidersDir = new File(dir, "shared-providers");
 +    sharedProvidersDir.mkdirs();
 +
 +    try {
 +      TestTopologyListener topoListener = new TestTopologyListener();
 +      FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
 +
 +      TopologyService provider = new DefaultTopologyService();
 +      Map<String, String> c = new HashMap<>();
 +
 +      GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
 +      EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
 +      EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
 +      EasyMock.replay(config);
 +
 +      provider.init(config, c);
 +      provider.addTopologyChangeListener(topoListener);
 +      provider.reloadTopologies();
 +
 +
 +      // Add a simple descriptor to the descriptors dir to verify topology generation and loading (KNOX-1006)
 +      AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
 +      EasyMock.expect(aliasService.getPasswordFromAliasForGateway(anyObject(String.class))).andReturn(null).anyTimes();
 +      EasyMock.replay(aliasService);
 +      DefaultTopologyService.DescriptorsMonitor dm =
 +              new DefaultTopologyService.DescriptorsMonitor(topologyDir, aliasService);
 +
 +      // Listener to simulate the topologies directory monitor, to notice when a topology has been deleted
 +      provider.addTopologyChangeListener(new TestTopologyDeleteListener((DefaultTopologyService)provider));
 +
 +      // Write out the referenced provider config first
 +      File provCfgFile = createFile(sharedProvidersDir,
 +                                    "ambari-cluster-policy.xml",
 +                                    "org/apache/knox/gateway/topology/file/ambari-cluster-policy.xml",
 +                                    System.currentTimeMillis());
 +      try {
 +        // Create the simple descriptor in the descriptors dir
 +        File simpleDesc = createFile(descriptorsDir,
 +                                     "four.json",
 +                                     "org/apache/knox/gateway/topology/file/simple-topology-four.json",
 +                                     System.currentTimeMillis());
 +
 +        // Trigger the topology generation by noticing the simple descriptor
 +        dm.onFileChange(simpleDesc);
 +
 +        // Load the generated topology
 +        provider.reloadTopologies();
 +        Collection<Topology> topologies = provider.getTopologies();
 +        assertThat(topologies.size(), is(1));
 +        Iterator<Topology> iterator = topologies.iterator();
 +        Topology topology = iterator.next();
 +        assertThat("four", is(topology.getName()));
 +        int serviceCount = topology.getServices().size();
 +        assertEquals("Expected the same number of services as are declared in the simple dscriptor.", 10, serviceCount);
 +
 +        // Overwrite the simple descriptor with a different set of services, and check that the changes are
 +        // propagated to the associated topology
 +        simpleDesc = createFile(descriptorsDir,
 +                                "four.json",
 +                                "org/apache/knox/gateway/topology/file/simple-descriptor-five.json",
 +                                System.currentTimeMillis());
 +        dm.onFileChange(simpleDesc);
 +        provider.reloadTopologies();
 +        topologies = provider.getTopologies();
 +        topology = topologies.iterator().next();
 +        assertNotEquals(serviceCount, topology.getServices().size());
 +        assertEquals(6, topology.getServices().size());
 +
 +        // Delete the simple descriptor, and make sure that the associated topology file is deleted
 +        simpleDesc.delete();
 +        dm.onFileDelete(simpleDesc);
 +        provider.reloadTopologies();
 +        topologies = provider.getTopologies();
 +        assertTrue(topologies.isEmpty());
 +
 +        // Delete a topology file, and make sure that the associated simple descriptor is deleted
 +        // Overwrite the simple descriptor with a different set of services, and check that the changes are
 +        // propagated to the associated topology
 +        simpleDesc = createFile(descriptorsDir,
 +                                "deleteme.json",
 +                                "org/apache/knox/gateway/topology/file/simple-descriptor-five.json",
 +                                System.currentTimeMillis());
 +        dm.onFileChange(simpleDesc);
 +        provider.reloadTopologies();
 +        topologies = provider.getTopologies();
 +        assertFalse(topologies.isEmpty());
 +        topology = topologies.iterator().next();
 +        assertEquals("deleteme", topology.getName());
 +        File topologyFile = new File(topologyDir, topology.getName() + ".xml");
 +        assertTrue(topologyFile.exists());
 +        topologyFile.delete();
 +        provider.reloadTopologies();
 +        assertFalse("Simple descriptor should have been deleted because the associated topology was.",
 +                    simpleDesc.exists());
 +
 +      } finally {
 +        provCfgFile.delete();
 +      }
 +    } finally {
 +      FileUtils.deleteQuietly(dir);
 +    }
 +  }
 +
 +  /**
 +   * KNOX-1014
 +   *
 +   * Test the lifecycle relationship between provider configuration files, simple descriptors, and topology files.
 +   *
 +   * N.B. This test depends on the DummyServiceDiscovery extension being configured:
 +   *        org.apache.knox.gateway.topology.discovery.test.extension.DummyServiceDiscovery
 +   */
 +  @Test
 +  public void testTopologiesUpdateFromProviderConfigChange() throws Exception {
 +    File dir = createDir();
 +    File topologyDir = new File(dir, "topologies");
 +    topologyDir.mkdirs();
 +
 +    File descriptorsDir = new File(dir, "descriptors");
 +    descriptorsDir.mkdirs();
 +
 +    File sharedProvidersDir = new File(dir, "shared-providers");
 +    sharedProvidersDir.mkdirs();
 +
 +    try {
 +      TestTopologyListener topoListener = new TestTopologyListener();
 +      FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
 +
 +      TopologyService ts = new DefaultTopologyService();
 +      Map<String, String> c = new HashMap<>();
 +
 +      GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
 +      EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
 +      EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
 +      EasyMock.replay(config);
 +
 +      ts.init(config, c);
 +      ts.addTopologyChangeListener(topoListener);
 +      ts.reloadTopologies();
 +
 +      java.lang.reflect.Field dmField = ts.getClass().getDeclaredField("descriptorsMonitor");
 +      dmField.setAccessible(true);
 +      DefaultTopologyService.DescriptorsMonitor dm = (DefaultTopologyService.DescriptorsMonitor) dmField.get(ts);
 +
 +      // Write out the referenced provider configs first
 +      createFile(sharedProvidersDir,
 +                 "provider-config-one.xml",
 +                 "org/apache/knox/gateway/topology/file/provider-config-one.xml",
 +                 System.currentTimeMillis());
 +
 +      // Create the simple descriptor, which depends on provider-config-one.xml
 +      File simpleDesc = createFile(descriptorsDir,
 +                                   "six.json",
 +                                   "org/apache/knox/gateway/topology/file/simple-descriptor-six.json",
 +                                   System.currentTimeMillis());
 +
 +      // "Notice" the simple descriptor change, and generate a topology based on it
 +      dm.onFileChange(simpleDesc);
 +
 +      // Load the generated topology
 +      ts.reloadTopologies();
 +      Collection<Topology> topologies = ts.getTopologies();
 +      assertThat(topologies.size(), is(1));
 +      Iterator<Topology> iterator = topologies.iterator();
 +      Topology topology = iterator.next();
 +      assertFalse("The Shiro provider is disabled in provider-config-one.xml",
 +                  topology.getProvider("authentication", "ShiroProvider").isEnabled());
 +
 +      // Overwrite the referenced provider configuration with a different ShiroProvider config, and check that the
 +      // changes are propagated to the associated topology
 +      File providerConfig = createFile(sharedProvidersDir,
 +                                       "provider-config-one.xml",
 +                                       "org/apache/knox/gateway/topology/file/ambari-cluster-policy.xml",
 +                                       System.currentTimeMillis());
 +
 +      // "Notice" the simple descriptor change as a result of the referenced config change
 +      dm.onFileChange(simpleDesc);
 +
 +      // Load the generated topology
 +      ts.reloadTopologies();
 +      topologies = ts.getTopologies();
 +      assertFalse(topologies.isEmpty());
 +      topology = topologies.iterator().next();
 +      assertTrue("The Shiro provider is enabled in ambari-cluster-policy.xml",
 +              topology.getProvider("authentication", "ShiroProvider").isEnabled());
 +
 +      // Delete the provider configuration, and make sure that the associated topology file is unaffected.
 +      // The topology file should not be affected because the simple descriptor handling will fail to resolve the
 +      // referenced provider configuration.
 +      providerConfig.delete();     // Delete the file
 +      dm.onFileChange(simpleDesc); // The provider config deletion will trigger a descriptor change notification
 +      ts.reloadTopologies();
 +      topologies = ts.getTopologies();
 +      assertFalse(topologies.isEmpty());
 +      assertTrue("The Shiro provider is enabled in ambari-cluster-policy.xml",
 +              topology.getProvider("authentication", "ShiroProvider").isEnabled());
 +
 +    } finally {
 +      FileUtils.deleteQuietly(dir);
 +    }
 +  }
 +
 +  /**
 +   * KNOX-1039
 +   */
 +  @Test
 +  public void testConfigurationCRUDAPI() throws Exception {
 +    File dir = createDir();
 +    File topologyDir = new File(dir, "topologies");
 +    topologyDir.mkdirs();
 +
 +    File descriptorsDir = new File(dir, "descriptors");
 +    descriptorsDir.mkdirs();
 +
 +    File sharedProvidersDir = new File(dir, "shared-providers");
 +    sharedProvidersDir.mkdirs();
 +
 +    try {
 +      TestTopologyListener topoListener = new TestTopologyListener();
 +      FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
 +
 +      TopologyService ts = new DefaultTopologyService();
 +      Map<String, String> c = new HashMap<>();
 +
 +      GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
 +      EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
 +      EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
 +      EasyMock.replay(config);
 +
 +      ts.init(config, c);
 +      ts.addTopologyChangeListener(topoListener);
 +      ts.reloadTopologies();
 +
 +      java.lang.reflect.Field dmField = ts.getClass().getDeclaredField("descriptorsMonitor");
 +      dmField.setAccessible(true);
 +      DefaultTopologyService.DescriptorsMonitor dm = (DefaultTopologyService.DescriptorsMonitor) dmField.get(ts);
 +
 +      final String simpleDescName  = "six.json";
 +      final String provConfOne     = "provider-config-one.xml";
 +      final String provConfTwo     = "ambari-cluster-policy.xml";
 +
 +      // "Deploy" the referenced provider configs first
 +      boolean isDeployed =
 +        ts.deployProviderConfiguration(provConfOne,
 +                FileUtils.readFileToString(new File(ClassLoader.getSystemResource(
 +                    "org/apache/knox/gateway/topology/file/provider-config-one.xml").toURI())));
 +      assertTrue(isDeployed);
 +      File provConfOneFile = new File(sharedProvidersDir, provConfOne);
 +      assertTrue(provConfOneFile.exists());
 +
 +      isDeployed =
 +        ts.deployProviderConfiguration(provConfTwo,
 +                FileUtils.readFileToString(new File(ClassLoader.getSystemResource(
 +                    "org/apache/knox/gateway/topology/file/ambari-cluster-policy.xml").toURI())));
 +      assertTrue(isDeployed);
 +      File provConfTwoFile = new File(sharedProvidersDir, provConfTwo);
 +      assertTrue(provConfTwoFile.exists());
 +
 +      // Validate the provider configurations known by the topology service
 +      Collection<File> providerConfigurations = ts.getProviderConfigurations();
 +      assertNotNull(providerConfigurations);
 +      assertEquals(2, providerConfigurations.size());
 +      assertTrue(providerConfigurations.contains(provConfOneFile));
 +      assertTrue(providerConfigurations.contains(provConfTwoFile));
 +
 +      // "Deploy" the simple descriptor, which depends on provConfOne
 +      isDeployed =
 +        ts.deployDescriptor(simpleDescName,
 +            FileUtils.readFileToString(new File(ClassLoader.getSystemResource(
 +                "org/apache/knox/gateway/topology/file/simple-descriptor-six.json").toURI())));
 +      assertTrue(isDeployed);
 +      File simpleDesc = new File(descriptorsDir, simpleDescName);
 +      assertTrue(simpleDesc.exists());
 +
 +      // Validate the simple descriptors known by the topology service
 +      Collection<File> descriptors = ts.getDescriptors();
 +      assertNotNull(descriptors);
 +      assertEquals(1, descriptors.size());
 +      assertTrue(descriptors.contains(simpleDesc));
 +
 +      // "Notice" the simple descriptor, so the provider configuration dependency relationship is recorded
 +      dm.onFileChange(simpleDesc);
 +
 +      // Attempt to delete the referenced provConfOne
 +      assertFalse("Should not be able to delete a provider configuration that is referenced by one or more descriptors",
 +                  ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfOne)));
 +
 +      // Overwrite the simple descriptor with content that changes the provider config reference to provConfTwo
 +      isDeployed =
 +        ts.deployDescriptor(simpleDescName,
 +              FileUtils.readFileToString(new File(ClassLoader.getSystemResource(
 +                  "org/apache/knox/gateway/topology/file/simple-descriptor-five.json").toURI())));
 +      assertTrue(isDeployed);
 +      assertTrue(simpleDesc.exists());
 +      ts.getProviderConfigurations();
 +
 +      // "Notice" the simple descriptor, so the provider configuration dependency relationship is updated
 +      dm.onFileChange(simpleDesc);
 +
 +      // Attempt to delete the referenced provConfOne
 +      assertTrue("Should be able to delete the provider configuration, now that it's not referenced by any descriptors",
 +                 ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfOne)));
 +
 +      // Re-validate the provider configurations known by the topology service
 +      providerConfigurations = ts.getProviderConfigurations();
 +      assertNotNull(providerConfigurations);
 +      assertEquals(1, providerConfigurations.size());
 +      assertFalse(providerConfigurations.contains(provConfOneFile));
 +      assertTrue(providerConfigurations.contains(provConfTwoFile));
 +
 +      // Attempt to delete the referenced provConfTwo
 +      assertFalse("Should not be able to delete a provider configuration that is referenced by one or more descriptors",
 +                  ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfTwo)));
 +
 +      // Delete the referencing simple descriptor
 +      assertTrue(ts.deleteDescriptor(FilenameUtils.getBaseName(simpleDescName)));
 +      assertFalse(simpleDesc.exists());
 +
 +      // Re-validate the simple descriptors known by the topology service
 +      descriptors = ts.getDescriptors();
 +      assertNotNull(descriptors);
 +      assertTrue(descriptors.isEmpty());
 +
 +      // "Notice" the simple descriptor, so the provider configuration dependency relationship is updated
 +      dm.onFileDelete(simpleDesc);
 +
 +      // Attempt to delete the referenced provConfTwo
 +      assertTrue("Should be able to delete the provider configuration, now that it's not referenced by any descriptors",
 +                 ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfTwo)));
 +
 +      // Re-validate the provider configurations known by the topology service
 +      providerConfigurations = ts.getProviderConfigurations();
 +      assertNotNull(providerConfigurations);
 +      assertTrue(providerConfigurations.isEmpty());
 +
 +    } finally {
 +      FileUtils.deleteQuietly(dir);
 +    }
 +  }
 +
 +  private void kickMonitor(FileAlterationMonitor monitor) {
 +    for (FileAlterationObserver observer : monitor.getObservers()) {
 +      observer.checkAndNotify();
 +    }
 +  }
 +
 +
 +  @Test
 +  public void testProviderParamsOrderIsPreserved() {
 +
 +    Provider provider = new Provider();
 +    String names[] = {"ldapRealm=",
 +        "ldapContextFactory",
 +        "ldapRealm.contextFactory",
 +        "ldapGroupRealm",
 +        "ldapGroupRealm.contextFactory",
 +        "ldapGroupRealm.contextFactory.systemAuthenticationMechanism"
 +    };
 +
 +    Param param = null;
 +    for (String name : names) {
 +      param = new Param();
 +      param.setName(name);
 +      param.setValue(name);
 +      provider.addParam(param);
 +
 +    }
 +    Map<String, String> params = provider.getParams();
 +    Set<String> keySet = params.keySet();
 +    Iterator<String> iter = keySet.iterator();
 +    int i = 0;
 +    while (iter.hasNext()) {
 +      assertTrue(iter.next().equals(names[i++]));
 +    }
 +
 +  }
 +
 +  private class TestTopologyListener implements TopologyListener {
 +
 +    ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>();
 +
 +    @Override
 +    public void handleTopologyEvent(List<TopologyEvent> events) {
 +      this.events.add(events);
 +    }
 +
 +  }
 +
 +
 +  private class TestTopologyDeleteListener implements TopologyListener {
 +
 +    FileAlterationListener delegate;
 +
 +    TestTopologyDeleteListener(FileAlterationListener delegate) {
 +      this.delegate = delegate;
 +    }
 +
 +    @Override
 +    public void handleTopologyEvent(List<TopologyEvent> events) {
 +      for (TopologyEvent event : events) {
 +        if (event.getType().equals(TopologyEvent.Type.DELETED)) {
 +          delegate.onFileDelete(new File(event.getTopology().getUri()));
 +        }
 +      }
 +    }
 +
 +  }
 +
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/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 df31f3d,0000000..2622f13
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,681 -1,0 +1,690 @@@
 +/**
 + * 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
++        YAML,
++        YML
 +    }
 +
 +    @Test
 +    public void testParseJSONSimpleDescriptor() throws Exception {
 +        testParseSimpleDescriptor(FileType.JSON);
 +    }
 +
 +    @Test
 +    public void testParseYAMLSimpleDescriptor() throws Exception {
++        testParseSimpleDescriptor(FileType.YML);
 +        testParseSimpleDescriptor(FileType.YAML);
 +    }
 +
 +    @Test
 +    public void testParseJSONSimpleDescriptorWithServiceParams() throws Exception {
 +        testParseSimpleDescriptorWithServiceParams(FileType.JSON);
 +    }
 +
 +    @Test
 +    public void testParseYAMLSimpleDescriptorWithServiceParams() throws Exception {
++        testParseSimpleDescriptorWithServiceParams(FileType.YML);
 +        testParseSimpleDescriptorWithServiceParams(FileType.YAML);
 +    }
 +
 +    @Test
 +    public void testParseJSONSimpleDescriptorWithApplications() throws Exception {
 +        testParseSimpleDescriptorWithApplications(FileType.JSON);
 +    }
 +
 +    @Test
 +    public void testParseYAMLSimpleDescriptorApplications() throws Exception {
++        testParseSimpleDescriptorWithApplications(FileType.YML);
 +        testParseSimpleDescriptorWithApplications(FileType.YAML);
 +    }
 +
 +
 +    @Test
 +    public void testParseJSONSimpleDescriptorWithServicesAndApplications() throws Exception {
 +        testParseSimpleDescriptorWithServicesAndApplications(FileType.JSON);
 +    }
 +
 +    @Test
 +    public void testParseYAMLSimpleDescriptorWithServicesAndApplications() throws Exception {
++        testParseSimpleDescriptorWithServicesAndApplications(FileType.YML);
 +        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    = "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", Collections.singletonList("http://c6401.ambari.apache.org:8080"));
 +
 +        String fileName = "test-topology." + getFileExtensionForType(type);
 +        File testFile = null;
 +        try {
 +            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 (testFile != null) {
 +                try {
 +                    testFile.delete();
 +                } catch (Exception e) {
 +                    // Ignore
 +                }
 +            }
 +        }
 +    }
 +
 +    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." + getFileExtensionForType(type);
 +        File testFile = null;
 +        try {
 +            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);
 +        } finally {
 +            if (testFile != null) {
 +                try {
 +                    testFile.delete();
 +                } catch (Exception e) {
 +                    // Ignore
 +                }
 +            }
 +        }
 +    }
 +
 +    private void testParseSimpleDescriptorWithApplications(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>> 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 {
 +            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 (testFile != null) {
 +                try {
 +                    testFile.delete();
 +                } catch (Exception e) {
 +                    // Ignore
 +                }
 +            }
 +        }
 +    }
 +
 +    private void testParseSimpleDescriptorWithServicesAndApplications(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);
 +
 +        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 {
 +            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 (testFile != null) {
 +                try {
 +                    testFile.delete();
 +                } catch (Exception e) {
 +                    // Ignore
 +                }
 +            }
 +        }
 +    }
 +
 +    private String getFileExtensionForType(FileType type) {
 +        String extension = null;
 +        switch (type) {
 +            case JSON:
 +                extension = "json";
 +                break;
-             case YAML:
++            case YML:
 +                extension = "yml";
 +                break;
++            case YAML:
++                extension = "yaml";
++                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 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 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:
++            case YML:
 +                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,
 +                           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 + "\"");
 +
 +        if (services != null && !services.isEmpty()) {
 +            fw.write(",\n\"services\":[\n");
 +            writeServiceOrApplicationJSON(fw, services, serviceParams);
 +            fw.write("]\n");
 +        }
 +
 +        if (apps != null && !apps.isEmpty()) {
 +            fw.write(",\n\"applications\":[\n");
 +            writeServiceOrApplicationJSON(fw, apps, appParams);
 +            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}");
 +                    }
 +                }
 +
 +                // 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,
 +                           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");
 +
 +        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 (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 = elementURLs.get(name);
 +            if (urls != null) {
 +                fw.write("      urls:\n");
 +                for (String url : urls) {
 +                    fw.write("          - " + url + "\n");
 +                }
 +            }
 +        }
 +    }
 +
 +
 +    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));
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +}