mirror of https://github.com/apache/jclouds.git
Promoted jclouds-chef/core to apis/chef
This commit is contained in:
commit
36dcc576af
|
@ -0,0 +1,134 @@
|
||||||
|
<?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.chef</groupId>
|
||||||
|
<artifactId>chef-project</artifactId>
|
||||||
|
<version>1.8.2-SNAPSHOT</version>
|
||||||
|
<relativePath>../project/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<groupId>org.apache.jclouds.api</groupId>
|
||||||
|
<artifactId>chef</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>Apache jclouds Chef :: Core</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=${jclouds.version},
|
||||||
|
org.jclouds*;version=${jclouds.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>${jclouds.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-core</artifactId>
|
||||||
|
<version>${jclouds.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||||
|
<version>${jclouds.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||||
|
<version>${jclouds.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>${jclouds.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-slf4j</artifactId>
|
||||||
|
<version>${jclouds.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.0.9</version>
|
||||||
|
<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>
|
|
@ -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))))))
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Suppliers.compose;
|
||||||
|
import static com.google.common.base.Suppliers.memoizeWithExpiration;
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
|
import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_CREDENTIAL;
|
||||||
|
import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_NAME;
|
||||||
|
import static org.jclouds.crypto.Pems.privateKeySpec;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.functions.BootstrapConfigForGroup;
|
||||||
|
import org.jclouds.chef.functions.ClientForGroup;
|
||||||
|
import org.jclouds.chef.functions.RunListForGroup;
|
||||||
|
import org.jclouds.chef.handlers.ChefApiErrorRetryHandler;
|
||||||
|
import org.jclouds.chef.handlers.ChefErrorHandler;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.date.TimeStamp;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
|
import org.jclouds.http.HttpRetryHandler;
|
||||||
|
import org.jclouds.http.annotation.ClientError;
|
||||||
|
import org.jclouds.http.annotation.Redirection;
|
||||||
|
import org.jclouds.http.annotation.ServerError;
|
||||||
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.io.ByteSource;
|
||||||
|
import com.google.inject.ConfigurationException;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Key;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.name.Names;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the Chef connection.
|
||||||
|
*/
|
||||||
|
@ConfiguresHttpApi
|
||||||
|
public abstract class BaseChefHttpApiModule<S> extends HttpApiModule<S> {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@TimeStamp
|
||||||
|
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||||
|
return cache.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* borrowing concurrency code to ensure that caching takes place properly
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@TimeStamp
|
||||||
|
Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) {
|
||||||
|
return memoizeWithExpiration(new Supplier<String>() {
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return dateService.iso8601SecondsDateFormat();
|
||||||
|
}
|
||||||
|
}, seconds, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: potentially change this
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public Supplier<PrivateKey> supplyKey(final LoadingCache<Credentials, PrivateKey> keyCache,
|
||||||
|
@org.jclouds.location.Provider final Supplier<Credentials> creds) {
|
||||||
|
return compose(new Function<Credentials, PrivateKey>() {
|
||||||
|
@Override
|
||||||
|
public PrivateKey apply(Credentials in) {
|
||||||
|
return keyCache.getUnchecked(in);
|
||||||
|
}
|
||||||
|
}, creds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
LoadingCache<Credentials, PrivateKey> privateKeyCache(PrivateKeyForCredentials loader) {
|
||||||
|
// throw out the private key related to old credentials
|
||||||
|
return CacheBuilder.newBuilder().maximumSize(2).build(loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* it is relatively expensive to extract a private key from a PEM. cache the
|
||||||
|
* relationship between current credentials so that the private key is only
|
||||||
|
* recalculated once.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
@Singleton
|
||||||
|
private static class PrivateKeyForCredentials extends CacheLoader<Credentials, PrivateKey> {
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PrivateKeyForCredentials(Crypto crypto) {
|
||||||
|
this.crypto = crypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrivateKey load(Credentials in) {
|
||||||
|
try {
|
||||||
|
return crypto.rsaKeyFactory().generatePrivate(
|
||||||
|
privateKeySpec(ByteSource.wrap(in.credential.getBytes(Charsets.UTF_8))));
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw propagate(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw propagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Validator
|
||||||
|
public Optional<String> provideValidatorName(Injector injector) {
|
||||||
|
// Named properties can not be injected as optional here, so let's use the
|
||||||
|
// injector to bypass it
|
||||||
|
Key<String> key = Key.get(String.class, Names.named(CHEF_VALIDATOR_NAME));
|
||||||
|
try {
|
||||||
|
return Optional.<String> of(injector.getInstance(key));
|
||||||
|
} catch (ConfigurationException ex) {
|
||||||
|
return Optional.<String> absent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Validator
|
||||||
|
public Optional<PrivateKey> provideValidatorCredential(Crypto crypto, Injector injector)
|
||||||
|
throws InvalidKeySpecException, IOException {
|
||||||
|
// Named properties can not be injected as optional here, so let's use the
|
||||||
|
// injector to bypass it
|
||||||
|
Key<String> key = Key.get(String.class, Names.named(CHEF_VALIDATOR_CREDENTIAL));
|
||||||
|
try {
|
||||||
|
String validatorCredential = injector.getInstance(key);
|
||||||
|
PrivateKey validatorKey = crypto.rsaKeyFactory().generatePrivate(
|
||||||
|
Pems.privateKeySpec(ByteSource.wrap(validatorCredential.getBytes(Charsets.UTF_8))));
|
||||||
|
return Optional.<PrivateKey> of(validatorKey);
|
||||||
|
} catch (ConfigurationException ex) {
|
||||||
|
return Optional.<PrivateKey> absent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CacheLoader<String, List<String>> runListForGroup(RunListForGroup runListForGroup) {
|
||||||
|
return CacheLoader.from(runListForGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CacheLoader<String, ? extends JsonBall> bootstrapConfigForGroup(BootstrapConfigForGroup bootstrapConfigForGroup) {
|
||||||
|
return CacheLoader.from(bootstrapConfigForGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CacheLoader<String, Client> groupToClient(ClientForGroup clientForGroup) {
|
||||||
|
return CacheLoader.from(clientForGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindErrorHandlers() {
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ChefErrorHandler.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ChefErrorHandler.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ChefErrorHandler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindRetryHandlers() {
|
||||||
|
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(ChefApiErrorRetryHandler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import static org.jclouds.chef.config.ChefProperties.CHEF_GEM_SYSTEM_VERSION;
|
||||||
|
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 static org.jclouds.chef.config.ChefProperties.CHEF_VERSION;
|
||||||
|
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||||
|
import org.jclouds.scriptbuilder.statements.chef.InstallChefGems;
|
||||||
|
import org.jclouds.scriptbuilder.statements.chef.InstallChefUsingOmnibus;
|
||||||
|
import org.jclouds.scriptbuilder.statements.ruby.InstallRuby;
|
||||||
|
import org.jclouds.scriptbuilder.statements.ruby.InstallRubyGems;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides bootstrap configuration for nodes.
|
||||||
|
*/
|
||||||
|
public class ChefBootstrapModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named("installChefGems")
|
||||||
|
@Singleton
|
||||||
|
Statement installChefGems(BootstrapProperties bootstrapProperties) {
|
||||||
|
InstallRubyGems installRubyGems = InstallRubyGems.builder()
|
||||||
|
.version(bootstrapProperties.gemSystemVersion().orNull())
|
||||||
|
.updateSystem(bootstrapProperties.updateGemSystem(), bootstrapProperties.gemSystemVersion().orNull())
|
||||||
|
.updateExistingGems(bootstrapProperties.updateGems()) //
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Statement installChef = InstallChefGems.builder().version(bootstrapProperties.chefVersion().orNull()).build();
|
||||||
|
|
||||||
|
return new StatementList(InstallRuby.builder().build(), installRubyGems, installChef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named("installChefOmnibus")
|
||||||
|
@Singleton
|
||||||
|
Statement installChefUsingOmnibus() {
|
||||||
|
return new InstallChefUsingOmnibus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@InstallChef
|
||||||
|
@Singleton
|
||||||
|
Statement installChef(BootstrapProperties bootstrapProperties, @Named("installChefGems") Statement installChefGems,
|
||||||
|
@Named("installChefOmnibus") Statement installChefOmnibus) {
|
||||||
|
return bootstrapProperties.useOmnibus() ? installChefOmnibus : installChefGems;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
private static class BootstrapProperties {
|
||||||
|
@Named(CHEF_VERSION)
|
||||||
|
@Inject(optional = true)
|
||||||
|
private String chefVersionProperty;
|
||||||
|
|
||||||
|
@Named(CHEF_GEM_SYSTEM_VERSION)
|
||||||
|
@Inject(optional = true)
|
||||||
|
private String gemSystemVersionProperty;
|
||||||
|
|
||||||
|
@Named(CHEF_UPDATE_GEM_SYSTEM)
|
||||||
|
@Inject
|
||||||
|
private String updateGemSystemProeprty;
|
||||||
|
|
||||||
|
@Named(CHEF_UPDATE_GEMS)
|
||||||
|
@Inject
|
||||||
|
private String updateGemsProperty;
|
||||||
|
|
||||||
|
@Named(CHEF_USE_OMNIBUS)
|
||||||
|
@Inject
|
||||||
|
private String useOmnibus;
|
||||||
|
|
||||||
|
public Optional<String> chefVersion() {
|
||||||
|
return Optional.fromNullable(chefVersionProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> gemSystemVersion() {
|
||||||
|
return Optional.fromNullable(gemSystemVersionProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateGemSystem() {
|
||||||
|
return Boolean.parseBoolean(updateGemSystemProeprty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateGems() {
|
||||||
|
return Boolean.parseBoolean(updateGemsProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean useOmnibus() {
|
||||||
|
return Boolean.parseBoolean(useOmnibus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the Chef connection.
|
||||||
|
*/
|
||||||
|
@ConfiguresHttpApi
|
||||||
|
public class ChefHttpApiModule extends BaseChefHttpApiModule<ChefApi> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,321 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.DatabagItem;
|
||||||
|
import org.jclouds.chef.functions.ParseCookbookDefinitionFromJson;
|
||||||
|
import org.jclouds.chef.functions.ParseCookbookVersionsV09FromJson;
|
||||||
|
import org.jclouds.chef.functions.ParseCookbookVersionsV10FromJson;
|
||||||
|
import org.jclouds.chef.functions.ParseKeySetFromJson;
|
||||||
|
import org.jclouds.chef.suppliers.ChefVersionSupplier;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
|
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullHackJsonLiteralAdapter;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.io.ByteSource;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.internal.JsonReaderInternalAccess;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
public class ChefParserModule extends AbstractModule {
|
||||||
|
@ImplementedBy(PrivateKeyAdapterImpl.class)
|
||||||
|
public interface PrivateKeyAdapter extends JsonDeserializer<PrivateKey> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class PrivateKeyAdapterImpl implements PrivateKeyAdapter {
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PrivateKeyAdapterImpl(Crypto crypto) {
|
||||||
|
this.crypto = crypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrivateKey deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
|
throws JsonParseException {
|
||||||
|
String keyText = json.getAsString().replaceAll("\\n", "\n");
|
||||||
|
try {
|
||||||
|
return crypto.rsaKeyFactory().generatePrivate(
|
||||||
|
Pems.privateKeySpec(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8))));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ImplementedBy(PublicKeyAdapterImpl.class)
|
||||||
|
public interface PublicKeyAdapter extends JsonDeserializer<PublicKey> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class PublicKeyAdapterImpl implements PublicKeyAdapter {
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PublicKeyAdapterImpl(Crypto crypto) {
|
||||||
|
this.crypto = crypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PublicKey deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
|
throws JsonParseException {
|
||||||
|
String keyText = json.getAsString().replaceAll("\\n", "\n");
|
||||||
|
try {
|
||||||
|
return crypto.rsaKeyFactory().generatePublic(
|
||||||
|
Pems.publicKeySpec(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8))));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ImplementedBy(X509CertificateAdapterImpl.class)
|
||||||
|
public interface X509CertificateAdapter extends JsonDeserializer<X509Certificate> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class X509CertificateAdapterImpl implements X509CertificateAdapter {
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
X509CertificateAdapterImpl(Crypto crypto) {
|
||||||
|
this.crypto = crypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
|
throws JsonParseException {
|
||||||
|
String keyText = json.getAsString().replaceAll("\\n", "\n");
|
||||||
|
try {
|
||||||
|
return Pems.x509Certificate(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8)),
|
||||||
|
crypto.certFactory());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* writes or reads the literal directly
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public static class DataBagItemAdapter extends NullHackJsonLiteralAdapter<DatabagItem> {
|
||||||
|
final Gson gson = new Gson();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DatabagItem createJsonLiteralFromRawJson(String text) {
|
||||||
|
IdHolder idHolder = gson.fromJson(text, IdHolder.class);
|
||||||
|
checkState(idHolder.id != null,
|
||||||
|
"databag item must be a json hash ex. {\"id\":\"item1\",\"my_key\":\"my_data\"}; was %s", text);
|
||||||
|
text = text.replaceFirst(String.format("\\{\"id\"[ ]?:\"%s\",", idHolder.id), "{");
|
||||||
|
return new DatabagItem(idHolder.id, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String toString(DatabagItem value) {
|
||||||
|
String text = value.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
IdHolder idHolder = gson.fromJson(text, IdHolder.class);
|
||||||
|
if (idHolder.id == null) {
|
||||||
|
text = text.replaceFirst("\\{", String.format("{\"id\":\"%s\",", value.getId()));
|
||||||
|
} else {
|
||||||
|
checkArgument(value.getId().equals(idHolder.id),
|
||||||
|
"incorrect id in databagItem text, should be %s: was %s", value.getId(), idHolder.id);
|
||||||
|
}
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class IdHolder {
|
||||||
|
private String id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The NullFilteringTypeAdapterFactories.MapTypeAdapter class is final. Do
|
||||||
|
// the same logic here
|
||||||
|
private static final class KeepLastRepeatedKeyMapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
|
||||||
|
|
||||||
|
protected final TypeAdapter<K> keyAdapter;
|
||||||
|
protected final TypeAdapter<V> valueAdapter;
|
||||||
|
|
||||||
|
protected KeepLastRepeatedKeyMapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
||||||
|
this.keyAdapter = keyAdapter;
|
||||||
|
this.valueAdapter = valueAdapter;
|
||||||
|
nullSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(JsonWriter out, Map<K, V> value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.beginObject();
|
||||||
|
for (Map.Entry<K, V> element : value.entrySet()) {
|
||||||
|
out.name(String.valueOf(element.getKey()));
|
||||||
|
valueAdapter.write(out, element.getValue());
|
||||||
|
}
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<K, V> read(JsonReader in) throws IOException {
|
||||||
|
Map<K, V> result = Maps.newHashMap();
|
||||||
|
in.beginObject();
|
||||||
|
while (in.hasNext()) {
|
||||||
|
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
|
||||||
|
K name = keyAdapter.read(in);
|
||||||
|
V value = valueAdapter.read(in);
|
||||||
|
if (value != null) {
|
||||||
|
// If there are repeated keys, overwrite them to only keep the last one
|
||||||
|
result.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.endObject();
|
||||||
|
return ImmutableMap.copyOf(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(keyAdapter, valueAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
KeepLastRepeatedKeyMapTypeAdapter<?, ?> that = KeepLastRepeatedKeyMapTypeAdapter.class.cast(obj);
|
||||||
|
return equal(this.keyAdapter, that.keyAdapter) && equal(this.valueAdapter, that.valueAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toStringHelper(this).add("keyAdapter", keyAdapter).add("valueAdapter", valueAdapter).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KeepLastRepeatedKeyMapTypeAdapterFactory extends MapTypeAdapterFactory {
|
||||||
|
|
||||||
|
public KeepLastRepeatedKeyMapTypeAdapterFactory() {
|
||||||
|
super(Map.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected <K, V, T> TypeAdapter<T> newAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
||||||
|
return (TypeAdapter<T>) new KeepLastRepeatedKeyMapTypeAdapter<K, V>(keyAdapter, valueAdapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public Map<Type, Object> provideCustomAdapterBindings(DataBagItemAdapter adapter, PrivateKeyAdapter privateAdapter,
|
||||||
|
PublicKeyAdapter publicAdapter, X509CertificateAdapter certAdapter) {
|
||||||
|
return ImmutableMap.<Type, Object> of(DatabagItem.class, adapter, PrivateKey.class, privateAdapter,
|
||||||
|
PublicKey.class, publicAdapter, X509Certificate.class, certAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@CookbookParser
|
||||||
|
public Function<HttpResponse, Set<String>> provideCookbookDefinitionAdapter(ChefVersionSupplier chefVersionSupplier,
|
||||||
|
ParseCookbookDefinitionFromJson v10parser, ParseKeySetFromJson v09parser) {
|
||||||
|
return chefVersionSupplier.get() >= 10 ? v10parser : v09parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@CookbookVersionsParser
|
||||||
|
public Function<HttpResponse, Set<String>> provideCookbookDefinitionAdapter(ChefVersionSupplier chefVersionSupplier,
|
||||||
|
ParseCookbookVersionsV10FromJson v10parser, ParseCookbookVersionsV09FromJson v09parser) {
|
||||||
|
return chefVersionSupplier.get() >= 10 ? v10parser : v09parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||||
|
bind(MapTypeAdapterFactory.class).to(KeepLastRepeatedKeyMapTypeAdapterFactory.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.config;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration properties and constants used in Chef connections.
|
||||||
|
*/
|
||||||
|
public interface ChefProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the Chef logger.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_LOGGER = "jclouds.chef";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Databag that holds chef bootstrap hints, should be a json ball in the
|
||||||
|
* following format:
|
||||||
|
* <p>
|
||||||
|
* {"tag":{"run_list":["recipe[apache2]"]}}
|
||||||
|
*/
|
||||||
|
public static final String CHEF_BOOTSTRAP_DATABAG = "chef.bootstrap-databag";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the validator client used to allow nodes to autoregister in
|
||||||
|
* the Chef server.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_VALIDATOR_NAME = "chef.validator-name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The credential of the validator client used to allow nodes to autoregister
|
||||||
|
* in the Chef server.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_VALIDATOR_CREDENTIAL = "chef.validator-credential";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of the Chef gem to install when bootstrapping nodes.
|
||||||
|
* <p>
|
||||||
|
* If this property is not set, by default the latest available Chef gem will
|
||||||
|
* be installed. The values can be fixed versions such as '0.10.8' or
|
||||||
|
* constrained values such as '>= 0.10.8'.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_VERSION = "chef.version";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean property. Default (false).
|
||||||
|
* <p>
|
||||||
|
* When bootstrapping a node, forces a gem system update before installing
|
||||||
|
* the Chef gems.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_UPDATE_GEM_SYSTEM = "chef.update-gem-system";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used in conjunction with {@link #CHEF_UPDATE_GEM_SYSTEM}. This
|
||||||
|
* property will force the version of RubyGems to update the system to.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_GEM_SYSTEM_VERSION = "chef.gem-system-version";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean property. Default (false).
|
||||||
|
* <p>
|
||||||
|
* When bootstrapping a node, updates the existing gems before installing
|
||||||
|
* Chef.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_UPDATE_GEMS = "chef.update-gems";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean property. Default (true).
|
||||||
|
* <p>
|
||||||
|
* When bootstrapping a node, install the Chef client using the Omnibus
|
||||||
|
* installer.
|
||||||
|
* <p>
|
||||||
|
* This property must be set prior to running the
|
||||||
|
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
|
||||||
|
*/
|
||||||
|
public static final String CHEF_USE_OMNIBUS = "chef.use-omnibus";
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.PARAMETER;
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure the cookbook Json parser.
|
||||||
|
* <p>
|
||||||
|
* Chef Server version 0.9 and 0.10 return a different Json when rquesting the
|
||||||
|
* cookbook definitions. This annotation can be used to setup the cookbook
|
||||||
|
* parser.
|
||||||
|
*/
|
||||||
|
@Target({ METHOD, PARAMETER, FIELD })
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Qualifier
|
||||||
|
public @interface CookbookParser {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.PARAMETER;
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure the cookbook versions Json parser.
|
||||||
|
* <p>
|
||||||
|
* Chef Server version 0.9 and 0.10 return a different Json when rquesting the
|
||||||
|
* cookbook versions. This annotation can be used to setup the cookbook versions
|
||||||
|
* parser.
|
||||||
|
*/
|
||||||
|
@Target({ METHOD, PARAMETER, FIELD })
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Qualifier
|
||||||
|
public @interface CookbookVersionsParser {
|
||||||
|
|
||||||
|
}
|
|
@ -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.config;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.PARAMETER;
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure the Chef install script.
|
||||||
|
*/
|
||||||
|
@Target({ METHOD, PARAMETER, FIELD })
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Qualifier
|
||||||
|
public @interface InstallChef {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.PARAMETER;
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure the validator client information.
|
||||||
|
* <p>
|
||||||
|
* In a Chef server it must be only one validator client. This client is used by
|
||||||
|
* new nodes to autoregister themselves in the Chef server.
|
||||||
|
*/
|
||||||
|
@Target({ METHOD, PARAMETER, FIELD })
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Qualifier
|
||||||
|
public @interface Validator {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attribute in a cookbook metadata.
|
||||||
|
*/
|
||||||
|
public class Attribute {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String required;
|
||||||
|
private boolean calculated;
|
||||||
|
private ImmutableSet.Builder<String> choice = ImmutableSet.builder();
|
||||||
|
private JsonBall defaultValue;
|
||||||
|
private String type;
|
||||||
|
private ImmutableList.Builder<String> recipes = ImmutableList.builder();
|
||||||
|
private String displayName;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public Builder required(String required) {
|
||||||
|
this.required = checkNotNull(required, "required");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder calculated(boolean calculated) {
|
||||||
|
this.calculated = calculated;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder choice(String choice) {
|
||||||
|
this.choice.add(checkNotNull(choice, "choice"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder choices(Iterable<String> choices) {
|
||||||
|
this.choice.addAll(checkNotNull(choices, "choices"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defaultValue(JsonBall defaultValue) {
|
||||||
|
this.defaultValue = checkNotNull(defaultValue, "defaultValue");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder type(String type) {
|
||||||
|
this.type = checkNotNull(type, "type");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recipe(String recipe) {
|
||||||
|
this.recipes.add(checkNotNull(recipe, "recipe"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recipes(Iterable<String> recipes) {
|
||||||
|
this.recipes.addAll(checkNotNull(recipes, "recipes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder displayName(String displayName) {
|
||||||
|
this.displayName = checkNotNull(displayName, "displayName");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder description(String description) {
|
||||||
|
this.description = checkNotNull(description, "description");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attribute build() {
|
||||||
|
return new Attribute(required, calculated, choice.build(), defaultValue, type, recipes.build(), displayName,
|
||||||
|
description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String required;
|
||||||
|
private final boolean calculated;
|
||||||
|
private final Set<String> choice;
|
||||||
|
@SerializedName("default")
|
||||||
|
private final JsonBall defaultValue;
|
||||||
|
private final String type;
|
||||||
|
private final List<String> recipes;
|
||||||
|
@SerializedName("display_name")
|
||||||
|
private final String displayName;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "required", "calculated", "choice", "default", "type", "recipes", "display_name",
|
||||||
|
"description" })
|
||||||
|
protected Attribute(String required, boolean calculated, @Nullable Set<String> choice, JsonBall defaultValue,
|
||||||
|
String type, @Nullable List<String> recipes, String displayName, String description) {
|
||||||
|
this.required = required;
|
||||||
|
this.calculated = calculated;
|
||||||
|
this.choice = copyOfOrEmpty(choice);
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.type = type;
|
||||||
|
this.recipes = copyOfOrEmpty(recipes);
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequired() {
|
||||||
|
return required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCalculated() {
|
||||||
|
return calculated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getChoice() {
|
||||||
|
return choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonBall getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRecipes() {
|
||||||
|
return recipes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (calculated ? 1231 : 1237);
|
||||||
|
result = prime * result + ((choice == null) ? 0 : choice.hashCode());
|
||||||
|
result = prime * result + ((defaultValue == null) ? 0 : defaultValue.hashCode());
|
||||||
|
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||||
|
result = prime * result + ((displayName == null) ? 0 : displayName.hashCode());
|
||||||
|
result = prime * result + ((recipes == null) ? 0 : recipes.hashCode());
|
||||||
|
result = prime * result + ((required == null) ? 0 : required.hashCode());
|
||||||
|
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Attribute other = (Attribute) obj;
|
||||||
|
if (calculated != other.calculated)
|
||||||
|
return false;
|
||||||
|
if (choice == null) {
|
||||||
|
if (other.choice != null)
|
||||||
|
return false;
|
||||||
|
} else if (!choice.equals(other.choice))
|
||||||
|
return false;
|
||||||
|
if (defaultValue == null) {
|
||||||
|
if (other.defaultValue != null)
|
||||||
|
return false;
|
||||||
|
} else if (!defaultValue.equals(other.defaultValue))
|
||||||
|
return false;
|
||||||
|
if (description == null) {
|
||||||
|
if (other.description != null)
|
||||||
|
return false;
|
||||||
|
} else if (!description.equals(other.description))
|
||||||
|
return false;
|
||||||
|
if (displayName == null) {
|
||||||
|
if (other.displayName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!displayName.equals(other.displayName))
|
||||||
|
return false;
|
||||||
|
if (recipes == null) {
|
||||||
|
if (other.recipes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!recipes.equals(other.recipes))
|
||||||
|
return false;
|
||||||
|
if (required == null) {
|
||||||
|
if (other.required != null)
|
||||||
|
return false;
|
||||||
|
} else if (!required.equals(other.required))
|
||||||
|
return false;
|
||||||
|
if (type == null) {
|
||||||
|
if (other.type != null)
|
||||||
|
return false;
|
||||||
|
} else if (!type.equals(other.type))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Attribute [calculated=" + calculated + ", choice=" + choice + ", defaultValue=" + defaultValue
|
||||||
|
+ ", description=" + description + ", displayName=" + displayName + ", recipes=" + recipes + ", required="
|
||||||
|
+ required + ", type=" + type + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures how the nodes in a group will bootstrap.
|
||||||
|
*
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
public class BootstrapConfig {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private ImmutableList.Builder<String> runList = ImmutableList.builder();
|
||||||
|
private String environment;
|
||||||
|
private JsonBall attribtues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the run list that will be executed in the nodes of the group.
|
||||||
|
*/
|
||||||
|
public Builder runList(Iterable<String> runList) {
|
||||||
|
this.runList.addAll(checkNotNull(runList, "runList"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the environment where the nodes in the group will be deployed.
|
||||||
|
*/
|
||||||
|
public Builder environment(String environment) {
|
||||||
|
this.environment = checkNotNull(environment, "environment");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the attributes that will be populated to the deployed nodes.
|
||||||
|
*/
|
||||||
|
public Builder attributes(JsonBall attributes) {
|
||||||
|
this.attribtues = checkNotNull(attributes, "attributes");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BootstrapConfig build() {
|
||||||
|
return new BootstrapConfig(runList.build(), Optional.fromNullable(environment),
|
||||||
|
Optional.fromNullable(attribtues));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<String> runList;
|
||||||
|
private final Optional<String> environment;
|
||||||
|
private final Optional<JsonBall> attribtues;
|
||||||
|
|
||||||
|
protected BootstrapConfig(List<String> runList, Optional<String> environment, Optional<JsonBall> attribtues) {
|
||||||
|
this.runList = checkNotNull(runList, "runList");
|
||||||
|
this.environment = checkNotNull(environment, "environment");
|
||||||
|
this.attribtues = checkNotNull(attribtues, "attributes");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRunList() {
|
||||||
|
return runList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getEnvironment() {
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<JsonBall> getAttribtues() {
|
||||||
|
return attribtues;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The checksum of an uploaded resource.
|
||||||
|
*/
|
||||||
|
public class ChecksumStatus {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private URI url;
|
||||||
|
private boolean needsUpload;
|
||||||
|
|
||||||
|
public Builder url(URI url) {
|
||||||
|
this.url = checkNotNull(url, "url");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder needsUpload(boolean needsUpload) {
|
||||||
|
this.needsUpload = needsUpload;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChecksumStatus build() {
|
||||||
|
return new ChecksumStatus(url, needsUpload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final URI url;
|
||||||
|
@SerializedName("needs_upload")
|
||||||
|
private final boolean needsUpload;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "url", "needs_upload" })
|
||||||
|
protected ChecksumStatus(URI url, boolean needsUpload) {
|
||||||
|
this.url = url;
|
||||||
|
this.needsUpload = needsUpload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean needsUpload() {
|
||||||
|
return needsUpload;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (needsUpload ? 1231 : 1237);
|
||||||
|
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
ChecksumStatus other = (ChecksumStatus) obj;
|
||||||
|
if (needsUpload != other.needsUpload)
|
||||||
|
return false;
|
||||||
|
if (url == null) {
|
||||||
|
if (other.url != null)
|
||||||
|
return false;
|
||||||
|
} else if (!url.equals(other.url))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ChecksumStatus [needsUpload=" + needsUpload + ", url=" + url + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client object.
|
||||||
|
*/
|
||||||
|
public class Client {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private X509Certificate certificate;
|
||||||
|
private PrivateKey privateKey;
|
||||||
|
private String orgname;
|
||||||
|
private String clientname;
|
||||||
|
private String name;
|
||||||
|
private boolean validator;
|
||||||
|
|
||||||
|
public Builder certificate(X509Certificate certificate) {
|
||||||
|
this.certificate = checkNotNull(certificate, "certificate");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder privateKey(PrivateKey privateKey) {
|
||||||
|
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder orgname(String orgname) {
|
||||||
|
this.orgname = checkNotNull(orgname, "orgname");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder clientname(String clientname) {
|
||||||
|
this.clientname = checkNotNull(clientname, "clientname");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder isValidator(boolean validator) {
|
||||||
|
this.validator = validator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client build() {
|
||||||
|
return new Client(certificate, orgname, clientname, name, validator, privateKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final X509Certificate certificate;
|
||||||
|
@SerializedName("private_key")
|
||||||
|
private final PrivateKey privateKey;
|
||||||
|
private final String orgname;
|
||||||
|
private final String clientname;
|
||||||
|
private final String name;
|
||||||
|
private final boolean validator;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "certificate", "orgname", "clientname", "name", "validator", "private_key" })
|
||||||
|
protected Client(X509Certificate certificate, String orgname, String clientname, String name, boolean validator,
|
||||||
|
@Nullable PrivateKey privateKey) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.orgname = orgname;
|
||||||
|
this.clientname = clientname;
|
||||||
|
this.name = name;
|
||||||
|
this.validator = validator;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrivateKey getPrivateKey() {
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509Certificate getCertificate() {
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrgname() {
|
||||||
|
return orgname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientname() {
|
||||||
|
return clientname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidator() {
|
||||||
|
return validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((certificate == null) ? 0 : certificate.hashCode());
|
||||||
|
result = prime * result + ((clientname == null) ? 0 : clientname.hashCode());
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((orgname == null) ? 0 : orgname.hashCode());
|
||||||
|
result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode());
|
||||||
|
result = prime * result + (validator ? 1231 : 1237);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Client other = (Client) obj;
|
||||||
|
if (certificate == null) {
|
||||||
|
if (other.certificate != null)
|
||||||
|
return false;
|
||||||
|
} else if (!certificate.equals(other.certificate))
|
||||||
|
return false;
|
||||||
|
if (clientname == null) {
|
||||||
|
if (other.clientname != null)
|
||||||
|
return false;
|
||||||
|
} else if (!clientname.equals(other.clientname))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (orgname == null) {
|
||||||
|
if (other.orgname != null)
|
||||||
|
return false;
|
||||||
|
} else if (!orgname.equals(other.orgname))
|
||||||
|
return false;
|
||||||
|
if (privateKey == null) {
|
||||||
|
if (other.privateKey != null)
|
||||||
|
return false;
|
||||||
|
} else if (!privateKey.equals(other.privateKey))
|
||||||
|
return false;
|
||||||
|
if (validator != other.validator)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Client [name=" + name + ", clientname=" + clientname + ", orgname=" + orgname + ", isValidator="
|
||||||
|
+ validator + ", certificate=" + certificate + ", privateKey=" + (privateKey == null ? "not " : "")
|
||||||
|
+ "present]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookbook definition as returned by the Chef server >= 0.10.8.
|
||||||
|
*/
|
||||||
|
public class CookbookDefinition {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String name;
|
||||||
|
private URI url;
|
||||||
|
private ImmutableSet.Builder<Version> versions = ImmutableSet.builder();
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder url(URI url) {
|
||||||
|
this.url = checkNotNull(url, "url");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder version(Version version) {
|
||||||
|
this.versions.add(checkNotNull(version, "version"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder versions(Iterable<Version> versions) {
|
||||||
|
this.versions.addAll(checkNotNull(versions, "versions"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder from(CookbookDefinition def) {
|
||||||
|
this.url = checkNotNull(def.getUrl(), "url");
|
||||||
|
this.versions.addAll(checkNotNull(def.getVersions(), "versions"));
|
||||||
|
this.name = def.getName();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CookbookDefinition build() {
|
||||||
|
return new CookbookDefinition(name, url, versions.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final URI url;
|
||||||
|
private final Set<Version> versions;
|
||||||
|
|
||||||
|
@ConstructorProperties({"name", "url", "versions" })
|
||||||
|
protected CookbookDefinition(String name, URI url, @Nullable Set<Version> versions) {
|
||||||
|
this.name = name;
|
||||||
|
this.url = url;
|
||||||
|
this.versions = copyOfOrEmpty(versions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Version> getVersions() {
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||||
|
result = prime * result + ((versions == null) ? 0 : versions.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
CookbookDefinition other = (CookbookDefinition) obj;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (url == null) {
|
||||||
|
if (other.url != null)
|
||||||
|
return false;
|
||||||
|
} else if (!url.equals(other.url))
|
||||||
|
return false;
|
||||||
|
if (versions == null) {
|
||||||
|
if (other.versions != null)
|
||||||
|
return false;
|
||||||
|
} else if (!versions.equals(other.versions))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CookbookDefinition [name=" + name + ", url=" + url + ", versions=" + versions + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Version {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private URI url;
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
public Builder url(URI url) {
|
||||||
|
this.url = checkNotNull(url, "url");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder version(String version) {
|
||||||
|
this.version = checkNotNull(version, "version");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Version build() {
|
||||||
|
return new Version(url, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final URI url;
|
||||||
|
private final String version;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "url", "version" })
|
||||||
|
protected Version(URI url, String version) {
|
||||||
|
this.url = url;
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||||
|
result = prime * result + ((version == null) ? 0 : version.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Version other = (Version) obj;
|
||||||
|
if (url == null) {
|
||||||
|
if (other.url != null)
|
||||||
|
return false;
|
||||||
|
} else if (!url.equals(other.url))
|
||||||
|
return false;
|
||||||
|
if (version == null) {
|
||||||
|
if (other.version != null)
|
||||||
|
return false;
|
||||||
|
} else if (!version.equals(other.version))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Version [url=" + url + ", version=" + version + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,369 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookbook object.
|
||||||
|
*/
|
||||||
|
public class CookbookVersion {
|
||||||
|
public static Builder builder(String name, String version) {
|
||||||
|
return new Builder(name, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String cookbookName;
|
||||||
|
private ImmutableSet.Builder<Resource> definitions = ImmutableSet.builder();
|
||||||
|
private ImmutableSet.Builder<Attribute> attributes = ImmutableSet.builder();
|
||||||
|
private ImmutableSet.Builder<Resource> files = ImmutableSet.builder();
|
||||||
|
private Metadata metadata = Metadata.builder().build();
|
||||||
|
private ImmutableSet.Builder<Resource> providers = ImmutableSet.builder();
|
||||||
|
private ImmutableSet.Builder<Resource> resources = ImmutableSet.builder();
|
||||||
|
private ImmutableSet.Builder<Resource> templates = ImmutableSet.builder();
|
||||||
|
private ImmutableSet.Builder<Resource> libraries = ImmutableSet.builder();
|
||||||
|
private String version;
|
||||||
|
private ImmutableSet.Builder<Resource> recipes = ImmutableSet.builder();
|
||||||
|
private ImmutableSet.Builder<Resource> rootFiles = ImmutableSet.builder();
|
||||||
|
|
||||||
|
public Builder(String name, String version) {
|
||||||
|
this.cookbookName = checkNotNull(name, "name");
|
||||||
|
this.version = checkNotNull(version, "version");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder cookbookName(String cookbookName) {
|
||||||
|
this.cookbookName = checkNotNull(cookbookName, "cookbookName");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder definition(Resource definition) {
|
||||||
|
this.definitions.add(checkNotNull(definition, "definition"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder definitions(Iterable<Resource> definitions) {
|
||||||
|
this.definitions.addAll(checkNotNull(definitions, "definitions"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder attribute(Attribute attribute) {
|
||||||
|
this.attributes.add(checkNotNull(attribute, "attribute"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder attributes(Iterable<Attribute> attributes) {
|
||||||
|
this.attributes.addAll(checkNotNull(attributes, "attributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder file(Resource file) {
|
||||||
|
this.files.add(checkNotNull(file, "file"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder files(Iterable<Resource> files) {
|
||||||
|
this.files.addAll(checkNotNull(files, "files"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder metadata(Metadata metadata) {
|
||||||
|
this.metadata = checkNotNull(metadata, "metadata");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder provider(Resource provider) {
|
||||||
|
this.providers.add(checkNotNull(provider, "provider"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder providers(Iterable<Resource> providers) {
|
||||||
|
this.providers.addAll(checkNotNull(providers, "providers"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder resource(Resource resource) {
|
||||||
|
this.resources.add(checkNotNull(resource, "resource"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder resources(Iterable<Resource> resources) {
|
||||||
|
this.resources.addAll(checkNotNull(resources, "resources"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder template(Resource template) {
|
||||||
|
this.templates.add(checkNotNull(template, "template"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder templates(Iterable<Resource> templates) {
|
||||||
|
this.templates.addAll(checkNotNull(templates, "templates"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder library(Resource library) {
|
||||||
|
this.libraries.add(checkNotNull(library, "library"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder libraries(Iterable<Resource> libraries) {
|
||||||
|
this.libraries.addAll(checkNotNull(libraries, "libraries"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder version(String version) {
|
||||||
|
this.version = checkNotNull(version, "version");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recipe(Resource recipe) {
|
||||||
|
this.recipes.add(checkNotNull(recipe, "recipe"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recipes(Iterable<Resource> recipes) {
|
||||||
|
this.recipes.addAll(checkNotNull(recipes, "recipes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder rootFile(Resource rootFile) {
|
||||||
|
this.rootFiles.add(checkNotNull(rootFile, "rootFile"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder rootFiles(Iterable<Resource> rootFiles) {
|
||||||
|
this.rootFiles.addAll(checkNotNull(rootFiles, "rootFiles"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CookbookVersion build() {
|
||||||
|
return new CookbookVersion(checkNotNull(cookbookName, "name") + "-" + checkNotNull(version, "version"),
|
||||||
|
definitions.build(), attributes.build(), files.build(), metadata, providers.build(), cookbookName,
|
||||||
|
resources.build(), templates.build(), libraries.build(), version, recipes.build(), rootFiles.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Set<Resource> definitions;
|
||||||
|
private final Set<Attribute> attributes;
|
||||||
|
private final Set<Resource> files;
|
||||||
|
private final Metadata metadata;
|
||||||
|
private final Set<Resource> providers;
|
||||||
|
@SerializedName("cookbook_name")
|
||||||
|
private final String cookbookName;
|
||||||
|
private final Set<Resource> resources;
|
||||||
|
private final Set<Resource> templates;
|
||||||
|
private final Set<Resource> libraries;
|
||||||
|
private final String version;
|
||||||
|
private final Set<Resource> recipes;
|
||||||
|
@SerializedName("root_files")
|
||||||
|
private final Set<Resource> rootFiles;
|
||||||
|
|
||||||
|
// internal
|
||||||
|
@SerializedName("json_class")
|
||||||
|
private String _jsonClass = "Chef::CookbookVersion";
|
||||||
|
@SerializedName("chef_type")
|
||||||
|
private String _chefType = "cookbook_version";
|
||||||
|
|
||||||
|
@ConstructorProperties({ "name", "definitions", "attributes", "files", "metadata", "providers", "cookbook_name",
|
||||||
|
"resources", "templates", "libraries", "version", "recipes", "root_files" })
|
||||||
|
protected CookbookVersion(String name, @Nullable Set<Resource> definitions, @Nullable Set<Attribute> attributes,
|
||||||
|
@Nullable Set<Resource> files, Metadata metadata, @Nullable Set<Resource> providers, String cookbookName,
|
||||||
|
@Nullable Set<Resource> resources, @Nullable Set<Resource> templates, @Nullable Set<Resource> libraries,
|
||||||
|
String version, @Nullable Set<Resource> recipes, @Nullable Set<Resource> rootFiles) {
|
||||||
|
this.name = name;
|
||||||
|
this.definitions = copyOfOrEmpty(definitions);
|
||||||
|
this.attributes = copyOfOrEmpty(attributes);
|
||||||
|
this.files = copyOfOrEmpty(files);
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.providers = copyOfOrEmpty(providers);
|
||||||
|
this.cookbookName = cookbookName;
|
||||||
|
this.resources = copyOfOrEmpty(resources);
|
||||||
|
this.templates = copyOfOrEmpty(templates);
|
||||||
|
this.libraries = copyOfOrEmpty(libraries);
|
||||||
|
this.version = version;
|
||||||
|
this.recipes = copyOfOrEmpty(recipes);
|
||||||
|
this.rootFiles = copyOfOrEmpty(rootFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getDefinitions() {
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Attribute> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getFiles() {
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Metadata getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getSuppliers() {
|
||||||
|
return providers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCookbookName() {
|
||||||
|
return cookbookName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getResources() {
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getTemplates() {
|
||||||
|
return templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getLibraries() {
|
||||||
|
return libraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getRecipes() {
|
||||||
|
return recipes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Resource> getRootFiles() {
|
||||||
|
return rootFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
|
||||||
|
result = prime * result + ((cookbookName == null) ? 0 : cookbookName.hashCode());
|
||||||
|
result = prime * result + ((definitions == null) ? 0 : definitions.hashCode());
|
||||||
|
result = prime * result + ((files == null) ? 0 : files.hashCode());
|
||||||
|
result = prime * result + ((libraries == null) ? 0 : libraries.hashCode());
|
||||||
|
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((providers == null) ? 0 : providers.hashCode());
|
||||||
|
result = prime * result + ((recipes == null) ? 0 : recipes.hashCode());
|
||||||
|
result = prime * result + ((resources == null) ? 0 : resources.hashCode());
|
||||||
|
result = prime * result + ((rootFiles == null) ? 0 : rootFiles.hashCode());
|
||||||
|
result = prime * result + ((templates == null) ? 0 : templates.hashCode());
|
||||||
|
result = prime * result + ((version == null) ? 0 : version.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
CookbookVersion other = (CookbookVersion) obj;
|
||||||
|
if (attributes == null) {
|
||||||
|
if (other.attributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!attributes.equals(other.attributes))
|
||||||
|
return false;
|
||||||
|
if (cookbookName == null) {
|
||||||
|
if (other.cookbookName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!cookbookName.equals(other.cookbookName))
|
||||||
|
return false;
|
||||||
|
if (definitions == null) {
|
||||||
|
if (other.definitions != null)
|
||||||
|
return false;
|
||||||
|
} else if (!definitions.equals(other.definitions))
|
||||||
|
return false;
|
||||||
|
if (files == null) {
|
||||||
|
if (other.files != null)
|
||||||
|
return false;
|
||||||
|
} else if (!files.equals(other.files))
|
||||||
|
return false;
|
||||||
|
if (libraries == null) {
|
||||||
|
if (other.libraries != null)
|
||||||
|
return false;
|
||||||
|
} else if (!libraries.equals(other.libraries))
|
||||||
|
return false;
|
||||||
|
if (metadata == null) {
|
||||||
|
if (other.metadata != null)
|
||||||
|
return false;
|
||||||
|
} else if (!metadata.equals(other.metadata))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (providers == null) {
|
||||||
|
if (other.providers != null)
|
||||||
|
return false;
|
||||||
|
} else if (!providers.equals(other.providers))
|
||||||
|
return false;
|
||||||
|
if (recipes == null) {
|
||||||
|
if (other.recipes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!recipes.equals(other.recipes))
|
||||||
|
return false;
|
||||||
|
if (resources == null) {
|
||||||
|
if (other.resources != null)
|
||||||
|
return false;
|
||||||
|
} else if (!resources.equals(other.resources))
|
||||||
|
return false;
|
||||||
|
if (rootFiles == null) {
|
||||||
|
if (other.rootFiles != null)
|
||||||
|
return false;
|
||||||
|
} else if (!rootFiles.equals(other.rootFiles))
|
||||||
|
return false;
|
||||||
|
if (templates == null) {
|
||||||
|
if (other.templates != null)
|
||||||
|
return false;
|
||||||
|
} else if (!templates.equals(other.templates))
|
||||||
|
return false;
|
||||||
|
if (version == null) {
|
||||||
|
if (other.version != null)
|
||||||
|
return false;
|
||||||
|
} else if (!version.equals(other.version))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Cookbook [attributes=" + attributes + ", cookbookName=" + cookbookName + ", definitions=" + definitions
|
||||||
|
+ ", files=" + files + ", libraries=" + libraries + ", metadata=" + metadata + ", name=" + name
|
||||||
|
+ ", providers=" + providers + ", recipes=" + recipes + ", resources=" + resources + ", rootFiles="
|
||||||
|
+ rootFiles + ", templates=" + templates + ", version=" + version + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An item in a data bag.
|
||||||
|
*/
|
||||||
|
public class DatabagItem extends JsonBall {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public DatabagItem(String id, String value) {
|
||||||
|
super(value);
|
||||||
|
this.id = checkNotNull(id, "id");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!super.equals(obj))
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
DatabagItem other = (DatabagItem) obj;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment.
|
||||||
|
*/
|
||||||
|
public class Environment {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String name;
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> attributes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder();
|
||||||
|
private String description = "";
|
||||||
|
private ImmutableMap.Builder<String, String> cookbookVersions = ImmutableMap.builder();
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder attribute(String key, JsonBall value) {
|
||||||
|
this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder attributes(Map<String, JsonBall> attributes) {
|
||||||
|
this.attributes.putAll(checkNotNull(attributes, "attributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder overrideAttribute(String key, JsonBall value) {
|
||||||
|
this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder overrideAttributes(Map<String, JsonBall> overrideAttributes) {
|
||||||
|
this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder cookbookVersion(String key, String version) {
|
||||||
|
this.cookbookVersions.put(checkNotNull(key, "key"), checkNotNull(version, "version"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder cookbookVersions(Map<String, String> cookbookVersions) {
|
||||||
|
this.cookbookVersions.putAll(checkNotNull(cookbookVersions, "cookbookVersions"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder description(String description) {
|
||||||
|
this.description = checkNotNull(description, "description");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Environment build() {
|
||||||
|
return new Environment(name, attributes.build(), overrideAttributes.build(), description,
|
||||||
|
cookbookVersions.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
@SerializedName("default_attributes")
|
||||||
|
private final Map<String, JsonBall> attributes;
|
||||||
|
@SerializedName("override_attributes")
|
||||||
|
private final Map<String, JsonBall> overrideAttributes;
|
||||||
|
private final String description;
|
||||||
|
@SerializedName("cookbook_versions")
|
||||||
|
private final Map<String, String> cookbookVersions;
|
||||||
|
|
||||||
|
// internal
|
||||||
|
@SerializedName("json_class")
|
||||||
|
private final String _jsonClass = "Chef::Environment";
|
||||||
|
@SerializedName("chef_type")
|
||||||
|
private final String _chefType = "environment";
|
||||||
|
|
||||||
|
@ConstructorProperties({ "name", "default_attributes", "override_attributes", "description", "cookbook_versions" })
|
||||||
|
protected Environment(String name, @Nullable Map<String, JsonBall> attributes,
|
||||||
|
@Nullable Map<String, JsonBall> overrideAttributes, String description,
|
||||||
|
@Nullable Map<String, String> cookbookVersions) {
|
||||||
|
this.name = name;
|
||||||
|
this.attributes = copyOfOrEmpty(attributes);
|
||||||
|
this.overrideAttributes = copyOfOrEmpty(overrideAttributes);
|
||||||
|
this.description = description;
|
||||||
|
this.cookbookVersions = copyOfOrEmpty(cookbookVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getOverrideAttributes() {
|
||||||
|
return overrideAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getCookbookVersions() {
|
||||||
|
return cookbookVersions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Environment that = (Environment) o;
|
||||||
|
|
||||||
|
if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null)
|
||||||
|
return false;
|
||||||
|
if (cookbookVersions != null ? !cookbookVersions.equals(that.cookbookVersions) : that.cookbookVersions != null)
|
||||||
|
return false;
|
||||||
|
if (description != null ? !description.equals(that.description) : that.description != null)
|
||||||
|
return false;
|
||||||
|
if (!name.equals(that.name))
|
||||||
|
return false;
|
||||||
|
if (overrideAttributes != null ? !overrideAttributes.equals(that.overrideAttributes)
|
||||||
|
: that.overrideAttributes != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = name.hashCode();
|
||||||
|
result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
|
||||||
|
result = 31 * result + (overrideAttributes != null ? overrideAttributes.hashCode() : 0);
|
||||||
|
result = 31 * result + (description != null ? description.hashCode() : 0);
|
||||||
|
result = 31 * result + (cookbookVersions != null ? cookbookVersions.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Environment [" + "name='" + name + '\'' + ", attributes=" + attributes + ", overrideAttributes="
|
||||||
|
+ overrideAttributes + ", description='" + description + '\'' + ", cookbookVersions=" + cookbookVersions
|
||||||
|
+ ']';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,447 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A metadata object.
|
||||||
|
*/
|
||||||
|
public class Metadata {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String license;
|
||||||
|
private String maintainer;
|
||||||
|
private ImmutableMap.Builder<String, String> suggestions = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, String> dependencies = ImmutableMap.builder();
|
||||||
|
private String maintainerEmail;
|
||||||
|
private ImmutableMap.Builder<String, String> conflicting = ImmutableMap.builder();
|
||||||
|
private String description;
|
||||||
|
private ImmutableMap.Builder<String, String> providing = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, String> platforms = ImmutableMap.builder();
|
||||||
|
private String version;
|
||||||
|
private ImmutableMap.Builder<String, String> recipes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, String> replacing = ImmutableMap.builder();
|
||||||
|
private String name;
|
||||||
|
private ImmutableMap.Builder<String, String> groupings = ImmutableMap.builder();
|
||||||
|
private String longDescription;
|
||||||
|
private ImmutableMap.Builder<String, Attribute> attributes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, String> recommendations = ImmutableMap.builder();
|
||||||
|
|
||||||
|
public Builder license(String license) {
|
||||||
|
this.license = checkNotNull(license, "license");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder maintainer(String maintainer) {
|
||||||
|
this.maintainer = checkNotNull(maintainer, "maintainer");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder suggestion(String key, String value) {
|
||||||
|
this.suggestions.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder suggestions(Map<String, String> suggestions) {
|
||||||
|
this.suggestions.putAll(checkNotNull(suggestions, "suggestions"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder dependency(String key, String value) {
|
||||||
|
this.dependencies.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder dependencies(Map<String, String> dependencies) {
|
||||||
|
this.dependencies.putAll(checkNotNull(dependencies, "dependencies"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder maintainerEmail(String maintainerEmail) {
|
||||||
|
this.maintainerEmail = checkNotNull(maintainerEmail, "maintainerEmail");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder conflicting(String key, String value) {
|
||||||
|
this.conflicting.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder conflicting(Map<String, String> conflicting) {
|
||||||
|
this.conflicting.putAll(checkNotNull(conflicting, "conflicting"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder description(String description) {
|
||||||
|
this.description = checkNotNull(description, "description");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder providing(String key, String value) {
|
||||||
|
this.providing.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder providing(Map<String, String> providing) {
|
||||||
|
this.providing.putAll(checkNotNull(providing, "providing"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder platform(String key, String value) {
|
||||||
|
this.platforms.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder platforms(Map<String, String> platforms) {
|
||||||
|
this.platforms.putAll(checkNotNull(platforms, "platforms"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder version(String version) {
|
||||||
|
this.version = checkNotNull(version, "version");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recipe(String key, String value) {
|
||||||
|
this.recipes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recipes(Map<String, String> recipes) {
|
||||||
|
this.recipes.putAll(checkNotNull(recipes, "recipes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder replacing(String key, String value) {
|
||||||
|
this.replacing.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder replacing(Map<String, String> replacing) {
|
||||||
|
this.replacing.putAll(checkNotNull(replacing, "replacing"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder grouping(String key, String value) {
|
||||||
|
this.groupings.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder grouping(Map<String, String> groupings) {
|
||||||
|
this.groupings.putAll(checkNotNull(groupings, "groupings"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder longDescription(String longDescription) {
|
||||||
|
this.longDescription = checkNotNull(longDescription, "longDescription");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder attribute(String key, Attribute value) {
|
||||||
|
this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder attributes(Map<String, Attribute> attributes) {
|
||||||
|
this.attributes.putAll(checkNotNull(attributes, "attributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recommendation(String key, String value) {
|
||||||
|
this.recommendations.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder recommendations(Map<String, String> recommendations) {
|
||||||
|
this.recommendations.putAll(checkNotNull(recommendations, "recommendations"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Metadata build() {
|
||||||
|
return new Metadata(license, maintainer, suggestions.build(), dependencies.build(), maintainerEmail,
|
||||||
|
conflicting.build(), description, providing.build(), platforms.build(), version, recipes.build(),
|
||||||
|
replacing.build(), name, groupings.build(), longDescription, attributes.build(), recommendations.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String license;
|
||||||
|
private final String maintainer;
|
||||||
|
private final Map<String, String> suggestions;
|
||||||
|
private final Map<String, String> dependencies;
|
||||||
|
@SerializedName("maintainer_email")
|
||||||
|
private final String maintainerEmail;
|
||||||
|
private final Map<String, String> conflicting;
|
||||||
|
private final String description;
|
||||||
|
private final Map<String, String> providing;
|
||||||
|
private final Map<String, String> platforms;
|
||||||
|
private final String version;
|
||||||
|
private final Map<String, String> recipes;
|
||||||
|
private final Map<String, String> replacing;
|
||||||
|
private final String name;
|
||||||
|
private final Map<String, String> groupings;
|
||||||
|
@SerializedName("long_description")
|
||||||
|
private final String longDescription;
|
||||||
|
private final Map<String, Attribute> attributes;
|
||||||
|
private final Map<String, String> recommendations;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "license", "maintainer", "suggestions", "dependencies", "maintainer_email", "conflicting",
|
||||||
|
"description", "providing", "platforms", "version", "recipes", "replacing", "name", "groupings",
|
||||||
|
"long_description", "attributes", "recommendations" })
|
||||||
|
protected Metadata(String license, String maintainer, @Nullable Map<String, String> suggestions,
|
||||||
|
@Nullable Map<String, String> dependencies, String maintainerEmail, @Nullable Map<String, String> conflicting,
|
||||||
|
String description, @Nullable Map<String, String> providing, @Nullable Map<String, String> platforms,
|
||||||
|
String version, @Nullable Map<String, String> recipes, @Nullable Map<String, String> replacing, String name,
|
||||||
|
@Nullable Map<String, String> groupings, String longDescription, @Nullable Map<String, Attribute> attributes,
|
||||||
|
@Nullable Map<String, String> recommendations) {
|
||||||
|
this.license = license;
|
||||||
|
this.maintainer = maintainer;
|
||||||
|
this.suggestions = copyOfOrEmpty(suggestions);
|
||||||
|
this.dependencies = copyOfOrEmpty(dependencies);
|
||||||
|
this.maintainerEmail = maintainerEmail;
|
||||||
|
this.conflicting = copyOfOrEmpty(conflicting);
|
||||||
|
this.description = description;
|
||||||
|
this.providing = copyOfOrEmpty(providing);
|
||||||
|
this.platforms = copyOfOrEmpty(platforms);
|
||||||
|
this.version = version;
|
||||||
|
this.recipes = copyOfOrEmpty(recipes);
|
||||||
|
this.replacing = copyOfOrEmpty(replacing);
|
||||||
|
this.name = name;
|
||||||
|
this.groupings = copyOfOrEmpty(groupings);
|
||||||
|
this.longDescription = longDescription;
|
||||||
|
this.attributes = copyOfOrEmpty(attributes);
|
||||||
|
this.recommendations = copyOfOrEmpty(recommendations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLicense() {
|
||||||
|
return license;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMaintainer() {
|
||||||
|
return maintainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getSuggestions() {
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getDependencies() {
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMaintainerEmail() {
|
||||||
|
return maintainerEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getConflicting() {
|
||||||
|
return conflicting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getProviding() {
|
||||||
|
return providing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getPlatforms() {
|
||||||
|
return platforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRecipes() {
|
||||||
|
return recipes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getReplacing() {
|
||||||
|
return replacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getGroupings() {
|
||||||
|
return groupings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLongDescription() {
|
||||||
|
return longDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Attribute> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRecommendations() {
|
||||||
|
return recommendations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
|
||||||
|
result = prime * result + ((conflicting == null) ? 0 : conflicting.hashCode());
|
||||||
|
result = prime * result + ((dependencies == null) ? 0 : dependencies.hashCode());
|
||||||
|
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||||
|
result = prime * result + ((groupings == null) ? 0 : groupings.hashCode());
|
||||||
|
result = prime * result + ((license == null) ? 0 : license.hashCode());
|
||||||
|
result = prime * result + ((longDescription == null) ? 0 : longDescription.hashCode());
|
||||||
|
result = prime * result + ((maintainer == null) ? 0 : maintainer.hashCode());
|
||||||
|
result = prime * result + ((maintainerEmail == null) ? 0 : maintainerEmail.hashCode());
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((platforms == null) ? 0 : platforms.hashCode());
|
||||||
|
result = prime * result + ((providing == null) ? 0 : providing.hashCode());
|
||||||
|
result = prime * result + ((recipes == null) ? 0 : recipes.hashCode());
|
||||||
|
result = prime * result + ((recommendations == null) ? 0 : recommendations.hashCode());
|
||||||
|
result = prime * result + ((replacing == null) ? 0 : replacing.hashCode());
|
||||||
|
result = prime * result + ((suggestions == null) ? 0 : suggestions.hashCode());
|
||||||
|
result = prime * result + ((version == null) ? 0 : version.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Metadata other = (Metadata) obj;
|
||||||
|
if (attributes == null) {
|
||||||
|
if (other.attributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!attributes.equals(other.attributes))
|
||||||
|
return false;
|
||||||
|
if (conflicting == null) {
|
||||||
|
if (other.conflicting != null)
|
||||||
|
return false;
|
||||||
|
} else if (!conflicting.equals(other.conflicting))
|
||||||
|
return false;
|
||||||
|
if (dependencies == null) {
|
||||||
|
if (other.dependencies != null)
|
||||||
|
return false;
|
||||||
|
} else if (!dependencies.equals(other.dependencies))
|
||||||
|
return false;
|
||||||
|
if (description == null) {
|
||||||
|
if (other.description != null)
|
||||||
|
return false;
|
||||||
|
} else if (!description.equals(other.description))
|
||||||
|
return false;
|
||||||
|
if (groupings == null) {
|
||||||
|
if (other.groupings != null)
|
||||||
|
return false;
|
||||||
|
} else if (!groupings.equals(other.groupings))
|
||||||
|
return false;
|
||||||
|
if (license == null) {
|
||||||
|
if (other.license != null)
|
||||||
|
return false;
|
||||||
|
} else if (!license.equals(other.license))
|
||||||
|
return false;
|
||||||
|
if (longDescription == null) {
|
||||||
|
if (other.longDescription != null)
|
||||||
|
return false;
|
||||||
|
} else if (!longDescription.equals(other.longDescription))
|
||||||
|
return false;
|
||||||
|
if (maintainer == null) {
|
||||||
|
if (other.maintainer != null)
|
||||||
|
return false;
|
||||||
|
} else if (!maintainer.equals(other.maintainer))
|
||||||
|
return false;
|
||||||
|
if (maintainerEmail == null) {
|
||||||
|
if (other.maintainerEmail != null)
|
||||||
|
return false;
|
||||||
|
} else if (!maintainerEmail.equals(other.maintainerEmail))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (platforms == null) {
|
||||||
|
if (other.platforms != null)
|
||||||
|
return false;
|
||||||
|
} else if (!platforms.equals(other.platforms))
|
||||||
|
return false;
|
||||||
|
if (providing == null) {
|
||||||
|
if (other.providing != null)
|
||||||
|
return false;
|
||||||
|
} else if (!providing.equals(other.providing))
|
||||||
|
return false;
|
||||||
|
if (recipes == null) {
|
||||||
|
if (other.recipes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!recipes.equals(other.recipes))
|
||||||
|
return false;
|
||||||
|
if (recommendations == null) {
|
||||||
|
if (other.recommendations != null)
|
||||||
|
return false;
|
||||||
|
} else if (!recommendations.equals(other.recommendations))
|
||||||
|
return false;
|
||||||
|
if (replacing == null) {
|
||||||
|
if (other.replacing != null)
|
||||||
|
return false;
|
||||||
|
} else if (!replacing.equals(other.replacing))
|
||||||
|
return false;
|
||||||
|
if (suggestions == null) {
|
||||||
|
if (other.suggestions != null)
|
||||||
|
return false;
|
||||||
|
} else if (!suggestions.equals(other.suggestions))
|
||||||
|
return false;
|
||||||
|
if (version == null) {
|
||||||
|
if (other.version != null)
|
||||||
|
return false;
|
||||||
|
} else if (!version.equals(other.version))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Metadata [attributes=" + attributes + ", conflicting=" + conflicting + ", dependencies=" + dependencies
|
||||||
|
+ ", description=" + description + ", groupings=" + groupings + ", license=" + license
|
||||||
|
+ ", longDescription=" + longDescription + ", maintainer=" + maintainer + ", maintainerEmail="
|
||||||
|
+ maintainerEmail + ", name=" + name + ", platforms=" + platforms + ", providing=" + providing
|
||||||
|
+ ", recipes=" + recipes + ", recommendations=" + recommendations + ", replacing=" + replacing
|
||||||
|
+ ", suggestions=" + suggestions + ", version=" + version + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node object.
|
||||||
|
*/
|
||||||
|
public class Node {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String name;
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> normalAttributes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> defaultAttributes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> automaticAttributes = ImmutableMap.builder();
|
||||||
|
private ImmutableList.Builder<String> runList = ImmutableList.builder();
|
||||||
|
private String environment;
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder normalAttribute(String key, JsonBall value) {
|
||||||
|
this.normalAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder normalAttributes(Map<String, JsonBall> normalAttributes) {
|
||||||
|
this.normalAttributes.putAll(checkNotNull(normalAttributes, "normalAttributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder overrideAttribute(String key, JsonBall value) {
|
||||||
|
this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder overrideAttributes(Map<String, JsonBall> overrideAttributes) {
|
||||||
|
this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defaultAttribute(String key, JsonBall value) {
|
||||||
|
this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defaultAttributes(Map<String, JsonBall> defaultAttributes) {
|
||||||
|
this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder automaticAttribute(String key, JsonBall value) {
|
||||||
|
this.automaticAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder automaticAttributes(Map<String, JsonBall> automaticAttribute) {
|
||||||
|
this.automaticAttributes.putAll(checkNotNull(automaticAttribute, "automaticAttribute"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder runListElement(String element) {
|
||||||
|
this.runList.add(checkNotNull(element, "element"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder runList(Iterable<String> runList) {
|
||||||
|
this.runList.addAll(checkNotNull(runList, "runList"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since Chef 0.10
|
||||||
|
*/
|
||||||
|
public Builder environment(String environment) {
|
||||||
|
this.environment = checkNotNull(environment, "environment");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node build() {
|
||||||
|
return new Node(name, normalAttributes.build(), overrideAttributes.build(), defaultAttributes.build(),
|
||||||
|
automaticAttributes.build(), runList.build(), environment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
@SerializedName("normal")
|
||||||
|
private final Map<String, JsonBall> normalAttributes;
|
||||||
|
@SerializedName("override")
|
||||||
|
private final Map<String, JsonBall> overrideAttributes;
|
||||||
|
@SerializedName("default")
|
||||||
|
private final Map<String, JsonBall> defaultAttributes;
|
||||||
|
@SerializedName("automatic")
|
||||||
|
private final Map<String, JsonBall> automaticAttributes;
|
||||||
|
@SerializedName("run_list")
|
||||||
|
private final List<String> runList;
|
||||||
|
@SerializedName("chef_environment")
|
||||||
|
private final String environment;
|
||||||
|
|
||||||
|
// internal
|
||||||
|
@SerializedName("json_class")
|
||||||
|
private final String _jsonClass = "Chef::Node";
|
||||||
|
@SerializedName("chef_type")
|
||||||
|
private final String _chefType = "node";
|
||||||
|
|
||||||
|
@ConstructorProperties({ "name", "normal", "override", "default", "automatic", "run_list", "chef_environment" })
|
||||||
|
protected Node(String name, @Nullable Map<String, JsonBall> normalAttributes,
|
||||||
|
@Nullable Map<String, JsonBall> overrideAttributes, @Nullable Map<String, JsonBall> defaultAttributes,
|
||||||
|
@Nullable Map<String, JsonBall> automaticAttributes, List<String> runList, @Nullable String environment) {
|
||||||
|
this.name = name;
|
||||||
|
this.environment = environment;
|
||||||
|
this.normalAttributes = copyOfOrEmpty(normalAttributes);
|
||||||
|
this.overrideAttributes = copyOfOrEmpty(overrideAttributes);
|
||||||
|
this.defaultAttributes = copyOfOrEmpty(defaultAttributes);
|
||||||
|
this.automaticAttributes = copyOfOrEmpty(automaticAttributes);
|
||||||
|
this.runList = copyOfOrEmpty(runList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getNormalAttributes() {
|
||||||
|
return normalAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getOverrideAttributes() {
|
||||||
|
return overrideAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getDefaultAttributes() {
|
||||||
|
return defaultAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getAutomaticAttributes() {
|
||||||
|
return automaticAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRunList() {
|
||||||
|
return runList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since Chef 0.10
|
||||||
|
*/
|
||||||
|
public String getEnvironment() {
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode());
|
||||||
|
result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode());
|
||||||
|
result = prime * result + ((automaticAttributes == null) ? 0 : automaticAttributes.hashCode());
|
||||||
|
result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode());
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((normalAttributes == null) ? 0 : normalAttributes.hashCode());
|
||||||
|
result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode());
|
||||||
|
result = prime * result + ((runList == null) ? 0 : runList.hashCode());
|
||||||
|
result = prime * result + ((environment == null) ? 0 : environment.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Node other = (Node) obj;
|
||||||
|
if (_chefType == null) {
|
||||||
|
if (other._chefType != null)
|
||||||
|
return false;
|
||||||
|
} else if (!_chefType.equals(other._chefType))
|
||||||
|
return false;
|
||||||
|
if (_jsonClass == null) {
|
||||||
|
if (other._jsonClass != null)
|
||||||
|
return false;
|
||||||
|
} else if (!_jsonClass.equals(other._jsonClass))
|
||||||
|
return false;
|
||||||
|
if (automaticAttributes == null) {
|
||||||
|
if (other.automaticAttributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!automaticAttributes.equals(other.automaticAttributes))
|
||||||
|
return false;
|
||||||
|
if (defaultAttributes == null) {
|
||||||
|
if (other.defaultAttributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!defaultAttributes.equals(other.defaultAttributes))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (normalAttributes == null) {
|
||||||
|
if (other.normalAttributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!normalAttributes.equals(other.normalAttributes))
|
||||||
|
return false;
|
||||||
|
if (overrideAttributes == null) {
|
||||||
|
if (other.overrideAttributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!overrideAttributes.equals(other.overrideAttributes))
|
||||||
|
return false;
|
||||||
|
if (runList == null) {
|
||||||
|
if (other.runList != null)
|
||||||
|
return false;
|
||||||
|
} else if (!runList.equals(other.runList))
|
||||||
|
return false;
|
||||||
|
if (environment == null) {
|
||||||
|
if (other.environment != null)
|
||||||
|
return false;
|
||||||
|
} else if (!environment.equals(other.environment))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Node [name=" + name + ", runList=" + runList + ", normalAttributes=" + normalAttributes
|
||||||
|
+ ", defaultAttributes=" + defaultAttributes + ", overrideAttributes=" + overrideAttributes
|
||||||
|
+ ", chefEnvironment=" + environment + ", automaticAttributes=" + automaticAttributes + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.jclouds.io.payloads.FilePayload;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Bytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource object.
|
||||||
|
*/
|
||||||
|
public class Resource {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String name;
|
||||||
|
private URI url;
|
||||||
|
private byte[] checksum;
|
||||||
|
private String path;
|
||||||
|
private String specificity = "default";
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder url(URI url) {
|
||||||
|
this.url = checkNotNull(url, "url");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder checksum(byte[] checksum) {
|
||||||
|
this.checksum = checkNotNull(checksum, "checksum");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder path(String path) {
|
||||||
|
this.path = checkNotNull(path, "path");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder specificity(String specificity) {
|
||||||
|
this.specificity = checkNotNull(specificity, "specificity");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder fromPayload(FilePayload payload) {
|
||||||
|
checkNotNull(payload, "payload");
|
||||||
|
this.name(payload.getRawContent().getName());
|
||||||
|
this.checksum(payload.getContentMetadata().getContentMD5());
|
||||||
|
this.path(payload.getRawContent().getPath());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Resource build() {
|
||||||
|
return new Resource(name, url, checksum, path, specificity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final URI url;
|
||||||
|
private final byte[] checksum;
|
||||||
|
private final String path;
|
||||||
|
private final String specificity;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "name", "url", "checksum", "path", "specificity" })
|
||||||
|
protected Resource(String name, URI url, byte[] checksum, String path, String specificity) {
|
||||||
|
this.name = name;
|
||||||
|
this.url = url;
|
||||||
|
this.checksum = checksum;
|
||||||
|
this.path = path;
|
||||||
|
this.specificity = specificity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getChecksum() {
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpecificity() {
|
||||||
|
return specificity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + Arrays.hashCode(checksum);
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((path == null) ? 0 : path.hashCode());
|
||||||
|
result = prime * result + ((specificity == null) ? 0 : specificity.hashCode());
|
||||||
|
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Resource other = (Resource) obj;
|
||||||
|
if (!Arrays.equals(checksum, other.checksum))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (path == null) {
|
||||||
|
if (other.path != null)
|
||||||
|
return false;
|
||||||
|
} else if (!path.equals(other.path))
|
||||||
|
return false;
|
||||||
|
if (specificity == null) {
|
||||||
|
if (other.specificity != null)
|
||||||
|
return false;
|
||||||
|
} else if (!specificity.equals(other.specificity))
|
||||||
|
return false;
|
||||||
|
if (url == null) {
|
||||||
|
if (other.url != null)
|
||||||
|
return false;
|
||||||
|
} else if (!url.equals(other.url))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Resource [checksum=" + Bytes.asList(checksum) + ", name=" + name + ", path=" + path + ", specificity="
|
||||||
|
+ specificity + ", url=" + url + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Role object.
|
||||||
|
*/
|
||||||
|
public class Role {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder();
|
||||||
|
private ImmutableMap.Builder<String, JsonBall> defaultAttributes = ImmutableMap.builder();
|
||||||
|
private ImmutableList.Builder<String> runList = ImmutableList.builder();
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder description(String description) {
|
||||||
|
this.description = checkNotNull(description, "description");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder overrideAttribute(String key, JsonBall value) {
|
||||||
|
this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder overrideAttributes(Map<String, JsonBall> overrideAttributes) {
|
||||||
|
this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defaultAttribute(String key, JsonBall value) {
|
||||||
|
this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defaultAttributes(Map<String, JsonBall> defaultAttributes) {
|
||||||
|
this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder runListElement(String element) {
|
||||||
|
this.runList.add(checkNotNull(element, "element"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder runList(Iterable<String> runList) {
|
||||||
|
this.runList.addAll(checkNotNull(runList, "runList"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Role build() {
|
||||||
|
return new Role(name, description, defaultAttributes.build(), runList.build(), overrideAttributes.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String description;
|
||||||
|
@SerializedName("override_attributes")
|
||||||
|
private final Map<String, JsonBall> overrideAttributes;
|
||||||
|
@SerializedName("default_attributes")
|
||||||
|
private final Map<String, JsonBall> defaultAttributes;
|
||||||
|
@SerializedName("run_list")
|
||||||
|
private final List<String> runList;
|
||||||
|
|
||||||
|
// internal
|
||||||
|
@SerializedName("json_class")
|
||||||
|
private final String _jsonClass = "Chef::Role";
|
||||||
|
@SerializedName("chef_type")
|
||||||
|
private final String _chefType = "role";
|
||||||
|
|
||||||
|
@ConstructorProperties({ "name", "description", "default_attributes", "run_list", "override_attributes" })
|
||||||
|
protected Role(String name, String description, @Nullable Map<String, JsonBall> defaultAttributes,
|
||||||
|
@Nullable List<String> runList, @Nullable Map<String, JsonBall> overrideAttributes) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.defaultAttributes = copyOfOrEmpty(defaultAttributes);
|
||||||
|
this.runList = copyOfOrEmpty(runList);
|
||||||
|
this.overrideAttributes = copyOfOrEmpty(overrideAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getOverrideAttributes() {
|
||||||
|
return overrideAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JsonBall> getDefaultAttributes() {
|
||||||
|
return defaultAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRunList() {
|
||||||
|
return runList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode());
|
||||||
|
result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode());
|
||||||
|
result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode());
|
||||||
|
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode());
|
||||||
|
result = prime * result + ((runList == null) ? 0 : runList.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Role other = (Role) obj;
|
||||||
|
if (_chefType == null) {
|
||||||
|
if (other._chefType != null)
|
||||||
|
return false;
|
||||||
|
} else if (!_chefType.equals(other._chefType))
|
||||||
|
return false;
|
||||||
|
if (_jsonClass == null) {
|
||||||
|
if (other._jsonClass != null)
|
||||||
|
return false;
|
||||||
|
} else if (!_jsonClass.equals(other._jsonClass))
|
||||||
|
return false;
|
||||||
|
if (defaultAttributes == null) {
|
||||||
|
if (other.defaultAttributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!defaultAttributes.equals(other.defaultAttributes))
|
||||||
|
return false;
|
||||||
|
if (description == null) {
|
||||||
|
if (other.description != null)
|
||||||
|
return false;
|
||||||
|
} else if (!description.equals(other.description))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (overrideAttributes == null) {
|
||||||
|
if (other.overrideAttributes != null)
|
||||||
|
return false;
|
||||||
|
} else if (!overrideAttributes.equals(other.overrideAttributes))
|
||||||
|
return false;
|
||||||
|
if (runList == null) {
|
||||||
|
if (other.runList != null)
|
||||||
|
return false;
|
||||||
|
} else if (!runList.equals(other.runList))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Role [name=" + name + ", description=" + description + ", defaultAttributes=" + defaultAttributes
|
||||||
|
+ ", overrideAttributes=" + overrideAttributes + ", runList=" + runList + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sandbox object.
|
||||||
|
*/
|
||||||
|
public class Sandbox {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String rev;
|
||||||
|
private boolean isCompleted;
|
||||||
|
private Date createTime;
|
||||||
|
private ImmutableSet.Builder<String> checksums = ImmutableSet.builder();
|
||||||
|
private String name;
|
||||||
|
private String guid;
|
||||||
|
|
||||||
|
public Builder rev(String rev) {
|
||||||
|
this.rev = checkNotNull(rev, "rev");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder isCompleted(boolean isCompleted) {
|
||||||
|
this.isCompleted = isCompleted;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder createTime(Date createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder checksum(String checksum) {
|
||||||
|
this.checksums.add(checkNotNull(checksum, "checksum"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder checksums(Iterable<String> checksums) {
|
||||||
|
this.checksums.addAll(checkNotNull(checksums, "checksums"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder guid(String guid) {
|
||||||
|
this.guid = checkNotNull(guid, "guid");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sandbox build() {
|
||||||
|
return new Sandbox(rev, isCompleted, createTime, checksums.build(), name, guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SerializedName("_rev")
|
||||||
|
private final String rev;
|
||||||
|
@SerializedName("is_completed")
|
||||||
|
private final boolean isCompleted;
|
||||||
|
@SerializedName("create_time")
|
||||||
|
private final Date createTime;
|
||||||
|
private final Set<String> checksums;
|
||||||
|
private final String name;
|
||||||
|
private final String guid;
|
||||||
|
|
||||||
|
// internal
|
||||||
|
@SerializedName("json_class")
|
||||||
|
private final String _jsonClass = "Chef::Sandbox";
|
||||||
|
@SerializedName("chef_type")
|
||||||
|
private final String _chefType = "sandbox";
|
||||||
|
|
||||||
|
@ConstructorProperties({ "_rev", "is_completed", "create_time", "checksums", "name", "guid" })
|
||||||
|
protected Sandbox(String rev, boolean isCompleted, Date createTime, @Nullable Set<String> checksums, String name,
|
||||||
|
String guid) {
|
||||||
|
this.rev = rev;
|
||||||
|
this.isCompleted = isCompleted;
|
||||||
|
this.createTime = createTime;
|
||||||
|
this.checksums = copyOfOrEmpty(checksums);
|
||||||
|
this.name = name;
|
||||||
|
this.guid = guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRev() {
|
||||||
|
return rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompleted() {
|
||||||
|
return isCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getChecksums() {
|
||||||
|
return checksums;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGuid() {
|
||||||
|
return guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((checksums == null) ? 0 : checksums.hashCode());
|
||||||
|
result = prime * result + ((createTime == null) ? 0 : createTime.hashCode());
|
||||||
|
result = prime * result + ((guid == null) ? 0 : guid.hashCode());
|
||||||
|
result = prime * result + (isCompleted ? 1231 : 1237);
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((rev == null) ? 0 : rev.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Sandbox other = (Sandbox) obj;
|
||||||
|
if (checksums == null) {
|
||||||
|
if (other.checksums != null)
|
||||||
|
return false;
|
||||||
|
} else if (!checksums.equals(other.checksums))
|
||||||
|
return false;
|
||||||
|
if (createTime == null) {
|
||||||
|
if (other.createTime != null)
|
||||||
|
return false;
|
||||||
|
} else if (!createTime.equals(other.createTime))
|
||||||
|
return false;
|
||||||
|
if (guid == null) {
|
||||||
|
if (other.guid != null)
|
||||||
|
return false;
|
||||||
|
} else if (!guid.equals(other.guid))
|
||||||
|
return false;
|
||||||
|
if (isCompleted != other.isCompleted)
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (rev == null) {
|
||||||
|
if (other.rev != null)
|
||||||
|
return false;
|
||||||
|
} else if (!rev.equals(other.rev))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Sandbox [checksums=" + checksums + ", createTime=" + createTime + ", guid=" + guid + ", isCompleted="
|
||||||
|
+ isCompleted + ", name=" + name + ", rev=" + rev + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A result of a search.
|
||||||
|
*/
|
||||||
|
public class SearchResult<T> extends LinkedHashSet<T> {
|
||||||
|
private static final long serialVersionUID = 4000610660948065287L;
|
||||||
|
private long start;
|
||||||
|
|
||||||
|
SearchResult() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchResult(long start, Iterable<T> results) {
|
||||||
|
this.start = start;
|
||||||
|
Iterables.addAll(this, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the result position this started from from
|
||||||
|
*/
|
||||||
|
long getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An upload sandbox.
|
||||||
|
*/
|
||||||
|
public class UploadSandbox {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private URI uri;
|
||||||
|
private ImmutableMap.Builder<List<Byte>, ChecksumStatus> checksums = ImmutableMap.builder();
|
||||||
|
private String sandboxId;
|
||||||
|
|
||||||
|
public Builder uri(URI uri) {
|
||||||
|
this.uri = checkNotNull(uri, "uri");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder checksum(List<Byte> key, ChecksumStatus value) {
|
||||||
|
this.checksums.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder checksums(Map<List<Byte>, ChecksumStatus> checksums) {
|
||||||
|
this.checksums.putAll(checkNotNull(checksums, "checksums"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder sandboxId(String sandboxId) {
|
||||||
|
this.sandboxId = checkNotNull(sandboxId, "sandboxId");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UploadSandbox build() {
|
||||||
|
return new UploadSandbox(uri, checksums.build(), sandboxId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final URI uri;
|
||||||
|
private final Map<List<Byte>, ChecksumStatus> checksums;
|
||||||
|
@SerializedName("sandbox_id")
|
||||||
|
private final String sandboxId;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "uri", "checksums", "sandbox_id" })
|
||||||
|
protected UploadSandbox(URI uri, @Nullable Map<List<Byte>, ChecksumStatus> checksums, String sandboxId) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.checksums = copyOfOrEmpty(checksums);
|
||||||
|
this.sandboxId = sandboxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<List<Byte>, ChecksumStatus> getChecksums() {
|
||||||
|
return checksums;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSandboxId() {
|
||||||
|
return sandboxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((checksums == null) ? 0 : checksums.hashCode());
|
||||||
|
result = prime * result + ((sandboxId == null) ? 0 : sandboxId.hashCode());
|
||||||
|
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
UploadSandbox other = (UploadSandbox) obj;
|
||||||
|
if (checksums == null) {
|
||||||
|
if (other.checksums != null)
|
||||||
|
return false;
|
||||||
|
} else if (!checksums.equals(other.checksums))
|
||||||
|
return false;
|
||||||
|
if (sandboxId == null) {
|
||||||
|
if (other.sandboxId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!sandboxId.equals(other.sandboxId))
|
||||||
|
return false;
|
||||||
|
if (uri == null) {
|
||||||
|
if (other.uri != null)
|
||||||
|
return false;
|
||||||
|
} else if (!uri.equals(other.uri))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UploadSandbox [checksums=" + checksums + ", id=" + sandboxId + ", uri=" + uri + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* 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.filters;
|
||||||
|
|
||||||
|
import static com.google.common.base.Charsets.UTF_8;
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.hash.Hashing.sha1;
|
||||||
|
import static com.google.common.io.BaseEncoding.base64;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.date.TimeStamp;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.http.HttpException;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
|
import org.jclouds.http.HttpUtils;
|
||||||
|
import org.jclouds.http.internal.SignatureWire;
|
||||||
|
import org.jclouds.io.ByteStreams2;
|
||||||
|
import org.jclouds.io.Payload;
|
||||||
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.io.payloads.MultipartForm;
|
||||||
|
import org.jclouds.io.payloads.Part;
|
||||||
|
import org.jclouds.io.payloads.RSAEncryptingPayload;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.io.ByteSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ported from mixlib-authentication in order to sign Chef requests.
|
||||||
|
*
|
||||||
|
* @see <a href= "http://github.com/opscode/mixlib-authentication" />
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class SignedHeaderAuth implements HttpRequestFilter {
|
||||||
|
public static final String SIGNING_DESCRIPTION = "version=1.0";
|
||||||
|
|
||||||
|
private final SignatureWire signatureWire;
|
||||||
|
private final Supplier<Credentials> creds;
|
||||||
|
private final Supplier<PrivateKey> supplyKey;
|
||||||
|
private final Provider<String> timeStampProvider;
|
||||||
|
private final String emptyStringHash;
|
||||||
|
private final HttpUtils utils;
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(Constants.LOGGER_SIGNATURE)
|
||||||
|
Logger signatureLog = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SignedHeaderAuth(SignatureWire signatureWire, @org.jclouds.location.Provider Supplier<Credentials> creds,
|
||||||
|
Supplier<PrivateKey> supplyKey, @TimeStamp Provider<String> timeStampProvider, HttpUtils utils, Crypto crypto) {
|
||||||
|
this.signatureWire = checkNotNull(signatureWire, "signatureWire");
|
||||||
|
this.creds = checkNotNull(creds, "creds");
|
||||||
|
this.supplyKey = checkNotNull(supplyKey, "supplyKey");
|
||||||
|
this.timeStampProvider = checkNotNull(timeStampProvider, "timeStampProvider");
|
||||||
|
this.emptyStringHash = hashBody(Payloads.newStringPayload(""));
|
||||||
|
this.utils = checkNotNull(utils, "utils");
|
||||||
|
this.crypto = checkNotNull(crypto, "crypto");
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpRequest filter(HttpRequest input) throws HttpException {
|
||||||
|
HttpRequest request = input.toBuilder().endpoint(input.getEndpoint().toString().replace("%3F", "?")).build();
|
||||||
|
String contentHash = hashBody(request.getPayload());
|
||||||
|
Multimap<String, String> headers = ArrayListMultimap.create();
|
||||||
|
headers.put("X-Ops-Content-Hash", contentHash);
|
||||||
|
String timestamp = timeStampProvider.get();
|
||||||
|
String toSign = createStringToSign(request.getMethod(), hashPath(request.getEndpoint().getPath()), contentHash,
|
||||||
|
timestamp);
|
||||||
|
headers.put("X-Ops-Userid", creds.get().identity);
|
||||||
|
headers.put("X-Ops-Sign", SIGNING_DESCRIPTION);
|
||||||
|
request = calculateAndReplaceAuthorizationHeaders(request, toSign);
|
||||||
|
headers.put("X-Ops-Timestamp", timestamp);
|
||||||
|
utils.logRequest(signatureLog, request, "<<");
|
||||||
|
|
||||||
|
return request.toBuilder().replaceHeaders(headers).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
HttpRequest calculateAndReplaceAuthorizationHeaders(HttpRequest request, String toSign) throws HttpException {
|
||||||
|
String signature = sign(toSign);
|
||||||
|
if (signatureWire.enabled())
|
||||||
|
signatureWire.input(Strings2.toInputStream(signature));
|
||||||
|
String[] signatureLines = Iterables.toArray(Splitter.fixedLength(60).split(signature), String.class);
|
||||||
|
|
||||||
|
Multimap<String, String> headers = ArrayListMultimap.create();
|
||||||
|
for (int i = 0; i < signatureLines.length; i++) {
|
||||||
|
headers.put("X-Ops-Authorization-" + (i + 1), signatureLines[i]);
|
||||||
|
}
|
||||||
|
return request.toBuilder().replaceHeaders(headers).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String createStringToSign(String request, String hashedPath, String contentHash, String timestamp) {
|
||||||
|
|
||||||
|
return new StringBuilder().append("Method:").append(request).append("\n").append("Hashed Path:")
|
||||||
|
.append(hashedPath).append("\n").append("X-Ops-Content-Hash:").append(contentHash).append("\n")
|
||||||
|
.append("X-Ops-Timestamp:").append(timestamp).append("\n").append("X-Ops-UserId:")
|
||||||
|
.append(creds.get().identity).toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
String hashPath(String path) {
|
||||||
|
try {
|
||||||
|
return base64().encode(ByteSource.wrap(canonicalPath(path).getBytes(UTF_8)).hash(sha1()).asBytes());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Throwables.propagateIfPossible(e);
|
||||||
|
throw new HttpException("error creating sigature for path: " + path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the canonicalized path, which collapses multiple slashes (/) and
|
||||||
|
* removes a trailing slash unless the path is only "/"
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
String canonicalPath(String path) {
|
||||||
|
path = path.replaceAll("\\/+", "/");
|
||||||
|
return path.endsWith("/") && path.length() > 1 ? path.substring(0, path.length() - 1) : path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
String hashBody(Payload payload) {
|
||||||
|
if (payload == null)
|
||||||
|
return emptyStringHash;
|
||||||
|
payload = useTheFilePartIfForm(payload);
|
||||||
|
checkArgument(payload != null, "payload was null");
|
||||||
|
checkArgument(payload.isRepeatable(), "payload must be repeatable: " + payload);
|
||||||
|
try {
|
||||||
|
return base64().encode(ByteStreams2.hashAndClose(payload.getInput(), sha1()).asBytes());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Throwables.propagateIfPossible(e);
|
||||||
|
throw new HttpException("error creating sigature for payload: " + payload, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Payload useTheFilePartIfForm(Payload payload) {
|
||||||
|
if (payload instanceof MultipartForm) {
|
||||||
|
Iterable<? extends Part> parts = MultipartForm.class.cast(payload).getRawContent();
|
||||||
|
try {
|
||||||
|
payload = Iterables.find(parts, new Predicate<Part>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Part input) {
|
||||||
|
return "file".equals(input.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sign(String toSign) {
|
||||||
|
try {
|
||||||
|
byte[] encrypted = ByteStreams2.toByteArrayAndClose(new RSAEncryptingPayload(crypto, Payloads.newStringPayload(toSign), supplyKey.get()).openStream());
|
||||||
|
return base64().encode(encrypted);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new HttpException("error signing request", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.domain.DatabagItem;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Retrieves the bootstrap configuration for a specific group
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class BootstrapConfigForGroup implements Function<String, DatabagItem> {
|
||||||
|
public static final Type BOOTSTRAP_CONFIG_TYPE = new TypeLiteral<Map<String, JsonBall>>() {
|
||||||
|
}.getType();
|
||||||
|
private final ChefApi api;
|
||||||
|
private final String databag;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public BootstrapConfigForGroup(@Named(CHEF_BOOTSTRAP_DATABAG) String databag, ChefApi api) {
|
||||||
|
this.databag = checkNotNull(databag, "databag");
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabagItem apply(String from) {
|
||||||
|
DatabagItem bootstrapConfig = api.getDatabagItem(databag, from);
|
||||||
|
checkState(bootstrapConfig != null, "databag item %s/%s not found", databag, from);
|
||||||
|
return bootstrapConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Sets.newHashSet;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Generates a client relevant for a particular group
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ClientForGroup implements Function<String, Client> {
|
||||||
|
private final ChefApi chefApi;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ClientForGroup(ChefApi chefApi) {
|
||||||
|
this.chefApi = checkNotNull(chefApi, "chefApi");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Client apply(String from) {
|
||||||
|
String clientName = findNextClientName(chefApi.listClients(), from + "-client-%02d");
|
||||||
|
Client client = chefApi.createClient(clientName);
|
||||||
|
// response from create only includes the key
|
||||||
|
return Client.builder() //
|
||||||
|
.clientname(clientName) //
|
||||||
|
.name(clientName) //
|
||||||
|
.isValidator(false) //
|
||||||
|
.privateKey(client.getPrivateKey()) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String findNextClientName(Set<String> clients, String pattern) {
|
||||||
|
String clientName;
|
||||||
|
Set<String> names = newHashSet(clients);
|
||||||
|
int index = 0;
|
||||||
|
while (true) {
|
||||||
|
clientName = String.format(pattern, index++);
|
||||||
|
if (!names.contains(clientName))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.config.InstallChef;
|
||||||
|
import org.jclouds.chef.config.Validator;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
import org.jclouds.scriptbuilder.ExitInsteadOfReturn;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Generates a bootstrap script relevant for a particular group
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class GroupToBootScript implements Function<String, Statement> {
|
||||||
|
private static final Pattern newLinePattern = Pattern.compile("(\\r\\n)|(\\n)");
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static final Type RUN_LIST_TYPE = new TypeLiteral<Map<String, List<String>>>() {
|
||||||
|
}.getType();
|
||||||
|
private final Supplier<URI> endpoint;
|
||||||
|
private final Json json;
|
||||||
|
private final CacheLoader<String, ? extends JsonBall> bootstrapConfigForGroup;
|
||||||
|
private final Statement installChef;
|
||||||
|
private final Optional<String> validatorName;
|
||||||
|
private final Optional<PrivateKey> validatorCredential;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public GroupToBootScript(@Provider Supplier<URI> endpoint, Json json,
|
||||||
|
CacheLoader<String, ? extends JsonBall> bootstrapConfigForGroup,
|
||||||
|
@InstallChef Statement installChef, @Validator Optional<String> validatorName,
|
||||||
|
@Validator Optional<PrivateKey> validatorCredential) {
|
||||||
|
this.endpoint = checkNotNull(endpoint, "endpoint");
|
||||||
|
this.json = checkNotNull(json, "json");
|
||||||
|
this.bootstrapConfigForGroup = checkNotNull(bootstrapConfigForGroup, "bootstrapConfigForGroup");
|
||||||
|
this.installChef = checkNotNull(installChef, "installChef");
|
||||||
|
this.validatorName = checkNotNull(validatorName, "validatorName");
|
||||||
|
this.validatorCredential = checkNotNull(validatorCredential, validatorCredential);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement apply(String group) {
|
||||||
|
checkNotNull(group, "group");
|
||||||
|
String validatorClientName = validatorName.get();
|
||||||
|
PrivateKey validatorKey = validatorCredential.get();
|
||||||
|
|
||||||
|
JsonBall bootstrapConfig = null;
|
||||||
|
try {
|
||||||
|
bootstrapConfig = bootstrapConfigForGroup.load(group);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw propagate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, JsonBall> config = json.fromJson(bootstrapConfig.toString(),
|
||||||
|
BootstrapConfigForGroup.BOOTSTRAP_CONFIG_TYPE);
|
||||||
|
Optional<JsonBall> environment = Optional.fromNullable(config.get("environment"));
|
||||||
|
|
||||||
|
String chefConfigDir = "{root}etc{fs}chef";
|
||||||
|
Statement createChefConfigDir = exec("{md} " + chefConfigDir);
|
||||||
|
Statement createClientRb = appendFile(chefConfigDir + "{fs}client.rb", ImmutableList.of("require 'rubygems'",
|
||||||
|
"require 'ohai'", "o = Ohai::System.new", "o.all_plugins",
|
||||||
|
String.format("node_name \"%s-\" + o[:ipaddress]", group), "log_level :info", "log_location STDOUT",
|
||||||
|
String.format("validation_client_name \"%s\"", validatorClientName),
|
||||||
|
String.format("chef_server_url \"%s\"", endpoint.get())));
|
||||||
|
|
||||||
|
Statement createValidationPem = appendFile(chefConfigDir + "{fs}validation.pem",
|
||||||
|
Splitter.on(newLinePattern).split(Pems.pem(validatorKey)));
|
||||||
|
|
||||||
|
String chefBootFile = chefConfigDir + "{fs}first-boot.json";
|
||||||
|
Statement createFirstBoot = appendFile(chefBootFile, Collections.singleton(json.toJson(bootstrapConfig)));
|
||||||
|
|
||||||
|
ImmutableMap.Builder<String, String> options = ImmutableMap.builder();
|
||||||
|
options.put("-j", chefBootFile);
|
||||||
|
if (environment.isPresent()) {
|
||||||
|
options.put("-E", environment.get().toString());
|
||||||
|
}
|
||||||
|
String strOptions = Joiner.on(' ').withKeyValueSeparator(" ").join(options.build());
|
||||||
|
Statement runChef = exec("chef-client " + strOptions);
|
||||||
|
|
||||||
|
return newStatementList(new ExitInsteadOfReturn(installChef), createChefConfigDir, createClientRb, createValidationPem,
|
||||||
|
createFirstBoot, runChef);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.config.CookbookParser;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a cookbook definition from a Json response, taking care of using the
|
||||||
|
* appropriate parser.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookDefinitionCheckingChefVersion implements Function<HttpResponse, Set<String>> {
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
final Function<HttpResponse, Set<String>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookDefinitionCheckingChefVersion(@CookbookParser Function<HttpResponse, Set<String>> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(HttpResponse response) {
|
||||||
|
return parser.apply(response);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.CookbookDefinition;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a cookbook definition from a Json response, assuming a Chef Server >=
|
||||||
|
* 0.10.8.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookDefinitionFromJson implements Function<HttpResponse, Set<String>> {
|
||||||
|
|
||||||
|
/** Parser for responses from chef server >= 0.10.8 */
|
||||||
|
private final ParseJson<Map<String, CookbookDefinition>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookDefinitionFromJson(ParseJson<Map<String, CookbookDefinition>> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(HttpResponse response) {
|
||||||
|
return parser.apply(response).keySet();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import org.jclouds.chef.domain.CookbookDefinition;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the cookbook versions in a Chef Server >= 0.10.8.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookDefinitionFromJsonv10 implements Function<HttpResponse, CookbookDefinition> {
|
||||||
|
|
||||||
|
/** Parser for responses from chef server >= 0.10.8 */
|
||||||
|
private final ParseJson<Map<String, CookbookDefinition>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookDefinitionFromJsonv10(ParseJson<Map<String, CookbookDefinition>> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CookbookDefinition apply(HttpResponse response) {
|
||||||
|
Map<String, CookbookDefinition> result = parser.apply(response);
|
||||||
|
String cookbookName = result.keySet().iterator().next();
|
||||||
|
CookbookDefinition def = result.values().iterator().next();
|
||||||
|
return CookbookDefinition.builder() //
|
||||||
|
.from(def) //
|
||||||
|
.name(cookbookName) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import org.jclouds.chef.domain.CookbookDefinition;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the cookbook versions in a Chef Server >= 0.10.8.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookDefinitionListFromJsonv10 implements Function<HttpResponse, Set<CookbookDefinition>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for responses from chef server >= 0.10.8
|
||||||
|
*/
|
||||||
|
private final ParseJson<Map<String, CookbookDefinition>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookDefinitionListFromJsonv10(ParseJson<Map<String, CookbookDefinition>> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<CookbookDefinition> apply(HttpResponse response) {
|
||||||
|
Set<Map.Entry<String, CookbookDefinition>> result = parser.apply(response).entrySet();
|
||||||
|
return newLinkedHashSet(transform(result, new Function<Map.Entry<String, CookbookDefinition>, CookbookDefinition>() {
|
||||||
|
@Override
|
||||||
|
public CookbookDefinition apply(Map.Entry<String, CookbookDefinition> input) {
|
||||||
|
String cookbookName = input.getKey();
|
||||||
|
CookbookDefinition def = input.getValue();
|
||||||
|
return CookbookDefinition.builder() //
|
||||||
|
.from(def) //
|
||||||
|
.name(cookbookName) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.config.CookbookVersionsParser;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a cookbook versions from a Json response, taking care of using the
|
||||||
|
* appropriate parser.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookVersionsCheckingChefVersion implements Function<HttpResponse, Set<String>> {
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
final Function<HttpResponse, Set<String>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookVersionsCheckingChefVersion(@CookbookVersionsParser Function<HttpResponse, Set<String>> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(HttpResponse response) {
|
||||||
|
return parser.apply(response);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import static com.google.common.collect.Iterables.getFirst;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the cookbook versions in a Chef Server <= 0.9.8.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookVersionsV09FromJson implements Function<HttpResponse, Set<String>> {
|
||||||
|
|
||||||
|
private final ParseJson<Map<String, Set<String>>> json;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookVersionsV09FromJson(ParseJson<Map<String, Set<String>>> json) {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(HttpResponse response) {
|
||||||
|
return getFirst(json.apply(response).values(), null);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.CookbookDefinition;
|
||||||
|
import org.jclouds.chef.domain.CookbookDefinition.Version;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import static com.google.common.collect.Iterables.getFirst;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the cookbook versions in a Chef Server >= 0.10.8.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookVersionsV10FromJson implements Function<HttpResponse, Set<String>> {
|
||||||
|
|
||||||
|
/** Parser for responses from chef server >= 0.10.8 */
|
||||||
|
private final ParseJson<Map<String, CookbookDefinition>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseCookbookVersionsV10FromJson(ParseJson<Map<String, CookbookDefinition>> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(HttpResponse response) {
|
||||||
|
CookbookDefinition def = getFirst(parser.apply(response).values(), null);
|
||||||
|
return newLinkedHashSet(transform(def.getVersions(), new Function<Version, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(Version input) {
|
||||||
|
return input.getVersion();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ReturnStringIf2xx;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseErrorFromJsonOrReturnBody implements Function<HttpResponse, String> {
|
||||||
|
Pattern pattern = Pattern.compile(".*\\[\"([^\"]+)\"\\].*");
|
||||||
|
private final ReturnStringIf2xx returnStringIf200;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseErrorFromJsonOrReturnBody(ReturnStringIf2xx returnStringIf200) {
|
||||||
|
this.returnStringIf200 = returnStringIf200;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(HttpResponse response) {
|
||||||
|
String content = returnStringIf200.apply(response);
|
||||||
|
if (content == null)
|
||||||
|
return null;
|
||||||
|
return parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String parse(String in) {
|
||||||
|
Matcher matcher = pattern.matcher(in);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return matcher.group(1);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseKeySetFromJson implements Function<HttpResponse, Set<String>> {
|
||||||
|
|
||||||
|
private final ParseJson<Map<String, String>> json;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseKeySetFromJson(ParseJson<Map<String, String>> json) {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(HttpResponse response) {
|
||||||
|
return json.apply(response).keySet();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.functions;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseSearchClientsFromJson extends ParseSearchResultFromJson<Client> {
|
||||||
|
|
||||||
|
// TODO add generic json parser detector
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseSearchClientsFromJson(ParseJson<Response<Client>> json) {
|
||||||
|
super(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.DatabagItem;
|
||||||
|
import org.jclouds.chef.domain.SearchResult;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the search result into a {@link DatabagItem} object.
|
||||||
|
* <p>
|
||||||
|
* When searching databags, the items are contained inside the
|
||||||
|
* <code>raw_data</code> list.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseSearchDatabagFromJson implements Function<HttpResponse, SearchResult<DatabagItem>> {
|
||||||
|
|
||||||
|
private final ParseJson<Response> responseParser;
|
||||||
|
|
||||||
|
private final Json json;
|
||||||
|
|
||||||
|
static class Row {
|
||||||
|
@SerializedName("raw_data")
|
||||||
|
JsonBall rawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Response {
|
||||||
|
long start;
|
||||||
|
List<Row> rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseSearchDatabagFromJson(ParseJson<Response> responseParser, Json json) {
|
||||||
|
this.responseParser = responseParser;
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<DatabagItem> apply(HttpResponse response) {
|
||||||
|
Response returnVal = responseParser.apply(response);
|
||||||
|
Iterable<DatabagItem> items = transform(returnVal.rows, new Function<Row, DatabagItem>() {
|
||||||
|
@Override
|
||||||
|
public DatabagItem apply(Row input) {
|
||||||
|
return json.fromJson(input.rawData.toString(), DatabagItem.class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SearchResult<DatabagItem>(returnVal.start, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.functions;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Environment;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseSearchEnvironmentsFromJson extends ParseSearchResultFromJson<Environment> {
|
||||||
|
|
||||||
|
// TODO add generic json parser detector
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseSearchEnvironmentsFromJson(ParseJson<Response<Environment>> json) {
|
||||||
|
super(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.functions;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseSearchNodesFromJson extends ParseSearchResultFromJson<Node> {
|
||||||
|
|
||||||
|
// TODO add generic json parser detector
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseSearchNodesFromJson(ParseJson<Response<Node>> json) {
|
||||||
|
super(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.SearchResult;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseSearchResultFromJson<T> implements Function<HttpResponse, SearchResult<T>> {
|
||||||
|
|
||||||
|
private final ParseJson<Response<T>> json;
|
||||||
|
|
||||||
|
static class Response<T> {
|
||||||
|
long start;
|
||||||
|
List<T> rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseSearchResultFromJson(ParseJson<Response<T>> json) {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<T> apply(HttpResponse response) {
|
||||||
|
Response<T> returnVal = json.apply(response);
|
||||||
|
return new SearchResult<T>(returnVal.start, returnVal.rows);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.functions;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Role;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseSearchRolesFromJson extends ParseSearchResultFromJson<Role> {
|
||||||
|
|
||||||
|
// TODO add generic json parser detector
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseSearchRolesFromJson(ParseJson<Response<Role>> json) {
|
||||||
|
super(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.DatabagItem;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the run-list for a specific group
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class RunListForGroup implements Function<String, List<String>> {
|
||||||
|
public static final Type RUN_LIST_TYPE = new TypeLiteral<List<String>>() {
|
||||||
|
}.getType();
|
||||||
|
private final BootstrapConfigForGroup bootstrapConfigForGroup;
|
||||||
|
|
||||||
|
private final Json json;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public RunListForGroup(BootstrapConfigForGroup bootstrapConfigForGroup, Json json) {
|
||||||
|
this.bootstrapConfigForGroup = checkNotNull(bootstrapConfigForGroup, "bootstrapConfigForGroup");
|
||||||
|
this.json = checkNotNull(json, "json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> apply(String from) {
|
||||||
|
DatabagItem bootstrapConfig = bootstrapConfigForGroup.apply(from);
|
||||||
|
Map<String, JsonBall> config = json.fromJson(bootstrapConfig.toString(),
|
||||||
|
BootstrapConfigForGroup.BOOTSTRAP_CONFIG_TYPE);
|
||||||
|
JsonBall runlist = config.get("run_list");
|
||||||
|
return json.fromJson(runlist.toString(), RUN_LIST_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the uri field of the given {@link Resource}.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class UriForResource implements Function<Object, URI> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI apply(Object input) {
|
||||||
|
checkArgument(checkNotNull(input, "input") instanceof Resource,
|
||||||
|
"This function can only be applied to Resource objects");
|
||||||
|
return ((Resource) input).getUrl();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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.handlers;
|
||||||
|
|
||||||
|
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.HttpRetryHandler;
|
||||||
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow for eventual consistency on sandbox requests.
|
||||||
|
*/
|
||||||
|
public class ChefApiErrorRetryHandler implements HttpRetryHandler {
|
||||||
|
|
||||||
|
@Inject(optional = true)
|
||||||
|
@Named(Constants.PROPERTY_MAX_RETRIES)
|
||||||
|
private int retryCountLimit = 5;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ChefApiErrorRetryHandler(BackoffLimitedRetryHandler backoffLimitedRetryHandler) {
|
||||||
|
this.backoffLimitedRetryHandler = backoffLimitedRetryHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||||
|
if (command.getFailureCount() > retryCountLimit)
|
||||||
|
return false;
|
||||||
|
if (response.getStatusCode() == 400 && command.getCurrentRequest().getMethod().equals("PUT")
|
||||||
|
&& command.getCurrentRequest().getEndpoint().getPath().indexOf("sandboxes") != -1) {
|
||||||
|
if (response.getPayload() != null) {
|
||||||
|
String error = new String(closeClientButKeepContentStream(response));
|
||||||
|
if (error != null && error.indexOf("was not uploaded") != -1) {
|
||||||
|
return backoffLimitedRetryHandler.shouldRetryRequest(command, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.handlers;
|
||||||
|
|
||||||
|
import static org.jclouds.util.Closeables2.closeQuietly;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.functions.ParseErrorFromJsonOrReturnBody;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will parse and set an appropriate exception on the command object.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ChefErrorHandler implements HttpErrorHandler {
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
private final ParseErrorFromJsonOrReturnBody errorParser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ChefErrorHandler(ParseErrorFromJsonOrReturnBody errorParser) {
|
||||||
|
this.errorParser = errorParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleError(HttpCommand command, HttpResponse response) {
|
||||||
|
String message = errorParser.apply(response);
|
||||||
|
Exception exception = new HttpResponseException(command, response, message);
|
||||||
|
try {
|
||||||
|
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
|
||||||
|
response.getStatusLine());
|
||||||
|
switch (response.getStatusCode()) {
|
||||||
|
case 401:
|
||||||
|
case 403:
|
||||||
|
exception = new AuthorizationException(message, exception);
|
||||||
|
break;
|
||||||
|
case 404:
|
||||||
|
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||||
|
exception = new ResourceNotFoundException(message, exception);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
closeQuietly(response.getPayload());
|
||||||
|
command.setException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,299 @@
|
||||||
|
/*
|
||||||
|
* 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.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.ChefContext;
|
||||||
|
import org.jclouds.chef.ChefService;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.BootstrapConfig;
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
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.functions.BootstrapConfigForGroup;
|
||||||
|
import org.jclouds.chef.functions.GroupToBootScript;
|
||||||
|
import org.jclouds.chef.functions.RunListForGroup;
|
||||||
|
import org.jclouds.chef.strategy.CleanupStaleNodesAndClients;
|
||||||
|
import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes;
|
||||||
|
import org.jclouds.chef.strategy.DeleteAllClientsInList;
|
||||||
|
import org.jclouds.chef.strategy.DeleteAllNodesInList;
|
||||||
|
import org.jclouds.chef.strategy.ListClients;
|
||||||
|
import org.jclouds.chef.strategy.ListCookbookVersions;
|
||||||
|
import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment;
|
||||||
|
import org.jclouds.chef.strategy.ListEnvironments;
|
||||||
|
import org.jclouds.chef.strategy.ListNodes;
|
||||||
|
import org.jclouds.chef.strategy.ListNodesInEnvironment;
|
||||||
|
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.io.ByteStreams2;
|
||||||
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.io.payloads.RSADecryptingPayload;
|
||||||
|
import org.jclouds.io.payloads.RSAEncryptingPayload;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.io.InputSupplier;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class BaseChefService implements ChefService {
|
||||||
|
|
||||||
|
private final ChefContext chefContext;
|
||||||
|
private final ChefApi api;
|
||||||
|
private final CleanupStaleNodesAndClients cleanupStaleNodesAndClients;
|
||||||
|
private final CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes;
|
||||||
|
private final DeleteAllNodesInList deleteAllNodesInList;
|
||||||
|
private final ListNodes listNodes;
|
||||||
|
private final DeleteAllClientsInList deleteAllClientsInList;
|
||||||
|
private final ListClients listClients;
|
||||||
|
private final UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode;
|
||||||
|
private final Supplier<PrivateKey> privateKey;
|
||||||
|
private final GroupToBootScript groupToBootScript;
|
||||||
|
private final String databag;
|
||||||
|
private final BootstrapConfigForGroup bootstrapConfigForGroup;
|
||||||
|
private final RunListForGroup runListForGroup;
|
||||||
|
private final ListCookbookVersions listCookbookVersions;
|
||||||
|
private final ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment;
|
||||||
|
private final ListEnvironments listEnvironments;
|
||||||
|
private final ListNodesInEnvironment listNodesInEnvironment;
|
||||||
|
private final Json json;
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected BaseChefService(ChefContext chefContext, ChefApi api,
|
||||||
|
CleanupStaleNodesAndClients cleanupStaleNodesAndClients,
|
||||||
|
CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes,
|
||||||
|
DeleteAllNodesInList deleteAllNodesInList, ListNodes listNodes, DeleteAllClientsInList deleteAllClientsInList,
|
||||||
|
ListClients listClients, ListCookbookVersions listCookbookVersions,
|
||||||
|
UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode, Supplier<PrivateKey> privateKey,
|
||||||
|
@Named(CHEF_BOOTSTRAP_DATABAG) String databag, GroupToBootScript groupToBootScript,
|
||||||
|
BootstrapConfigForGroup bootstrapConfigForGroup, RunListForGroup runListForGroup,
|
||||||
|
ListEnvironments listEnvironments, ListNodesInEnvironment listNodesInEnvironment,
|
||||||
|
ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment, Json json, Crypto crypto) {
|
||||||
|
this.chefContext = checkNotNull(chefContext, "chefContext");
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
this.cleanupStaleNodesAndClients = checkNotNull(cleanupStaleNodesAndClients, "cleanupStaleNodesAndClients");
|
||||||
|
this.createNodeAndPopulateAutomaticAttributes = checkNotNull(createNodeAndPopulateAutomaticAttributes,
|
||||||
|
"createNodeAndPopulateAutomaticAttributes");
|
||||||
|
this.deleteAllNodesInList = checkNotNull(deleteAllNodesInList, "deleteAllNodesInList");
|
||||||
|
this.listNodes = checkNotNull(listNodes, "listNodes");
|
||||||
|
this.deleteAllClientsInList = checkNotNull(deleteAllClientsInList, "deleteAllClientsInList");
|
||||||
|
this.listClients = checkNotNull(listClients, "listClients");
|
||||||
|
this.listCookbookVersions = checkNotNull(listCookbookVersions, "listCookbookVersions");
|
||||||
|
this.updateAutomaticAttributesOnNode = checkNotNull(updateAutomaticAttributesOnNode,
|
||||||
|
"updateAutomaticAttributesOnNode");
|
||||||
|
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||||
|
this.groupToBootScript = checkNotNull(groupToBootScript, "groupToBootScript");
|
||||||
|
this.databag = checkNotNull(databag, "databag");
|
||||||
|
this.bootstrapConfigForGroup = checkNotNull(bootstrapConfigForGroup, "bootstrapConfigForGroup");
|
||||||
|
this.runListForGroup = checkNotNull(runListForGroup, "runListForGroup");
|
||||||
|
this.listEnvironments = checkNotNull(listEnvironments, "listEnvironments");
|
||||||
|
this.listNodesInEnvironment = checkNotNull(listNodesInEnvironment, "listNodesInEnvironment");
|
||||||
|
this.listCookbookVersionsInEnvironment = checkNotNull(listCookbookVersionsInEnvironment, "listCookbookVersionsInEnvironment");
|
||||||
|
this.json = checkNotNull(json, "json");
|
||||||
|
this.crypto = checkNotNull(crypto, "crypto");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChefContext getContext() {
|
||||||
|
return chefContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] encrypt(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||||
|
return ByteStreams2.toByteArrayAndClose(new RSAEncryptingPayload(crypto, Payloads.newPayload(supplier.getInput()), privateKey
|
||||||
|
.get()).openStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] decrypt(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||||
|
return ByteStreams2.toByteArrayAndClose(new RSADecryptingPayload(crypto, Payloads.newPayload(supplier.getInput()), privateKey
|
||||||
|
.get()).openStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
String buildBootstrapConfiguration(BootstrapConfig bootstrapConfig) {
|
||||||
|
checkNotNull(bootstrapConfig, "bootstrapConfig must not be null");
|
||||||
|
|
||||||
|
Map<String, Object> configMap = Maps.newHashMap();
|
||||||
|
configMap.put("run_list", bootstrapConfig.getRunList());
|
||||||
|
|
||||||
|
if (bootstrapConfig.getEnvironment().isPresent()) {
|
||||||
|
configMap.put("environment", bootstrapConfig.getEnvironment().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bootstrapConfig.getAttribtues().isPresent()) {
|
||||||
|
Map<String, Object> attributes = json.fromJson(bootstrapConfig.getAttribtues().get().toString(),
|
||||||
|
BootstrapConfigForGroup.BOOTSTRAP_CONFIG_TYPE);
|
||||||
|
configMap.putAll(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.toJson(configMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement createBootstrapScriptForGroup(String group) {
|
||||||
|
return groupToBootScript.apply(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBootstrapConfigForGroup(String group, BootstrapConfig bootstrapConfig) {
|
||||||
|
try {
|
||||||
|
api.createDatabag(databag);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String jsonConfig = buildBootstrapConfiguration(bootstrapConfig);
|
||||||
|
DatabagItem runlist = new DatabagItem(group, jsonConfig);
|
||||||
|
|
||||||
|
if (api.getDatabagItem(databag, group) == null) {
|
||||||
|
api.createDatabagItem(databag, runlist);
|
||||||
|
} else {
|
||||||
|
api.updateDatabagItem(databag, runlist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getRunListForGroup(String group) {
|
||||||
|
return runListForGroup.apply(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonBall getBootstrapConfigForGroup(String group) {
|
||||||
|
return bootstrapConfigForGroup.apply(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanupStaleNodesAndClients(String prefix, int secondsStale) {
|
||||||
|
cleanupStaleNodesAndClients.execute(prefix, secondsStale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable<String> runList) {
|
||||||
|
return createNodeAndPopulateAutomaticAttributes.execute(nodeName, runList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAutomaticAttributesOnNode(String nodeName) {
|
||||||
|
updateAutomaticAttributesOnNode.execute(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAllNodesInList(Iterable<String> names) {
|
||||||
|
deleteAllNodesInList.execute(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAllClientsInList(Iterable<String> names) {
|
||||||
|
deleteAllClientsInList.execute(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> listNodes() {
|
||||||
|
return listNodes.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> listNodes(ExecutorService executorService) {
|
||||||
|
return listNodes.execute(executorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Client> listClients() {
|
||||||
|
return listClients.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Client> listClients(ExecutorService executorService) {
|
||||||
|
return listClients.execute(executorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersions() {
|
||||||
|
return listCookbookVersions.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Iterable<? extends CookbookVersion> listCookbookVersions(
|
||||||
|
ExecutorService executorService) {
|
||||||
|
return listCookbookVersions.execute(executorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName) {
|
||||||
|
return listCookbookVersionsInEnvironment.execute(environmentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName,
|
||||||
|
ExecutorService executorService) {
|
||||||
|
return listCookbookVersionsInEnvironment.execute(executorService, environmentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName,
|
||||||
|
String numVersions) {
|
||||||
|
return listCookbookVersionsInEnvironment.execute(environmentName, numVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName,
|
||||||
|
String numVersions, ExecutorService executorService) {
|
||||||
|
return listCookbookVersionsInEnvironment.execute(executorService, environmentName, numVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Environment> listEnvironments() {
|
||||||
|
return listEnvironments.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> listNodesInEnvironment(String environmentName) {
|
||||||
|
return listNodesInEnvironment.execute(environmentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> listNodesInEnvironment(String environmentName, ExecutorService executorService) {
|
||||||
|
return listNodesInEnvironment.execute(executorService, environmentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Context;
|
||||||
|
import org.jclouds.chef.ChefContext;
|
||||||
|
import org.jclouds.chef.ChefService;
|
||||||
|
import org.jclouds.internal.BaseView;
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ChefContextImpl extends BaseView implements ChefContext {
|
||||||
|
private final ChefService chefService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected ChefContextImpl(@Provider Context backend, @Provider TypeToken<? extends Context> backendType,
|
||||||
|
ChefService chefService) {
|
||||||
|
super(backend, backendType);
|
||||||
|
this.chefService = checkNotNull(chefService, "chefService");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChefService getChefService() {
|
||||||
|
return chefService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
delegate().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for the create client method.
|
||||||
|
*/
|
||||||
|
public class CreateClientOptions implements Cloneable {
|
||||||
|
/** Administrator flag. This flag will be ignored in Opscode Hosted Chef. */
|
||||||
|
private boolean admin;
|
||||||
|
|
||||||
|
public CreateClientOptions() {
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateClientOptions(final boolean admin) {
|
||||||
|
super();
|
||||||
|
this.admin = admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAdmin() {
|
||||||
|
return admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateClientOptions admin() {
|
||||||
|
this.admin = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object clone() throws CloneNotSupportedException {
|
||||||
|
return new CreateClientOptions(admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[admin=" + admin + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* @see CreateClientOptions#admin()
|
||||||
|
*/
|
||||||
|
public static CreateClientOptions admin() {
|
||||||
|
CreateClientOptions options = new CreateClientOptions();
|
||||||
|
return options.admin();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for the search api.
|
||||||
|
*/
|
||||||
|
public class SearchOptions extends BaseHttpRequestOptions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A valid search string.
|
||||||
|
*/
|
||||||
|
public SearchOptions query(String query) {
|
||||||
|
this.queryParameters.put("q", checkNotNull(query, "query"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sort string, such as 'name DESC'.
|
||||||
|
*/
|
||||||
|
public SearchOptions sort(String sort) {
|
||||||
|
this.queryParameters.put("sort", checkNotNull(sort, "sort"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of rows to return.
|
||||||
|
*/
|
||||||
|
public SearchOptions rows(int rows) {
|
||||||
|
this.queryParameters.put("rows", String.valueOf(rows));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result number to start from.
|
||||||
|
*/
|
||||||
|
public SearchOptions start(int start) {
|
||||||
|
this.queryParameters.put("start", String.valueOf(start));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SearchOptions#query(String)
|
||||||
|
*/
|
||||||
|
public static SearchOptions query(String query) {
|
||||||
|
SearchOptions options = new SearchOptions();
|
||||||
|
return options.query(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SearchOptions#sort(String)
|
||||||
|
*/
|
||||||
|
public static SearchOptions start(String start) {
|
||||||
|
SearchOptions options = new SearchOptions();
|
||||||
|
return options.sort(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SearchOptions#rows(int)
|
||||||
|
*/
|
||||||
|
public static SearchOptions rows(int rows) {
|
||||||
|
SearchOptions options = new SearchOptions();
|
||||||
|
return options.rows(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SearchOptions#start(int)
|
||||||
|
*/
|
||||||
|
public static SearchOptions start(int start) {
|
||||||
|
SearchOptions options = new SearchOptions();
|
||||||
|
return options.start(start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.predicates;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.any;
|
||||||
|
import static com.google.common.collect.Iterables.get;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.LinkedListMultimap;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for cookbook filters (predicates).
|
||||||
|
*
|
||||||
|
* This class has static methods that create customized predicates to use with
|
||||||
|
* {@link org.jclouds.chef.ChefService}.
|
||||||
|
*/
|
||||||
|
public class CookbookVersionPredicates {
|
||||||
|
/**
|
||||||
|
* @see #containsRecipes
|
||||||
|
*/
|
||||||
|
public static Predicate<CookbookVersion> containsRecipe(String recipe) {
|
||||||
|
return containsRecipes(checkNotNull(recipe, "recipe must be defined"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that the default recipe of a cookbook is its name. Otherwise, you
|
||||||
|
* prefix the recipe with the name of the cookbook. ex. {@code apache2} will
|
||||||
|
* be the default recipe where {@code apache2::mod_proxy} is a specific one
|
||||||
|
* in the cookbook.
|
||||||
|
*
|
||||||
|
* @param recipes
|
||||||
|
* names of the recipes.
|
||||||
|
* @return true if the cookbook version contains a recipe in the list.
|
||||||
|
*/
|
||||||
|
public static Predicate<CookbookVersion> containsRecipes(String... recipes) {
|
||||||
|
checkNotNull(recipes, "recipes must be defined");
|
||||||
|
final Multimap<String, String> search = LinkedListMultimap.create();
|
||||||
|
for (String recipe : recipes) {
|
||||||
|
if (recipe.indexOf("::") != -1) {
|
||||||
|
Iterable<String> nameRecipe = Splitter.on("::").split(recipe);
|
||||||
|
search.put(get(nameRecipe, 0), get(nameRecipe, 1) + ".rb");
|
||||||
|
} else {
|
||||||
|
search.put(recipe, "default.rb");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Predicate<CookbookVersion>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(final CookbookVersion cookbookVersion) {
|
||||||
|
return search.containsKey(cookbookVersion.getCookbookName())
|
||||||
|
&& any(search.get(cookbookVersion.getCookbookName()), new Predicate<String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(final String recipeName) {
|
||||||
|
return any(cookbookVersion.getRecipes(), new Predicate<Resource>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Resource resource) {
|
||||||
|
return resource.getName().equals(recipeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "containsRecipes(" + search + ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import org.jclouds.chef.strategy.internal.CleanupStaleNodesAndClientsImpl;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Cleans up nodes and clients who have been hanging around too long.
|
||||||
|
*/
|
||||||
|
@ImplementedBy(CleanupStaleNodesAndClientsImpl.class)
|
||||||
|
public interface CleanupStaleNodesAndClients {
|
||||||
|
|
||||||
|
void execute(String prefix, int secondsStale);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.internal.CreateNodeAndPopulateAutomaticAttributesImpl;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Creates a new node with automatic attributes.
|
||||||
|
*/
|
||||||
|
@ImplementedBy(CreateNodeAndPopulateAutomaticAttributesImpl.class)
|
||||||
|
public interface CreateNodeAndPopulateAutomaticAttributes {
|
||||||
|
Node execute(Node node);
|
||||||
|
|
||||||
|
Node execute(String nodeName, Iterable<String> runList);
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy;
|
||||||
|
|
||||||
|
import org.jclouds.chef.strategy.internal.DeleteAllClientsInListImpl;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all clients in a given list.
|
||||||
|
*/
|
||||||
|
@ImplementedBy(DeleteAllClientsInListImpl.class)
|
||||||
|
public interface DeleteAllClientsInList {
|
||||||
|
|
||||||
|
void execute(Iterable<String> names);
|
||||||
|
|
||||||
|
void execute(ListeningExecutorService executor, Iterable<String> names);
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import org.jclouds.chef.strategy.internal.DeleteAllNodesInListImpl;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
@ImplementedBy(DeleteAllNodesInListImpl.class)
|
||||||
|
public interface DeleteAllNodesInList {
|
||||||
|
|
||||||
|
void execute(Iterable<String> names);
|
||||||
|
|
||||||
|
void execute(ListeningExecutorService executor, Iterable<String> names);
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListClientsImpl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@ImplementedBy(ListClientsImpl.class)
|
||||||
|
public interface ListClients {
|
||||||
|
|
||||||
|
Iterable<? extends Client> execute();
|
||||||
|
|
||||||
|
Iterable<? extends Client> execute(ExecutorService executor);
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListCookbookVersionsImpl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@ImplementedBy(ListCookbookVersionsImpl.class)
|
||||||
|
public interface ListCookbookVersions {
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute();
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(ExecutorService executor);
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListCookbookVersionsInEnvironmentImpl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@ImplementedBy(ListCookbookVersionsInEnvironmentImpl.class)
|
||||||
|
public interface ListCookbookVersionsInEnvironment {
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(String environmentName);
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(String environmentName, String numVersions);
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(ExecutorService executor, String environmentName);
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(ExecutorService executor, String environmentName, String numVersions);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import org.jclouds.chef.domain.Environment;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListEnvironmentsImpl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@ImplementedBy(ListEnvironmentsImpl.class)
|
||||||
|
public interface ListEnvironments {
|
||||||
|
|
||||||
|
Iterable<? extends Environment> execute();
|
||||||
|
|
||||||
|
Iterable<? extends Environment> execute(ExecutorService executor);
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListNodesImpl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@ImplementedBy(ListNodesImpl.class)
|
||||||
|
public interface ListNodes {
|
||||||
|
|
||||||
|
Iterable<? extends Node> execute();
|
||||||
|
|
||||||
|
Iterable<? extends Node> execute(ExecutorService executor);
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListNodesInEnvironmentImpl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@ImplementedBy(ListNodesInEnvironmentImpl.class)
|
||||||
|
public interface ListNodesInEnvironment {
|
||||||
|
|
||||||
|
Iterable<? extends Node> execute(String environmentName);
|
||||||
|
|
||||||
|
Iterable<? extends Node> execute(ExecutorService executor, String environmentName);
|
||||||
|
|
||||||
|
}
|
|
@ -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.strategy;
|
||||||
|
|
||||||
|
import org.jclouds.chef.strategy.internal.UpdateAutomaticAttributesOnNodeImpl;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Updates node with new automatic attributes.
|
||||||
|
*/
|
||||||
|
@ImplementedBy(UpdateAutomaticAttributesOnNodeImpl.class)
|
||||||
|
public interface UpdateAutomaticAttributesOnNode {
|
||||||
|
|
||||||
|
void execute(String nodeName);
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.chef.strategy.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.util.concurrent.Futures.allAsList;
|
||||||
|
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
||||||
|
|
||||||
|
public abstract class BaseListCookbookVersionsImpl {
|
||||||
|
|
||||||
|
protected final ChefApi api;
|
||||||
|
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
BaseListCookbookVersionsImpl(ChefApi api) {
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends CookbookVersion> execute(Iterable<String> toGet) {
|
||||||
|
return concat(transform(toGet, new Function<String, Iterable<? extends CookbookVersion>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> apply(final String cookbook) {
|
||||||
|
// TODO getting each version could also go parallel
|
||||||
|
Set<String> cookbookVersions = api.listVersionsOfCookbook(cookbook);
|
||||||
|
Iterable<? extends CookbookVersion> cookbooksVersions = transform(cookbookVersions,
|
||||||
|
new Function<String, CookbookVersion>() {
|
||||||
|
@Override
|
||||||
|
public CookbookVersion apply(final String version) {
|
||||||
|
return api.getCookbook(cookbook, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.trace(String.format("getting versions of cookbook: %s", cookbook));
|
||||||
|
return cookbooksVersions;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends CookbookVersion> executeConcurrently(final ListeningExecutorService executor,
|
||||||
|
Iterable<String> cookbookNames) {
|
||||||
|
return concat(transform(cookbookNames, new Function<String, Iterable<? extends CookbookVersion>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> apply(final String cookbook) {
|
||||||
|
// TODO getting each version could also go parallel
|
||||||
|
Set<String> cookbookVersions = api.listVersionsOfCookbook(cookbook);
|
||||||
|
ListenableFuture<List<CookbookVersion>> futures = allAsList(transform(cookbookVersions,
|
||||||
|
new Function<String, ListenableFuture<CookbookVersion>>() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<CookbookVersion> apply(final String version) {
|
||||||
|
return executor.submit(new Callable<CookbookVersion>() {
|
||||||
|
@Override
|
||||||
|
public CookbookVersion call() throws Exception {
|
||||||
|
return api.getCookbook(cookbook, version);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
logger.trace(String.format("getting versions of cookbook: %s", cookbook));
|
||||||
|
return getUnchecked(futures);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.util.concurrent.Futures.allAsList;
|
||||||
|
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
||||||
|
|
||||||
|
public abstract class BaseListNodesImpl {
|
||||||
|
|
||||||
|
protected final ChefApi api;
|
||||||
|
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
BaseListNodesImpl(ChefApi api) {
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends Node> execute(Iterable<String> toGet) {
|
||||||
|
Iterable<? extends Node> nodes = transform(toGet, new Function<String, Node>() {
|
||||||
|
@Override
|
||||||
|
public Node apply(final String input) {
|
||||||
|
return api.getNode(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.trace(String.format("getting nodes: %s", Joiner.on(',').join(toGet)));
|
||||||
|
return nodes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends Node> executeConcurrently(final ListeningExecutorService executor,
|
||||||
|
Iterable<String> toGet) {
|
||||||
|
ListenableFuture<List<Node>> futures = allAsList(transform(toGet, new Function<String, ListenableFuture<Node>>() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Node> apply(final String input) {
|
||||||
|
return executor.submit(new Callable<Node>() {
|
||||||
|
@Override
|
||||||
|
public Node call() throws Exception {
|
||||||
|
return api.getNode(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
logger.trace(String.format("getting nodes: %s", Joiner.on(',').join(toGet)));
|
||||||
|
return getUnchecked(futures);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Predicates.and;
|
||||||
|
import static com.google.common.base.Predicates.notNull;
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static org.jclouds.chef.util.ChefUtils.fromOhaiTime;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.CleanupStaleNodesAndClients;
|
||||||
|
import org.jclouds.chef.strategy.DeleteAllClientsInList;
|
||||||
|
import org.jclouds.chef.strategy.DeleteAllNodesInList;
|
||||||
|
import org.jclouds.chef.strategy.ListNodes;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Cleans up nodes and apis who have been hanging around too long.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClients {
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final ListNodes nodeLister;
|
||||||
|
private final DeleteAllNodesInList nodeDeleter;
|
||||||
|
private final DeleteAllClientsInList clientDeleter;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CleanupStaleNodesAndClientsImpl(DeleteAllNodesInList nodeDeleter, DeleteAllClientsInList clientDeleter,
|
||||||
|
ListNodes nodeLister) {
|
||||||
|
this.nodeLister = checkNotNull(nodeLister, "nodeLister");
|
||||||
|
this.nodeDeleter = checkNotNull(nodeDeleter, "nodeDeleter");
|
||||||
|
this.clientDeleter = checkNotNull(clientDeleter, "clientDeleter");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final String prefix, int secondsStale) {
|
||||||
|
final Calendar expired = Calendar.getInstance();
|
||||||
|
expired.setTime(new Date());
|
||||||
|
expired.add(Calendar.SECOND, -secondsStale);
|
||||||
|
Iterable<? extends Node> staleNodes = filter(
|
||||||
|
nodeLister.execute(), and(notNull(), new Predicate<Node>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Node input) {
|
||||||
|
return input.getName().startsWith(prefix);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Predicate<Node>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Node input) {
|
||||||
|
JsonBall dateLong = input.getAutomaticAttributes().get("ohai_time");
|
||||||
|
if (dateLong == null)
|
||||||
|
return true;
|
||||||
|
Calendar nodeUpdate = Calendar.getInstance();
|
||||||
|
nodeUpdate.setTime(fromOhaiTime(dateLong));
|
||||||
|
return expired.after(nodeUpdate);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
Iterable<String> nodeNames = transform(staleNodes, new Function<Node, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(Node from) {
|
||||||
|
return from.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
nodeDeleter.execute(nodeNames);
|
||||||
|
clientDeleter.execute(nodeNames);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.ohai.Automatic;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Updates node with new automatic attributes.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class CreateNodeAndPopulateAutomaticAttributesImpl implements CreateNodeAndPopulateAutomaticAttributes {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final ChefApi chef;
|
||||||
|
private final Supplier<Map<String, JsonBall>> automaticSupplier;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CreateNodeAndPopulateAutomaticAttributesImpl(ChefApi chef,
|
||||||
|
@Automatic Supplier<Map<String, JsonBall>> automaticSupplier) {
|
||||||
|
this.chef = checkNotNull(chef, "chef");
|
||||||
|
this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node execute(Node node) {
|
||||||
|
logger.trace("creating node %s", node.getName());
|
||||||
|
Node withAutomatic = Node.builder() //
|
||||||
|
.name(node.getName()) //
|
||||||
|
.normalAttributes(node.getNormalAttributes()) //
|
||||||
|
.overrideAttributes(node.getOverrideAttributes()) //
|
||||||
|
.defaultAttributes(node.getDefaultAttributes()) //
|
||||||
|
.automaticAttributes(node.getAutomaticAttributes()) //
|
||||||
|
.automaticAttributes(automaticSupplier.get()) //
|
||||||
|
.runList(node.getRunList()) //
|
||||||
|
.environment(node.getEnvironment()) //
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
chef.createNode(withAutomatic);
|
||||||
|
logger.debug("created node %s", withAutomatic.getName());
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node execute(String nodeName, Iterable<String> runList) {
|
||||||
|
return execute(Node.builder().name(nodeName).runList(runList).environment("_default").build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.util.concurrent.Futures.allAsList;
|
||||||
|
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.strategy.DeleteAllClientsInList;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concurrently delete all given clients.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class DeleteAllClientsInListImpl implements DeleteAllClientsInList {
|
||||||
|
|
||||||
|
protected final ChefApi api;
|
||||||
|
protected final ListeningExecutorService userExecutor;
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
DeleteAllClientsInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) {
|
||||||
|
this.userExecutor = checkNotNull(userExecutor, "userExecuor");
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Iterable<String> names) {
|
||||||
|
execute(userExecutor, names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final ListeningExecutorService executor, Iterable<String> names) {
|
||||||
|
ListenableFuture<List<Client>> futures = allAsList(transform(names,
|
||||||
|
new Function<String, ListenableFuture<Client>>() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Client> apply(final String input) {
|
||||||
|
return executor.submit(new Callable<Client>() {
|
||||||
|
@Override
|
||||||
|
public Client call() throws Exception {
|
||||||
|
return api.deleteClient(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
logger.trace(String.format("deleting clients: %s", Joiner.on(',').join(names)));
|
||||||
|
getUnchecked(futures);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.util.concurrent.Futures.allAsList;
|
||||||
|
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.DeleteAllNodesInList;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class DeleteAllNodesInListImpl implements DeleteAllNodesInList {
|
||||||
|
|
||||||
|
protected final ChefApi api;
|
||||||
|
protected final ListeningExecutorService userExecutor;
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
DeleteAllNodesInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) {
|
||||||
|
this.userExecutor = checkNotNull(userExecutor, "userExecuor");
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Iterable<String> names) {
|
||||||
|
execute(userExecutor, names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final ListeningExecutorService executor, Iterable<String> names) {
|
||||||
|
ListenableFuture<List<Node>> futures = allAsList(transform(names, new Function<String, ListenableFuture<Node>>() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Node> apply(final String input) {
|
||||||
|
return executor.submit(new Callable<Node>() {
|
||||||
|
@Override
|
||||||
|
public Node call() throws Exception {
|
||||||
|
return api.deleteNode(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
logger.trace(String.format("deleting nodes: %s", Joiner.on(',').join(names)));
|
||||||
|
getUnchecked(futures);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.util.concurrent.Futures.allAsList;
|
||||||
|
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.strategy.ListClients;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ListClientsImpl implements ListClients {
|
||||||
|
|
||||||
|
protected final ChefApi api;
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListClientsImpl(ChefApi api) {
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Client> execute() {
|
||||||
|
|
||||||
|
Iterable<String> toGet = api.listClients();
|
||||||
|
Iterable<? extends Client> clients = transform(toGet,
|
||||||
|
new Function<String, Client>() {
|
||||||
|
@Override
|
||||||
|
public Client apply(final String input) {
|
||||||
|
|
||||||
|
return api.getClient(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.trace(String.format("getting clients: %s", Joiner.on(',').join(toGet)));
|
||||||
|
return clients;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Client> execute(ExecutorService executorService) {
|
||||||
|
return this.execute(MoreExecutors.listeningDecorator(executorService));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<? extends Client> execute(ListeningExecutorService listeningExecutor) {
|
||||||
|
return executeConcurrently(listeningExecutor, api.listClients());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterable<? extends Client> executeConcurrently(final ListeningExecutorService executor,
|
||||||
|
Iterable<String> toGet) {
|
||||||
|
ListenableFuture<List<Client>> futures = allAsList(transform(toGet,
|
||||||
|
new Function<String, ListenableFuture<Client>>() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Client> apply(final String input) {
|
||||||
|
return executor.submit(new Callable<Client>() {
|
||||||
|
@Override
|
||||||
|
public Client call() throws Exception {
|
||||||
|
return api.getClient(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
logger.trace(String.format("getting clients: %s", Joiner.on(',').join(toGet)));
|
||||||
|
return getUnchecked(futures);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.strategy.ListCookbookVersions;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ListCookbookVersionsImpl extends BaseListCookbookVersionsImpl implements ListCookbookVersions {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListCookbookVersionsImpl(ChefApi api) {
|
||||||
|
super(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute() {
|
||||||
|
return super.execute(api.listCookbooks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(ExecutorService executor) {
|
||||||
|
return this.executeConcurrently(MoreExecutors.listeningDecorator(executor));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<? extends CookbookVersion> executeConcurrently(ListeningExecutorService executor) {
|
||||||
|
return super.executeConcurrently(executor, api.listCookbooks());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.CookbookDefinition;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ListCookbookVersionsInEnvironmentImpl extends BaseListCookbookVersionsImpl
|
||||||
|
implements ListCookbookVersionsInEnvironment {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListCookbookVersionsInEnvironmentImpl(ChefApi api) {
|
||||||
|
super(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(String environmentName) {
|
||||||
|
return super.execute(transform(api.listCookbooksInEnvironment(environmentName),
|
||||||
|
new Function<CookbookDefinition, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(CookbookDefinition cookbookDefinition) {
|
||||||
|
return cookbookDefinition.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(String environmentName, String numVersions) {
|
||||||
|
return super.execute(transform(api.listCookbooksInEnvironment(environmentName, numVersions),
|
||||||
|
new Function<CookbookDefinition, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(CookbookDefinition cookbookDefinition) {
|
||||||
|
return cookbookDefinition.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(ExecutorService executor,
|
||||||
|
String environmentName) {
|
||||||
|
return this.executeConcurrently(MoreExecutors.listeningDecorator(executor), environmentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(ExecutorService executor,
|
||||||
|
String environmentName, String numVersions) {
|
||||||
|
return this.executeConcurrently(MoreExecutors.listeningDecorator(executor), environmentName, numVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<? extends CookbookVersion> executeConcurrently(ListeningExecutorService executor,
|
||||||
|
String environmentName) {
|
||||||
|
return super.execute(
|
||||||
|
transform(api.listCookbooksInEnvironment(environmentName), new Function<CookbookDefinition, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(CookbookDefinition cookbookDefinition) {
|
||||||
|
return cookbookDefinition.getName();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<? extends CookbookVersion> executeConcurrently(ListeningExecutorService executor,
|
||||||
|
String environmentName, String numVersions) {
|
||||||
|
return super.execute(transform(api.listCookbooksInEnvironment(environmentName, numVersions),
|
||||||
|
new Function<CookbookDefinition, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(CookbookDefinition cookbookDefinition) {
|
||||||
|
return cookbookDefinition.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.util.concurrent.Futures.allAsList;
|
||||||
|
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Environment;
|
||||||
|
import org.jclouds.chef.strategy.ListEnvironments;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ListEnvironmentsImpl implements ListEnvironments {
|
||||||
|
|
||||||
|
protected final ChefApi api;
|
||||||
|
protected final ListeningExecutorService userExecutor;
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListEnvironmentsImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) {
|
||||||
|
this.userExecutor = checkNotNull(userExecutor, "userExecuor");
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Environment> execute() {
|
||||||
|
return execute(userExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Environment> execute(ExecutorService executor) {
|
||||||
|
return this.execute(MoreExecutors.listeningDecorator(executor));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterable<? extends Environment> execute(ListeningExecutorService executor) {
|
||||||
|
return execute(executor, api.listEnvironments());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterable<? extends Environment> execute(final ListeningExecutorService executor, Iterable<String> toGet) {
|
||||||
|
ListenableFuture<List<Environment>> futures = allAsList(transform(toGet,
|
||||||
|
new Function<String, ListenableFuture<Environment>>() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Environment> apply(final String input) {
|
||||||
|
return executor.submit(new Callable<Environment>() {
|
||||||
|
@Override
|
||||||
|
public Environment call() throws Exception {
|
||||||
|
return api.getEnvironment(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
logger.trace(String.format("deleting environments: %s", Joiner.on(',').join(toGet)));
|
||||||
|
return getUnchecked(futures);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.ListNodes;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ListNodesImpl extends BaseListNodesImpl implements ListNodes {
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListNodesImpl(ChefApi api) {
|
||||||
|
super(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> execute() {
|
||||||
|
return super.execute(api.listNodes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> execute(ExecutorService executor) {
|
||||||
|
return this.executeConcurrently(MoreExecutors.listeningDecorator(executor));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<? extends Node> executeConcurrently(ListeningExecutorService executor) {
|
||||||
|
return super.executeConcurrently(executor, api.listNodes());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.ListNodesInEnvironment;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ListNodesInEnvironmentImpl extends BaseListNodesImpl implements ListNodesInEnvironment {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListNodesInEnvironmentImpl(ChefApi api) {
|
||||||
|
super(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> execute(String environmentName) {
|
||||||
|
return super.execute(api.listNodesInEnvironment(environmentName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends Node> execute(ExecutorService executor, String environmentName) {
|
||||||
|
return this.executeConcurrently(MoreExecutors.listeningDecorator(executor), environmentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<? extends Node> executeConcurrently(ListeningExecutorService executor,
|
||||||
|
String environmentName) {
|
||||||
|
return super.executeConcurrently(executor, api.listNodesInEnvironment(environmentName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.chef.domain.Node;
|
||||||
|
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.ohai.Automatic;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Updates node with new automatic attributes.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class UpdateAutomaticAttributesOnNodeImpl implements UpdateAutomaticAttributesOnNode {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final ChefApi chef;
|
||||||
|
private final Supplier<Map<String, JsonBall>> automaticSupplier;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public UpdateAutomaticAttributesOnNodeImpl(ChefApi chef, @Automatic Supplier<Map<String, JsonBall>> automaticSupplier) {
|
||||||
|
this.chef = checkNotNull(chef, "chef");
|
||||||
|
this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String nodeName) {
|
||||||
|
logger.trace("updating node %s", nodeName);
|
||||||
|
Node node = chef.getNode(nodeName);
|
||||||
|
Node updated = Node.builder() //
|
||||||
|
.name(node.getName()) //
|
||||||
|
.normalAttributes(node.getNormalAttributes()) //
|
||||||
|
.overrideAttributes(node.getOverrideAttributes()) //
|
||||||
|
.defaultAttributes(node.getDefaultAttributes()) //
|
||||||
|
.automaticAttributes(automaticSupplier.get()) //
|
||||||
|
.runList(node.getRunList()) //
|
||||||
|
.environment(node.getEnvironment()) //
|
||||||
|
.build();
|
||||||
|
|
||||||
|
chef.updateNode(updated);
|
||||||
|
logger.debug("updated node %s", nodeName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* 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.suppliers;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.firstNonNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.config.ChefProperties;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.rest.annotations.ApiVersion;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properly supply the version of the Chef Server.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ChefVersionSupplier implements Supplier<Integer> {
|
||||||
|
|
||||||
|
/** The default version to assume in case we can not parse it. */
|
||||||
|
public static final Integer FALLBACK_VERSION = 10;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ChefProperties.CHEF_LOGGER)
|
||||||
|
private Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
/** The configured version of the Chef Server API. */
|
||||||
|
private final String apiVersion;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ChefVersionSupplier(@ApiVersion String apiVersion) {
|
||||||
|
this.apiVersion = checkNotNull(apiVersion, "apiVersion must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer get() {
|
||||||
|
// Old versions of Chef have versions like 0.9.x, 0.10.x, but newer
|
||||||
|
// versions are in the format 10.x.y, 11.x.y
|
||||||
|
Pattern versionPattern = Pattern.compile("(?:0\\.(\\d+)|(\\d+)\\.\\d+)(?:\\.\\d)*");
|
||||||
|
|
||||||
|
Matcher m = versionPattern.matcher(apiVersion);
|
||||||
|
if (!m.matches()) {
|
||||||
|
logger.warn("Configured version does not match the standard version pattern. Assuming version %s",
|
||||||
|
FALLBACK_VERSION);
|
||||||
|
return FALLBACK_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.valueOf(firstNonNull(m.group(1), m.group(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,387 @@
|
||||||
|
/*
|
||||||
|
* 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.test;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.config.LocalBlobStore;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.PageSet;
|
||||||
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
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.options.CreateClientOptions;
|
||||||
|
import org.jclouds.chef.options.SearchOptions;
|
||||||
|
import org.jclouds.io.Payload;
|
||||||
|
import org.jclouds.lifecycle.Closer;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-memory chef simulator.
|
||||||
|
*/
|
||||||
|
public class TransientChefApi implements ChefApi {
|
||||||
|
@Singleton
|
||||||
|
private static class StorageMetadataToName implements Function<PageSet<? extends StorageMetadata>, Set<String>> {
|
||||||
|
@Override
|
||||||
|
public Set<String> apply(PageSet<? extends StorageMetadata> from) {
|
||||||
|
return newLinkedHashSet(transform(from, new Function<StorageMetadata, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(StorageMetadata from) {
|
||||||
|
return from.getName();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
private static class BlobToDatabagItem implements Function<Blob, DatabagItem> {
|
||||||
|
@Override
|
||||||
|
public DatabagItem apply(Blob from) {
|
||||||
|
try {
|
||||||
|
return from == null ? null : new DatabagItem(from.getMetadata().getName(), Strings2.toStringAndClose(from
|
||||||
|
.getPayload().getInput()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
propagate(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final LocalBlobStore databags;
|
||||||
|
private final BlobToDatabagItem blobToDatabagItem;
|
||||||
|
private final StorageMetadataToName storageMetadataToName;
|
||||||
|
private final Closer closer;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
TransientChefApi(@Named("databags") LocalBlobStore databags, StorageMetadataToName storageMetadataToName,
|
||||||
|
BlobToDatabagItem blobToDatabagItem, Closer closer) {
|
||||||
|
this.databags = checkNotNull(databags, "databags");
|
||||||
|
this.storageMetadataToName = checkNotNull(storageMetadataToName, "storageMetadataToName");
|
||||||
|
this.blobToDatabagItem = checkNotNull(blobToDatabagItem, "blobToDatabagItem");
|
||||||
|
this.closer = checkNotNull(closer, "closer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sandbox commitSandbox(String id, boolean isCompleted) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Client createClient(String clientName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Client createClient(String clientName, CreateClientOptions options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createDatabag(String databagName) {
|
||||||
|
databags.createContainerInLocation(null, databagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabagItem createDatabagItem(String databagName, DatabagItem databagItem) {
|
||||||
|
Blob blob = databags.blobBuilder(databagItem.getId()).payload(databagItem.toString()).build();
|
||||||
|
databags.putBlob(databagName, blob);
|
||||||
|
return databagItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createNode(Node node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createRole(Role role) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Client deleteClient(String clientName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CookbookVersion deleteCookbook(String cookbookName, String version) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDatabag(String databagName) {
|
||||||
|
databags.deleteContainer(databagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabagItem deleteDatabagItem(String databagName, String databagItemId) {
|
||||||
|
DatabagItem item = blobToDatabagItem.apply(databags.getBlob(databagName, databagItemId));
|
||||||
|
databags.removeBlob(databagName, databagItemId);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node deleteNode(String nodeName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Role deleteRole(String rolename) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Client generateKeyForClient(String clientName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Client getClient(String clientName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CookbookVersion getCookbook(String cookbookName, String version) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabagItem getDatabagItem(String databagName, String databagItemId) {
|
||||||
|
return blobToDatabagItem.apply(databags.getBlob(databagName, databagItemId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode(String nodeName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Role getRole(String roleName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UploadSandbox createUploadSandboxForChecksums(Set<List<Byte>> md5s) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listVersionsOfCookbook(String cookbookName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listClients() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listCookbooks() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listDatabagItems(String databagName) {
|
||||||
|
return storageMetadataToName.apply(databags.list(databagName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listDatabags() {
|
||||||
|
return storageMetadataToName.apply(databags.list());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listNodes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listRoles() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listSearchIndexes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Client> searchClients() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Client> searchClients(SearchOptions options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends DatabagItem> searchDatabagItems(String databagName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends DatabagItem> searchDatabagItems(String databagName, SearchOptions options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Node> searchNodes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Node> searchNodes(SearchOptions options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Role> searchRoles() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Role> searchRoles(SearchOptions options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CookbookVersion updateCookbook(String cookbookName, String version, CookbookVersion cookbook) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabagItem updateDatabagItem(String databagName, DatabagItem item) {
|
||||||
|
return createDatabagItem(databagName, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node updateNode(Node node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Role updateRole(Role role) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadContent(URI location, Payload content) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceContents(Resource resource) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listEnvironments() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createEnvironment(Environment environment) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Environment deleteEnvironment(String environmentName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Environment getEnvironment(String environmentName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Environment updateEnvironment(Environment environment) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<CookbookDefinition> listCookbooksInEnvironment(String environmentName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<CookbookDefinition> listCookbooksInEnvironment(String environmentName, String numVersions) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CookbookDefinition getCookbookInEnvironment(String environmentName, String cookbookName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CookbookDefinition getCookbookInEnvironment(String environmentName, String cookbookName, String numVersions) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Environment> searchEnvironments() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchResult<? extends Environment> searchEnvironments(SearchOptions options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listRecipesInEnvironment(String environmentName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> listNodesInEnvironment(String environmentName) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
closer.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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.test;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.chef.ChefApiMetadata;
|
||||||
|
import org.jclouds.chef.config.ChefBootstrapModule;
|
||||||
|
import org.jclouds.chef.config.ChefParserModule;
|
||||||
|
import org.jclouds.chef.test.config.TransientChefApiModule;
|
||||||
|
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 the Amazon-specific Chef API
|
||||||
|
*/
|
||||||
|
public class TransientChefApiMetadata extends BaseHttpApiMetadata<TransientChefApi> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new Builder().fromApiMetadata(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransientChefApiMetadata() {
|
||||||
|
this(new Builder());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TransientChefApiMetadata(Builder builder) {
|
||||||
|
super(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder extends BaseHttpApiMetadata.Builder<TransientChefApi, Builder> {
|
||||||
|
protected Builder() {
|
||||||
|
id("transientchef")
|
||||||
|
.name("In-memory Chef API")
|
||||||
|
.identityName("unused")
|
||||||
|
.defaultIdentity("api")
|
||||||
|
.documentation(URI.create("http://localhost"))
|
||||||
|
.defaultCredential(
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n")
|
||||||
|
.defaultEndpoint("transientchef")
|
||||||
|
.defaultProperties(ChefApiMetadata.defaultProperties())
|
||||||
|
.defaultModules(
|
||||||
|
ImmutableSet.<Class<? extends Module>> of(TransientChefApiModule.class, ChefParserModule.class,
|
||||||
|
ChefBootstrapModule.class, JMXOhaiModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransientChefApiMetadata build() {
|
||||||
|
return new TransientChefApiMetadata(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Builder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* 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.test.config;
|
||||||
|
|
||||||
|
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.ContextBuilder;
|
||||||
|
import org.jclouds.blobstore.TransientApiMetadata;
|
||||||
|
import org.jclouds.blobstore.config.LocalBlobStore;
|
||||||
|
import org.jclouds.chef.ChefApi;
|
||||||
|
import org.jclouds.chef.config.Validator;
|
||||||
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.functions.BootstrapConfigForGroup;
|
||||||
|
import org.jclouds.chef.functions.ClientForGroup;
|
||||||
|
import org.jclouds.chef.functions.RunListForGroup;
|
||||||
|
import org.jclouds.chef.test.TransientChefApi;
|
||||||
|
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
|
import org.jclouds.rest.config.RestModule;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.name.Names;
|
||||||
|
|
||||||
|
@ConfiguresHttpApi
|
||||||
|
public class TransientChefApiModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
install(new RestModule());
|
||||||
|
bind(ChefApi.class).to(TransientChefApi.class);
|
||||||
|
bind(LocalBlobStore.class).annotatedWith(Names.named("databags"))
|
||||||
|
.toInstance(
|
||||||
|
ContextBuilder
|
||||||
|
.newBuilder(new TransientApiMetadata())
|
||||||
|
.modules(
|
||||||
|
ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(),
|
||||||
|
sameThreadExecutor()))).buildInjector().getInstance(LocalBlobStore.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public Supplier<PrivateKey> supplyKey() {
|
||||||
|
return new Supplier<PrivateKey>() {
|
||||||
|
@Override
|
||||||
|
public PrivateKey get() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CacheLoader<String, List<String>> runListForGroup(RunListForGroup runListForGroup) {
|
||||||
|
return CacheLoader.from(runListForGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CacheLoader<String, ? extends JsonBall> bootstrapConfigForGroup(BootstrapConfigForGroup bootstrapConfigForGroup) {
|
||||||
|
return CacheLoader.from(bootstrapConfigForGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CacheLoader<String, Client> groupToClient(ClientForGroup clientForGroup) {
|
||||||
|
return CacheLoader.from(clientForGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Validator
|
||||||
|
public Optional<String> provideValidatorName(Injector injector) {
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Validator
|
||||||
|
public Optional<PrivateKey> provideValidatorCredential(Crypto crypto, Injector injector)
|
||||||
|
throws InvalidKeySpecException, IOException {
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.util;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.ohai.Automatic;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Binder;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.multibindings.MapBinder;
|
||||||
|
|
||||||
|
public class ChefUtils {
|
||||||
|
|
||||||
|
public static Date fromOhaiTime(JsonBall ohaiDate) {
|
||||||
|
return new Date(Long.parseLong(checkNotNull(ohaiDate, "ohaiDate").toString().replaceAll("\\.[0-9]*$", "")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonBall toOhaiTime(long millis) {
|
||||||
|
return new JsonBall(millis + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MapBinder<String, Supplier<JsonBall>> ohaiAutomaticAttributeBinder(Binder binder) {
|
||||||
|
MapBinder<String, Supplier<JsonBall>> mapbinder = MapBinder.newMapBinder(binder, new TypeLiteral<String>() {
|
||||||
|
}, new TypeLiteral<Supplier<JsonBall>>() {
|
||||||
|
}, Automatic.class);
|
||||||
|
return mapbinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return NoSuchElementException if no element in the runList is a role.
|
||||||
|
*/
|
||||||
|
public static String findRoleInRunList(List<String> runList) {
|
||||||
|
final Pattern pattern = Pattern.compile("^role\\[(.*)\\]$");
|
||||||
|
String roleToParse = Iterables.find(runList, new Predicate<String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(String input) {
|
||||||
|
return pattern.matcher(input).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
Matcher matcher = pattern.matcher(roleToParse);
|
||||||
|
matcher.find();
|
||||||
|
return matcher.group(1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods to work with collections.
|
||||||
|
*/
|
||||||
|
public class CollectionUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an immutable list with the elements of the given list. If the
|
||||||
|
* input list is <code>null</code>, it returns an empty list.
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* The list used to build the immutable one.
|
||||||
|
* @return An immutable list with the elements of the given list.
|
||||||
|
*/
|
||||||
|
public static <T> ImmutableList<T> copyOfOrEmpty(@Nullable List<T> input) {
|
||||||
|
return input == null ? ImmutableList.<T> of() : ImmutableList.copyOf(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an immutable set with the elements of the given set. If the input
|
||||||
|
* set is <code>null</code>, it returns an empty set.
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* The set used to build the immutable one.
|
||||||
|
* @return An immutable set with the elements of the given set.
|
||||||
|
*/
|
||||||
|
public static <T> ImmutableSet<T> copyOfOrEmpty(@Nullable Set<T> input) {
|
||||||
|
return input == null ? ImmutableSet.<T> of() : ImmutableSet.copyOf(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an immutable map with the elements of the given map. If the input
|
||||||
|
* map is <code>null</code>, it returns an empty map.
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* The map used to build the immutable one.
|
||||||
|
* @return An immutable map with the elements of the given map.
|
||||||
|
*/
|
||||||
|
public static <K, V> ImmutableMap<K, V> copyOfOrEmpty(@Nullable Map<K, V> input) {
|
||||||
|
return input == null ? ImmutableMap.<K, V> of() : ImmutableMap.copyOf(input);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.addAll;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static com.google.common.collect.Lists.transform;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds a run list in the correct syntax for chef.
|
||||||
|
*/
|
||||||
|
public class RunListBuilder {
|
||||||
|
private List<String> list = newArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following recipe to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRecipe(String recipe) {
|
||||||
|
return addRecipes(checkNotNull(recipe, "recipe"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following recipes to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRecipes(String... recipes) {
|
||||||
|
addAll(list, transform(Arrays.asList(checkNotNull(recipes, "recipes")), new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
return "recipe[" + from + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following role to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRole(String role) {
|
||||||
|
return addRoles(checkNotNull(role, "role"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following roles to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRoles(String... roles) {
|
||||||
|
addAll(list, transform(Arrays.asList(checkNotNull(roles, "roles")), new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
return "role[" + from + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> build() {
|
||||||
|
return ImmutableList.copyOf(list);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.ohai;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.PARAMETER;
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target({ TYPE, METHOD, PARAMETER })
|
||||||
|
@Qualifier
|
||||||
|
public @interface Automatic {
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.ohai;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.ohai.functions.NestSlashKeys;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class AutomaticSupplier implements Supplier<Map<String, JsonBall>> {
|
||||||
|
private final Multimap<String, Supplier<JsonBall>> autoAttrs;
|
||||||
|
private final NestSlashKeys nester;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AutomaticSupplier(@Automatic Multimap<String, Supplier<JsonBall>> autoAttrs, NestSlashKeys nester) {
|
||||||
|
this.autoAttrs = checkNotNull(autoAttrs, "autoAttrs");
|
||||||
|
this.nester = checkNotNull(nester, "nester");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, JsonBall> get() {
|
||||||
|
return nester.apply(autoAttrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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.ohai.config;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target(TYPE)
|
||||||
|
public @interface ConfiguresOhai {
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.ohai.config;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.RuntimeMXBean;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
import org.jclouds.ohai.suppliers.UptimeSecondsSupplier;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.multibindings.MapBinder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wires the components needed to parse ohai data from a JVM
|
||||||
|
*/
|
||||||
|
@ConfiguresOhai
|
||||||
|
public class JMXOhaiModule extends OhaiModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected RuntimeMXBean provideRuntimeMXBean() {
|
||||||
|
return ManagementFactory.getRuntimeMXBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapBinder<String, Supplier<JsonBall>> bindOhai() {
|
||||||
|
MapBinder<String, Supplier<JsonBall>> mapBinder = super.bindOhai();
|
||||||
|
mapBinder.addBinding("uptime_seconds").to(UptimeSecondsSupplier.class);
|
||||||
|
return mapBinder;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue