Merge branch 'master' of git://github.com/jclouds/jclouds

* 'master' of git://github.com/jclouds/jclouds:
  fixed base archetype and removed twitter client
  Issue 191, 273: moved to http://github.com/jclouds/chef
  Issue 191, 273: moved to http://github.com/jclouds/chef
  added test to aws for unknown instance type
  Issue 358: changed to enum.UNRECOGNIZED for all values that could arrive from a server
  Issue 280: started work converting to new error type in vcloud
  Issue 199: update to latest version of ning
  Add test for vararg options
This commit is contained in:
Adrian Cole 2010-09-18 16:22:09 -07:00
commit de5ec94344
294 changed files with 1285 additions and 19615 deletions

View File

@ -39,8 +39,8 @@ our blobstore api supports: s3, rackspace, azure, atmos online, att synaptic,
* note * the pom dependency org.jclouds/jclouds-allblobstore gives you access to
to all of these providers
we also have rest clients for: chef, opscodeplatform, twitter, as well a number of features
in the sandbox
we also have support for: ibmdev, mezeo, nirvanix, boxdotnet, as well a number of features
the sandbox
If you want access to all jclouds components, include the maven dependency org.jclouds/jclouds-all

View File

@ -39,20 +39,5 @@
<artifactId>jclouds-allblobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<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>

View File

@ -32,8 +32,8 @@
</requiredProperty>
<requiredProperty key="providerName" />
<requiredProperty key="providerEndpoint" />
<requiredProperty key="providerAccount" />
<requiredProperty key="providerKey" />
<requiredProperty key="providerIdentity" />
<requiredProperty key="providerCredential" />
</requiredProperties>
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">

View File

@ -1,94 +0,0 @@
#set( $lcaseProviderName = ${providerName.toLowerCase()} )
#set( $symbol_dollar = '$' )
<?xml version="1.0" encoding="UTF-8"?>
<!--
${symbol_dollar}HeadURL${symbol_dollar}
${symbol_dollar}Revision${symbol_dollar}
${symbol_dollar}Date${symbol_dollar}
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-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>${groupId}</groupId>
<artifactId>jclouds-${artifactId}</artifactId>
<name>jclouds ${providerName} core</name>
<description>jclouds components to access ${providerName}</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/${lcaseProviderName}</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/${lcaseProviderName}</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/${lcaseProviderName}</url>
</scm>
<!-- 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>
<properties>
<jclouds.test.identity>${providerAccount}</jclouds.test.identity>
<jclouds.test.credential>${providerKey}</jclouds.test.credential>
</properties>
<dependencies>
<dependency>
<groupId>${symbol_dollar}{project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${symbol_dollar}{project.version}</version>
</dependency>
<dependency>
<groupId>${symbol_dollar}{project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${symbol_dollar}{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>${symbol_dollar}{project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${symbol_dollar}{project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,42 +0,0 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/**
*
* 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.
* ====================================================================
*/
package ${package};
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Related to a ${providerName} resource.
*
* @author ${author}
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface ${providerName} {
}

View File

@ -1,66 +0,0 @@
#set( $ucaseProviderName = ${providerName.toUpperCase()} )
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/**
*
* 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
*
* 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 ${package};
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.Properties;
import org.jclouds.rest.RestContextBuilder;
import ${package}.${providerName}AsyncClient;
import ${package}.${providerName}Client;
import ${package}.config.${providerName}ContextModule;
import ${package}.config.${providerName}RestClientModule;
import ${package}.reference.${providerName}Constants;
import com.google.inject.Module;
/**
*
* @author ${author}
*/
public class ${providerName}ContextBuilder extends RestContextBuilder<${providerName}Client, ${providerName}AsyncClient> {
public ${providerName}ContextBuilder(String providerName, Properties props) {
super(providerName, ${providerName}Client.class, ${providerName}AsyncClient.class, props);
checkNotNull(properties.getProperty(${providerName}Constants.PROPERTY_${ucaseProviderName}_USER));
checkNotNull(properties.getProperty(${providerName}Constants.PROPERTY_${ucaseProviderName}_PASSWORD));
}
protected void addClientModule(List<Module> modules) {
modules.add(new ${providerName}RestClientModule());
}
@Override
protected void addContextModule(String providerName, List<Module> modules) {
modules.add(new ${providerName}ContextModule(providerName));
}
}

View File

@ -1,72 +0,0 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/**
*
* 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
*
* 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 ${package};
import java.net.URI;
import java.util.Properties;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import com.google.inject.Module;
/**
* Creates {@link RestContext} for {@link ${providerName}Client} instances based on the most commonly
* requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author ${author}
* @see RestContext
* @see ${providerName}Client
* @see ${providerName}AsyncClient
*/
public class ${providerName}ContextFactory {
public static RestContext<${providerName}Client, ${providerName}AsyncClient> createContext(String user, String password,
Module... modules) {
return new ${providerName}ContextBuilder("${artifactId}", new ${providerName}PropertiesBuilder(user, password).build())
.withModules(modules).buildContext();
}
public static RestContext<${providerName}Client, ${providerName}AsyncClient> createContext(URI endpoint, String user, String password,
Module... modules) {
return new ${providerName}ContextBuilder("${artifactId}", new ${providerName}PropertiesBuilder(user, password).withEndpoint(endpoint).build())
.withModules(modules).buildContext();
}
public static RestContext<${providerName}Client, ${providerName}AsyncClient> createContext(Properties properties, Module... modules) {
return new ${providerName}ContextBuilder("${artifactId}", new ${providerName}PropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
}

View File

@ -1,73 +0,0 @@
#set( $ucaseProviderName = ${providerName.toUpperCase()} )
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/**
*
* 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
*
* 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 ${package};
import static com.google.common.base.Preconditions.checkNotNull;
import static ${package}.reference.${providerName}Constants.PROPERTY_${ucaseProviderName}_ENDPOINT;
import static ${package}.reference.${providerName}Constants.PROPERTY_${ucaseProviderName}_PASSWORD;
import static ${package}.reference.${providerName}Constants.PROPERTY_${ucaseProviderName}_USER;
import java.net.URI;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in ${providerName} Clients
*
* @author ${author}
*/
public class ${providerName}PropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_${ucaseProviderName}_ENDPOINT, "${providerEndpoint}");
return properties;
}
public ${providerName}PropertiesBuilder(Properties properties) {
super(properties);
}
public ${providerName}PropertiesBuilder(String id, String secret) {
super();
withCredentials(id, secret);
}
public ${providerName}PropertiesBuilder withCredentials(String id, String secret) {
properties.setProperty(PROPERTY_${ucaseProviderName}_USER, checkNotNull(id, "user"));
properties.setProperty(PROPERTY_${ucaseProviderName}_PASSWORD, checkNotNull(secret, "password"));
return this;
}
public ${providerName}PropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(PROPERTY_${ucaseProviderName}_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
return this;
}
}

View File

@ -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.
* ====================================================================
*/
#set( $ucaseProviderName = ${providerName.toUpperCase()} )
package ${package}.config;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.lifecycle.Closer;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import ${package}.${providerName};
import ${package}.${providerName}AsyncClient;
import ${package}.${providerName}Client;
import ${package}.reference.${providerName}Constants;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures the ${providerName} connection, including logging and http transport.
*
* @author ${author}
*/
public class ${providerName}ContextModule extends AbstractModule {
public ${providerName}ContextModule(String providerName) {
// providerName ignored right now
}
@Override
protected void configure() {
// example of how to customize bindings
// bind(DateAdapter.class).to(CDateAdapter.class);
}
@Provides
@Singleton
RestContext<${providerName}Client, ${providerName}AsyncClient> provideContext(Closer closer, ${providerName}AsyncClient asyncApi,
${providerName}Client syncApi, @${providerName} URI endPoint, @Named(${providerName}Constants.PROPERTY_${ucaseProviderName}_USER) String identity) {
return new RestContextImpl<${providerName}Client, ${providerName}AsyncClient>(closer, asyncApi, syncApi, endPoint, identity);
}
}

View File

@ -1,93 +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.
* ====================================================================
*/
#set( $ucaseProviderName = ${providerName.toUpperCase()} )
package ${package}.config;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.http.HttpErrorHandler;
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.http.filters.BasicAuthentication;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.crypto.Crypto;
import ${package}.${providerName};
import ${package}.${providerName}Client;
import ${package}.${providerName}AsyncClient;
import ${package}.reference.${providerName}Constants;
import ${package}.handlers.${providerName}ErrorHandler;
import com.google.inject.Provides;
/**
* Configures the ${providerName} connection.
*
* @author ${author}
*/
@RequiresHttp
@ConfiguresRestClient
public class ${providerName}RestClientModule extends
RestClientModule<${providerName}Client, ${providerName}AsyncClient> {
public ${providerName}RestClientModule() {
super(${providerName}Client.class, ${providerName}AsyncClient.class);
}
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication(
@Named(${providerName}Constants.PROPERTY_${ucaseProviderName}_USER) String user,
@Named(${providerName}Constants.PROPERTY_${ucaseProviderName}_PASSWORD) String password,
Crypto crypto)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password, crypto);
}
@Provides
@Singleton
@${providerName}
protected URI provideURI(@Named(${providerName}Constants.PROPERTY_${ucaseProviderName}_ENDPOINT) String endpoint) {
return URI.create(endpoint);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
${providerName}ErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
${providerName}ErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
${providerName}ErrorHandler.class);
}
@Override
protected void bindRetryHandlers() {
// TODO
}
}

View File

@ -1,92 +0,0 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/**
*
* 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.
* ====================================================================
*/
package ${package}.handlers;
import java.io.IOException;
import javax.annotation.Resource;
import javax.inject.Singleton;
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 org.jclouds.util.Utils;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
/**
* This will parse and set an appropriate exception on the command object.
*
* @author Adrian Cole
*
*/
@Singleton
public class ${providerName}ErrorHandler implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
String message = parseMessage(response);
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
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 {
Closeables.closeQuietly(response.getContent());
command.setException(exception);
}
}
public String parseMessage(HttpResponse response) {
if (response.getContent() == null)
return null;
try {
return Utils.toStringAndClose(response.getContent());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
response.getContent().close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
}

View File

@ -1,33 +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.
* ====================================================================
*/
#set( $lcaseProviderName = ${providerName.toLowerCase()} )
#set( $ucaseProviderName = ${providerName.toUpperCase()} )
package ${package}.reference;
/**
* Configuration properties and constants used in ${providerName} connections.
*
* @author ${author}
*/
public interface ${providerName}Constants {
public static final String PROPERTY_${ucaseProviderName}_ENDPOINT = "jclouds.${lcaseProviderName}.endpoint";
public static final String PROPERTY_${ucaseProviderName}_USER = "jclouds.${lcaseProviderName}.user";
public static final String PROPERTY_${ucaseProviderName}_PASSWORD = "jclouds.${lcaseProviderName}.password";
}

View File

@ -32,7 +32,7 @@
<packaging>pom</packaging>
<name>jclouds Maven archetypes</name>
<modules>
<module>json-client-archetype</module>
<module>rest-client-archetype</module>
<module>compute-service-archetype</module>
</modules>
</project>

View File

@ -28,9 +28,9 @@
<artifactId>jclouds-archetypes</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jclouds-json-client-archetype</artifactId>
<name>jclouds JSON client archetype</name>
<description>Maven archetype for a provider of a JSON-speaking service</description>
<artifactId>jclouds-rest-client-archetype</artifactId>
<name>jclouds rest client archetype</name>
<description>Maven archetype for a provider of a rest-speaking service</description>
<packaging>maven-archetype</packaging>
<build>

View File

@ -19,7 +19,7 @@
====================================================================
-->
<archetype-descriptor name="jclouds-json-client-archetype">
<archetype-descriptor name="jclouds-rest-client-archetype">
<requiredProperties>
<requiredProperty key="groupId">
<defaultValue>org.jclouds</defaultValue>
@ -32,8 +32,9 @@
</requiredProperty>
<requiredProperty key="providerName" />
<requiredProperty key="providerEndpoint" />
<requiredProperty key="providerAccount" />
<requiredProperty key="providerKey" />
<requiredProperty key="providerIdentity" />
<requiredProperty key="providerApiVersion" />
<requiredProperty key="providerCredential" />
</requiredProperties>
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">

View File

@ -1,8 +1,8 @@
In this module, you can run just unit tests, or run tests that connect directly to the service. To run against the service, you'll need to specify the maven profile live.
When live is enabled, any tests that have "LiveTest" suffix will be run during the integration-test phase. In order for this to operate, you must specify the following
properties:
* jclouds.test.account
* jclouds.test.key
* test.${lcaseProviderName}.identity
* test.${lcaseProviderName}.credential
Note that this module is intentionally incomplete. You should global replace and create your own client from this example. Make sure that you use tests propertly. For
example, the test ending in *AsyncClientTest will help ensure that your annotations parse in the way you expect.

View File

@ -0,0 +1,141 @@
#set( $lcaseProviderName = ${providerName.toLowerCase()} )
#set(
$symbol_dollar = '$' )
<?xml version="1.0" encoding="UTF-8"?>
<!--
${symbol_dollar}HeadURL${symbol_dollar}
${symbol_dollar}Revision${symbol_dollar}
${symbol_dollar}Date${symbol_dollar} 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-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>${groupId}</groupId>
<artifactId>jclouds-${artifactId}</artifactId>
<name>jclouds ${providerName} core</name>
<description>jclouds components to access ${providerName}</description>
<scm>
<connection>scm:git:git@github.com:jclouds/jclouds.git</connection>
<developerConnection>scm:git:git@github.com:jclouds/jclouds.git</developerConnection>
<url>http://github.com/jclouds/jclouds/tree/master/${lcaseProviderName}</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>
<test.${lcaseProviderName}.identity>${providerIdentity}</test.${lcaseProviderName}.identity>
<test.${lcaseProviderName}.credential>${providerCredential}</test.${lcaseProviderName}.credential>
<test.${lcaseProviderName}.apiversion>${providerApiVersion}</test.${lcaseProviderName}.apiversion>
<test.${lcaseProviderName}.endpoint>${providerEndpoint}</test.${lcaseProviderName}.endpoint>
</properties>
<dependencies>
<dependency>
<groupId>${symbol_dollar}{project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${symbol_dollar}{project.version}</version>
</dependency>
<dependency>
<groupId>${symbol_dollar}{project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${symbol_dollar}{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>${symbol_dollar}{project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${symbol_dollar}{project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.${lcaseProviderName}.identity</name>
<value>\$\{test.${lcaseProviderName}.identity\}</value>
</property>
<property>
<name>test.${lcaseProviderName}.credential</name>
<value>\$\{test.${lcaseProviderName}.credential\}</value>
</property>
<property>
<name>test.${lcaseProviderName}.endpoint</name>
<value>\$\{test.${lcaseProviderName}.endpoint\}</value>
</property>
<property>
<name>test.${lcaseProviderName}.apiversion</name>
<value>\$\{test.${lcaseProviderName}.apiversion\}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -35,9 +35,9 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.http.filters.BasicAuthentication;
import ${package}.${providerName}Client;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
@ -51,10 +51,10 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see <a href="TODO: insert URL of provider documentation" />
* @author ${author}
*/
@Endpoint(${providerName}.class)
@RequestFilters(BasicAuthentication.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface ${providerName}AsyncClient {
public static final String API_VERSION = "${providerApiVersion}";
/*
* TODO: define interface methods for ${providerName}
*/
@ -64,6 +64,8 @@ public interface ${providerName}AsyncClient {
*/
@GET
@Path("/items")
@Consumes(MediaType.TEXT_PLAIN)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<String> list();
/**
@ -71,6 +73,7 @@ public interface ${providerName}AsyncClient {
*/
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Consumes(MediaType.TEXT_PLAIN)
@Path("/items/{itemId}")
ListenableFuture<String> get(@PathParam("itemId") long id);

View File

@ -27,27 +27,29 @@
*/
package ${package};
import static org.jclouds.rest.RestContextFactory.contextSpec;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Method;
import ${package}.config.${providerName}RestClientModule;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.CloseContentAndReturn;
import org.jclouds.http.functions.ReturnStringIf200;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory.ContextSpec;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
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 ${package}.${providerName}AsyncClient;
import ${package}.${providerName}Client;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
/**
* Tests annotation parsing of {@code ${providerName}AsyncClient}
@ -60,69 +62,66 @@ public class ${providerName}AsyncClientTest extends RestClientTest<${providerNam
public void testList() throws SecurityException, NoSuchMethodException, IOException {
Method method = ${providerName}AsyncClient.class.getMethod("list");
GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(method);
GeneratedHttpRequest<${providerName}AsyncClient> request = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/items HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null);
assertRequestLineEquals(request, "GET ${providerEndpoint}/items HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: text/plain\n");
assertPayloadEquals(request, null, null, false);
// now make sure request filters apply by replaying
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
Iterables.getOnlyElement(request.getFilters()).filter(request);
Iterables.getOnlyElement(request.getFilters()).filter(request);
assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/items HTTP/1.1");
assertRequestLineEquals(request, "GET ${providerEndpoint}/items HTTP/1.1");
// for example, using basic authentication, we should get "only one" header
assertHeadersEqual(httpRequest, "Accept: application/json\nAuthorization: Basic dXNlcjprZXk=\n");
assertPayloadEquals(httpRequest, null);
assertNonPayloadHeadersEqual(request, "Accept: text/plain\nAuthorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\n");
assertPayloadEquals(request, null, null, false);
// TODO: insert expected response class, which probably extends ParseJson
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class);
assertResponseParserClassEquals(method, request, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
checkFilters(request);
}
public void testGet() throws SecurityException, NoSuchMethodException, IOException {
Method method = ${providerName}AsyncClient.class.getMethod("get", long.class);
GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(method, 1);
GeneratedHttpRequest<${providerName}AsyncClient> request = processor.createRequest(method, 1);
assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/items/1 HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null);
assertRequestLineEquals(request, "GET ${providerEndpoint}/items/1 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: text/plain\n");
assertPayloadEquals(request, null, null, false);
// TODO: insert expected response class, which probably extends ParseJson
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class);
assertResponseParserClassEquals(method, request, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
// note that get methods should convert 404's to null
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
checkFilters(request);
}
public void testDelete() throws SecurityException, NoSuchMethodException, IOException {
Method method = ${providerName}AsyncClient.class.getMethod("delete", long.class);
GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(
GeneratedHttpRequest<${providerName}AsyncClient> request = processor.createRequest(
method, 1);
assertRequestLineEquals(httpRequest,
"DELETE ${providerEndpoint}/items/1 HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null);
assertRequestLineEquals(request, "DELETE ${providerEndpoint}/items/1 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpRequest);
checkFilters(request);
}
@Override
protected void checkFilters(GeneratedHttpRequest<${providerName}AsyncClient> httpRequest) {
assertEquals(httpRequest.getFilters().size(), 1);
assertEquals(httpRequest.getFilters().get(0).getClass(), BasicAuthentication.class);
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);
assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class);
}
@Override
@ -132,14 +131,8 @@ public class ${providerName}AsyncClientTest extends RestClientTest<${providerNam
}
@Override
protected Module createModule() {
return new ${providerName}RestClientModule() {
@Override
protected void configure() {
Names.bindProperties(binder(), new ${providerName}PropertiesBuilder("user", "key").build());
install(new NullLoggingModule());
super.configure();
}
};
public ContextSpec<${providerName}Client, ${providerName}AsyncClient> createContextSpec() {
return contextSpec("${lcaseProviderName}", "${providerEndpoint}", "${providerApiVersion}", "identity", "credential", ${providerName}Client.class,
${providerName}AsyncClient.class);
}
}

View File

@ -28,12 +28,19 @@
package ${package};
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.rest.RestContextFactory.contextSpec;
import static org.jclouds.rest.RestContextFactory.createContext;
import static org.testng.Assert.assertNotNull;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Tests behavior of {@code ${providerName}Client}
*
@ -42,26 +49,36 @@ import org.testng.annotations.Test;
@Test(groups = "live", testName = "${lcaseProviderName}.${providerName}ClientLiveTest")
public class ${providerName}ClientLiveTest {
private ${providerName}Client connection;
protected RestContext<${providerName}Client, ${providerName}AsyncClient> context;
protected String provider = "${lcaseProviderName}";
protected String identity;
protected String credential;
protected String endpoint;
protected String apiVersion;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test.${lcaseProviderName}.identity"), "test.${lcaseProviderName}.identity");
credential = checkNotNull(System.getProperty("test.${lcaseProviderName}.credential"), "test.${lcaseProviderName}.credential");
endpoint = checkNotNull(System.getProperty("test.${lcaseProviderName}.endpoint"), "test.${lcaseProviderName}.endpoint");
apiVersion = checkNotNull(System.getProperty("test.${lcaseProviderName}.apiversion"), "test.${lcaseProviderName}.apiversion");
}
@BeforeGroups(groups = { "live" })
public void setupClient() {
String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential");
connection = ${providerName}ContextFactory.createContext(identity, credential, new Log4JLoggingModule())
.getApi();
setupCredentials();
context = createContext(contextSpec(provider, endpoint, apiVersion, identity, credential,
${providerName}Client.class, ${providerName}AsyncClient.class), ImmutableSet.<Module> of(new Log4JLoggingModule()));
}
@Test
public void testList() throws Exception {
String response = connection.list();
String response = context.getApi().list();
assertNotNull(response);
}
@Test
public void testGet() throws Exception {
String response = connection.get(1l);
String response = context.getApi().get(1l);
assertNotNull(response);
}

View File

@ -433,74 +433,6 @@
<outputDirectory>providers/terremark</outputDirectory>
</fileSet>
<!-- providers: chef -->
<fileSet>
<directory>chef/target</directory>
<includes>
<include>jclouds-chef-${project.version}.jar</include>
</includes>
<outputDirectory>providers/chef/lib</outputDirectory>
</fileSet>
<fileSet>
<directory>chef/target</directory>
<includes>
<include>jclouds-chef-${project.version}-sources.jar</include>
</includes>
<outputDirectory>providers/chef/src</outputDirectory>
</fileSet>
<fileSet>
<directory>chef/target/apidocs</directory>
<outputDirectory>providers/chef/docs</outputDirectory>
</fileSet>
<fileSet>
<directory>chef</directory>
<includes>
<include>README.txt</include>
</includes>
<outputDirectory>providers/chef</outputDirectory>
</fileSet>
<!-- providers: opscodeplatform -->
<fileSet>
<directory>chef/target</directory>
<includes>
<include>jclouds-chef-${project.version}.jar</include>
</includes>
<outputDirectory>providers/opscodeplatform/lib</outputDirectory>
</fileSet>
<fileSet>
<directory>chef/target</directory>
<includes>
<include>jclouds-chef-${project.version}-sources.jar</include>
</includes>
<outputDirectory>providers/opscodeplatform/src</outputDirectory>
</fileSet>
<fileSet>
<directory>opscodeplatform/target</directory>
<includes>
<include>jclouds-opscodeplatform-${project.version}.jar</include>
</includes>
<outputDirectory>providers/opscodeplatform/lib</outputDirectory>
</fileSet>
<fileSet>
<directory>opscodeplatform/target</directory>
<includes>
<include>jclouds-opscodeplatform-${project.version}-sources.jar</include>
</includes>
<outputDirectory>providers/opscodeplatform/src</outputDirectory>
</fileSet>
<fileSet>
<directory>opscodeplatform/target/apidocs</directory>
<outputDirectory>providers/opscodeplatform/docs</outputDirectory>
</fileSet>
<fileSet>
<directory>opscodeplatform</directory>
<includes>
<include>README.txt</include>
</includes>
<outputDirectory>providers/opscodeplatform</outputDirectory>
</fileSet>
<!-- providers: twitter -->
<fileSet>
<directory>twitter/target</directory>

View File

@ -21,14 +21,18 @@ package org.jclouds.atmosonline.saas.domain;
public enum FileType {
DIRECTORY, REGULAR;
DIRECTORY, REGULAR, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static FileType fromValue(String v) {
return valueOf(v.toUpperCase());
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -29,7 +29,7 @@ import com.google.common.base.CaseFormat;
* @author Adrian Cole
*/
public enum StandardUnit {
SECONDS, PERCENT, BYTES, BITS, COUNT, BITS_PER_SECOND, COUNT_PER_SECOND, NONE;
SECONDS, PERCENT, BYTES, BITS, COUNT, BITS_PER_SECOND, COUNT_PER_SECOND, NONE, UNRECOGNIZED;
public String value() {
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name().replace("_PER_", "/")));
@ -41,7 +41,11 @@ public enum StandardUnit {
}
public static StandardUnit fromValue(String state) {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state").replace("/",
"_PER_")));
try {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state").replace(
"/", "_PER_")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -76,7 +76,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
.put(InstanceState.PENDING, NodeState.PENDING).put(InstanceState.RUNNING, NodeState.RUNNING).put(
InstanceState.SHUTTING_DOWN, NodeState.PENDING)
.put(InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING).put(
InstanceState.STOPPED, NodeState.SUSPENDED).build();
InstanceState.STOPPED, NodeState.SUSPENDED)
.put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED).build();
private final EC2Client client;
private final Map<RegionAndName, KeyPair> credentialsMap;

View File

@ -32,7 +32,7 @@ import java.util.Date;
*/
public class Attachment implements Comparable<Attachment> {
public static enum Status {
ATTACHING, ATTACHED, DETACHING, DETACHED, BUSY;
ATTACHING, ATTACHED, DETACHING, DETACHED, BUSY, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@ -43,7 +43,11 @@ public class Attachment implements Comparable<Attachment> {
}
public static Status fromValue(String status) {
return valueOf(checkNotNull(status, "status").toUpperCase());
try {
return valueOf(checkNotNull(status, "status").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@ -54,8 +58,7 @@ public class Attachment implements Comparable<Attachment> {
private final Status status;
private final Date attachTime;
public Attachment(String region, String volumeId, String instanceId, String device,
Status status, Date attachTime) {
public Attachment(String region, String volumeId, String instanceId, String device, Status status, Date attachTime) {
this.region = checkNotNull(region, "region");
this.volumeId = volumeId;
this.instanceId = instanceId;
@ -164,9 +167,8 @@ public class Attachment implements Comparable<Attachment> {
@Override
public String toString() {
return "Attachment [region=" + region + ", volumeId=" + volumeId + ", instanceId="
+ instanceId + ", device=" + device + ", attachTime=" + attachTime + ", status="
+ status + "]";
return "Attachment [region=" + region + ", volumeId=" + volumeId + ", instanceId=" + instanceId + ", device="
+ device + ", attachTime=" + attachTime + ", status=" + status + "]";
}
@Override

View File

@ -59,22 +59,18 @@ public class Image implements Comparable<Image> {
private final RootDeviceType rootDeviceType;
@Nullable
private final String rootDeviceName;
private final Map<String, EbsBlockDevice> ebsBlockDevices = Maps
.newHashMap();
private final Map<String, EbsBlockDevice> ebsBlockDevices = Maps.newHashMap();
private final String virtualizationType;
public String getVirtualizationType() {
return virtualizationType;
}
public Image(String region, Architecture architecture,
@Nullable String name, @Nullable String description, String imageId,
String imageLocation, String imageOwnerId, ImageState imageState,
ImageType imageType, boolean isPublic, Iterable<String> productCodes,
@Nullable String kernelId, @Nullable String platform,
@Nullable String ramdiskId, RootDeviceType rootDeviceType,
@Nullable String rootDeviceName,
Map<String, EbsBlockDevice> ebsBlockDevices, String virtualizationType) {
public Image(String region, Architecture architecture, @Nullable String name, @Nullable String description,
String imageId, String imageLocation, String imageOwnerId, ImageState imageState, ImageType imageType,
boolean isPublic, Iterable<String> productCodes, @Nullable String kernelId, @Nullable String platform,
@Nullable String ramdiskId, RootDeviceType rootDeviceType, @Nullable String rootDeviceName,
Map<String, EbsBlockDevice> ebsBlockDevices, String virtualizationType) {
this.region = checkNotNull(region, "region");
this.architecture = checkNotNull(architecture, "architecture");
this.imageId = checkNotNull(imageId, "imageId");
@ -88,14 +84,11 @@ public class Image implements Comparable<Image> {
this.isPublic = isPublic;
this.kernelId = kernelId;
this.platform = platform;
Iterables.addAll(this.productCodes, checkNotNull(productCodes,
"productCodes"));
Iterables.addAll(this.productCodes, checkNotNull(productCodes, "productCodes"));
this.ramdiskId = ramdiskId;
this.rootDeviceType = checkNotNull(rootDeviceType, "rootDeviceType");
this.ebsBlockDevices.putAll(checkNotNull(ebsBlockDevices,
"ebsBlockDevices"));
this.virtualizationType = checkNotNull(virtualizationType,
"virtualizationType");
this.ebsBlockDevices.putAll(checkNotNull(ebsBlockDevices, "ebsBlockDevices"));
this.virtualizationType = checkNotNull(virtualizationType, "virtualizationType");
}
/** The serialVersionUID */
@ -109,36 +102,48 @@ public class Image implements Comparable<Image> {
/**
* the image is deregistered and no longer available for launching
*/
DEREGISTERED;
DEREGISTERED, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static ImageState fromValue(String v) {
return valueOf(v.toUpperCase());
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static enum Architecture {
I386, X86_64;
I386, X86_64, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static Architecture fromValue(String v) {
return valueOf(v.toUpperCase());
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static enum ImageType {
MACHINE, KERNEL, RAMDISK;
MACHINE, KERNEL, RAMDISK, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static ImageType fromValue(String v) {
return valueOf(v.toUpperCase());
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@ -149,8 +154,7 @@ public class Image implements Comparable<Image> {
private final long volumeSize;
private final boolean deleteOnTermination;
public EbsBlockDevice(@Nullable String snapshotId, long volumeSize,
boolean deleteOnTermination) {
public EbsBlockDevice(@Nullable String snapshotId, long volumeSize, boolean deleteOnTermination) {
this.snapshotId = snapshotId;
this.volumeSize = volumeSize;
this.deleteOnTermination = deleteOnTermination;
@ -173,8 +177,7 @@ public class Image implements Comparable<Image> {
final int prime = 31;
int result = 1;
result = prime * result + (deleteOnTermination ? 1231 : 1237);
result = prime * result
+ ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + (int) (volumeSize ^ (volumeSize >>> 32));
return result;
}
@ -202,9 +205,8 @@ public class Image implements Comparable<Image> {
@Override
public String toString() {
return "EbsBlockDevice [deleteOnTermination=" + deleteOnTermination
+ ", snapshotId=" + snapshotId + ", volumeSize=" + volumeSize
+ "]";
return "EbsBlockDevice [deleteOnTermination=" + deleteOnTermination + ", snapshotId=" + snapshotId
+ ", volumeSize=" + volumeSize + "]";
}
}
@ -246,10 +248,9 @@ public class Image implements Comparable<Image> {
}
/**
* Current state of the AMI. If the operation returns available, the image is
* successfully registered and avail able for launching. If the operation
* returns deregistered, the image is deregistered and no longer available
* for launching.
* Current state of the AMI. If the operation returns available, the image is successfully
* registered and avail able for launching. If the operation returns deregistered, the image is
* deregistered and no longer available for launching.
*/
public ImageState getImageState() {
return imageState;
@ -263,16 +264,15 @@ public class Image implements Comparable<Image> {
}
/**
* Returns true if this image has public launch permissions. Returns false if
* it only has implicit and explicit launch permissions.
* Returns true if this image has public launch permissions. Returns false if it only has
* implicit and explicit launch permissions.
*/
public boolean isPublic() {
return isPublic;
}
/**
* The kernel associated with the image, if any. Only applicable for machine
* images.
* The kernel associated with the image, if any. Only applicable for machine images.
*/
public String getKernelId() {
return kernelId;
@ -293,8 +293,7 @@ public class Image implements Comparable<Image> {
}
/**
* The RAM disk associated with the image, if any. Only applicable for
* machine images.
* The RAM disk associated with the image, if any. Only applicable for machine images.
*/
public String getRamdiskId() {
return ramdiskId;
@ -309,8 +308,8 @@ public class Image implements Comparable<Image> {
/**
*
* @return The root device type used by the AMI. The AMI can use an Amazon
* EBS or instance store root device.
* @return The root device type used by the AMI. The AMI can use an Amazon EBS or instance store
* root device.
*/
public RootDeviceType getRootDeviceType() {
return rootDeviceType;
@ -336,37 +335,24 @@ public class Image implements Comparable<Image> {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((architecture == null) ? 0 : architecture.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
result = prime * result
+ ((ebsBlockDevices == null) ? 0 : ebsBlockDevices.hashCode());
result = prime * result + ((architecture == null) ? 0 : architecture.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((ebsBlockDevices == null) ? 0 : ebsBlockDevices.hashCode());
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
result = prime * result
+ ((imageLocation == null) ? 0 : imageLocation.hashCode());
result = prime * result
+ ((imageOwnerId == null) ? 0 : imageOwnerId.hashCode());
result = prime * result
+ ((imageState == null) ? 0 : imageState.hashCode());
result = prime * result
+ ((imageType == null) ? 0 : imageType.hashCode());
result = prime * result + ((imageLocation == null) ? 0 : imageLocation.hashCode());
result = prime * result + ((imageOwnerId == null) ? 0 : imageOwnerId.hashCode());
result = prime * result + ((imageState == null) ? 0 : imageState.hashCode());
result = prime * result + ((imageType == null) ? 0 : imageType.hashCode());
result = prime * result + (isPublic ? 1231 : 1237);
result = prime * result + ((kernelId == null) ? 0 : kernelId.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((platform == null) ? 0 : platform.hashCode());
result = prime * result
+ ((productCodes == null) ? 0 : productCodes.hashCode());
result = prime * result
+ ((ramdiskId == null) ? 0 : ramdiskId.hashCode());
result = prime * result + ((productCodes == null) ? 0 : productCodes.hashCode());
result = prime * result + ((ramdiskId == null) ? 0 : ramdiskId.hashCode());
result = prime * result + ((region == null) ? 0 : region.hashCode());
result = prime * result
+ ((rootDeviceName == null) ? 0 : rootDeviceName.hashCode());
result = prime * result
+ ((rootDeviceType == null) ? 0 : rootDeviceType.hashCode());
result = prime
* result
+ ((virtualizationType == null) ? 0 : virtualizationType.hashCode());
result = prime * result + ((rootDeviceName == null) ? 0 : rootDeviceName.hashCode());
result = prime * result + ((rootDeviceType == null) ? 0 : rootDeviceType.hashCode());
result = prime * result + ((virtualizationType == null) ? 0 : virtualizationType.hashCode());
return result;
}
@ -471,16 +457,13 @@ public class Image implements Comparable<Image> {
@Override
public String toString() {
return "Image [architecture=" + architecture + ", description="
+ description + ", ebsBlockDevices=" + ebsBlockDevices
+ ", imageId=" + imageId + ", imageLocation=" + imageLocation
+ ", imageOwnerId=" + imageOwnerId + ", imageState=" + imageState
+ ", imageType=" + imageType + ", isPublic=" + isPublic
+ ", kernelId=" + kernelId + ", name=" + name + ", platform="
+ platform + ", productCodes=" + productCodes + ", ramdiskId="
+ ramdiskId + ", region=" + region + ", rootDeviceName="
+ rootDeviceName + ", rootDeviceType=" + rootDeviceType
+ ", virtualizationType=" + virtualizationType + "]";
return "Image [architecture=" + architecture + ", description=" + description + ", ebsBlockDevices="
+ ebsBlockDevices + ", imageId=" + imageId + ", imageLocation=" + imageLocation + ", imageOwnerId="
+ imageOwnerId + ", imageState=" + imageState + ", imageType=" + imageType + ", isPublic=" + isPublic
+ ", kernelId=" + kernelId + ", name=" + name + ", platform=" + platform + ", productCodes="
+ productCodes + ", ramdiskId=" + ramdiskId + ", region=" + region + ", rootDeviceName="
+ rootDeviceName + ", rootDeviceType=" + rootDeviceType + ", virtualizationType=" + virtualizationType
+ "]";
}
}

View File

@ -58,7 +58,7 @@ public enum ImageAttribute {
/**
* the mapping that defines native device names to use when exposing virtual devices.
*/
BLOCK_DEVICE_MAPPING;
BLOCK_DEVICE_MAPPING, UNRECOGNIZED;
public String value() {
switch (this) {
case PRODUCT_CODES:
@ -97,7 +97,7 @@ public enum ImageAttribute {
else if ("blockDeviceMapping".equals(attribute))
return BLOCK_DEVICE_MAPPING;
else
throw new IllegalArgumentException("unmapped attribute: " + attribute);
return UNRECOGNIZED;
}
}

View File

@ -62,7 +62,7 @@ public enum InstanceState {
/**
* the instance is stopped
*/
STOPPED;
STOPPED, UNRECOGNIZED;
public String value() {
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()));
@ -74,8 +74,11 @@ public enum InstanceState {
}
public static InstanceState fromValue(String state) {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state,
"state")));
try {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
public static InstanceState fromValue(int v) {
@ -93,7 +96,7 @@ public enum InstanceState {
case 80:
return STOPPED;
default:
throw new IllegalArgumentException("invalid state:" + v);
return UNRECOGNIZED;
}
}
}

View File

@ -27,7 +27,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public enum IpProtocol {
TCP, UDP, ICMP;
TCP, UDP, ICMP, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
@ -39,7 +39,11 @@ public enum IpProtocol {
}
public static IpProtocol fromValue(String protocol) {
return valueOf(checkNotNull(protocol, "protocol").toUpperCase());
try {
return valueOf(checkNotNull(protocol, "protocol").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -35,7 +35,7 @@ import org.jclouds.aws.ec2.services.MonitoringClient;
*/
public enum MonitoringState {
PENDING, ENABLED, DISABLING, DISABLED;
PENDING, ENABLED, DISABLING, DISABLED, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
@ -54,6 +54,10 @@ public enum MonitoringState {
return DISABLED;
if ("true".endsWith(state))
return ENABLED;
return valueOf(checkNotNull(state, "state").toUpperCase());
try {
return valueOf(checkNotNull(state, "state").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -41,7 +41,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class PlacementGroup implements Comparable<PlacementGroup> {
public static enum State {
PENDING, AVAILABLE, DELETING, DELETED;
PENDING, AVAILABLE, DELETING, DELETED, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@ -52,7 +52,11 @@ public class PlacementGroup implements Comparable<PlacementGroup> {
}
public static State fromValue(String state) {
return valueOf(checkNotNull(state, "state").toUpperCase());
try {
return valueOf(checkNotNull(state, "state").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@ -146,8 +150,7 @@ public class PlacementGroup implements Comparable<PlacementGroup> {
@Override
public String toString() {
return "[name=" + name + ", region=" + region + ", state=" + state + ", strategy=" + strategy
+ "]";
return "[name=" + name + ", region=" + region + ", state=" + state + ", strategy=" + strategy + "]";
}
}

View File

@ -31,7 +31,7 @@ public enum RootDeviceType {
INSTANCE_STORE,
EBS;
EBS, UNRECOGNIZED;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
@ -42,6 +42,10 @@ public enum RootDeviceType {
}
public static RootDeviceType fromValue(String v) {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, v));
try {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, v));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -31,7 +31,7 @@ import java.util.Date;
*/
public class Snapshot implements Comparable<Snapshot> {
public static enum Status {
PENDING, COMPLETED, ERROR;
PENDING, COMPLETED, ERROR, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@ -42,7 +42,11 @@ public class Snapshot implements Comparable<Snapshot> {
}
public static Status fromValue(String status) {
return valueOf(checkNotNull(status, "status").toUpperCase());
try {
return valueOf(checkNotNull(status, "status").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@ -57,8 +61,8 @@ public class Snapshot implements Comparable<Snapshot> {
private final String description;
private final String ownerAlias;
public Snapshot(String region, String id, String volumeId, int volumeSize, Status status,
Date startTime, int progress, String ownerId, String description, String ownerAlias) {
public Snapshot(String region, String id, String volumeId, int volumeSize, Status status, Date startTime,
int progress, String ownerId, String description, String ownerAlias) {
this.region = checkNotNull(region, "region");
this.id = id;
this.volumeId = volumeId;
@ -135,8 +139,8 @@ public class Snapshot implements Comparable<Snapshot> {
}
/**
* The AWS identity alias (e.g., "amazon", "redhat", "self", etc.) or AWS identity ID that owns the
* AMI.
* The AWS identity alias (e.g., "amazon", "redhat", "self", etc.) or AWS identity ID that owns
* the AMI.
*/
public String getOwnerAlias() {
return ownerAlias;
@ -217,10 +221,9 @@ public class Snapshot implements Comparable<Snapshot> {
@Override
public String toString() {
return "Snapshot [description=" + description + ", id=" + id + ", ownerAlias=" + ownerAlias
+ ", ownerId=" + ownerId + ", progress=" + progress + ", startTime=" + startTime
+ ", status=" + status + ", volumeId=" + volumeId + ", volumeSize=" + volumeSize
+ "]";
return "Snapshot [description=" + description + ", id=" + id + ", ownerAlias=" + ownerAlias + ", ownerId="
+ ownerId + ", progress=" + progress + ", startTime=" + startTime + ", status=" + status + ", volumeId="
+ volumeId + ", volumeSize=" + volumeSize + "]";
}
@Override

View File

@ -46,7 +46,7 @@ public class Volume implements Comparable<Volume> {
* @author Adrian Cole
*/
public static enum InstanceInitiatedShutdownBehavior {
STOP, TERMINATE;
STOP, TERMINATE, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@ -57,12 +57,16 @@ public class Volume implements Comparable<Volume> {
}
public static InstanceInitiatedShutdownBehavior fromValue(String status) {
return valueOf(checkNotNull(status, "status").toUpperCase());
try {
return valueOf(checkNotNull(status, "status").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static enum Status {
CREATING, AVAILABLE, IN_USE, DELETING;
CREATING, AVAILABLE, IN_USE, DELETING, UNRECOGNIZED;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
}
@ -73,8 +77,11 @@ public class Volume implements Comparable<Volume> {
}
public static Status fromValue(String status) {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(
status, "status")));
try {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(status, "status")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@ -88,9 +95,8 @@ public class Volume implements Comparable<Volume> {
private final Date createTime;
private final Set<Attachment> attachments = Sets.newLinkedHashSet();
public Volume(String region, String id, int size, String snapshotId,
String availabilityZone, Volume.Status status, Date createTime,
Iterable<Attachment> attachments) {
public Volume(String region, String id, int size, String snapshotId, String availabilityZone, Volume.Status status,
Date createTime, Iterable<Attachment> attachments) {
this.region = checkNotNull(region, "region");
this.id = id;
this.size = size;
@ -208,8 +214,8 @@ public class Volume implements Comparable<Volume> {
@Override
public String toString() {
return "Volume [attachments=" + attachments + ", availabilityZone=" + availabilityZone
+ ", createTime=" + createTime + ", id=" + id + ", region=" + region + ", size="
+ size + ", snapshotId=" + snapshotId + ", status=" + status + "]";
return "Volume [attachments=" + attachments + ", availabilityZone=" + availabilityZone + ", createTime="
+ createTime + ", id=" + id + ", region=" + region + ", size=" + size + ", snapshotId=" + snapshotId
+ ", status=" + status + "]";
}
}

View File

@ -61,13 +61,17 @@ import com.google.common.base.CaseFormat;
* "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTrequestPaymentGET.html" />
*/
public enum Payer {
REQUESTER, BUCKET_OWNER;
REQUESTER, BUCKET_OWNER, UNRECOGNIZED;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
}
public static Payer fromValue(String payer) {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, payer));
try {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, payer));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -56,7 +56,7 @@ public class LocationConstraintHandler extends ParseSax.HandlerWithResult<String
return Region.US_WEST_1;
else if (v.equals(Region.AP_SOUTHEAST_1))
return Region.AP_SOUTHEAST_1;
throw new IllegalStateException("unimplemented location: " + v);
return v;
}
public void characters(char ch[], int start, int length) {

View File

@ -217,7 +217,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(image.getOperatingSystem().getArch(), "paravirtual");
assertEquals(image.getOperatingSystem().getDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getOperatingSystem().getFamily(), OsFamily.UNKNOWN);
assertEquals(image.getOperatingSystem().getFamily(), OsFamily.UNRECOGNIZED);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of("owner", "133804938231", "rootDeviceType",
"instance-store"));
assertEquals(image.getVersion(), "5622");

View File

@ -83,7 +83,7 @@ public class RunningInstanceToNodeMetadataTest {
DateService dateService = new SimpleDateFormatDateService();
@SuppressWarnings( { "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testApplyWithEBSWhenBootIsInstanceStoreAndAvailabilityZoneNotFound() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
@ -92,7 +92,7 @@ public class RunningInstanceToNodeMetadataTest {
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
ConcurrentMap<RegionAndName, org.jclouds.compute.domain.Image> imageMap = createMock(ConcurrentMap.class);
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M1_SMALL));
.<Hardware> of(EC2Hardware.M1_SMALL));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
Image image = createMock(Image.class);
@ -104,7 +104,7 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1d", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(instance.getIpAddress()).andReturn("174.129.1.50");
@ -118,21 +118,24 @@ public class RunningInstanceToNodeMetadataTest {
expect(imageMap.get(new RegionAndName(Region.US_EAST_1, "ami-1515f07c"))).andReturn(jcImage);
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("ami-1515f07c"))).andReturn(
(Set) ImmutableSet.<Image> of(image));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
expect(credentialsMap.get(new RegionAndName(Region.US_EAST_1, "jclouds#tag#us-east-1#50"))).andReturn(
new KeyPair(Region.US_EAST_1, "jclouds#tag#us-east-1#50", "keyFingerprint", "pass"));
new KeyPair(Region.US_EAST_1, "jclouds#tag#us-east-1#50", "keyFingerprint", "pass"));
expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce();
expect(instance.getInstanceType()).andReturn(InstanceType.M1_SMALL).atLeastOnce();
expect(instance.getEbsBlockDevices()).andReturn(
ImmutableMap.<String, EbsBlockDevice> of("/dev/sdg", new EbsBlockDevice("vol-1f20d376",
Attachment.Status.ATTACHED, dateService.iso8601DateParse("2009-12-11T16:32:46.000Z"), false),
"/dev/sdj", new EbsBlockDevice("vol-c0eb78aa", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2010-06-17T10:43:28.000Z"), false)));
ImmutableMap.<String, EbsBlockDevice> of(
"/dev/sdg",
new EbsBlockDevice("vol-1f20d376", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2009-12-11T16:32:46.000Z"), false),
"/dev/sdj",
new EbsBlockDevice("vol-c0eb78aa", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2010-06-17T10:43:28.000Z"), false)));
expect(instance.getRootDeviceType()).andReturn(RootDeviceType.INSTANCE_STORE);
expect(instance.getRootDeviceName()).andReturn(null).atLeastOnce();
@ -145,7 +148,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
@ -157,11 +160,11 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(metadata.getHardware().getProviderId(), "m1.small");
assertEquals(metadata.getHardware().getProcessors(), ImmutableList.<Processor> of(new Processor(1.0, 1.0)));
assertEquals(metadata.getHardware().getRam(), 1740);
assertEquals(metadata.getHardware().getVolumes(), ImmutableList.<Volume> of(new VolumeImpl(null,
Volume.Type.LOCAL, 10.0f, "/dev/sda1", true, false),//
new VolumeImpl(null, Volume.Type.LOCAL, 150.0f, "/dev/sda2", false, false),//
new VolumeImpl("vol-1f20d376", Volume.Type.SAN, null, "/dev/sdg", false, true),//
new VolumeImpl("vol-c0eb78aa", Volume.Type.SAN, null, "/dev/sdj", false, true)));
assertEquals(metadata.getHardware().getVolumes(),
ImmutableList.<Volume> of(new VolumeImpl(null, Volume.Type.LOCAL, 10.0f, "/dev/sda1", true, false),//
new VolumeImpl(null, Volume.Type.LOCAL, 150.0f, "/dev/sda2", false, false),//
new VolumeImpl("vol-1f20d376", Volume.Type.SAN, null, "/dev/sdg", false, true),//
new VolumeImpl("vol-c0eb78aa", Volume.Type.SAN, null, "/dev/sdj", false, true)));
assertEquals(metadata.getCredentials(), new Credentials("user", "pass"));
@ -175,16 +178,16 @@ public class RunningInstanceToNodeMetadataTest {
}
@SuppressWarnings( { "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testApplyForEucalyptusWhereNullAvailabilityZoneIpAddressNoGroups() throws UnknownHostException {
public void testApplyForNovaWhereNullAvailabilityZoneIpAddressNoGroups() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
AMIClient amiClient = createMock(AMIClient.class);
expect(client.getAMIServices()).andReturn(amiClient).atLeastOnce();
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
ConcurrentMap<RegionAndName, org.jclouds.compute.domain.Image> imageMap = createMock(ConcurrentMap.class);
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M1_SMALL));
.<Hardware> of(EC2Hardware.M1_SMALL));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
Image image = createMock(Image.class);
@ -196,7 +199,7 @@ public class RunningInstanceToNodeMetadataTest {
Location region = new LocationImpl(LocationScope.REGION, "us-east-1", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(region));
.<Location> of(region));
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(instance.getIpAddress()).andReturn(null);
@ -210,7 +213,7 @@ public class RunningInstanceToNodeMetadataTest {
expect(imageMap.get(new RegionAndName(Region.US_EAST_1, "ami-1515f07c"))).andReturn(jcImage);
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("ami-1515f07c"))).andReturn(
(Set) ImmutableSet.<Image> of(image));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
@ -231,7 +234,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
@ -243,9 +246,9 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(metadata.getHardware().getProviderId(), "m1.small");
assertEquals(metadata.getHardware().getProcessors(), ImmutableList.<Processor> of(new Processor(1.0, 1.0)));
assertEquals(metadata.getHardware().getRam(), 1740);
assertEquals(metadata.getHardware().getVolumes(), ImmutableList.<Volume> of(new VolumeImpl(null,
Volume.Type.LOCAL, 10.0f, "/dev/sda1", true, false),//
new VolumeImpl(null, Volume.Type.LOCAL, 150.0f, "/dev/sda2", false, false)));
assertEquals(metadata.getHardware().getVolumes(),
ImmutableList.<Volume> of(new VolumeImpl(null, Volume.Type.LOCAL, 10.0f, "/dev/sda1", true, false),//
new VolumeImpl(null, Volume.Type.LOCAL, 150.0f, "/dev/sda2", false, false)));
assertEquals(metadata.getCredentials(), new Credentials("user", null));
@ -259,19 +262,19 @@ public class RunningInstanceToNodeMetadataTest {
}
@SuppressWarnings( { "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testApplyForEucalyptusWhereImageNotFound() throws UnknownHostException {
public void testApplyWhereUnknownInstanceType() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
AMIClient amiClient = createMock(AMIClient.class);
expect(client.getAMIServices()).andReturn(amiClient).atLeastOnce();
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
ConcurrentMap<RegionAndName, org.jclouds.compute.domain.Image> imageMap = createMock(ConcurrentMap.class);
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M1_SMALL));
.<Hardware> of(EC2Hardware.M1_SMALL));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
Image image = createMock(Image.class);
expect(instance.getId()).andReturn("i-3d640055").atLeastOnce();
expect(instance.getGroupIds()).andReturn(ImmutableSet.<String> of()).atLeastOnce();
@ -280,7 +283,7 @@ public class RunningInstanceToNodeMetadataTest {
Location region = new LocationImpl(LocationScope.REGION, "us-east-1", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(region));
.<Location> of(region));
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(instance.getIpAddress()).andReturn(null);
@ -294,10 +297,83 @@ public class RunningInstanceToNodeMetadataTest {
expect(imageMap.get(new RegionAndName(Region.US_EAST_1, "ami-1515f07c"))).andReturn(jcImage);
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("ami-1515f07c"))).andReturn(
(Set) ImmutableSet.<Image> of());
expect(credentialProvider.execute(null)).andReturn(new Credentials("root", null));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
expect(credentialsMap.get(new RegionAndName(Region.US_EAST_1, "nebulatanimislam"))).andReturn(null);
expect(instance.getAvailabilityZone()).andReturn(null).atLeastOnce();
expect(instance.getInstanceType()).andReturn("hhttpp").atLeastOnce();
replay(imageMap);
replay(client);
replay(amiClient);
replay(credentialsMap);
replay(credentialProvider);
replay(instance);
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getTag(), "NOTAG-i-3d640055");
assertEquals(metadata.getLocation(), region);
assertEquals(metadata.getImageId(), "us-east-1/ami-1515f07c");
assertEquals(metadata.getHardware(), null);
assertEquals(metadata.getCredentials(), new Credentials("user", null));
verify(imageMap);
verify(jcImage);
verify(client);
verify(amiClient);
verify(credentialsMap);
verify(credentialProvider);
verify(instance);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testApplyForNovaWhereImageNotFound() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
AMIClient amiClient = createMock(AMIClient.class);
expect(client.getAMIServices()).andReturn(amiClient).atLeastOnce();
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
ConcurrentMap<RegionAndName, org.jclouds.compute.domain.Image> imageMap = createMock(ConcurrentMap.class);
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M1_SMALL));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
expect(instance.getId()).andReturn("i-3d640055").atLeastOnce();
expect(instance.getGroupIds()).andReturn(ImmutableSet.<String> of()).atLeastOnce();
expect(instance.getKeyName()).andReturn("nebulatanimislam").atLeastOnce();
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
Location region = new LocationImpl(LocationScope.REGION, "us-east-1", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(region));
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(instance.getIpAddress()).andReturn(null);
expect(instance.getPrivateIpAddress()).andReturn("10.202.117.241");
expect(instance.getRegion()).andReturn(Region.US_EAST_1).atLeastOnce();
expect(jcImage.getOperatingSystem()).andReturn(createMock(OperatingSystem.class)).atLeastOnce();
expect(instance.getImageId()).andReturn("ami-1515f07c").atLeastOnce();
expect(imageMap.get(new RegionAndName(Region.US_EAST_1, "ami-1515f07c"))).andReturn(jcImage);
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("ami-1515f07c"))).andReturn(
(Set) ImmutableSet.<Image> of());
expect(credentialProvider.execute(null)).andReturn(new Credentials("root", null));
expect(credentialsMap.get(new RegionAndName(Region.US_EAST_1, "nebulatanimislam"))).andReturn(null);
@ -316,7 +392,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
@ -328,9 +404,9 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(metadata.getHardware().getProviderId(), "m1.small");
assertEquals(metadata.getHardware().getProcessors(), ImmutableList.<Processor> of(new Processor(1.0, 1.0)));
assertEquals(metadata.getHardware().getRam(), 1740);
assertEquals(metadata.getHardware().getVolumes(), ImmutableList.<Volume> of(new VolumeImpl(null,
Volume.Type.LOCAL, 10.0f, "/dev/sda1", true, false),//
new VolumeImpl(null, Volume.Type.LOCAL, 150.0f, "/dev/sda2", false, false)));
assertEquals(metadata.getHardware().getVolumes(),
ImmutableList.<Volume> of(new VolumeImpl(null, Volume.Type.LOCAL, 10.0f, "/dev/sda1", true, false),//
new VolumeImpl(null, Volume.Type.LOCAL, 150.0f, "/dev/sda2", false, false)));
assertEquals(metadata.getCredentials(), new Credentials("root", null));
@ -357,9 +433,9 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
@ -389,7 +465,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), locations.get().iterator().next());
@ -418,9 +494,9 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
@ -438,7 +514,7 @@ public class RunningInstanceToNodeMetadataTest {
expect(instance.getRegion()).andReturn("us-east-1").atLeastOnce();
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andThrow(new NullPointerException())
.atLeastOnce();
.atLeastOnce();
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
@ -451,7 +527,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), locations.get().iterator().next());
@ -480,9 +556,9 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
@ -517,7 +593,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), locations.get().iterator().next());
@ -547,9 +623,9 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
@ -580,7 +656,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), locations.get().iterator().next());
@ -608,9 +684,9 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
@ -641,7 +717,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), locations.get().iterator().next());
@ -658,7 +734,7 @@ public class RunningInstanceToNodeMetadataTest {
verify(instance);
}
@SuppressWarnings( { "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testApplyWithKeyPairCreatesTagOfParsedSecurityGroupAndCredentialsBasedOnIt() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
@ -667,7 +743,7 @@ public class RunningInstanceToNodeMetadataTest {
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
ConcurrentMap<RegionAndName, org.jclouds.compute.domain.Image> imageMap = createMock(ConcurrentMap.class);
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
Image image = createMock(Image.class);
@ -679,7 +755,7 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(instance.getIpAddress()).andReturn("127.0.0.1");
@ -693,12 +769,12 @@ public class RunningInstanceToNodeMetadataTest {
expect(imageMap.get(new RegionAndName(Region.US_EAST_1, "imageId"))).andReturn(jcImage);
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
(Set) ImmutableSet.<Image> of(image));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
expect(credentialsMap.get(new RegionAndName(Region.US_EAST_1, "jclouds#tag#us-east-1#50"))).andReturn(
new KeyPair(Region.US_EAST_1, "jclouds#tag#us-east-1#50", "keyFingerprint", "pass"));
new KeyPair(Region.US_EAST_1, "jclouds#tag#us-east-1#50", "keyFingerprint", "pass"));
expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce();
@ -713,7 +789,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getTag(), "tag");
@ -732,7 +808,7 @@ public class RunningInstanceToNodeMetadataTest {
}
@SuppressWarnings( { "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testApplyWithTwoSecurityGroups() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
@ -741,7 +817,7 @@ public class RunningInstanceToNodeMetadataTest {
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
ConcurrentMap<RegionAndName, org.jclouds.compute.domain.Image> imageMap = createMock(ConcurrentMap.class);
Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(EC2Hardware.M2_4XLARGE));
.<Hardware> of(EC2Hardware.M2_4XLARGE));
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class);
Image image = createMock(Image.class);
@ -753,7 +829,7 @@ public class RunningInstanceToNodeMetadataTest {
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(location));
.<Location> of(location));
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(instance.getIpAddress()).andReturn("127.0.0.1");
@ -767,12 +843,12 @@ public class RunningInstanceToNodeMetadataTest {
expect(imageMap.get(new RegionAndName(Region.US_EAST_1, "imageId"))).andReturn(jcImage);
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
(Set) ImmutableSet.<Image> of(image));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
expect(credentialsMap.get(new RegionAndName(Region.US_EAST_1, "jclouds#tag#us-east-1#50"))).andReturn(
new KeyPair(Region.US_EAST_1, "jclouds#tag#us-east-1#50", "keyFingerprint", "pass"));
new KeyPair(Region.US_EAST_1, "jclouds#tag#us-east-1#50", "keyFingerprint", "pass"));
expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce();
@ -787,7 +863,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, imageMap, locations, hardwares);
credentialProvider, imageMap, locations, hardwares);
NodeMetadata metadata = parser.apply(instance);

View File

@ -27,7 +27,7 @@ import com.google.common.base.CaseFormat;
* @author Adrian Cole
*/
public enum BlobType {
BLOCK_BLOB, PAGE_BLOB;
BLOCK_BLOB, PAGE_BLOB, UNRECOGNIZED;
public String value() {
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
@ -39,7 +39,10 @@ public enum BlobType {
}
public static BlobType fromValue(String type) {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type,
"type")));
try {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -27,7 +27,7 @@ import com.google.common.base.CaseFormat;
* @author Adrian Cole
*/
public enum LeaseStatus {
LOCKED, UNLOCKED;
LOCKED, UNLOCKED, UNRECOGNIZED;
public String value() {
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
@ -39,7 +39,10 @@ public enum LeaseStatus {
}
public static LeaseStatus fromValue(String type) {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type,
"type")));
try {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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))))))

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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 + "]";
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 + "]";
}
}

View File

@ -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;
}
}

View File

@ -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 + "]";
}
}

View File

@ -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;
}
}

View File

@ -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 + "]";
}
}

View File

@ -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 + "]";
}
}

View File

@ -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 + "]";
}
}

View File

@ -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;
}
}

View File

@ -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 + "]";
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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()));
}
}

View File

@ -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;
}
}

View File

@ -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 + ")";
}
};
}
}

View File

@ -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";
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

Some files were not shown because too many files have changed in this diff Show More