mirror of https://github.com/apache/jclouds.git
Issue 191, Issue 273 refactored opscode api calls into a separate module
This commit is contained in:
parent
551a3639b5
commit
18e9294b89
|
@ -0,0 +1,92 @@
|
|||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,9 +60,14 @@
|
|||
</repositories>
|
||||
|
||||
<properties>
|
||||
<jclouds.test.user>user</jclouds.test.user>
|
||||
<jclouds.test.key>key</jclouds.test.key>
|
||||
<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.user>${jclouds.chef.identity}</jclouds.test.user>
|
||||
<jclouds.test.key>${jclouds.chef.rsa-key}</jclouds.test.key>
|
||||
<jclouds.test.endpoint>${jclouds.chef.endpoint}</jclouds.test.endpoint>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
|
|
|
@ -37,24 +37,15 @@ import javax.ws.rs.core.MediaType;
|
|||
|
||||
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
|
||||
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
|
||||
import org.jclouds.chef.domain.Organization;
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuth;
|
||||
import org.jclouds.chef.functions.OrganizationName;
|
||||
import org.jclouds.chef.functions.ParseKeyFromJson;
|
||||
import org.jclouds.chef.functions.ParseKeySetFromJson;
|
||||
import org.jclouds.chef.functions.ParseOrganizationFromJson;
|
||||
import org.jclouds.chef.functions.ParseUserFromJson;
|
||||
import org.jclouds.chef.functions.Username;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Endpoint;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
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;
|
||||
|
@ -72,116 +63,52 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface ChefAsyncClient {
|
||||
/**
|
||||
* @see ChefClient#createClientInOrganization
|
||||
* @see ChefCookbooks#listCookbooks
|
||||
*/
|
||||
@GET
|
||||
@Path("cookbooks")
|
||||
ListenableFuture<String> listCookbooks();
|
||||
|
||||
/**
|
||||
* @see ChefClient#createClientanization
|
||||
*/
|
||||
@POST
|
||||
@Path("/organizations/{orgname}/clients")
|
||||
@Path("clients")
|
||||
@ResponseParser(ParseKeyFromJson.class)
|
||||
ListenableFuture<String> createClientInOrg(@PathParam("orgname") String orgname,
|
||||
ListenableFuture<String> createClient(
|
||||
@BinderParam(BindClientnameToJsonPayload.class) String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#generateKeyForClientInOrg
|
||||
* @see ChefClient#generateKeyForClient
|
||||
*/
|
||||
@PUT
|
||||
@Path("/organizations/{orgname}/clients/{clientname}")
|
||||
@Path("clients/{clientname}")
|
||||
@ResponseParser(ParseKeyFromJson.class)
|
||||
ListenableFuture<String> generateKeyForClientInOrg(
|
||||
@PathParam("orgname") String orgname,
|
||||
ListenableFuture<String> generateKeyForClient(
|
||||
@PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#clientExistsInOrg
|
||||
* @see ChefClient#clientExists
|
||||
*/
|
||||
@HEAD
|
||||
@Path("/organizations/{orgname}/clients/{clientname}")
|
||||
@Path("clients/{clientname}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> clientExistsInOrg(@PathParam("orgname") String orgname,
|
||||
@PathParam("clientname") String clientname);
|
||||
ListenableFuture<Boolean> clientExists(@PathParam("clientname") String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteClientInOrg
|
||||
* @see ChefClient#deleteClient
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/organizations/{orgname}/clients/{clientname}")
|
||||
@Path("clients/{clientname}")
|
||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> deleteClientInOrg(@PathParam("orgname") String orgname,
|
||||
@PathParam("clientname") String clientname);
|
||||
ListenableFuture<Void> deleteClient(@PathParam("clientname") String clientname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createClientInOrganization
|
||||
* @see ChefClient#listClients
|
||||
*/
|
||||
@GET
|
||||
@Path("/organizations/{orgname}/clients")
|
||||
@Path("clients")
|
||||
@ResponseParser(ParseKeySetFromJson.class)
|
||||
ListenableFuture<Set<String>> listClientsInOrg(@PathParam("orgname") String orgname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createUser
|
||||
*/
|
||||
@POST
|
||||
@Path("/users")
|
||||
@ResponseParser(ParseKeyFromJson.class)
|
||||
ListenableFuture<String> createUser(@BinderParam(BindToJsonPayload.class) User user);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateUser
|
||||
*/
|
||||
@PUT
|
||||
@Path("/users/{username}")
|
||||
@ResponseParser(ParseUserFromJson.class)
|
||||
ListenableFuture<User> updateUser(
|
||||
@PathParam("username") @ParamParser(Username.class) @BinderParam(BindToJsonPayload.class) User user);
|
||||
|
||||
/**
|
||||
* @see ChefClient#getUser
|
||||
*/
|
||||
@GET
|
||||
@Path("/users/{username}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ResponseParser(ParseUserFromJson.class)
|
||||
ListenableFuture<User> getUser(@PathParam("username") String username);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteUser
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/users/{username}")
|
||||
@ResponseParser(ParseUserFromJson.class)
|
||||
ListenableFuture<User> deleteUser(@PathParam("username") String username);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createOrg
|
||||
*/
|
||||
@POST
|
||||
@Path("/organizations")
|
||||
@ResponseParser(ParseKeyFromJson.class)
|
||||
ListenableFuture<String> createOrg(@BinderParam(BindToJsonPayload.class) Organization org);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateOrg
|
||||
*/
|
||||
@PUT
|
||||
@Path("/organizations/{orgname}")
|
||||
@ResponseParser(ParseOrganizationFromJson.class)
|
||||
ListenableFuture<Organization> updateOrg(
|
||||
@PathParam("orgname") @ParamParser(OrganizationName.class) @BinderParam(BindToJsonPayload.class) Organization org);
|
||||
|
||||
/**
|
||||
* @see ChefClient#getOrg
|
||||
*/
|
||||
@GET
|
||||
@Path("/organizations/{orgname}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ResponseParser(ParseOrganizationFromJson.class)
|
||||
ListenableFuture<Organization> getOrg(@PathParam("orgname") String orgname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteOrg
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/organizations/{orgname}")
|
||||
@ResponseParser(ParseOrganizationFromJson.class)
|
||||
ListenableFuture<Organization> deleteOrg(@PathParam("orgname") String orgname);
|
||||
ListenableFuture<Set<String>> listClients();
|
||||
|
||||
}
|
||||
|
|
|
@ -44,12 +44,9 @@ package org.jclouds.chef;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.chef.domain.Organization;
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Chef.
|
||||
|
@ -61,6 +58,7 @@ import org.jclouds.rest.ResourceNotFoundException;
|
|||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface ChefClient {
|
||||
String listCookbooks();
|
||||
|
||||
/**
|
||||
* creates a new client
|
||||
|
@ -75,110 +73,16 @@ public interface ChefClient {
|
|||
* @throws HttpResponseException
|
||||
* "409 Conflict" if the client already exists
|
||||
*/
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
String createClientInOrg(String orgname, String name);
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
String createClient(String name);
|
||||
|
||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||
String generateKeyForClientInOrg(String orgname, String name);
|
||||
String generateKeyForClient(String name);
|
||||
|
||||
Set<String> listClientsInOrg(String orgname);
|
||||
Set<String> listClients();
|
||||
|
||||
boolean clientExistsInOrg(String orgname, String name);
|
||||
boolean clientExists(String name);
|
||||
|
||||
void deleteClientInOrg(String orgname, String name);
|
||||
void deleteClient(String name);
|
||||
|
||||
/**
|
||||
* creates a new user
|
||||
*
|
||||
* @return the private key of the user. You can then use this user 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 user.
|
||||
*/
|
||||
String createUser(User user);
|
||||
|
||||
/**
|
||||
* updates an existing user. Note: you must have update rights on the user.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized user.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Update rights on the user.
|
||||
* @throws ResourceNotFoundException
|
||||
* if the user does not exist.
|
||||
*/
|
||||
User updateUser(User user);
|
||||
|
||||
/**
|
||||
* retrieves an existing user. Note: you must have update rights on the user.
|
||||
*
|
||||
* @return null, if the user is not found
|
||||
*/
|
||||
User getUser(String username);
|
||||
|
||||
/**
|
||||
* deletes an existing user. Note: you must have delete rights on the user.
|
||||
*
|
||||
* @return the last state of the User object in question. * @throws AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized user.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Delete rights on the user.
|
||||
* @throws ResourceNotFoundException
|
||||
* <p/>
|
||||
* “404 Not Found” if the user does not exist.
|
||||
*/
|
||||
User deleteUser(String username);
|
||||
|
||||
/**
|
||||
* creates a new organization
|
||||
*
|
||||
* @return the private key of the organization. You can then use this organization name and
|
||||
* private key to access the Opscode API.
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized organization.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to create a organization.
|
||||
*/
|
||||
String createOrg(Organization organization);
|
||||
|
||||
/**
|
||||
* updates an existing organization. Note: you must have update rights on the organization.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized organization.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Update rights on the organization.
|
||||
* @throws ResourceNotFoundException
|
||||
* if the organization does not exist.
|
||||
*/
|
||||
Organization updateOrg(Organization organization);
|
||||
|
||||
/**
|
||||
* retrieves an existing organization. Note: you must have update rights on the organization.
|
||||
*
|
||||
* @return null, if the organization is not found
|
||||
*/
|
||||
Organization getOrg(String organizationname);
|
||||
|
||||
/**
|
||||
* deletes an existing organization. Note: you must have delete rights on the organization.
|
||||
*
|
||||
* @return the last state of the Organization object in question. * @throws
|
||||
* AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized organization.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Delete rights on the organization.
|
||||
* @throws ResourceNotFoundException
|
||||
* <p/>
|
||||
* “404 Not Found” if the organization does not exist.
|
||||
*/
|
||||
Organization deleteOrg(String organizationname);
|
||||
}
|
||||
|
|
|
@ -28,16 +28,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.rest.RestContextBuilder;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
|
||||
import org.jclouds.chef.config.ChefContextModule;
|
||||
import org.jclouds.chef.config.ChefRestClientModule;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.rest.RestContextBuilder;
|
||||
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -46,9 +42,7 @@ import com.google.inject.TypeLiteral;
|
|||
public class ChefContextBuilder extends RestContextBuilder<ChefAsyncClient, ChefClient> {
|
||||
|
||||
public ChefContextBuilder(String providerName, Properties props) {
|
||||
super(providerName, new TypeLiteral<ChefAsyncClient>() {
|
||||
}, new TypeLiteral<ChefClient>() {
|
||||
}, props);
|
||||
super(providerName, ChefClient.class, ChefAsyncClient.class, props);
|
||||
checkNotNull(properties.getProperty(ChefConstants.PROPERTY_CHEF_IDENTITY));
|
||||
checkNotNull(properties.getProperty(ChefConstants.PROPERTY_CHEF_RSA_KEY));
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ import org.jclouds.rest.RestContext;
|
|||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Creates {@link RestContext} for {@link ChefClient} instances based on the most commonly
|
||||
* requested arguments.
|
||||
* Creates {@link RestContext} for {@link ChefClient} 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/>
|
||||
|
@ -49,19 +49,20 @@ import com.google.inject.Module;
|
|||
*/
|
||||
public class ChefContextFactory {
|
||||
|
||||
public static RestContext<ChefAsyncClient, ChefClient> createContext(String identity, String rsaKey,
|
||||
Module... modules) {
|
||||
public static RestContext<ChefAsyncClient, ChefClient> createContext(String identity,
|
||||
String rsaKey, Module... modules) {
|
||||
return new ChefContextBuilder("chef", new ChefPropertiesBuilder(identity, rsaKey).build())
|
||||
.withModules(modules).buildContext();
|
||||
}
|
||||
|
||||
public static RestContext<ChefAsyncClient, ChefClient> createContext(URI endpoint, String identity, String rsaKey,
|
||||
Module... modules) {
|
||||
return new ChefContextBuilder("chef", new ChefPropertiesBuilder(identity, rsaKey).withEndpoint(endpoint).build())
|
||||
.withModules(modules).buildContext();
|
||||
public static RestContext<ChefAsyncClient, ChefClient> createContext(URI endpoint,
|
||||
String identity, String rsaKey, Module... modules) {
|
||||
return new ChefContextBuilder("chef", new ChefPropertiesBuilder(identity, rsaKey)
|
||||
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
|
||||
}
|
||||
|
||||
public static RestContext<ChefAsyncClient, ChefClient> createContext(Properties properties, Module... modules) {
|
||||
public static RestContext<ChefAsyncClient, ChefClient> createContext(Properties properties,
|
||||
Module... modules) {
|
||||
return new ChefContextBuilder("chef", new ChefPropertiesBuilder(properties).build())
|
||||
.withModules(modules).buildContext();
|
||||
}
|
||||
|
|
|
@ -25,26 +25,22 @@ package org.jclouds.chef;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_ENDPOINT;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_RSA_KEY;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_TIMESTAMP_INTERVAL;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_IDENTITY;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.PropertiesBuilder;
|
||||
import org.jclouds.chef.internal.BaseChefPropertiesBuilder;
|
||||
|
||||
/**
|
||||
* Builds properties used in Chef Clients
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ChefPropertiesBuilder extends PropertiesBuilder {
|
||||
public class ChefPropertiesBuilder extends BaseChefPropertiesBuilder {
|
||||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_CHEF_ENDPOINT, "https://api.opscode.com");
|
||||
properties.setProperty(PROPERTY_CHEF_TIMESTAMP_INTERVAL, "1");
|
||||
properties.setProperty(PROPERTY_CHEF_ENDPOINT, "http://localhost:4000");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -53,14 +49,11 @@ public class ChefPropertiesBuilder extends PropertiesBuilder {
|
|||
}
|
||||
|
||||
public ChefPropertiesBuilder(String identity, String rsaKey) {
|
||||
super();
|
||||
withCredentials(identity, rsaKey);
|
||||
super(URI.create("http://localhost:4000"), identity, rsaKey);
|
||||
}
|
||||
|
||||
public ChefPropertiesBuilder withCredentials(String identity, String rsaKey) {
|
||||
properties.setProperty(PROPERTY_CHEF_IDENTITY, checkNotNull(identity, "identity"));
|
||||
properties.setProperty(PROPERTY_CHEF_RSA_KEY, checkNotNull(rsaKey, "password"));
|
||||
return this;
|
||||
public ChefPropertiesBuilder(URI endpoint, String identity, String rsaKey) {
|
||||
super(endpoint, identity, rsaKey);
|
||||
}
|
||||
|
||||
public ChefPropertiesBuilder withEndpoint(URI endpoint) {
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* Copyright (C) 2009 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 org.jclouds.chef.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMReader;
|
||||
import org.jclouds.chef.handlers.ChefErrorHandler;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.concurrent.ExpirableSupplier;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
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.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Chef connection.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
public class BaseChefRestClientModule<A, S> extends RestClientModule<A, S> {
|
||||
|
||||
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(ChefConstants.PROPERTY_CHEF_TIMESTAMP_INTERVAL) long seconds,
|
||||
final DateService dateService) {
|
||||
return new ExpirableSupplier<String>(new Supplier<String>() {
|
||||
public String get() {
|
||||
return dateService.iso8601SecondsDateFormat();
|
||||
}
|
||||
}, seconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public PrivateKey provideKey(@Named(ChefConstants.PROPERTY_CHEF_RSA_KEY) String key)
|
||||
throws IOException {
|
||||
// TODO do this without adding a provider
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
KeyPair pair = KeyPair.class.cast(new PEMReader(new StringReader(key)).readObject());
|
||||
return pair.getPrivate();
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
|
@ -41,38 +41,18 @@
|
|||
*/
|
||||
package org.jclouds.chef.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.URI;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMReader;
|
||||
import org.jclouds.chef.Chef;
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.handlers.ChefErrorHandler;
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.concurrent.ExpirableSupplier;
|
||||
import org.jclouds.concurrent.internal.SyncProxy;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
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.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.RestClientFactory;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
|
@ -82,56 +62,10 @@ import com.google.inject.Provides;
|
|||
*/
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
public class ChefRestClientModule extends AbstractModule {
|
||||
public class ChefRestClientModule extends BaseChefRestClientModule<ChefAsyncClient, ChefClient> {
|
||||
|
||||
@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(ChefConstants.PROPERTY_CHEF_TIMESTAMP_INTERVAL) long seconds,
|
||||
final DateService dateService) {
|
||||
return new ExpirableSupplier<String>(new Supplier<String>() {
|
||||
public String get() {
|
||||
return dateService.iso8601SecondsDateFormat();
|
||||
}
|
||||
}, seconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindErrorHandlers();
|
||||
bindRetryHandlers();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public PrivateKey provideKey(@Named(ChefConstants.PROPERTY_CHEF_RSA_KEY) String key)
|
||||
throws IOException {
|
||||
// TODO do this without adding a provider
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
KeyPair pair = KeyPair.class.cast(new PEMReader(new StringReader(key)).readObject());
|
||||
return pair.getPrivate();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected ChefAsyncClient provideClient(RestClientFactory factory) {
|
||||
return factory.create(ChefAsyncClient.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ChefClient provideClient(ChefAsyncClient provider) throws IllegalArgumentException,
|
||||
SecurityException, NoSuchMethodException {
|
||||
return SyncProxy.create(ChefClient.class, provider);
|
||||
public ChefRestClientModule() {
|
||||
super(ChefClient.class, ChefAsyncClient.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -141,17 +75,4 @@ public class ChefRestClientModule extends AbstractModule {
|
|||
return URI.create(endpoint);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected void bindRetryHandlers() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.chef.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_IDENTITY;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_RSA_KEY;
|
||||
import static org.jclouds.chef.reference.ChefConstants.PROPERTY_CHEF_TIMESTAMP_INTERVAL;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.PropertiesBuilder;
|
||||
|
||||
/**
|
||||
* 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_CHEF_TIMESTAMP_INTERVAL, "1");
|
||||
return properties;
|
||||
}
|
||||
|
||||
public BaseChefPropertiesBuilder(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public BaseChefPropertiesBuilder(URI endpoint, String identity, String rsaKey) {
|
||||
super();
|
||||
withCredentials(identity, rsaKey);
|
||||
withEndpoint(endpoint);
|
||||
}
|
||||
|
||||
public BaseChefPropertiesBuilder withCredentials(String identity, String rsaKey) {
|
||||
properties.setProperty(PROPERTY_CHEF_IDENTITY, checkNotNull(identity, "identity"));
|
||||
properties.setProperty(PROPERTY_CHEF_RSA_KEY, checkNotNull(rsaKey, "password"));
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -27,24 +27,18 @@ import static org.testng.Assert.assertEquals;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.config.ChefRestClientModule;
|
||||
import org.jclouds.chef.domain.Organization;
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuth;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuthTest;
|
||||
import org.jclouds.chef.functions.ParseKeyFromJson;
|
||||
import org.jclouds.chef.functions.ParseKeySetFromJson;
|
||||
import org.jclouds.chef.functions.ParseOrganizationFromJson;
|
||||
import org.jclouds.chef.functions.ParseUserFromJson;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.functions.CloseContentAndReturn;
|
||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.rest.RestClientTest;
|
||||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||
|
@ -52,7 +46,6 @@ import org.jclouds.util.Jsr330;
|
|||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
|
@ -63,13 +56,10 @@ import com.google.inject.TypeLiteral;
|
|||
*/
|
||||
@Test(groups = "unit", testName = "chef.ChefAsyncClientTest")
|
||||
public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||
public void testClientExistsInOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("clientExistsInOrg", String.class,
|
||||
String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "org",
|
||||
"client");
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"HEAD https://api.opscode.com/organizations/org/clients/client HTTP/1.1");
|
||||
public void testClientExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("clientExists", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/clients/client HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
|
@ -81,13 +71,10 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
|
||||
}
|
||||
|
||||
public void testDeleteClientInOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteClientInOrg", String.class,
|
||||
String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "org",
|
||||
"client");
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"DELETE https://api.opscode.com/organizations/org/clients/client HTTP/1.1");
|
||||
public void testDeleteClient() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteClient", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/clients/client HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
|
@ -99,14 +86,11 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
|
||||
}
|
||||
|
||||
public void testGenerateKeyForClientInOrg() throws SecurityException, NoSuchMethodException,
|
||||
public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("generateKeyForClientInOrg", String.class,
|
||||
String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "org",
|
||||
"client");
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"PUT https://api.opscode.com/organizations/org/clients/client HTTP/1.1");
|
||||
Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 44\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\", \"private_key\": true}");
|
||||
|
@ -119,14 +103,11 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
|
||||
}
|
||||
|
||||
public void testCreateClientInOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createClientInOrg", String.class,
|
||||
String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "org",
|
||||
"client");
|
||||
public void testCreateClient() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createClient", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"POST https://api.opscode.com/organizations/org/clients HTTP/1.1");
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/clients HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 23\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\"}");
|
||||
|
@ -139,12 +120,11 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
|
||||
}
|
||||
|
||||
public void testListClientsInOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listClientsInOrg", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "org");
|
||||
public void testListClients() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("listClients");
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"GET https://api.opscode.com/organizations/org/clients HTTP/1.1");
|
||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/clients HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
|
@ -156,183 +136,6 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
|
||||
}
|
||||
|
||||
public void testCreateUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createUser", User.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new User(
|
||||
"myuser"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST https://api.opscode.com/users HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 21\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"username\":\"myuser\"}");
|
||||
|
||||
// now make sure request filters apply by replaying
|
||||
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
|
||||
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST https://api.opscode.com/users HTTP/1.1");
|
||||
assertHeadersEqual(
|
||||
httpRequest,
|
||||
new StringBuilder("Accept: application/json")
|
||||
.append("\n")
|
||||
.append("Content-Length: 21")
|
||||
.append("\n")
|
||||
.append("Content-Type: application/json")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-1: kfrkDpfgNU26k70R1vl1bEWk0Q0f9Fs/3kxOX7gHd7iNoJq03u7RrcrAOSgL")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-2: ETj5JNeCk18BmFkHMAbCA9hXVo1T4rlHCpbuzAzFlFxUGAT4wj8UoO7V886X")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-3: Kf8DvihP6ElthCNuu1xuhN0B4GEmWC9+ut7UMLe0L2T34VzkbCtuInGbf42/")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-4: G7iu94/xFOT1gN9cex4pNyTnRCHzob4JVU1usxt/2g5grN2SyYwRS5+4MNLN")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-5: WY/iLUPb/9dwtiIQsnUOXqDrs28zNswZulQW4AzYRd7MczJVKU4y4+4XRcB4")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-6: 2+BFLT5o6P6G0D+eCu3zSuaqEJRucPJPaDGWdKIMag==")
|
||||
.append("\n").append("X-Ops-Content-Hash: yLHOxvgIEtNw5UrZDxslOeMw1gw=")
|
||||
.append("\n").append("X-Ops-Sign: version=1.0").append("\n").append(
|
||||
"X-Ops-Timestamp: timestamp").append("\n").append(
|
||||
"X-Ops-Userid: user").append("\n").toString());
|
||||
assertPayloadEquals(httpRequest, "{\"username\":\"myuser\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("updateUser", User.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new User(
|
||||
"myuser"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT https://api.opscode.com/users/myuser HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 21\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"username\":\"myuser\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseUserFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGetUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("getUser", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "myuser");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET https://api.opscode.com/users/myuser HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseUserFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteUser", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "myuser");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "DELETE https://api.opscode.com/users/myuser HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseUserFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("createOrg", Organization.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
new Organization("myorganization"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST https://api.opscode.com/organizations HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 25\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"myorganization\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("updateOrg", Organization.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
new Organization("myorganization"));
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"PUT https://api.opscode.com/organizations/myorganization HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 25\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"myorganization\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseOrganizationFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGetOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("getOrg", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
"myorganization");
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"GET https://api.opscode.com/organizations/myorganization HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseOrganizationFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ChefAsyncClient.class.getMethod("deleteOrg", String.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
"myorganization");
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"DELETE https://api.opscode.com/organizations/myorganization HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseOrganizationFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkFilters(GeneratedHttpRequest<ChefAsyncClient> httpRequest) {
|
||||
assertEquals(httpRequest.getFilters().size(), 1);
|
||||
|
@ -350,9 +153,10 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
return new ChefRestClientModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
Jsr330.bindProperties(binder(), new ChefPropertiesBuilder(new Properties())
|
||||
.withCredentials("user", SignedHeaderAuthTest.PRIVATE_KEY).build());
|
||||
Jsr330.bindProperties(binder(), new ChefPropertiesBuilder("chef-validator",
|
||||
SignedHeaderAuthTest.PRIVATE_KEY).build());
|
||||
install(new NullLoggingModule());
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,11 +28,10 @@ import static org.testng.Assert.assertNotNull;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
@ -52,102 +51,65 @@ public class ChefClientLiveTest {
|
|||
private RestContext<ChefAsyncClient, ChefClient> validatorConnection;
|
||||
private RestContext<ChefAsyncClient, ChefClient> clientConnection;
|
||||
|
||||
private String orgname;
|
||||
private String clientKey;
|
||||
private String endpoint;
|
||||
private String validator;
|
||||
|
||||
public static final String PREFIX = System.getProperty("user.name") + "-jcloudstest";
|
||||
|
||||
@BeforeClass(groups = { "live" })
|
||||
public void setupClient() throws IOException {
|
||||
orgname = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||
endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint");
|
||||
validator = System.getProperty("jclouds.test.user");
|
||||
if (validator == null || validator.equals(""))
|
||||
validator = "chef-validator";
|
||||
String keyfile = System.getProperty("jclouds.test.key");
|
||||
if (keyfile == null || keyfile.equals(""))
|
||||
keyfile = System.getProperty("user.home") + "/chef/validation.pem";
|
||||
validatorConnection = createConnection(orgname + "-validator", Files.toString(new File(
|
||||
keyfile), Charsets.UTF_8));
|
||||
keyfile = "/etc/chef/validation.pem";
|
||||
validatorConnection = createConnection(validator, Files.toString(new File(keyfile),
|
||||
Charsets.UTF_8));
|
||||
}
|
||||
|
||||
private RestContext<ChefAsyncClient, ChefClient> createConnection(String identity, String key)
|
||||
throws IOException {
|
||||
return ChefContextFactory.createContext(identity, key, new Log4JLoggingModule());
|
||||
return ChefContextFactory.createContext(URI.create(endpoint), identity, key,
|
||||
new Log4JLoggingModule());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListClientsInOrg() throws Exception {
|
||||
Set<String> clients = validatorConnection.getApi().listClientsInOrg(orgname);
|
||||
public void testListClients() throws Exception {
|
||||
Set<String> clients = validatorConnection.getApi().listClients();
|
||||
assertNotNull(clients);
|
||||
assert clients.contains(orgname + "-validator");
|
||||
assert clients.contains(validator) : "validator: " + validator + " not in: " + clients;
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testListClientsInOrg")
|
||||
public void testCreateClientInOrg() throws Exception {
|
||||
validatorConnection.getApi().deleteClientInOrg(orgname, PREFIX);
|
||||
clientKey = validatorConnection.getApi().createClientInOrg(orgname, PREFIX);
|
||||
@Test(dependsOnMethods = "testListClients")
|
||||
public void testCreateClient() throws Exception {
|
||||
validatorConnection.getApi().deleteClient(PREFIX);
|
||||
clientKey = validatorConnection.getApi().createClient(PREFIX);
|
||||
assertNotNull(clientKey);
|
||||
System.out.println(clientKey);
|
||||
clientConnection = createConnection(PREFIX, clientKey);
|
||||
clientConnection.getApi().clientExistsInOrg(orgname, PREFIX);
|
||||
clientConnection.getApi().clientExists(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClientInOrg")
|
||||
public void testGenerateKeyForClientInOrg() throws Exception {
|
||||
clientKey = validatorConnection.getApi().generateKeyForClientInOrg(orgname, PREFIX);
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testGenerateKeyForClient() throws Exception {
|
||||
clientKey = validatorConnection.getApi().generateKeyForClient(PREFIX);
|
||||
assertNotNull(clientKey);
|
||||
clientConnection.close();
|
||||
clientConnection = createConnection(PREFIX, clientKey);
|
||||
clientConnection.getApi().clientExistsInOrg(orgname, PREFIX);
|
||||
clientConnection.getApi().clientExists(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClientInOrg")
|
||||
public void testClientExistsInOrg() throws Exception {
|
||||
assertNotNull(validatorConnection.getApi().clientExistsInOrg(orgname, PREFIX));
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testClientExists() throws Exception {
|
||||
assertNotNull(validatorConnection.getApi().clientExists(PREFIX));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testGetOrgFailsForValidationKey() throws Exception {
|
||||
validatorConnection.getApi().getOrg(orgname);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testGenerateKeyForClientInOrg", expectedExceptions = AuthorizationException.class)
|
||||
public void testGetOrgFailsForClient() throws Exception {
|
||||
clientConnection.getApi().getOrg(orgname);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testGetUser() throws Exception {
|
||||
User user = validatorConnection.getApi().getUser(orgname);
|
||||
assertNotNull(user);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testCreateUser() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testUpdateUser() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testDeleteUser() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testCreateOrg() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testUpdateOrg() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testDeleteOrg() throws Exception {
|
||||
// TODO
|
||||
|
||||
@Test(dependsOnMethods = "testGenerateKeyForClient")
|
||||
public void testListCookbooks() throws Exception {
|
||||
System.err.println(clientConnection.getApi().listCookbooks());
|
||||
}
|
||||
|
||||
@AfterClass(groups = { "live" })
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.jclouds.chef.filters;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
||||
import static org.easymock.classextension.EasyMock.createMock;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -37,18 +38,17 @@ import java.security.Security;
|
|||
import javax.inject.Provider;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMReader;
|
||||
import org.jboss.resteasy.specimpl.UriBuilderImpl;
|
||||
import org.jclouds.chef.ChefPropertiesBuilder;
|
||||
import org.jclouds.chef.config.ChefRestClientModule;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.config.ParserModule;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
import org.jclouds.http.internal.SignatureWire;
|
||||
import org.jclouds.rest.config.RestModule;
|
||||
import org.jclouds.util.Jsr330;
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
@ -200,9 +200,9 @@ public class SignedHeaderAuthTest {
|
|||
private SignedHeaderAuth signing_obj;
|
||||
private EncryptionService encryptionService;
|
||||
|
||||
@Test
|
||||
@Test(enabled = false)
|
||||
void canParseKeyFromCreateClient() throws IOException {
|
||||
String key = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA50Iwgq8OIfm5vY9Gwfb6UBt17D7V4djyFSLJ1AbCU/o8Zlrr\nW73JqaK5dC3IO6Dcu+/qPYGtBUWvhFAXrsFOooz0mTod/LtBN1YVurJ60goJrR6w\nKhUYC9H45OW/qcdIM7kdDwiyMZfbHqW6fo0xPqjvgxtZoI+v7pgThacOG6pw7PO6\nGgnJa3MGK3xEbzlI6+EBJWG3EiwexguwOpTD4a4TDIAqKrlVDPeUpU7rFbsBPRS8\nkypR3lU58+WRz/zi9fiH/Sy2X+S3yZg14HiutJjxc8zJsazF3eDxyLGPQmhv3Mso\nA0wbjGusbe6hPdDkzh/B2KO9u96QCdlGu/rc6QIDAQABAoIBAA/7OgD9+fsNF/Hq\nodgrqja4/xg5a2x1Ip2lTs9RPEKza1Mje1pWrkYD0c8ejtTYFAkE1mozuPJBU5TQ\nOCLChx2iohCovIPHqQUa9Nt3FBfJy8tj8Ian+IZwl0OyQOGJvQqeA00Tq8TTmrfu\negne1gVfhVXJIROAeocBiW/WEJqGti0OE5zQQMld3cJ5viTdEsaWYCu2HaEoblKB\nH6KfRGM2N3L3KjKFGtEg+cX1UdaMlzmp+O5/yvjBykZy6cuUOIsgz2e5nQV4hYEq\ntJ/+6E0QVTXfnVZi4IxKlkVMhyonqOxAOKGG+dWeWh3DqPJFzjmp3kcbRN9E3u+2\nqKU5gpECgYEA+a/i5z2jFCJ8rMpoCPPxm2eiIYZVs3LE33WU5FNNieBRC+KqO06h\nMB3rQ3k8KJDNJYWD5UwIrgjCD5mgkmcSDI6SbOn6PA1Mtw6qZlbeg17V9L9ryXxt\nSfC5AC+qVWd6unrLh0LgkvLS8rgG4GjLZY0HDDMrJWodcc+uWVk3Mo0CgYEA7RsG\nC9gOcHWi6WJ2uEDvLj4IkSkB4IFipEVcKl7VVDSnUgxaBZm3o0DLYDYhIOw7XcQL\n6vpxbRZdlApGyu1ahfMbk3+quFNMQuGxZcv9EhHz7ASnXK6mlrWkJzCGjLz6/MdI\nU0VGbtkBtOY/GaLXdTkQksWowVNoedISfQV9as0CgYEA0Tj1JVecw05yskeZDYd8\nOQCJ9xWd0pSlK6pXbUvweUwiHZd9ldy5bJxle1CnfEZ54KsUbptb2pk0I+ZTitob\nYbJGOEWHjbKHSg1b9A1uvx5EoqWUKG2/FmpEW0eVr6LaUFB9I4aCsCARa5mRCZJG\nfX3DHhHyYZOdwLSKIAyGGDECgYALEwkMQpIiFIyAZBXxcy74tPMHfKfWyZRG4ep1\nHCrQnQj3nxYRTuWx3VPicYTImeAH+CEqX3ouwy2pvXUjA0UIHpu6HutlYpacRRhZ\nDdcLIgWHj4wVmx6yyVcacXzHVAhRCCnLod+xS7d1sI9f7igsFHc+s7a3GOM3VWWB\nq2D5PQKBgQDY9eSb5pc5EYbPy0a/wKFLMNCVLXlDT8jRSC2UnhmcHbhi1IdUbn1j\nR+SuUgrAVNAKzJRY9wmF6Zt0pJ2YLFX7L8HaGyfzkib8kli2sXFonlQ4d0dTdcJo\nVGR1jTxfZQicdPcDPOLPpQz/rP31ZqdHtfaegTOxHebX7W2E5QvPZg==\n-----END RSA PRIVATE KEY-----\n";
|
||||
String key = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA50Iwgq8OIfm5vY9Gwfb6UBt17D7V4djyFSLJ1AbCU/o8Zlrr\nW73JqaK5dC3IO6Dcu+/qPYGtBUWvhFAXrsFOooz0mTod/LtBN1YVurJ60goJrR6w\nKhUYC9H45OW/qcdIM7kdDwiyMZfbHqW6fo0xPqjvgxtZoI+v7pgThacOG6pw7PO6\nGgnJa3MGK3xEbzlI6+EBJWG3EiwexguwOpTD4a4TDIAqKrlVDPeUpU7rFbsBPRS8\nkypR3lU58+WRz/zi9fiH/Sy2X+ChefyZg14HiutJjxc8zJsazF3eDxyLGPQmhv3Mso\nA0wbjGusbe6hPdDkzh/B2KO9u96QCdlGu/rc6QIDAQABAoIBAA/7OgD9+fsNF/Hq\nodgrqja4/xg5a2x1Ip2lTs9RPEKza1Mje1pWrkYD0c8ejtTYFAkE1mozuPJBU5TQ\nOCLChx2iohCovIPHqQUa9Nt3FBfJy8tj8Ian+IZwl0OyQOGJvQqeA00Tq8TTmrfu\negne1gVfhVXJIROAeocBiW/WEJqGti0OE5zQQMld3cJ5viTdEsaWYCu2HaEoblKB\nH6KfRGM2N3L3KjKFGtEg+cX1UdaMlzmp+O5/yvjBykZy6cuUOIsgz2e5nQV4hYEq\ntJ/+6E0QVTXfnVZi4IxKlkVMhyonqOxAOKGG+dWeWh3DqPJFzjmp3kcbRN9E3u+2\nqKU5gpECgYEA+a/i5z2jFCJ8rMpoCPPxm2eiIYZVs3LE33WU5FNNieBRC+KqO06h\nMB3rQ3k8KJDNJYWD5UwIrgjCD5mgkmcSDI6SbOn6PA1Mtw6qZlbeg17V9L9ryXxt\nSfC5AC+qVWd6unrLh0LgkvLS8rgG4GjLZY0HDDMrJWodcc+uWVk3Mo0CgYEA7RsG\nC9gOcHWi6WJ2uEDvLj4IkSkB4IFipEVcKl7VVDSnUgxaBZm3o0DLYDYhIOw7XcQL\n6vpxbRZdlApGyu1ahfMbk3+quFNMQuGxZcv9EhHz7ASnXK6mlrWkJzCGjLz6/MdI\nU0VGbtkBtOY/GaLXdTkQksWowVNoedISfQV9as0CgYEA0Tj1JVecw05yskeZDYd8\nOQCJ9xWd0pSlK6pXbUvweUwiHZd9ldy5bJxle1CnfEZ54KsUbptb2pk0I+ZTitob\nYbJGOEWHjbKHSg1b9A1uvx5EoqWUKG2/FmpEW0eVr6LaUFB9I4aCsCARa5mRCZJG\nfX3DHhHyYZOdwLSKIAyGGDECgYALEwkMQpIiFIyAZBXxcy74tPMHfKfWyZRG4ep1\nHCrQnQj3nxYRTuWx3VPicYTImeAH+CEqX3ouwy2pvXUjA0UIHpu6HutlYpacRRhZ\nDdcLIgWHj4wVmx6yyVcacXzHVAhRCCnLod+xS7d1sI9f7igsFHc+s7a3GOM3VWWB\nq2D5PQKBgQDY9eSb5pc5EYbPy0a/wKFLMNCVLXlDT8jRSC2UnhmcHbhi1IdUbn1j\nR+SuUgrAVNAKzJRY9wmF6Zt0pJ2YLFX7L8HaGyfzkib8kli2sXFonlQ4d0dTdcJo\nVGR1jTxfZQicdPcDPOLPpQz/rP31ZqdHtfaegTOxHebX7W2E5QvPZg==\n-----END RSA PRIVATE KEY-----\n";
|
||||
KeyPair.class.cast(new PEMReader(new StringReader(key)).readObject());
|
||||
}
|
||||
|
||||
|
@ -214,14 +214,15 @@ public class SignedHeaderAuthTest {
|
|||
*/
|
||||
@BeforeClass
|
||||
protected void createFilter() throws IOException {
|
||||
Injector injector = Guice.createInjector(new ChefRestClientModule(),
|
||||
Injector injector = Guice.createInjector(new RestModule(), new ChefRestClientModule(),
|
||||
new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()),
|
||||
new ParserModule(), new AbstractModule() {
|
||||
|
||||
new AbstractModule() {
|
||||
protected void configure() {
|
||||
Jsr330.bindProperties(binder(), checkNotNull(
|
||||
new ChefPropertiesBuilder("foo", "bar")).build());
|
||||
bind(UriBuilder.class).to(UriBuilderImpl.class);
|
||||
new ChefPropertiesBuilder(URI.create("http://localhost"), "foo",
|
||||
"bar")).build());
|
||||
bind(TransformingHttpCommandExecutorService.class).toInstance(
|
||||
createMock(TransformingHttpCommandExecutorService.class));
|
||||
}
|
||||
});
|
||||
encryptionService = injector.getInstance(EncryptionService.class);
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
|
||||
<suite name="jclouds-chef">
|
||||
<test verbose="2" name="org.jclouds.chef.functions.ParseKeyFromJsonTest" annotations="JDK">
|
||||
<classes>
|
||||
<class name="org.jclouds.chef.functions.ParseKeyFromJsonTest"/>
|
||||
</classes>
|
||||
</test>
|
||||
</suite>
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an ;AS IS; BASIS,
|
||||
* WITHOUT WARRANTIES OR 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.ibmdev.binders;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.binders.BindToStringPayload;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class BindImageVisibilityToJsonPayload extends BindToStringPayload {
|
||||
|
||||
@Override
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
|
||||
ImmutableSet.of(MediaType.APPLICATION_JSON));
|
||||
super.bindToRequest(request, String.format("{\"visibility\":\"%s\"}", payload));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.ibmdev.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 IBMDeveloperCloudErrorHandler 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 412:
|
||||
exception = new IllegalStateException(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$
|
||||
$Revision$
|
||||
$Date$
|
||||
|
||||
Copyright (C) 2009 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>org.jclouds</groupId>
|
||||
<artifactId>jclouds-opscodeplatform</artifactId>
|
||||
<name>jclouds Opscode Platform core</name>
|
||||
<description>jclouds components to access Opscode Platform</description>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/opscodeplatform</connection>
|
||||
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/opscodeplatform</developerConnection>
|
||||
<url>http://jclouds.googlecode.com/svn/trunk/opscodeplatform</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>http://jclouds.rimuhosting.com:8081/nexus/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<jclouds.opscodeplatform.org>MYORG</jclouds.opscodeplatform.org>
|
||||
<jclouds.opscodeplatform.rsa-key>/etc/chef/validation.pem</jclouds.opscodeplatform.rsa-key>
|
||||
<jclouds.test.user>${jclouds.opscodeplatform.org}</jclouds.test.user>
|
||||
<jclouds.test.key>${jclouds.opscodeplatform.rsa-key}</jclouds.test.key>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-chef</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-chef</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* Copyright (C) 2009 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 org.jclouds.opscodeplatform;
|
||||
|
||||
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 Opscode Platform resource.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
|
||||
@Qualifier
|
||||
public @interface OpscodePlatform {
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.Organization;
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuth;
|
||||
import org.jclouds.chef.functions.OrganizationName;
|
||||
import org.jclouds.chef.functions.ParseKeyFromJson;
|
||||
import org.jclouds.chef.functions.ParseOrganizationFromJson;
|
||||
import org.jclouds.chef.functions.ParseUserFromJson;
|
||||
import org.jclouds.chef.functions.Username;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.Endpoint;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to the Opscode Platform via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @see OpscodePlatformClient
|
||||
* @see <a href="TODO: insert URL of provider documentation" />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Endpoint(OpscodePlatform.class)
|
||||
@RequestFilters(SignedHeaderAuth.class)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface OpscodePlatformAsyncClient {
|
||||
/**
|
||||
* @see ChefCookbooks#listCookbooksInOrg
|
||||
*/
|
||||
@Delegate
|
||||
@Path("/organizations/{orgname}")
|
||||
ChefAsyncClient getChefClientForOrg(@PathParam("orgname") String orgname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createUser
|
||||
*/
|
||||
@POST
|
||||
@Path("/users")
|
||||
@ResponseParser(ParseKeyFromJson.class)
|
||||
ListenableFuture<String> createUser(@BinderParam(BindToJsonPayload.class) User user);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateUser
|
||||
*/
|
||||
@PUT
|
||||
@Path("/users/{username}")
|
||||
@ResponseParser(ParseUserFromJson.class)
|
||||
ListenableFuture<User> updateUser(
|
||||
@PathParam("username") @ParamParser(Username.class) @BinderParam(BindToJsonPayload.class) User user);
|
||||
|
||||
/**
|
||||
* @see ChefClient#getUser
|
||||
*/
|
||||
@GET
|
||||
@Path("/users/{username}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ResponseParser(ParseUserFromJson.class)
|
||||
ListenableFuture<User> getUser(@PathParam("username") String username);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteUser
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/users/{username}")
|
||||
@ResponseParser(ParseUserFromJson.class)
|
||||
ListenableFuture<User> deleteUser(@PathParam("username") String username);
|
||||
|
||||
/**
|
||||
* @see ChefClient#createOrg
|
||||
*/
|
||||
@POST
|
||||
@Path("/organizations")
|
||||
@ResponseParser(ParseKeyFromJson.class)
|
||||
ListenableFuture<String> createOrg(@BinderParam(BindToJsonPayload.class) Organization org);
|
||||
|
||||
/**
|
||||
* @see ChefClient#updateOrg
|
||||
*/
|
||||
@PUT
|
||||
@Path("/organizations/{orgname}")
|
||||
@ResponseParser(ParseOrganizationFromJson.class)
|
||||
ListenableFuture<Organization> updateOrg(
|
||||
@PathParam("orgname") @ParamParser(OrganizationName.class) @BinderParam(BindToJsonPayload.class) Organization org);
|
||||
|
||||
/**
|
||||
* @see ChefClient#getOrg
|
||||
*/
|
||||
@GET
|
||||
@Path("/organizations/{orgname}")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ResponseParser(ParseOrganizationFromJson.class)
|
||||
ListenableFuture<Organization> getOrg(@PathParam("orgname") String orgname);
|
||||
|
||||
/**
|
||||
* @see ChefClient#deleteOrg
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/organizations/{orgname}")
|
||||
@ResponseParser(ParseOrganizationFromJson.class)
|
||||
ListenableFuture<Organization> deleteOrg(@PathParam("orgname") String orgname);
|
||||
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.domain.Organization;
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.Endpoint;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to the Opscode Platform.
|
||||
* <p/>
|
||||
*
|
||||
* @see OpscodePlatformAsyncClient
|
||||
* @see <a href="TODO: insert URL of Opscode Platform documentation" />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface OpscodePlatformClient {
|
||||
/**
|
||||
* @return a chef client appropriate for the organization specified.
|
||||
*/
|
||||
@Delegate
|
||||
@Path("/organizations/{orgname}")
|
||||
@Endpoint(OpscodePlatform.class)
|
||||
ChefClient getChefClientForOrg(@PathParam("orgname") String orgname);
|
||||
|
||||
/**
|
||||
* creates a new user
|
||||
*
|
||||
* @return the private key of the user. You can then use this user 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 user.
|
||||
*/
|
||||
String createUser(User user);
|
||||
|
||||
/**
|
||||
* updates an existing user. Note: you must have update rights on the user.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized user.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Update rights on the user.
|
||||
* @throws ResourceNotFoundException
|
||||
* if the user does not exist.
|
||||
*/
|
||||
User updateUser(User user);
|
||||
|
||||
/**
|
||||
* retrieves an existing user. Note: you must have update rights on the user.
|
||||
*
|
||||
* @return null, if the user is not found
|
||||
*/
|
||||
User getUser(String username);
|
||||
|
||||
/**
|
||||
* deletes an existing user. Note: you must have delete rights on the user.
|
||||
*
|
||||
* @return the last state of the User object in question. * @throws AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized user.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Delete rights on the user.
|
||||
* @throws ResourceNotFoundException
|
||||
* <p/>
|
||||
* “404 Not Found” if the user does not exist.
|
||||
*/
|
||||
User deleteUser(String username);
|
||||
|
||||
/**
|
||||
* creates a new organization
|
||||
*
|
||||
* @return the private key of the organization. You can then use this organization name and
|
||||
* private key to access the Opscode API.
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* "401 Unauthorized" if the caller is not a recognized organization.
|
||||
* <p/>
|
||||
* "403 Forbidden" if the caller is not authorized to create a organization.
|
||||
*/
|
||||
String createOrg(Organization organization);
|
||||
|
||||
/**
|
||||
* updates an existing organization. Note: you must have update rights on the organization.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized organization.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Update rights on the organization.
|
||||
* @throws ResourceNotFoundException
|
||||
* if the organization does not exist.
|
||||
*/
|
||||
Organization updateOrg(Organization organization);
|
||||
|
||||
/**
|
||||
* retrieves an existing organization. Note: you must have update rights on the organization.
|
||||
*
|
||||
* @return null, if the organization is not found
|
||||
*/
|
||||
Organization getOrg(String organizationname);
|
||||
|
||||
/**
|
||||
* deletes an existing organization. Note: you must have delete rights on the organization.
|
||||
*
|
||||
* @return the last state of the Organization object in question. * @throws
|
||||
* AuthorizationException
|
||||
* <p/>
|
||||
* “401 Unauthorized” if you are not a recognized organization.
|
||||
* <p/>
|
||||
* “403 Forbidden” if you do not have Delete rights on the organization.
|
||||
* @throws ResourceNotFoundException
|
||||
* <p/>
|
||||
* “404 Not Found” if the organization does not exist.
|
||||
*/
|
||||
Organization deleteOrg(String organizationname);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.reference.ChefConstants;
|
||||
import org.jclouds.opscodeplatform.config.OpscodePlatformContextModule;
|
||||
import org.jclouds.opscodeplatform.config.OpscodePlatformRestClientModule;
|
||||
import org.jclouds.rest.RestContextBuilder;
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class OpscodePlatformContextBuilder extends RestContextBuilder<OpscodePlatformAsyncClient, OpscodePlatformClient> {
|
||||
|
||||
public OpscodePlatformContextBuilder(String providerName, Properties props) {
|
||||
super(providerName, OpscodePlatformClient.class, OpscodePlatformAsyncClient.class, props);
|
||||
checkNotNull(properties.getProperty(ChefConstants.PROPERTY_CHEF_IDENTITY));
|
||||
checkNotNull(properties.getProperty(ChefConstants.PROPERTY_CHEF_RSA_KEY));
|
||||
}
|
||||
|
||||
protected void addClientModule(List<Module> modules) {
|
||||
modules.add(new OpscodePlatformRestClientModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addContextModule(String providerName, List<Module> modules) {
|
||||
modules.add(new OpscodePlatformContextModule(providerName));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
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 OpscodePlatformClient} 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 Adrian Cole
|
||||
* @see RestContext
|
||||
* @see OpscodePlatformClient
|
||||
* @see OpscodePlatformAsyncClient
|
||||
*/
|
||||
public class OpscodePlatformContextFactory {
|
||||
|
||||
public static RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> createContext(
|
||||
String identity, String rsaKey, Module... modules) {
|
||||
return new OpscodePlatformContextBuilder("opscodeplatform",
|
||||
new OpscodePlatformPropertiesBuilder(identity, rsaKey).build()).withModules(modules)
|
||||
.buildContext();
|
||||
}
|
||||
|
||||
public static RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> createContext(
|
||||
URI endpoint, String identity, String rsaKey, Module... modules) {
|
||||
return new OpscodePlatformContextBuilder("opscodeplatform",
|
||||
new OpscodePlatformPropertiesBuilder(identity, rsaKey).withEndpoint(endpoint)
|
||||
.build()).withModules(modules).buildContext();
|
||||
}
|
||||
|
||||
public static RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> createContext(
|
||||
Properties properties, Module... modules) {
|
||||
return new OpscodePlatformContextBuilder("opscodeplatform",
|
||||
new OpscodePlatformPropertiesBuilder(properties).build()).withModules(modules)
|
||||
.buildContext();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.opscodeplatform.reference.OpscodePlatformConstants.PROPERTY_OPSCODEPLATFORM_ENDPOINT;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.chef.internal.BaseChefPropertiesBuilder;
|
||||
|
||||
/**
|
||||
* Builds properties used in Chef Clients
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class OpscodePlatformPropertiesBuilder extends BaseChefPropertiesBuilder {
|
||||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_OPSCODEPLATFORM_ENDPOINT, "https://api.opscode.com");
|
||||
return properties;
|
||||
}
|
||||
|
||||
public OpscodePlatformPropertiesBuilder(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public OpscodePlatformPropertiesBuilder(URI endpoint, String identity, String rsaKey) {
|
||||
super(endpoint, identity, rsaKey);
|
||||
}
|
||||
|
||||
public OpscodePlatformPropertiesBuilder(String identity, String rsaKey) {
|
||||
super(URI.create("https://api.opscode.com"), identity, rsaKey);
|
||||
}
|
||||
|
||||
public BaseChefPropertiesBuilder withEndpoint(URI endpoint) {
|
||||
properties.setProperty(PROPERTY_OPSCODEPLATFORM_ENDPOINT, checkNotNull(endpoint, "endpoint")
|
||||
.toString());
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform.config;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.lifecycle.Closer;
|
||||
import org.jclouds.opscodeplatform.OpscodePlatform;
|
||||
import org.jclouds.opscodeplatform.OpscodePlatformAsyncClient;
|
||||
import org.jclouds.opscodeplatform.OpscodePlatformClient;
|
||||
import org.jclouds.opscodeplatform.reference.OpscodePlatformConstants;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.jclouds.rest.internal.RestContextImpl;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the OpscodePlatform connection, including logging and http transport.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class OpscodePlatformContextModule extends AbstractModule {
|
||||
|
||||
public OpscodePlatformContextModule(String providerName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> provideContext(Closer closer,
|
||||
OpscodePlatformAsyncClient asyncApi, OpscodePlatformClient syncApi,
|
||||
@OpscodePlatform URI endPoint,
|
||||
@Named(OpscodePlatformConstants.PROPERTY_OPSCODEPLATFORM_ENDPOINT) String account) {
|
||||
return new RestContextImpl<OpscodePlatformAsyncClient, OpscodePlatformClient>(closer,
|
||||
asyncApi, syncApi, endPoint, account);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* Copyright (C) 2009 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 org.jclouds.opscodeplatform.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.chef.ChefAsyncClient;
|
||||
import org.jclouds.chef.ChefClient;
|
||||
import org.jclouds.chef.config.BaseChefRestClientModule;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.opscodeplatform.OpscodePlatform;
|
||||
import org.jclouds.opscodeplatform.OpscodePlatformAsyncClient;
|
||||
import org.jclouds.opscodeplatform.OpscodePlatformClient;
|
||||
import org.jclouds.opscodeplatform.reference.OpscodePlatformConstants;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Opscode Platform connection.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
public class OpscodePlatformRestClientModule extends
|
||||
BaseChefRestClientModule<OpscodePlatformAsyncClient, OpscodePlatformClient> {
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
|
||||
.<Class<?>, Class<?>> builder()//
|
||||
.put(ChefClient.class, ChefAsyncClient.class)//
|
||||
.build();
|
||||
|
||||
public OpscodePlatformRestClientModule() {
|
||||
super(OpscodePlatformClient.class, OpscodePlatformAsyncClient.class, DELEGATE_MAP);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@OpscodePlatform
|
||||
protected URI provideURI(
|
||||
@Named(OpscodePlatformConstants.PROPERTY_OPSCODEPLATFORM_ENDPOINT) String endpoint) {
|
||||
return URI.create(endpoint);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform.reference;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in Opscode Platform connections.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface OpscodePlatformConstants {
|
||||
public static final String PROPERTY_OPSCODEPLATFORM_ENDPOINT = "jclouds.opscodeplatform.endpoint";
|
||||
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
||||
import static org.easymock.classextension.EasyMock.createMock;
|
||||
import static org.easymock.classextension.EasyMock.replay;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.jclouds.chef.domain.Organization;
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuth;
|
||||
import org.jclouds.chef.filters.SignedHeaderAuthTest;
|
||||
import org.jclouds.chef.functions.ParseKeyFromJson;
|
||||
import org.jclouds.chef.functions.ParseOrganizationFromJson;
|
||||
import org.jclouds.chef.functions.ParseUserFromJson;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.opscodeplatform.config.OpscodePlatformRestClientModule;
|
||||
import org.jclouds.rest.RestClientTest;
|
||||
import org.jclouds.rest.config.RestModule;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||
import org.jclouds.util.Jsr330;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Tests annotation parsing of {@code OpscodePlatformAsyncClient}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "opscodeplatform.OpscodePlatformAsyncClientTest")
|
||||
public class OpscodePlatformAsyncClientTest extends RestClientTest<OpscodePlatformAsyncClient> {
|
||||
|
||||
public void testDelegatedChefCallsResolveProperly() throws SecurityException,
|
||||
NoSuchMethodException, InterruptedException, ExecutionException {
|
||||
final TransformingHttpCommandExecutorService httpExecutor = createMock(TransformingHttpCommandExecutorService.class);
|
||||
|
||||
Injector injector = Guice.createInjector(createModule(), new RestModule() {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(TransformingHttpCommandExecutorService.class).toInstance(httpExecutor);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
}, new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()));
|
||||
|
||||
replay(httpExecutor);
|
||||
|
||||
OpscodePlatformAsyncClient caller = injector.getInstance(OpscodePlatformAsyncClient.class);
|
||||
|
||||
try {
|
||||
caller.getChefClientForOrg("goo").listClients().get();
|
||||
assert false : "shouldn't have connected as this url should be dummy";
|
||||
} catch (AssertionError e) {
|
||||
assert e.getMessage().indexOf(
|
||||
"[request=GET https://api.opscode.com/organizations/goo/clients HTTP/1.1]") != -1 : e
|
||||
.getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testCreateUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("createUser", User.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, new User("myuser"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST https://api.opscode.com/users HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 21\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"username\":\"myuser\"}");
|
||||
|
||||
// now make sure request filters apply by replaying
|
||||
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
|
||||
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST https://api.opscode.com/users HTTP/1.1");
|
||||
assertHeadersEqual(
|
||||
httpRequest,
|
||||
new StringBuilder("Accept: application/json")
|
||||
.append("\n")
|
||||
.append("Content-Length: 21")
|
||||
.append("\n")
|
||||
.append("Content-Type: application/json")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-1: kfrkDpfgNU26k70R1vl1bEWk0Q0f9Fs/3kxOX7gHd7iNoJq03u7RrcrAOSgL")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-2: ETj5JNeCk18BmFkHMAbCA9hXVo1T4rlHCpbuzAzFlFxUGAT4wj8UoO7V886X")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-3: Kf8DvihP6ElthCNuu1xuhN0B4GEmWC9+ut7UMLe0L2T34VzkbCtuInGbf42/")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-4: G7iu94/xFOT1gN9cex4pNyTnRCHzob4JVU1usxt/2g5grN2SyYwRS5+4MNLN")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-5: WY/iLUPb/9dwtiIQsnUOXqDrs28zNswZulQW4AzYRd7MczJVKU4y4+4XRcB4")
|
||||
.append("\n")
|
||||
.append(
|
||||
"X-Ops-Authorization-6: 2+BFLT5o6P6G0D+eCu3zSuaqEJRucPJPaDGWdKIMag==")
|
||||
.append("\n").append("X-Ops-Content-Hash: yLHOxvgIEtNw5UrZDxslOeMw1gw=")
|
||||
.append("\n").append("X-Ops-Sign: version=1.0").append("\n").append(
|
||||
"X-Ops-Timestamp: timestamp").append("\n").append(
|
||||
"X-Ops-Userid: user").append("\n").toString());
|
||||
assertPayloadEquals(httpRequest, "{\"username\":\"myuser\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("updateUser", User.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, new User("myuser"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT https://api.opscode.com/users/myuser HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 21\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"username\":\"myuser\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseUserFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGetUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("getUser", String.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, "myuser");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "GET https://api.opscode.com/users/myuser HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseUserFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteUser() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("deleteUser", String.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, "myuser");
|
||||
|
||||
assertRequestLineEquals(httpRequest, "DELETE https://api.opscode.com/users/myuser HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseUserFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testCreateOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("createOrg", Organization.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, new Organization("myorganization"));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST https://api.opscode.com/organizations HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 25\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"myorganization\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testUpdateOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("updateOrg", Organization.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, new Organization("myorganization"));
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"PUT https://api.opscode.com/organizations/myorganization HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest,
|
||||
"Accept: application/json\nContent-Length: 25\nContent-Type: application/json\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"myorganization\"}");
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseOrganizationFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testGetOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("getOrg", String.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, "myorganization");
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"GET https://api.opscode.com/organizations/myorganization HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseOrganizationFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteOrg() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = OpscodePlatformAsyncClient.class.getMethod("deleteOrg", String.class);
|
||||
GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest = processor.createRequest(
|
||||
method, "myorganization");
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"DELETE https://api.opscode.com/organizations/myorganization HTTP/1.1");
|
||||
assertHeadersEqual(httpRequest, "Accept: application/json\n");
|
||||
assertPayloadEquals(httpRequest, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseOrganizationFromJson.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpRequest);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkFilters(GeneratedHttpRequest<OpscodePlatformAsyncClient> httpRequest) {
|
||||
assertEquals(httpRequest.getFilters().size(), 1);
|
||||
assertEquals(httpRequest.getFilters().get(0).getClass(), SignedHeaderAuth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeLiteral<RestAnnotationProcessor<OpscodePlatformAsyncClient>> createTypeLiteral() {
|
||||
return new TypeLiteral<RestAnnotationProcessor<OpscodePlatformAsyncClient>>() {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new OpscodePlatformRestClientModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
Jsr330.bindProperties(binder(), new OpscodePlatformPropertiesBuilder("user",
|
||||
SignedHeaderAuthTest.PRIVATE_KEY).build());
|
||||
install(new NullLoggingModule());
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
return "timestamp";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
*
|
||||
* 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 org.jclouds.opscodeplatform;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.chef.domain.User;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code OpscodePlatformClient}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "chef.OpscodePlatformClientLiveTest")
|
||||
public class OpscodePlatformClientLiveTest {
|
||||
|
||||
private RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> validatorConnection;
|
||||
private RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> clientConnection;
|
||||
|
||||
private String orgname;
|
||||
private String clientKey;
|
||||
|
||||
public static final String PREFIX = System.getProperty("user.name") + "-jcloudstest";
|
||||
|
||||
@BeforeClass(groups = { "live" })
|
||||
public void setupClient() throws IOException {
|
||||
orgname = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||
String keyfile = System.getProperty("jclouds.test.key");
|
||||
if (keyfile == null || keyfile.equals(""))
|
||||
keyfile = "/etc/chef/validation.pem";
|
||||
validatorConnection = createConnection(orgname + "-validator", Files.toString(new File(
|
||||
keyfile), Charsets.UTF_8));
|
||||
}
|
||||
|
||||
private RestContext<OpscodePlatformAsyncClient, OpscodePlatformClient> createConnection(
|
||||
String identity, String key) throws IOException {
|
||||
return OpscodePlatformContextFactory.createContext(identity, key, new Log4JLoggingModule());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListClientsInOrg() throws Exception {
|
||||
Set<String> clients = validatorConnection.getApi().getChefClientForOrg(orgname).listClients();
|
||||
assertNotNull(clients);
|
||||
assert clients.contains(orgname + "-validator");
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testListClientsInOrg")
|
||||
public void testCreateClientInOrg() throws Exception {
|
||||
validatorConnection.getApi().getChefClientForOrg(orgname).deleteClient(PREFIX);
|
||||
clientKey = validatorConnection.getApi().getChefClientForOrg(orgname).createClient(PREFIX);
|
||||
assertNotNull(clientKey);
|
||||
System.out.println(clientKey);
|
||||
clientConnection = createConnection(PREFIX, clientKey);
|
||||
clientConnection.getApi().getChefClientForOrg(orgname).clientExists(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClientInOrg")
|
||||
public void testGenerateKeyForClientInOrg() throws Exception {
|
||||
clientKey = validatorConnection.getApi().getChefClientForOrg(orgname).generateKeyForClient(
|
||||
PREFIX);
|
||||
assertNotNull(clientKey);
|
||||
clientConnection.close();
|
||||
clientConnection = createConnection(PREFIX, clientKey);
|
||||
clientConnection.getApi().getChefClientForOrg(orgname).clientExists(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClientInOrg")
|
||||
public void testClientExistsInOrg() throws Exception {
|
||||
assertNotNull(validatorConnection.getApi().getChefClientForOrg(orgname).clientExists(PREFIX));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testGetOrgFailsForValidationKey() throws Exception {
|
||||
validatorConnection.getApi().getOrg(orgname);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testGenerateKeyForClientInOrg", expectedExceptions = AuthorizationException.class)
|
||||
public void testGetOrgFailsForClient() throws Exception {
|
||||
clientConnection.getApi().getOrg(orgname);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testGetUser() throws Exception {
|
||||
User user = validatorConnection.getApi().getUser(orgname);
|
||||
assertNotNull(user);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testCreateUser() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testUpdateUser() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testDeleteUser() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testCreateOrg() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testUpdateOrg() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testDeleteOrg() throws Exception {
|
||||
// TODO
|
||||
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testGenerateKeyForClientInOrg")
|
||||
public void testListCookbooksInOrg() throws Exception {
|
||||
System.err.println(clientConnection.getApi().getChefClientForOrg(orgname).listCookbooks());
|
||||
}
|
||||
|
||||
@AfterClass(groups = { "live" })
|
||||
public void teardownClient() throws IOException {
|
||||
if (clientConnection != null)
|
||||
clientConnection.close();
|
||||
if (validatorConnection != null)
|
||||
validatorConnection.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?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="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${symbol_escape}n
|
||||
-->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message${symbol_escape}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${symbol_escape}n
|
||||
-->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message${symbol_escape}n <param
|
||||
name="ConversionPattern" value="%d %-5r %-5p [%c]
|
||||
(%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</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>
|
||||
|
||||
<!-- ======================= -->
|
||||
<!-- Setup the Root category -->
|
||||
<!-- ======================= -->
|
||||
|
||||
<root>
|
||||
<priority value="WARN" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
Loading…
Reference in New Issue