You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2017/11/08 23:21:24 UTC

knox git commit: KNOX-1110 - Simple Descriptors Must Accommodate Application elements (Phil Zampino via lmccay)

Repository: knox
Updated Branches:
  refs/heads/master 6b250b193 -> a068eb8da


KNOX-1110 - Simple Descriptors Must Accommodate Application elements (Phil Zampino via lmccay)

Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/a068eb8d
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/a068eb8d
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/a068eb8d

Branch: refs/heads/master
Commit: a068eb8da8848ca5b5729fb568984621bfb60bf2
Parents: 6b250b1
Author: Larry McCay <lm...@hortonworks.com>
Authored: Wed Nov 8 18:21:09 2017 -0500
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Wed Nov 8 18:21:09 2017 -0500

----------------------------------------------------------------------
 .../topology/simple/SimpleDescriptor.java       |  10 +
 .../simple/SimpleDescriptorHandler.java         |  31 +
 .../topology/simple/SimpleDescriptorImpl.java   |  42 +-
 .../simple/SimpleDescriptorFactoryTest.java     | 631 +++++++++++++------
 4 files changed, 527 insertions(+), 187 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/a068eb8d/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptor.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptor.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptor.java
index 7072965..9cb0e2f 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptor.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptor.java
@@ -37,6 +37,8 @@ public interface SimpleDescriptor {
 
     List<Service> getServices();
 
+    List<Application> getApplications();
+
 
     interface Service {
         String getName();
@@ -45,4 +47,12 @@ public interface SimpleDescriptor {
 
         List<String> getURLs();
     }
+
+    interface Application {
+        String getName();
+
+        Map<String, String> getParams();
+
+        List<String> getURLs();
+    }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/a068eb8d/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorHandler.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorHandler.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorHandler.java
index 70c9539..040eb86 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorHandler.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorHandler.java
@@ -161,6 +161,7 @@ public class SimpleDescriptorHandler {
             }
             policyReader.close();
 
+            // Services
             // Sort the service names to write the services alphabetically
             List<String> serviceNames = new ArrayList<>(validServiceNames);
             Collections.sort(serviceNames);
@@ -192,6 +193,36 @@ public class SimpleDescriptorHandler {
                 fw.write("    </service>\n");
             }
 
+            // Applications
+            List<SimpleDescriptor.Application> apps = desc.getApplications();
+            if (apps != null) {
+                for (SimpleDescriptor.Application app : apps) {
+                    fw.write("    <application>\n");
+                    fw.write("        <name>" + app.getName() + "</name>\n");
+
+                    // URLs
+                    List<String> urls = app.getURLs();
+                    if (urls != null) {
+                        for (String url : urls) {
+                            fw.write("        <url>" + url + "</url>\n");
+                        }
+                    }
+
+                    // Params
+                    Map<String, String> appParams = app.getParams();
+                    if (appParams != null) {
+                        for (String paramName : appParams.keySet()) {
+                            fw.write("        <param>\n");
+                            fw.write("            <name>" + paramName + "</name>\n");
+                            fw.write("            <value>" + appParams.get(paramName) + "</value>\n");
+                            fw.write("        </param>\n");
+                        }
+                    }
+
+                    fw.write("    </application>\n");
+                }
+            }
+
             fw.write("</topology>\n");
 
             fw.flush();

http://git-wip-us.apache.org/repos/asf/knox/blob/a068eb8d/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorImpl.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorImpl.java
index bb430a1..7de38a8 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorImpl.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorImpl.java
@@ -46,6 +46,9 @@ class SimpleDescriptorImpl implements SimpleDescriptor {
     @JsonProperty("services")
     private List<ServiceImpl> services;
 
+    @JsonProperty("applications")
+    private List<ApplicationImpl> applications;
+
     private String name = null;
 
     void setName(String name) {
@@ -90,7 +93,18 @@ class SimpleDescriptorImpl implements SimpleDescriptor {
     @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;
     }
 
@@ -120,4 +134,30 @@ class SimpleDescriptorImpl implements SimpleDescriptor {
         }
     }
 
+    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/a068eb8d/gateway-server/src/test/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorFactoryTest.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorFactoryTest.java b/gateway-server/src/test/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorFactoryTest.java
index 2ba8758..129ff7c 100644
--- a/gateway-server/src/test/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorFactoryTest.java
+++ b/gateway-server/src/test/java/org/apache/hadoop/gateway/topology/simple/SimpleDescriptorFactoryTest.java
@@ -27,13 +27,57 @@ 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";
 
@@ -42,20 +86,27 @@ public class SimpleDescriptorFactoryTest {
         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
                 }
@@ -63,8 +114,7 @@ public class SimpleDescriptorFactoryTest {
         }
     }
 
-    @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";
@@ -99,25 +149,24 @@ public class SimpleDescriptorFactoryTest {
         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
                 }
@@ -125,34 +174,59 @@ public class SimpleDescriptorFactoryTest {
         }
     }
 
-    @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
                 }
@@ -160,13 +234,11 @@ public class SimpleDescriptorFactoryTest {
         }
     }
 
-
-    @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";
 
@@ -175,7 +247,7 @@ public class SimpleDescriptorFactoryTest {
         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"));
@@ -197,18 +269,51 @@ public class SimpleDescriptorFactoryTest {
         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
                 }
@@ -216,82 +321,103 @@ public class SimpleDescriptorFactoryTest {
         }
     }
 
-
-    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,
@@ -299,7 +425,9 @@ public class SimpleDescriptorFactoryTest {
                            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);
@@ -308,50 +436,20 @@ public class SimpleDescriptorFactoryTest {
         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();
@@ -359,17 +457,52 @@ public class SimpleDescriptorFactoryTest {
         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,
@@ -378,7 +511,10 @@ public class SimpleDescriptorFactoryTest {
                            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);
@@ -388,14 +524,33 @@ public class SimpleDescriptorFactoryTest {
         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");
@@ -404,7 +559,7 @@ public class SimpleDescriptorFactoryTest {
             }
 
             // 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) {
@@ -412,11 +567,115 @@ public class SimpleDescriptorFactoryTest {
                 }
             }
         }
-        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));
+                        }
+                    }
+                }
+            }
+        }
+    }
 
 }