Refactored create client to be the jclouds way

This commit is contained in:
Ignasi Barrera 2011-09-14 16:50:24 +02:00
parent a9d425489f
commit 5154ab2ee8
7 changed files with 164 additions and 9 deletions

View File

@ -32,6 +32,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.chef.binders.AdminFlagFromCreateClientOptions;
import org.jclouds.chef.binders.BindAdminClientToJsonPayload;
import org.jclouds.chef.binders.BindChecksumsToJsonPayload;
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
@ -55,10 +56,13 @@ import org.jclouds.chef.functions.ParseSearchClientsFromJson;
import org.jclouds.chef.functions.ParseSearchDatabagFromJson;
import org.jclouds.chef.functions.ParseSearchNodesFromJson;
import org.jclouds.chef.functions.ParseSearchRolesFromJson;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.Unwrap;
@ -153,14 +157,14 @@ public interface ChefAsyncClient {
*/
@POST
@Path("/clients")
ListenableFuture<Client> createClient(@BinderParam(BindNameToJsonPayload.class) String clientname);
/**
* @see ChefClient#createAdminClient(String)
*/
@MapBinder(BindToJsonPayload.class)
ListenableFuture<Client> createClient(@PayloadParam("name") String clientname);
@POST
@Path("/clients")
ListenableFuture<Client> createAdminClient(@BinderParam(BindAdminClientToJsonPayload.class) String clientname);
@MapBinder(BindToJsonPayload.class)
ListenableFuture<Client> createClient(@PayloadParam("name") String clientname,
@PayloadParam("admin") @ParamParser(AdminFlagFromCreateClientOptions.class) CreateClientOptions options);
/**
* @see ChefClient#generateKeyForClient

View File

@ -23,6 +23,10 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.chef.binders.AdminFlagFromCreateClientOptions;
import org.jclouds.chef.domain.Client;
import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.DatabagItem;
@ -31,12 +35,18 @@ import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides synchronous access to Chef.
* <p/>
@ -155,7 +165,7 @@ public interface ChefClient {
* "409 Conflict" if the client already exists
*/
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
Client createAdminClient(String name);
Client createClient(String name, CreateClientOptions options);
/**
* generate a new key-pair for this client, and return the new private key in

View File

@ -0,0 +1,38 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.chef.binders;
import javax.inject.Singleton;
import org.jclouds.chef.options.CreateClientOptions;
import com.google.common.base.Function;
/**
* @author Ignasi Barrera
*/
@Singleton
public class AdminFlagFromCreateClientOptions implements Function<Object, String> {
public String apply(Object from) {
return String.valueOf(((CreateClientOptions) from).isAdmin());
}
}

View File

@ -0,0 +1,71 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.chef.options;
/**
* Options for the create client method.
*
* @author Ignasi Barrera
*/
public class CreateClientOptions implements Cloneable
{
/** Administrator flag. This flag will be ignored in Opscode Hosted Chef. */
private boolean admin;
public CreateClientOptions() {
}
CreateClientOptions(final boolean admin) {
super();
this.admin = admin;
}
public boolean isAdmin() {
return admin;
}
public CreateClientOptions admin() {
this.admin = true;
return this;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new CreateClientOptions(admin);
}
@Override
public String toString() {
return "[admin=" + admin + "]";
}
public static class Builder
{
/**
* @see CreateClientOptions#admin()
*/
public static CreateClientOptions admin() {
CreateClientOptions options = new CreateClientOptions();
return options.admin();
}
}
}

View File

@ -48,6 +48,7 @@ import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
@ -121,9 +122,9 @@ public class TransientChefAsyncClient implements ChefAsyncClient {
// TODO Auto-generated method stub
return null;
}
@Override
public ListenableFuture<Client> createAdminClient(String clientname) {
public ListenableFuture<Client> createClient(String clientname, CreateClientOptions options) {
// TODO Auto-generated method stub
return null;
}

View File

@ -39,6 +39,7 @@ import org.jclouds.chef.domain.Resource;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.crypto.Pems;
import org.jclouds.io.InputSuppliers;
@ -211,6 +212,19 @@ public abstract class BaseChefClientLiveTest {
assert clients.contains(PREFIX) : String.format("client %s not in %s", PREFIX, clients);
assertNotNull(getClientConnection().getClient(PREFIX));
}
@Test
public void testCreateAdminClient() throws Exception {
getAdminConnection().deleteClient(PREFIX);
clientKey = Pems.pem(getAdminConnection().createClient(PREFIX, CreateClientOptions.Builder.admin()).getPrivateKey());
recreateClientConnection();
getClientConnection().clientExists(PREFIX);
Set<String> clients = getAdminConnection().listClients();
assert clients.contains(PREFIX) : String.format("client %s not in %s", PREFIX, clients);
assertNotNull(getClientConnection().getClient(PREFIX));
}
@Test(dependsOnMethods = "testCreateClient")
public void testClientExists() throws Exception {

View File

@ -38,6 +38,7 @@ import org.jclouds.chef.functions.ParseSearchClientsFromJson;
import org.jclouds.chef.functions.ParseSearchDatabagFromJson;
import org.jclouds.chef.functions.ParseSearchNodesFromJson;
import org.jclouds.chef.functions.ParseSearchRolesFromJson;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
@ -222,6 +223,22 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
checkFilters(httpRequest);
}
public void testCreateAdminClient() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("createClient", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client", CreateClientOptions.Builder.admin());
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/clients HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.8\n");
assertPayloadEquals(httpRequest, "{\"name\":\"client\", \"admin\": true}", "application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testListClients() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("listClients");