ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From yus...@apache.org
Subject [12/12] git commit: AMBARI-5482. Integrate Ambari Shell. (Janos Matyas and Krisztian Horvath via yusaku)
Date Sat, 31 May 2014 07:21:16 GMT
AMBARI-5482. Integrate Ambari Shell. (Janos Matyas and Krisztian Horvath via yusaku)


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

Branch: refs/heads/trunk
Commit: 11dd9df85b0470a283feb2d2cde75a5a46927e86
Parents: c6402f5
Author: Yusaku Sako <yusaku@hortonworks.com>
Authored: Sat May 31 07:02:19 2014 +0000
Committer: Yusaku Sako <yusaku@hortonworks.com>
Committed: Sat May 31 07:02:19 2014 +0000

----------------------------------------------------------------------
 ambari-client/assemblies/client.xml             |  20 +
 ambari-client/groovy-client/pom.xml             | 113 +++
 .../ambari/groovy/client/AmbariClient.groovy    | 510 +++++++++++
 .../client/AmbariConnectionException.groovy     |  27 +
 .../ambari/groovy/client/DoNotDeleteMe.java     |  26 +
 .../resources/blueprints/multi-node-hdfs-yarn   |  57 ++
 .../resources/blueprints/single-node-hdfs-yarn  |  48 +
 .../AmbariClientTest.groovy                     | 425 +++++++++
 .../apache/ambari/groovy/client/NeitherMe.java  |  27 +
 .../src/test/resources/blueprint.json           |  48 +
 .../src/test/resources/blueprints.json          |  21 +
 .../src/test/resources/cluster.json             |  16 +
 .../test/resources/hdfsServiceComponents.json   |  63 ++
 .../src/test/resources/services.json            |  14 +
 .../groovy-client/src/test/resources/tasks.json | 471 ++++++++++
 ambari-client/pom.xml                           | 151 +---
 ambari-client/python-client/pom.xml             | 195 ++++
 .../python-client/src/examples/create.py        | 147 +++
 .../python-client/src/examples/delete.py        |  66 ++
 .../python-client/src/examples/example.py       | 133 +++
 .../python-client/src/examples/main.py          | 166 ++++
 .../python-client/src/examples/trial.py         | 145 +++
 .../src/main/python/ambari_client/__init__.py   |  16 +
 .../src/main/python/ambari_client/ambari_api.py | 185 ++++
 .../main/python/ambari_client/core/__init__.py  |  16 +
 .../main/python/ambari_client/core/coreutils.py |  16 +
 .../main/python/ambari_client/core/errors.py    |  78 ++
 .../python/ambari_client/core/http_client.py    | 175 ++++
 .../python/ambari_client/core/http_utils.py     |  52 ++
 .../python/ambari_client/core/rest_resource.py  | 120 +++
 .../main/python/ambari_client/model/__init__.py |  16 +
 .../python/ambari_client/model/base_model.py    | 109 +++
 .../main/python/ambari_client/model/cluster.py  | 331 +++++++
 .../python/ambari_client/model/component.py     |  97 ++
 .../python/ambari_client/model/configuration.py | 138 +++
 .../src/main/python/ambari_client/model/host.py | 255 ++++++
 .../main/python/ambari_client/model/paths.py    |  50 +
 .../main/python/ambari_client/model/service.py  | 203 +++++
 .../main/python/ambari_client/model/stack.py    |  79 ++
 .../main/python/ambari_client/model/status.py   |  71 ++
 .../main/python/ambari_client/model/utils.py    | 231 +++++
 .../python/ambari_client/resources/__init__.py  |  16 +
 .../python/ambari_client/resources/clusters.py  |  58 ++
 .../python/ambari_client/resources/hosts.py     | 127 +++
 .../python/ambari_client/resources/stacks.py    |  41 +
 .../python-client/src/main/python/setup.py      |  39 +
 .../python-client/src/packages/tarball/all.xml  |  34 +
 .../src/test/python/TestAmbariClient.py         | 211 +++++
 .../src/test/python/TestClusterModel.py         | 428 +++++++++
 .../src/test/python/TestComponentModel.py       |  54 ++
 .../src/test/python/TestHostModel.py            |  80 ++
 .../src/test/python/TestServiceModel.py         | 105 +++
 .../src/test/python/TestStatusModel.py          |  82 ++
 .../json/ambariclient_bootstrap_hosts.json      |   5 +
 .../json/ambariclient_get_all_clusters.json     |  12 +
 .../python/json/ambariclient_get_all_hosts.json |  77 ++
 .../json/ambariclient_get_components.json       |  53 ++
 .../python/json/ambariclient_get_config.json    | 905 +++++++++++++++++++
 .../test/python/json/ambariclient_get_host.json |  63 ++
 .../json/clustermodel_error_deleting_host.json  |   4 +
 .../python/json/clustermodel_get_all_hosts.json | 375 ++++++++
 .../json/clustermodel_get_all_services.json     | 120 +++
 .../python/json/clustermodel_get_cluster.json   | 103 +++
 .../json/clustermodel_get_core_site_config.json |  32 +
 .../json/clustermodel_get_global_config.json    |  64 ++
 .../json/clustermodel_get_hdfs_site_config.json |  53 ++
 .../test/python/json/clustermodel_get_host.json | 250 +++++
 .../clustermodel_get_mapred_site_config.json    |  58 ++
 .../python/json/clustermodel_get_service.json   |  29 +
 .../python/json/componentmodel_get_metrics.json | 133 +++
 .../test/python/json/get_cluster_service.json   |  27 +
 .../python/json/get_components_from_stack.json  |  41 +
 .../test/python/json/get_host_component.json    |  41 +
 .../test/python/json/get_host_components.json   |  60 ++
 .../test/python/json/get_service_component.json | 108 +++
 .../python/json/get_service_components.json     | 133 +++
 .../json/hostmodel_get_host_component.json      | 181 ++++
 .../json/hostmodel_get_host_components.json     | 222 +++++
 .../python/json/servicemodel_get_component.json |  20 +
 .../json/servicemodel_get_components.json       |  61 ++
 .../python/json/status_error_with_message.json  |   4 +
 .../src/test/python/json/status_ok_with_id.json |   7 +
 .../python-client/src/test/python/unitTests.py  | 119 +++
 .../src/test/python/utils/HttpClientInvoker.py  | 153 ++++
 ambari-client/src/examples/create.py            | 147 ---
 ambari-client/src/examples/delete.py            |  66 --
 ambari-client/src/examples/example.py           | 133 ---
 ambari-client/src/examples/main.py              | 166 ----
 ambari-client/src/examples/trial.py             | 145 ---
 .../src/main/python/ambari_client/__init__.py   |  16 -
 .../src/main/python/ambari_client/ambari_api.py | 185 ----
 .../main/python/ambari_client/core/__init__.py  |  16 -
 .../main/python/ambari_client/core/coreutils.py |  16 -
 .../main/python/ambari_client/core/errors.py    |  78 --
 .../python/ambari_client/core/http_client.py    | 175 ----
 .../python/ambari_client/core/http_utils.py     |  52 --
 .../python/ambari_client/core/rest_resource.py  | 120 ---
 .../main/python/ambari_client/model/__init__.py |  16 -
 .../python/ambari_client/model/base_model.py    | 109 ---
 .../main/python/ambari_client/model/cluster.py  | 331 -------
 .../python/ambari_client/model/component.py     |  97 --
 .../python/ambari_client/model/configuration.py | 138 ---
 .../src/main/python/ambari_client/model/host.py | 255 ------
 .../main/python/ambari_client/model/paths.py    |  50 -
 .../main/python/ambari_client/model/service.py  | 203 -----
 .../main/python/ambari_client/model/stack.py    |  79 --
 .../main/python/ambari_client/model/status.py   |  71 --
 .../main/python/ambari_client/model/utils.py    | 231 -----
 .../python/ambari_client/resources/__init__.py  |  16 -
 .../python/ambari_client/resources/clusters.py  |  58 --
 .../python/ambari_client/resources/hosts.py     | 127 ---
 .../python/ambari_client/resources/stacks.py    |  41 -
 ambari-client/src/main/python/setup.py          |  39 -
 ambari-client/src/packages/tarball/all.xml      |  34 -
 .../src/test/python/TestAmbariClient.py         | 211 -----
 .../src/test/python/TestClusterModel.py         | 428 ---------
 .../src/test/python/TestComponentModel.py       |  54 --
 ambari-client/src/test/python/TestHostModel.py  |  80 --
 .../src/test/python/TestServiceModel.py         | 105 ---
 .../src/test/python/TestStatusModel.py          |  82 --
 .../json/ambariclient_bootstrap_hosts.json      |   5 -
 .../json/ambariclient_get_all_clusters.json     |  12 -
 .../python/json/ambariclient_get_all_hosts.json |  77 --
 .../json/ambariclient_get_components.json       |  53 --
 .../python/json/ambariclient_get_config.json    | 905 -------------------
 .../test/python/json/ambariclient_get_host.json |  63 --
 .../json/clustermodel_error_deleting_host.json  |   4 -
 .../python/json/clustermodel_get_all_hosts.json | 375 --------
 .../json/clustermodel_get_all_services.json     | 120 ---
 .../python/json/clustermodel_get_cluster.json   | 103 ---
 .../json/clustermodel_get_core_site_config.json |  32 -
 .../json/clustermodel_get_global_config.json    |  64 --
 .../json/clustermodel_get_hdfs_site_config.json |  53 --
 .../test/python/json/clustermodel_get_host.json | 250 -----
 .../clustermodel_get_mapred_site_config.json    |  58 --
 .../python/json/clustermodel_get_service.json   |  29 -
 .../python/json/componentmodel_get_metrics.json | 133 ---
 .../test/python/json/get_cluster_service.json   |  27 -
 .../python/json/get_components_from_stack.json  |  41 -
 .../test/python/json/get_host_component.json    |  41 -
 .../test/python/json/get_host_components.json   |  60 --
 .../test/python/json/get_service_component.json | 108 ---
 .../python/json/get_service_components.json     | 133 ---
 .../json/hostmodel_get_host_component.json      | 181 ----
 .../json/hostmodel_get_host_components.json     | 222 -----
 .../python/json/servicemodel_get_component.json |  20 -
 .../json/servicemodel_get_components.json       |  61 --
 .../python/json/status_error_with_message.json  |   4 -
 .../src/test/python/json/status_ok_with_id.json |   7 -
 ambari-client/src/test/python/unitTests.py      | 119 ---
 .../src/test/python/utils/HttpClientInvoker.py  | 153 ----
 ambari-project/pom.xml                          |  72 +-
 ambari-shell/pom.xml                            | 120 +++
 .../org/apache/ambari/shell/AmbariShell.java    | 110 +++
 .../ambari/shell/commands/BasicCommands.java    | 173 ++++
 .../shell/commands/BlueprintCommands.java       | 184 ++++
 .../ambari/shell/commands/ClusterCommands.java  | 260 ++++++
 .../ambari/shell/commands/ElephantCommand.java  |  53 ++
 .../ambari/shell/commands/HostCommands.java     | 117 +++
 .../configuration/ConverterConfiguration.java   | 125 +++
 .../shell/configuration/ShellConfiguration.java | 102 +++
 .../shell/customization/AmbariBanner.java       |  50 +
 .../shell/customization/AmbariPrompt.java       |  43 +
 .../ambari/shell/model/AmbariContext.java       | 159 ++++
 .../org/apache/ambari/shell/model/Focus.java    |  53 ++
 .../apache/ambari/shell/model/FocusType.java    |  55 ++
 .../org/apache/ambari/shell/model/Hints.java    |  59 ++
 .../ambari/shell/support/TableRenderer.java     | 121 +++
 ambari-shell/src/main/resources/elephant.txt    |   8 +
 .../shell/commands/BlueprintCommandsTest.java   | 115 +++
 .../shell/commands/ClusterCommandsTest.java     | 246 +++++
 .../ambari/shell/commands/HostCommandsTest.java |  65 ++
 .../shell/customization/AmbariPromptTest.java   |  54 ++
 .../ambari/shell/model/AmbariContextTest.java   |  66 ++
 .../ambari/shell/support/TableRendererTest.java |  54 ++
 ambari-shell/src/test/resources/2columns        |   5 +
 ambari-shell/src/test/resources/3columns        |   5 +
 .../src/test/resources/testBlueprint.json       |  48 +
 pom.xml                                         |   2 +
 179 files changed, 12282 insertions(+), 7840 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/assemblies/client.xml
----------------------------------------------------------------------
diff --git a/ambari-client/assemblies/client.xml b/ambari-client/assemblies/client.xml
new file mode 100644
index 0000000..20670cd
--- /dev/null
+++ b/ambari-client/assemblies/client.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<assembly>
+</assembly>

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/pom.xml b/ambari-client/groovy-client/pom.xml
new file mode 100644
index 0000000..ed34848
--- /dev/null
+++ b/ambari-client/groovy-client/pom.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<!-- Licensed 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.
+  See accompanying LICENSE file. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>ambari-client</artifactId>
+    <groupId>org.apache.ambari</groupId>
+    <version>1.3.0-SNAPSHOT</version>
+    <relativePath>../../ambari-client/</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.ambari</groupId>
+  <artifactId>groovy-client</artifactId>
+  <packaging>jar</packaging>
+  <version>1.3.0-SNAPSHOT</version>
+  <name>Ambari Groovy Client</name>
+  <description>Ambari Groovy client</description>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy</groupId>
+      <artifactId>groovy-all</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy.modules.http-builder</groupId>
+      <artifactId>http-builder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.spockframework</groupId>
+      <artifactId>spock-core</artifactId>
+      <version>0.7-groovy-2.0</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <!-- 2.8.0-01 and later require maven-compiler-plugin 3.1 or higher -->
+        <version>3.1</version>
+        <configuration>
+          <compilerId>groovy-eclipse-compiler</compilerId>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-eclipse-compiler</artifactId>
+            <version>2.8.0-01</version>
+          </dependency>
+          <!-- for 2.8.0-01 and later you must have an explicit dependency on
+            groovy-eclipse-batch -->
+          <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-eclipse-batch</artifactId>
+            <version>2.1.8-01</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>src/main/resources/blueprints/multi-node-hdfs-yarn</exclude>
+            <exclude>src/main/resources/blueprints/single-node-hdfs-yarn</exclude>
+            <exclude>src/test/resources/blueprint.json</exclude>
+            <exclude>src/test/resources/blueprints.json</exclude>
+            <exclude>src/test/resources/cluster.json</exclude>
+            <exclude>src/test/resources/hdfsServiceComponents.json</exclude>
+            <exclude>src/test/resources/services.json</exclude>
+            <exclude>src/test/resources/tasks.json</exclude>
+          </excludes>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>test</phase>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <skipAssembly>true</skipAssembly>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariClient.groovy
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariClient.groovy b/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariClient.groovy
new file mode 100644
index 0000000..5b05c60
--- /dev/null
+++ b/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariClient.groovy
@@ -0,0 +1,510 @@
+/**
+ * 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.ambari.groovy.client
+
+import groovy.json.JsonBuilder
+import groovy.json.JsonSlurper
+import groovyx.net.http.HttpResponseException
+import groovyx.net.http.RESTClient
+import org.apache.http.NoHttpResponseException
+import org.apache.http.client.ClientProtocolException
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+/**
+ * Basic client to send requests to the Ambari server.
+ */
+class AmbariClient {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariClient.class)
+  private static final int PAD = 30
+  private static final int OK_RESPONSE = 200
+  boolean debugEnabled = false;
+  def RESTClient ambari
+  def slurper = new JsonSlurper()
+  def clusterName
+
+  /**
+   * Connects to the ambari server.
+   *
+   * @param host host of the Ambari server; default value is localhost
+   * @param port port of the Ambari server; default value is 8080
+   * @param user username of the Ambari server; default is admin
+   * @param password password fom the Ambari server; default is admin
+   */
+  AmbariClient(host = 'localhost', port = '8080', user = 'admin', password = 'admin') {
+    ambari = new RESTClient("http://${host}:${port}/api/v1/" as String)
+    ambari.headers['Authorization'] = 'Basic ' + "$user:$password".getBytes('iso-8859-1').encodeBase64()
+    ambari.headers['X-Requested-By'] = 'ambari'
+  }
+
+  /**
+   * Connects to the ambari server.
+   *
+   * @param restClient underlying client
+   * @param slurper slurper to parse responses
+   */
+  AmbariClient(RESTClient restClient, JsonSlurper slurper) {
+    this.ambari = restClient
+    this.slurper = slurper
+  }
+
+  /**
+   * Sets the debug variable. Used by printing the API calls for the Ambari Shell.
+   *
+   * @param enabled enable or disable
+   */
+  def setDebugEnabled(boolean enabled) {
+    debugEnabled = enabled;
+  }
+
+  /**
+   * Returns the name of the cluster.
+   *
+   * @return the name of the cluster of null if no cluster yet
+   */
+  def String getClusterName() {
+    if (!clusterName) {
+      def clusters = getClusters();
+      if (clusters) {
+        clusterName = clusters.items[0]?.Clusters?.cluster_name
+      }
+    }
+    return clusterName
+  }
+
+  /**
+   * Checks whether the blueprint exists or not.
+   *
+   * @param id id of the blueprint
+   * @return true if exists false otherwise
+   */
+  def boolean doesBlueprintExists(String id) {
+    def result = false
+    try {
+      result = ambari.get(path: "blueprints/$id", query: ['fields': "Blueprints"]).status == OK_RESPONSE
+    } catch (e) {
+      LOGGER.info("Blueprint does not exist", e)
+    }
+    return result
+  }
+
+  /**
+   * Checks whether there are available blueprints or not.
+   *
+   * @return true if blueprints are available false otherwise
+   */
+  def boolean isBlueprintAvailable() {
+    return getBlueprints().items?.size > 0
+  }
+
+  /**
+   * Returns a pre-formatted String of the blueprint.
+   *
+   * @param id id of the blueprint
+   * @return formatted String
+   */
+  def String showBlueprint(String id) {
+    def resp = getBlueprint(id)
+    if (resp) {
+      def groups = resp.host_groups.collect {
+        def name = it.name
+        def comps = it.components.collect { it.name.padRight(PAD).padLeft(PAD + 10) }.join("\n")
+        return "HOSTGROUP: $name\n$comps"
+      }.join("\n")
+      return "[${resp.Blueprints.stack_name}:${resp.Blueprints.stack_version}]\n$groups"
+    }
+    return "Not found"
+  }
+
+  /**
+   * Returns the host group - components mapping of the blueprint.
+   *
+   * @param id id of the blueprint
+   * @return Map where the key is the host group and the value is the list of components
+   */
+  def Map<String, List<String>> getBlueprintMap(String id) {
+    def result = getBlueprint(id).host_groups?.collectEntries { [(it.name): it.components.collect { it.name }] }
+    result ?: new HashMap()
+  }
+
+  /**
+   * Returns a pre-formatted String of the blueprints.
+   *
+   * @return formatted blueprint list
+   */
+  def String showBlueprints() {
+    getBlueprints().items.collect { "${it.Blueprints.blueprint_name.padRight(PAD)} [${it.Blueprints.stack_name}:${it.Blueprints.stack_version}]" }.join("\n")
+  }
+
+  /**
+   * Returns a Map containing the blueprint name - stack association.
+   *
+   * @return Map where the key is the blueprint's name value is the used stack
+   */
+  def Map<String, String> getBlueprintsMap() {
+    def result = getBlueprints().items?.collectEntries { [(it.Blueprints.blueprint_name): it.Blueprints.stack_name + ":" + it.Blueprints.stack_version] }
+    result ?: new HashMap()
+  }
+
+  /**
+   * Returns the name of the host groups for a given blueprint.
+   *
+   * @param blueprint id of the blueprint
+   * @return host group list or empty list
+   */
+  def List<String> getHostGroups(String blueprint) {
+    def result = getBlueprint(blueprint)
+    result ? result.host_groups.collect { it.name } : new ArrayList<String>()
+  }
+
+  /**
+   * Returns a pre-formatted String of a blueprint used by the cluster.
+   *
+   * @return formatted String
+   */
+  def String showClusterBlueprint() {
+    ambari.get(path: "clusters/${getClusterName()}", query: ['format': "blueprint"]).data.text
+  }
+
+  /**
+   * Adds a blueprint to the Ambari server. Exception is thrown if fails.
+   *
+   * @param json blueprint as json
+   * @throws HttpResponseException in case of error
+   */
+  def void addBlueprint(String json) throws HttpResponseException {
+    if (json) {
+      postBlueprint(json)
+    }
+  }
+
+  /**
+   * Adds 2 default blueprints.
+   *
+   * @throws HttpResponseException in case of error
+   */
+  def void addDefaultBlueprints() throws HttpResponseException {
+    addBlueprint(getResourceContent("blueprints/multi-node-hdfs-yarn"))
+    addBlueprint(getResourceContent("blueprints/single-node-hdfs-yarn"))
+  }
+
+  /**
+   * Creates a cluster with the given blueprint and host group - host association.
+   *
+   * @param clusterName name of the cluster
+   * @param blueprintName blueprint id used to create this cluster
+   * @param hostGroups Map<String, List<String> key - host group, value - host list
+   * @return true if the creation was successful false otherwise
+   * @throws HttpResponseException in case of error
+   */
+  def void createCluster(String clusterName, String blueprintName, Map<String, List<String>> hostGroups) throws HttpResponseException {
+    ambari.post(path: "clusters/$clusterName", body: createClusterJson(blueprintName, hostGroups), { it })
+  }
+
+  /**
+   * Deletes the cluster.
+   *
+   * @param clusterName name of the cluster
+   * @throws HttpResponseException in case of error
+   */
+  def void deleteCluster(String clusterName) throws HttpResponseException {
+    ambari.delete(path: "clusters/$clusterName")
+  }
+
+  /**
+   * Returns the active cluster as json
+   *
+   * @return cluster as json String
+   * @throws HttpResponseException in case of error
+   */
+  def String getClusterAsJson() throws HttpResponseException {
+    getRequest("clusters/${getClusterName()}")
+  }
+
+  /**
+   * Returns all clusters as json
+   *
+   * @return json String
+   * @throws HttpResponseException in case of error
+   */
+  def getClustersAsJson() throws HttpResponseException {
+    getRequest("clusters")
+  }
+
+  /**
+   * Returns a pre-formatted String of the clusters.
+   *
+   * @return pre-formatted cluster list
+   */
+  def String showClusterList() {
+    getClusters().items.collect { "[$it.Clusters.cluster_id] $it.Clusters.cluster_name:$it.Clusters.version" }.join("\n")
+  }
+
+  /**
+   * Returns the task properties as Map.
+   *
+   * @param request request id; default is 1
+   * @return property Map or empty Map
+   */
+  def getTasks(request = 1) {
+    getAllResources("requests/$request", "tasks/Tasks")
+  }
+
+  /**
+   * Returns a pre-formatted task list.
+   *
+   * @param request request id; default is 1
+   * @return pre-formatted task list
+   */
+  def String showTaskList(request = 1) {
+    getTasks(request)?.tasks.collect { "${it.Tasks.command_detail.padRight(PAD)} [${it.Tasks.status}]" }.join("\n")
+  }
+
+  /**
+   * Returns a Map containing the task's command detail as key and the task's status as value.
+   *
+   * @param request request id; default is 1
+   * @return key task command detail; task value status
+   */
+  def Map<String, String> getTaskMap(request = 1) {
+    def result = getTasks(request).tasks?.collectEntries { [(it.Tasks.command_detail): it.Tasks.status] }
+    result ?: new HashMap()
+  }
+
+  /**
+   * Returns the available host names and its states.
+   *
+   * @return hostname state association
+   */
+  def Map<String, String> getHostNames() {
+    getHosts().items.collectEntries { [(it.Hosts.host_name): it.Hosts.host_status] }
+  }
+
+  /**
+   * Returns a pre-formatted list of the hosts.
+   *
+   * @return pre-formatted String
+   */
+  def String showHostList() {
+    getHosts().items.collect { "$it.Hosts.host_name [$it.Hosts.host_status] $it.Hosts.ip $it.Hosts.os_type:$it.Hosts.os_arch" }.join("\n")
+  }
+
+  /**
+   * Returns a pre-formatted list of the service components.
+   *
+   * @return pre-formatted String
+   */
+  def String showServiceComponents() {
+    getServices().items.collect {
+      def name = it.ServiceInfo.service_name
+      def state = it.ServiceInfo.state
+      def componentList = getServiceComponents(name).items.collect {
+        "    ${it.ServiceComponentInfo.component_name.padRight(PAD)}  [$it.ServiceComponentInfo.state]"
+      }.join("\n")
+      "${name.padRight(PAD)} [$state]\n$componentList"
+    }.join("\n")
+  }
+
+  /**
+   * Returns the service components properties as Map where the key is the service name and
+   * value is a component - state association.
+   *
+   * @return service name - [component name - status]
+   */
+  def Map<String, Map<String, String>> getServiceComponentsMap() {
+    def result = getServices().items.collectEntries {
+      def name = it.ServiceInfo.service_name
+      def componentList = getServiceComponents(name).items.collectEntries { [(it.ServiceComponentInfo.component_name): it.ServiceComponentInfo.state] }
+      [(name): componentList]
+    }
+    result ?: new HashMap()
+  }
+
+  /**
+   * Returns a pre-formatted service list.
+   *
+   * @return formatted String
+   */
+  def String showServiceList() {
+    getServices().items.collect { "${it.ServiceInfo.service_name.padRight(PAD)} [$it.ServiceInfo.state]" }.join("\n")
+  }
+
+  /**
+   * Returns the services properties as Map where the key is the service's name and the values is the service's state.
+   *
+   * @return service name - service state association as Map
+   */
+  def Map<String, String> getServicesMap() {
+    def result = getServices().items.collectEntries { [(it.ServiceInfo.service_name): it.ServiceInfo.state] }
+    result ?: new HashMap()
+  }
+
+  /**
+   * Returns a pre-formatted component list of a host.
+   *
+   * @param host which host's components are requested
+   * @return formatted String
+   */
+  def String showHostComponentList(host) {
+    getHostComponents(host).items.collect { "${it.HostRoles.component_name.padRight(PAD)} [$it.HostRoles.state]" }.join("\n")
+  }
+
+  /**
+   * Returns the host's components as Map where the key is the component's name and values is its state.
+   *
+   * @param host which host's components are requested
+   * @return component name - state association
+   */
+  def Map<String, String> getHostComponentsMap(host) {
+    def result = getHostComponents(host).items?.collectEntries { [(it.HostRoles.component_name): it.HostRoles.state] }
+    result ?: new HashMap()
+  }
+
+  /**
+   * Returns the blueprint json as String.
+   *
+   * @param id id of the blueprint
+   * @return json as String, exception if thrown is it fails
+   */
+  def String getBlueprintAsJson(id) {
+    return getRequest("blueprints/$id", "host_groups,Blueprints")
+  }
+
+  private def getAllResources(resourceName, fields) {
+    slurp("clusters/${getClusterName()}/$resourceName", "$fields/*")
+  }
+
+  /**
+   * Posts the blueprint JSON to Ambari with name 'bp' in the URL
+   * because it does not matter here. The blueprint's name is
+   * provided in the JSON.
+   *
+   * @param blueprint json
+   * @return response message
+   */
+  private void postBlueprint(String blueprint) {
+    ambari.post(path: "blueprints/bp", body: blueprint, { it })
+  }
+
+  private def createClusterJson(String name, Map hostGroups) {
+    def builder = new JsonBuilder()
+    def groups = hostGroups.collect {
+      def hostList = it.value.collect { ['fqdn': it] }
+      [name: it.key, hosts: hostList]
+    }
+    builder { "blueprint" name; "host-groups" groups }
+    builder.toPrettyString()
+  }
+
+  private def slurp(path, fields = "") {
+    def baseUri = ambari.getUri();
+    if (debugEnabled) {
+      println "[DEBUG] ${baseUri}${path}?fields=$fields"
+    }
+    def result = new HashMap()
+    try {
+      result = slurper.parseText(getRequest(path, fields))
+    } catch (e) {
+      if (e instanceof NoHttpResponseException || e instanceof ConnectException || e instanceof ClientProtocolException ||
+        e instanceof UnknownHostException || (e instanceof HttpResponseException && e.message == "Bad credentials")) {
+        throw new AmbariConnectionException("Cannot connect to Ambari $baseUri")
+      }
+      LOGGER.error("Error occurred during GET request to $baseUri/$path", e)
+    }
+    return result
+  }
+
+  /**
+   * Return the blueprint's properties as a Map.
+   *
+   * @param id id of the blueprint
+   * @return properties as Map
+   */
+  private def getBlueprint(id) {
+    slurp("blueprints/$id", "host_groups,Blueprints")
+  }
+
+  /**
+   * Returns a Map containing the blueprint's properties parsed from the Ambari response json.
+   *
+   * @return blueprint's properties as Map or empty Map
+   */
+  private def getBlueprints() {
+    slurp("blueprints", "Blueprints")
+  }
+
+  /**
+   * Returns a Map containing the cluster's properties parsed from the Ambari response json.
+   *
+   * @return cluster's properties as Map or empty Map
+   */
+  private def getClusters() {
+    slurp("clusters", "Clusters")
+  }
+
+  /**
+   * Returns the available hosts properties as a Map.
+   *
+   * @return Map containing the hosts properties
+   */
+  private def getHosts() {
+    slurp("hosts", "Hosts")
+  }
+
+  /**
+   * Returns the service components properties as Map.
+   *
+   * @param service id of the service
+   * @return service component properties as Map
+   */
+  private def getServiceComponents(service) {
+    getAllResources("services/$service/components", "ServiceComponentInfo")
+  }
+
+  /**
+   * Returns the services properties as Map parsed from Ambari response json.
+   *
+   * @return service properties as Map
+   */
+  private def getServices() {
+    getAllResources("services", "ServiceInfo")
+  }
+
+  /**
+   * Returns the properties of the host components as a Map parsed from the Ambari response json.
+   *
+   * @param host which host's components are requested
+   * @return component properties as Map
+   */
+  private def getHostComponents(host) {
+    getAllResources("hosts/$host/host_components", "HostRoles")
+  }
+
+  private String getRequest(path, fields = "") {
+    if (fields) {
+      ambari.get(path: "$path", query: ['fields': "$fields"]).data.text
+    } else {
+      ambari.get(path: "$path").data.text
+    }
+  }
+
+  private String getResourceContent(name) {
+    getClass().getClassLoader().getResourceAsStream(name)?.text
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariConnectionException.groovy
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariConnectionException.groovy b/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariConnectionException.groovy
new file mode 100644
index 0000000..f88223c
--- /dev/null
+++ b/ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariConnectionException.groovy
@@ -0,0 +1,27 @@
+/**
+ * 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.ambari.groovy.client
+
+/**
+ * Exception used to indicate that there are connection issues.
+ */
+class AmbariConnectionException extends RuntimeException {
+  public AmbariConnectionException(String s) {
+    super(s)
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/main/java/org/apache/ambari/groovy/client/DoNotDeleteMe.java
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/main/java/org/apache/ambari/groovy/client/DoNotDeleteMe.java b/ambari-client/groovy-client/src/main/java/org/apache/ambari/groovy/client/DoNotDeleteMe.java
new file mode 100644
index 0000000..6b2ec19
--- /dev/null
+++ b/ambari-client/groovy-client/src/main/java/org/apache/ambari/groovy/client/DoNotDeleteMe.java
@@ -0,0 +1,26 @@
+/**
+ * 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.ambari.groovy.client;
+
+/**
+ * The maven plugin will only compile the groovy classes into the jar
+ * if it contains at least one java class, otherwise it will tell you that
+ * there are no source classes found.
+ */
+public class DoNotDeleteMe {
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/main/resources/blueprints/multi-node-hdfs-yarn
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/main/resources/blueprints/multi-node-hdfs-yarn b/ambari-client/groovy-client/src/main/resources/blueprints/multi-node-hdfs-yarn
new file mode 100644
index 0000000..0630453
--- /dev/null
+++ b/ambari-client/groovy-client/src/main/resources/blueprints/multi-node-hdfs-yarn
@@ -0,0 +1,57 @@
+{
+  "host_groups" : [
+    {
+      "name" : "master",
+      "components" : [
+      {
+        "name" : "NAMENODE"
+      },
+      {
+        "name" : "SECONDARY_NAMENODE"
+      },       
+      {
+        "name" : "RESOURCEMANAGER"
+      },
+      {
+        "name" : "HISTORYSERVER"
+      },
+      {
+        "name" : "NAGIOS_SERVER"
+      },
+      {
+        "name" : "ZOOKEEPER_SERVER"
+      }
+      ],
+      "cardinality" : "1"
+    },
+    {
+      "name" : "slaves",
+      "components" : [
+      {
+        "name" : "DATANODE"
+      },
+      {
+        "name" : "HDFS_CLIENT"
+      },
+      {
+        "name" : "NODEMANAGER"
+      },
+      {
+        "name" : "YARN_CLIENT"
+      },
+      {
+        "name" : "MAPREDUCE2_CLIENT"
+      },
+      {
+        "name" : "ZOOKEEPER_CLIENT"
+      }
+      ],
+      "cardinality" : "2"
+    }
+  ],
+  "Blueprints" : {
+    "blueprint_name" : "multi-node-hdfs-yarn",
+    "stack_name" : "HDP",
+    "stack_version" : "2.0"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/main/resources/blueprints/single-node-hdfs-yarn
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/main/resources/blueprints/single-node-hdfs-yarn b/ambari-client/groovy-client/src/main/resources/blueprints/single-node-hdfs-yarn
new file mode 100644
index 0000000..1a7d302
--- /dev/null
+++ b/ambari-client/groovy-client/src/main/resources/blueprints/single-node-hdfs-yarn
@@ -0,0 +1,48 @@
+{
+  "host_groups" : [
+    {
+      "name" : "host_group_1",
+      "components" : [
+      {
+        "name" : "NAMENODE"
+      },
+      {
+        "name" : "SECONDARY_NAMENODE"
+      },       
+      {
+        "name" : "DATANODE"
+      },
+      {
+        "name" : "HDFS_CLIENT"
+      },
+      {
+        "name" : "RESOURCEMANAGER"
+      },
+      {
+        "name" : "NODEMANAGER"
+      },
+      {
+        "name" : "YARN_CLIENT"
+      },
+      {
+        "name" : "HISTORYSERVER"
+      },
+      {
+        "name" : "MAPREDUCE2_CLIENT"
+      },
+      {
+        "name" : "ZOOKEEPER_SERVER"
+      },
+      {
+        "name" : "ZOOKEEPER_CLIENT"
+      }
+      ],
+      "cardinality" : "1"
+    }
+  ],
+  "Blueprints" : {
+    "blueprint_name" : "single-node-hdfs-yarn",
+    "stack_name" : "HDP",
+    "stack_version" : "2.0"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/groovy/com.sequenceiq.ambari.client/AmbariClientTest.groovy
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/groovy/com.sequenceiq.ambari.client/AmbariClientTest.groovy b/ambari-client/groovy-client/src/test/groovy/com.sequenceiq.ambari.client/AmbariClientTest.groovy
new file mode 100644
index 0000000..77ad26a
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/groovy/com.sequenceiq.ambari.client/AmbariClientTest.groovy
@@ -0,0 +1,425 @@
+/**
+ * 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.ambari.groovy.client
+
+import groovy.json.JsonSlurper
+import groovyx.net.http.HttpResponseDecorator
+import groovyx.net.http.HttpResponseException
+import groovyx.net.http.RESTClient
+import spock.lang.Specification
+
+class AmbariClientTest extends Specification {
+
+  def rest = Mock(RESTClient)
+  def slurper = Mock(JsonSlurper)
+  def decorator = Mock(HttpResponseDecorator)
+  def ambari = new AmbariClient(rest, slurper)
+  def realSlurper = new JsonSlurper()
+
+  def "test get the name of the cluster"() {
+    given:
+    def request = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+
+    when:
+    def result = ambari.getClusterName()
+
+    then:
+    "cluster1" == result
+  }
+
+  def "test get the name when there is no cluster"() {
+    given:
+    def request = [path: "clusters", query: [fields: "Clusters"]]
+    def mockResponse = ["items": new ArrayList()]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+
+    when:
+    def result = ambari.getClusterName()
+
+    then:
+    null == result
+  }
+
+  def "test if blueprint does not exists"() {
+    given:
+    decorator.status >> 500
+    def request = [path: "blueprints/bp", query: ['fields': "Blueprints"]]
+    rest.get(request) >> decorator
+
+    when:
+    def result = ambari.doesBlueprintExists("bp")
+
+    then:
+    result == false
+  }
+
+  def "test if blueprint exists"() {
+    given:
+    decorator.status >> 200
+    def request = [path: "blueprints/bp", query: ['fields': "Blueprints"]]
+    rest.get(request) >> decorator
+
+    when:
+    def result = ambari.doesBlueprintExists("bp")
+
+    then:
+    result == true
+  }
+
+  def "test get blueprint as map"() {
+    given:
+    def request = [path: "blueprints/bp", query: [fields: "host_groups,Blueprints"]]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    def mockResponse = [host_groups: [[name: "bp", components: [[name: "hdfs"], [name: "yarn"]]]]]
+    slurper.parseText("map") >> mockResponse
+
+    when:
+    def response = ambari.getBlueprintMap("bp")
+
+    then:
+    [bp: ["hdfs", "yarn"]] == response
+  }
+
+  def "test get blueprint as map for empty result"() {
+    given:
+    def request = [path: "blueprints/bp", query: [fields: "host_groups,Blueprints"]]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> [:]
+
+    when:
+    def response = ambari.getBlueprintMap("bp")
+
+    then:
+    [:] == response
+  }
+
+  def "test get host groups"() {
+    given:
+    def request = [path: "blueprints/bp", query: [fields: "host_groups,Blueprints"]]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> [host_groups: [[name: "group1"], [name: "group2"]]]
+
+    when:
+    def result = ambari.getHostGroups("bp")
+
+    then:
+    ["group1", "group2"] == result
+  }
+
+  def "test get host groups for no groups"() {
+    given:
+    def request = [path: "blueprints/bp", query: [fields: "host_groups,Blueprints"]]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> null
+
+    when:
+    def result = ambari.getHostGroups("bp")
+
+    then:
+    [] == result
+  }
+
+  def "test get host names"() {
+    given:
+    def request = [path: "hosts", query: [fields: "Hosts"]]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    def hosts = [[Hosts: [host_name: "server.ambari.com", host_status: "HEALTHY"]]]
+    def mapResponse = [items: hosts]
+    slurper.parseText("map") >> mapResponse
+
+    when:
+    def result = ambari.getHostNames()
+
+    then:
+    "HEALTHY" == result["server.ambari.com"]
+    1 == result.size()
+  }
+
+  def "test get host names for empty result"() {
+    given:
+    def request = [path: "hosts", query: [fields: "Hosts"]]
+    rest.get(request) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> []
+
+    when:
+    def result = ambari.getHostNames()
+
+    then:
+    [:] == result
+  }
+
+  def "test add blueprint for success"() {
+    given:
+    def json = getClass().getResourceAsStream("blueprint.json")
+    def request = [path: "blueprints/bp", body: json]
+    rest.post(request, { it })
+
+    when:
+    ambari.addBlueprint(json)
+
+    then:
+    notThrown(HttpResponseException)
+  }
+
+  def "test add blueprint for empty json"() {
+    given:
+    def request = [path: "blueprints/bp", body: ""]
+    rest.post(request, { it })
+
+    when:
+    ambari.addBlueprint("")
+
+    then:
+    notThrown(HttpResponseException)
+  }
+
+  def "test create cluster json"() {
+    given:
+    def json = getClass().getResourceAsStream("/cluster.json").text
+    def groups = [host_group_1: ["server.ambari.com", "server2.ambari.com"]]
+    def request = [path: "clusters/c1", body: json]
+
+    when:
+    ambari.createCluster("c1", "c1", groups)
+
+    then:
+    1 * rest.post(request, { it })
+  }
+
+  def "test get task as map"() {
+    given:
+    //get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the actual tasks
+    def req2 = [path: "clusters/cluster1/requests/1", query: ['fields': "tasks/Tasks/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "map2"]
+    def json = realSlurper.parseText(getClass().getResourceAsStream("/tasks.json").text)
+    slurper.parseText("map2") >> json
+
+    when:
+    def result = ambari.getTaskMap()
+
+    then:
+    ["DATANODE INSTALL"          : "COMPLETED",
+     "DATANODE START"            : "COMPLETED",
+     "HDFS_CLIENT INSTALL"       : "COMPLETED",
+     "HISTORYSERVER INSTALL"     : "COMPLETED",
+     "HISTORYSERVER START"       : "COMPLETED",
+     "MAPREDUCE2_CLIENT INSTALL" : "COMPLETED",
+     "NAMENODE INSTALL"          : "COMPLETED",
+     "NAMENODE START"            : "COMPLETED",
+     "NODEMANAGER INSTALL"       : "COMPLETED",
+     "NODEMANAGER START"         : "COMPLETED",
+     "RESOURCEMANAGER INSTALL"   : "COMPLETED",
+     "RESOURCEMANAGER START"     : "COMPLETED",
+     "SECONDARY_NAMENODE INSTALL": "COMPLETED",
+     "SECONDARY_NAMENODE START"  : "COMPLETED",
+     "YARN_CLIENT INSTALL"       : "COMPLETED",
+     "ZOOKEEPER_CLIENT INSTALL"  : "COMPLETED",
+     "ZOOKEEPER_SERVER INSTALL"  : "COMPLETED",
+     "ZOOKEEPER_SERVER START"    : "COMPLETED"
+    ] == result
+  }
+
+  def "test get task as map for no task"() {
+    given:
+    //get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the actual tasks
+    def req2 = [path: "clusters/cluster1/requests/1", query: ['fields': "tasks/Tasks/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "map2"]
+    slurper.parseText("map2") >> [:]
+
+    when:
+    def result = ambari.getTaskMap()
+
+    then:
+    [:] == result
+  }
+
+  def "test get service components map"() {
+    given:
+    // get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the services
+    def req2 = [path: "clusters/cluster1/services", query: ['fields': "ServiceInfo/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "dec"]
+    def json = realSlurper.parseText(getClass().getResourceAsStream("/services.json").text)
+    slurper.parseText("dec") >> json
+    // get service components
+    def req3 = [path: "clusters/cluster1/services/HDFS/components", query: ['fields': "ServiceComponentInfo/*"]]
+    def decorator3 = Mock(HttpResponseDecorator)
+    rest.get(req3) >> decorator3
+    decorator3.data >> [text: "dec3"]
+    def json2 = realSlurper.parseText(getClass().getResourceAsStream("/hdfsServiceComponents.json").text)
+    slurper.parseText("dec3") >> json2
+
+    when:
+    def Map result = ambari.getServiceComponentsMap()
+
+    then:
+    [HDFS: [
+      DATANODE          : "STARTED",
+      HDFS_CLIENT       : "INSTALLED",
+      NAMENODE          : "STARTED",
+      SECONDARY_NAMENODE: "STARTED"]
+    ] == result
+  }
+
+  def "test get service components map for empty services"() {
+    given:
+    // get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the services
+    def req2 = [path: "clusters/cluster1/services", query: ['fields': "ServiceInfo/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "dec"]
+    slurper.parseText("dec") >> []
+
+    when:
+    def Map result = ambari.getServiceComponentsMap()
+
+    then:
+    [:] == result
+  }
+
+  def "test get service components map for empty components"() {
+    given:
+    // get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the services
+    def req2 = [path: "clusters/cluster1/services", query: ['fields': "ServiceInfo/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "dec"]
+    def json = realSlurper.parseText(getClass().getResourceAsStream("/services.json").text)
+    slurper.parseText("dec") >> json
+    // get service components
+    def req3 = [path: "clusters/cluster1/services/HDFS/components", query: ['fields': "ServiceComponentInfo/*"]]
+    def decorator3 = Mock(HttpResponseDecorator)
+    rest.get(req3) >> decorator3
+    decorator3.data >> [text: "dec3"]
+    slurper.parseText("dec3") >> []
+
+    when:
+    def Map result = ambari.getServiceComponentsMap()
+
+    then:
+    [HDFS: [:]] == result
+  }
+
+  def "test get services as map"() {
+    given:
+    // get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the services
+    def req2 = [path: "clusters/cluster1/services", query: ['fields': "ServiceInfo/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "dec"]
+    def json = realSlurper.parseText(getClass().getResourceAsStream("/services.json").text)
+    slurper.parseText("dec") >> json
+
+    when:
+    def result = ambari.getServicesMap()
+
+    then:
+    [HDFS: "STARTED"] == result
+  }
+
+  def "test get services as map for empty result"() {
+    given:
+    // get the name of the cluster
+    def req1 = [path: "clusters", query: [fields: "Clusters"]]
+    def items = new ArrayList()
+    items.add([Clusters: [cluster_name: "cluster1"]])
+    def mockResponse = ["items": items]
+    rest.get(req1) >> decorator
+    decorator.data >> [text: "map"]
+    slurper.parseText("map") >> mockResponse
+    // get the services
+    def req2 = [path: "clusters/cluster1/services", query: ['fields': "ServiceInfo/*"]]
+    def decorator2 = Mock(HttpResponseDecorator)
+    rest.get(req2) >> decorator2
+    decorator2.data >> [text: "dec"]
+    slurper.parseText("dec") >> []
+
+    when:
+    def result = ambari.getServicesMap()
+
+    then:
+    [:] == result
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/java/org/apache/ambari/groovy/client/NeitherMe.java
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/java/org/apache/ambari/groovy/client/NeitherMe.java b/ambari-client/groovy-client/src/test/java/org/apache/ambari/groovy/client/NeitherMe.java
new file mode 100644
index 0000000..18d3579
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/java/org/apache/ambari/groovy/client/NeitherMe.java
@@ -0,0 +1,27 @@
+/**
+ * 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.ambari.groovy.client;
+
+/**
+ * The maven plugin will only run the tests if it contains
+ * at least one java class.
+ *
+ * @see org.apache.ambari.groovy.client.DoNotDeleteMe
+ */
+public class NeitherMe {
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/resources/blueprint.json
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/resources/blueprint.json b/ambari-client/groovy-client/src/test/resources/blueprint.json
new file mode 100644
index 0000000..1a7d302
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/resources/blueprint.json
@@ -0,0 +1,48 @@
+{
+  "host_groups" : [
+    {
+      "name" : "host_group_1",
+      "components" : [
+      {
+        "name" : "NAMENODE"
+      },
+      {
+        "name" : "SECONDARY_NAMENODE"
+      },       
+      {
+        "name" : "DATANODE"
+      },
+      {
+        "name" : "HDFS_CLIENT"
+      },
+      {
+        "name" : "RESOURCEMANAGER"
+      },
+      {
+        "name" : "NODEMANAGER"
+      },
+      {
+        "name" : "YARN_CLIENT"
+      },
+      {
+        "name" : "HISTORYSERVER"
+      },
+      {
+        "name" : "MAPREDUCE2_CLIENT"
+      },
+      {
+        "name" : "ZOOKEEPER_SERVER"
+      },
+      {
+        "name" : "ZOOKEEPER_CLIENT"
+      }
+      ],
+      "cardinality" : "1"
+    }
+  ],
+  "Blueprints" : {
+    "blueprint_name" : "single-node-hdfs-yarn",
+    "stack_name" : "HDP",
+    "stack_version" : "2.0"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/resources/blueprints.json
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/resources/blueprints.json b/ambari-client/groovy-client/src/test/resources/blueprints.json
new file mode 100644
index 0000000..208a954
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/resources/blueprints.json
@@ -0,0 +1,21 @@
+{
+  "href" : "http://localhost:49233/api/v1/blueprints?fields=Blueprints",
+  "items" : [
+    {
+      "href" : "http://localhost:49233/api/v1/blueprints/multi-node-hdfs-yarn",
+      "Blueprints" : {
+        "blueprint_name" : "multi-node-hdfs-yarn",
+        "stack_name" : "HDP",
+        "stack_version" : "2.0"
+      }
+    },
+    {
+      "href" : "http://localhost:49233/api/v1/blueprints/single-node-hdfs-yarn",
+      "Blueprints" : {
+        "blueprint_name" : "single-node-hdfs-yarn",
+        "stack_name" : "HDP",
+        "stack_version" : "2.0"
+      }
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/resources/cluster.json
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/resources/cluster.json b/ambari-client/groovy-client/src/test/resources/cluster.json
new file mode 100644
index 0000000..886a960
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/resources/cluster.json
@@ -0,0 +1,16 @@
+{
+    "blueprint": "c1",
+    "host-groups": [
+        {
+            "name": "host_group_1",
+            "hosts": [
+                {
+                    "fqdn": "server.ambari.com"
+                },
+                {
+                    "fqdn": "server2.ambari.com"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/resources/hdfsServiceComponents.json
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/resources/hdfsServiceComponents.json b/ambari-client/groovy-client/src/test/resources/hdfsServiceComponents.json
new file mode 100644
index 0000000..b4f8e50
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/resources/hdfsServiceComponents.json
@@ -0,0 +1,63 @@
+{
+  "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services/HDFS/components?fields=ServiceComponentInfo/*",
+  "items" : [
+    {
+      "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services/HDFS/components/DATANODE",
+      "ServiceComponentInfo" : {
+        "category" : "SLAVE",
+        "cluster_name" : "single-node-hdfs-yarn",
+        "component_name" : "DATANODE",
+        "service_name" : "HDFS",
+        "state" : "STARTED"
+      }
+    },
+    {
+      "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services/HDFS/components/HDFS_CLIENT",
+      "ServiceComponentInfo" : {
+        "category" : "CLIENT",
+        "cluster_name" : "single-node-hdfs-yarn",
+        "component_name" : "HDFS_CLIENT",
+        "service_name" : "HDFS",
+        "state" : "INSTALLED"
+      }
+    },
+    {
+      "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services/HDFS/components/NAMENODE",
+      "ServiceComponentInfo" : {
+        "CapacityRemaining" : 31924920320,
+        "CapacityTotal" : 39078707200,
+        "CapacityUsed" : 24576,
+        "DeadNodes" : "{}",
+        "DecomNodes" : "{}",
+        "HeapMemoryMax" : 1052770304,
+        "HeapMemoryUsed" : 100962448,
+        "LiveNodes" : "{\"server.ambari.com\":{\"infoAddr\":\"172.17.0.2:50075\",\"infoSecureAddr\":\"172.17.0.2:0\",\"xferaddr\":\"172.17.0.2:50010\",\"lastContact\":0,\"usedSpace\":24576,\"adminState\":\"In Service\",\"nonDfsUsedSpace\":7153762304,\"capacity\":39078707200,\"numBlocks\":0,\"version\":\"2.4.0.2.1.1.0-385\",\"used\":24576,\"remaining\":31924920320,\"blockScheduled\":0,\"blockPoolUsed\":24576,\"blockPoolUsedPercent\":6.2888466E-5,\"volfails\":0}}",
+        "NonDfsUsedSpace" : 7153762304,
+        "NonHeapMemoryMax" : 136314880,
+        "NonHeapMemoryUsed" : 33860904,
+        "PercentRemaining" : 81.6939,
+        "PercentUsed" : 6.2888466E-5,
+        "Safemode" : "",
+        "StartTime" : 1400572832732,
+        "TotalFiles" : 10,
+        "UpgradeFinalized" : true,
+        "Version" : "2.4.0.2.1.1.0-385, r68ceccf06a4441273e81a5ec856d41fc7e11c792",
+        "category" : "MASTER",
+        "cluster_name" : "single-node-hdfs-yarn",
+        "component_name" : "NAMENODE",
+        "service_name" : "HDFS",
+        "state" : "STARTED"
+      }
+    },
+    {
+      "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services/HDFS/components/SECONDARY_NAMENODE",
+      "ServiceComponentInfo" : {
+        "category" : "MASTER",
+        "cluster_name" : "single-node-hdfs-yarn",
+        "component_name" : "SECONDARY_NAMENODE",
+        "service_name" : "HDFS",
+        "state" : "STARTED"
+      }
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11dd9df8/ambari-client/groovy-client/src/test/resources/services.json
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/src/test/resources/services.json b/ambari-client/groovy-client/src/test/resources/services.json
new file mode 100644
index 0000000..aceed13
--- /dev/null
+++ b/ambari-client/groovy-client/src/test/resources/services.json
@@ -0,0 +1,14 @@
+{
+  "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services?fields=ServiceInfo/*",
+  "items" : [
+    {
+      "href" : "http://localhost:49271/api/v1/clusters/single-node-hdfs-yarn/services/HDFS",
+      "ServiceInfo" : {
+        "cluster_name" : "single-node-hdfs-yarn",
+        "maintenance_state" : "OFF",
+        "service_name" : "HDFS",
+        "state" : "STARTED"
+      }
+    }
+  ]
+}
\ No newline at end of file


Mime
View raw message