You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2014/07/28 22:03:01 UTC
[10/10] git commit: Move jclouds-chef to the main jclouds repo
Move jclouds-chef to the main jclouds repo
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/867c7a40
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/867c7a40
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/867c7a40
Branch: refs/heads/master
Commit: 867c7a407c1db8f56ff3211d70481755cf71440f
Parents: eba727f
Author: Ignasi Barrera <na...@apache.org>
Authored: Mon Jul 28 17:34:30 2014 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Jul 28 21:08:54 2014 +0200
----------------------------------------------------------------------
apis/chef/pom.xml | 131 +++
apis/chef/src/main/clojure/org/jclouds/chef.clj | 261 ++++++
.../src/main/java/org/jclouds/chef/ChefApi.java | 853 +++++++++++++++++++
.../java/org/jclouds/chef/ChefApiMetadata.java | 110 +++
.../main/java/org/jclouds/chef/ChefContext.java | 37 +
.../main/java/org/jclouds/chef/ChefService.java | 263 ++++++
.../binders/BindChecksumsToJsonPayload.java | 54 ++
.../BindCreateClientOptionsToJsonPayload.java | 71 ++
.../BindGenerateKeyForClientToJsonPayload.java | 35 +
.../org/jclouds/chef/binders/DatabagItemId.java | 32 +
.../jclouds/chef/binders/EnvironmentName.java | 31 +
.../java/org/jclouds/chef/binders/NodeName.java | 32 +
.../java/org/jclouds/chef/binders/RoleName.java | 32 +
.../chef/config/BaseChefHttpApiModule.java | 208 +++++
.../chef/config/ChefBootstrapModule.java | 121 +++
.../jclouds/chef/config/ChefHttpApiModule.java | 28 +
.../jclouds/chef/config/ChefParserModule.java | 321 +++++++
.../org/jclouds/chef/config/ChefProperties.java | 110 +++
.../org/jclouds/chef/config/CookbookParser.java | 41 +
.../chef/config/CookbookVersionsParser.java | 41 +
.../org/jclouds/chef/config/InstallChef.java | 37 +
.../java/org/jclouds/chef/config/Validator.java | 40 +
.../java/org/jclouds/chef/domain/Attribute.java | 235 +++++
.../jclouds/chef/domain/BootstrapConfig.java | 95 +++
.../org/jclouds/chef/domain/ChecksumStatus.java | 102 +++
.../java/org/jclouds/chef/domain/Client.java | 182 ++++
.../jclouds/chef/domain/CookbookDefinition.java | 217 +++++
.../jclouds/chef/domain/CookbookVersion.java | 369 ++++++++
.../org/jclouds/chef/domain/DatabagItem.java | 63 ++
.../org/jclouds/chef/domain/Environment.java | 178 ++++
.../java/org/jclouds/chef/domain/Metadata.java | 447 ++++++++++
.../main/java/org/jclouds/chef/domain/Node.java | 263 ++++++
.../java/org/jclouds/chef/domain/Resource.java | 169 ++++
.../main/java/org/jclouds/chef/domain/Role.java | 205 +++++
.../java/org/jclouds/chef/domain/Sandbox.java | 195 +++++
.../org/jclouds/chef/domain/SearchResult.java | 46 +
.../org/jclouds/chef/domain/UploadSandbox.java | 136 +++
.../jclouds/chef/filters/SignedHeaderAuth.java | 200 +++++
.../chef/functions/BootstrapConfigForGroup.java | 61 ++
.../jclouds/chef/functions/ClientForGroup.java | 69 ++
.../chef/functions/GroupToBootScript.java | 130 +++
...seCookbookDefinitionCheckingChefVersion.java | 49 ++
.../ParseCookbookDefinitionFromJson.java | 50 ++
.../ParseCookbookDefinitionFromJsonv10.java | 52 ++
.../ParseCookbookDefinitionListFromJsonv10.java | 63 ++
...arseCookbookVersionsCheckingChefVersion.java | 49 ++
.../ParseCookbookVersionsV09FromJson.java | 49 ++
.../ParseCookbookVersionsV10FromJson.java | 59 ++
.../ParseErrorFromJsonOrReturnBody.java | 55 ++
.../chef/functions/ParseKeySetFromJson.java | 45 +
.../functions/ParseSearchClientsFromJson.java | 35 +
.../functions/ParseSearchDatabagFromJson.java | 77 ++
.../ParseSearchEnvironmentsFromJson.java | 35 +
.../functions/ParseSearchNodesFromJson.java | 35 +
.../functions/ParseSearchResultFromJson.java | 50 ++
.../functions/ParseSearchRolesFromJson.java | 35 +
.../jclouds/chef/functions/RunListForGroup.java | 61 ++
.../jclouds/chef/functions/UriForResource.java | 42 +
.../chef/handlers/ChefApiErrorRetryHandler.java | 67 ++
.../jclouds/chef/handlers/ChefErrorHandler.java | 81 ++
.../jclouds/chef/internal/BaseChefService.java | 299 +++++++
.../jclouds/chef/internal/ChefContextImpl.java | 55 ++
.../chef/options/CreateClientOptions.java | 64 ++
.../org/jclouds/chef/options/SearchOptions.java | 95 +++
.../predicates/CookbookVersionPredicates.java | 93 ++
.../strategy/CleanupStaleNodesAndClients.java | 32 +
...reateNodeAndPopulateAutomaticAttributes.java | 33 +
.../chef/strategy/DeleteAllClientsInList.java | 34 +
.../chef/strategy/DeleteAllNodesInList.java | 31 +
.../org/jclouds/chef/strategy/ListClients.java | 32 +
.../chef/strategy/ListCookbookVersions.java | 32 +
.../ListCookbookVersionsInEnvironment.java | 37 +
.../jclouds/chef/strategy/ListEnvironments.java | 31 +
.../org/jclouds/chef/strategy/ListNodes.java | 32 +
.../chef/strategy/ListNodesInEnvironment.java | 32 +
.../UpdateAutomaticAttributesOnNode.java | 31 +
.../internal/BaseListCookbookVersionsImpl.java | 97 +++
.../strategy/internal/BaseListNodesImpl.java | 77 ++
.../CleanupStaleNodesAndClientsImpl.java | 102 +++
...eNodeAndPopulateAutomaticAttributesImpl.java | 83 ++
.../internal/DeleteAllClientsInListImpl.java | 85 ++
.../internal/DeleteAllNodesInListImpl.java | 81 ++
.../chef/strategy/internal/ListClientsImpl.java | 109 +++
.../internal/ListCookbookVersionsImpl.java | 60 ++
.../ListCookbookVersionsInEnvironmentImpl.java | 117 +++
.../strategy/internal/ListEnvironmentsImpl.java | 96 +++
.../chef/strategy/internal/ListNodesImpl.java | 62 ++
.../internal/ListNodesInEnvironmentImpl.java | 62 ++
.../UpdateAutomaticAttributesOnNodeImpl.java | 75 ++
.../chef/suppliers/ChefVersionSupplier.java | 73 ++
.../org/jclouds/chef/test/TransientChefApi.java | 387 +++++++++
.../chef/test/TransientChefApiMetadata.java | 75 ++
.../test/config/TransientChefApiModule.java | 116 +++
.../java/org/jclouds/chef/util/ChefUtils.java | 71 ++
.../org/jclouds/chef/util/CollectionUtils.java | 69 ++
.../org/jclouds/chef/util/RunListBuilder.java | 83 ++
.../main/java/org/jclouds/ohai/Automatic.java | 33 +
.../org/jclouds/ohai/AutomaticSupplier.java | 48 ++
.../org/jclouds/ohai/config/ConfiguresOhai.java | 28 +
.../org/jclouds/ohai/config/JMXOhaiModule.java | 48 ++
.../org/jclouds/ohai/config/OhaiModule.java | 183 ++++
.../ohai/functions/ByteArrayToMacAddress.java | 51 ++
.../ohai/functions/MapSetToMultimap.java | 42 +
.../jclouds/ohai/functions/NestSlashKeys.java | 156 ++++
.../ohai/suppliers/UptimeSecondsSupplier.java | 44 +
.../services/org.jclouds.apis.ApiMetadata | 2 +
.../src/test/clojure/org/jclouds/chef_test.clj | 70 ++
.../org/jclouds/chef/BaseChefApiExpectTest.java | 44 +
.../org/jclouds/chef/ChefApiExpectTest.java | 279 ++++++
.../java/org/jclouds/chef/ChefApiLiveTest.java | 32 +
.../org/jclouds/chef/ChefApiMetadataTest.java | 33 +
.../test/java/org/jclouds/chef/ChefApiTest.java | 741 ++++++++++++++++
.../BindHexEncodedMD5sToJsonPayloadTest.java | 70 ++
.../chef/config/ChefParserModuleTest.java | 93 ++
.../chef/filters/SignedHeaderAuthTest.java | 213 +++++
.../functions/BootstrapConfigForGroupTest.java | 74 ++
.../chef/functions/ClientForGroupTest.java | 106 +++
.../chef/functions/GroupToBootScriptTest.java | 230 +++++
.../chef/functions/ParseClientFromJsonTest.java | 98 +++
...okbookDefinitionCheckingChefVersionTest.java | 62 ++
.../ParseCookbookDefinitionFromJsonTest.java | 72 ++
.../ParseCookbookDefinitionFromJsonv10Test.java | 74 ++
...seCookbookDefinitionListFromJsonv10Test.java | 92 ++
.../ParseCookbookVersionFromJsonTest.java | 129 +++
...CookbookVersionsCheckingChefVersionTest.java | 62 ++
.../ParseCookbookVersionsV09FromJsonTest.java | 61 ++
.../ParseCookbookVersionsV10FromJsonTest.java | 68 ++
.../functions/ParseDataBagItemFromJsonTest.java | 65 ++
.../ParseErrorFromJsonOrReturnBodyTest.java | 42 +
.../chef/functions/ParseKeySetFromJsonTest.java | 66 ++
.../chef/functions/ParseNodeFromJsonTest.java | 73 ++
.../functions/ParseSandboxFromJsonTest.java | 71 ++
.../ParseSearchDataBagItemFromJsonTest.java | 62 ++
.../ParseUploadSandboxFromJsonTest.java | 87 ++
.../chef/functions/RunListForGroupTest.java | 92 ++
.../chef/functions/UriForResourceTest.java | 54 ++
.../handlers/ChefApiErrorRetryHandlerTest.java | 115 +++
.../chef/internal/BaseChefApiLiveTest.java | 542 ++++++++++++
.../jclouds/chef/internal/BaseChefLiveTest.java | 96 +++
.../chef/internal/BaseChefServiceTest.java | 99 +++
.../chef/internal/BaseStubbedOhaiLiveTest.java | 60 ++
...CleanupStaleNodesAndClientsImplLiveTest.java | 61 ++
...PopulateAutomaticAttributesImplLiveTest.java | 62 ++
...eAndPopulateAutomaticAttributesImplTest.java | 61 ++
...DeleteAllApisAndNodesInListImplLiveTest.java | 64 ++
...okbookVersionsInEnvironmentImplLiveTest.java | 217 +++++
.../internal/ListNodesImplLiveTest.java | 82 ++
.../ListNodesInEnvironmentImplLiveTest.java | 86 ++
...teAutomaticAttributesOnNodeImplLiveTest.java | 61 ++
...UpdateAutomaticAttributesOnNodeImplTest.java | 63 ++
.../chef/suppliers/ChefVersionSupplierTest.java | 47 +
.../test/TransientChefApiIntegrationTest.java | 69 ++
.../chef/test/TransientChefApiMetadataTest.java | 33 +
.../org/jclouds/chef/util/ChefUtilsTest.java | 57 ++
.../jclouds/chef/util/RunListBuilderTest.java | 71 ++
.../java/org/jclouds/ohai/config/JMXTest.java | 82 ++
.../org/jclouds/ohai/config/OhaiModuleTest.java | 147 ++++
.../functions/ByteArrayToMacAddressTest.java | 33 +
.../ohai/functions/NestSlashKeysTest.java | 117 +++
.../resources/apache-chef-demo-cookbook.json | 46 +
apis/chef/src/test/resources/bootstrap-env.sh | 56 ++
apis/chef/src/test/resources/bootstrap.sh | 56 ++
apis/chef/src/test/resources/brew-cookbook.json | 48 ++
apis/chef/src/test/resources/client.json | 8 +
apis/chef/src/test/resources/clients_list.json | 5 +
apis/chef/src/test/resources/data_list.json | 4 +
apis/chef/src/test/resources/env_cookbooks.json | 20 +
.../src/test/resources/environment_recipes.json | 6 +
.../chef/src/test/resources/mysql-cookbook.json | 268 ++++++
apis/chef/src/test/resources/node.json | 10 +
apis/chef/src/test/resources/nodes_list.json | 5 +
apis/chef/src/test/resources/privkey.txt | 27 +
apis/chef/src/test/resources/pubkey.txt | 9 +
apis/chef/src/test/resources/roles_list.json | 4 +
apis/chef/src/test/resources/sandbox.json | 12 +
apis/chef/src/test/resources/search_role.json | 34 +
.../src/test/resources/search_role_empty.json | 5 +
.../src/test/resources/tomcat-cookbook.json | 121 +++
apis/chef/src/test/resources/upload-site.json | 13 +
apis/pom.xml | 1 +
project/pom.xml | 2 +
providers/enterprise-chef/pom.xml | 110 +++
.../enterprisechef/EnterpriseChefApi.java | 124 +++
.../EnterpriseChefApiMetadata.java | 82 ++
.../EnterpriseChefProviderMetadata.java | 86 ++
.../BindGroupToUpdateRequestJsonPayload.java | 79 ++
.../enterprisechef/binders/GroupName.java | 38 +
.../config/EnterpriseChefHttpApiModule.java | 36 +
.../jclouds/enterprisechef/domain/Group.java | 211 +++++
.../org/jclouds/enterprisechef/domain/User.java | 220 +++++
.../org.jclouds.providers.ProviderMetadata | 1 +
.../EnterpriseChefApiExpectTest.java | 209 +++++
.../EnterpriseChefApiLiveTest.java | 122 +++
.../EnterpriseChefProviderMetadataTest.java | 31 +
...BindGroupToUpdateRequestJsonPayloadTest.java | 82 ++
.../enterprisechef/binders/GroupNameTest.java | 40 +
.../src/test/resources/group-update.json | 1 +
.../src/test/resources/group.json | 14 +
.../src/test/resources/groups.json | 7 +
.../src/test/resources/user.json | 9 +
providers/pom.xml | 1 +
201 files changed, 18721 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/pom.xml
----------------------------------------------------------------------
diff --git a/apis/chef/pom.xml b/apis/chef/pom.xml
new file mode 100644
index 0000000..6d0d889
--- /dev/null
+++ b/apis/chef/pom.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-project</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <relativePath>../../project/pom.xml</relativePath>
+ </parent>
+ <groupId>org.apache.jclouds.api</groupId>
+ <artifactId>chef</artifactId>
+ <packaging>bundle</packaging>
+ <name>jclouds Chef api</name>
+ <description>jclouds components to access Chef</description>
+
+ <properties>
+ <test.chef.endpoint>http://localhost:4000</test.chef.endpoint>
+ <test.chef.api-version />
+ <test.chef.build-version />
+ <test.chef.identity>chef-webui</test.chef.identity>
+ <test.chef.credential>${user.home}/.chef/webui.pem</test.chef.credential>
+ <jclouds.osgi.import>org.jclouds*;version=${project.version},*</jclouds.osgi.import>
+ <jclouds.osgi.export>
+ org.jclouds.chef*;version=${project.version};-noimport:=true,
+ org.jclouds.ohai*;version=${project.version};-noimport:=true,
+ </jclouds.osgi.export>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-scriptbuilder</artifactId>
+ <version>${project.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-scriptbuilder</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <!-- for ohai -->
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-multibindings</artifactId>
+ <version>3.0</version>
+ </dependency>
+ <!-- for transient chef provider -->
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-blobstore</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.driver</groupId>
+ <artifactId>jclouds-slf4j</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>live</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>integration</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <systemPropertyVariables>
+ <test.chef.endpoint>${test.chef.endpoint}</test.chef.endpoint>
+ <test.chef.api-version>${test.chef.api-version}</test.chef.api-version>
+ <test.chef.build-version>${test.chef.build-version}</test.chef.build-version>
+ <test.chef.identity>${test.chef.identity}</test.chef.identity>
+ <test.chef.credential>${test.chef.credential}</test.chef.credential>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/clojure/org/jclouds/chef.clj
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/clojure/org/jclouds/chef.clj b/apis/chef/src/main/clojure/org/jclouds/chef.clj
new file mode 100644
index 0000000..ad0f200
--- /dev/null
+++ b/apis/chef/src/main/clojure/org/jclouds/chef.clj
@@ -0,0 +1,261 @@
+;
+; 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.
+;
+
+(ns
+ #^{:author "Adrian Cole"
+ :doc "A clojure binding to the jclouds chef interface.
+
+Here's a quick example of how to manipulate a databag on the Opscode Platform,
+which is basically Chef Server as a Service.
+
+(use 'org.jclouds.chef)
+
+(def client \"YOUR_CLIENT\")
+;; load the rsa key from ~/.chef/CLIENT_NAME.pem
+(def credential (load-pem client))
+
+;; create a connection to the opscode platform
+(def chef (chef-service \"chef\" client credential :chef.endpoint \"https://api.opscode.com/organizations/YOUR_ORG\"))
+
+(with-chef-service [chef]
+ (create-databag \"cluster-config\")
+ (update-databag-item \"cluster-config\" {:id \"master\" :name \"myhost.com\"}))
+
+;; note that you can create your chef connection like this to do in-memory testing
+(def chef (chef-service \"transientchef\" \"\" \"\"))
+
+See http://code.google.com/p/jclouds for details."}
+ org.jclouds.chef
+ (:use [org.jclouds.core])
+ (:require (org.danlarkin [json :as json]))
+ (:import
+ java.util.Properties
+ [org.jclouds ContextBuilder]
+ [org.jclouds.chef ChefClient
+ ChefService ChefContext]
+ [org.jclouds.chef.domain DatabagItem]))
+(try
+ (use '[clojure.contrib.reflect :only [get-field]])
+ (catch Exception e
+ (use '[clojure.contrib.java-utils
+ :only [wall-hack-field]
+ :rename {wall-hack-field get-field}])))
+
+(defn load-pem
+ "get the pem associated with the supplied identity"
+ ([#^String identity]
+ (slurp (str (. System getProperty "user.home") "/.chef/" identity ".pem"))))
+
+;; TODO find a way to pass the chef provider by default
+
+(defn chef-service
+ "Create a logged in context to a chef server.
+
+provider \"chef\" is a remote connection, and you can pass the option
+ :chef.endpoint \"https://url\" to override the endpoint
+
+provider \"transientchef\" is for in-memory when you are looking to do
+unit testing"
+ ([#^String provider #^String identity #^String credential & options]
+ (let [module-keys (set (keys module-lookup))
+ ext-modules (filter #(module-keys %) options)
+ opts (apply hash-map (filter #(not (module-keys %)) options))]
+ (.. (ContextBuilder/newBuilder provider)
+ (credentials provider-identity provider-credential)
+ (modules (apply modules (concat ext-modules (opts :extensions))))
+ (overrides (reduce #(do (.put %1 (name (first %2)) (second %2)) %1)
+ (Properties.) (dissoc opts :extensions)))
+ (build ChefContext)
+ (getChefService)))))
+
+(defn chef-context
+ "Returns a chef context from a chef service."
+ [#^ChefService chef]
+ (.getContext chef))
+
+(defn chef-service?
+ [object]
+ (instance? ChefService object))
+
+(defn chef-context?
+ [object]
+ (instance? ChefContext object))
+
+(defn as-chef-service
+ "Tries hard to produce a chef service from its input arguments"
+ [& args]
+ (cond
+ (chef-service? (first args)) (first args)
+ (chef-context? (first args)) (.getChefService (first args))
+ :else (apply chef-service args)))
+
+(defn as-chef-api
+ "Tries hard to produce a chef client from its input arguments"
+ [& args]
+ (cond
+ (chef-service? (first args)) (.getApi (.getContext (first args)))
+ (chef-context? (first args)) (.getApi (first args))
+ :else (.getApi (.getContext (apply chef-service args)))))
+
+(def *chef*)
+
+(defmacro with-chef-service
+ "Specify the default chef service"
+ [[& chef-or-args] & body]
+ `(binding [*chef* (as-chef-service ~@chef-or-args)]
+ ~@body))
+
+(defn nodes
+ "Retrieve the names of the existing nodes in your chef server."
+ ([] (nodes *chef*))
+ ([#^ChefService chef]
+ (seq (.listNodes (as-chef-api chef)))))
+
+(defn nodes-with-details
+ "Retrieve the existing nodes in your chef server including all details."
+ ([] (nodes *chef*))
+ ([#^ChefService chef]
+ (seq (.listNodes chef))))
+
+(defn clients
+ "Retrieve the names of the existing clients in your chef server."
+ ([] (clients *chef*))
+ ([#^ChefService chef]
+ (seq (.listClients (as-chef-api chef)))))
+
+(defn clients-with-details
+ "Retrieve the existing clients in your chef server including all details."
+ ([] (clients *chef*))
+ ([#^ChefService chef]
+ (seq (.listClients chef))))
+
+(defn cookbooks
+ "Retrieve the names of the existing cookbooks in your chef server."
+ ([] (cookbooks *chef*))
+ ([#^ChefService chef]
+ (seq (.listCookbooks (as-chef-api chef)))))
+
+(defn cookbook-versions
+ "Retrieve the versions of an existing cookbook in your chef server."
+ ([name] (cookbook-versions *chef*))
+ ([#^ChefService name chef]
+ (seq (.getVersionsOfCookbook (as-chef-api chef) name))))
+
+(defn cookbook-versions-with-details
+ "Retrieve the existing cookbook versions in your chef server including all details."
+ ([] (cookbook-versions *chef*))
+ ([#^ChefService chef]
+ (seq (.listCookbookVersions chef))))
+
+(defn update-run-list
+ "Updates the run-list associated with a tag"
+ ([run-list tag] (update-run-list run-list tag *chef*))
+ ([run-list tag #^ChefService chef]
+ (.updateRunListForTag chef run-list tag)))
+
+(defn run-list
+ "Retrieves the run-list associated with a tag"
+ ([tag] (run-list tag *chef*))
+ ([tag #^ChefService chef]
+ (seq (.getRunListForTag chef tag))))
+
+(defn create-bootstrap
+ "creates a client and bootstrap script associated with a tag"
+ ([tag] (create-bootstrap tag *chef*))
+ ([tag #^ChefService chef]
+ (.createClientAndBootstrapScriptForTag chef tag)))
+
+(defn databags
+ "Retrieve the names of the existing data bags in your chef server."
+ ([] (databags *chef*))
+ ([#^ChefService chef]
+ (seq (.listDatabags (as-chef-api chef)))))
+
+(defn databag-exists?
+ "Predicate to check presence of a databag"
+ ([databag-name]
+ (databag-exists? databag-name *chef*))
+ ([databag-name #^ChefService chef]
+ (.databagExists (as-chef-api chef) databag-name)))
+
+(defn delete-databag
+ "Delete a data bag, including its items"
+ ([databag]
+ (delete-databag databag *chef*))
+ ([databag chef]
+ (.deleteDatabag (as-chef-api chef) databag)))
+
+(defn create-databag
+ "create a data bag"
+ ([databag]
+ (create-databag databag *chef*))
+ ([databag chef]
+ (.createDatabag (as-chef-api chef) databag)))
+
+(defn databag-items
+ "Retrieve the names of the existing items in a data bag in your chef server."
+ ([databag]
+ (databag-items databag *chef*))
+ ([databag chef]
+ (seq (.listDatabagItems (as-chef-api chef) databag))))
+
+(defn databag-item-exists?
+ "Predicate to check presence of a databag item"
+ ([databag-name item-id]
+ (databag-item-exists? databag-name item-id *chef*))
+ ([databag-name item-id #^ChefService chef]
+ (.databagExists (as-chef-api chef) databag-name item-id)))
+
+(defn databag-item
+ "Get an item from the data bag"
+ ([databag item-id]
+ (databag-item databag item-id *chef*))
+ ([databag item-id chef]
+ (json/decode-from-str (str (.getDatabagItem (as-chef-api chef) databag item-id)))))
+
+(defn delete-databag-item
+ "delete an item from the data bag"
+ ([databag item-id]
+ (delete-databag-item databag item-id *chef*))
+ ([databag item-id chef]
+ (.deleteDatabagItem (as-chef-api chef) databag item-id)))
+
+(defn create-databag-item
+ "put a new item in the data bag. Note the Map you pass must have an :id key:
+
+ex.
+ (create-databag-item \"cluster-config\" {:id \"master\" :name \"myhost.com\"}))"
+ ([databag value]
+ (create-databag-item databag value *chef*))
+ ([databag value chef]
+ (let [value-str (json/encode-to-str value)]
+ (let [value-json (json/decode-from-str value-str)]
+ (.createDatabagItem (as-chef-api chef) databag
+ (DatabagItem. (get value-json :id) value-str))))))
+
+(defn update-databag-item
+ "updates an existing item in the data bag. Note the Map you pass must have an :id key:
+
+ex.
+ (update-databag-item \"cluster-config\" {:id \"master\" :name \"myhost.com\"}))"
+ ([databag value]
+ (update-databag-item databag value *chef*))
+ ([databag value chef]
+ (let [value-str (json/encode-to-str value)]
+ (let [value-json (json/decode-from-str value-str)]
+ (.updateDatabagItem (as-chef-api chef) databag
+ (DatabagItem. (get value-json :id) value-str))))))
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/ChefApi.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/ChefApi.java b/apis/chef/src/main/java/org/jclouds/chef/ChefApi.java
new file mode 100644
index 0000000..13f4971
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/ChefApi.java
@@ -0,0 +1,853 @@
+/*
+ * 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.jclouds.chef;
+
+import java.io.Closeable;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Constants;
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.chef.binders.BindChecksumsToJsonPayload;
+import org.jclouds.chef.binders.BindCreateClientOptionsToJsonPayload;
+import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
+import org.jclouds.chef.binders.DatabagItemId;
+import org.jclouds.chef.binders.EnvironmentName;
+import org.jclouds.chef.binders.NodeName;
+import org.jclouds.chef.binders.RoleName;
+import org.jclouds.chef.domain.Client;
+import org.jclouds.chef.domain.CookbookDefinition;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.chef.domain.Environment;
+import org.jclouds.chef.domain.Node;
+import org.jclouds.chef.domain.Resource;
+import org.jclouds.chef.domain.Role;
+import org.jclouds.chef.domain.Sandbox;
+import org.jclouds.chef.domain.SearchResult;
+import org.jclouds.chef.domain.UploadSandbox;
+import org.jclouds.chef.filters.SignedHeaderAuth;
+import org.jclouds.chef.functions.ParseCookbookDefinitionCheckingChefVersion;
+import org.jclouds.chef.functions.ParseCookbookDefinitionFromJsonv10;
+import org.jclouds.chef.functions.ParseCookbookDefinitionListFromJsonv10;
+import org.jclouds.chef.functions.ParseCookbookVersionsCheckingChefVersion;
+import org.jclouds.chef.functions.ParseKeySetFromJson;
+import org.jclouds.chef.functions.ParseSearchClientsFromJson;
+import org.jclouds.chef.functions.ParseSearchDatabagFromJson;
+import org.jclouds.chef.functions.ParseSearchEnvironmentsFromJson;
+import org.jclouds.chef.functions.ParseSearchNodesFromJson;
+import org.jclouds.chef.functions.ParseSearchRolesFromJson;
+import org.jclouds.chef.functions.UriForResource;
+import org.jclouds.chef.options.CreateClientOptions;
+import org.jclouds.chef.options.SearchOptions;
+import org.jclouds.io.Payload;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.WrapWith;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ * Provides synchronous access to Chef.
+ */
+@RequestFilters(SignedHeaderAuth.class)
+@Headers(keys = "X-Chef-Version", values = "{" + Constants.PROPERTY_API_VERSION + "}")
+@Consumes(MediaType.APPLICATION_JSON)
+public interface ChefApi extends Closeable {
+
+ // Clients
+
+ /**
+ * Lists the names of the existing clients.
+ *
+ * @return The names of the existing clients.
+ */
+ @Named("client:list")
+ @GET
+ @Path("/clients")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listClients();
+
+ /**
+ * Gets the details of existing client.
+ *
+ * @param clientname The name of the client to get.
+ * @return The details of the given client.
+ */
+ @Named("client:get")
+ @GET
+ @Path("/clients/{clientname}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Client getClient(@PathParam("clientname") String clientName);
+
+ /**
+ * Creates a new client.
+ *
+ * @param clientname The name of the new client
+ * @return The client with the generated private key. This key should be
+ * stored so client can be properly authenticated .
+ */
+ @Named("client:create")
+ @POST
+ @Path("/clients")
+ @MapBinder(BindToJsonPayload.class)
+ Client createClient(@PayloadParam("name") String clientName);
+
+ /**
+ * Creates a new client with custom options.
+ *
+ * @param clientname The name of the new client
+ * @param options The options to customize the client creation.
+ * @return The client with the generated private key. This key should be
+ * stored so client can be properly authenticated .
+ */
+ @Named("client:create")
+ @POST
+ @Path("/clients")
+ @MapBinder(BindCreateClientOptionsToJsonPayload.class)
+ Client createClient(@PayloadParam("name") String clientName, CreateClientOptions options);
+
+ /**
+ * Generates a new key-pair for this client, and return the new private key in
+ * the response body.
+ *
+ * @param clientname The name of the client.
+ * @return The details of the client with the new private key.
+ */
+ @Named("client:generatekey")
+ @PUT
+ @Path("/clients/{clientname}")
+ Client generateKeyForClient(
+ @PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientName);
+
+ /**
+ * Deletes the given client.
+ *
+ * @param clientname The name of the client to delete.
+ * @return The deleted client.
+ */
+ @Named("client:delete")
+ @DELETE
+ @Path("/clients/{clientname}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Client deleteClient(@PathParam("clientname") String clientName);
+
+ // Cookbooks
+
+ /**
+ * Lists the names of the existing cookbooks.
+ *
+ * @return The names of the exsisting cookbooks.
+ */
+ @Named("cookbook:list")
+ @GET
+ @Path("/cookbooks")
+ @ResponseParser(ParseCookbookDefinitionCheckingChefVersion.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listCookbooks();
+
+ /**
+ * Lists the cookbooks that are available in the given environment.
+ *
+ * @param environmentname The name of the environment to get the cookbooks
+ * from.
+ * @return The definitions of the cookbooks (name, URL and versions) available in
+ * the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("cookbook:list")
+ @GET
+ @ResponseParser(ParseCookbookDefinitionListFromJsonv10.class)
+ @Path("/environments/{environmentname}/cookbooks")
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<CookbookDefinition> listCookbooksInEnvironment(@PathParam("environmentname") String environmentName);
+
+ /**
+ * Lists the cookbooks that are available in the given environment, limiting
+ * the number of versions returned for each cookbook.
+ *
+ * @param environmentname The name of the environment to get the cookbooks
+ * from.
+ * @param numversions The number of cookbook versions to include in the
+ * response, where n is the number of cookbook versions.
+ * @return The definitions of the cookbooks (name, URL and versions) available in
+ * the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("cookbook:list")
+ @GET
+ @ResponseParser(ParseCookbookDefinitionListFromJsonv10.class)
+ @Path("/environments/{environmentname}/cookbooks?num_versions={numversions}")
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<CookbookDefinition> listCookbooksInEnvironment(@PathParam("environmentname") String environmentName,
+ @PathParam("numversions") String numVersions);
+
+ /**
+ * Lists the available versions of the given cookbook.
+ *
+ * @param cookbookName The name of the cookbook.
+ * @return The available versions of the given cookbook.
+ */
+ @Named("cookbook:versions")
+ @GET
+ @Path("/cookbooks/{cookbookname}")
+ @ResponseParser(ParseCookbookVersionsCheckingChefVersion.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listVersionsOfCookbook(@PathParam("cookbookname") String cookbookName);
+
+ /**
+ * Gets the details of the given cookbook, with the links to each resource
+ * such as recipe files, attributes, etc.
+ *
+ * @param cookbookName The name of the cookbook.
+ * @param version The version of the cookbook to get.
+ * @return The details of the given cookbook.
+ */
+ @Named("cookbook:get")
+ @GET
+ @Path("/cookbooks/{cookbookname}/{version}")
+ @Fallback(NullOnNotFoundOr404.class)
+ CookbookVersion getCookbook(@PathParam("cookbookname") String cookbookName, @PathParam("version") String version);
+
+ /**
+ * Gets the definition of the cookbook in the given environment.
+ *
+ * @param environmentname The name of the environment.
+ * @param cookbookname The name of the cookbook.
+ * @return The definition of the cookbook (URL and versions) of the cookbook
+ * in the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:cookbook")
+ @GET
+ @ResponseParser(ParseCookbookDefinitionFromJsonv10.class)
+ @Path("/environments/{environmentname}/cookbooks/{cookbookname}")
+ CookbookDefinition getCookbookInEnvironment(@PathParam("environmentname") String environmentName,
+ @PathParam("cookbookname") String cookbookName);
+
+ /**
+ * Gets the definition of the cookbook in the given environment.
+ *
+ * @param environmentname The name of the environment.
+ * @param cookbookname The name of the cookbook.
+ * @param numversions The number of cookbook versions to include in the
+ * response, where n is the number of cookbook versions.
+ * @return The definition of the cookbook (URL and versions) of the cookbook
+ * in the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:cookbook")
+ @GET
+ @ResponseParser(ParseCookbookDefinitionFromJsonv10.class)
+ @Path("/environments/{environmentname}/cookbooks/{cookbookname}?num_versions={numversions}")
+ CookbookDefinition getCookbookInEnvironment(@PathParam("environmentname") String environmentName,
+ @PathParam("cookbookname") String cookbookName, @PathParam("numversions") String numVersions);
+
+ /**
+ * Lists the names of the recipes in the given environment.
+ *
+ * @param environmentname The name of the environment.
+ * @return The names of the recipes in the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:recipelist")
+ @GET
+ @Path("/environments/{environmentname}/recipes")
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listRecipesInEnvironment(@PathParam("environmentname") String environmentName);
+
+ /**
+ * Creates or updates the given cookbook.
+ *
+ * @param cookbookName The name of the cookbook to create or update.
+ * @param version The version of the cookbook to create or update.
+ * @param cookbook The contents of the cookbook to create or update.
+ * @return The details of the created or updated cookbook.
+ */
+ @Named("cookbook:update")
+ @PUT
+ @Path("/cookbooks/{cookbookname}/{version}")
+ CookbookVersion updateCookbook(@PathParam("cookbookname") String cookbookName, @PathParam("version") String version,
+ @BinderParam(BindToJsonPayload.class) CookbookVersion cookbook);
+
+ /**
+ * Deletes the given cookbook.
+ *
+ * @param cookbookName The name of the cookbook to delete.
+ * @param version The version of the cookbook to delete.
+ * @return The details of the deleted cookbook.
+ */
+ @Named("cookbook:delete")
+ @DELETE
+ @Path("/cookbooks/{cookbookname}/{version}")
+ @Fallback(NullOnNotFoundOr404.class)
+ CookbookVersion deleteCookbook(@PathParam("cookbookname") String cookbookName, @PathParam("version") String version);
+
+ // Data bags
+
+ /**
+ * Lists the names of the existing data bags.
+ *
+ * @return The names of the existing data bags.
+ */
+ @Named("databag:list")
+ @GET
+ @Path("/data")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listDatabags();
+
+ /**
+ * Creates a new data bag.
+ *
+ * @param databagName The name for the new data bag.
+ */
+ @Named("databag:create")
+ @POST
+ @Path("/data")
+ void createDatabag(@WrapWith("name") String databagName);
+
+ /**
+ * Deletes a data bag, including its items.
+ *
+ * @param databagName The name of the data bag to delete.
+ */
+ @Named("databag:delete")
+ @DELETE
+ @Path("/data/{name}")
+ @Fallback(VoidOnNotFoundOr404.class)
+ void deleteDatabag(@PathParam("name") String databagName);
+
+ /**
+ * Lists the names of the items in a data bag.
+ *
+ * @param databagName The name of the data bag.
+ * @return The names of the items in the given data bag.
+ */
+ @Named("databag:listitems")
+ @GET
+ @Path("/data/{name}")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listDatabagItems(@PathParam("name") String databagName);
+
+ /**
+ * Gets an item in a data bag.
+ *
+ * @param databagName The name of the data bag.
+ * @param databagItemId The identifier of the item to get.
+ * @return The details of the item in the given data bag.
+ */
+ @Named("databag:getitem")
+ @GET
+ @Path("/data/{databagName}/{databagItemId}")
+ @Fallback(NullOnNotFoundOr404.class)
+ DatabagItem getDatabagItem(@PathParam("databagName") String databagName,
+ @PathParam("databagItemId") String databagItemId);
+
+ /**
+ * Adds an item in a data bag.
+ *
+ * @param databagName The name of the data bag.
+ * @param The item to add to the data bag.
+ * @param The item just added to the data bag.
+ */
+ @Named("databag:createitem")
+ @POST
+ @Path("/data/{databagName}")
+ DatabagItem createDatabagItem(@PathParam("databagName") String databagName,
+ @BinderParam(BindToJsonPayload.class) DatabagItem databagItem);
+
+ /**
+ * Updates an item in a data bag.
+ *
+ * @param databagName The name of the data bag.
+ * @param item The new contents for the item in the data bag.
+ * @return The details for the updated item in the data bag.
+ */
+ @Named("databag:updateitem")
+ @PUT
+ @Path("/data/{databagName}/{databagItemId}")
+ DatabagItem updateDatabagItem(
+ @PathParam("databagName") String databagName,
+ @PathParam("databagItemId") @ParamParser(DatabagItemId.class) @BinderParam(BindToJsonPayload.class) DatabagItem item);
+
+ /**
+ * Deletes an item from a data bag.
+ *
+ * @param databagName The name of the data bag.
+ * @param databagItemId The identifier of the item to delete.
+ * @return The item deleted from the data bag.
+ */
+ @Named("databag:deleteitem")
+ @DELETE
+ @Path("/data/{databagName}/{databagItemId}")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("raw_data")
+ DatabagItem deleteDatabagItem(@PathParam("databagName") String databagName,
+ @PathParam("databagItemId") String databagItemId);
+
+ // Environments
+
+ /**
+ * Lists the names of the existing environments.
+ *
+ * @return The names of the existing environments.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:list")
+ @GET
+ @Path("/environments")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listEnvironments();
+
+ /**
+ * Gets the details of an existing environment.
+ *
+ * @param environmentname The name of the environment to get.
+ * @return The details of the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:get")
+ @GET
+ @Path("/environments/{environmentname}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Environment getEnvironment(@PathParam("environmentname") String environmentName);
+
+ /**
+ * Creates a new environment.
+ *
+ * @param environment The environment to create.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:create")
+ @POST
+ @Path("/environments")
+ void createEnvironment(@BinderParam(BindToJsonPayload.class) Environment environment);
+
+ /**
+ * Updates the given environment.
+ *
+ * @param environment The new details for the environment.
+ * @return The details of the updated environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:update")
+ @PUT
+ @Path("/environments/{environmentname}")
+ Environment updateEnvironment(
+ @PathParam("environmentname") @ParamParser(EnvironmentName.class) @BinderParam(BindToJsonPayload.class) Environment environment);
+
+ /**
+ * Deletes the given environment.
+ *
+ * @param environmentname The name of the environment to delete.
+ * @return The details of the deleted environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:delete")
+ @DELETE
+ @Path("/environments/{environmentname}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Environment deleteEnvironment(@PathParam("environmentname") String environmentName);
+
+ // Nodes
+
+ /**
+ * Lists the names of the existing nodes.
+ *
+ * @return The names of the existing nodes.
+ */
+ @Named("node:list")
+ @GET
+ @Path("/nodes")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listNodes();
+
+ /**
+ * Lists the names of the nodes in the given environment.
+ *
+ * @param environmentname The name of the environment.
+ * @return The names of the existing nodes in the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("environment:nodelist")
+ @GET
+ @Path("/environments/{environmentname}/nodes")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listNodesInEnvironment(@PathParam("environmentname") String environmentName);
+
+ /**
+ * Gets the details of the given node.
+ *
+ * @param nodename The name of the node to get.
+ * @return The details of the given node.
+ */
+ @Named("node:get")
+ @GET
+ @Path("/nodes/{nodename}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Node getNode(@PathParam("nodename") String nodeName);
+
+ /**
+ * Creates a new node.
+ *
+ * @param node The details of the node to create.
+ */
+ @Named("node:create")
+ @POST
+ @Path("/nodes")
+ void createNode(@BinderParam(BindToJsonPayload.class) Node node);
+
+ /**
+ * Updates an existing node.
+ *
+ * @param node The new details for the node.
+ * @return The details of the updated node.
+ */
+ @Named("node:update")
+ @PUT
+ @Path("/nodes/{nodename}")
+ Node updateNode(@PathParam("nodename") @ParamParser(NodeName.class) @BinderParam(BindToJsonPayload.class) Node node);
+
+ /**
+ * Deletes the given node.
+ *
+ * @param nodename The name of the node to delete.
+ * @return The details of the deleted node.
+ */
+ @Named("node:delete")
+ @DELETE
+ @Path("/nodes/{nodename}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Node deleteNode(@PathParam("nodename") String nodeName);
+
+ // Roles
+
+ /**
+ * Lists the names of the existing roles.
+ *
+ * @return The names of the existing roles.
+ */
+ @Named("role:list")
+ @GET
+ @Path("/roles")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listRoles();
+
+ /**
+ * Gets the details of the given role.
+ *
+ * @param rolename The name of the role to get.
+ * @return The details of the given role.
+ */
+ @Named("role:get")
+ @GET
+ @Path("/roles/{rolename}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Role getRole(@PathParam("rolename") String roleName);
+
+ /**
+ * Creates a new role.
+ *
+ * @param role The details for the new role.
+ */
+ @Named("role:create")
+ @POST
+ @Path("/roles")
+ void createRole(@BinderParam(BindToJsonPayload.class) Role role);
+
+ /**
+ * Updates the given role.
+ *
+ * @param role The new details for the role.
+ * @return The details of the updated role.
+ */
+ @Named("role:update")
+ @PUT
+ @Path("/roles/{rolename}")
+ Role updateRole(@PathParam("rolename") @ParamParser(RoleName.class) @BinderParam(BindToJsonPayload.class) Role role);
+
+ /**
+ * Deletes the given role.
+ *
+ * @param rolename The name of the role to delete.
+ * @return The details of the deleted role.
+ */
+ @Named("role:delete")
+ @DELETE
+ @Path("/roles/{rolename}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Role deleteRole(@PathParam("rolename") String roleName);
+
+ // Sandboxes
+
+ /**
+ * Creates a new sandbox.
+ * <p>
+ * It accepts a list of checksums as input and returns the URLs against which
+ * to PUT files that need to be uploaded.
+ *
+ * @param md5s The raw md5 sums. Uses {@code Bytes.asList()} and
+ * {@code Bytes.toByteArray()} as necessary
+ * @return The upload sandbox with the URLs against which to PUT files that
+ * need to be uploaded.
+ */
+ @Named("sandbox:upload")
+ @POST
+ @Path("/sandboxes")
+ UploadSandbox createUploadSandboxForChecksums(@BinderParam(BindChecksumsToJsonPayload.class) Set<List<Byte>> md5s);
+
+ /**
+ * Uploads the given content to the sandbox at the given URI.
+ * <p>
+ * The URI must be obtained, after uploading a sandbox, from the
+ * {@link UploadSandbox#getUri()}.
+ *
+ * @param location The URI where the upload must be performed.
+ * @param content The contents to upload.
+ */
+ @Named("content:upload")
+ @PUT
+ @Produces("application/x-binary")
+ void uploadContent(@EndpointParam URI location, Payload content);
+
+ /**
+ * Gets the contents of the given resource.
+ *
+ * @param resource The resource to get.
+ * @return An input stream for the content of the requested resource.
+ */
+ @Named("content:get")
+ @GET
+ @Fallback(NullOnNotFoundOr404.class)
+ @SkipEncoding({ '+', ' ', '/', '=', ':', ';' })
+ InputStream getResourceContents(@EndpointParam(parser = UriForResource.class) Resource resource);
+
+ /**
+ * Confirms if the sandbox is completed or not.
+ * <p>
+ * This method should be used after uploading contents to the sandbox.
+ *
+ * @param id The id of the sandbox to commit.
+ * @param isCompleted Flag to set if the sandbox is completed or not.
+ * @return The details of the sandbox.
+ */
+ @Named("sandbox:commit")
+ @PUT
+ @Path("/sandboxes/{id}")
+ Sandbox commitSandbox(@PathParam("id") String id, @WrapWith("is_completed") boolean isCompleted);
+
+ // Search
+
+ /**
+ * Lists the names of the available search indexes.
+ * <p>
+ * By default, the "role", "node" and "api" indexes will always be available.
+ * <p>
+ * Note that the search indexes may lag behind the most current data by at
+ * least 10 seconds at any given time - so if you need to write data and
+ * immediately query it, you likely need to produce an artificial delay (or
+ * simply retry until the data is available).
+ *
+ * @return The names of the available search indexes.
+ */
+ @Named("search:indexes")
+ @GET
+ @Path("/search")
+ @ResponseParser(ParseKeySetFromJson.class)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<String> listSearchIndexes();
+
+ /**
+ * Searches all clients.
+ * <p>
+ * Note that without any request parameters this will return all of the data
+ * within the index.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:clients")
+ @GET
+ @Path("/search/client")
+ @ResponseParser(ParseSearchClientsFromJson.class)
+ SearchResult<? extends Client> searchClients();
+
+ /**
+ * Searches all clients that match the given options.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:clients")
+ @GET
+ @Path("/search/client")
+ @ResponseParser(ParseSearchClientsFromJson.class)
+ SearchResult<? extends Client> searchClients(SearchOptions options);
+
+ /**
+ * Searches all items in a data bag.
+ * <p>
+ * Note that without any request parameters this will return all of the data
+ * within the index.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:databag")
+ @GET
+ @Path("/search/{databagName}")
+ @ResponseParser(ParseSearchDatabagFromJson.class)
+ SearchResult<? extends DatabagItem> searchDatabagItems(@PathParam("databagName") String databagName);
+
+ /**
+ * Searches all items in a data bag that match the given options.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:databag")
+ @GET
+ @Path("/search/{databagName}")
+ @ResponseParser(ParseSearchDatabagFromJson.class)
+ SearchResult<? extends DatabagItem> searchDatabagItems(@PathParam("databagName") String databagName,
+ SearchOptions options);
+
+ /**
+ * Searches all environments.
+ * <p>
+ * Note that without any request parameters this will return all of the data
+ * within the index.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("search:environments")
+ @GET
+ @Path("/search/environment")
+ @ResponseParser(ParseSearchEnvironmentsFromJson.class)
+ SearchResult<? extends Environment> searchEnvironments();
+
+ /**
+ * Searches all environments that match the given options.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @SinceApiVersion("0.10.0")
+ @Named("search:environments")
+ @GET
+ @Path("/search/environment")
+ @ResponseParser(ParseSearchEnvironmentsFromJson.class)
+ SearchResult<? extends Environment> searchEnvironments(SearchOptions options);
+
+ /**
+ * Searches all nodes.
+ * <p>
+ * Note that without any request parameters this will return all of the data
+ * within the index.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:nodes")
+ @GET
+ @Path("/search/node")
+ @ResponseParser(ParseSearchNodesFromJson.class)
+ SearchResult<? extends Node> searchNodes();
+
+ /**
+ * Searches all nodes that match the given options.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:nodes")
+ @GET
+ @Path("/search/node")
+ @ResponseParser(ParseSearchNodesFromJson.class)
+ SearchResult<? extends Node> searchNodes(SearchOptions options);
+
+ /**
+ * Searches all roles.
+ * <p>
+ * Note that without any request parameters this will return all of the data
+ * within the index.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:roles")
+ @GET
+ @Path("/search/role")
+ @ResponseParser(ParseSearchRolesFromJson.class)
+ SearchResult<? extends Role> searchRoles();
+
+ /**
+ * Searches all roles that match the given options.
+ *
+ * @return The response contains the total number of rows that matched the
+ * request, the position this result set returns (useful for paging)
+ * and the rows themselves.
+ */
+ @Named("search:roles")
+ @GET
+ @Path("/search/role")
+ @ResponseParser(ParseSearchRolesFromJson.class)
+ SearchResult<? extends Role> searchRoles(SearchOptions options);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/ChefApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/ChefApiMetadata.java b/apis/chef/src/main/java/org/jclouds/chef/ChefApiMetadata.java
new file mode 100644
index 0000000..ede03e9
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/ChefApiMetadata.java
@@ -0,0 +1,110 @@
+/*
+ * 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.jclouds.chef;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
+import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG;
+import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEMS;
+import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEM_SYSTEM;
+import static org.jclouds.chef.config.ChefProperties.CHEF_USE_OMNIBUS;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.chef.config.ChefBootstrapModule;
+import org.jclouds.chef.config.ChefHttpApiModule;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.ohai.config.JMXOhaiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for OpsCode's Chef api.
+ */
+public class ChefApiMetadata extends BaseHttpApiMetadata<ChefApi> {
+
+ /**
+ * The default Chef Server API version to use.
+ */
+ public static final String DEFAULT_API_VERSION = "0.10.8";
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ public ChefApiMetadata() {
+ this(new Builder());
+ }
+
+ protected ChefApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseHttpApiMetadata.defaultProperties();
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.updateCookbook", MINUTES.toMillis(10) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createClient", MINUTES.toMillis(2) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.generateKeyForClient", MINUTES.toMillis(2) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createNode", MINUTES.toMillis(2) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.updateNode", MINUTES.toMillis(10) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createRole", MINUTES.toMillis(2) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.updateRole", MINUTES.toMillis(10) + "");
+ properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createEnvironment", MINUTES.toMillis(2) + "");
+ properties.setProperty(PROPERTY_SESSION_INTERVAL, "1");
+ properties.setProperty(CHEF_BOOTSTRAP_DATABAG, "bootstrap");
+ properties.setProperty(CHEF_UPDATE_GEM_SYSTEM, "false");
+ properties.setProperty(CHEF_UPDATE_GEMS, "false");
+ properties.setProperty(CHEF_USE_OMNIBUS, "true");
+ return properties;
+ }
+
+ public static class Builder extends BaseHttpApiMetadata.Builder<ChefApi, Builder> {
+
+ protected Builder() {
+ id("chef")
+ .name("OpsCode Chef Api")
+ .identityName("User")
+ .credentialName("Certificate")
+ .version(DEFAULT_API_VERSION)
+ .documentation(URI.create("http://wiki.opscode.com/display/chef/Server+API"))
+ .defaultEndpoint("http://localhost:4000")
+ .defaultProperties(ChefApiMetadata.defaultProperties())
+ .view(ChefContext.class)
+ .defaultModules(
+ ImmutableSet.<Class<? extends Module>> of(ChefHttpApiModule.class, ChefParserModule.class,
+ ChefBootstrapModule.class, JMXOhaiModule.class));
+ }
+
+ @Override
+ public ChefApiMetadata build() {
+ return new ChefApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/ChefContext.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/ChefContext.java b/apis/chef/src/main/java/org/jclouds/chef/ChefContext.java
new file mode 100644
index 0000000..7809634
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/ChefContext.java
@@ -0,0 +1,37 @@
+/*
+ * 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.jclouds.chef;
+
+import java.io.Closeable;
+
+import org.jclouds.View;
+import org.jclouds.chef.internal.ChefContextImpl;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ * Provides an entry point to Chef features.
+ */
+@ImplementedBy(ChefContextImpl.class)
+public interface ChefContext extends View, Closeable {
+
+ /**
+ * Provides access to high level Chef features.
+ */
+ ChefService getChefService();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/ChefService.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/ChefService.java b/apis/chef/src/main/java/org/jclouds/chef/ChefService.java
new file mode 100644
index 0000000..040107a
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/ChefService.java
@@ -0,0 +1,263 @@
+/*
+ * 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.jclouds.chef;
+
+import com.google.common.io.InputSupplier;
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.BootstrapConfig;
+import org.jclouds.chef.domain.Client;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.domain.Environment;
+import org.jclouds.chef.domain.Node;
+import org.jclouds.chef.internal.BaseChefService;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.scriptbuilder.domain.Statement;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Provides high level Chef operations.
+ */
+@ImplementedBy(BaseChefService.class)
+public interface ChefService {
+
+ /**
+ * Gets the context that created this service.
+ *
+ * @return The context that created the service.
+ */
+ ChefContext getContext();
+
+ // Crypto
+
+ /**
+ * Encrypts the given input stream.
+ *
+ * @param supplier The input stream to encrypt.
+ * @return The encrypted bytes for the given input stream.
+ * @throws IOException If there is an error reading from the input stream.
+ */
+ byte[] encrypt(InputSupplier<? extends InputStream> supplier) throws IOException;
+
+ /**
+ * Decrypts the given input stream.
+ *
+ * @param supplier The input stream to decrypt.
+ * @return The decrypted bytes for the given input stream.
+ * @throws IOException If there is an error reading from the input stream.
+ */
+ byte[] decrypt(InputSupplier<? extends InputStream> supplier) throws IOException;
+
+ // Bootstrap
+
+ /**
+ * Creates all steps necessary to bootstrap the node.
+ *
+ * @param group corresponds to a configured
+ * {@link ChefProperties#CHEF_BOOTSTRAP_DATABAG} data bag where
+ * run_list and other information are stored.
+ * @return The script used to bootstrap the node.
+ */
+ Statement createBootstrapScriptForGroup(String group);
+
+ /**
+ * Configures how the nodes of a certain group will be bootstrapped
+ *
+ * @param group The group where the given bootstrap configuration will be
+ * applied.
+ * @param bootstrapConfig The configuration to be applied to the nodes in the
+ * group.
+ */
+ void updateBootstrapConfigForGroup(String group, BootstrapConfig bootstrapConfig);
+
+ /**
+ * Gets the run list for the given group.
+ *
+ * @param The group to get the configured run list for.
+ * @return run list for all nodes bootstrapped with a certain group
+ */
+ List<String> getRunListForGroup(String group);
+
+ /**
+ * Gets the bootstrap configuration for a given group.
+ * <p/>
+ * The bootstrap configuration is a Json object containing the run list and
+ * the configured attributes.
+ *
+ * @param group The name of the group.
+ * @return The bootstrap configuration for the given group.
+ */
+ JsonBall getBootstrapConfigForGroup(String group);
+
+ // Nodes / Clients
+
+ /**
+ * Creates a new node and populates the automatic attributes.
+ *
+ * @param nodeName The name of the node to create.
+ * @param runList The run list for the created node.
+ * @return The created node with the automatic attributes populated.
+ * @see OhaiModule
+ * @see ChefUtils#ohaiAutomaticAttributeBinder(com.google.inject.Binder)
+ */
+ Node createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable<String> runList);
+
+ /**
+ * Updates and populate the automatic attributes of the given node.
+ *
+ * @param nodeName The node to update.
+ */
+ void updateAutomaticAttributesOnNode(String nodeName);
+
+ /**
+ * Removes the nodes and clients that have been inactive for a given amount of
+ * time.
+ *
+ * @param prefix The prefix for the nodes and clients to delete.
+ * @param secondsStale The seconds of inactivity to consider a node and
+ * client obsolete.
+ */
+ void cleanupStaleNodesAndClients(String prefix, int secondsStale);
+
+ /**
+ * Deletes the given nodes.
+ *
+ * @param names The names of the nodes to delete.
+ */
+ void deleteAllNodesInList(Iterable<String> names);
+
+ /**
+ * Deletes the given clients.
+ *
+ * @param names The names of the client to delete.
+ */
+ void deleteAllClientsInList(Iterable<String> names);
+
+ /**
+ * Lists the details of all existing nodes.
+ *
+ * @return The details of all existing nodes.
+ */
+ Iterable<? extends Node> listNodes();
+
+ /**
+ * Lists the details of all existing nodes, executing concurrently using the executorService.
+ *
+ * @return The details of all existing nodes.
+ */
+ Iterable<? extends Node> listNodes(ExecutorService executorService);
+
+ /**
+ * Lists the details of all existing nodes in the given environment.
+ *
+ * @param environmentName The name fo the environment.
+ * @return The details of all existing nodes in the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ Iterable<? extends Node> listNodesInEnvironment(String environmentName);
+
+ /**
+ * Lists the details of all existing nodes in the given environment, using the ExecutorService to paralleling the execution.
+ *
+ * @param executorService The thread pool used in this operation
+ * @param environmentName The name fo the environment.
+ * @return The details of all existing nodes in the given environment.
+ */
+ @SinceApiVersion("0.10.0")
+ Iterable<? extends Node> listNodesInEnvironment(String environmentName, ExecutorService executorService);
+
+ /**
+ * Lists the details of all existing clients.
+ *
+ * @return The details of all existing clients.
+ */
+ Iterable<? extends Client> listClients();
+
+ /**
+ * Lists the details of all existing clients, but executing concurrently using the threads available in the ExecutorService.
+ *
+ * @return The details of all existing clients.
+ */
+ Iterable<? extends Client> listClients(ExecutorService executorService);
+
+ /**
+ * Lists the details of all existing cookbooks.
+ *
+ * @return The details of all existing cookbooks.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersions();
+
+ /**
+ * Lists the details of all existing cookbooks. This method is executed concurrently, using the threads available in the ExecutorService.
+ *
+ * @return The details of all existing cookbooks.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersions(ExecutorService executorService);
+
+ /**
+ * Lists the details of all existing cookbooks in an environment.
+ *
+ * @param environmentName The environment name.
+ * @return The details of all existing cookbooks in an environment.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName);
+
+ /**
+ * Lists the details of all existing cookbooks in an environment.
+
+ * @param executorService The thread pool to do the concurrent execution.
+ * @param environmentName The environment name.
+ * @return The details of all existing cookbooks in an environment.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName, ExecutorService executorService);
+
+ /**
+ * Lists the details of all existing cookbooks in an environment
+ * limiting number of versions.
+ *
+ * @param environmentName The environment name.
+ * @param numVersions The number of cookbook versions to include.
+ * Use 'all' to return all cookbook versions.
+ * @return The details of all existing cookbooks in environment.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName, String numVersions);
+
+ /**
+ * Lists the details of all existing cookbooks in an environment
+ * limiting number of versions.
+ *
+ * @param executorService The executorService used to do this operation concurrently.
+ * @param environmentName The environment name.
+ * @param numVersions The number of cookbook versions to include.
+ * Use 'all' to return all cookbook versions.
+ * @return The details of all existing cookbooks in environment.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName, String numVersions, ExecutorService executorService);
+
+ /**
+ * Lists the details of all existing environments.
+ *
+ * @return The details of all existing environments.
+ */
+ @SinceApiVersion("0.10.0")
+ Iterable<? extends Environment> listEnvironments();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/BindChecksumsToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/BindChecksumsToJsonPayload.java b/apis/chef/src/main/java/org/jclouds/chef/binders/BindChecksumsToJsonPayload.java
new file mode 100644
index 0000000..9a744a3
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/BindChecksumsToJsonPayload.java
@@ -0,0 +1,54 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.io.BaseEncoding.base16;
+import static com.google.common.primitives.Bytes.toArray;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Singleton;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.binders.BindToStringPayload;
+
+@Singleton
+public class BindChecksumsToJsonPayload extends BindToStringPayload {
+
+ @SuppressWarnings("unchecked")
+ public HttpRequest bindToRequest(HttpRequest request, Object input) {
+ checkArgument(checkNotNull(input, "input") instanceof Set, "this binder is only valid for Set!");
+
+ Set<List<Byte>> md5s = (Set<List<Byte>>) input;
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("{\"checksums\":{");
+
+ for (List<Byte> md5 : md5s)
+ builder.append(String.format("\"%s\":null,", base16().lowerCase().encode(toArray(md5))));
+ builder.deleteCharAt(builder.length() - 1);
+ builder.append("}}");
+ super.bindToRequest(request, builder.toString());
+ request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
+ return request;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/BindCreateClientOptionsToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/BindCreateClientOptionsToJsonPayload.java b/apis/chef/src/main/java/org/jclouds/chef/binders/BindCreateClientOptionsToJsonPayload.java
new file mode 100644
index 0000000..b719c66
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/BindCreateClientOptionsToJsonPayload.java
@@ -0,0 +1,71 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.chef.options.CreateClientOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.json.Json;
+import org.jclouds.rest.binders.BindToJsonPayload;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+/**
+ * Bind the parameters of a {@link CreateClientOptions} to the payload.
+ */
+public class BindCreateClientOptionsToJsonPayload extends BindToJsonPayload {
+ @Inject
+ public BindCreateClientOptionsToJsonPayload(Json jsonBinder) {
+ super(jsonBinder);
+ }
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+ checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
+ "this binder is only valid for GeneratedHttpRequests");
+ GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
+ checkState(gRequest.getInvocation().getArgs() != null, "args should be initialized at this point");
+
+ String name = checkNotNull(postParams.remove("name"), "name").toString();
+ CreateClientOptions options = (CreateClientOptions) Iterables.find(gRequest.getInvocation().getArgs(),
+ Predicates.instanceOf(CreateClientOptions.class));
+
+ return bindToRequest(request, new CreateClientParams(name, options));
+ }
+
+ @SuppressWarnings("unused")
+ private static class CreateClientParams {
+ private String name;
+
+ private boolean admin;
+
+ public CreateClientParams(String name, CreateClientOptions options) {
+ this.name = name;
+ this.admin = options.isAdmin();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/BindGenerateKeyForClientToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/BindGenerateKeyForClientToJsonPayload.java b/apis/chef/src/main/java/org/jclouds/chef/binders/BindGenerateKeyForClientToJsonPayload.java
new file mode 100644
index 0000000..4bd5821
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/BindGenerateKeyForClientToJsonPayload.java
@@ -0,0 +1,35 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import javax.inject.Singleton;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.binders.BindToStringPayload;
+
+@Singleton
+public class BindGenerateKeyForClientToJsonPayload extends BindToStringPayload {
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
+ super.bindToRequest(request, String.format("{\"name\":\"%s\", \"private_key\": true}", payload));
+ request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
+ return request;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/DatabagItemId.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/DatabagItemId.java b/apis/chef/src/main/java/org/jclouds/chef/binders/DatabagItemId.java
new file mode 100644
index 0000000..5dd5a62
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/DatabagItemId.java
@@ -0,0 +1,32 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.DatabagItem;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class DatabagItemId implements Function<Object, String> {
+
+ public String apply(Object from) {
+ return ((DatabagItem) from).getId();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/EnvironmentName.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/EnvironmentName.java b/apis/chef/src/main/java/org/jclouds/chef/binders/EnvironmentName.java
new file mode 100644
index 0000000..1650521
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/EnvironmentName.java
@@ -0,0 +1,31 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import com.google.common.base.Function;
+import org.jclouds.chef.domain.Environment;
+
+import javax.inject.Singleton;
+
+@Singleton
+public class EnvironmentName implements Function<Object, String> {
+
+ @Override
+ public String apply(Object input) {
+ return ((Environment) input).getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/NodeName.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/NodeName.java b/apis/chef/src/main/java/org/jclouds/chef/binders/NodeName.java
new file mode 100644
index 0000000..5277895
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/NodeName.java
@@ -0,0 +1,32 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.Node;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class NodeName implements Function<Object, String> {
+
+ public String apply(Object from) {
+ return ((Node) from).getName();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/binders/RoleName.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/binders/RoleName.java b/apis/chef/src/main/java/org/jclouds/chef/binders/RoleName.java
new file mode 100644
index 0000000..aa78a06
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/binders/RoleName.java
@@ -0,0 +1,32 @@
+/*
+ * 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.jclouds.chef.binders;
+
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.Role;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class RoleName implements Function<Object, String> {
+
+ public String apply(Object from) {
+ return ((Role) from).getName();
+ }
+
+}