mirror of https://github.com/apache/jclouds.git
Issue 191, 273: moved to http://github.com/jclouds/chef
This commit is contained in:
parent
2b918d5827
commit
686d058b09
10
all/pom.xml
10
all/pom.xml
|
@ -44,15 +44,5 @@
|
|||
<artifactId>jclouds-twitter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-chef</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-opscodeplatform</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$ $Revision$ $Date$ Copyright (C) 2010 Cloud Conscious,
|
||||
LLC <info@cloudconscious.com>
|
||||
|
||||
====================================================================
|
||||
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.html 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.jclouds</groupId>
|
||||
<artifactId>jclouds-chef-project</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<artifactId>jclouds-chef-compute</artifactId>
|
||||
<name>jclouds chef compute integration</name>
|
||||
<description>provisions nodes with jclouds and kick's off chef to configure and integrate</description>
|
||||
<properties>
|
||||
<!--
|
||||
for example: ec2, trmk-ecloud, bluelock-vclouddirector,
|
||||
cloudservers, etc
|
||||
-->
|
||||
<jclouds.compute.provider>YOUR_PREFERRED_PROVIDER</jclouds.compute.provider>
|
||||
<!-- leave blank unless you have a different url to override -->
|
||||
<jclouds.compute.endpoint></jclouds.compute.endpoint>
|
||||
<jclouds.compute.identity>YOUR_ACCOUNT</jclouds.compute.identity>
|
||||
<jclouds.compute.credential>YOUR_CREDENTIAL</jclouds.compute.credential>
|
||||
<!-- tag for nodes used in the tests -->
|
||||
<jclouds.compute.tag>jcloudschef</jclouds.compute.tag>
|
||||
<jclouds.chef.identity>YOUR_USER</jclouds.chef.identity>
|
||||
<jclouds.chef.credential.pem>${user.home}/.chef/${jclouds.chef.identity}.pem</jclouds.chef.credential.pem>
|
||||
<jclouds.opscodeplatform.org>YOUR_ORG</jclouds.opscodeplatform.org>
|
||||
<jclouds.chef.endpoint>https://api.opscode.com/organizations/${jclouds.opscodeplatform.org}</jclouds.chef.endpoint>
|
||||
</properties>
|
||||
|
||||
<!-- bootstrapping: need to fetch the project POM -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jclouds-googlecode-deploy</id>
|
||||
<url>http://jclouds.googlecode.com/svn/repo</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jclouds-rimu-snapshots-nexus</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-chef</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-compute</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-jsch</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-log4j</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.14</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-compute</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-allcompute</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</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>
|
||||
<excludes>
|
||||
<exclude>none</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*LiveTest.java</include>
|
||||
</includes>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>jclouds.compute.provider</name>
|
||||
<value>${jclouds.compute.provider}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.compute.endpoint</name>
|
||||
<value>${jclouds.compute.endpoint}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.compute.identity</name>
|
||||
<value>${jclouds.compute.identity}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.compute.credential</name>
|
||||
<value>${jclouds.compute.credential}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.compute.tag</name>
|
||||
<value>${jclouds.compute.tag}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.compute.credential</name>
|
||||
<value>${jclouds.compute.credential}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.chef.credential.pem</name>
|
||||
<value>${jclouds.chef.credential.pem}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.chef.endpoint</name>
|
||||
<value>${jclouds.chef.endpoint}</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
|
@ -1,165 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.compute;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Iterables.any;
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.getLast;
|
||||
import static org.jclouds.chef.predicates.CookbookVersionPredicates.containsRecipe;
|
||||
import static org.jclouds.chef.predicates.CookbookVersionPredicates.containsRecipes;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.runScript;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.ChefContext;
|
||||
import org.jclouds.chef.ChefContextFactory;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.util.RunListBuilder;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.predicates.NodePredicates;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.annotations.AfterGroups;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "chef.ChefComputeServiceLiveTest")
|
||||
public class ChefComputeServiceLiveTest {
|
||||
|
||||
private ComputeServiceContext computeContext;
|
||||
private ChefContext chefContext;
|
||||
private String tag;
|
||||
private String clientName;
|
||||
private String chefEndpoint;
|
||||
private Iterable<? extends NodeMetadata> nodes;
|
||||
|
||||
@BeforeGroups(groups = { "live" })
|
||||
public void setupAll() throws FileNotFoundException, IOException {
|
||||
tag = System.getProperty("jclouds.compute.tag") != null ? System.getProperty("jclouds.compute.tag")
|
||||
: "jcloudschef";
|
||||
String computeProvider = checkNotNull(System.getProperty("jclouds.compute.provider"), "jclouds.compute.provider");
|
||||
String computeEndpoint = System.getProperty("jclouds.compute.endpoint");
|
||||
String computeIdentity = checkNotNull(System.getProperty("jclouds.compute.identity"), "jclouds.compute.identity");
|
||||
String computeCredential = checkNotNull(System.getProperty("jclouds.compute.credential"),
|
||||
"jclouds.compute.credential");
|
||||
chefEndpoint = checkNotNull(System.getProperty("jclouds.chef.endpoint"), "jclouds.chef.endpoint");
|
||||
String chefIdentity = checkNotNull(System.getProperty("jclouds.chef.identity"), "jclouds.chef.identity");
|
||||
String chefCredentialFile = System.getProperty("jclouds.chef.credential.pem");
|
||||
if (chefCredentialFile == null || chefCredentialFile.equals(""))
|
||||
chefCredentialFile = System.getProperty("user.home") + "/.chef/" + chefIdentity + ".pem";
|
||||
|
||||
Properties props = new Properties();
|
||||
props.setProperty(computeProvider + ".identity", computeIdentity);
|
||||
props.setProperty(computeProvider + ".credential", computeCredential);
|
||||
props.setProperty("chef.endpoint", chefEndpoint);
|
||||
props.setProperty("chef.identity", chefIdentity);
|
||||
props.setProperty("chef.credential.file", chefCredentialFile);
|
||||
|
||||
if (computeEndpoint != null && !computeEndpoint.trim().equals(""))
|
||||
props.setProperty(computeProvider + ".endpoint", computeEndpoint);
|
||||
|
||||
computeContext = new ComputeServiceContextFactory().createContext(computeProvider, ImmutableSet.of(
|
||||
new Log4JLoggingModule(), getSshModule()), props);
|
||||
|
||||
chefContext = new ChefContextFactory().createContext(ImmutableSet.<Module> of(new Log4JLoggingModule()), props);
|
||||
}
|
||||
|
||||
protected Module getSshModule() {
|
||||
return new JschSshClientModule();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanUpdateRunList() throws IOException {
|
||||
String recipe = "apache2";
|
||||
|
||||
Iterable<? extends CookbookVersion> cookbookVersions = chefContext.getChefService().listCookbookVersions();
|
||||
|
||||
if (any(cookbookVersions, containsRecipe(recipe))) {
|
||||
List<String> runList = new RunListBuilder().addRecipe(recipe).build();
|
||||
chefContext.getChefService().updateRunListForTag(runList, tag);
|
||||
assertEquals(chefContext.getChefService().getRunListForTag(tag), runList);
|
||||
} else {
|
||||
assert false : String.format("recipe %s not in %s", recipe, cookbookVersions);
|
||||
}
|
||||
|
||||
// TODO move this to a unit test
|
||||
assert any(cookbookVersions, containsRecipe("apache2::mod_proxy"));
|
||||
assert any(cookbookVersions, containsRecipes("apache2", "apache2::mod_proxy", "apache2::mod_proxy_http"));
|
||||
assert !any(cookbookVersions, containsRecipe("apache2::bar"));
|
||||
assert !any(cookbookVersions, containsRecipe("foo::bar"));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCanUpdateRunList")
|
||||
public void testRunNodesWithBootstrap() throws IOException {
|
||||
|
||||
Payload bootstrap = chefContext.getChefService().createClientAndBootstrapScriptForTag(tag);
|
||||
|
||||
try {
|
||||
nodes = computeContext.getComputeService().runNodesWithTag(tag, 1, runScript(bootstrap));
|
||||
} catch (RunNodesException e) {
|
||||
nodes = concat(e.getSuccessfulNodes(), e.getNodeErrors().keySet());
|
||||
}
|
||||
|
||||
for (NodeMetadata node : nodes) {
|
||||
URI uri = URI.create("http://" + getLast(node.getPublicAddresses()));
|
||||
InputStream content = computeContext.utils().http().get(uri);
|
||||
String string = Utils.toStringAndClose(content);
|
||||
assert string.indexOf("It works!") >= 0 : string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@AfterGroups(groups = { "live" })
|
||||
public void teardownCompute() {
|
||||
if (computeContext != null) {
|
||||
computeContext.getComputeService().destroyNodesMatching(NodePredicates.withTag(tag));
|
||||
computeContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
@AfterGroups(groups = { "live" })
|
||||
public void teardownChef() {
|
||||
if (chefContext != null) {
|
||||
chefContext.getChefService().cleanupStaleNodesAndClients(tag + "-", 1);
|
||||
if (clientName != null && chefContext.getApi().clientExists(clientName))
|
||||
chefContext.getApi().deleteClient(clientName);
|
||||
chefContext.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
|
||||
Copyright (C) 2009 Cloud Conscious, LLC.
|
||||
<info@cloudconscious.com>
|
||||
|
||||
====================================================================
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0 Unless required by
|
||||
applicable law or agreed to in writing, software distributed
|
||||
under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions
|
||||
and limitations under the License.
|
||||
====================================================================
|
||||
-->
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
<!--
|
||||
For more configuration infromation and examples see the Apache
|
||||
Log4j website: http://logging.apache.org/log4j/
|
||||
-->
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
|
||||
debug="false">
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-compute.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-ssh.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="CHEFFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-chef.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-wire.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="COMPUTEFILE" />
|
||||
</appender>
|
||||
<appender name="ASYNCCHEF" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="CHEFFILE" />
|
||||
</appender>
|
||||
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="SSHFILE" />
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="FILE" />
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="WIREFILE" />
|
||||
</appender>
|
||||
|
||||
<!-- ================ -->
|
||||
<!-- Limit categories -->
|
||||
<!-- ================ -->
|
||||
|
||||
<category name="org.jclouds">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNC" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.headers">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.wire">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.chef">
|
||||
<priority value="TRACE" />
|
||||
<appender-ref ref="ASYNCCHEF" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.ssh">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCSSH" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.compute">
|
||||
<priority value="TRACE" />
|
||||
<appender-ref ref="ASYNCCOMPUTE" />
|
||||
</category>
|
||||
<!--
|
||||
|
||||
<category name="jclouds.wire"> <priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" /> </category> <category
|
||||
name="jclouds.signature"> <priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" /> </category>
|
||||
-->
|
||||
|
||||
<!-- ======================= -->
|
||||
<!-- Setup the Root category -->
|
||||
<!-- ======================= -->
|
||||
|
||||
<root>
|
||||
<priority value="WARN" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2010 Cloud Conscious, LLC
|
||||
<info@cloudconscious.com>
|
||||
|
||||
====================================================================
|
||||
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.html 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.jclouds</groupId>
|
||||
<artifactId>jclouds-chef-project</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<artifactId>jclouds-chef</artifactId>
|
||||
<name>jclouds Chef core</name>
|
||||
<description>jclouds components to access Chef</description>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/chef</connection>
|
||||
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/chef</developerConnection>
|
||||
<url>http://jclouds.googlecode.com/svn/trunk/chef</url>
|
||||
</scm>
|
||||
|
||||
<!-- bootstrapping: need to fetch the project POM -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jclouds-googlecode-deploy</id>
|
||||
<url>http://jclouds.googlecode.com/svn/repo</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jclouds-rimu-snapshots-nexus</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<jclouds.chef.identity>chef-validator</jclouds.chef.identity>
|
||||
<jclouds.chef.rsa-key>/etc/chef/validation.pem</jclouds.chef.rsa-key>
|
||||
<jclouds.chef.endpoint>http://localhost:4000</jclouds.chef.endpoint>
|
||||
<jclouds.test.identity>${jclouds.chef.identity}</jclouds.test.identity>
|
||||
<jclouds.test.credential>${jclouds.chef.rsa-key}</jclouds.test.credential>
|
||||
<jclouds.test.endpoint>${jclouds.chef.endpoint}</jclouds.test.endpoint>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- only required for Pems.java and only writing a private key file -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15</artifactId>
|
||||
<version>1.44</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.14</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-log4j</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.danlarkin</groupId>
|
||||
<artifactId>clojure-json</artifactId>
|
||||
<version>1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- for transient chef provider -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-blobstore</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,261 +0,0 @@
|
|||
;
|
||||
;
|
||||
; Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
;
|
||||
; ====================================================================
|
||||
; Licensed under the Apache License, Version 2.0 (the "License");
|
||||
; you may not use this file except in compliance with the License.
|
||||
; You may obtain a copy of the License at
|
||||
;
|
||||
; http://www.apache.org/licenses/LICENSE-2.0
|
||||
;
|
||||
; Unless required by applicable law or agreed to in writing, software
|
||||
; distributed under the License is distributed on an "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
; See the License for the specific language governing permissions and
|
||||
; limitations under the License.
|
||||
; ====================================================================
|
||||
;
|
||||
|
||||
(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.chef ChefClient
|
||||
ChefService ChefContext ChefContextFactory]
|
||||
[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))]
|
||||
(.. (ChefContextFactory.)
|
||||
(createContext provider identity credential
|
||||
(apply modules (concat ext-modules (opts :extensions)))
|
||||
(reduce #(do (.put %1 (name (first %2)) (second %2)) %1)
|
||||
(Properties.) (dissoc opts :extensions)))
|
||||
(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))))))
|
|
@ -1,420 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HEAD;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.chef.binders.BindChecksumsToJsonPayload;
|
||||
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
|
||||
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
|
||||
import org.jclouds.chef.binders.BindIsCompletedToJsonPayload;
|
||||
import org.jclouds.chef.binders.BindNameToJsonPayload;
|
||||
import org.jclouds.chef.binders.DatabagItemId;
|
||||
import org.jclouds.chef.binders.NodeName;
|
||||
import org.jclouds.chef.binders.RoleName;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
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.ParseKeySetFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchClientsFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchDatabagFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchNodesFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchRolesFromJson;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.annotations.Unwrap;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Chef via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @see ChefClient
|
||||
* @see <a href="TODO: insert URL of provider documentation" />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@RequestFilters(SignedHeaderAuth.class)
|
||||
@Headers(keys = "X-Chef-Version", values = ChefAsyncClient.VERSION)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface ChefAsyncClient {
|
||||
public static final String VERSION = "0.9.8";
|
||||
|
||||
/**
|
||||
* @see ChefClient#getUploadSandboxForChecksums
|
||||
*/
|
||||
@POST
|
||||
@Path("/sandboxes")
|
||||
ListenableFuture<UploadSandbox> getUploadSandboxForChecksums(
|
||||
@BinderParam(BindChecksumsToJsonPayload.class) Set<List<Byte>> md5s);
|
||||
|
||||
@PUT
|
||||
@Path("")
|
||||
ListenableFuture<Void> uploadContent(@BinderParam(BindChecksumsToJsonPayload.class) Set<List<Byte>> md5s);
|
||||
|
||||
/**
|
||||
* @see ChefClient#commitSandbox
|
||||
*/
|
||||
@PUT
|
||||
@Path("/sandboxes/{id}")
|
||||
ListenableFuture<Sandbox> commitSandbox(@PathParam("id") String id,
|
||||
@BinderParam(BindIsCompletedToJsonPayload.class) boolean isCompleted);
|
||||
|
||||
/**
|
||||
* @see ChefCookbooks#listCookbooks
|
||||
*/
|
||||
@GET
|
||||
@Path("/cookbooks")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listCookbooks();
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateCookbook
|
||||
*/
|
||||
@PUT
|
||||
@Path("/cookbooks/{cookbookname}/{version}")
|
||||
ListenableFuture<CookbookVersion> updateCookbook(@PathParam("cookbookname") String cookbookName,
|
||||
@PathParam("version") String version, @BinderParam(BindToJsonPayload.class) CookbookVersion cookbook);
|
||||
|
||||
/**
|
||||
* @see ChefCookbook#deleteCookbook(String)
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/cookbooks/{cookbookname}/{version}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<CookbookVersion> deleteCookbook(@PathParam("cookbookname") String cookbookName,
|
||||
@PathParam("version") String version);
|
||||
|
||||
/**
|
||||
* @see ChefCookbook#getVersionsOfCookbook
|
||||
*/
|
||||
@GET
|
||||
@Path("/cookbooks/{cookbookname}")
|
||||
@Unwrap
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> getVersionsOfCookbook(@PathParam("cookbookname") String cookbookName);
|
||||
|
||||
/**
|
||||
* @see ChefCookbook#getCookbook
|
||||
*/
|
||||
@GET
|
||||
@Path("/cookbooks/{cookbookname}/{version}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<CookbookVersion> getCookbook(@PathParam("cookbookname") String cookbookName,
|
||||
@PathParam("version") String version);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createClient
|
||||
*/
|
||||
@POST
|
||||
@Path("/clients")
|
||||
ListenableFuture<Client> createClient(@BinderParam(BindClientnameToJsonPayload.class) String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#generateKeyForClient
|
||||
*/
|
||||
@PUT
|
||||
@Path("/clients/{clientname}")
|
||||
ListenableFuture<Client> generateKeyForClient(
|
||||
@PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#clientExists
|
||||
*/
|
||||
@HEAD
|
||||
@Path("/clients/{clientname}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> clientExists(@PathParam("clientname") String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#getClient
|
||||
*/
|
||||
@GET
|
||||
@Path("/clients/{clientname}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Client> getClient(@PathParam("clientname") String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteClient
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/clients/{clientname}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Client> deleteClient(@PathParam("clientname") String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#listClients
|
||||
*/
|
||||
@GET
|
||||
@Path("/clients")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listClients();
|
||||
|
||||
/**
|
||||
* @see ChefClient#createNode
|
||||
*/
|
||||
@POST
|
||||
@Path("/nodes")
|
||||
ListenableFuture<Void> createNode(@BinderParam(BindToJsonPayload.class) Node node);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateNode
|
||||
*/
|
||||
@PUT
|
||||
@Path("/nodes/{nodename}")
|
||||
ListenableFuture<Node> updateNode(
|
||||
@PathParam("nodename") @ParamParser(NodeName.class) @BinderParam(BindToJsonPayload.class) Node node);
|
||||
|
||||
/**
|
||||
* @see ChefNode#nodeExists
|
||||
*/
|
||||
@HEAD
|
||||
@Path("/nodes/{nodename}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> nodeExists(@PathParam("nodename") String nodename);
|
||||
|
||||
/**
|
||||
* @see ChefNode#getNode
|
||||
*/
|
||||
@GET
|
||||
@Path("/nodes/{nodename}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Node> getNode(@PathParam("nodename") String nodename);
|
||||
|
||||
/**
|
||||
* @see ChefNode#deleteNode
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/nodes/{nodename}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Node> deleteNode(@PathParam("nodename") String nodename);
|
||||
|
||||
/**
|
||||
* @see ChefNode#listNodes
|
||||
*/
|
||||
@GET
|
||||
@Path("/nodes")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listNodes();
|
||||
|
||||
/**
|
||||
* @see ChefClient#createRole
|
||||
*/
|
||||
@POST
|
||||
@Path("/roles")
|
||||
ListenableFuture<Void> createRole(@BinderParam(BindToJsonPayload.class) Role role);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateRole
|
||||
*/
|
||||
@PUT
|
||||
@Path("/roles/{rolename}")
|
||||
ListenableFuture<Role> updateRole(
|
||||
@PathParam("rolename") @ParamParser(RoleName.class) @BinderParam(BindToJsonPayload.class) Role role);
|
||||
|
||||
/**
|
||||
* @see ChefRole#roleExists
|
||||
*/
|
||||
@HEAD
|
||||
@Path("/roles/{rolename}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> roleExists(@PathParam("rolename") String rolename);
|
||||
|
||||
/**
|
||||
* @see ChefRole#getRole
|
||||
*/
|
||||
@GET
|
||||
@Path("/roles/{rolename}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Role> getRole(@PathParam("rolename") String rolename);
|
||||
|
||||
/**
|
||||
* @see ChefRole#deleteRole
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/roles/{rolename}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Role> deleteRole(@PathParam("rolename") String rolename);
|
||||
|
||||
/**
|
||||
* @see ChefRole#listRoles
|
||||
*/
|
||||
@GET
|
||||
@Path("/roles")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listRoles();
|
||||
|
||||
/**
|
||||
* @see ChefClient#listDatabags
|
||||
*/
|
||||
@GET
|
||||
@Path("/data")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listDatabags();
|
||||
|
||||
/**
|
||||
* @see ChefClient#createDatabag
|
||||
*/
|
||||
@POST
|
||||
@Path("/data")
|
||||
ListenableFuture<Void> createDatabag(@BinderParam(BindNameToJsonPayload.class) String databagName);
|
||||
|
||||
/**
|
||||
* @see ChefClient#databagExists
|
||||
*/
|
||||
@HEAD
|
||||
@Path("/data/{name}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> databagExists(@PathParam("name") String databagName);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteDatabag
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/data/{name}")
|
||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> deleteDatabag(@PathParam("name") String databagName);
|
||||
|
||||
/**
|
||||
* @see ChefClient#listDatabagItems
|
||||
*/
|
||||
@GET
|
||||
@Path("/data/{name}")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listDatabagItems(@PathParam("name") String databagName);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createDatabagItem
|
||||
*/
|
||||
@POST
|
||||
@Path("/data/{databagName}")
|
||||
ListenableFuture<DatabagItem> createDatabagItem(@PathParam("databagName") String databagName,
|
||||
@BinderParam(BindToJsonPayload.class) DatabagItem databagItem);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateDatabagItem
|
||||
*/
|
||||
@PUT
|
||||
@Path("/data/{databagName}/{databagItemId}")
|
||||
ListenableFuture<DatabagItem> updateDatabagItem(
|
||||
@PathParam("databagName") String databagName,
|
||||
@PathParam("databagItemId") @ParamParser(DatabagItemId.class) @BinderParam(BindToJsonPayload.class) DatabagItem item);
|
||||
|
||||
/**
|
||||
* @see ChefClient#databagItemExists
|
||||
*/
|
||||
@HEAD
|
||||
@Path("/data/{databagName}/{databagItemId}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> databagItemExists(@PathParam("databagName") String databagName,
|
||||
@PathParam("databagItemId") String databagItemId);
|
||||
|
||||
/**
|
||||
* @see ChefClient#getDatabagItem
|
||||
*/
|
||||
@GET
|
||||
@Path("/data/{databagName}/{databagItemId}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<DatabagItem> getDatabagItem(@PathParam("databagName") String databagName,
|
||||
@PathParam("databagItemId") String databagItemId);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteDatabagItem
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/data/{databagName}/{databagItemId}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<DatabagItem> deleteDatabagItem(@PathParam("databagName") String databagName,
|
||||
@PathParam("databagItemId") String databagItemId);
|
||||
|
||||
/**
|
||||
* @see ChefClient#listSearchIndexes
|
||||
*/
|
||||
@GET
|
||||
@Path("/search")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<String>> listSearchIndexes();
|
||||
|
||||
/**
|
||||
* @see ChefClient#searchRoles
|
||||
*/
|
||||
@GET
|
||||
@Path("/search/role")
|
||||
@ResponseParser(ParseSearchRolesFromJson.class)
|
||||
ListenableFuture<? extends SearchResult<? extends Role>> searchRoles();
|
||||
|
||||
/**
|
||||
* @see ChefClient#searchClients
|
||||
*/
|
||||
@GET
|
||||
@Path("/search/client")
|
||||
@ResponseParser(ParseSearchClientsFromJson.class)
|
||||
ListenableFuture<? extends SearchResult<? extends Client>> searchClients();
|
||||
|
||||
/**
|
||||
* @see ChefClient#searchNodes
|
||||
*/
|
||||
@GET
|
||||
@Path("/search/node")
|
||||
@ResponseParser(ParseSearchNodesFromJson.class)
|
||||
ListenableFuture<? extends SearchResult<? extends Node>> searchNodes();
|
||||
|
||||
/**
|
||||
* @see ChefClient#searchDatabag
|
||||
*/
|
||||
@GET
|
||||
@Path("/search/{databagName}")
|
||||
@ResponseParser(ParseSearchDatabagFromJson.class)
|
||||
ListenableFuture<? extends SearchResult<? extends DatabagItem>> searchDatabag(
|
||||
@PathParam("databagName") String databagName);
|
||||
}
|
|
@ -1,533 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
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.concurrent.Timeout;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Chef.
|
||||
* <p/>
|
||||
*
|
||||
* @see ChefAsyncClient
|
||||
* @see <a href="TODO: insert URL of Chef documentation" />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface ChefClient {
|
||||
/**
|
||||
*
|
||||
* FIXME Comment this
|
||||
*
|
||||
* @param md5s
|
||||
* raw md5s; uses {@code Bytes.asList()} and {@code
|
||||
* Bytes.toByteArray()} as necessary
|
||||
* @return
|
||||
*/
|
||||
UploadSandbox getUploadSandboxForChecksums(Set<List<Byte>> md5s);
|
||||
|
||||
Sandbox commitSandbox(String id, boolean isCompleted);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a list of all the cookbook names
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have permission to see the
|
||||
* cookbook list.
|
||||
*/
|
||||
Set<String> listCookbooks();
|
||||
|
||||
/**
|
||||
* Creates or updates (uploads) a cookbook //TODO document
|
||||
*
|
||||
* @param cookbookName
|
||||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the cookbook already exists
|
||||
*/
|
||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
||||
CookbookVersion updateCookbook(String cookbookName, String version, CookbookVersion cookbook);
|
||||
|
||||
/**
|
||||
* deletes an existing cookbook.
|
||||
*
|
||||
* @return last state of the client you deleted or null, if not found
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have Delete rights on the
|
||||
* cookbook.
|
||||
*/
|
||||
CookbookVersion deleteCookbook(String cookbookName, String version);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the versions of a cookbook or null, if not found
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to view the
|
||||
* cookbook.
|
||||
*/
|
||||
Set<String> getVersionsOfCookbook(String cookbookName);
|
||||
|
||||
/**
|
||||
* Returns a description of the cookbook, with links to all of its component
|
||||
* parts, and the metadata.
|
||||
*
|
||||
* @return the cookbook or null, if not found
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to view the
|
||||
* cookbook.
|
||||
*/
|
||||
CookbookVersion getCookbook(String cookbookName, String version);
|
||||
|
||||
/**
|
||||
* creates a new client
|
||||
*
|
||||
* @return the private key of the client. You can then use this client name
|
||||
* and private key to access the Opscode API.
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to create a
|
||||
* client.
|
||||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the client already exists
|
||||
*/
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
Client createClient(String name);
|
||||
|
||||
/**
|
||||
* generate a new key-pair for this client, and return the new private key in
|
||||
* the response body.
|
||||
*
|
||||
* @return the new private key
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to modify the
|
||||
* client.
|
||||
*/
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
Client generateKeyForClient(String name);
|
||||
|
||||
/**
|
||||
* @return list of client names.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have rights to list clients.
|
||||
*/
|
||||
Set<String> listClients();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if the specified client name exists.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have rights to view the client.
|
||||
*/
|
||||
boolean clientExists(String name);
|
||||
|
||||
/**
|
||||
* deletes an existing client.
|
||||
*
|
||||
* @return last state of the client you deleted or null, if not found
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have Delete rights on the client.
|
||||
*/
|
||||
Client deleteClient(String name);
|
||||
|
||||
/**
|
||||
* gets an existing client.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the client.
|
||||
*/
|
||||
Client getClient(String name);
|
||||
|
||||
/**
|
||||
* creates a new node
|
||||
*
|
||||
* @return //TODO
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to create a
|
||||
* node.
|
||||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the node already exists
|
||||
*/
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
void createNode(Node node);
|
||||
|
||||
/**
|
||||
* Creates or updates (uploads) a node //TODO document
|
||||
*
|
||||
* @param nodeName
|
||||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the node already exists
|
||||
*/
|
||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
||||
Node updateNode(Node node);
|
||||
|
||||
/**
|
||||
* @return list of node names.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have rights to list nodes.
|
||||
*/
|
||||
Set<String> listNodes();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if the specified node name exists.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have rights to view the node.
|
||||
*/
|
||||
boolean nodeExists(String name);
|
||||
|
||||
/**
|
||||
* deletes an existing node.
|
||||
*
|
||||
* @return last state of the node you deleted or null, if not found
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have Delete rights on the node.
|
||||
*/
|
||||
Node deleteNode(String name);
|
||||
|
||||
/**
|
||||
* gets an existing node.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the node.
|
||||
*/
|
||||
Node getNode(String name);
|
||||
|
||||
/**
|
||||
* creates a new role
|
||||
*
|
||||
* @return //TODO
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to create a
|
||||
* role.
|
||||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the role already exists
|
||||
*/
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
void createRole(Role role);
|
||||
|
||||
/**
|
||||
* Creates or updates (uploads) a role //TODO document
|
||||
*
|
||||
* @param roleName
|
||||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the role already exists
|
||||
*/
|
||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
||||
Role updateRole(Role role);
|
||||
|
||||
/**
|
||||
* @return list of role names.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have rights to list roles.
|
||||
*/
|
||||
Set<String> listRoles();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if the specified role name exists.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have rights to view the role.
|
||||
*/
|
||||
boolean roleExists(String name);
|
||||
|
||||
/**
|
||||
* deletes an existing role.
|
||||
*
|
||||
* @return last state of the role you deleted or null, if not found
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have Delete rights on the role.
|
||||
*/
|
||||
Role deleteRole(String name);
|
||||
|
||||
/**
|
||||
* gets an existing role.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the role.
|
||||
*/
|
||||
Role getRole(String name);
|
||||
|
||||
/**
|
||||
* lists databags available to the client
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
Set<String> listDatabags();
|
||||
|
||||
/**
|
||||
* creates a databag.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
void createDatabag(String databagName);
|
||||
|
||||
/**
|
||||
* true is a databag exists
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
boolean databagExists(String databagName);
|
||||
|
||||
/**
|
||||
* Delete a data bag, including its items
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
void deleteDatabag(String databagName);
|
||||
|
||||
/**
|
||||
* Show the items in a data bag.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
Set<String> listDatabagItems(String databagName);
|
||||
|
||||
/**
|
||||
* Create a data bag item in the data bag
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
* <p/>
|
||||
* @throws IllegalStateException
|
||||
* if the item already exists
|
||||
*
|
||||
*/
|
||||
DatabagItem createDatabagItem(String databagName, @BinderParam(BindToJsonPayload.class) DatabagItem node);
|
||||
|
||||
/**
|
||||
* Update (or create if not exists) a data bag item
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
DatabagItem updateDatabagItem(String databagName, DatabagItem item);
|
||||
|
||||
/**
|
||||
* determines if a databag item exists
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
boolean databagItemExists(String databagName, String databagItemId);
|
||||
|
||||
/**
|
||||
* gets an existing databag item.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
DatabagItem getDatabagItem(String databagName, String databagItemId);
|
||||
|
||||
/**
|
||||
* Delete a data bag item
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
DatabagItem deleteDatabagItem(String databagName, String databagItemId);
|
||||
|
||||
/**
|
||||
* Show indexes you can search on
|
||||
* <p/>
|
||||
* By default, the "role", "node" and "client" 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.)
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if you are not a recognized user.
|
||||
* <p/>
|
||||
* "403 Forbidden" if you do not have view rights on the databag.
|
||||
*/
|
||||
Set<String> listSearchIndexes();
|
||||
|
||||
/**
|
||||
* search 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 your
|
||||
* request, the position this result set returns (useful for paging)
|
||||
* and the rows themselves.
|
||||
*/
|
||||
SearchResult<? extends Role> searchRoles();
|
||||
|
||||
/**
|
||||
* search 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 your
|
||||
* request, the position this result set returns (useful for paging)
|
||||
* and the rows themselves.
|
||||
*/
|
||||
SearchResult<? extends Client> searchClients();
|
||||
|
||||
/**
|
||||
* search 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 your
|
||||
* request, the position this result set returns (useful for paging)
|
||||
* and the rows themselves.
|
||||
*/
|
||||
SearchResult<? extends Node> searchNodes();
|
||||
|
||||
/**
|
||||
* search all items in a databag.
|
||||
* <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 your
|
||||
* request, the position this result set returns (useful for paging)
|
||||
* and the rows themselves.
|
||||
*/
|
||||
SearchResult<? extends DatabagItem> searchDatabag(String databagName);
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import org.jclouds.chef.internal.ChefContextImpl;
|
||||
import org.jclouds.rest.RestContext;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@ImplementedBy(ChefContextImpl.class)
|
||||
public interface ChefContext extends RestContext<ChefClient, ChefAsyncClient>{
|
||||
|
||||
ChefService getChefService();
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.config.ChefRestClientModule;
|
||||
import org.jclouds.ohai.OhaiContextBuilder;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChefContextBuilder extends OhaiContextBuilder<ChefClient, ChefAsyncClient> {
|
||||
|
||||
public ChefContextBuilder(Properties props) {
|
||||
super(ChefClient.class, ChefAsyncClient.class, props);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addClientModule(List<Module> modules) {
|
||||
modules.add(new ChefRestClientModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Injector buildInjector() {
|
||||
addOhaiModuleIfNotPresent();
|
||||
return super.buildInjector();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public ChefContextBuilder withModules(Iterable<Module> modules) {
|
||||
return (ChefContextBuilder) super.withModules(modules);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public ChefContext buildContext() {
|
||||
Injector injector = buildInjector();
|
||||
return injector.getInstance(ChefContext.class);
|
||||
}
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import static org.jclouds.rest.RestContextFactory.createContextBuilder;
|
||||
import static org.jclouds.util.Utils.propagateAuthorizationOrOriginalException;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.rest.RestContextBuilder;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Helper class to instantiate {@code ChefContext} instances.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChefContextFactory {
|
||||
|
||||
private final RestContextFactory contextFactory;
|
||||
|
||||
/**
|
||||
* Initializes with the default properties built-in to jclouds. This is
|
||||
* typically stored in the classpath resource {@code rest.properties}
|
||||
*
|
||||
* @see RestContextFactory#getPropertiesFromResource
|
||||
*/
|
||||
public ChefContextFactory() {
|
||||
this(new RestContextFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds definitions in the specified properties.
|
||||
*/
|
||||
public ChefContextFactory(Properties properties) {
|
||||
this(new RestContextFactory(properties));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Uses the supplied RestContextFactory to create {@link ChefContext}s
|
||||
*/
|
||||
public ChefContextFactory(RestContextFactory restContextFactory) {
|
||||
this.contextFactory = restContextFactory;
|
||||
}
|
||||
|
||||
public static <S, A> ChefContext buildContextUnwrappingExceptions(RestContextBuilder<S, A> builder) {
|
||||
try {
|
||||
return (ChefContext) builder.buildContext();
|
||||
} catch (Exception e) {
|
||||
return propagateAuthorizationOrOriginalException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #createContext(String, String, String)
|
||||
*/
|
||||
public ChefContext createContext(String identity, String credential) {
|
||||
return createContext("chef", identity, credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(String, String, String)
|
||||
*/
|
||||
public ChefContext createContext(String provider, String identity, String credential) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(contextFactory.createContextBuilder(provider,
|
||||
identity, credential));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #createContext(String, Properties)
|
||||
*/
|
||||
public ChefContext createContext(Properties overrides) {
|
||||
return createContext("chef", overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(String, Properties)
|
||||
*/
|
||||
public ChefContext createContext(String provider, Properties overrides) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(contextFactory.createContextBuilder(provider,
|
||||
overrides));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #createContext(String, Iterable, Properties)
|
||||
*/
|
||||
public ChefContext createContext(Iterable<? extends Module> modules, Properties overrides) {
|
||||
return createContext("chef", modules, overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(String, Iterable, Properties)
|
||||
*/
|
||||
public ChefContext createContext(String provider, Iterable<? extends Module> modules, Properties overrides) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(contextFactory.createContextBuilder(provider,
|
||||
modules, overrides));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #createContext(String,String,String,Iterable)
|
||||
*/
|
||||
public ChefContext createContext(@Nullable String identity, @Nullable String credential,
|
||||
Iterable<? extends Module> modules) {
|
||||
return createContext("chef", identity, credential, modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(String,String String,
|
||||
* Iterable)
|
||||
*/
|
||||
public ChefContext createContext(String provider, @Nullable String identity, @Nullable String credential,
|
||||
Iterable<? extends Module> modules) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(contextFactory.createContextBuilder(provider,
|
||||
identity, credential, modules));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #createContext(String,String, String, Iterable, Properties)
|
||||
*/
|
||||
public ChefContext createContext(@Nullable String identity, @Nullable String credential,
|
||||
Iterable<? extends Module> modules, Properties overrides) {
|
||||
return createContext("chef", identity, credential, modules, overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(String,String,String,
|
||||
* Iterable, Properties)
|
||||
*/
|
||||
public ChefContext createContext(String provider, @Nullable String identity, @Nullable String credential,
|
||||
Iterable<? extends Module> modules, Properties overrides) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(contextFactory.createContextBuilder(provider,
|
||||
identity, credential, modules, overrides));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(ContextSpec)
|
||||
*/
|
||||
public <S, A> ChefContext createContext(ContextSpec<S, A> contextSpec) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(createContextBuilder(contextSpec));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RestContextFactory#createContextBuilder(ContextSpec, Properties)
|
||||
*/
|
||||
public <S, A> ChefContext createContext(ContextSpec<S, A> contextSpec, Properties overrides) {
|
||||
RestContextBuilder<?, ?> builder = RestContextBuilder.class.cast(createContextBuilder(contextSpec, overrides));
|
||||
return buildContextUnwrappingExceptions(builder);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.internal.BaseChefPropertiesBuilder;
|
||||
|
||||
/**
|
||||
* Builds properties used in Chef Clients
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChefPropertiesBuilder extends BaseChefPropertiesBuilder {
|
||||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_ENDPOINT, "http://localhost:4000");
|
||||
return properties;
|
||||
}
|
||||
|
||||
public ChefPropertiesBuilder(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.internal.BaseChefService;
|
||||
import org.jclouds.io.Payload;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.io.InputSupplier;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* Provides high level chef operations
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(BaseChefService.class)
|
||||
public interface ChefService {
|
||||
/**
|
||||
* @return a reference to the context that created this.
|
||||
*/
|
||||
ChefContext getContext();
|
||||
|
||||
byte[] encrypt(InputSupplier<? extends InputStream> supplier) throws IOException;
|
||||
|
||||
byte[] decrypt(InputSupplier<? extends InputStream> supplier) throws IOException;
|
||||
|
||||
void cleanupStaleNodesAndClients(String prefix, int secondsStale);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param nodeName
|
||||
* @param runList
|
||||
* @return node sent to the server containing the automatic attributes
|
||||
*/
|
||||
Node createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable<String> runList);
|
||||
|
||||
/**
|
||||
* Creates all steps necessary to bootstrap and run the chef client.
|
||||
*
|
||||
* @param tag
|
||||
* corresponds to a configured
|
||||
* {@link org.jclouds.chef.reference.ChefConstants#CHEF_BOOTSTRAP_DATABAG databag}
|
||||
* where run_list and other information are stored
|
||||
* @return boot script
|
||||
* @see #updateRunListForTag
|
||||
*/
|
||||
Payload createClientAndBootstrapScriptForTag(String tag);
|
||||
|
||||
/**
|
||||
* assigns a run list to all nodes bootstrapped with a certain tag
|
||||
*
|
||||
* @param runList
|
||||
* list of recipes or roles to assign. syntax is {@code recipe[name]} and {@code
|
||||
* role[name]}
|
||||
*
|
||||
* @param tag
|
||||
* corresponds to a configured
|
||||
* {@link org.jclouds.chef.reference.ChefConstants#CHEF_BOOTSTRAP_DATABAG databag}
|
||||
* where run_list and other information are stored
|
||||
* @see #makeChefClientBootstrapScriptForTag
|
||||
*/
|
||||
void updateRunListForTag(Iterable<String> runList, String tag);
|
||||
|
||||
/**
|
||||
* @param tag
|
||||
* corresponds to a configured
|
||||
* {@link org.jclouds.chef.reference.ChefConstants#CHEF_BOOTSTRAP_DATABAG databag}
|
||||
* where run_list and other information are stored
|
||||
* @return run list for all nodes bootstrapped with a certain tag
|
||||
* @see #updateRunListForTag
|
||||
*/
|
||||
List<String> getRunListForTag(String tag);
|
||||
|
||||
void deleteAllNodesInList(Iterable<String> names);
|
||||
|
||||
Iterable<? extends Node> listNodes();
|
||||
|
||||
Iterable<? extends Node> listNodesMatching(Predicate<String> nodeNameSelector);
|
||||
|
||||
Iterable<? extends Node> listNodesNamed(Iterable<String> names);
|
||||
|
||||
void deleteAllClientsInList(Iterable<String> names);
|
||||
|
||||
Iterable<? extends Client> listClientsDetails();
|
||||
|
||||
Iterable<? extends Client> listClientsDetailsMatching(Predicate<String> clientNameSelector);
|
||||
|
||||
Iterable<? extends Client> listClientsNamed(Iterable<String> names);
|
||||
|
||||
Iterable<? extends CookbookVersion> listCookbookVersions();
|
||||
|
||||
Iterable<? extends CookbookVersion> listCookbookVersionsMatching(Predicate<String> cookbookNameSelector);
|
||||
|
||||
Iterable<? extends CookbookVersion> listCookbookVersionsNamed(Iterable<String> cookbookNames);
|
||||
|
||||
void updateAutomaticAttributesOnNode(String nodeName);
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.binders;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.binders.BindToStringPayload;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BindChecksumsToJsonPayload extends BindToStringPayload {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void 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,", CryptoStreams.hex(Bytes.toArray(md5))));
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
builder.append("}}");
|
||||
super.bindToRequest(request, builder.toString());
|
||||
request.getPayload().setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class BindClientnameToJsonPayload extends BindToStringPayload {
|
||||
|
||||
@Override
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
super.bindToRequest(request, String.format("{\"clientname\":\"%s\"}", payload));
|
||||
request.getPayload().setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class BindGenerateKeyForClientToJsonPayload extends BindToStringPayload {
|
||||
|
||||
@Override
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
super.bindToRequest(request, String.format("{\"clientname\":\"%s\", \"private_key\": true}",
|
||||
payload));
|
||||
request.getPayload().setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class BindIsCompletedToJsonPayload extends BindToStringPayload {
|
||||
|
||||
@Override
|
||||
public void bindToRequest(HttpRequest request, Object value) {
|
||||
super.bindToRequest(request, String.format("{\"is_completed\":\"%s\"}", value));
|
||||
request.getPayload().setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class BindNameToJsonPayload extends BindToStringPayload {
|
||||
|
||||
@Override
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
super.bindToRequest(request, String.format("{\"name\":\"%s\"}", payload));
|
||||
request.getPayload().setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.binders;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class DatabagItemId implements Function<Object, String> {
|
||||
|
||||
public String apply(Object from) {
|
||||
return ((DatabagItem) from).getId();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.binders;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.domain.Node;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class NodeName implements Function<Object, String> {
|
||||
|
||||
public String apply(Object from) {
|
||||
return ((Node) from).getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.binders;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.domain.Role;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class RoleName implements Function<Object, String> {
|
||||
|
||||
public String apply(Object from) {
|
||||
return ((Role) from).getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.config;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
|
||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.handlers.ChefClientErrorRetryHandler;
|
||||
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.http.HttpErrorHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.io.InputSuppliers;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Chef connection.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
public class BaseChefRestClientModule<S, A> extends RestClientModule<S, A> {
|
||||
|
||||
protected BaseChefRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
|
||||
super(syncClientType, asyncClientType);
|
||||
}
|
||||
|
||||
protected BaseChefRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
|
||||
Map<Class<?>, Class<?>> delegates) {
|
||||
super(syncClientType, asyncClientType, delegates);
|
||||
}
|
||||
|
||||
@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 Suppliers.memoizeWithExpiration(new Supplier<String>() {
|
||||
public String get() {
|
||||
return dateService.iso8601SecondsDateFormat();
|
||||
}
|
||||
}, seconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public PrivateKey provideKey(Crypto crypto, @Named(PROPERTY_CREDENTIAL) String pem) throws InvalidKeySpecException,
|
||||
IOException {
|
||||
return crypto.rsaKeyFactory().generatePrivate(Pems.privateKeySpec(InputSuppliers.of(pem)));
|
||||
}
|
||||
|
||||
@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(ChefClientErrorRetryHandler.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new ChefParserModule());
|
||||
super.configure();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.config;
|
||||
|
||||
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 javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.crypto.Pems;
|
||||
import org.jclouds.io.InputSuppliers;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonLiteral;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.ImplementedBy;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChefParserModule extends AbstractModule {
|
||||
@ImplementedBy(PrivateKeyAdapterImpl.class)
|
||||
public static 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(InputSuppliers.of(keyText)));
|
||||
} 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 static 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(InputSuppliers.of(keyText)));
|
||||
} 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 static 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(InputSuppliers.of(keyText), 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ImplementedBy(DataBagItemAdapterImpl.class)
|
||||
public static interface DataBagItemAdapter extends JsonSerializer<DatabagItem>, JsonDeserializer<DatabagItem> {
|
||||
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class DataBagItemAdapterImpl implements DataBagItemAdapter {
|
||||
private final Json json;
|
||||
|
||||
@Inject
|
||||
DataBagItemAdapterImpl(Json json) {
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(DatabagItem src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
String text = src.toString();
|
||||
try {
|
||||
IdHolder idHolder = json.fromJson(text, IdHolder.class);
|
||||
if (idHolder.id == null)
|
||||
text = text.replaceFirst("\\{", String.format("{\"id\":\"%s\",", src.getId()));
|
||||
else
|
||||
checkArgument(src.getId().equals(idHolder.id), "incorrect id in databagItem text, should be %s: was %s",
|
||||
src.getId(), idHolder.id);
|
||||
return new JsonLiteral(text);
|
||||
} catch (JsonParseException e) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"databag item must be a json hash ex. {\"id\":\"item1\",\"my_key\":\"my_data\"}; was %s", text), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabagItem deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
String text = jsonElement.toString();
|
||||
IdHolder idHolder = json.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);
|
||||
}
|
||||
}
|
||||
|
||||
private static class IdHolder {
|
||||
private String id;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(Constants.PROPERTY_GSON_ADAPTERS)
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.functions.ClientForTag;
|
||||
import org.jclouds.chef.functions.RunListForTag;
|
||||
import org.jclouds.chef.statements.InstallChefGems;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
/**
|
||||
* Configures the Chef connection.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
public class ChefRestClientModule extends BaseChefRestClientModule<ChefClient, ChefAsyncClient> {
|
||||
|
||||
public ChefRestClientModule() {
|
||||
super(ChefClient.class, ChefAsyncClient.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Map<String, List<String>> runListForTag(RunListForTag runListForTag) {
|
||||
return new MapMaker().makeComputingMap(runListForTag);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Map<String, Client> tagToClient(ClientForTag tagToClient) {
|
||||
return new MapMaker().makeComputingMap(tagToClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(Statement.class).annotatedWith(Names.named("installChefGems")).to(InstallChefGems.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Cookbook object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Attribute {
|
||||
|
||||
private String required;
|
||||
private boolean calculated;
|
||||
private List<String> choice = Lists.newArrayList();
|
||||
@SerializedName("default")
|
||||
private JsonBall defaultValue;
|
||||
private String type;
|
||||
private List<String> recipes = Lists.newArrayList();
|
||||
@SerializedName("display_name")
|
||||
private String displayName;
|
||||
private String description;
|
||||
|
||||
public Attribute(String required, boolean calculated, Set<String> choice, JsonBall defaultValue, String type,
|
||||
List<String> recipes, String displayName, String description) {
|
||||
this.required = required;
|
||||
this.calculated = calculated;
|
||||
Iterables.addAll(this.choice, choice);
|
||||
this.defaultValue = defaultValue;
|
||||
this.type = type;
|
||||
Iterables.addAll(this.recipes, recipes);
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Attribute() {
|
||||
}
|
||||
|
||||
public String getRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
public boolean isCalculated() {
|
||||
return calculated;
|
||||
}
|
||||
|
||||
public List<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 + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChecksumStatus {
|
||||
private URI url;
|
||||
@SerializedName("needs_upload")
|
||||
private boolean needsUpload;
|
||||
|
||||
public ChecksumStatus(URI url, boolean needsUpload) {
|
||||
this.url = url;
|
||||
this.needsUpload = needsUpload;
|
||||
}
|
||||
|
||||
public ChecksumStatus() {
|
||||
|
||||
}
|
||||
|
||||
public URI getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public boolean needsUpload() {
|
||||
return needsUpload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChecksumStatus [needsUpload=" + needsUpload + ", url=" + url + "]";
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Client object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Client {
|
||||
private X509Certificate certificate;
|
||||
@SerializedName("private_key")
|
||||
private PrivateKey privateKey;
|
||||
private String orgname;
|
||||
private String clientname;
|
||||
private String name;
|
||||
private boolean validator;
|
||||
|
||||
// only for deserialization
|
||||
Client() {
|
||||
|
||||
}
|
||||
|
||||
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 String toString() {
|
||||
return "[name=" + name + ", clientname=" + clientname + ", orgname=" + orgname + ", isValidator=" + validator
|
||||
+ ", certificate=" + certificate + ", privateKey=" + (privateKey != null) + "]";
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
public Client(X509Certificate certificate, String orgname, String clientname, String name, boolean isValidator,
|
||||
@Nullable PrivateKey privateKey) {
|
||||
this.certificate = certificate;
|
||||
this.orgname = orgname;
|
||||
this.clientname = clientname;
|
||||
this.name = name;
|
||||
this.validator = isValidator;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Cookbook object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CookbookVersion {
|
||||
|
||||
private String name;
|
||||
private Set<Resource> definitions = Sets.newLinkedHashSet();
|
||||
private Set<Attribute> attributes = Sets.newLinkedHashSet();
|
||||
private Set<Resource> files = Sets.newLinkedHashSet();
|
||||
private Metadata metadata = new Metadata();
|
||||
private Set<Resource> providers = Sets.newLinkedHashSet();
|
||||
@SerializedName("cookbook_name")
|
||||
private String cookbookName;
|
||||
private Set<Resource> resources = Sets.newLinkedHashSet();
|
||||
private Set<Resource> templates = Sets.newLinkedHashSet();
|
||||
private Set<Resource> libraries = Sets.newLinkedHashSet();
|
||||
private String version;
|
||||
private Set<Resource> recipes = Sets.newLinkedHashSet();
|
||||
@SerializedName("root_files")
|
||||
private Set<Resource> rootFiles = Sets.newLinkedHashSet();
|
||||
|
||||
// internal
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("json_class")
|
||||
private String _jsonClass = "Chef::CookbookVersion";
|
||||
@SerializedName("chef_type")
|
||||
@SuppressWarnings("unused")
|
||||
private String _chefType = "cookbook_version";
|
||||
|
||||
public CookbookVersion(String cookbookName, String version) {
|
||||
this.cookbookName = cookbookName;
|
||||
this.version = version;
|
||||
this.name = cookbookName + "-" + version;
|
||||
}
|
||||
|
||||
public CookbookVersion(String name, Set<Resource> definitions, Set<Attribute> attributes, Set<Resource> files,
|
||||
Metadata metadata, Set<Resource> providers, String cookbookName, Set<Resource> resources,
|
||||
Set<Resource> templates, Set<Resource> libraries, String version, Set<Resource> recipes,
|
||||
Set<Resource> rootFiles) {
|
||||
this.name = name;
|
||||
Iterables.addAll(this.definitions, definitions);
|
||||
Iterables.addAll(this.attributes, attributes);
|
||||
Iterables.addAll(this.files, files);
|
||||
this.metadata = metadata;
|
||||
Iterables.addAll(this.providers, providers);
|
||||
this.cookbookName = cookbookName;
|
||||
Iterables.addAll(this.resources, resources);
|
||||
Iterables.addAll(this.templates, templates);
|
||||
Iterables.addAll(this.libraries, libraries);
|
||||
this.version = version;
|
||||
Iterables.addAll(this.recipes, recipes);
|
||||
Iterables.addAll(this.rootFiles, rootFiles);
|
||||
}
|
||||
|
||||
// hidden but needs to be here for json deserialization to work
|
||||
CookbookVersion() {
|
||||
|
||||
}
|
||||
|
||||
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 + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class DatabagItem extends JsonBall {
|
||||
|
||||
private static final long serialVersionUID = 7905637919304343493L;
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,281 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Cookbook object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Metadata {
|
||||
|
||||
private String license;
|
||||
private String maintainer;
|
||||
private Map<String, String> suggestions = Maps.newLinkedHashMap();
|
||||
private Map<String, Set<String>> dependencies = Maps.newLinkedHashMap();
|
||||
@SerializedName("maintainer_email")
|
||||
private String maintainerEmail;
|
||||
private Map<String, Set<String>> conflicting = Maps.newLinkedHashMap();
|
||||
private String description;
|
||||
private Map<String, Set<String>> providing = Maps.newLinkedHashMap();
|
||||
private Map<String, Set<String>> platforms = Maps.newLinkedHashMap();
|
||||
private String version;
|
||||
private Map<String, String> recipes = Maps.newLinkedHashMap();
|
||||
private Map<String, Set<String>> replacing = Maps.newLinkedHashMap();
|
||||
private String name;
|
||||
private Map<String, String> groupings = Maps.newLinkedHashMap();
|
||||
@SerializedName("long_description")
|
||||
private String longDescription;
|
||||
private Map<String, Attribute> attributes = Maps.newLinkedHashMap();
|
||||
private Map<String, String> recommendations = Maps.newLinkedHashMap();
|
||||
|
||||
public Metadata(String license, String maintainer, Map<String, String> suggestions,
|
||||
Map<String, Set<String>> dependencies, String maintainerEmail, Map<String, Set<String>> conflicting,
|
||||
String description, Map<String, Set<String>> providing, Map<String, Set<String>> platforms, String version,
|
||||
Map<String, String> recipes, Map<String, Set<String>> replacing, String name, Map<String, String> groupings,
|
||||
String longDescription, Map<String, Attribute> attributes, Map<String, String> recommendations) {
|
||||
this.license = license;
|
||||
this.maintainer = maintainer;
|
||||
this.suggestions.putAll(suggestions);
|
||||
this.dependencies.putAll(dependencies);
|
||||
this.maintainerEmail = maintainerEmail;
|
||||
this.conflicting.putAll(conflicting);
|
||||
this.description = description;
|
||||
this.providing.putAll(providing);
|
||||
this.platforms.putAll(platforms);
|
||||
this.version = version;
|
||||
this.recipes.putAll(recipes);
|
||||
this.replacing.putAll(replacing);
|
||||
this.name = name;
|
||||
this.groupings.putAll(groupings);
|
||||
this.longDescription = longDescription;
|
||||
this.attributes.putAll(attributes);
|
||||
this.recommendations.putAll(recommendations);
|
||||
}
|
||||
|
||||
public Metadata() {
|
||||
}
|
||||
|
||||
public String getLicense() {
|
||||
return license;
|
||||
}
|
||||
|
||||
public String getMaintainer() {
|
||||
return maintainer;
|
||||
}
|
||||
|
||||
public Map<String, String> getSuggestions() {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public String getMaintainerEmail() {
|
||||
return maintainerEmail;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getConflicting() {
|
||||
return conflicting;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getProviding() {
|
||||
return providing;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getPlatforms() {
|
||||
return platforms;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public Map<String, String> getRecipes() {
|
||||
return recipes;
|
||||
}
|
||||
|
||||
public Map<String, Set<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 + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Sandbox object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Node {
|
||||
|
||||
private String name;
|
||||
private Map<String, JsonBall> normal = Maps.newLinkedHashMap();
|
||||
private Map<String, JsonBall> override = Maps.newLinkedHashMap();
|
||||
@SerializedName("default")
|
||||
private Map<String, JsonBall> defaultA = Maps.newLinkedHashMap();
|
||||
private Map<String, JsonBall> automatic = Maps.newLinkedHashMap();
|
||||
@SerializedName("run_list")
|
||||
private List<String> runList = Lists.newArrayList();
|
||||
|
||||
// internal
|
||||
@SerializedName("json_class")
|
||||
private String _jsonClass = "Chef::Node";
|
||||
|
||||
public Node(String name, Map<String, JsonBall> normal, Map<String, JsonBall> override,
|
||||
Map<String, JsonBall> defaultA, Map<String, JsonBall> automatic, Iterable<String> runList) {
|
||||
this.name = name;
|
||||
this.normal.putAll(normal);
|
||||
this.override.putAll(override);
|
||||
this.defaultA.putAll(defaultA);
|
||||
this.automatic.putAll(automatic);
|
||||
Iterables.addAll(this.runList, runList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node [name=" + name + ", runList=" + runList + ", normal=" + normal + ", default=" + defaultA
|
||||
+ ", override=" + override + ", automatic=" + automatic + "]";
|
||||
}
|
||||
|
||||
public Node(String name, Iterable<String> runList) {
|
||||
this.name = name;
|
||||
Iterables.addAll(this.runList, runList);
|
||||
}
|
||||
|
||||
// hidden but needs to be here for json deserialization to work
|
||||
Node() {
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Map<String, JsonBall> getNormal() {
|
||||
return normal;
|
||||
}
|
||||
|
||||
public Map<String, JsonBall> getOverride() {
|
||||
return override;
|
||||
}
|
||||
|
||||
public Map<String, JsonBall> getDefault() {
|
||||
return defaultA;
|
||||
}
|
||||
|
||||
public Map<String, JsonBall> getAutomatic() {
|
||||
return automatic;
|
||||
}
|
||||
|
||||
public List<String> getRunList() {
|
||||
return runList;
|
||||
}
|
||||
|
||||
@SerializedName("chef_type")
|
||||
private String _chefType = "node";
|
||||
|
||||
@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 + ((automatic == null) ? 0 : automatic.hashCode());
|
||||
result = prime * result + ((defaultA == null) ? 0 : defaultA.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((normal == null) ? 0 : normal.hashCode());
|
||||
result = prime * result + ((override == null) ? 0 : override.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;
|
||||
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 (automatic == null) {
|
||||
if (other.automatic != null)
|
||||
return false;
|
||||
} else if (!automatic.equals(other.automatic))
|
||||
return false;
|
||||
if (defaultA == null) {
|
||||
if (other.defaultA != null)
|
||||
return false;
|
||||
} else if (!defaultA.equals(other.defaultA))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (normal == null) {
|
||||
if (other.normal != null)
|
||||
return false;
|
||||
} else if (!normal.equals(other.normal))
|
||||
return false;
|
||||
if (override == null) {
|
||||
if (other.override != null)
|
||||
return false;
|
||||
} else if (!override.equals(other.override))
|
||||
return false;
|
||||
if (runList == null) {
|
||||
if (other.runList != null)
|
||||
return false;
|
||||
} else if (!runList.equals(other.runList))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jclouds.io.payloads.FilePayload;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
|
||||
/**
|
||||
* Cookbook object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Resource {
|
||||
|
||||
private String name;
|
||||
private URI url;
|
||||
private byte[] checksum;
|
||||
private String path;
|
||||
private String specificity;
|
||||
|
||||
public Resource(FilePayload payload) {
|
||||
this(payload.getRawContent().getName(), null, payload.getContentMD5(), payload
|
||||
.getRawContent().getPath(), "default");
|
||||
}
|
||||
|
||||
public Resource(String name, byte[] checksum, String path) {
|
||||
this(name, null, checksum, path, "default");
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
// hidden but needs to be here for json deserialization to work
|
||||
Resource() {
|
||||
}
|
||||
|
||||
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 + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Sandbox object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Role {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
@SerializedName("override_attributes")
|
||||
private Map<String, JsonBall> override = Maps.newLinkedHashMap();
|
||||
@SerializedName("default_attributes")
|
||||
private Map<String, JsonBall> defaultA = Maps.newLinkedHashMap();
|
||||
@SerializedName("run_list")
|
||||
private List<String> runList = Lists.newArrayList();
|
||||
|
||||
// internal
|
||||
@SerializedName("json_class")
|
||||
private String _jsonClass = "Chef::Role";
|
||||
@SerializedName("chef_type")
|
||||
private String _chefType = "role";
|
||||
|
||||
public Role(String name, String description, Map<String, JsonBall> defaultA, List<String> runList,
|
||||
Map<String, JsonBall> override) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultA = defaultA;
|
||||
this.runList = runList;
|
||||
this.override = override;
|
||||
}
|
||||
|
||||
public Role(String name, Iterable<String> runList) {
|
||||
this.name = name;
|
||||
Iterables.addAll(this.runList, runList);
|
||||
}
|
||||
|
||||
// hidden but needs to be here for json deserialization to work
|
||||
Role() {
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Map<String, JsonBall> getOverride() {
|
||||
return override;
|
||||
}
|
||||
|
||||
public Map<String, JsonBall> getDefault() {
|
||||
return defaultA;
|
||||
}
|
||||
|
||||
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 + ((defaultA == null) ? 0 : defaultA.hashCode());
|
||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((override == null) ? 0 : override.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 (defaultA == null) {
|
||||
if (other.defaultA != null)
|
||||
return false;
|
||||
} else if (!defaultA.equals(other.defaultA))
|
||||
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 (override == null) {
|
||||
if (other.override != null)
|
||||
return false;
|
||||
} else if (!override.equals(other.override))
|
||||
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 "[name=" + name + ", description=" + description + ", defaultA=" + defaultA + ", override=" + override
|
||||
+ ", runList=" + runList + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Sandbox object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Sandbox {
|
||||
|
||||
@SerializedName("_rev")
|
||||
private String rev;
|
||||
@SerializedName("is_completed")
|
||||
private boolean isCompleted;
|
||||
@SerializedName("create_time")
|
||||
private Date createTime;
|
||||
private Set<String> checksums = Sets.newLinkedHashSet();
|
||||
private String name;
|
||||
private String guid;
|
||||
|
||||
// internal
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("json_class")
|
||||
private String _jsonClass = "Chef::Sandbox";
|
||||
@SerializedName("chef_type")
|
||||
@SuppressWarnings("unused")
|
||||
private String _chefType = "sandbox";
|
||||
|
||||
public Sandbox(String rev, boolean isCompleted, Date createTime, Iterable<String> checksums, String name, String guid) {
|
||||
this.rev = rev;
|
||||
this.isCompleted = isCompleted;
|
||||
this.createTime = createTime;
|
||||
Iterables.addAll(this.checksums, checksums);
|
||||
this.name = name;
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
public Sandbox() {
|
||||
|
||||
}
|
||||
|
||||
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 + "]";
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class SearchResult<T> extends LinkedHashSet<T> {
|
||||
private long start;
|
||||
|
||||
SearchResult() {
|
||||
}
|
||||
|
||||
public SearchResult(long start, Iterable<T> results) {
|
||||
this.start = start;
|
||||
Iterables.addAll(this, results);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 4000610660948065287L;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the result position this started from from
|
||||
*/
|
||||
long getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class UploadSandbox {
|
||||
private URI uri;
|
||||
private Map<List<Byte>, ChecksumStatus> checksums = Maps.newLinkedHashMap();
|
||||
@SerializedName("sandbox_id")
|
||||
private String sandboxId;
|
||||
|
||||
public UploadSandbox(URI uri, Map<List<Byte>, ChecksumStatus> checksums, String sandboxId) {
|
||||
this.uri = uri;
|
||||
this.checksums.putAll(checksums);
|
||||
this.sandboxId = sandboxId;
|
||||
}
|
||||
|
||||
public UploadSandbox() {
|
||||
|
||||
}
|
||||
|
||||
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 "UploadSite [checksums=" + checksums + ", id=" + sandboxId + ", uri=" + uri + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.filters;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.jclouds.Constants.PROPERTY_IDENTITY;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Collections;
|
||||
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.crypto.CryptoStreams;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
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.InputSuppliers;
|
||||
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.Utils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
/**
|
||||
* Ported from mixlib-authentication in order to sign Chef requests.
|
||||
*
|
||||
* @see <a href= "http://github.com/opscode/mixlib-authentication" />
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class SignedHeaderAuth implements HttpRequestFilter {
|
||||
public static final String SIGNING_DESCRIPTION = "version=1.0";
|
||||
|
||||
private final SignatureWire signatureWire;
|
||||
private final String userId;
|
||||
private final PrivateKey privateKey;
|
||||
private final Provider<String> timeStampProvider;
|
||||
private final Crypto crypto;
|
||||
private final String emptyStringHash;
|
||||
private final HttpUtils utils;
|
||||
|
||||
@Resource
|
||||
@Named(Constants.LOGGER_SIGNATURE)
|
||||
Logger signatureLog = Logger.NULL;
|
||||
|
||||
@Inject
|
||||
public SignedHeaderAuth(SignatureWire signatureWire, @Named(PROPERTY_IDENTITY) String userId, PrivateKey privateKey,
|
||||
@TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) {
|
||||
this.signatureWire = signatureWire;
|
||||
this.userId = userId;
|
||||
this.privateKey = privateKey;
|
||||
this.timeStampProvider = timeStampProvider;
|
||||
this.crypto = crypto;
|
||||
this.emptyStringHash = hashBody(Payloads.newStringPayload(""));
|
||||
this.utils = utils;
|
||||
}
|
||||
|
||||
public void filter(HttpRequest request) throws HttpException {
|
||||
|
||||
String contentHash = hashBody(request.getPayload());
|
||||
request.getHeaders().replaceValues("X-Ops-Content-Hash", Collections.singletonList(contentHash));
|
||||
String timestamp = timeStampProvider.get();
|
||||
String toSign = createStringToSign(request.getMethod(), hashPath(request.getEndpoint().getPath()), contentHash,
|
||||
timestamp);
|
||||
request.getHeaders().replaceValues("X-Ops-Userid", Collections.singletonList(userId));
|
||||
request.getHeaders().replaceValues("X-Ops-Sign", Collections.singletonList(SIGNING_DESCRIPTION));
|
||||
calculateAndReplaceAuthorizationHeaders(request, toSign);
|
||||
request.getHeaders().replaceValues("X-Ops-Timestamp", Collections.singletonList(timestamp));
|
||||
utils.logRequest(signatureLog, request, "<<");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void calculateAndReplaceAuthorizationHeaders(HttpRequest request, String toSign) throws HttpException {
|
||||
String signature = sign(toSign);
|
||||
if (signatureWire.enabled())
|
||||
signatureWire.input(Utils.toInputStream(signature));
|
||||
String[] signatureLines = Iterables.toArray(Splitter.fixedLength(60).split(signature), String.class);
|
||||
for (int i = 0; i < signatureLines.length; i++) {
|
||||
request.getHeaders().replaceValues("X-Ops-Authorization-" + (i + 1),
|
||||
Collections.singletonList(signatureLines[i]));
|
||||
}
|
||||
}
|
||||
|
||||
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(userId).toString();
|
||||
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String hashPath(String path) {
|
||||
try {
|
||||
return CryptoStreams.base64(CryptoStreams.digest(InputSuppliers.of(canonicalPath(path)), crypto.sha1()));
|
||||
} 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 CryptoStreams.base64(CryptoStreams.digest(payload, crypto.sha1()));
|
||||
} 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 = ByteStreams.toByteArray(new RSAEncryptingPayload(Payloads.newStringPayload(toSign),
|
||||
privateKey));
|
||||
return CryptoStreams.base64(encrypted);
|
||||
} catch (Exception e) {
|
||||
throw new HttpException("error signing request", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.ChefClient;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* Generates a client relevant for a particular tag
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ClientForTag implements Function<String, Client> {
|
||||
private final ChefClient chefClient;
|
||||
|
||||
@Inject
|
||||
public ClientForTag(ChefClient chefClient) {
|
||||
this.chefClient = checkNotNull(chefClient, "chefClient");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Client apply(String from) {
|
||||
String clientName = findNextClientName(chefClient.listClients(), from + "-validator-%02d");
|
||||
Client client = chefClient.createClient(clientName);
|
||||
// response from create only includes the key
|
||||
return new Client(null, null, clientName, clientName, false, client.getPrivateKey());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@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 arg0) {
|
||||
return json.apply(arg0).keySet();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ParseSearchClientsFromJson extends ParseSearchResultFromJson<Client> {
|
||||
|
||||
// TODO add generic json parser detector
|
||||
|
||||
@Inject
|
||||
ParseSearchClientsFromJson(ParseJson<Response<Client>> json) {
|
||||
super(json);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.functions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ParseSearchDatabagFromJson extends ParseSearchResultFromJson<DatabagItem> {
|
||||
|
||||
// TODO add generic json parser detector
|
||||
|
||||
@Inject
|
||||
ParseSearchDatabagFromJson(ParseJson<Response<DatabagItem>> json) {
|
||||
super(json);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ParseSearchNodesFromJson extends ParseSearchResultFromJson<Node> {
|
||||
|
||||
// TODO add generic json parser detector
|
||||
|
||||
@Inject
|
||||
ParseSearchNodesFromJson(ParseJson<Response<Node>> json) {
|
||||
super(json);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@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 arg0) {
|
||||
Response<T> returnVal = json.apply(arg0);
|
||||
return new SearchResult<T>(returnVal.start, returnVal.rows);
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ParseSearchRolesFromJson extends ParseSearchResultFromJson<Role> {
|
||||
|
||||
// TODO add generic json parser detector
|
||||
|
||||
@Inject
|
||||
ParseSearchRolesFromJson(ParseJson<Response<Role>> json) {
|
||||
super(json);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.reference.ChefConstants.CHEF_BOOTSTRAP_DATABAG;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.json.Json;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
*
|
||||
* Retrieves the run-list for a specific tag
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class RunListForTag implements Function<String, List<String>> {
|
||||
public static final Type RUN_LIST_TYPE = new TypeLiteral<Map<String, List<String>>>() {
|
||||
}.getType();
|
||||
private final ChefClient client;
|
||||
private final Json json;
|
||||
private final String databag;
|
||||
|
||||
@Inject
|
||||
public RunListForTag(@Named(CHEF_BOOTSTRAP_DATABAG) String databag, ChefClient client, Json json) {
|
||||
this.databag = checkNotNull(databag, "databag");
|
||||
this.client = checkNotNull(client, "client");
|
||||
this.json = checkNotNull(json, "json");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<String> apply(String from) {
|
||||
DatabagItem list = client.getDatabagItem(databag, from);
|
||||
checkState(list != null, "databag item %s/%s not found", databag, from);
|
||||
return ((Map<String, List<String>>) json.fromJson(list.toString(), RUN_LIST_TYPE)).get("run_list");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.io.Payloads.newStringPayload;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.createFile;
|
||||
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.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.crypto.Pems;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.rest.annotations.Provider;
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
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 tag
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class TagToBootScript implements Function<String, Payload> {
|
||||
@VisibleForTesting
|
||||
static final Type RUN_LIST_TYPE = new TypeLiteral<Map<String, List<String>>>() {
|
||||
}.getType();
|
||||
private final URI endpoint;
|
||||
private final Json json;
|
||||
private final Map<String, Client> tagToClient;
|
||||
private final Map<String, List<String>> runListForTag;
|
||||
private final Statement installChefGems;
|
||||
|
||||
@Inject
|
||||
public TagToBootScript(@Provider URI endpoint, Json json, Map<String, Client> tagToClient,
|
||||
Map<String, List<String>> runListForTag, @Named("installChefGems") Statement installChefGems) {
|
||||
this.endpoint = checkNotNull(endpoint, "endpoint");
|
||||
this.json = checkNotNull(json, "json");
|
||||
this.tagToClient = checkNotNull(tagToClient, "tagToClient");
|
||||
this.runListForTag = checkNotNull(runListForTag, "runListForTag");
|
||||
this.installChefGems = checkNotNull(installChefGems, "installChefGems");
|
||||
}
|
||||
|
||||
public Payload apply(String tag) {
|
||||
checkNotNull(tag, "tag");
|
||||
|
||||
Client client = tagToClient.get(tag);
|
||||
checkState(client != null, "could not get a client for tag %s", tag);
|
||||
checkState(client.getClientname() != null, "clientname null for %s", client);
|
||||
checkState(client.getPrivateKey() != null, "privatekey null for %s", client);
|
||||
|
||||
List<String> runList = runListForTag.get(tag);
|
||||
checkState(runList != null, "runList for %s was not found", tag);
|
||||
checkState(runList.size() > 0, "runList for %s was empty", tag);
|
||||
|
||||
String chefConfigDir = "{root}etc{fs}chef";
|
||||
Statement createChefConfigDir = exec("{md} " + chefConfigDir);
|
||||
Statement createClientRb = createFile(chefConfigDir + "{fs}client.rb", ImmutableList.of("require 'rubygems'",
|
||||
"require 'ohai'", "o = Ohai::System.new", "o.all_plugins", String.format(
|
||||
"node_name \"%s-\" + o[:ipaddress]", tag), "log_level :info", "log_location STDOUT", String
|
||||
.format("validation_client_name \"%s\"", client.getClientname()), String.format(
|
||||
"chef_server_url \"%s\"", endpoint)));
|
||||
|
||||
Statement createValidationPem = createFile(chefConfigDir + "{fs}validation.pem", Splitter.on('\n').split(
|
||||
Pems.pem(client.getPrivateKey())));
|
||||
|
||||
String chefBootFile = chefConfigDir + "{fs}first-boot.json";
|
||||
|
||||
Statement createFirstBoot = createFile(chefBootFile, Collections.singleton(json.toJson(ImmutableMap
|
||||
.<String, List<String>> of("run_list", runList), RUN_LIST_TYPE)));
|
||||
|
||||
Statement runChef = exec("chef-client -j " + chefBootFile);
|
||||
|
||||
Statement bootstrapAndRunChef = newStatementList(installChefGems, createChefConfigDir, createClientRb,
|
||||
createValidationPem, createFirstBoot, runChef);
|
||||
|
||||
String runScript = bootstrapAndRunChef.render(OsFamily.UNIX);
|
||||
return newStringPayload(runScript);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChefClientErrorRetryHandler 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
|
||||
ChefClientErrorRetryHandler(BackoffLimitedRetryHandler backoffLimitedRetryHandler) {
|
||||
this.backoffLimitedRetryHandler = backoffLimitedRetryHandler;
|
||||
}
|
||||
|
||||
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||
if (command.getFailureCount() > retryCountLimit)
|
||||
return false;
|
||||
if (response.getStatusCode() == 400 && command.getRequest().getMethod().equals("PUT")
|
||||
&& command.getRequest().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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.handlers;
|
||||
|
||||
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;
|
||||
|
||||
import com.google.common.io.Closeables;
|
||||
|
||||
/**
|
||||
* This will parse and set an appropriate exception on the command object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@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.getRequest()
|
||||
.getRequestLine(), response.getStatusLine());
|
||||
switch (response.getStatusCode()) {
|
||||
case 401:
|
||||
case 403:
|
||||
exception = new AuthorizationException(message, exception);
|
||||
break;
|
||||
case 404:
|
||||
if (!command.getRequest().getMethod().equals("DELETE")) {
|
||||
exception = new ResourceNotFoundException(message, exception);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
if (response.getPayload() != null)
|
||||
Closeables.closeQuietly(response.getPayload().getInput());
|
||||
command.setException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.internal;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||
import static org.jclouds.chef.reference.ChefConstants.CHEF_BOOTSTRAP_DATABAG;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.PropertiesBuilder;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
|
||||
/**
|
||||
* Builds properties used in Chef Clients
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public abstract class BaseChefPropertiesBuilder extends PropertiesBuilder {
|
||||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_SESSION_INTERVAL, "1");
|
||||
properties.setProperty(PROPERTY_API_VERSION, ChefAsyncClient.VERSION);
|
||||
properties.setProperty(CHEF_BOOTSTRAP_DATABAG, "bootstrap");
|
||||
return properties;
|
||||
}
|
||||
|
||||
public BaseChefPropertiesBuilder(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
}
|
|
@ -1,227 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.chef.reference.ChefConstants.CHEF_BOOTSTRAP_DATABAG;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.ChefContext;
|
||||
import org.jclouds.chef.ChefService;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.functions.RunListForTag;
|
||||
import org.jclouds.chef.functions.TagToBootScript;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
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.ListNodes;
|
||||
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.io.payloads.RSADecryptingPayload;
|
||||
import org.jclouds.io.payloads.RSAEncryptingPayload;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.InputSupplier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BaseChefService implements ChefService {
|
||||
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final ChefContext chefContext;
|
||||
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 Provider<PrivateKey> privateKey;
|
||||
private final TagToBootScript tagToBootScript;
|
||||
private final String databag;
|
||||
private final RunListForTag runListForTag;
|
||||
private final ListCookbookVersions listCookbookVersions;
|
||||
|
||||
@Inject
|
||||
protected BaseChefService(ChefContext chefContext, CleanupStaleNodesAndClients cleanupStaleNodesAndClients,
|
||||
CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes,
|
||||
DeleteAllNodesInList deleteAllNodesInList, ListNodes listNodes,
|
||||
DeleteAllClientsInList deleteAllClientsInList, ListClients listClients,
|
||||
ListCookbookVersions listCookbookVersions, UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode,
|
||||
Provider<PrivateKey> privateKey, @Named(CHEF_BOOTSTRAP_DATABAG) String databag,
|
||||
TagToBootScript tagToBootScript, RunListForTag runListForTag) {
|
||||
this.chefContext = checkNotNull(chefContext, "chefContext");
|
||||
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.tagToBootScript = checkNotNull(tagToBootScript, "tagToBootScript");
|
||||
this.databag = checkNotNull(databag, "databag");
|
||||
this.runListForTag = checkNotNull(runListForTag, "runListForTag");
|
||||
}
|
||||
|
||||
@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 deleteAllNodesInList(Iterable<String> names) {
|
||||
deleteAllNodesInList.execute(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> listNodes() {
|
||||
return listNodes.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> listNodesMatching(Predicate<String> nodeNameSelector) {
|
||||
return listNodes.execute(nodeNameSelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> listNodesNamed(Iterable<String> names) {
|
||||
return listNodes.execute(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllClientsInList(Iterable<String> names) {
|
||||
deleteAllClientsInList.execute(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Client> listClientsDetails() {
|
||||
return listClients.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Client> listClientsDetailsMatching(Predicate<String> clientNameSelector) {
|
||||
return listClients.execute(clientNameSelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Client> listClientsNamed(Iterable<String> names) {
|
||||
return listClients.execute(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends CookbookVersion> listCookbookVersions() {
|
||||
return listCookbookVersions.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends CookbookVersion> listCookbookVersionsMatching(Predicate<String> cookbookNameSelector) {
|
||||
return listCookbookVersions.execute(cookbookNameSelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends CookbookVersion> listCookbookVersionsNamed(Iterable<String> names) {
|
||||
return listCookbookVersions.execute(names);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateAutomaticAttributesOnNode(String nodeName) {
|
||||
updateAutomaticAttributesOnNode.execute(nodeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChefContext getContext() {
|
||||
return chefContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Payload createClientAndBootstrapScriptForTag(String tag) {
|
||||
return tagToBootScript.apply(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRunListForTag(Iterable<String> runList, String tag) {
|
||||
try {
|
||||
chefContext.getApi().createDatabag(databag);
|
||||
} catch (IllegalStateException e) {
|
||||
|
||||
}
|
||||
chefContext.getApi().updateDatabagItem(
|
||||
databag,
|
||||
new DatabagItem(tag, chefContext.utils().json().toJson(
|
||||
ImmutableMap.<String, List<String>> of("run_list", Lists.newArrayList(runList)),
|
||||
RunListForTag.RUN_LIST_TYPE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRunListForTag(String tag) {
|
||||
return runListForTag.apply(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decrypt(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||
return ByteStreams.toByteArray(new RSADecryptingPayload(Payloads.newPayload(supplier.getInput()), privateKey
|
||||
.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encrypt(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||
return ByteStreams.toByteArray(new RSAEncryptingPayload(Payloads.newPayload(supplier.getInput()), privateKey
|
||||
.get()));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.internal;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.ChefContext;
|
||||
import org.jclouds.chef.ChefService;
|
||||
import org.jclouds.lifecycle.Closer;
|
||||
import org.jclouds.rest.Utils;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
import org.jclouds.rest.annotations.Identity;
|
||||
import org.jclouds.rest.annotations.Provider;
|
||||
import org.jclouds.rest.internal.RestContextImpl;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ChefContextImpl extends RestContextImpl<ChefClient, ChefAsyncClient> implements ChefContext {
|
||||
private final ChefService chefService;
|
||||
|
||||
@Inject
|
||||
protected ChefContextImpl(Closer closer, Utils utils, Injector injector, TypeLiteral<ChefClient> syncApi,
|
||||
TypeLiteral<ChefAsyncClient> asyncApi, @Provider URI endpoint, @Provider String provider,
|
||||
@Identity String identity, @ApiVersion String apiVersion, ChefService chefService) {
|
||||
super(closer, utils, injector, syncApi, asyncApi, endpoint, provider, identity, apiVersion);
|
||||
this.chefService = chefService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChefService getChefService() {
|
||||
return chefService;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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}.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
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 + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.reference;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in Chef connections.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface ChefConstants {
|
||||
/**
|
||||
* There are generally 3 types of identities
|
||||
* <ul>
|
||||
* <li>validator - used to create clients within an organization; {@code orgname}-validator</li>
|
||||
* <li>client - scoped to an organization, used on nodes to run chef</li>
|
||||
* <li>user - used to run commands like knife and access cookbook sites</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The PEM-encoded key
|
||||
*/
|
||||
|
||||
/**
|
||||
* how often to refresh timestamps in seconds.
|
||||
*/
|
||||
|
||||
public static final String CHEF_LOGGER = "jclouds.chef";
|
||||
public static final String CHEF_SERVICE_CLIENT = "chef.service-client";
|
||||
public static final String CHEF_NODE = "chef.node";
|
||||
public static final String CHEF_NODE_PATTERN = "chef.node-pattern";
|
||||
public static final String CHEF_RUN_LIST = "chef.run-list";
|
||||
/**
|
||||
* 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";
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.statements;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class InstallChefGems implements Statement {
|
||||
@Override
|
||||
public String render(OsFamily family) {
|
||||
try {
|
||||
return Utils.toStringAndClose(InstallChefGems.class.getClassLoader().getResourceAsStream(
|
||||
"install-chef-gems.sh"));
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(CleanupStaleNodesAndClientsImpl.class)
|
||||
public interface CleanupStaleNodesAndClients {
|
||||
|
||||
void execute(String prefix, int secondsStale);
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(CreateNodeAndPopulateAutomaticAttributesImpl.class)
|
||||
public interface CreateNodeAndPopulateAutomaticAttributes {
|
||||
Node execute(Node node);
|
||||
|
||||
Node execute(String nodeName, Iterable<String> runList);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy;
|
||||
|
||||
import org.jclouds.chef.strategy.internal.DeleteAllClientsInListImpl;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(DeleteAllClientsInListImpl.class)
|
||||
public interface DeleteAllClientsInList {
|
||||
|
||||
public void execute(Iterable<String> names);
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy;
|
||||
|
||||
import org.jclouds.chef.strategy.internal.DeleteAllNodesInListImpl;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(DeleteAllNodesInListImpl.class)
|
||||
public interface DeleteAllNodesInList {
|
||||
|
||||
public void execute(Iterable<String> names);
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy;
|
||||
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.strategy.internal.ListClientsImpl;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(ListClientsImpl.class)
|
||||
public interface ListClients {
|
||||
|
||||
Iterable<? extends Client> execute();
|
||||
|
||||
Iterable<? extends Client> execute(Predicate<String> clientNameSelector);
|
||||
|
||||
Iterable<? extends Client> execute(Iterable<String> toGet);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy;
|
||||
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.strategy.internal.ListCookbookVersionsImpl;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(ListCookbookVersionsImpl.class)
|
||||
public interface ListCookbookVersions {
|
||||
|
||||
Iterable<? extends CookbookVersion> execute();
|
||||
|
||||
Iterable<? extends CookbookVersion> execute(Predicate<String> cookbookNameSelector);
|
||||
|
||||
Iterable<? extends CookbookVersion> execute(Iterable<String> cookbookNames);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy;
|
||||
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.strategy.internal.ListNodesImpl;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(ListNodesImpl.class)
|
||||
public interface ListNodes {
|
||||
|
||||
Iterable<? extends Node> execute();
|
||||
|
||||
Iterable<? extends Node> execute(Predicate<String> nodeNameSelector);
|
||||
|
||||
Iterable<? extends Node> execute(Iterable<String> toGet);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy;
|
||||
|
||||
import org.jclouds.chef.strategy.internal.UpdateAutomaticAttributesOnNodeImpl;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
* Updates node with new automatic attributes.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(UpdateAutomaticAttributesOnNodeImpl.class)
|
||||
public interface UpdateAutomaticAttributesOnNode {
|
||||
|
||||
public void execute(String nodeName);
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.domain.Node;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
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 clients who have been hanging around too long.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClients {
|
||||
@Resource
|
||||
@Named(ChefConstants.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(new Predicate<String>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
return input.startsWith(prefix);
|
||||
}
|
||||
|
||||
}), and(notNull(), new Predicate<Node>() {
|
||||
@Override
|
||||
public boolean apply(Node input) {
|
||||
JsonBall dateLong = input.getAutomatic().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);
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.ChefClient;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
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.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class CreateNodeAndPopulateAutomaticAttributesImpl implements CreateNodeAndPopulateAutomaticAttributes {
|
||||
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final ChefClient chef;
|
||||
private final Supplier<Map<String, JsonBall>> automaticSupplier;
|
||||
|
||||
@Inject
|
||||
public CreateNodeAndPopulateAutomaticAttributesImpl(ChefClient 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.getAutomatic().putAll(automaticSupplier.get());
|
||||
chef.createNode(node);
|
||||
logger.debug("created node %s", node.getName());
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node execute(String nodeName, Iterable<String> runList) {
|
||||
return execute(new Node(nodeName, runList));
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy.internal;
|
||||
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.chef.strategy.DeleteAllClientsInList;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class DeleteAllClientsInListImpl implements DeleteAllClientsInList {
|
||||
|
||||
protected final ChefClient chefClient;
|
||||
protected final ChefAsyncClient chefAsyncClient;
|
||||
protected final ExecutorService userExecutor;
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject(optional = true)
|
||||
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||
protected Long maxTime;
|
||||
|
||||
@Inject
|
||||
DeleteAllClientsInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||
ChefClient getAllClient, ChefAsyncClient ablobstore) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.chefAsyncClient = ablobstore;
|
||||
this.chefClient = getAllClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Iterable<String> names) {
|
||||
Map<String, Exception> exceptions = newHashMap();
|
||||
Map<String, Future<?>> responses = newHashMap();
|
||||
for (String name : names) {
|
||||
responses.put(name, chefAsyncClient.deleteClient(name));
|
||||
}
|
||||
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
|
||||
"deleting clients: %s", names));
|
||||
if (exceptions.size() > 0)
|
||||
throw new RuntimeException(String.format("errors deleting clients: %s: %s", names, exceptions));
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy.internal;
|
||||
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.chef.strategy.DeleteAllNodesInList;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class DeleteAllNodesInListImpl implements DeleteAllNodesInList {
|
||||
|
||||
protected final ChefClient chefClient;
|
||||
protected final ChefAsyncClient chefAsyncClient;
|
||||
protected final ExecutorService userExecutor;
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject(optional = true)
|
||||
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||
protected Long maxTime;
|
||||
|
||||
@Inject
|
||||
DeleteAllNodesInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||
ChefClient getAllNode, ChefAsyncClient ablobstore) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.chefAsyncClient = ablobstore;
|
||||
this.chefClient = getAllNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Iterable<String> names) {
|
||||
Map<String, Exception> exceptions = newHashMap();
|
||||
Map<String, Future<?>> responses = newHashMap();
|
||||
for (String name : names) {
|
||||
responses.put(name, chefAsyncClient.deleteNode(name));
|
||||
}
|
||||
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
|
||||
"deleting nodes: %s", names));
|
||||
if (exceptions.size() > 0)
|
||||
throw new RuntimeException(String.format("errors deleting nodes: %s: %s", names, exceptions));
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy.internal;
|
||||
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.chef.strategy.ListClients;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ListClientsImpl implements ListClients {
|
||||
|
||||
protected final ChefClient chefClient;
|
||||
protected final ChefAsyncClient chefAsyncClient;
|
||||
protected final ExecutorService userExecutor;
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject(optional = true)
|
||||
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||
protected Long maxTime;
|
||||
|
||||
@Inject
|
||||
ListClientsImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ChefClient getAllClient,
|
||||
ChefAsyncClient ablobstore) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.chefAsyncClient = ablobstore;
|
||||
this.chefClient = getAllClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Client> execute() {
|
||||
return execute(chefClient.listClients());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Client> execute(Predicate<String> clientNameSelector) {
|
||||
return execute(filter(chefClient.listClients(), clientNameSelector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Client> execute(Iterable<String> toGet) {
|
||||
return transformParallel(toGet, new Function<String, Future<Client>>() {
|
||||
|
||||
@Override
|
||||
public Future<Client> apply(String from) {
|
||||
return chefAsyncClient.getClient(from);
|
||||
}
|
||||
|
||||
}, userExecutor, maxTime, logger, "getting clients");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy.internal;
|
||||
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.chef.strategy.ListCookbookVersions;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ListCookbookVersionsImpl implements ListCookbookVersions {
|
||||
|
||||
protected final ChefClient chefClient;
|
||||
protected final ChefAsyncClient chefAsyncClient;
|
||||
protected final ExecutorService userExecutor;
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject(optional = true)
|
||||
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||
protected Long maxTime;
|
||||
|
||||
@Inject
|
||||
ListCookbookVersionsImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||
ChefClient getAllCookbookVersion, ChefAsyncClient ablobstore) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.chefAsyncClient = ablobstore;
|
||||
this.chefClient = getAllCookbookVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends CookbookVersion> execute() {
|
||||
return execute(chefClient.listCookbooks());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends CookbookVersion> execute(Predicate<String> cookbookNameSelector) {
|
||||
return execute(filter(chefClient.listCookbooks(), cookbookNameSelector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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
|
||||
return transformParallel(chefClient.getVersionsOfCookbook(cookbook),
|
||||
new Function<String, Future<CookbookVersion>>() {
|
||||
|
||||
@Override
|
||||
public Future<CookbookVersion> apply(String version) {
|
||||
return chefAsyncClient.getCookbook(cookbook, version);
|
||||
}
|
||||
|
||||
}, userExecutor, maxTime, logger, "getting versions of cookbook " + cookbook);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.strategy.internal;
|
||||
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.chef.strategy.ListNodes;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ListNodesImpl implements ListNodes {
|
||||
|
||||
protected final ChefClient chefClient;
|
||||
protected final ChefAsyncClient chefAsyncClient;
|
||||
protected final ExecutorService userExecutor;
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject(optional = true)
|
||||
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||
protected Long maxTime;
|
||||
|
||||
@Inject
|
||||
ListNodesImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ChefClient getAllNode,
|
||||
ChefAsyncClient ablobstore) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.chefAsyncClient = ablobstore;
|
||||
this.chefClient = getAllNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> execute() {
|
||||
return execute(chefClient.listNodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> execute(Predicate<String> nodeNameSelector) {
|
||||
return execute(filter(chefClient.listNodes(), nodeNameSelector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> execute(Iterable<String> toGet) {
|
||||
return transformParallel(toGet, new Function<String, Future<Node>>() {
|
||||
|
||||
@Override
|
||||
public Future<Node> apply(String from) {
|
||||
return chefAsyncClient.getNode(from);
|
||||
}
|
||||
|
||||
}, userExecutor, maxTime, logger, "getting nodes");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.ChefClient;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
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.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class UpdateAutomaticAttributesOnNodeImpl implements UpdateAutomaticAttributesOnNode {
|
||||
|
||||
@Resource
|
||||
@Named(ChefConstants.CHEF_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final ChefClient chef;
|
||||
private final Supplier<Map<String, JsonBall>> automaticSupplier;
|
||||
|
||||
@Inject
|
||||
public UpdateAutomaticAttributesOnNodeImpl(ChefClient 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.getAutomatic().putAll(automaticSupplier.get());
|
||||
chef.updateNode(node);
|
||||
logger.debug("updated node %s", nodeName);
|
||||
}
|
||||
}
|
|
@ -1,346 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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 static org.jclouds.concurrent.Futures.compose;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.blobstore.TransientAsyncBlobStore;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
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.util.Utils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* In-memory chef simulator.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
||||
public class TransientChefAsyncClient implements ChefAsyncClient {
|
||||
@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(), Utils.toStringAndClose(from
|
||||
.getPayload().getInput()));
|
||||
} catch (IOException e) {
|
||||
propagate(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final TransientAsyncBlobStore databags;
|
||||
private final ExecutorService executor;
|
||||
private final BlobToDatabagItem blobToDatabagItem;
|
||||
private final StorageMetadataToName storageMetadataToName;
|
||||
|
||||
@Inject
|
||||
TransientChefAsyncClient(@Named("databags") TransientAsyncBlobStore databags,
|
||||
StorageMetadataToName storageMetadataToName, BlobToDatabagItem blobToDatabagItem,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.databags = checkNotNull(databags, "databags");
|
||||
this.storageMetadataToName = checkNotNull(storageMetadataToName, "storageMetadataToName");
|
||||
this.blobToDatabagItem = checkNotNull(blobToDatabagItem, "blobToDatabagItem");
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> clientExists(String clientname) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Sandbox> commitSandbox(String id, boolean isCompleted) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Client> createClient(String clientname) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> createDatabag(String databagName) {
|
||||
return databags.createContainerInLocationIfAbsent(null, databagName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<DatabagItem> createDatabagItem(String databagName, DatabagItem databagItem) {
|
||||
Blob blob = databags.newBlob(databagItem.getId());
|
||||
blob.setPayload(databagItem.toString());
|
||||
databags.putBlobAndReturnOld(databagName, blob);
|
||||
return Futures.immediateFuture(databagItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> createNode(Node node) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> createRole(Role role) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> databagExists(String databagName) {
|
||||
return databags.containerExists(databagName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> databagItemExists(String databagName, String databagItemId) {
|
||||
return databags.blobExists(databagName, databagItemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Client> deleteClient(String clientname) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<CookbookVersion> deleteCookbook(String cookbookName, String version) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> deleteDatabag(String databagName) {
|
||||
return databags.deleteContainer(databagName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<DatabagItem> deleteDatabagItem(String databagName, String databagItemId) {
|
||||
return compose(databags.removeBlobAndReturnOld(databagName, databagItemId), blobToDatabagItem, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Node> deleteNode(String nodename) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Role> deleteRole(String rolename) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Client> generateKeyForClient(String clientname) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Client> getClient(String clientname) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<CookbookVersion> getCookbook(String cookbookName, String version) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<DatabagItem> getDatabagItem(String databagName, String databagItemId) {
|
||||
return compose(databags.getBlob(databagName, databagItemId), blobToDatabagItem, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Node> getNode(String nodename) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Role> getRole(String rolename) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<UploadSandbox> getUploadSandboxForChecksums(Set<List<Byte>> md5s) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> getVersionsOfCookbook(String cookbookName) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listClients() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listCookbooks() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listDatabagItems(String databagName) {
|
||||
return compose(databags.list(databagName), storageMetadataToName, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listDatabags() {
|
||||
return compose(databags.list(), storageMetadataToName, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listNodes() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listRoles() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<String>> listSearchIndexes() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> nodeExists(String nodename) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> roleExists(String rolename) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<? extends SearchResult<? extends Client>> searchClients() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<? extends SearchResult<? extends DatabagItem>> searchDatabag(String databagName) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<? extends SearchResult<? extends Node>> searchNodes() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<? extends SearchResult<? extends Role>> searchRoles() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<CookbookVersion> updateCookbook(String cookbookName, String version, CookbookVersion cookbook) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<DatabagItem> updateDatabagItem(String databagName, DatabagItem item) {
|
||||
return createDatabagItem(databagName, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Node> updateNode(Node node) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Role> updateRole(Role role) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> uploadContent(Set<List<Byte>> md5s) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
|
||||
/**
|
||||
* In-memory chef simulator.
|
||||
* <p/>
|
||||
*
|
||||
* @see ChefAsyncClient
|
||||
* @see <a href="TODO: insert URL of Chef documentation" />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.MILLISECONDS)
|
||||
public interface TransientChefClient extends ChefClient {
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.ChefContextBuilder;
|
||||
import org.jclouds.chef.test.config.TransientChefClientModule;
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class TransientChefContextBuilder extends ChefContextBuilder {
|
||||
|
||||
public TransientChefContextBuilder(Properties props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addClientModule(List<Module> modules) {
|
||||
modules.add(new TransientChefClientModule());
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.chef.test.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.TransientAsyncBlobStore;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.config.BaseChefRestClientModule;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.functions.ClientForTag;
|
||||
import org.jclouds.chef.functions.RunListForTag;
|
||||
import org.jclouds.chef.statements.InstallChefGems;
|
||||
import org.jclouds.chef.test.TransientChefAsyncClient;
|
||||
import org.jclouds.chef.test.TransientChefClient;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class TransientChefClientModule extends BaseChefRestClientModule<TransientChefClient, ChefAsyncClient> {
|
||||
|
||||
public TransientChefClientModule() {
|
||||
super(TransientChefClient.class, ChefAsyncClient.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(TransientAsyncBlobStore.class).annotatedWith(Names.named("databags")).toInstance(
|
||||
new RestContextFactory().createContextBuilder("transient", "foo", "bar").buildInjector().getInstance(
|
||||
TransientAsyncBlobStore.class));
|
||||
bind(Statement.class).annotatedWith(Names.named("installChefGems")).to(InstallChefGems.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindAsyncClient() {
|
||||
bind(ChefAsyncClient.class).to(TransientChefAsyncClient.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ChefClient provideClient(TransientChefClient in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Map<String, List<String>> runListForTag(RunListForTag runListForTag) {
|
||||
return new MapMaker().makeComputingMap(runListForTag);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Map<String, Client> tagToClient(ClientForTag tagToClient) {
|
||||
return new MapMaker().makeComputingMap(tagToClient);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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 org.jclouds.ohai.config.multibindings.MapBinder;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target( { TYPE, METHOD, PARAMETER })
|
||||
@Qualifier
|
||||
public @interface Automatic {
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.ohai.config.ConfiguresOhai;
|
||||
import org.jclouds.ohai.config.JMXOhaiModule;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.jclouds.rest.RestContextBuilder;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* @see RestContext
|
||||
*/
|
||||
public class OhaiContextBuilder<S, A> extends RestContextBuilder<S, A> {
|
||||
|
||||
@Inject
|
||||
public OhaiContextBuilder(Class<S> syncClientClass, Class<A> asyncClientClass, Properties properties) {
|
||||
super(syncClientClass, asyncClientClass, properties);
|
||||
}
|
||||
|
||||
protected void addOhaiModuleIfNotPresent() {
|
||||
if (!Iterables.any(modules, new Predicate<Module>() {
|
||||
public boolean apply(Module input) {
|
||||
return input.getClass().isAnnotationPresent(ConfiguresOhai.class);
|
||||
}
|
||||
|
||||
})) {
|
||||
addOhaiModule();
|
||||
}
|
||||
}
|
||||
|
||||
protected void addOhaiModule() {
|
||||
modules.add(new JMXOhaiModule());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(TYPE)
|
||||
public @interface ConfiguresOhai {
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
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.config.multibindings.MapBinder;
|
||||
import org.jclouds.ohai.suppliers.UptimeSecondsSupplier;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Wires the components needed to parse ohai data from a JVM
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.config;
|
||||
|
||||
import static org.jclouds.chef.util.ChefUtils.ohaiAutomaticAttributeBinder;
|
||||
import static org.jclouds.chef.util.ChefUtils.toOhaiTime;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.ohai.Automatic;
|
||||
import org.jclouds.ohai.AutomaticSupplier;
|
||||
import org.jclouds.ohai.config.multibindings.MapBinder;
|
||||
import org.jclouds.ohai.functions.ByteArrayToMacAddress;
|
||||
import org.jclouds.ohai.functions.MapSetToMultimap;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Wires the components needed to parse ohai data
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ConfiguresOhai
|
||||
public class OhaiModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(new TypeLiteral<Function<byte[], String>>() {
|
||||
}).to(new TypeLiteral<ByteArrayToMacAddress>() {
|
||||
});
|
||||
bindOhai();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Automatic
|
||||
protected Supplier<Map<String, JsonBall>> provideAutomatic(AutomaticSupplier in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Automatic
|
||||
Multimap<String, Supplier<JsonBall>> provideAutomatic(MapSetToMultimap<String, Supplier<JsonBall>> converter,
|
||||
@Automatic Map<String, Set<Supplier<JsonBall>>> input) {
|
||||
return converter.apply(input);
|
||||
|
||||
}
|
||||
|
||||
@Named("systemProperties")
|
||||
@Provides
|
||||
protected Properties systemProperties() {
|
||||
return System.getProperties();
|
||||
}
|
||||
|
||||
public MapBinder<String, Supplier<JsonBall>> bindOhai() {
|
||||
MapBinder<String, Supplier<JsonBall>> mapbinder = ohaiAutomaticAttributeBinder(binder()).permitDuplicates();
|
||||
mapbinder.addBinding("ohai_time").to(OhaiTimeProvider.class);
|
||||
mapbinder.addBinding("jvm/system").to(SystemPropertiesProvider.class);
|
||||
mapbinder.addBinding("platform").to(PlatformProvider.class);
|
||||
mapbinder.addBinding("platform_version").to(PlatformVersionProvider.class);
|
||||
mapbinder.addBinding("current_user").to(CurrentUserProvider.class);
|
||||
return mapbinder;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class OhaiTimeProvider implements Supplier<JsonBall> {
|
||||
private final Provider<Long> timeProvider;
|
||||
|
||||
@Inject
|
||||
OhaiTimeProvider(Provider<Long> timeProvider) {
|
||||
this.timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonBall get() {
|
||||
return toOhaiTime(timeProvider.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Provides
|
||||
protected Long millis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class SystemPropertiesProvider implements Supplier<JsonBall> {
|
||||
|
||||
private final Json json;
|
||||
private final Properties systemProperties;
|
||||
|
||||
@Inject
|
||||
SystemPropertiesProvider(Json json, @Named("systemProperties") Properties systemProperties) {
|
||||
this.json = json;
|
||||
this.systemProperties = systemProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonBall get() {
|
||||
return new JsonBall(json.toJson(systemProperties));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class PlatformProvider extends SystemPropertyProvider {
|
||||
|
||||
@Inject
|
||||
PlatformProvider(@Named("systemProperties") Properties systemProperties) {
|
||||
super("os.name", systemProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonBall get() {
|
||||
JsonBall returnValue = super.get();
|
||||
return returnValue != null ? new JsonBall(returnValue.toString().replaceAll("[ -]", "").toLowerCase()) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class PlatformVersionProvider extends SystemPropertyProvider {
|
||||
|
||||
@Inject
|
||||
PlatformVersionProvider(@Named("systemProperties") Properties systemProperties) {
|
||||
super("os.version", systemProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class CurrentUserProvider extends SystemPropertyProvider {
|
||||
|
||||
@Inject
|
||||
CurrentUserProvider(@Named("systemProperties") Properties systemProperties) {
|
||||
super("user.name", systemProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SystemPropertyProvider implements Supplier<JsonBall> {
|
||||
private final Properties systemProperties;
|
||||
private final String property;
|
||||
|
||||
@Inject
|
||||
SystemPropertyProvider(String property, @Named("systemProperties") Properties systemProperties) {
|
||||
this.property = property;
|
||||
this.systemProperties = systemProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonBall get() {
|
||||
return systemProperties.containsKey(property) ? new JsonBall(systemProperties.getProperty(property)) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.config.multibindings;
|
||||
|
||||
import com.google.inject.BindingAnnotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* An internal binding annotation applied to each element in a multibinding.
|
||||
* All elements are assigned a globally-unique id to allow different modules
|
||||
* to contribute multibindings independently.
|
||||
*
|
||||
* @author jessewilson@google.com (Jesse Wilson)
|
||||
*/
|
||||
@Retention(RUNTIME) @BindingAnnotation
|
||||
@interface Element {
|
||||
String setName();
|
||||
int uniqueId();
|
||||
}
|
|
@ -1,537 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.config.multibindings;
|
||||
|
||||
import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
|
||||
import static org.jclouds.ohai.config.multibindings.Multibinder.checkConfiguration;
|
||||
import static org.jclouds.ohai.config.multibindings.Multibinder.checkNotNull;
|
||||
import static org.jclouds.ohai.config.multibindings.Multibinder.setOf;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.jclouds.ohai.config.multibindings.Multibinder.RealMultibinder;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.binder.LinkedBindingBuilder;
|
||||
import com.google.inject.spi.Dependency;
|
||||
import com.google.inject.spi.ProviderWithDependencies;
|
||||
import com.google.inject.util.Types;
|
||||
|
||||
/**
|
||||
* An API to bind multiple map entries separately, only to later inject them as
|
||||
* a complete map. MapBinder is intended for use in your application's module:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* public class SnacksModule extends AbstractModule {
|
||||
* protected void configure() {
|
||||
* MapBinder<String, Snack> mapbinder
|
||||
* = MapBinder.newMapBinder(binder(), String.class, Snack.class);
|
||||
* mapbinder.addBinding("twix").toInstance(new Twix());
|
||||
* mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
|
||||
* mapbinder.addBinding("skittles").to(Skittles.class);
|
||||
* }
|
||||
* }</code>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* With this binding, a {@link Map}{@code <String, Snack>} can now be injected:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* class SnackMachine {
|
||||
* {@literal @}Inject
|
||||
* public SnackMachine(Map<String, Snack> snacks) { ... }
|
||||
* }</code>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* In addition to binding {@code Map<K, V>}, a mapbinder will also bind {@code
|
||||
* Map<K, Provider<V>>} for lazy value provision:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* class SnackMachine {
|
||||
* {@literal @}Inject
|
||||
* public SnackMachine(Map<String, Provider<Snack>> snackSuppliers) { ... }
|
||||
* }</code>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Contributing mapbindings from different modules is supported. For example, it
|
||||
* is okay to have both {@code CandyModule} and {@code ChipsModule} both create
|
||||
* their own {@code MapBinder<String, Snack>}, and to each contribute bindings
|
||||
* to the snacks map. When that map is injected, it will contain entries from
|
||||
* both modules.
|
||||
*
|
||||
* <p>
|
||||
* The map's iteration order is consistent with the binding order. This is
|
||||
* convenient when multiple elements are contributed by the same module because
|
||||
* that module can order its bindings appropriately. Avoid relying on the
|
||||
* iteration order of elements contributed by different modules, since there is
|
||||
* no equivalent mechanism to order modules.
|
||||
*
|
||||
* <p>
|
||||
* Values are resolved at map injection time. If a value is bound to a provider,
|
||||
* that provider's get method will be called each time the map is injected
|
||||
* (unless the binding is also scoped, or a map of providers is injected).
|
||||
*
|
||||
* <p>
|
||||
* Annotations are used to create different maps of the same key/value type.
|
||||
* Each distinct annotation gets its own independent map.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Keys must be distinct.</strong> If the same key is bound more than
|
||||
* once, map injection will fail. However, use {@link #permitDuplicates()} in
|
||||
* order to allow duplicate keys; extra bindings to {@code Map<K, Set<V>>} and
|
||||
* {@code Map<K, Set<Provider<V>>} will be added.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Keys must be non-null.</strong> {@code addBinding(null)} will throw
|
||||
* an unchecked exception.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Values must be non-null to use map injection.</strong> If any value
|
||||
* is null, map injection will fail (although injecting a map of providers will
|
||||
* not).
|
||||
*
|
||||
* @author dpb@google.com (David P. Baker)
|
||||
*/
|
||||
public abstract class MapBinder<K, V> {
|
||||
private MapBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
|
||||
* valueType} in a {@link Map} that is itself bound with no binding
|
||||
* annotation.
|
||||
*/
|
||||
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
|
||||
binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
|
||||
return newMapBinder(binder, valueType, Key.get(mapOf(keyType, valueType)), Key.get(mapOfProviderOf(keyType,
|
||||
valueType)), Key.get(mapOf(keyType, setOf(valueType))), Key.get(mapOfSetOfProviderOf(keyType, valueType)),
|
||||
Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
|
||||
* valueType} in a {@link Map} that is itself bound with no binding
|
||||
* annotation.
|
||||
*/
|
||||
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType, Class<V> valueType) {
|
||||
return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
|
||||
* valueType} in a {@link Map} that is itself bound with {@code annotation}.
|
||||
*/
|
||||
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType,
|
||||
Annotation annotation) {
|
||||
binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
|
||||
return newMapBinder(binder, valueType, Key.get(mapOf(keyType, valueType), annotation), Key.get(mapOfProviderOf(
|
||||
keyType, valueType), annotation), Key.get(mapOf(keyType, setOf(valueType)), annotation), Key.get(
|
||||
mapOfSetOfProviderOf(keyType, valueType), annotation), Multibinder.newSetBinder(binder, entryOfProviderOf(
|
||||
keyType, valueType), annotation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
|
||||
* valueType} in a {@link Map} that is itself bound with {@code annotation}.
|
||||
*/
|
||||
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType, Class<V> valueType,
|
||||
Annotation annotation) {
|
||||
return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
|
||||
* valueType} in a {@link Map} that is itself bound with {@code
|
||||
* annotationType}.
|
||||
*/
|
||||
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType,
|
||||
Class<? extends Annotation> annotationType) {
|
||||
binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
|
||||
return newMapBinder(binder, valueType, Key.get(mapOf(keyType, valueType), annotationType), Key.get(
|
||||
mapOfProviderOf(keyType, valueType), annotationType), Key.get(mapOf(keyType, setOf(valueType)),
|
||||
annotationType), Key.get(mapOfSetOfProviderOf(keyType, valueType), annotationType), Multibinder
|
||||
.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
|
||||
* valueType} in a {@link Map} that is itself bound with {@code
|
||||
* annotationType}.
|
||||
*/
|
||||
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType, Class<V> valueType,
|
||||
Class<? extends Annotation> annotationType) {
|
||||
return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotationType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// a map of <K, V> is safely a Map<K, V>
|
||||
private static <K, V> TypeLiteral<Map<K, V>> mapOf(TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
|
||||
return (TypeLiteral<Map<K, V>>) TypeLiteral.get(Types.mapOf(keyType.getType(), valueType.getType()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// a provider map <K, V> is safely a Map<K, Provider<V>>
|
||||
private static <K, V> TypeLiteral<Map<K, Provider<V>>> mapOfProviderOf(TypeLiteral<K> keyType,
|
||||
TypeLiteral<V> valueType) {
|
||||
return (TypeLiteral<Map<K, Provider<V>>>) TypeLiteral.get(Types.mapOf(keyType.getType(), Types
|
||||
.providerOf(valueType.getType())));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// a provider map <K, Set<V>> is safely a Map<K, Set<Provider<V>>>
|
||||
private static <K, V> TypeLiteral<Map<K, Set<Provider<V>>>> mapOfSetOfProviderOf(TypeLiteral<K> keyType,
|
||||
TypeLiteral<V> valueType) {
|
||||
return (TypeLiteral<Map<K, Set<Provider<V>>>>) TypeLiteral.get(Types.mapOf(keyType.getType(), Types.setOf(Types
|
||||
.providerOf(valueType.getType()))));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// a provider entry <K, V> is safely a Map.Entry<K, Provider<V>>
|
||||
private static <K, V> TypeLiteral<Map.Entry<K, Provider<V>>> entryOfProviderOf(TypeLiteral<K> keyType,
|
||||
TypeLiteral<V> valueType) {
|
||||
return (TypeLiteral<Entry<K, Provider<V>>>) TypeLiteral.get(newParameterizedTypeWithOwner(Map.class, Entry.class,
|
||||
keyType.getType(), Types.providerOf(valueType.getType())));
|
||||
}
|
||||
|
||||
private static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<V> valueType, Key<Map<K, V>> mapKey,
|
||||
Key<Map<K, Provider<V>>> providerMapKey, Key<Map<K, Set<V>>> multimapKey,
|
||||
Key<Map<K, Set<Provider<V>>>> providerMultimapKey, Multibinder<Entry<K, Provider<V>>> entrySetBinder) {
|
||||
RealMapBinder<K, V> mapBinder = new RealMapBinder<K, V>(binder, valueType, mapKey, providerMapKey, multimapKey,
|
||||
providerMultimapKey, entrySetBinder);
|
||||
binder.install(mapBinder);
|
||||
return mapBinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@code MapBinder} to handle duplicate entries.
|
||||
* <p>
|
||||
* When multiple equal keys are bound, the value that gets included in the
|
||||
* map is arbitrary.
|
||||
* <p>
|
||||
* In addition to the {@code Map<K, V>} and {@code Map<K, Provider<V>>} maps
|
||||
* that are normally bound, a {@code Map<K, Set<V>>} and {@code Map<K,
|
||||
* Set<Provider<V>>>} are <em>also</em> bound, which contain all values bound
|
||||
* to each key.
|
||||
* <p>
|
||||
* When multiple modules contribute elements to the map, this configuration
|
||||
* option impacts all of them.
|
||||
*
|
||||
* @return this map binder
|
||||
*/
|
||||
public abstract MapBinder<K, V> permitDuplicates();
|
||||
|
||||
/**
|
||||
* Returns a binding builder used to add a new entry in the map. Each key
|
||||
* must be distinct (and non-null). Bound providers will be evaluated each
|
||||
* time the map is injected.
|
||||
*
|
||||
* <p>
|
||||
* It is an error to call this method without also calling one of the {@code
|
||||
* to} methods on the returned binding builder.
|
||||
*
|
||||
* <p>
|
||||
* Scoping elements independently is supported. Use the {@code in} method to
|
||||
* specify a binding scope.
|
||||
*/
|
||||
public abstract LinkedBindingBuilder<V> addBinding(K key);
|
||||
|
||||
/**
|
||||
* The actual mapbinder plays several roles:
|
||||
*
|
||||
* <p>
|
||||
* As a MapBinder, it acts as a factory for LinkedBindingBuilders for each of
|
||||
* the map's values. It delegates to a {@link Multibinder} of entries (keys
|
||||
* to value providers).
|
||||
*
|
||||
* <p>
|
||||
* As a Module, it installs the binding to the map itself, as well as to a
|
||||
* corresponding map whose values are providers. It uses the entry set
|
||||
* multibinder to construct the map and the provider map.
|
||||
*
|
||||
* <p>
|
||||
* As a module, this implements equals() and hashcode() in order to trick
|
||||
* Guice into executing its configure() method only once. That makes it so
|
||||
* that multiple mapbinders can be created for the same target map, but only
|
||||
* one is bound. Since the list of bindings is retrieved from the injector
|
||||
* itself (and not the mapbinder), each mapbinder has access to all
|
||||
* contributions from all equivalent mapbinders.
|
||||
*
|
||||
* <p>
|
||||
* Rather than binding a single Map.Entry<K, V>, the map binder binds
|
||||
* keys and values independently. This allows the values to be properly
|
||||
* scoped.
|
||||
*
|
||||
* <p>
|
||||
* We use a subclass to hide 'implements Module' from the public API.
|
||||
*/
|
||||
private static final class RealMapBinder<K, V> extends MapBinder<K, V> implements Module {
|
||||
private final TypeLiteral<V> valueType;
|
||||
private final Key<Map<K, V>> mapKey;
|
||||
private final Key<Map<K, Provider<V>>> providerMapKey;
|
||||
private final Key<Map<K, Set<V>>> multimapKey;
|
||||
private final Key<Map<K, Set<Provider<V>>>> providerMultimapKey;
|
||||
private final RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder;
|
||||
|
||||
/*
|
||||
* the target injector's binder. non-null until initialization, null
|
||||
* afterwards
|
||||
*/
|
||||
private Binder binder;
|
||||
|
||||
private RealMapBinder(Binder binder, TypeLiteral<V> valueType, Key<Map<K, V>> mapKey,
|
||||
Key<Map<K, Provider<V>>> providerMapKey, Key<Map<K, Set<V>>> multimapKey,
|
||||
Key<Map<K, Set<Provider<V>>>> providerMultimapKey, Multibinder<Map.Entry<K, Provider<V>>> entrySetBinder) {
|
||||
this.valueType = valueType;
|
||||
this.mapKey = mapKey;
|
||||
this.providerMapKey = providerMapKey;
|
||||
this.multimapKey = multimapKey;
|
||||
this.providerMultimapKey = providerMultimapKey;
|
||||
this.entrySetBinder = (RealMultibinder<Entry<K, Provider<V>>>) entrySetBinder;
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapBinder<K, V> permitDuplicates() {
|
||||
entrySetBinder.permitDuplicates();
|
||||
binder.install(new MultimapBinder<K, V>(multimapKey, providerMultimapKey, entrySetBinder.getSetKey()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates two bindings. One for the {@code Map.Entry<K,
|
||||
* Provider<V>>} and another for {@code V}.
|
||||
*/
|
||||
@Override
|
||||
public LinkedBindingBuilder<V> addBinding(K key) {
|
||||
checkNotNull(key, "key");
|
||||
checkConfiguration(!isInitialized(), "MapBinder was already initialized");
|
||||
|
||||
Key<V> valueKey = Key.get(valueType, new RealElement(entrySetBinder.getSetName()));
|
||||
entrySetBinder.addBinding().toInstance(new MapEntry<K, Provider<V>>(key, binder.getProvider(valueKey)));
|
||||
return binder.bind(valueKey);
|
||||
}
|
||||
|
||||
public void configure(Binder binder) {
|
||||
checkConfiguration(!isInitialized(), "MapBinder was already initialized");
|
||||
|
||||
final ImmutableSet<Dependency<?>> dependencies = ImmutableSet.<Dependency<?>> of(Dependency.get(entrySetBinder
|
||||
.getSetKey()));
|
||||
|
||||
// Binds a Map<K, Provider<V>> from a collection of Map<Entry<K,
|
||||
// Provider<V>>.
|
||||
final Provider<Set<Entry<K, Provider<V>>>> entrySetProvider = binder.getProvider(entrySetBinder.getSetKey());
|
||||
binder.bind(providerMapKey).toProvider(new ProviderWithDependencies<Map<K, Provider<V>>>() {
|
||||
private Map<K, Provider<V>> providerMap;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Inject
|
||||
void initialize(Injector injector) {
|
||||
RealMapBinder.this.binder = null;
|
||||
boolean permitDuplicates = entrySetBinder.permitsDuplicates(injector);
|
||||
|
||||
Map<K, Provider<V>> providerMapMutable = new LinkedHashMap<K, Provider<V>>();
|
||||
for (Entry<K, Provider<V>> entry : entrySetProvider.get()) {
|
||||
Provider<V> previous = providerMapMutable.put(entry.getKey(), entry.getValue());
|
||||
checkConfiguration(previous == null || permitDuplicates,
|
||||
"Map injection failed due to duplicated key \"%s\"", entry.getKey());
|
||||
}
|
||||
|
||||
providerMap = ImmutableMap.copyOf(providerMapMutable);
|
||||
}
|
||||
|
||||
public Map<K, Provider<V>> get() {
|
||||
return providerMap;
|
||||
}
|
||||
|
||||
public Set<Dependency<?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
});
|
||||
|
||||
final Provider<Map<K, Provider<V>>> mapProvider = binder.getProvider(providerMapKey);
|
||||
binder.bind(mapKey).toProvider(new ProviderWithDependencies<Map<K, V>>() {
|
||||
public Map<K, V> get() {
|
||||
Map<K, V> map = new LinkedHashMap<K, V>();
|
||||
for (Entry<K, Provider<V>> entry : mapProvider.get().entrySet()) {
|
||||
V value = entry.getValue().get();
|
||||
K key = entry.getKey();
|
||||
checkConfiguration(value != null, "Map injection failed due to null value for key \"%s\"", key);
|
||||
map.put(key, value);
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public Set<Dependency<?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isInitialized() {
|
||||
return binder == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof RealMapBinder<?, ?> && ((RealMapBinder<?, ?>) o).mapKey.equals(mapKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mapKey.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds {@code Map<K, Set<V>>} and {{@code Map<K, Set<Provider<V>>>}.
|
||||
*/
|
||||
private static final class MultimapBinder<K, V> implements Module {
|
||||
|
||||
private final Key<Map<K, Set<V>>> multimapKey;
|
||||
private final Key<Map<K, Set<Provider<V>>>> providerMultimapKey;
|
||||
private final Key<Set<Entry<K, Provider<V>>>> entrySetKey;
|
||||
|
||||
public MultimapBinder(Key<Map<K, Set<V>>> multimapKey, Key<Map<K, Set<Provider<V>>>> providerMultimapKey,
|
||||
Key<Set<Entry<K, Provider<V>>>> entrySetKey) {
|
||||
this.multimapKey = multimapKey;
|
||||
this.providerMultimapKey = providerMultimapKey;
|
||||
this.entrySetKey = entrySetKey;
|
||||
}
|
||||
|
||||
public void configure(Binder binder) {
|
||||
final ImmutableSet<Dependency<?>> dependencies = ImmutableSet.<Dependency<?>> of(Dependency
|
||||
.get(entrySetKey));
|
||||
|
||||
final Provider<Set<Entry<K, Provider<V>>>> entrySetProvider = binder.getProvider(entrySetKey);
|
||||
// Binds a Map<K, Set<Provider<V>>> from a collection of
|
||||
// Map<Entry<K, Provider<V>> if
|
||||
// permitDuplicates was called.
|
||||
binder.bind(providerMultimapKey).toProvider(new ProviderWithDependencies<Map<K, Set<Provider<V>>>>() {
|
||||
private Map<K, Set<Provider<V>>> providerMultimap;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Inject
|
||||
void initialize(Injector injector) {
|
||||
Map<K, ImmutableSet.Builder<Provider<V>>> providerMultimapMutable = new LinkedHashMap<K, ImmutableSet.Builder<Provider<V>>>();
|
||||
for (Entry<K, Provider<V>> entry : entrySetProvider.get()) {
|
||||
if (!providerMultimapMutable.containsKey(entry.getKey())) {
|
||||
providerMultimapMutable.put(entry.getKey(), ImmutableSet.<Provider<V>> builder());
|
||||
}
|
||||
providerMultimapMutable.get(entry.getKey()).add(entry.getValue());
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<K, Set<Provider<V>>> providerMultimapBuilder = ImmutableMap.builder();
|
||||
for (Entry<K, ImmutableSet.Builder<Provider<V>>> entry : providerMultimapMutable.entrySet()) {
|
||||
providerMultimapBuilder.put(entry.getKey(), entry.getValue().build());
|
||||
}
|
||||
providerMultimap = providerMultimapBuilder.build();
|
||||
}
|
||||
|
||||
public Map<K, Set<Provider<V>>> get() {
|
||||
return providerMultimap;
|
||||
}
|
||||
|
||||
public Set<Dependency<?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
});
|
||||
|
||||
final Provider<Map<K, Set<Provider<V>>>> multimapProvider = binder.getProvider(providerMultimapKey);
|
||||
binder.bind(multimapKey).toProvider(new ProviderWithDependencies<Map<K, Set<V>>>() {
|
||||
|
||||
public Map<K, Set<V>> get() {
|
||||
ImmutableMap.Builder<K, Set<V>> multimapBuilder = ImmutableMap.builder();
|
||||
for (Entry<K, Set<Provider<V>>> entry : multimapProvider.get().entrySet()) {
|
||||
K key = entry.getKey();
|
||||
ImmutableSet.Builder<V> valuesBuilder = ImmutableSet.builder();
|
||||
for (Provider<V> valueProvider : entry.getValue()) {
|
||||
V value = valueProvider.get();
|
||||
checkConfiguration(value != null, "Multimap injection failed due to null value for key \"%s\"",
|
||||
key);
|
||||
valuesBuilder.add(value);
|
||||
}
|
||||
multimapBuilder.put(key, valuesBuilder.build());
|
||||
}
|
||||
return multimapBuilder.build();
|
||||
}
|
||||
|
||||
public Set<Dependency<?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MapEntry<K, V> implements Map.Entry<K, V> {
|
||||
private final K key;
|
||||
private final V value;
|
||||
|
||||
private MapEntry(K key, V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Map.Entry<?, ?> && key.equals(((Map.Entry<?, ?>) obj).getKey())
|
||||
&& value.equals(((Map.Entry<?, ?>) obj).getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 127 * ("key".hashCode() ^ key.hashCode()) + 127 * ("value".hashCode() ^ value.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MapEntry(" + key + ", " + value + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,413 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.config.multibindings;
|
||||
|
||||
import static com.google.inject.name.Names.named;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Binding;
|
||||
import com.google.inject.ConfigurationException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.binder.LinkedBindingBuilder;
|
||||
import com.google.inject.internal.Errors;
|
||||
import com.google.inject.spi.Dependency;
|
||||
import com.google.inject.spi.HasDependencies;
|
||||
import com.google.inject.spi.Message;
|
||||
import com.google.inject.spi.Toolable;
|
||||
import com.google.inject.util.Types;
|
||||
|
||||
/**
|
||||
*
|
||||
* An API to bind multiple values separately, only to later inject them as a
|
||||
* complete collection. Multibinder is intended for use in your application's
|
||||
* module:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* public class SnacksModule extends AbstractModule {
|
||||
* protected void configure() {
|
||||
* Multibinder<Snack> multibinder
|
||||
* = Multibinder.newSetBinder(binder(), Snack.class);
|
||||
* multibinder.addBinding().toInstance(new Twix());
|
||||
* multibinder.addBinding().toProvider(SnickersProvider.class);
|
||||
* multibinder.addBinding().to(Skittles.class);
|
||||
* }
|
||||
* }</code>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* With this binding, a {@link Set}{@code <Snack>} can now be injected:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* class SnackMachine {
|
||||
* {@literal @}Inject
|
||||
* public SnackMachine(Set<Snack> snacks) { ... }
|
||||
* }</code>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Contributing multibindings from different modules is supported. For example,
|
||||
* it is okay to have both {@code CandyModule} and {@code ChipsModule} to both
|
||||
* create their own {@code Multibinder<Snack>}, and to each contribute bindings
|
||||
* to the set of snacks. When that set is injected, it will contain elements
|
||||
* from both modules.
|
||||
*
|
||||
* <p>
|
||||
* The set's iteration order is consistent with the binding order. This is
|
||||
* convenient when multiple elements are contributed by the same module because
|
||||
* that module can order its bindings appropriately. Avoid relying on the
|
||||
* iteration order of elements contributed by different modules, since there is
|
||||
* no equivalent mechanism to order modules.
|
||||
*
|
||||
* <p>
|
||||
* Elements are resolved at set injection time. If an element is bound to a
|
||||
* provider, that provider's get method will be called each time the set is
|
||||
* injected (unless the binding is also scoped).
|
||||
*
|
||||
* <p>
|
||||
* Annotations are be used to create different sets of the same element type.
|
||||
* Each distinct annotation gets its own independent collection of elements.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Elements must be distinct.</strong> If multiple bound elements have
|
||||
* the same value, set injection will fail.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Elements must be non-null.</strong> If any set element is null, set
|
||||
* injection will fail.
|
||||
*
|
||||
* @author jessewilson@google.com (Jesse Wilson)
|
||||
*/
|
||||
public abstract class Multibinder<T> {
|
||||
private Multibinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new multibinder that collects instances of {@code type} in a
|
||||
* {@link Set} that is itself bound with no binding annotation.
|
||||
*/
|
||||
public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type) {
|
||||
binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
|
||||
RealMultibinder<T> result = new RealMultibinder<T>(binder, type, "", Key.get(Multibinder.<T> setOf(type)));
|
||||
binder.install(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new multibinder that collects instances of {@code type} in a
|
||||
* {@link Set} that is itself bound with no binding annotation.
|
||||
*/
|
||||
public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type) {
|
||||
return newSetBinder(binder, TypeLiteral.get(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new multibinder that collects instances of {@code type} in a
|
||||
* {@link Set} that is itself bound with {@code annotation}.
|
||||
*/
|
||||
public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type, Annotation annotation) {
|
||||
binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
|
||||
RealMultibinder<T> result = new RealMultibinder<T>(binder, type, annotation.toString(), Key.get(Multibinder
|
||||
.<T> setOf(type), annotation));
|
||||
binder.install(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new multibinder that collects instances of {@code type} in a
|
||||
* {@link Set} that is itself bound with {@code annotation}.
|
||||
*/
|
||||
public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type, Annotation annotation) {
|
||||
return newSetBinder(binder, TypeLiteral.get(type), annotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new multibinder that collects instances of {@code type} in a
|
||||
* {@link Set} that is itself bound with {@code annotationType}.
|
||||
*/
|
||||
public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type,
|
||||
Class<? extends Annotation> annotationType) {
|
||||
binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
|
||||
RealMultibinder<T> result = new RealMultibinder<T>(binder, type, "@" + annotationType.getName(), Key.get(
|
||||
Multibinder.<T> setOf(type), annotationType));
|
||||
binder.install(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new multibinder that collects instances of {@code type} in a
|
||||
* {@link Set} that is itself bound with {@code annotationType}.
|
||||
*/
|
||||
public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type,
|
||||
Class<? extends Annotation> annotationType) {
|
||||
return newSetBinder(binder, TypeLiteral.get(type), annotationType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// wrapping a T in a Set safely returns a Set<T>
|
||||
static <T> TypeLiteral<Set<T>> setOf(TypeLiteral<T> elementType) {
|
||||
Type type = Types.setOf(elementType.getType());
|
||||
return (TypeLiteral<Set<T>>) TypeLiteral.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the bound set to silently discard duplicate elements. When
|
||||
* multiple equal values are bound, the one that gets included is arbitrary.
|
||||
* When multiple modules contribute elements to the set, this configuration
|
||||
* option impacts all of them.
|
||||
*
|
||||
* @return this multibinder
|
||||
*/
|
||||
public abstract Multibinder<T> permitDuplicates();
|
||||
|
||||
/**
|
||||
* Returns a binding builder used to add a new element in the set. Each bound
|
||||
* element must have a distinct value. Bound providers will be evaluated each
|
||||
* time the set is injected.
|
||||
*
|
||||
* <p>
|
||||
* It is an error to call this method without also calling one of the {@code
|
||||
* to} methods on the returned binding builder.
|
||||
*
|
||||
* <p>
|
||||
* Scoping elements independently is supported. Use the {@code in} method to
|
||||
* specify a binding scope.
|
||||
*/
|
||||
public abstract LinkedBindingBuilder<T> addBinding();
|
||||
|
||||
/**
|
||||
* The actual multibinder plays several roles:
|
||||
*
|
||||
* <p>
|
||||
* As a Multibinder, it acts as a factory for LinkedBindingBuilders for each
|
||||
* of the set's elements. Each binding is given an annotation that identifies
|
||||
* it as a part of this set.
|
||||
*
|
||||
* <p>
|
||||
* As a Module, it installs the binding to the set itself. As a module, this
|
||||
* implements equals() and hashcode() in order to trick Guice into executing
|
||||
* its configure() method only once. That makes it so that multiple
|
||||
* multibinders can be created for the same target collection, but only one
|
||||
* is bound. Since the list of bindings is retrieved from the injector itself
|
||||
* (and not the multibinder), each multibinder has access to all
|
||||
* contributions from all multibinders.
|
||||
*
|
||||
* <p>
|
||||
* As a Provider, this constructs the set instances.
|
||||
*
|
||||
* <p>
|
||||
* We use a subclass to hide 'implements Module, Provider' from the public
|
||||
* API.
|
||||
*/
|
||||
static final class RealMultibinder<T> extends Multibinder<T> implements Module, Provider<Set<T>>, HasDependencies {
|
||||
|
||||
private final TypeLiteral<T> elementType;
|
||||
private final String setName;
|
||||
private final Key<Set<T>> setKey;
|
||||
private final Key<Boolean> permitDuplicatesKey;
|
||||
|
||||
/*
|
||||
* the target injector's binder. non-null until initialization, null
|
||||
* afterwards
|
||||
*/
|
||||
private Binder binder;
|
||||
|
||||
/*
|
||||
* a provider for each element in the set. null until initialization,
|
||||
* non-null afterwards
|
||||
*/
|
||||
private List<Provider<T>> providers;
|
||||
private Set<Dependency<?>> dependencies;
|
||||
|
||||
/**
|
||||
* whether duplicates are allowed. Possibly configured by a different
|
||||
* instance
|
||||
*/
|
||||
private boolean permitDuplicates;
|
||||
|
||||
private RealMultibinder(Binder binder, TypeLiteral<T> elementType, String setName, Key<Set<T>> setKey) {
|
||||
this.binder = checkNotNull(binder, "binder");
|
||||
this.elementType = checkNotNull(elementType, "elementType");
|
||||
this.setName = checkNotNull(setName, "setName");
|
||||
this.setKey = checkNotNull(setKey, "setKey");
|
||||
this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates"));
|
||||
}
|
||||
|
||||
public void configure(Binder binder) {
|
||||
checkConfiguration(!isInitialized(), "Multibinder was already initialized");
|
||||
binder.bind(setKey).toProvider(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multibinder<T> permitDuplicates() {
|
||||
binder.install(new PermitDuplicatesModule(permitDuplicatesKey));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedBindingBuilder<T> addBinding() {
|
||||
checkConfiguration(!isInitialized(), "Multibinder was already initialized");
|
||||
|
||||
return binder.bind(Key.get(elementType, new RealElement(setName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by Guice at Injector-creation time to prepare providers for
|
||||
* each element in this set. At this time the set's size is known, but its
|
||||
* contents are only evaluated when get() is invoked.
|
||||
*/
|
||||
@Toolable
|
||||
@Inject
|
||||
void initialize(Injector injector) {
|
||||
providers = Lists.newArrayList();
|
||||
List<Dependency<?>> dependencies = Lists.newArrayList();
|
||||
for (Binding<?> entry : injector.findBindingsByType(elementType)) {
|
||||
|
||||
if (keyMatches(entry.getKey())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
// protected by findBindingsByType()
|
||||
Binding<T> binding = (Binding<T>) entry;
|
||||
providers.add(binding.getProvider());
|
||||
dependencies.add(Dependency.get(binding.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
this.dependencies = ImmutableSet.copyOf(dependencies);
|
||||
this.permitDuplicates = permitsDuplicates(injector);
|
||||
this.binder = null;
|
||||
}
|
||||
|
||||
boolean permitsDuplicates(Injector injector) {
|
||||
return injector.getBindings().containsKey(permitDuplicatesKey);
|
||||
}
|
||||
|
||||
private boolean keyMatches(Key<?> key) {
|
||||
return key.getTypeLiteral().equals(elementType) && key.getAnnotation() instanceof Element
|
||||
&& ((Element) key.getAnnotation()).setName().equals(setName);
|
||||
}
|
||||
|
||||
private boolean isInitialized() {
|
||||
return binder == null;
|
||||
}
|
||||
|
||||
public Set<T> get() {
|
||||
checkConfiguration(isInitialized(), "Multibinder is not initialized");
|
||||
|
||||
Set<T> result = new LinkedHashSet<T>();
|
||||
for (Provider<T> provider : providers) {
|
||||
final T newValue = provider.get();
|
||||
checkConfiguration(newValue != null, "Set injection failed due to null element");
|
||||
checkConfiguration(result.add(newValue) || permitDuplicates,
|
||||
"Set injection failed due to duplicated element \"%s\"", newValue);
|
||||
}
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
String getSetName() {
|
||||
return setName;
|
||||
}
|
||||
|
||||
Key<Set<T>> getSetKey() {
|
||||
return setKey;
|
||||
}
|
||||
|
||||
public Set<Dependency<?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof RealMultibinder<?> && ((RealMultibinder<?>) o).setKey.equals(setKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return setKey.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder().append(setName).append(setName.length() > 0 ? " " : "").append("Multibinder<")
|
||||
.append(elementType).append(">").toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We install the permit duplicates configuration as its own binding, all by
|
||||
* itself. This way, if only one of a multibinder's users remember to call
|
||||
* permitDuplicates(), they're still permitted.
|
||||
*/
|
||||
private static class PermitDuplicatesModule extends AbstractModule {
|
||||
private final Key<Boolean> key;
|
||||
|
||||
PermitDuplicatesModule(Key<Boolean> key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(key).toInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof PermitDuplicatesModule && ((PermitDuplicatesModule) o).key.equals(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getClass().hashCode() ^ key.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
static void checkConfiguration(boolean condition, String format, Object... args) {
|
||||
if (condition) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args))));
|
||||
}
|
||||
|
||||
static <T> T checkNotNull(T reference, String name) {
|
||||
if (reference != null) {
|
||||
return reference;
|
||||
}
|
||||
|
||||
NullPointerException npe = new NullPointerException(name);
|
||||
throw new ConfigurationException(ImmutableSet.of(new Message(ImmutableList.of(), npe.toString(), npe)));
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package org.jclouds.ohai.config.multibindings;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
||||
/**
|
||||
* @author jessewilson@google.com (Jesse Wilson)
|
||||
*/
|
||||
class RealElement implements Element {
|
||||
private static final AtomicInteger nextUniqueId = new AtomicInteger(1);
|
||||
|
||||
private final int uniqueId;
|
||||
private final String setName;
|
||||
|
||||
RealElement(String setName) {
|
||||
uniqueId = nextUniqueId.getAndIncrement();
|
||||
this.setName = setName;
|
||||
}
|
||||
|
||||
public String setName() {
|
||||
return setName;
|
||||
}
|
||||
|
||||
public int uniqueId() {
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> annotationType() {
|
||||
return Element.class;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "@" + Element.class.getName() + "(setName=" + setName
|
||||
+ ",uniqueId=" + uniqueId + ")";
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
return o instanceof Element
|
||||
&& ((Element) o).setName().equals(setName())
|
||||
&& ((Element) o).uniqueId() == uniqueId();
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return 127 * ("setName".hashCode() ^ setName.hashCode())
|
||||
+ 127 * ("uniqueId".hashCode() ^ uniqueId);
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Taken from r1154 of Guice, as they decided to stop supporting multiple bindings and instead silently throw them away.
|
||||
*/
|
||||
package org.jclouds.ohai.config.multibindings;
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.functions;
|
||||
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Lists.partition;
|
||||
import static com.google.common.primitives.Bytes.asList;
|
||||
import static com.google.common.primitives.Bytes.toArray;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates a string in the form: {@code 00:26:bb:09:e6:c4 }
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ByteArrayToMacAddress implements Function<byte[], String> {
|
||||
|
||||
@Override
|
||||
public String apply(byte[] from) {
|
||||
return Joiner.on(':').join(transform(partition(asList(from), 1), new Function<List<Byte>, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(List<Byte> from) {
|
||||
return CryptoStreams.hex(toArray(from));
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.functions;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class MapSetToMultimap<K, V> implements Function<Map<K, Set<V>>, Multimap<K, V>> {
|
||||
|
||||
@Override
|
||||
public Multimap<K, V> apply(Map<K, Set<V>> from) {
|
||||
Multimap<K, V> returnV = LinkedHashMultimap.create();
|
||||
for (Entry<K, Set<V>> entry : from.entrySet()) {
|
||||
for (V value : entry.getValue())
|
||||
returnV.put(entry.getKey(), value);
|
||||
}
|
||||
return returnV;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
import org.jclouds.json.Json;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class NestSlashKeys implements Function<Multimap<String, Supplier<JsonBall>>, Map<String, JsonBall>> {
|
||||
|
||||
private final Json json;
|
||||
|
||||
@Inject
|
||||
NestSlashKeys(Json json) {
|
||||
this.json = checkNotNull(json, "json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, JsonBall> apply(Multimap<String, Supplier<JsonBall>> from) {
|
||||
|
||||
Map<String, JsonBall> autoAttrs = mergeSameKeys(from);
|
||||
|
||||
Map<String, JsonBall> modifiableFlatMap = Maps.newLinkedHashMap(Maps.filterKeys(autoAttrs,
|
||||
new Predicate<String>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
return input.indexOf('/') == -1;
|
||||
}
|
||||
|
||||
}));
|
||||
Map<String, JsonBall> withSlashesMap = Maps.difference(autoAttrs, modifiableFlatMap).entriesOnlyOnLeft();
|
||||
for (Entry<String, JsonBall> entry : withSlashesMap.entrySet()) {
|
||||
List<String> keyParts = Lists.newArrayList(Splitter.on('/').split(entry.getKey()));
|
||||
JsonBall toInsert = entry.getValue();
|
||||
try {
|
||||
putUnderContext(keyParts, toInsert, modifiableFlatMap);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("error inserting value in entry: " + entry.getKey(), e);
|
||||
}
|
||||
}
|
||||
return modifiableFlatMap;
|
||||
}
|
||||
|
||||
private Map<String, JsonBall> mergeSameKeys(Multimap<String, Supplier<JsonBall>> from) {
|
||||
Map<String, JsonBall> merged = Maps.newLinkedHashMap();
|
||||
for (Entry<String, Supplier<JsonBall>> entry : from.entries()) {
|
||||
if (merged.containsKey(entry.getKey())) {
|
||||
mergeAsPeer(entry.getKey(), entry.getValue().get(), merged);
|
||||
} else {
|
||||
merged.put(entry.getKey(), entry.getValue().get());
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void mergeAsPeer(String key, JsonBall value, Map<String, JsonBall> insertionContext) {
|
||||
Map<String, JsonBall> valueContext = json.fromJson(insertionContext.get(key).toString(), mapLiteral);
|
||||
Map<String, JsonBall> toPut = json.<Map<String, JsonBall>> fromJson(value.toString(), mapLiteral);
|
||||
Set<String> uniques = Sets.difference(toPut.keySet(), valueContext.keySet());
|
||||
for (String k : uniques)
|
||||
valueContext.put(k, toPut.get(k));
|
||||
Set<String> conflicts = Sets.difference(toPut.keySet(), uniques);
|
||||
for (String k : conflicts) {
|
||||
JsonBall v = toPut.get(k);
|
||||
if (v.toString().matches("^\\{.*\\}$")) {
|
||||
mergeAsPeer(k, v, valueContext);
|
||||
} else {
|
||||
// replace
|
||||
valueContext.put(k, v);
|
||||
}
|
||||
}
|
||||
insertionContext.put(key, new JsonBall(json.toJson(valueContext, mapLiteral)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keyParts
|
||||
* @param toInsert
|
||||
* @param destination
|
||||
* @throws IllegalArgumentException
|
||||
* <p/>
|
||||
* if destination.get(keyParts(0)) is not a map *
|
||||
* <p/>
|
||||
* keyParts is zero length
|
||||
*/
|
||||
void putUnderContext(List<String> keyParts, JsonBall toInsert, Map<String, JsonBall> destination) {
|
||||
checkNotNull(keyParts, "keyParts");
|
||||
checkArgument(keyParts.size() >= 1, "keyParts must contain at least one element");
|
||||
|
||||
checkNotNull(toInsert, "toInsert");
|
||||
checkNotNull(destination, "destination");
|
||||
|
||||
String rootKey = keyParts.remove(0);
|
||||
String rootValue = destination.containsKey(rootKey) ? destination.get(rootKey).toString() : "{}";
|
||||
|
||||
checkArgument(rootValue.matches("^\\{.*\\}$"), "value must be a hash: %s", rootValue);
|
||||
Map<String, JsonBall> insertionContext = json.fromJson(rootValue, mapLiteral);
|
||||
if (keyParts.size() == 1) {
|
||||
if (!insertionContext.containsKey(keyParts.get(0))) {
|
||||
insertionContext.put(keyParts.get(0), toInsert);
|
||||
} else {
|
||||
String key = keyParts.get(0);
|
||||
mergeAsPeer(key, toInsert, insertionContext);
|
||||
}
|
||||
} else {
|
||||
putUnderContext(keyParts, toInsert, insertionContext);
|
||||
}
|
||||
destination.put(rootKey, new JsonBall(json.toJson(insertionContext, mapLiteral)));
|
||||
}
|
||||
|
||||
final Type mapLiteral = new TypeLiteral<Map<String, JsonBall>>() {
|
||||
}.getType();
|
||||
final Type listLiteral = new TypeLiteral<List<JsonBall>>() {
|
||||
}.getType();
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.ohai.suppliers;
|
||||
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class UptimeSecondsSupplier implements Supplier<JsonBall> {
|
||||
|
||||
@Inject
|
||||
UptimeSecondsSupplier(RuntimeMXBean runtime) {
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
private final RuntimeMXBean runtime;
|
||||
|
||||
@Override
|
||||
public JsonBall get() {
|
||||
long uptimeInSeconds = runtime.getUptime() / 1000;
|
||||
return new JsonBall(uptimeInSeconds);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
if [ ! -f /usr/bin/chef-client ]; then
|
||||
apt-get update
|
||||
apt-get install -y ruby ruby1.8-dev build-essential wget libruby-extras libruby1.8-extras
|
||||
mkdir -p /tmp/bootchef
|
||||
(
|
||||
cd /tmp/bootchef
|
||||
wget http://rubyforge.org/frs/download.php/69365/rubygems-1.3.6.tgz
|
||||
tar xvf rubygems-1.3.6.tgz
|
||||
cd rubygems-1.3.6
|
||||
ruby setup.rb
|
||||
cp /usr/bin/gem1.8 /usr/bin/gem
|
||||
)
|
||||
rm -rf /tmp/bootchef
|
||||
gem install chef ohai --no-rdoc --no-ri --verbose
|
||||
fi
|
|
@ -1,72 +0,0 @@
|
|||
;
|
||||
;
|
||||
; Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
;
|
||||
; ====================================================================
|
||||
; Licensed under the Apache License, Version 2.0 (the "License");
|
||||
; you may not use this file except in compliance with the License.
|
||||
; You may obtain a copy of the License at
|
||||
;
|
||||
; http://www.apache.org/licenses/LICENSE-2.0
|
||||
;
|
||||
; Unless required by applicable law or agreed to in writing, software
|
||||
; distributed under the License is distributed on an "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
; See the License for the specific language governing permissions and
|
||||
; limitations under the License.
|
||||
; ====================================================================
|
||||
;
|
||||
|
||||
(ns org.jclouds.chef-test
|
||||
(:use [org.jclouds.chef] :reload-all)
|
||||
(:use [clojure.test]))
|
||||
|
||||
(defn clean-stub-fixture
|
||||
"This should allow basic tests to easily be run with another service."
|
||||
[service account key & options]
|
||||
(fn [f]
|
||||
(with-chef-service [(apply chef-service service account key options)]
|
||||
(doseq [databag (databags)]
|
||||
(delete-databag databag))
|
||||
(f))))
|
||||
|
||||
(use-fixtures :each (clean-stub-fixture "transientchef" "" ""))
|
||||
|
||||
(deftest chef-service?-test
|
||||
(is (chef-service? *chef*)))
|
||||
|
||||
(deftest as-chef-service-test
|
||||
(is (chef-service? (chef-service "transientchef" "" "")))
|
||||
(is (chef-service? (as-chef-service *chef*)))
|
||||
(is (chef-service? (as-chef-service (chef-context *chef*)))))
|
||||
|
||||
(deftest create-existing-databag-test
|
||||
(is (not (databag-exists? "")))
|
||||
(create-databag "fred")
|
||||
(is (databag-exists? "fred")))
|
||||
|
||||
(deftest create-databag-test
|
||||
(create-databag "fred")
|
||||
(is (databag-exists? "fred")))
|
||||
|
||||
(deftest databags-test
|
||||
(is (empty? (databags)))
|
||||
(create-databag "fred")
|
||||
(is (= 1 (count (databags)))))
|
||||
|
||||
(deftest databag-items-test
|
||||
(create-databag "databag")
|
||||
(is (empty? (databag-items "databag")))
|
||||
(is (create-databag-item "databag" {:id "databag-item1" :value "databag-value1"}))
|
||||
(is (create-databag-item "databag" {:id "databag-item2" :value "databag-value2"}))
|
||||
(is (= 2 (count (databag-items "databag")))))
|
||||
|
||||
(deftest databag-item-test
|
||||
(create-databag "databag")
|
||||
(is (create-databag-item "databag" {:id "databag-item1" :value "databag-value1"}))
|
||||
(is (create-databag-item "databag" {:id "databag-item2" :value "databag-value2"}))
|
||||
(is (= {:id "databag-item2" :value "databag-value2"} (databag-item "databag" "databag-item2"))))
|
||||
|
||||
(deftest run-list-test
|
||||
(update-run-list #{"recipe[foo]"} "tag")
|
||||
(is (= ["recipe[foo]"] (run-list "tag"))))
|
|
@ -1,378 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.chef.domain.ChecksumStatus;
|
||||
import org.jclouds.chef.domain.Client;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.domain.Resource;
|
||||
import org.jclouds.chef.domain.Role;
|
||||
import org.jclouds.chef.domain.SearchResult;
|
||||
import org.jclouds.chef.domain.UploadSandbox;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.crypto.Pems;
|
||||
import org.jclouds.io.InputSuppliers;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.io.payloads.FilePayload;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.HttpClient;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Bytes;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ChefClient}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "chef.ChefClientLiveTest")
|
||||
public abstract class BaseChefClientLiveTest {
|
||||
|
||||
protected String clientKey;
|
||||
|
||||
protected abstract void closeContexts();
|
||||
|
||||
protected abstract void recreateClientConnection() throws IOException;
|
||||
|
||||
protected abstract ChefClient getClientConnection();
|
||||
|
||||
protected abstract ChefClient getValidatorConnection();
|
||||
|
||||
protected abstract ChefClient getAdminConnection();
|
||||
|
||||
protected abstract HttpClient getHttp();
|
||||
|
||||
public abstract void setupClient() throws IOException;
|
||||
|
||||
protected String endpoint;
|
||||
protected String user;
|
||||
private Node node;
|
||||
private Role role;
|
||||
protected Json json;
|
||||
protected DatabagItem databagItem;
|
||||
public static final String PREFIX = System.getProperty("user.name") + "-jcloudstest";
|
||||
|
||||
public BaseChefClientLiveTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void testCreateNewCookbook() throws Exception {
|
||||
|
||||
// define the file you want in the cookbook
|
||||
FilePayload content = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml"));
|
||||
content.setContentType("application/x-binary");
|
||||
|
||||
// get an md5 so that you can see if the server already has it or not
|
||||
Payloads.calculateMD5(content);
|
||||
|
||||
// Note that java collections cannot effectively do equals or hashcodes on
|
||||
// byte arrays,
|
||||
// so let's convert to a list of bytes.
|
||||
List<Byte> md5 = Bytes.asList(content.getContentMD5());
|
||||
|
||||
// request an upload site for this file
|
||||
UploadSandbox site = getAdminConnection().getUploadSandboxForChecksums(ImmutableSet.of(md5));
|
||||
|
||||
try {
|
||||
assert site.getChecksums().containsKey(md5) : md5 + " not in " + site.getChecksums();
|
||||
|
||||
ChecksumStatus status = site.getChecksums().get(md5);
|
||||
if (status.needsUpload()) {
|
||||
getHttp().put(status.getUrl(), content);
|
||||
}
|
||||
|
||||
getAdminConnection().commitSandbox(site.getSandboxId(), true);
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
getAdminConnection().commitSandbox(site.getSandboxId(), false);
|
||||
}
|
||||
|
||||
// create a new cookbook
|
||||
CookbookVersion cookbook = new CookbookVersion("test3", "0.0.0");
|
||||
cookbook.getRootFiles().add(new Resource(content));
|
||||
|
||||
// upload the cookbook to the remote server
|
||||
getAdminConnection().updateCookbook("test3", "0.0.0", cookbook);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testGenerateKeyForClient() throws Exception {
|
||||
clientKey = Pems.pem(getClientConnection().generateKeyForClient(PREFIX).getPrivateKey());
|
||||
|
||||
assertNotNull(clientKey);
|
||||
recreateClientConnection();
|
||||
getClientConnection().clientExists(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateNewCookbook")
|
||||
public void testListCookbooks() throws Exception {
|
||||
for (String cookbook : getAdminConnection().listCookbooks())
|
||||
for (String version : getAdminConnection().getVersionsOfCookbook(cookbook)) {
|
||||
System.err.printf("%s/%s:%n", cookbook, version);
|
||||
CookbookVersion cookbookO = getAdminConnection().getCookbook(cookbook, version);
|
||||
for (Resource resource : ImmutableList.<Resource> builder().addAll(cookbookO.getDefinitions()).addAll(
|
||||
cookbookO.getFiles()).addAll(cookbookO.getLibraries()).addAll(cookbookO.getSuppliers()).addAll(
|
||||
cookbookO.getRecipes()).addAll(cookbookO.getResources()).addAll(cookbookO.getRootFiles()).addAll(
|
||||
cookbookO.getTemplates()).build()) {
|
||||
try {
|
||||
InputStream stream = getHttp().get(resource.getUrl());
|
||||
byte[] md5 = CryptoStreams.md5(InputSuppliers.of(stream));
|
||||
assertEquals(md5, resource.getChecksum());
|
||||
} catch (NullPointerException e) {
|
||||
assert false : "resource not found: " + resource;
|
||||
}
|
||||
System.err.printf("resource %s ok%n", resource.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testListCookbooks")
|
||||
public void testUpdateCookbook() throws Exception {
|
||||
for (String cookbook : getAdminConnection().listCookbooks())
|
||||
for (String version : getAdminConnection().getVersionsOfCookbook(cookbook)) {
|
||||
System.err.printf("%s/%s:%n", cookbook, version);
|
||||
CookbookVersion cook = getAdminConnection().getCookbook(cookbook, version);
|
||||
getAdminConnection().updateCookbook(cookbook, version, cook);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testUpdateCookbook")
|
||||
public void testCreateCookbook() throws Exception {
|
||||
for (String cookbook : getAdminConnection().listCookbooks())
|
||||
for (String version : getAdminConnection().getVersionsOfCookbook(cookbook)) {
|
||||
System.err.printf("%s/%s:%n", cookbook, version);
|
||||
CookbookVersion cook = getAdminConnection().getCookbook(cookbook, version);
|
||||
getAdminConnection().deleteCookbook(cookbook, version);
|
||||
assert getAdminConnection().getCookbook(cookbook, version) == null : cookbook + version;
|
||||
getAdminConnection().updateCookbook(cookbook, version, cook);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testValidatorCannotListClients() throws Exception {
|
||||
for (String client : getValidatorConnection().listClients())
|
||||
assertNotNull(getValidatorConnection().getClient(client));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testValidatorCannotDeleteClient() throws Exception {
|
||||
getValidatorConnection().deleteClient(PREFIX);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testValidatorCannotCreateClient() throws Exception {
|
||||
getValidatorConnection().createClient(PREFIX);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateClient() throws Exception {
|
||||
getAdminConnection().deleteClient(PREFIX);
|
||||
|
||||
clientKey = Pems.pem(getAdminConnection().createClient(PREFIX).getPrivateKey());
|
||||
|
||||
recreateClientConnection();
|
||||
getClientConnection().clientExists(PREFIX);
|
||||
Set<String> clients = getAdminConnection().listClients();
|
||||
assert clients.contains(PREFIX) : String.format("client %s not in %s", PREFIX, clients);
|
||||
assertNotNull(getClientConnection().getClient(PREFIX));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testClientExists() throws Exception {
|
||||
assertNotNull(getValidatorConnection().clientExists(PREFIX));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListNodes() throws Exception {
|
||||
Set<String> nodes = getAdminConnection().listNodes();
|
||||
assertNotNull(nodes);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateRole")
|
||||
public void testCreateNode() throws Exception {
|
||||
getAdminConnection().deleteNode(PREFIX);
|
||||
getClientConnection().createNode(new Node(PREFIX, Collections.singleton("role[" + PREFIX + "]")));
|
||||
node = getAdminConnection().getNode(PREFIX);
|
||||
// TODO check recipes
|
||||
assertNotNull(node);
|
||||
Set<String> nodes = getAdminConnection().listNodes();
|
||||
assert nodes.contains(PREFIX) : String.format("node %s not in %s", PREFIX, nodes);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateNode")
|
||||
public void testNodeExists() throws Exception {
|
||||
assertNotNull(getClientConnection().nodeExists(PREFIX));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testNodeExists")
|
||||
public void testUpdateNode() throws Exception {
|
||||
for (String nodename : getClientConnection().listNodes()) {
|
||||
Node node = getAdminConnection().getNode(nodename);
|
||||
getAdminConnection().updateNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRoles() throws Exception {
|
||||
Set<String> roles = getAdminConnection().listRoles();
|
||||
assertNotNull(roles);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testCreateRole() throws Exception {
|
||||
getAdminConnection().deleteRole(PREFIX);
|
||||
getAdminConnection().createRole(new Role(PREFIX, Collections.singleton("recipe[java]")));
|
||||
role = getAdminConnection().getRole(PREFIX);
|
||||
assertNotNull(role);
|
||||
assertEquals(role.getName(), PREFIX);
|
||||
assertEquals(role.getRunList(), Collections.singleton("recipe[java]"));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateRole")
|
||||
public void testRoleExists() throws Exception {
|
||||
assertNotNull(getClientConnection().roleExists(PREFIX));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testRoleExists")
|
||||
public void testUpdateRole() throws Exception {
|
||||
for (String rolename : getClientConnection().listRoles()) {
|
||||
Role role = getAdminConnection().getRole(rolename);
|
||||
getAdminConnection().updateRole(role);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListDatabags() throws Exception {
|
||||
Set<String> databags = getAdminConnection().listDatabags();
|
||||
assertNotNull(databags);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testCreateDatabag() throws Exception {
|
||||
getAdminConnection().deleteDatabag(PREFIX);
|
||||
getAdminConnection().createDatabag(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateDatabag")
|
||||
public void testDatabagExists() throws Exception {
|
||||
assertNotNull(getClientConnection().databagExists(PREFIX));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateDatabagItem")
|
||||
public void testListDatabagItems() throws Exception {
|
||||
Set<String> databagItems = getAdminConnection().listDatabagItems(PREFIX);
|
||||
assertNotNull(databagItems);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = { "testCreateDatabag", "testCreateRole" })
|
||||
public void testCreateDatabagItem() throws Exception {
|
||||
Properties config = new Properties();
|
||||
config.setProperty("foo", "bar");
|
||||
getAdminConnection().deleteDatabagItem(PREFIX, PREFIX);
|
||||
databagItem = getAdminConnection().createDatabagItem(PREFIX, new DatabagItem("config", json.toJson(config)));
|
||||
assertNotNull(databagItem);
|
||||
assertEquals(databagItem.getId(), "config");
|
||||
assertEquals(config, json.fromJson(databagItem.toString(), Properties.class));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateDatabagItem")
|
||||
public void testDatabagItemExists() throws Exception {
|
||||
assertNotNull(getClientConnection().databagItemExists(PREFIX, PREFIX));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testDatabagItemExists")
|
||||
public void testUpdateDatabagItem() throws Exception {
|
||||
for (String databagItemId : getClientConnection().listDatabagItems(PREFIX)) {
|
||||
DatabagItem databagItem = getAdminConnection().getDatabagItem(PREFIX, databagItemId);
|
||||
getAdminConnection().updateDatabagItem(PREFIX, databagItem);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListSearchIndexes() throws Exception {
|
||||
Set<String> indexes = getAdminConnection().listSearchIndexes();
|
||||
assertNotNull(indexes);
|
||||
assert indexes.contains("node") : indexes;
|
||||
assert indexes.contains("client") : indexes;
|
||||
assert indexes.contains("role") : indexes;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchNodes() throws Exception {
|
||||
SearchResult<? extends Node> results = getAdminConnection().searchNodes();
|
||||
assertNotNull(results);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchClients() throws Exception {
|
||||
SearchResult<? extends Client> results = getAdminConnection().searchClients();
|
||||
assertNotNull(results);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchRoles() throws Exception {
|
||||
SearchResult<? extends Role> results = getAdminConnection().searchRoles();
|
||||
assertNotNull(results);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testDatabagItemExists")
|
||||
public void testSearchDatabag() throws Exception {
|
||||
SearchResult<? extends DatabagItem> results = getAdminConnection().searchDatabag(PREFIX);
|
||||
assertNotNull(results);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testSearchDatabagNotFound() throws Exception {
|
||||
SearchResult<? extends DatabagItem> results = getAdminConnection().searchDatabag("whoopie");
|
||||
assertNotNull(results);
|
||||
}
|
||||
|
||||
@AfterClass(groups = { "live" })
|
||||
public void teardownClient() throws IOException {
|
||||
if (getValidatorConnection().clientExists(PREFIX))
|
||||
getValidatorConnection().deleteClient(PREFIX);
|
||||
if (getAdminConnection().nodeExists(PREFIX))
|
||||
getAdminConnection().deleteNode(PREFIX);
|
||||
if (getAdminConnection().roleExists(PREFIX))
|
||||
getAdminConnection().deleteRole(PREFIX);
|
||||
if (getAdminConnection().databagExists(PREFIX))
|
||||
getAdminConnection().deleteDatabag(PREFIX);
|
||||
closeContexts();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,745 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.chef.config.ChefRestClientModule;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.chef.domain.DatabagItem;
|
||||
import org.jclouds.chef.domain.Node;
|
||||
import org.jclouds.chef.domain.Role;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuth;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuthTest;
|
||||
import org.jclouds.chef.functions.ParseKeySetFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchClientsFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchDatabagFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchNodesFromJson;
|
||||
import org.jclouds.chef.functions.ParseSearchRolesFromJson;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.RestClientTest;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
|
||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Tests annotation parsing of {@code ChefAsyncClient}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "chef.ChefAsyncClientTest")
|
||||
public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||
|
||||
public void testCommitSandbox() throws SecurityException, NoSuchMethodException, IOException {
|
||||
|
||||
Method method = ChefAsyncClient.class.getMethod("commitSandbox", String.class, boolean.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
"0189e76ccc476701d6b374e5a1a27347", true);
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"PUT http://localhost:4000/sandboxes/0189e76ccc476701d6b374e5a1a27347 HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, "{\"is_completed\":\"true\"}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGetUploadSandboxForChecksums() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("getUploadSandboxForChecksums", Set.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, ImmutableSet.of(Bytes
|
||||
.asList(CryptoStreams.hex("0189e76ccc476701d6b374e5a1a27347")), Bytes.asList(CryptoStreams
|
||||
.hex("0c5ecd7788cf4f6c7de2a57193897a6c")), Bytes.asList(CryptoStreams
|
||||
.hex("1dda05ed139664f1f89b9dec482b77c0"))));
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/sandboxes HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"checksums\":{\"0189e76ccc476701d6b374e5a1a27347\":null,\"0c5ecd7788cf4f6c7de2a57193897a6c\":null,\"1dda05ed139664f1f89b9dec482b77c0\":null}}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGetCookbook() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("getCookbook", String.class, String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "cookbook", "1.0.0");
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks/cookbook/1.0.0 HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteCookbook() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteCookbook", String.class, String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "cookbook", "1.0.0");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/cookbooks/cookbook/1.0.0 HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateCookbook() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, String.class,
|
||||
CookbookVersion.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "cookbook", "1.0.1",
|
||||
new CookbookVersion("cookbook", "1.0.1"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"cookbook-1.0.1\",\"definitions\":[],\"attributes\":[],\"files\":[],\"metadata\":{\"suggestions\":{},\"dependencies\":{},\"conflicting\":{},\"providing\":{},\"platforms\":{},\"recipes\":{},\"replacing\":{},\"groupings\":{},\"attributes\":{},\"recommendations\":{}},\"providers\":[],\"cookbook_name\":\"cookbook\",\"resources\":[],\"templates\":[],\"libraries\":[],\"version\":\"1.0.1\",\"recipes\":[],\"root_files\":[],\"json_class\":\"Chef::CookbookVersion\",\"chef_type\":\"cookbook_version\"}",
|
||||
"application/json", false);
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListCookbooks() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listCookbooks");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testClientExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("clientExists", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/clients/client HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteClient() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteClient", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/clients/client HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateClient() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createClient", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/clients HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\"}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListClients() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listClients");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/clients HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\", \"private_key\": true}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testNodeExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("nodeExists", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "node");
|
||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/nodes/node HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteNode() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteNode", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "node");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/nodes/node HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateNode() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createNode", Node.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Node("testnode",
|
||||
ImmutableSet.of("recipe[java]")));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/nodes HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"testnode\",\"normal\":{},\"override\":{},\"default\":{},\"automatic\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Node\",\"chef_type\":\"node\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateNode() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("updateNode", Node.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Node("testnode",
|
||||
ImmutableSet.of("recipe[java]")));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/nodes/testnode HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"testnode\",\"normal\":{},\"override\":{},\"default\":{},\"automatic\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Node\",\"chef_type\":\"node\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListNodes() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listNodes");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/nodes HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testRoleExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("roleExists", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "role");
|
||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/roles/role HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteRole() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteRole", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "role");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/roles/role HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateRole() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createRole", Role.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Role("testrole",
|
||||
ImmutableSet.of("recipe[java]")));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/roles HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateRole() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("updateRole", Role.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Role("testrole",
|
||||
ImmutableSet.of("recipe[java]")));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/roles/testrole HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListRoles() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listRoles");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/roles HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDatabagExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("databagExists", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "databag");
|
||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/data/databag HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteDatabag() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteDatabag", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "databag");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/data/databag HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateDatabag() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createDatabag", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"name\"}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListDatabags() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listDatabags");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/data HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDatabagItemExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("databagItemExists", String.class, String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", "databagItem");
|
||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/data/name/databagItem HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteDatabagItem() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteDatabagItem", String.class, String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", "databagItem");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/data/name/databagItem HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testCreateDatabagItemThrowsIllegalArgumentOnPrimitive() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createDatabagItem", String.class, DatabagItem.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", new DatabagItem("id",
|
||||
"100"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"testdatabagItem\",\"override_attributes\":{},\"default_attributes\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::DatabagItem\",\"chef_type\":\"databagItem\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testCreateDatabagItemThrowsIllegalArgumentOnWrongId() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createDatabagItem", String.class, DatabagItem.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", new DatabagItem("id",
|
||||
"{\"id\": \"item1\",\"my_key\": \"my_data\"}"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(
|
||||
httpRequest,
|
||||
"{\"name\":\"testdatabagItem\",\"override_attributes\":{},\"default_attributes\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::DatabagItem\",\"chef_type\":\"databagItem\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateDatabagItem() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createDatabagItem", String.class, DatabagItem.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", new DatabagItem("id",
|
||||
"{\"id\": \"id\",\"my_key\": \"my_data\"}"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, "{\"id\": \"id\",\"my_key\": \"my_data\"}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateDatabagItemEvenWhenUserForgotId() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createDatabagItem", String.class, DatabagItem.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", new DatabagItem("id",
|
||||
"{\"my_key\": \"my_data\"}"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, "{\"id\":\"id\",\"my_key\": \"my_data\"}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateDatabagItem() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("updateDatabagItem", String.class, DatabagItem.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name", new DatabagItem("id",
|
||||
"{\"my_key\": \"my_data\"}"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/data/name/id HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
|
||||
assertPayloadEquals(httpRequest, "{\"id\":\"id\",\"my_key\": \"my_data\"}", "application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListDatabagItems() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listDatabagItems", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "name");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/data/name HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testListSearchIndexes() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listSearchIndexes");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testSearchRoles() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("searchRoles");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/role HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseSearchRolesFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testSearchClients() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("searchClients");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/client HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseSearchClientsFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testSearchNodes() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("searchNodes");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/node HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseSearchNodesFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testSearchDatabag() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("searchDatabag", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "foo");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/foo HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
|
||||
assertPayloadEquals(httpRequest, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseSearchDatabagFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkFilters(HttpRequest request) {
|
||||
assertEquals(request.getFilters().size(), 1);
|
||||
assertEquals(request.getFilters().get(0).getClass(), SignedHeaderAuth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeLiteral<RestAnnotationProcessor<ChefAsyncClient>> createTypeLiteral() {
|
||||
return new TypeLiteral<RestAnnotationProcessor<ChefAsyncClient>>() {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestChefRestClientModule();
|
||||
}
|
||||
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
static class TestChefRestClientModule extends ChefRestClientModule {
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
return "timestamp";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSpec<ChefClient, ChefAsyncClient> createContextSpec() {
|
||||
return new RestContextFactory().createContextSpec("chef", "user", SignedHeaderAuthTest.PRIVATE_KEY,
|
||||
new Properties());
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.config.ChefParserModule;
|
||||
import org.jclouds.chef.domain.CookbookVersion;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rest.HttpClient;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ChefClient}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "chef.ChefClientLiveTest")
|
||||
public class ChefClientLiveTest extends BaseChefClientLiveTest {
|
||||
|
||||
private ChefContext validatorConnection;
|
||||
private ChefContext clientConnection;
|
||||
private ChefContext adminConnection;
|
||||
|
||||
private String validator;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = { "live" })
|
||||
public void setupClient() throws IOException {
|
||||
endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint");
|
||||
validator = System.getProperty("jclouds.test.validator");
|
||||
if (validator == null || validator.equals(""))
|
||||
validator = "chef-validator";
|
||||
String validatorKey = System.getProperty("jclouds.test.validator.key");
|
||||
if (validatorKey == null || validatorKey.equals(""))
|
||||
validatorKey = System.getProperty("user.home") + "/.chef/validation.pem";
|
||||
user = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
|
||||
String keyfile = System.getProperty("jclouds.test.credential");
|
||||
if (keyfile == null || keyfile.equals(""))
|
||||
keyfile = System.getProperty("user.home") + "/.chef/" + user + ".pem";
|
||||
validatorConnection = createConnection(validator, Files.toString(new File(validatorKey), Charsets.UTF_8));
|
||||
adminConnection = createConnection(user, Files.toString(new File(keyfile), Charsets.UTF_8));
|
||||
json = Guice.createInjector(new GsonModule(), new ChefParserModule()).getInstance(Json.class);
|
||||
}
|
||||
|
||||
private ChefContext createConnection(String identity, String key) throws IOException {
|
||||
Properties props = new Properties();
|
||||
props.setProperty("chef.endpoint", endpoint);
|
||||
return new ChefContextFactory().createContext(identity, key, ImmutableSet.<Module> of(new Log4JLoggingModule()),
|
||||
props);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpClient getHttp() {
|
||||
return adminConnection.utils().http();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChefClient getAdminConnection() {
|
||||
return adminConnection.getApi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChefClient getValidatorConnection() {
|
||||
return validatorConnection.getApi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChefClient getClientConnection() {
|
||||
return clientConnection.getApi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recreateClientConnection() throws IOException {
|
||||
if (clientConnection != null)
|
||||
clientConnection.close();
|
||||
clientConnection = createConnection(PREFIX, clientKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListCookbookVersionsWithChefService() throws Exception {
|
||||
Iterable<? extends CookbookVersion> cookbooks = adminConnection.getChefService().listCookbookVersions();
|
||||
assertNotNull(cookbooks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeContexts() {
|
||||
if (clientConnection != null)
|
||||
clientConnection.close();
|
||||
if (validatorConnection != null)
|
||||
validatorConnection.close();
|
||||
if (adminConnection != null)
|
||||
adminConnection.close();
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef;
|
||||
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class ProvidersInPropertiesTest {
|
||||
|
||||
@Test
|
||||
public void testSupportedProviders() {
|
||||
Iterable<String> providers = Utils.getSupportedProviders();
|
||||
assert Iterables.contains(providers, "chef") : providers;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.binders;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
|
||||
import org.jclouds.chef.config.ChefParserModule;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "chef.BootstrapChefClientTest")
|
||||
public class BindHexEncodedMD5sToJsonPayloadTest {
|
||||
|
||||
Injector injector = Guice.createInjector(new ChefParserModule(), new GsonModule());
|
||||
BindChecksumsToJsonPayload binder = injector.getInstance(BindChecksumsToJsonPayload.class);
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMustBeIterable() {
|
||||
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
|
||||
binder.bindToRequest(request, new File("foo"));
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testCorrect() {
|
||||
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
|
||||
binder.bindToRequest(request, ImmutableSet.of(CryptoStreams.hex("abddef"), CryptoStreams.hex("1234")));
|
||||
assertEquals(request.getPayload().getRawContent(), "{\"checksums\":{\"abddef\":null,\"1234\":null}}");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
|
||||
public void testNullIsBad() {
|
||||
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
|
||||
binder.bindToRequest(request, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.jclouds.chef.filters;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.internal.SignatureWire;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.BaseRestClientTest.MockModule;
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "chef.SignedHeaderAuthTest")
|
||||
public class SignedHeaderAuthTest {
|
||||
|
||||
public static final String USER_ID = "spec-user";
|
||||
public static final String BODY = "Spec Body";
|
||||
// Base64.encode64(Digest::SHA1.digest("Spec Body")).chomp
|
||||
public static final String HASHED_BODY = "DFteJZPVv6WKdQmMqZUQUumUyRs=";
|
||||
public static final String TIMESTAMP_ISO8601 = "2009-01-01T12:00:00Z";
|
||||
|
||||
public static final String PATH = "/organizations/clownco";
|
||||
// Base64.encode64(Digest::SHA1.digest("/organizations/clownco")).chomp
|
||||
|
||||
public static final String HASHED_CANONICAL_PATH = "YtBWDn1blGGuFIuKksdwXzHU9oE=";
|
||||
public static final String REQUESTING_ACTOR_ID = "c0f8a68c52bffa1020222a56b23cccfa";
|
||||
|
||||
// Content hash is ???TODO
|
||||
public static final String X_OPS_CONTENT_HASH = "DFteJZPVv6WKdQmMqZUQUumUyRs=";
|
||||
|
||||
public static final String[] X_OPS_AUTHORIZATION_LINES = new String[] {
|
||||
"jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4",
|
||||
"NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc",
|
||||
"3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O",
|
||||
"IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy",
|
||||
"9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0", "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" };
|
||||
|
||||
// We expect Mixlib::Authentication::SignedHeaderAuth//sign to return this
|
||||
// if passed the BODY above.
|
||||
public static final Multimap<String, String> EXPECTED_SIGN_RESULT = ImmutableMultimap.<String, String> builder()
|
||||
.put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH).put("X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0")
|
||||
.put("X-Ops-Authorization-1", X_OPS_AUTHORIZATION_LINES[0]).put("X-Ops-Authorization-2",
|
||||
X_OPS_AUTHORIZATION_LINES[1]).put("X-Ops-Authorization-3", X_OPS_AUTHORIZATION_LINES[2]).put(
|
||||
"X-Ops-Authorization-4", X_OPS_AUTHORIZATION_LINES[3]).put("X-Ops-Authorization-5",
|
||||
X_OPS_AUTHORIZATION_LINES[4]).put("X-Ops-Authorization-6", X_OPS_AUTHORIZATION_LINES[5]).put(
|
||||
"X-Ops-Timestamp", TIMESTAMP_ISO8601).build();
|
||||
|
||||
// Content hash for empty string
|
||||
public static final String X_OPS_CONTENT_HASH_EMPTY = "2jmj7l5rSw0yVb/vlWAYkK/YBwk=";
|
||||
public static final Multimap<String, String> EXPECTED_SIGN_RESULT_EMPTY = ImmutableMultimap
|
||||
.<String, String> builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH_EMPTY).put("X-Ops-Userid", USER_ID)
|
||||
.put("X-Ops-Sign", "version=1.0").put("X-Ops-Authorization-1",
|
||||
"N6U75kopDK64cEFqrB6vw+PnubnXr0w5LQeXnIGNGLRP2LvifwIeisk7QxEx").put("X-Ops-Authorization-2",
|
||||
"mtpQOWAw8HvnWErjzuk9AvUsqVmWpv14ficvkaD79qsPMvbje+aLcIrCGT1P").put("X-Ops-Authorization-3",
|
||||
"3d2uvf4w7iqwzrIscPnkxLR6o6pymR90gvJXDPzV7Le0jbfD8kmZ8AAK0sGG").put("X-Ops-Authorization-4",
|
||||
"09F1ftW80bLatJTA66Cw2wBz261r6x/abZhIKFJFDWLzyQGJ8ZNOkUrDDtgI").put("X-Ops-Authorization-5",
|
||||
"svLVXpOJKZZfKunsElpWjjsyNt3k8vpI1Y4ANO8Eg2bmeCPeEK+YriGm5fbC").put("X-Ops-Authorization-6",
|
||||
"DzWNPylHJqMeGKVYwGQKpg62QDfe5yXh3wZLiQcXow==").put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build();
|
||||
|
||||
public static String PUBLIC_KEY;
|
||||
public static String PRIVATE_KEY;
|
||||
|
||||
static {
|
||||
try {
|
||||
PUBLIC_KEY = Utils.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/pubkey.txt"));
|
||||
|
||||
PRIVATE_KEY = Utils.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/privkey.txt"));
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void canonicalizedPathRemovesMultipleSlashes() {
|
||||
assertEquals(signing_obj.canonicalPath("///"), "/");
|
||||
}
|
||||
|
||||
@Test
|
||||
void canonicalizedPathRemovesTrailingSlash() {
|
||||
assertEquals(signing_obj.canonicalPath("/path/"), "/path");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGenerateTheCorrectStringToSignAndSignature() {
|
||||
|
||||
URI host = URI.create("http://localhost/" + PATH);
|
||||
HttpRequest request = new HttpRequest(HttpMethod.POST, host);
|
||||
request.setPayload(BODY);
|
||||
|
||||
String expected_string_to_sign = new StringBuilder().append("Method:POST").append("\n").append("Hashed Path:")
|
||||
.append(HASHED_CANONICAL_PATH).append("\n").append("X-Ops-Content-Hash:").append(HASHED_BODY).append("\n")
|
||||
.append("X-Ops-Timestamp:").append(TIMESTAMP_ISO8601).append("\n").append("X-Ops-UserId:").append(USER_ID)
|
||||
.toString();
|
||||
|
||||
assertEquals(signing_obj.createStringToSign("POST", HASHED_CANONICAL_PATH, HASHED_BODY, TIMESTAMP_ISO8601),
|
||||
expected_string_to_sign);
|
||||
assertEquals(signing_obj.sign(expected_string_to_sign), Joiner.on("").join(X_OPS_AUTHORIZATION_LINES));
|
||||
|
||||
signing_obj.filter(request);
|
||||
Multimap<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders());
|
||||
headersWithoutContentLength.removeAll(HttpHeaders.CONTENT_LENGTH);
|
||||
assertEquals(headersWithoutContentLength.values(), EXPECTED_SIGN_RESULT.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGenerateTheCorrectStringToSignAndSignatureWithNoBody() {
|
||||
|
||||
URI host = URI.create("http://localhost/" + PATH);
|
||||
HttpRequest request = new HttpRequest(HttpMethod.DELETE, host);
|
||||
|
||||
signing_obj.filter(request);
|
||||
Multimap<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders());
|
||||
assertEquals(headersWithoutContentLength.entries(), EXPECTED_SIGN_RESULT_EMPTY.entries());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotChokeWhenSigningARequestForAResourceWithALongName() {
|
||||
StringBuilder path = new StringBuilder("nodes/");
|
||||
for (int i = 0; i < 100; i++)
|
||||
path.append('A');
|
||||
URI host = URI.create("http://localhost/" + path.toString());
|
||||
HttpRequest request = new HttpRequest(HttpMethod.PUT, host);
|
||||
request.setPayload(BODY);
|
||||
signing_obj.filter(request);
|
||||
}
|
||||
|
||||
private SignedHeaderAuth signing_obj;
|
||||
private Crypto crypto;
|
||||
|
||||
/**
|
||||
* before class, as we need to ensure that the filter is threadsafe.
|
||||
*
|
||||
* @throws IOException
|
||||
*
|
||||
*/
|
||||
@BeforeClass
|
||||
protected void createFilter() throws IOException {
|
||||
|
||||
Injector injector = new RestContextFactory().createContextBuilder("chef", USER_ID, PRIVATE_KEY,
|
||||
ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule()), new Properties()).buildInjector();
|
||||
|
||||
crypto = injector.getInstance(Crypto.class);
|
||||
HttpUtils utils = injector.getInstance(HttpUtils.class);
|
||||
|
||||
PrivateKey privateKey = injector.getInstance(PrivateKey.class);
|
||||
|
||||
signing_obj = new SignedHeaderAuth(new SignatureWire(), USER_ID, privateKey, new Provider<String>() {
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return TIMESTAMP_ISO8601;
|
||||
}
|
||||
|
||||
}, crypto, utils);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue