From 3f2a196f269727faea732806807ea04043ca9126 Mon Sep 17 00:00:00 2001 From: Ignasi Barrera Date: Wed, 21 Aug 2013 13:14:10 +0200 Subject: [PATCH] JCLOUDS-245/JCLOUDS-254: Fix live tests Refactored the domain model to be immutable and addressed some inconsistences with the Chef Server API model. Removed all HEAD methods, as they have been removed from newer versions of Chef. They were used to test the existance of a given resource, and with newer versions the only way to do that is via a GET operation. Now all live tests are passing for Community Chef 0.10.8, 11.0.6 and Enterprise Chef. --- README.md | 2 +- .../chef/compute/ChefComputeServiceLiveTest.java | 2 +- core/src/main/java/org/jclouds/chef/ChefApi.java | 77 +----- .../org/jclouds/chef/config/ChefParserModule.java | 86 +++++++ .../java/org/jclouds/chef/domain/Attribute.java | 113 +++++++-- .../org/jclouds/chef/domain/BootstrapConfig.java | 17 +- .../org/jclouds/chef/domain/ChecksumStatus.java | 49 +++- .../main/java/org/jclouds/chef/domain/Client.java | 94 +++++-- .../jclouds/chef/domain/CookbookDefinition.java | 72 +++++- .../org/jclouds/chef/domain/CookbookVersion.java | 209 +++++++++++++--- .../java/org/jclouds/chef/domain/DatabagItem.java | 3 +- .../java/org/jclouds/chef/domain/Environment.java | 143 +++++++---- .../java/org/jclouds/chef/domain/Metadata.java | 250 ++++++++++++++++--- .../main/java/org/jclouds/chef/domain/Node.java | 242 +++++++++++------- .../java/org/jclouds/chef/domain/Resource.java | 77 ++++-- .../main/java/org/jclouds/chef/domain/Role.java | 131 +++++++--- .../main/java/org/jclouds/chef/domain/Sandbox.java | 88 +++++-- .../java/org/jclouds/chef/domain/SearchResult.java | 7 +- .../org/jclouds/chef/domain/UploadSandbox.java | 62 ++++- .../org/jclouds/chef/functions/ClientForGroup.java | 7 +- .../internal/CleanupStaleNodesAndClientsImpl.java | 2 +- ...eateNodeAndPopulateAutomaticAttributesImpl.java | 19 +- .../UpdateAutomaticAttributesOnNodeImpl.java | 14 +- .../org/jclouds/chef/test/TransientChefApi.java | 25 -- .../org/jclouds/chef/util/CollectionUtils.java | 71 ++++++ .../test/java/org/jclouds/chef/ChefApiTest.java | 103 +------- .../BindHexEncodedMD5sToJsonPayloadTest.java | 4 +- .../jclouds/chef/config/ChefParserModuleTest.java | 95 ++++++++ .../chef/functions/ParseClientFromJsonTest.java | 4 +- .../ParseCookbookDefinitionFromJsonv10Test.java | 15 +- ...ParseCookbookDefinitionListFromJsonv10Test.java | 21 +- .../ParseCookbookVersionFromJsonTest.java | 80 +++--- .../chef/functions/ParseNodeFromJsonTest.java | 12 +- .../chef/functions/ParseSandboxFromJsonTest.java | 7 +- .../functions/ParseUploadSandboxFromJsonTest.java | 26 +- .../jclouds/chef/functions/UriForResourceTest.java | 2 +- .../jclouds/chef/internal/BaseChefApiLiveTest.java | 186 +++++++------- ...AndPopulateAutomaticAttributesImplLiveTest.java | 2 +- ...NodeAndPopulateAutomaticAttributesImplTest.java | 12 +- ...pdateAutomaticAttributesOnNodeImplLiveTest.java | 4 +- .../UpdateAutomaticAttributesOnNodeImplTest.java | 17 +- .../chef/test/TransientChefApiIntegrationTest.java | 12 +- .../test/resources/apache-chef-demo-cookbook.json | 21 +- core/src/test/resources/brew-cookbook.json | 49 +++- core/src/test/resources/client.json | 9 +- core/src/test/resources/client.txt | 7 - core/src/test/resources/logback.xml | 5 - core/src/test/resources/mysql-cookbook.json | 269 ++++++++++++++++++++- core/src/test/resources/newclient.txt | 1 - core/src/test/resources/node.json | 12 +- core/src/test/resources/tomcat-cookbook.json | 122 +++++++++- .../jclouds/enterprisechef/EnterpriseChefApi.java | 15 -- .../org/jclouds/enterprisechef/domain/Group.java | 124 ++++++++-- .../org/jclouds/enterprisechef/domain/User.java | 137 ++++++++--- .../EnterpriseChefApiExpectTest.java | 15 +- .../enterprisechef/EnterpriseChefApiLiveTest.java | 19 +- .../BindGroupToUpdateRequestJsonPayloadTest.java | 9 +- .../enterprisechef/binders/GroupNameTest.java | 2 +- 58 files changed, 2353 insertions(+), 927 deletions(-) create mode 100644 core/src/main/java/org/jclouds/chef/util/CollectionUtils.java create mode 100644 core/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java delete mode 100644 core/src/test/resources/client.txt delete mode 100644 core/src/test/resources/newclient.txt diff --git a/README.md b/README.md index ed2c40e..cb1987f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is the jclouds Chef api. It provides access to the different flavours of th * [Chef community](http://www.opscode.com/chef/) * [Enterprise Chef](http://www.opscode.com/enterprise-chef/) -It currently supports versions **0.9** and **0.10** of the standard Chef server apis, and an initial +It currently supports versions **0.9**, **0.10** and **11** of the standard Chef server apis, and an initial and very basic (still in progress) implementation of the user and organization api of the Enterprise Chef. Also provides a set of utility methods to combine Chef features with the jclouds Compute service, allowing diff --git a/compute/src/test/java/org/jclouds/chef/compute/ChefComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/chef/compute/ChefComputeServiceLiveTest.java index 71290d7..0c8fcc5 100644 --- a/compute/src/test/java/org/jclouds/chef/compute/ChefComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/chef/compute/ChefComputeServiceLiveTest.java @@ -108,7 +108,7 @@ public class ChefComputeServiceLiveTest extends BaseComputeServiceIntegratedChef if (context != null) { view.getChefService().cleanupStaleNodesAndClients(group + "-", 1); ChefApi api = view.unwrapApi(ChefApi.class); - if (clientName != null && api.clientExists(clientName)) { + if (clientName != null && api.getClient(clientName) != null) { api.deleteClient(clientName); } context.close(); diff --git a/core/src/main/java/org/jclouds/chef/ChefApi.java b/core/src/main/java/org/jclouds/chef/ChefApi.java index 3c3d2bc..faa189c 100644 --- a/core/src/main/java/org/jclouds/chef/ChefApi.java +++ b/core/src/main/java/org/jclouds/chef/ChefApi.java @@ -26,7 +26,6 @@ import javax.inject.Named; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; -import javax.ws.rs.HEAD; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -36,7 +35,6 @@ import javax.ws.rs.core.MediaType; import org.jclouds.Constants; import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; -import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.chef.binders.BindChecksumsToJsonPayload; @@ -86,6 +84,7 @@ import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SinceApiVersion; +import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.binders.BindToJsonPayload; /** @@ -295,20 +294,6 @@ public interface ChefApi extends Closeable { Set listClients(); /** - * @return true if the specified client name exists. - * @throws AuthorizationException - *

- * "401 Unauthorized" if you are not a recognized user. - *

- * "403 Forbidden" if you do not have rights to view the client. - */ - @Named("client:exists") - @HEAD - @Path("/clients/{clientname}") - @Fallback(FalseOnNotFoundOr404.class) - boolean clientExists(@PathParam("clientname") String clientname); - - /** * deletes an existing client. * * @return last state of the client you deleted or null, if not found @@ -385,20 +370,6 @@ public interface ChefApi extends Closeable { Set listNodes(); /** - * @return true if the specified node name exists. - * @throws AuthorizationException - *

- * "401 Unauthorized" if you are not a recognized user. - *

- * "403 Forbidden" if you do not have rights to view the node. - */ - @Named("node:exists") - @HEAD - @Path("/nodes/{nodename}") - @Fallback(FalseOnNotFoundOr404.class) - boolean nodeExists(@PathParam("nodename") String nodename); - - /** * deletes an existing node. * * @return last state of the node you deleted or null, if not found @@ -474,20 +445,6 @@ public interface ChefApi extends Closeable { Set listRoles(); /** - * @return true if the specified role name exists. - * @throws AuthorizationException - *

- * "401 Unauthorized" if you are not a recognized user. - *

- * "403 Forbidden" if you do not have rights to view the role. - */ - @Named("role:exists") - @HEAD - @Path("/roles/{rolename}") - @Fallback(FalseOnNotFoundOr404.class) - boolean roleExists(@PathParam("rolename") String rolename); - - /** * deletes an existing role. * * @return last state of the role you deleted or null, if not found @@ -549,21 +506,6 @@ public interface ChefApi extends Closeable { void createDatabag(@BinderParam(BindNameToJsonPayload.class) String databagName); /** - * true is a databag exists - * - * @throws AuthorizationException - *

- * "401 Unauthorized" if you are not a recognized user. - *

- * "403 Forbidden" if you do not have view rights on the databag. - */ - @Named("databag:exists") - @HEAD - @Path("/data/{name}") - @Fallback(FalseOnNotFoundOr404.class) - boolean databagExists(@PathParam("name") String databagName); - - /** * Delete a data bag, including its items * * @throws AuthorizationException @@ -629,22 +571,6 @@ public interface ChefApi extends Closeable { @PathParam("databagItemId") @ParamParser(DatabagItemId.class) @BinderParam(BindToJsonPayload.class) DatabagItem item); /** - * determines if a databag item exists - * - * @throws AuthorizationException - *

- * "401 Unauthorized" if you are not a recognized user. - *

- * "403 Forbidden" if you do not have view rights on the databag. - */ - @Named("databag:itemexists") - @HEAD - @Path("/data/{databagName}/{databagItemId}") - @Fallback(FalseOnNotFoundOr404.class) - boolean databagItemExists(@PathParam("databagName") String databagName, - @PathParam("databagItemId") String databagItemId); - - /** * gets an existing databag item. * * @throws AuthorizationException @@ -853,6 +779,7 @@ public interface ChefApi extends Closeable { @Named("content:get") @GET @Fallback(NullOnNotFoundOr404.class) + @SkipEncoding({'+', ' ', '/', '=', ':', ';'}) InputStream getResourceContents(@EndpointParam(parser = UriForResource.class) Resource resource); /** diff --git a/core/src/main/java/org/jclouds/chef/config/ChefParserModule.java b/core/src/main/java/org/jclouds/chef/config/ChefParserModule.java index 7a92064..f7457fe 100644 --- a/core/src/main/java/org/jclouds/chef/config/ChefParserModule.java +++ b/core/src/main/java/org/jclouds/chef/config/ChefParserModule.java @@ -16,6 +16,8 @@ */ package org.jclouds.chef.config; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; @@ -45,13 +47,16 @@ import org.jclouds.crypto.Pems; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory; import org.jclouds.json.internal.NullHackJsonLiteralAdapter; import org.jclouds.rest.annotations.ApiVersion; import com.google.common.base.Charsets; import com.google.common.base.Function; +import com.google.common.base.Objects; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.common.io.ByteStreams; import com.google.gson.Gson; import com.google.gson.JsonDeserializationContext; @@ -59,6 +64,10 @@ import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.JsonReaderInternalAccess; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; import com.google.inject.AbstractModule; import com.google.inject.ImplementedBy; import com.google.inject.Provides; @@ -211,6 +220,82 @@ public class ChefParserModule extends AbstractModule { private String id; } + // The NullFilteringTypeAdapterFactories.MapTypeAdapter class is final. Do + // the same logic here + private static final class KeepLastRepeatedKeyMapTypeAdapter extends TypeAdapter> { + + protected final TypeAdapter keyAdapter; + protected final TypeAdapter valueAdapter; + + protected KeepLastRepeatedKeyMapTypeAdapter(TypeAdapter keyAdapter, TypeAdapter valueAdapter) { + this.keyAdapter = keyAdapter; + this.valueAdapter = valueAdapter; + nullSafe(); + } + + public void write(JsonWriter out, Map value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + out.beginObject(); + for (Map.Entry element : value.entrySet()) { + out.name(String.valueOf(element.getKey())); + valueAdapter.write(out, element.getValue()); + } + out.endObject(); + } + + public Map read(JsonReader in) throws IOException { + Map result = Maps.newHashMap(); + in.beginObject(); + while (in.hasNext()) { + JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in); + K name = keyAdapter.read(in); + V value = valueAdapter.read(in); + if (value != null) { + // If there are repeated keys, overwrite them to only keep the last one + result.put(name, value); + } + } + in.endObject(); + return ImmutableMap.copyOf(result); + } + + @Override + public int hashCode() { + return Objects.hashCode(keyAdapter, valueAdapter); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + KeepLastRepeatedKeyMapTypeAdapter that = KeepLastRepeatedKeyMapTypeAdapter.class.cast(obj); + return equal(this.keyAdapter, that.keyAdapter) && equal(this.valueAdapter, that.valueAdapter); + } + + @Override + public String toString() { + return toStringHelper(this).add("keyAdapter", keyAdapter).add("valueAdapter", valueAdapter).toString(); + } + } + + public static class KeepLastRepeatedKeyMapTypeAdapterFactory extends MapTypeAdapterFactory { + + public KeepLastRepeatedKeyMapTypeAdapterFactory() { + super(Map.class); + } + + @SuppressWarnings("unchecked") + @Override + protected TypeAdapter newAdapter(TypeAdapter keyAdapter, TypeAdapter valueAdapter) { + return (TypeAdapter) new KeepLastRepeatedKeyMapTypeAdapter(keyAdapter, valueAdapter); + } + } + @Provides @Singleton public Map provideCustomAdapterBindings(DataBagItemAdapter adapter, PrivateKeyAdapter privateAdapter, @@ -252,5 +337,6 @@ public class ChefParserModule extends AbstractModule { @Override protected void configure() { bind(DateAdapter.class).to(Iso8601DateAdapter.class); + bind(MapTypeAdapterFactory.class).to(KeepLastRepeatedKeyMapTypeAdapterFactory.class); } } diff --git a/core/src/main/java/org/jclouds/chef/domain/Attribute.java b/core/src/main/java/org/jclouds/chef/domain/Attribute.java index 38d10c6..a5fb25d 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Attribute.java +++ b/core/src/main/java/org/jclouds/chef/domain/Attribute.java @@ -16,48 +16,122 @@ */ package org.jclouds.chef.domain; +import static org.jclouds.chef.util.CollectionUtils.*; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; import java.util.List; import java.util.Set; import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.gson.annotations.SerializedName; /** - * Cookbook object. + * An attribute in a cookbook metadata. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Attribute { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String required; + private boolean calculated; + private ImmutableSet.Builder choice = ImmutableSet.builder(); + private JsonBall defaultValue; + private String type; + private ImmutableList.Builder recipes = ImmutableList.builder(); + private String displayName; + private String description; + + public Builder required(String required) { + this.required = checkNotNull(required, "required"); + return this; + } + + public Builder calculated(boolean calculated) { + this.calculated = calculated; + return this; + } + + public Builder choice(String choice) { + this.choice.add(checkNotNull(choice, "choice")); + return this; + } + + public Builder choices(Iterable choices) { + this.choice.addAll(checkNotNull(choices, "choices")); + return this; + } + + public Builder defaultValue(JsonBall defaultValue) { + this.defaultValue = checkNotNull(defaultValue, "defaultValue"); + return this; + } + + public Builder type(String type) { + this.type = checkNotNull(type, "type"); + return this; + } + + public Builder recipe(String recipe) { + this.recipes.add(checkNotNull(recipe, "recipe")); + return this; + } + + public Builder recipes(Iterable recipes) { + this.recipes.addAll(checkNotNull(recipes, "recipes")); + return this; + } + + public Builder displayName(String displayName) { + this.displayName = checkNotNull(displayName, "displayName"); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Attribute build() { + return new Attribute(required, calculated, choice.build(), defaultValue, type, recipes.build(), displayName, + description); + } + } - private String required; - private boolean calculated; - private List choice = Lists.newArrayList(); + private final String required; + private final boolean calculated; + private final Set choice; @SerializedName("default") - private JsonBall defaultValue; - private String type; - private List recipes = Lists.newArrayList(); + private final JsonBall defaultValue; + private final String type; + private final List recipes; @SerializedName("display_name") - private String displayName; - private String description; + private final String displayName; + private final String description; - public Attribute(String required, boolean calculated, Set choice, JsonBall defaultValue, String type, - List recipes, String displayName, String description) { + @ConstructorProperties({ "required", "calculated", "choice", "default", "type", "recipes", "display_name", + "description" }) + protected Attribute(String required, boolean calculated, @Nullable Set choice, JsonBall defaultValue, + String type, @Nullable List recipes, String displayName, String description) { this.required = required; this.calculated = calculated; - Iterables.addAll(this.choice, choice); + this.choice = copyOfOrEmpty(choice); this.defaultValue = defaultValue; this.type = type; - Iterables.addAll(this.recipes, recipes); + this.recipes = copyOfOrEmpty(recipes); this.displayName = displayName; this.description = description; } - public Attribute() { - } - public String getRequired() { return required; } @@ -66,7 +140,7 @@ public class Attribute { return calculated; } - public List getChoice() { + public Set getChoice() { return choice; } @@ -162,4 +236,3 @@ public class Attribute { } } - diff --git a/core/src/main/java/org/jclouds/chef/domain/BootstrapConfig.java b/core/src/main/java/org/jclouds/chef/domain/BootstrapConfig.java index 2c16514..22d8f36 100644 --- a/core/src/main/java/org/jclouds/chef/domain/BootstrapConfig.java +++ b/core/src/main/java/org/jclouds/chef/domain/BootstrapConfig.java @@ -17,14 +17,13 @@ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Iterables.addAll; import java.util.List; import org.jclouds.domain.JsonBall; import com.google.common.base.Optional; -import com.google.common.collect.Lists; +import com.google.common.collect.ImmutableList; /** * Configures how the nodes in a group will bootstrap. @@ -33,13 +32,12 @@ import com.google.common.collect.Lists; * @since 1.7 */ public class BootstrapConfig { - public static Builder builder() { return new Builder(); } public static class Builder { - private List runList = Lists.newArrayList(); + private ImmutableList.Builder runList = ImmutableList.builder(); private String environment; private JsonBall attribtues; @@ -47,7 +45,7 @@ public class BootstrapConfig { * Sets the run list that will be executed in the nodes of the group. */ public Builder runList(Iterable runList) { - addAll(this.runList, checkNotNull(runList, "runList")); + this.runList.addAll(checkNotNull(runList, "runList")); return this; } @@ -68,13 +66,14 @@ public class BootstrapConfig { } public BootstrapConfig build() { - return new BootstrapConfig(runList, Optional.fromNullable(environment), Optional.fromNullable(attribtues)); + return new BootstrapConfig(runList.build(), Optional.fromNullable(environment), + Optional.fromNullable(attribtues)); } } - private List runList = Lists.newArrayList(); - private Optional environment; - private Optional attribtues; + private final List runList; + private final Optional environment; + private final Optional attribtues; protected BootstrapConfig(List runList, Optional environment, Optional attribtues) { this.runList = checkNotNull(runList, "runList"); diff --git a/core/src/main/java/org/jclouds/chef/domain/ChecksumStatus.java b/core/src/main/java/org/jclouds/chef/domain/ChecksumStatus.java index ffe7e64..e1c77e9 100644 --- a/core/src/main/java/org/jclouds/chef/domain/ChecksumStatus.java +++ b/core/src/main/java/org/jclouds/chef/domain/ChecksumStatus.java @@ -16,26 +16,50 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.*; +import java.beans.ConstructorProperties; import java.net.URI; import com.google.gson.annotations.SerializedName; /** + * The checksum of an uploaded resource. * * @author Adrian Cole + * @author Ignasi Barrera */ public class ChecksumStatus { - private URI url; - @SerializedName("needs_upload") - private boolean needsUpload; + public static Builder builder() { + return new Builder(); + } - public ChecksumStatus(URI url, boolean needsUpload) { - this.url = url; - this.needsUpload = needsUpload; + public static class Builder { + private URI url; + private boolean needsUpload; + + public Builder url(URI url) { + this.url = checkNotNull(url, "url"); + return this; + } + + public Builder needsUpload(boolean needsUpload) { + this.needsUpload = needsUpload; + return this; + } + + public ChecksumStatus build() { + return new ChecksumStatus(url, needsUpload); + } } - public ChecksumStatus() { + private final URI url; + @SerializedName("needs_upload") + private final boolean needsUpload; + @ConstructorProperties({ "url", "needs_upload" }) + protected ChecksumStatus(URI url, boolean needsUpload) { + this.url = url; + this.needsUpload = needsUpload; } public URI getUrl() { @@ -47,11 +71,6 @@ public class ChecksumStatus { } @Override - public String toString() { - return "ChecksumStatus [needsUpload=" + needsUpload + ", url=" + url + "]"; - } - - @Override public int hashCode() { final int prime = 31; int result = 1; @@ -78,5 +97,9 @@ public class ChecksumStatus { return false; return true; } -} + @Override + public String toString() { + return "ChecksumStatus [needsUpload=" + needsUpload + ", url=" + url + "]"; + } +} diff --git a/core/src/main/java/org/jclouds/chef/domain/Client.java b/core/src/main/java/org/jclouds/chef/domain/Client.java index 47dc4e0..101638c 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Client.java +++ b/core/src/main/java/org/jclouds/chef/domain/Client.java @@ -16,6 +16,9 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.*; + +import java.beans.ConstructorProperties; import java.security.PrivateKey; import java.security.cert.X509Certificate; @@ -27,19 +30,73 @@ import com.google.gson.annotations.SerializedName; * Client object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Client { - private X509Certificate certificate; - @SerializedName("private_key") - private PrivateKey privateKey; - private String orgname; - private String clientname; - private String name; - private boolean validator; + public static Builder builder() { + return new Builder(); + } - // only for deserialization - Client() { + public static class Builder { + private X509Certificate certificate; + private PrivateKey privateKey; + private String orgname; + private String clientname; + private String name; + private boolean validator; + + public Builder certificate(X509Certificate certificate) { + this.certificate = checkNotNull(certificate, "certificate"); + return this; + } + + public Builder privateKey(PrivateKey privateKey) { + this.privateKey = checkNotNull(privateKey, "privateKey"); + return this; + } + + public Builder orgname(String orgname) { + this.orgname = checkNotNull(orgname, "orgname"); + return this; + } + + public Builder clientname(String clientname) { + this.clientname = checkNotNull(clientname, "clientname"); + return this; + } + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder isValidator(boolean validator) { + this.validator = validator; + return this; + } + + public Client build() { + return new Client(certificate, orgname, clientname, name, validator, privateKey); + } + } + private final X509Certificate certificate; + @SerializedName("private_key") + private final PrivateKey privateKey; + private final String orgname; + private final String clientname; + private final String name; + private final boolean validator; + + @ConstructorProperties({ "certificate", "orgname", "clientname", "name", "validator", "private_key" }) + protected Client(X509Certificate certificate, String orgname, String clientname, String name, boolean validator, + @Nullable PrivateKey privateKey) { + this.certificate = certificate; + this.orgname = orgname; + this.clientname = clientname; + this.name = name; + this.validator = validator; + this.privateKey = privateKey; } public PrivateKey getPrivateKey() { @@ -67,12 +124,6 @@ public class Client { } @Override - public String toString() { - return "[name=" + name + ", clientname=" + clientname + ", orgname=" + orgname + ", isValidator=" + validator - + ", certificate=" + certificate + ", privateKey=" + (privateKey != null) + "]"; - } - - @Override public int hashCode() { final int prime = 31; int result = 1; @@ -124,14 +175,11 @@ public class Client { return true; } - public Client(X509Certificate certificate, String orgname, String clientname, String name, boolean isValidator, - @Nullable PrivateKey privateKey) { - this.certificate = certificate; - this.orgname = orgname; - this.clientname = clientname; - this.name = name; - this.validator = isValidator; - this.privateKey = privateKey; + @Override + public String toString() { + return "Client [name=" + name + ", clientname=" + clientname + ", orgname=" + orgname + ", isValidator=" + + validator + ", certificate=" + certificate + ", privateKey=" + (privateKey == null ? "not " : "") + + "present]"; } } diff --git a/core/src/main/java/org/jclouds/chef/domain/CookbookDefinition.java b/core/src/main/java/org/jclouds/chef/domain/CookbookDefinition.java index 7b0dea2..6531f03 100644 --- a/core/src/main/java/org/jclouds/chef/domain/CookbookDefinition.java +++ b/core/src/main/java/org/jclouds/chef/domain/CookbookDefinition.java @@ -16,10 +16,16 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; import java.net.URI; import java.util.Set; -import com.google.common.collect.Sets; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; /** * Cookbook definition as returned by the Chef server >= 0.10.8. @@ -27,18 +33,41 @@ import com.google.common.collect.Sets; * @author Ignasi Barrera */ public class CookbookDefinition { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private URI url; + private ImmutableSet.Builder versions = ImmutableSet.builder(); + + public Builder url(URI url) { + this.url = checkNotNull(url, "url"); + return this; + } - private URI url; - private Set versions = Sets.newLinkedHashSet(); + public Builder version(Version version) { + this.versions.add(checkNotNull(version, "version")); + return this; + } - // only for deserialization - CookbookDefinition() { + public Builder versions(Iterable versions) { + this.versions.addAll(checkNotNull(versions, "versions")); + return this; + } + public CookbookDefinition build() { + return new CookbookDefinition(url, versions.build()); + } } - public CookbookDefinition(URI url, Set versions) { + private final URI url; + private final Set versions; + + @ConstructorProperties({ "url", "versions" }) + protected CookbookDefinition(URI url, @Nullable Set versions) { this.url = url; - this.versions = versions; + this.versions = copyOfOrEmpty(versions); } public URI getUrl() { @@ -86,15 +115,34 @@ public class CookbookDefinition { } public static class Version { - private URI url; - private String version; + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private URI url; + private String version; - // only for deserialization - Version() { + public Builder url(URI url) { + this.url = checkNotNull(url, "url"); + return this; + } + public Builder version(String version) { + this.version = checkNotNull(version, "version"); + return this; + } + + public Version build() { + return new Version(url, version); + } } - public Version(URI url, String version) { + private final URI url; + private final String version; + + @ConstructorProperties({ "url", "version" }) + protected Version(URI url, String version) { this.url = url; this.version = version; } diff --git a/core/src/main/java/org/jclouds/chef/domain/CookbookVersion.java b/core/src/main/java/org/jclouds/chef/domain/CookbookVersion.java index 9251bd1..5af929e 100644 --- a/core/src/main/java/org/jclouds/chef/domain/CookbookVersion.java +++ b/core/src/main/java/org/jclouds/chef/domain/CookbookVersion.java @@ -16,34 +16,174 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; import java.util.Set; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; import com.google.gson.annotations.SerializedName; /** * Cookbook object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class CookbookVersion { + public static Builder builder(String name, String version) { + return new Builder(name, version); + } + + public static class Builder { + private String cookbookName; + private ImmutableSet.Builder definitions = ImmutableSet.builder(); + private ImmutableSet.Builder attributes = ImmutableSet.builder(); + private ImmutableSet.Builder files = ImmutableSet.builder(); + private Metadata metadata = Metadata.builder().build(); + private ImmutableSet.Builder providers = ImmutableSet.builder(); + private ImmutableSet.Builder resources = ImmutableSet.builder(); + private ImmutableSet.Builder templates = ImmutableSet.builder(); + private ImmutableSet.Builder libraries = ImmutableSet.builder(); + private String version; + private ImmutableSet.Builder recipes = ImmutableSet.builder(); + private ImmutableSet.Builder rootFiles = ImmutableSet.builder(); + + public Builder(String name, String version) { + this.cookbookName = checkNotNull(name, "name"); + this.version = checkNotNull(version, "version"); + } + + public Builder cookbookName(String cookbookName) { + this.cookbookName = checkNotNull(cookbookName, "cookbookName"); + return this; + } + + public Builder definition(Resource definition) { + this.definitions.add(checkNotNull(definition, "definition")); + return this; + } + + public Builder definitions(Iterable definitions) { + this.definitions.addAll(checkNotNull(definitions, "definitions")); + return this; + } + + public Builder attribute(Attribute attribute) { + this.attributes.add(checkNotNull(attribute, "attribute")); + return this; + } + + public Builder attributes(Iterable attributes) { + this.attributes.addAll(checkNotNull(attributes, "attributes")); + return this; + } + + public Builder file(Resource file) { + this.files.add(checkNotNull(file, "file")); + return this; + } + + public Builder files(Iterable files) { + this.files.addAll(checkNotNull(files, "files")); + return this; + } + + public Builder metadata(Metadata metadata) { + this.metadata = checkNotNull(metadata, "metadata"); + return this; + } + + public Builder provider(Resource provider) { + this.providers.add(checkNotNull(provider, "provider")); + return this; + } + + public Builder providers(Iterable providers) { + this.providers.addAll(checkNotNull(providers, "providers")); + return this; + } + + public Builder resource(Resource resource) { + this.resources.add(checkNotNull(resource, "resource")); + return this; + } + + public Builder resources(Iterable resources) { + this.resources.addAll(checkNotNull(resources, "resources")); + return this; + } + + public Builder template(Resource template) { + this.templates.add(checkNotNull(template, "template")); + return this; + } - private String name; - private Set definitions = Sets.newLinkedHashSet(); - private Set attributes = Sets.newLinkedHashSet(); - private Set files = Sets.newLinkedHashSet(); - private Metadata metadata = new Metadata(); - private Set providers = Sets.newLinkedHashSet(); + public Builder templates(Iterable templates) { + this.templates.addAll(checkNotNull(templates, "templates")); + return this; + } + + public Builder library(Resource library) { + this.libraries.add(checkNotNull(library, "library")); + return this; + } + + public Builder libraries(Iterable libraries) { + this.libraries.addAll(checkNotNull(libraries, "libraries")); + return this; + } + + public Builder version(String version) { + this.version = checkNotNull(version, "version"); + return this; + } + + public Builder recipe(Resource recipe) { + this.recipes.add(checkNotNull(recipe, "recipe")); + return this; + } + + public Builder recipes(Iterable recipes) { + this.recipes.addAll(checkNotNull(recipes, "recipes")); + return this; + } + + public Builder rootFile(Resource rootFile) { + this.rootFiles.add(checkNotNull(rootFile, "rootFile")); + return this; + } + + public Builder rootFiles(Iterable rootFiles) { + this.rootFiles.addAll(checkNotNull(rootFiles, "rootFiles")); + return this; + } + + public CookbookVersion build() { + return new CookbookVersion(checkNotNull(cookbookName, "name") + "-" + checkNotNull(version, "version"), + definitions.build(), attributes.build(), files.build(), metadata, providers.build(), cookbookName, + resources.build(), templates.build(), libraries.build(), version, recipes.build(), rootFiles.build()); + } + } + + private final String name; + private final Set definitions; + private final Set attributes; + private final Set files; + private final Metadata metadata; + private final Set providers; @SerializedName("cookbook_name") - private String cookbookName; - private Set resources = Sets.newLinkedHashSet(); - private Set templates = Sets.newLinkedHashSet(); - private Set libraries = Sets.newLinkedHashSet(); - private String version; - private Set recipes = Sets.newLinkedHashSet(); + private final String cookbookName; + private final Set resources; + private final Set templates; + private final Set libraries; + private final String version; + private final Set recipes; @SerializedName("root_files") - private Set rootFiles = Sets.newLinkedHashSet(); + private final Set rootFiles; // internal @SerializedName("json_class") @@ -51,34 +191,25 @@ public class CookbookVersion { @SerializedName("chef_type") private String _chefType = "cookbook_version"; - public CookbookVersion(String cookbookName, String version) { - this.cookbookName = cookbookName; - this.version = version; - this.name = cookbookName + "-" + version; - } - - public CookbookVersion(String name, Set definitions, Set attributes, Set files, - Metadata metadata, Set providers, String cookbookName, Set resources, - Set templates, Set libraries, String version, Set recipes, - Set rootFiles) { + @ConstructorProperties({ "name", "definitions", "attributes", "files", "metadata", "providers", "cookbook_name", + "resources", "templates", "libraries", "version", "recipes", "root_files" }) + protected CookbookVersion(String name, @Nullable Set definitions, @Nullable Set attributes, + @Nullable Set files, Metadata metadata, @Nullable Set providers, String cookbookName, + @Nullable Set resources, @Nullable Set templates, @Nullable Set libraries, + String version, @Nullable Set recipes, @Nullable Set rootFiles) { this.name = name; - Iterables.addAll(this.definitions, definitions); - Iterables.addAll(this.attributes, attributes); - Iterables.addAll(this.files, files); + this.definitions = copyOfOrEmpty(definitions); + this.attributes = copyOfOrEmpty(attributes); + this.files = copyOfOrEmpty(files); this.metadata = metadata; - Iterables.addAll(this.providers, providers); + this.providers = copyOfOrEmpty(providers); this.cookbookName = cookbookName; - Iterables.addAll(this.resources, resources); - Iterables.addAll(this.templates, templates); - Iterables.addAll(this.libraries, libraries); + this.resources = copyOfOrEmpty(resources); + this.templates = copyOfOrEmpty(templates); + this.libraries = copyOfOrEmpty(libraries); this.version = version; - Iterables.addAll(this.recipes, recipes); - Iterables.addAll(this.rootFiles, rootFiles); - } - - // hidden but needs to be here for json deserialization to work - CookbookVersion() { - + this.recipes = copyOfOrEmpty(recipes); + this.rootFiles = copyOfOrEmpty(rootFiles); } public String getName() { diff --git a/core/src/main/java/org/jclouds/chef/domain/DatabagItem.java b/core/src/main/java/org/jclouds/chef/domain/DatabagItem.java index 8d253a5..9138b9f 100644 --- a/core/src/main/java/org/jclouds/chef/domain/DatabagItem.java +++ b/core/src/main/java/org/jclouds/chef/domain/DatabagItem.java @@ -21,8 +21,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import org.jclouds.domain.JsonBall; /** + * An item in a data bag. * * @author Adrian Cole + * @author Ignasi Barrera */ public class DatabagItem extends JsonBall { @@ -62,4 +64,3 @@ public class DatabagItem extends JsonBall { return id; } } - diff --git a/core/src/main/java/org/jclouds/chef/domain/Environment.java b/core/src/main/java/org/jclouds/chef/domain/Environment.java index d96caa7..f54208e 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Environment.java +++ b/core/src/main/java/org/jclouds/chef/domain/Environment.java @@ -16,48 +16,105 @@ */ package org.jclouds.chef.domain; -import com.google.common.collect.Maps; -import com.google.gson.annotations.SerializedName; -import org.jclouds.domain.JsonBall; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; +import java.beans.ConstructorProperties; import java.util.Map; +import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +/** + * An environment. + * + * @author Ignasi Barrera + */ public class Environment { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + private ImmutableMap.Builder attributes = ImmutableMap.builder(); + private ImmutableMap.Builder overrideAttributes = ImmutableMap.builder(); + private String description = ""; + private ImmutableMap.Builder cookbookVersions = ImmutableMap.builder(); + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder attribute(String key, JsonBall value) { + this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder attributes(Map attributes) { + this.attributes.putAll(checkNotNull(attributes, "attributes")); + return this; + } + + public Builder overrideAttribute(String key, JsonBall value) { + this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder overrideAttributes(Map overrideAttributes) { + this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); + return this; + } + + public Builder cookbookVersion(String key, String version) { + this.cookbookVersions.put(checkNotNull(key, "key"), checkNotNull(version, "version")); + return this; + } + + public Builder cookbookVersions(Map cookbookVersions) { + this.cookbookVersions.putAll(checkNotNull(cookbookVersions, "cookbookVersions")); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Environment build() { + return new Environment(name, attributes.build(), overrideAttributes.build(), description, + cookbookVersions.build()); + } + } - private String name; - @SerializedName("default_attributes") - private Map attributes = Maps.newLinkedHashMap(); + private final String name; + @SerializedName("default_attributes") + private final Map attributes; @SerializedName("override_attributes") - private Map overrideAttributes = Maps.newLinkedHashMap(); - private String description = ""; + private final Map overrideAttributes; + private final String description; @SerializedName("cookbook_versions") - private Map cookbookVersions = Maps.newLinkedHashMap(); + private final Map cookbookVersions; + // internal @SerializedName("json_class") - private String _jsonClass = "Chef::Environment"; + private final String _jsonClass = "Chef::Environment"; @SerializedName("chef_type") - private String _chefType = "environment"; + private final String _chefType = "environment"; - public Environment(String name, Map attributes, Map overrideAttributes, - String description, Map cookbookVersions) { + @ConstructorProperties({ "name", "default_attributes", "override_attributes", "description", "cookbook_versions" }) + protected Environment(String name, @Nullable Map attributes, + @Nullable Map overrideAttributes, String description, + @Nullable Map cookbookVersions) { this.name = name; - this.attributes.putAll(attributes); - this.overrideAttributes.putAll(overrideAttributes); + this.attributes = copyOfOrEmpty(attributes); + this.overrideAttributes = copyOfOrEmpty(overrideAttributes); this.description = description; - this.cookbookVersions.putAll(cookbookVersions); - } - - public Environment(String name, String description) { - this.name = name; - this.description = description; - } - - public Environment(String name) { - this(name, null); - } - - // hidden but needs to be here for json deserialization to work - Environment() { + this.cookbookVersions = copyOfOrEmpty(cookbookVersions); } public String getName() { @@ -82,17 +139,23 @@ public class Environment { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Environment that = (Environment) o; - if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) return false; + if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) + return false; if (cookbookVersions != null ? !cookbookVersions.equals(that.cookbookVersions) : that.cookbookVersions != null) return false; - if (description != null ? !description.equals(that.description) : that.description != null) return false; - if (!name.equals(that.name)) return false; - if (overrideAttributes != null ? !overrideAttributes.equals(that.overrideAttributes) : that.overrideAttributes != null) + if (description != null ? !description.equals(that.description) : that.description != null) + return false; + if (!name.equals(that.name)) + return false; + if (overrideAttributes != null ? !overrideAttributes.equals(that.overrideAttributes) + : that.overrideAttributes != null) return false; return true; @@ -110,12 +173,8 @@ public class Environment { @Override public String toString() { - return "[" + - "name='" + name + '\'' + - ", attributes=" + attributes + - ", overrideAttributes=" + overrideAttributes + - ", description='" + description + '\'' + - ", cookbookVersions=" + cookbookVersions + - ']'; + return "Environment [" + "name='" + name + '\'' + ", attributes=" + attributes + ", overrideAttributes=" + + overrideAttributes + ", description='" + description + '\'' + ", cookbookVersions=" + cookbookVersions + + ']'; } } diff --git a/core/src/main/java/org/jclouds/chef/domain/Metadata.java b/core/src/main/java/org/jclouds/chef/domain/Metadata.java index 2bc1044..0cfb66f 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Metadata.java +++ b/core/src/main/java/org/jclouds/chef/domain/Metadata.java @@ -16,63 +16,236 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; import java.util.Map; -import com.google.common.collect.Maps; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** - * Cookbook object. + * A metadata object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Metadata { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String license; + private String maintainer; + private ImmutableMap.Builder suggestions = ImmutableMap.builder(); + private ImmutableMap.Builder dependencies = ImmutableMap.builder(); + private String maintainerEmail; + private ImmutableMap.Builder conflicting = ImmutableMap.builder(); + private String description; + private ImmutableMap.Builder providing = ImmutableMap.builder(); + private ImmutableMap.Builder platforms = ImmutableMap.builder(); + private String version; + private ImmutableMap.Builder recipes = ImmutableMap.builder(); + private ImmutableMap.Builder replacing = ImmutableMap.builder(); + private String name; + private ImmutableMap.Builder groupings = ImmutableMap.builder(); + private String longDescription; + private ImmutableMap.Builder attributes = ImmutableMap.builder(); + private ImmutableMap.Builder recommendations = ImmutableMap.builder(); + + public Builder license(String license) { + this.license = checkNotNull(license, "license"); + return this; + } + + public Builder maintainer(String maintainer) { + this.maintainer = checkNotNull(maintainer, "maintainer"); + return this; + } + + public Builder suggestion(String key, String value) { + this.suggestions.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder suggestions(Map suggestions) { + this.suggestions.putAll(checkNotNull(suggestions, "suggestions")); + return this; + } + + public Builder dependency(String key, String value) { + this.dependencies.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder dependencies(Map dependencies) { + this.dependencies.putAll(checkNotNull(dependencies, "dependencies")); + return this; + } + + public Builder maintainerEmail(String maintainerEmail) { + this.maintainerEmail = checkNotNull(maintainerEmail, "maintainerEmail"); + return this; + } + + public Builder conflicting(String key, String value) { + this.conflicting.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder conflicting(Map conflicting) { + this.conflicting.putAll(checkNotNull(conflicting, "conflicting")); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Builder providing(String key, String value) { + this.providing.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder providing(Map providing) { + this.providing.putAll(checkNotNull(providing, "providing")); + return this; + } + + public Builder platform(String key, String value) { + this.platforms.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder platforms(Map platforms) { + this.platforms.putAll(checkNotNull(platforms, "platforms")); + return this; + } + + public Builder version(String version) { + this.version = checkNotNull(version, "version"); + return this; + } - private String license; - private String maintainer; - private Map suggestions = Maps.newLinkedHashMap(); - private Map dependencies = Maps.newLinkedHashMap(); + public Builder recipe(String key, String value) { + this.recipes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder recipes(Map recipes) { + this.recipes.putAll(checkNotNull(recipes, "recipes")); + return this; + } + + public Builder replacing(String key, String value) { + this.replacing.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder replacing(Map replacing) { + this.replacing.putAll(checkNotNull(replacing, "replacing")); + return this; + } + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder grouping(String key, String value) { + this.groupings.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder grouping(Map groupings) { + this.groupings.putAll(checkNotNull(groupings, "groupings")); + return this; + } + + public Builder longDescription(String longDescription) { + this.longDescription = checkNotNull(longDescription, "longDescription"); + return this; + } + + public Builder attribute(String key, Attribute value) { + this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder attributes(Map attributes) { + this.attributes.putAll(checkNotNull(attributes, "attributes")); + return this; + } + + public Builder recommendation(String key, String value) { + this.recommendations.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder recommendations(Map recommendations) { + this.recommendations.putAll(checkNotNull(recommendations, "recommendations")); + return this; + } + + public Metadata build() { + return new Metadata(license, maintainer, suggestions.build(), dependencies.build(), maintainerEmail, + conflicting.build(), description, providing.build(), platforms.build(), version, recipes.build(), + replacing.build(), name, groupings.build(), longDescription, attributes.build(), recommendations.build()); + } + + } + + private final String license; + private final String maintainer; + private final Map suggestions; + private final Map dependencies; @SerializedName("maintainer_email") - private String maintainerEmail; - private Map conflicting = Maps.newLinkedHashMap(); - private String description; - private Map providing = Maps.newLinkedHashMap(); - private Map platforms = Maps.newLinkedHashMap(); - private String version; - private Map recipes = Maps.newLinkedHashMap(); - private Map replacing = Maps.newLinkedHashMap(); - private String name; - private Map groupings = Maps.newLinkedHashMap(); + private final String maintainerEmail; + private final Map conflicting; + private final String description; + private final Map providing; + private final Map platforms; + private final String version; + private final Map recipes; + private final Map replacing; + private final String name; + private final Map groupings; @SerializedName("long_description") - private String longDescription; - private Map attributes = Maps.newLinkedHashMap(); - private Map recommendations = Maps.newLinkedHashMap(); - - public Metadata(String license, String maintainer, Map suggestions, - Map dependencies, String maintainerEmail, Map conflicting, String description, - Map providing, Map platforms, String version, Map recipes, - Map replacing, String name, Map groupings, String longDescription, - Map attributes, Map recommendations) { + private final String longDescription; + private final Map attributes; + private final Map recommendations; + + @ConstructorProperties({ "license", "maintainer", "suggestions", "dependencies", "maintainer_email", "conflicting", + "description", "providing", "platforms", "version", "recipes", "replacing", "name", "groupings", + "long_description", "attributes", "recommendations" }) + protected Metadata(String license, String maintainer, @Nullable Map suggestions, + @Nullable Map dependencies, String maintainerEmail, @Nullable Map conflicting, + String description, @Nullable Map providing, @Nullable Map platforms, + String version, @Nullable Map recipes, @Nullable Map replacing, String name, + @Nullable Map groupings, String longDescription, @Nullable Map attributes, + @Nullable Map recommendations) { this.license = license; this.maintainer = maintainer; - this.suggestions.putAll(suggestions); - this.dependencies.putAll(dependencies); + this.suggestions = copyOfOrEmpty(suggestions); + this.dependencies = copyOfOrEmpty(dependencies); this.maintainerEmail = maintainerEmail; - this.conflicting.putAll(conflicting); + this.conflicting = copyOfOrEmpty(conflicting); this.description = description; - this.providing.putAll(providing); - this.platforms.putAll(platforms); + this.providing = copyOfOrEmpty(providing); + this.platforms = copyOfOrEmpty(platforms); this.version = version; - this.recipes.putAll(recipes); - this.replacing.putAll(replacing); + this.recipes = copyOfOrEmpty(recipes); + this.replacing = copyOfOrEmpty(replacing); this.name = name; - this.groupings.putAll(groupings); + this.groupings = copyOfOrEmpty(groupings); this.longDescription = longDescription; - this.attributes.putAll(attributes); - this.recommendations.putAll(recommendations); - } - - public Metadata() { + this.attributes = copyOfOrEmpty(attributes); + this.recommendations = copyOfOrEmpty(recommendations); } public String getLicense() { @@ -275,4 +448,3 @@ public class Metadata { } } - diff --git a/core/src/main/java/org/jclouds/chef/domain/Node.java b/core/src/main/java/org/jclouds/chef/domain/Node.java index 83cd5a8..4d4fa0f 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Node.java +++ b/core/src/main/java/org/jclouds/chef/domain/Node.java @@ -16,109 +16,160 @@ */ package org.jclouds.chef.domain; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.gson.annotations.SerializedName; -import org.jclouds.domain.JsonBall; -import org.jclouds.javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; +import java.beans.ConstructorProperties; import java.util.List; import java.util.Map; +import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + /** - * Sandbox object. + * Node object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Node { + public static Builder builder() { + return new Builder(); + } - private String name; - private Map normal = Maps.newLinkedHashMap(); - private Map override = Maps.newLinkedHashMap(); - @SerializedName("default") - private Map defaultA = Maps.newLinkedHashMap(); - private Map automatic = Maps.newLinkedHashMap(); - @SerializedName("run_list") - private List runList = Lists.newArrayList(); + public static class Builder { + private String name; + private ImmutableMap.Builder normalAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder overrideAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder defaultAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder automaticAttributes = ImmutableMap.builder(); + private ImmutableList.Builder runList = ImmutableList.builder(); + private String environment; - /** - * @since chef 0.10 - */ - @SerializedName("chef_environment") - @Nullable - private String chefEnvironment; + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } - // internal - @SerializedName("json_class") - private String _jsonClass = "Chef::Node"; + public Builder normalAttribute(String key, JsonBall value) { + this.normalAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + public Builder normalAttributes(Map normalAttributes) { + this.normalAttributes.putAll(checkNotNull(normalAttributes, "normalAttributes")); + return this; + } - @SerializedName("chef_type") - private String _chefType = "node"; + public Builder overrideAttribute(String key, JsonBall value) { + this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } - public Node(String name, Map normal, Map override, - Map defaultA, Map automatic, Iterable runList) { - this(name, normal, override, defaultA, automatic, runList, null); - } + public Builder overrideAttributes(Map overrideAttributes) { + this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); + return this; + } - /** - * @since chef 0.10 - */ - public Node(String name, Map normal, Map override, - Map defaultA, Map automatic, Iterable runList, - String chefEnvironment) { - this.name = name; - this.chefEnvironment = chefEnvironment; - this.normal.putAll(normal); - this.override.putAll(override); - this.defaultA.putAll(defaultA); - this.automatic.putAll(automatic); - Iterables.addAll(this.runList, runList); - } + public Builder defaultAttribute(String key, JsonBall value) { + this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } - @Override - public String toString() { - return "Node [name=" + name + ", runList=" + runList + ", normal=" + normal + ", default=" + defaultA - + ", override=" + override + ", chefEnvironment=" + chefEnvironment + ", automatic=" + automatic + "]"; - } + public Builder defaultAttributes(Map defaultAttributes) { + this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes")); + return this; + } - public Node(String name, Iterable runList) { - this(name, runList, "_default"); - } + public Builder automaticAttribute(String key, JsonBall value) { + this.automaticAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } - /** - * @since chef 0.10 - */ - public Node(String name, Iterable runList, String chefEnvironment) { - this.name = name; - this.chefEnvironment = chefEnvironment; - Iterables.addAll(this.runList, runList); + public Builder automaticAttributes(Map automaticAttribute) { + this.automaticAttributes.putAll(checkNotNull(automaticAttribute, "automaticAttribute")); + return this; + } + + public Builder runListElement(String element) { + this.runList.add(checkNotNull(element, "element")); + return this; + } + + public Builder runList(Iterable runList) { + this.runList.addAll(checkNotNull(runList, "runList")); + return this; + } + + /** + * @since Chef 0.10 + */ + public Builder environment(String environment) { + this.environment = checkNotNull(environment, "environment"); + return this; + } + + public Node build() { + return new Node(name, normalAttributes.build(), overrideAttributes.build(), defaultAttributes.build(), + automaticAttributes.build(), runList.build(), environment); + } } - // hidden but needs to be here for json deserialization to work - Node() { + private final String name; + @SerializedName("normal") + private final Map normalAttributes; + @SerializedName("override") + private final Map overrideAttributes; + @SerializedName("default") + private final Map defaultAttributes; + @SerializedName("automatic") + private final Map automaticAttributes; + @SerializedName("run_list") + private final List runList; + @SerializedName("chef_environment") + private final String environment; + + // internal + @SerializedName("json_class") + private final String _jsonClass = "Chef::Node"; + @SerializedName("chef_type") + private final String _chefType = "node"; + @ConstructorProperties({ "name", "normal", "override", "default", "automatic", "run_list", "chef_environment" }) + protected Node(String name, @Nullable Map normalAttributes, + @Nullable Map overrideAttributes, @Nullable Map defaultAttributes, + @Nullable Map automaticAttributes, List runList, @Nullable String environment) { + this.name = name; + this.environment = environment; + this.normalAttributes = copyOfOrEmpty(normalAttributes); + this.overrideAttributes = copyOfOrEmpty(overrideAttributes); + this.defaultAttributes = copyOfOrEmpty(defaultAttributes); + this.automaticAttributes = copyOfOrEmpty(automaticAttributes); + this.runList = copyOfOrEmpty(runList); } public String getName() { return name; } - public Map getNormal() { - return normal; + public Map getNormalAttributes() { + return normalAttributes; } - public Map getOverride() { - return override; + public Map getOverrideAttributes() { + return overrideAttributes; } - public Map getDefault() { - return defaultA; + public Map getDefaultAttributes() { + return defaultAttributes; } - public Map getAutomatic() { - return automatic; + public Map getAutomaticAttributes() { + return automaticAttributes; } public List getRunList() { @@ -126,10 +177,10 @@ public class Node { } /** - * @since chef 0.10 + * @since Chef 0.10 */ - public String getChefEnvironment() { - return chefEnvironment; + public String getEnvironment() { + return environment; } @Override @@ -138,13 +189,13 @@ public class Node { int result = 1; result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode()); result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode()); - result = prime * result + ((automatic == null) ? 0 : automatic.hashCode()); - result = prime * result + ((defaultA == null) ? 0 : defaultA.hashCode()); + result = prime * result + ((automaticAttributes == null) ? 0 : automaticAttributes.hashCode()); + result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((normal == null) ? 0 : normal.hashCode()); - result = prime * result + ((override == null) ? 0 : override.hashCode()); + result = prime * result + ((normalAttributes == null) ? 0 : normalAttributes.hashCode()); + result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode()); result = prime * result + ((runList == null) ? 0 : runList.hashCode()); - result = prime * result + ((chefEnvironment == null) ? 0 : chefEnvironment.hashCode()); + result = prime * result + ((environment == null) ? 0 : environment.hashCode()); return result; } @@ -167,42 +218,49 @@ public class Node { return false; } else if (!_jsonClass.equals(other._jsonClass)) return false; - if (automatic == null) { - if (other.automatic != null) + if (automaticAttributes == null) { + if (other.automaticAttributes != null) return false; - } else if (!automatic.equals(other.automatic)) + } else if (!automaticAttributes.equals(other.automaticAttributes)) return false; - if (defaultA == null) { - if (other.defaultA != null) + if (defaultAttributes == null) { + if (other.defaultAttributes != null) return false; - } else if (!defaultA.equals(other.defaultA)) + } else if (!defaultAttributes.equals(other.defaultAttributes)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; - if (normal == null) { - if (other.normal != null) + if (normalAttributes == null) { + if (other.normalAttributes != null) return false; - } else if (!normal.equals(other.normal)) + } else if (!normalAttributes.equals(other.normalAttributes)) return false; - if (override == null) { - if (other.override != null) + if (overrideAttributes == null) { + if (other.overrideAttributes != null) return false; - } else if (!override.equals(other.override)) + } else if (!overrideAttributes.equals(other.overrideAttributes)) return false; if (runList == null) { if (other.runList != null) return false; } else if (!runList.equals(other.runList)) return false; - if (chefEnvironment == null) { - if (other.chefEnvironment != null) + if (environment == null) { + if (other.environment != null) return false; - } else if (!chefEnvironment.equals(other.chefEnvironment)) + } else if (!environment.equals(other.environment)) return false; return true; } + @Override + public String toString() { + return "Node [name=" + name + ", runList=" + runList + ", normalAttributes=" + normalAttributes + + ", defaultAttributes=" + defaultAttributes + ", overrideAttributes=" + overrideAttributes + + ", chefEnvironment=" + environment + ", automaticAttributes=" + automaticAttributes + "]"; + } + } diff --git a/core/src/main/java/org/jclouds/chef/domain/Resource.java b/core/src/main/java/org/jclouds/chef/domain/Resource.java index 687a468..15ac613 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Resource.java +++ b/core/src/main/java/org/jclouds/chef/domain/Resource.java @@ -16,6 +16,9 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.*; + +import java.beans.ConstructorProperties; import java.net.URI; import java.util.Arrays; @@ -24,28 +27,69 @@ import org.jclouds.io.payloads.FilePayload; import com.google.common.primitives.Bytes; /** - * Cookbook object. + * Resource object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Resource { - - private String name; - private URI url; - private byte[] checksum; - private String path; - private String specificity; - - public Resource(FilePayload payload) { - this(payload.getRawContent().getName(), null, payload.getContentMetadata().getContentMD5(), payload - .getRawContent().getPath(), "default"); + public static Builder builder() { + return new Builder(); } - public Resource(String name, byte[] checksum, String path) { - this(name, null, checksum, path, "default"); + public static class Builder { + private String name; + private URI url; + private byte[] checksum; + private String path; + private String specificity = "default"; + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder url(URI url) { + this.url = checkNotNull(url, "url"); + return this; + } + + public Builder checksum(byte[] checksum) { + this.checksum = checkNotNull(checksum, "checksum"); + return this; + } + + public Builder path(String path) { + this.path = checkNotNull(path, "path"); + return this; + } + + public Builder specificity(String specificity) { + this.specificity = checkNotNull(specificity, "specificity"); + return this; + } + + public Builder fromPayload(FilePayload payload) { + checkNotNull(payload, "payload"); + this.name(payload.getRawContent().getName()); + this.checksum(payload.getContentMetadata().getContentMD5()); + this.path(payload.getRawContent().getPath()); + return this; + } + + public Resource build() { + return new Resource(name, url, checksum, path, specificity); + } } - public Resource(String name, URI url, byte[] checksum, String path, String specificity) { + private final String name; + private final URI url; + private final byte[] checksum; + private final String path; + private final String specificity; + + @ConstructorProperties({ "name", "url", "checksum", "path", "specificity" }) + protected Resource(String name, URI url, byte[] checksum, String path, String specificity) { this.name = name; this.url = url; this.checksum = checksum; @@ -53,10 +97,6 @@ public class Resource { this.specificity = specificity; } - // hidden but needs to be here for json deserialization to work - Resource() { - } - public String getName() { return name; } @@ -130,4 +170,3 @@ public class Resource { } } - diff --git a/core/src/main/java/org/jclouds/chef/domain/Role.java b/core/src/main/java/org/jclouds/chef/domain/Role.java index 95d91f1..1b73609 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Role.java +++ b/core/src/main/java/org/jclouds/chef/domain/Role.java @@ -16,55 +16,106 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; import java.util.List; import java.util.Map; import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** - * Sandbox object. + * Role object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Role { + public static Builder builder() { + return new Builder(); + } - private String name; - private String description; + public static class Builder { + private String name; + private String description; + private ImmutableMap.Builder overrideAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder defaultAttributes = ImmutableMap.builder(); + private ImmutableList.Builder runList = ImmutableList.builder(); + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Builder overrideAttribute(String key, JsonBall value) { + this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder overrideAttributes(Map overrideAttributes) { + this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); + return this; + } + + public Builder defaultAttribute(String key, JsonBall value) { + this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder defaultAttributes(Map defaultAttributes) { + this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes")); + return this; + } + + public Builder runListElement(String element) { + this.runList.add(checkNotNull(element, "element")); + return this; + } + + public Builder runList(Iterable runList) { + this.runList.addAll(checkNotNull(runList, "runList")); + return this; + } + + public Role build() { + return new Role(name, description, defaultAttributes.build(), runList.build(), overrideAttributes.build()); + } + } + + private final String name; + private final String description; @SerializedName("override_attributes") - private Map override = Maps.newLinkedHashMap(); + private final Map overrideAttributes; @SerializedName("default_attributes") - private Map defaultA = Maps.newLinkedHashMap(); + private final Map defaultAttributes; @SerializedName("run_list") - private List runList = Lists.newArrayList(); + private final List runList; // internal @SerializedName("json_class") - private String _jsonClass = "Chef::Role"; + private final String _jsonClass = "Chef::Role"; @SerializedName("chef_type") - private String _chefType = "role"; + private final String _chefType = "role"; - public Role(String name, String description, Map defaultA, List runList, - Map override) { + @ConstructorProperties({ "name", "description", "default_attributes", "run_list", "override_attributes" }) + protected Role(String name, String description, @Nullable Map defaultAttributes, + @Nullable List runList, @Nullable Map overrideAttributes) { this.name = name; this.description = description; - this.defaultA = defaultA; - this.runList = runList; - this.override = override; - } - - public Role(String name, Iterable runList) { - this.name = name; - Iterables.addAll(this.runList, runList); - } - - // hidden but needs to be here for json deserialization to work - Role() { - + this.defaultAttributes = copyOfOrEmpty(defaultAttributes); + this.runList = copyOfOrEmpty(runList); + this.overrideAttributes = copyOfOrEmpty(overrideAttributes); } public String getName() { @@ -75,12 +126,12 @@ public class Role { return description; } - public Map getOverride() { - return override; + public Map getOverrideAttributes() { + return overrideAttributes; } - public Map getDefault() { - return defaultA; + public Map getDefaultAttributes() { + return defaultAttributes; } public List getRunList() { @@ -93,10 +144,10 @@ public class Role { int result = 1; result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode()); result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode()); - result = prime * result + ((defaultA == null) ? 0 : defaultA.hashCode()); + result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((override == null) ? 0 : override.hashCode()); + result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode()); result = prime * result + ((runList == null) ? 0 : runList.hashCode()); return result; } @@ -120,10 +171,10 @@ public class Role { return false; } else if (!_jsonClass.equals(other._jsonClass)) return false; - if (defaultA == null) { - if (other.defaultA != null) + if (defaultAttributes == null) { + if (other.defaultAttributes != null) return false; - } else if (!defaultA.equals(other.defaultA)) + } else if (!defaultAttributes.equals(other.defaultAttributes)) return false; if (description == null) { if (other.description != null) @@ -135,10 +186,10 @@ public class Role { return false; } else if (!name.equals(other.name)) return false; - if (override == null) { - if (other.override != null) + if (overrideAttributes == null) { + if (other.overrideAttributes != null) return false; - } else if (!override.equals(other.override)) + } else if (!overrideAttributes.equals(other.overrideAttributes)) return false; if (runList == null) { if (other.runList != null) @@ -150,8 +201,8 @@ public class Role { @Override public String toString() { - return "[name=" + name + ", description=" + description + ", defaultA=" + defaultA + ", override=" + override - + ", runList=" + runList + "]"; + return "Role [name=" + name + ", description=" + description + ", defaultAttributes=" + defaultAttributes + + ", overrideAttributes=" + overrideAttributes + ", runList=" + runList + "]"; } } diff --git a/core/src/main/java/org/jclouds/chef/domain/Sandbox.java b/core/src/main/java/org/jclouds/chef/domain/Sandbox.java index 98c8c96..774aa4a 100644 --- a/core/src/main/java/org/jclouds/chef/domain/Sandbox.java +++ b/core/src/main/java/org/jclouds/chef/domain/Sandbox.java @@ -16,49 +16,104 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; import java.util.Date; import java.util.Set; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; import com.google.gson.annotations.SerializedName; /** * Sandbox object. * * @author Adrian Cole + * @author Ignasi Barrera */ public class Sandbox { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String rev; + private boolean isCompleted; + private Date createTime; + private ImmutableSet.Builder checksums = ImmutableSet.builder(); + private String name; + private String guid; + + public Builder rev(String rev) { + this.rev = checkNotNull(rev, "rev"); + return this; + } + + public Builder isCompleted(boolean isCompleted) { + this.isCompleted = isCompleted; + return this; + } + + public Builder createTime(Date createTime) { + this.createTime = createTime; + return this; + } + + public Builder checksum(String checksum) { + this.checksums.add(checkNotNull(checksum, "checksum")); + return this; + } + + public Builder checksums(Iterable checksums) { + this.checksums.addAll(checkNotNull(checksums, "checksums")); + return this; + } + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder guid(String guid) { + this.guid = checkNotNull(guid, "guid"); + return this; + } + + public Sandbox build() { + return new Sandbox(rev, isCompleted, createTime, checksums.build(), name, guid); + } + } @SerializedName("_rev") - private String rev; + private final String rev; @SerializedName("is_completed") - private boolean isCompleted; + private final boolean isCompleted; @SerializedName("create_time") - private Date createTime; - private Set checksums = Sets.newLinkedHashSet(); - private String name; - private String guid; + private final Date createTime; + private final Set checksums; + private final String name; + private final String guid; // internal @SerializedName("json_class") - private String _jsonClass = "Chef::Sandbox"; + private final String _jsonClass = "Chef::Sandbox"; @SerializedName("chef_type") - private String _chefType = "sandbox"; + private final String _chefType = "sandbox"; - public Sandbox(String rev, boolean isCompleted, Date createTime, Iterable checksums, String name, String guid) { + @ConstructorProperties({ "_rev", "is_completed", "create_time", "checksums", "name", "guid" }) + protected Sandbox(String rev, boolean isCompleted, Date createTime, @Nullable Set checksums, String name, + String guid) { this.rev = rev; this.isCompleted = isCompleted; this.createTime = createTime; - Iterables.addAll(this.checksums, checksums); + this.checksums = copyOfOrEmpty(checksums); this.name = name; this.guid = guid; } - public Sandbox() { - - } - public String getRev() { return rev; } @@ -141,4 +196,3 @@ public class Sandbox { + isCompleted + ", name=" + name + ", rev=" + rev + "]"; } } - diff --git a/core/src/main/java/org/jclouds/chef/domain/SearchResult.java b/core/src/main/java/org/jclouds/chef/domain/SearchResult.java index 91222a2..1e2cced 100644 --- a/core/src/main/java/org/jclouds/chef/domain/SearchResult.java +++ b/core/src/main/java/org/jclouds/chef/domain/SearchResult.java @@ -21,11 +21,13 @@ import java.util.LinkedHashSet; import com.google.common.collect.Iterables; /** + * A result of a search. * * @author Adrian Cole - * + * @author Ignasi Barrera */ public class SearchResult extends LinkedHashSet { + private static final long serialVersionUID = 4000610660948065287L; private long start; SearchResult() { @@ -36,8 +38,6 @@ public class SearchResult extends LinkedHashSet { Iterables.addAll(this, results); } - private static final long serialVersionUID = 4000610660948065287L; - /** * * @return the result position this started from from @@ -47,4 +47,3 @@ public class SearchResult extends LinkedHashSet { } } - diff --git a/core/src/main/java/org/jclouds/chef/domain/UploadSandbox.java b/core/src/main/java/org/jclouds/chef/domain/UploadSandbox.java index f9bd6f1..868c147 100644 --- a/core/src/main/java/org/jclouds/chef/domain/UploadSandbox.java +++ b/core/src/main/java/org/jclouds/chef/domain/UploadSandbox.java @@ -16,31 +16,70 @@ */ package org.jclouds.chef.domain; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; import java.net.URI; import java.util.List; import java.util.Map; -import com.google.common.collect.Maps; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** + * An upload sandbox. * * @author Adrian Cole + * @author Ignasi Barrera */ public class UploadSandbox { - private URI uri; - private Map, ChecksumStatus> checksums = Maps.newLinkedHashMap(); - @SerializedName("sandbox_id") - private String sandboxId; + public static Builder builder() { + return new Builder(); + } - public UploadSandbox(URI uri, Map, ChecksumStatus> checksums, String sandboxId) { - this.uri = uri; - this.checksums.putAll(checksums); - this.sandboxId = sandboxId; + public static class Builder { + private URI uri; + private ImmutableMap.Builder, ChecksumStatus> checksums = ImmutableMap.builder(); + private String sandboxId; + + public Builder uri(URI uri) { + this.uri = checkNotNull(uri, "uri"); + return this; + } + + public Builder checksum(List key, ChecksumStatus value) { + this.checksums.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder checksums(Map, ChecksumStatus> checksums) { + this.checksums.putAll(checkNotNull(checksums, "checksums")); + return this; + } + + public Builder sandboxId(String sandboxId) { + this.sandboxId = checkNotNull(sandboxId, "sandboxId"); + return this; + } + + public UploadSandbox build() { + return new UploadSandbox(uri, checksums.build(), sandboxId); + } } - public UploadSandbox() { + private final URI uri; + private final Map, ChecksumStatus> checksums; + @SerializedName("sandbox_id") + private final String sandboxId; + @ConstructorProperties({ "uri", "checksums", "sandbox_id" }) + protected UploadSandbox(URI uri, @Nullable Map, ChecksumStatus> checksums, String sandboxId) { + this.uri = uri; + this.checksums = copyOfOrEmpty(checksums); + this.sandboxId = sandboxId; } public URI getUri() { @@ -94,8 +133,7 @@ public class UploadSandbox { @Override public String toString() { - return "UploadSite [checksums=" + checksums + ", id=" + sandboxId + ", uri=" + uri + "]"; + return "UploadSandbox [checksums=" + checksums + ", id=" + sandboxId + ", uri=" + uri + "]"; } } - diff --git a/core/src/main/java/org/jclouds/chef/functions/ClientForGroup.java b/core/src/main/java/org/jclouds/chef/functions/ClientForGroup.java index f51b7a2..a9c1c33 100644 --- a/core/src/main/java/org/jclouds/chef/functions/ClientForGroup.java +++ b/core/src/main/java/org/jclouds/chef/functions/ClientForGroup.java @@ -49,7 +49,12 @@ public class ClientForGroup implements Function { String clientName = findNextClientName(chefApi.listClients(), from + "-client-%02d"); Client client = chefApi.createClient(clientName); // response from create only includes the key - return new Client(null, null, clientName, clientName, false, client.getPrivateKey()); + return Client.builder() // + .clientname(clientName) // + .name(clientName) // + .isValidator(false) // + .privateKey(client.getPrivateKey()) // + .build(); } private static String findNextClientName(Set clients, String pattern) { diff --git a/core/src/main/java/org/jclouds/chef/strategy/internal/CleanupStaleNodesAndClientsImpl.java b/core/src/main/java/org/jclouds/chef/strategy/internal/CleanupStaleNodesAndClientsImpl.java index 28d4e1b..a3ef7c2 100644 --- a/core/src/main/java/org/jclouds/chef/strategy/internal/CleanupStaleNodesAndClientsImpl.java +++ b/core/src/main/java/org/jclouds/chef/strategy/internal/CleanupStaleNodesAndClientsImpl.java @@ -82,7 +82,7 @@ public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClie }), and(notNull(), new Predicate() { @Override public boolean apply(Node input) { - JsonBall dateLong = input.getAutomatic().get("ohai_time"); + JsonBall dateLong = input.getAutomaticAttributes().get("ohai_time"); if (dateLong == null) return true; Calendar nodeUpdate = Calendar.getInstance(); diff --git a/core/src/main/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImpl.java b/core/src/main/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImpl.java index 54de5e7..d6336b2 100644 --- a/core/src/main/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImpl.java +++ b/core/src/main/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImpl.java @@ -61,14 +61,25 @@ public class CreateNodeAndPopulateAutomaticAttributesImpl implements CreateNodeA @Override public Node execute(Node node) { logger.trace("creating node %s", node.getName()); - node.getAutomatic().putAll(automaticSupplier.get()); - chef.createNode(node); - logger.debug("created node %s", node.getName()); + Node withAutomatic = Node.builder() // + .name(node.getName()) // + .normalAttributes(node.getNormalAttributes()) // + .overrideAttributes(node.getOverrideAttributes()) // + .defaultAttributes(node.getDefaultAttributes()) // + .automaticAttributes(node.getAutomaticAttributes()) // + .automaticAttributes(automaticSupplier.get()) // + .runList(node.getRunList()) // + .environment(node.getEnvironment()) // + .build(); + + + chef.createNode(withAutomatic); + logger.debug("created node %s", withAutomatic.getName()); return node; } @Override public Node execute(String nodeName, Iterable runList) { - return execute(new Node(nodeName, runList, "_default")); + return execute(Node.builder().name(nodeName).runList(runList).environment("_default").build()); } } diff --git a/core/src/main/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImpl.java b/core/src/main/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImpl.java index e1af597..4d9bea4 100644 --- a/core/src/main/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImpl.java +++ b/core/src/main/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImpl.java @@ -61,9 +61,17 @@ public class UpdateAutomaticAttributesOnNodeImpl implements UpdateAutomaticAttri public void execute(String nodeName) { logger.trace("updating node %s", nodeName); Node node = chef.getNode(nodeName); - Node mutable = new Node(node.getName(), node.getNormal(), node.getOverride(), node.getDefault(), - automaticSupplier.get(), node.getRunList(), node.getChefEnvironment()); - chef.updateNode(mutable); + Node updated = Node.builder() // + .name(node.getName()) // + .normalAttributes(node.getNormalAttributes()) // + .overrideAttributes(node.getOverrideAttributes()) // + .defaultAttributes(node.getDefaultAttributes()) // + .automaticAttributes(automaticSupplier.get()) // + .runList(node.getRunList()) // + .environment(node.getEnvironment()) // + .build(); + + chef.updateNode(updated); logger.debug("updated node %s", nodeName); } } diff --git a/core/src/main/java/org/jclouds/chef/test/TransientChefApi.java b/core/src/main/java/org/jclouds/chef/test/TransientChefApi.java index 70a17d9..908ae2f 100644 --- a/core/src/main/java/org/jclouds/chef/test/TransientChefApi.java +++ b/core/src/main/java/org/jclouds/chef/test/TransientChefApi.java @@ -104,11 +104,6 @@ public class TransientChefApi implements ChefApi { } @Override - public boolean clientExists(String clientname) { - throw new UnsupportedOperationException(); - } - - @Override public Sandbox commitSandbox(String id, boolean isCompleted) { throw new UnsupportedOperationException(); } @@ -146,16 +141,6 @@ public class TransientChefApi implements ChefApi { } @Override - public boolean databagExists(String databagName) { - return databags.containerExists(databagName); - } - - @Override - public boolean databagItemExists(String databagName, String databagItemId) { - return databags.blobExists(databagName, databagItemId); - } - - @Override public Client deleteClient(String clientname) { throw new UnsupportedOperationException(); } @@ -263,16 +248,6 @@ public class TransientChefApi implements ChefApi { } @Override - public boolean nodeExists(String nodename) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean roleExists(String rolename) { - throw new UnsupportedOperationException(); - } - - @Override public SearchResult searchClients() { throw new UnsupportedOperationException(); } diff --git a/core/src/main/java/org/jclouds/chef/util/CollectionUtils.java b/core/src/main/java/org/jclouds/chef/util/CollectionUtils.java new file mode 100644 index 0000000..0e62804 --- /dev/null +++ b/core/src/main/java/org/jclouds/chef/util/CollectionUtils.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.util; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * Utility methods to work with collections. + * + * @author Ignasi Barrera + */ +public class CollectionUtils { + + /** + * Creates an immutable list with the elements of the given list. If the + * input list is null, it returns an empty list. + * + * @param input + * The list used to build the immutable one. + * @return An immutable list with the elements of the given list. + */ + public static ImmutableList copyOfOrEmpty(@Nullable List input) { + return input == null ? ImmutableList. of() : ImmutableList.copyOf(input); + } + + /** + * Creates an immutable set with the elements of the given set. If the input + * set is null, it returns an empty set. + * + * @param input + * The set used to build the immutable one. + * @return An immutable set with the elements of the given set. + */ + public static ImmutableSet copyOfOrEmpty(@Nullable Set input) { + return input == null ? ImmutableSet. of() : ImmutableSet.copyOf(input); + } + + /** + * Creates an immutable map with the elements of the given map. If the input + * map is null, it returns an empty map. + * + * @param input + * The map used to build the immutable one. + * @return An immutable map with the elements of the given map. + */ + public static ImmutableMap copyOfOrEmpty(@Nullable Map input) { + return input == null ? ImmutableMap. of() : ImmutableMap.copyOf(input); + } +} diff --git a/core/src/test/java/org/jclouds/chef/ChefApiTest.java b/core/src/test/java/org/jclouds/chef/ChefApiTest.java index bdb059a..33d6a98 100644 --- a/core/src/test/java/org/jclouds/chef/ChefApiTest.java +++ b/core/src/test/java/org/jclouds/chef/ChefApiTest.java @@ -28,7 +28,6 @@ import java.util.Set; import org.jclouds.Constants; import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; -import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.apis.ApiMetadata; @@ -55,7 +54,6 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnInputStream; -import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.io.Payload; import org.jclouds.io.payloads.StringPayload; import org.jclouds.reflect.Invocation; @@ -172,7 +170,7 @@ public class ChefApiTest extends BaseAsyncApiTest { Invokable method = method(ChefApi.class, "updateCookbook", String.class, String.class, CookbookVersion.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of("cookbook", "1.0.1", new CookbookVersion("cookbook", "1.0.1")))); + ImmutableList. of("cookbook", "1.0.1", CookbookVersion.builder("cookbook", "1.0.1").build()))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION @@ -229,22 +227,6 @@ public class ChefApiTest extends BaseAsyncApiTest { } - public void testApiExists() throws SecurityException, NoSuchMethodException, IOException { - Invokable method = method(ChefApi.class, "clientExists", String.class); - GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("api"))); - assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/clients/api HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION - + "-test\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class); - assertSaxResponseParserClassEquals(method, null); - assertFallbackClassEquals(method, FalseOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - public void testDeleteClient() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteClient", String.class); GeneratedHttpRequest httpRequest = processor @@ -331,21 +313,6 @@ public class ChefApiTest extends BaseAsyncApiTest { } - public void testNodeExists() throws SecurityException, NoSuchMethodException, IOException { - Invokable method = method(ChefApi.class, "nodeExists", String.class); - GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("node"))); - assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION - + "-test\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class); - assertSaxResponseParserClassEquals(method, null); - assertFallbackClassEquals(method, FalseOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - public void testDeleteNode() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteNode", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("node"))); @@ -364,8 +331,10 @@ public class ChefApiTest extends BaseAsyncApiTest { public void testCreateNode() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createNode", Node.class); - GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of(new Node("testnode", ImmutableSet.of("recipe[java]"), "_default")))); + GeneratedHttpRequest httpRequest = processor.apply(Invocation.create( + method, + ImmutableList. of(Node.builder().name("testnode").runListElement("recipe[java]") + .environment("_default").build()))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/nodes HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION @@ -385,8 +354,10 @@ public class ChefApiTest extends BaseAsyncApiTest { public void testUpdateNode() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "updateNode", Node.class); - GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of(new Node("testnode", ImmutableSet.of("recipe[java]"), "_default")))); + GeneratedHttpRequest httpRequest = processor.apply(Invocation.create( + method, + ImmutableList. of(Node.builder().name("testnode").runListElement("recipe[java]") + .environment("_default").build()))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/nodes/testnode HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION @@ -421,22 +392,6 @@ public class ChefApiTest extends BaseAsyncApiTest { } - public void testRoleExists() throws SecurityException, NoSuchMethodException, IOException { - Invokable method = method(ChefApi.class, "roleExists", String.class); - GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("role"))); - assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/roles/role HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION - + "-test\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class); - assertSaxResponseParserClassEquals(method, null); - assertFallbackClassEquals(method, FalseOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - public void testDeleteRole() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteRole", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("role"))); @@ -456,7 +411,7 @@ public class ChefApiTest extends BaseAsyncApiTest { public void testCreateRole() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createRole", Role.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of(new Role("testrole", ImmutableSet.of("recipe[java]"))))); + ImmutableList. of(Role.builder().name("testrole").runListElement("recipe[java]").build()))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/roles HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION @@ -476,7 +431,7 @@ public class ChefApiTest extends BaseAsyncApiTest { public void testUpdateRole() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "updateRole", Role.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of(new Role("testrole", ImmutableSet.of("recipe[java]"))))); + ImmutableList. of(Role.builder().name("testrole").runListElement("recipe[java]").build()))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/roles/testrole HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION @@ -510,23 +465,6 @@ public class ChefApiTest extends BaseAsyncApiTest { } - public void testDatabagExists() throws SecurityException, NoSuchMethodException, IOException { - Invokable method = method(ChefApi.class, "databagExists", String.class); - GeneratedHttpRequest httpRequest = processor - .apply(Invocation.create(method, ImmutableList. of("databag"))); - assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/data/databag HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION - + "-test\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class); - assertSaxResponseParserClassEquals(method, null); - assertFallbackClassEquals(method, FalseOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - public void testDeleteDatabag() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteDatabag", String.class); GeneratedHttpRequest httpRequest = processor @@ -578,23 +516,6 @@ public class ChefApiTest extends BaseAsyncApiTest { } - public void testDatabagItemExists() throws SecurityException, NoSuchMethodException, IOException { - Invokable method = method(ChefApi.class, "databagItemExists", String.class, String.class); - GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of("name", "databagItem"))); - assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/data/name/databagItem HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION - + "-test\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class); - assertSaxResponseParserClassEquals(method, null); - assertFallbackClassEquals(method, FalseOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - public void testDeleteDatabagItem() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteDatabagItem", String.class, String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, @@ -891,7 +812,7 @@ public class ChefApiTest extends BaseAsyncApiTest { public void testGetResourceContents() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "getResourceContents", Resource.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, - ImmutableList. of(new Resource("test", URI.create("http://foo/bar"), new byte[] {}, null, null)))); + ImmutableList. of(Resource.builder().name("test").url(URI.create("http://foo/bar")).build()))); assertRequestLineEquals(httpRequest, "GET http://foo/bar HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApi.VERSION diff --git a/core/src/test/java/org/jclouds/chef/binders/BindHexEncodedMD5sToJsonPayloadTest.java b/core/src/test/java/org/jclouds/chef/binders/BindHexEncodedMD5sToJsonPayloadTest.java index c703090..282e68e 100644 --- a/core/src/test/java/org/jclouds/chef/binders/BindHexEncodedMD5sToJsonPayloadTest.java +++ b/core/src/test/java/org/jclouds/chef/binders/BindHexEncodedMD5sToJsonPayloadTest.java @@ -17,6 +17,7 @@ package org.jclouds.chef.binders; import static com.google.common.io.BaseEncoding.base16; +import static com.google.common.primitives.Bytes.asList; import static org.testng.Assert.assertEquals; import java.io.File; @@ -56,11 +57,10 @@ public class BindHexEncodedMD5sToJsonPayloadTest { binder.bindToRequest(request, new File("foo")); } - @Test(enabled = false) public void testCorrect() { HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost").build(); binder.bindToRequest(request, - ImmutableSet.of(base16().lowerCase().decode("abddef"), base16().lowerCase().decode("1234"))); + ImmutableSet.of(asList(base16().lowerCase().decode("abddef")), asList(base16().lowerCase().decode("1234")))); assertEquals(request.getPayload().getRawContent(), "{\"checksums\":{\"abddef\":null,\"1234\":null}}"); } diff --git a/core/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java b/core/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java new file mode 100644 index 0000000..76db791 --- /dev/null +++ b/core/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.config; + +import static com.google.common.base.Objects.equal; +import static org.testng.Assert.assertEquals; + +import java.lang.reflect.Type; +import java.util.Map; + +import org.jclouds.chef.config.ChefParserModule.KeepLastRepeatedKeyMapTypeAdapterFactory; +import org.testng.annotations.Test; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * Unit tests for the {@link ChefParserModule} class. + * + * @author Ignasi Barrera + */ +@Test(groups = "unit", testName = "ChefParserModuleTest") +public class ChefParserModuleTest { + + private static class KeyValue { + private final String key; + private final String value; + + private KeyValue(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public int hashCode() { + return Objects.hashCode(key, value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + KeyValue that = KeyValue.class.cast(obj); + return equal(this.key, that.key) && equal(this.value, that.value); + } + } + + private Gson map = new GsonBuilder().registerTypeAdapterFactory(new KeepLastRepeatedKeyMapTypeAdapterFactory()) + .create(); + private Type mapType = new TypeToken>() { + private static final long serialVersionUID = 1L; + }.getType(); + private Type mapkeyValueType = new TypeToken>() { + private static final long serialVersionUID = 1L; + }.getType(); + + public void testKeepLastRepeatedKeyMapTypeAdapter() { + Map noNulls = map.fromJson("{\"value\":\"a test string!\"}", mapType); + assertEquals(noNulls, ImmutableMap.of("value", "a test string!")); + Map withNull = map.fromJson("{\"value\":null}", mapType); + assertEquals(withNull, ImmutableMap.of()); + Map withEmpty = map.fromJson("{\"value\":\"\"}", mapType); + assertEquals(withEmpty, ImmutableMap.of("value", "")); + Map keyValues = map.fromJson( + "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\"}}", + mapkeyValueType); + assertEquals(keyValues, + ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo"), "i-bar", new KeyValue("i-bar", "bar"))); + Map duplicates = map + .fromJson( + "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\", \"value\":\"foo2\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\",\"value\":\"bar2\"}}", + mapkeyValueType); + assertEquals(duplicates, + ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo2"), "i-bar", new KeyValue("i-bar", "bar2"))); + } +} diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java b/core/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java index 6fd7449..355d9a4 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java @@ -79,8 +79,8 @@ public class ParseClientFromJsonTest { public void test() throws IOException { - Client user = new Client(certificate, "jclouds", "adriancole-jcloudstest", "adriancole-jcloudstest", false, - privateKey); + Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest") + .name("adriancole-jcloudstest").isValidator(false).privateKey(privateKey).build(); byte[] encrypted = ByteStreams.toByteArray(new RSAEncryptingPayload(Payloads.newPayload("fooya"), user .getCertificate().getPublicKey())); diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java b/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java index e806fa2..987e45a 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java @@ -31,12 +31,11 @@ import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; -@Test(groups = {"unit"}, singleThreaded = true) +@Test(groups = { "unit" }, singleThreaded = true) public class ParseCookbookDefinitionFromJsonv10Test { private ParseCookbookDefinitionFromJsonv10 handler; @@ -54,6 +53,13 @@ public class ParseCookbookDefinitionFromJsonv10Test { } public void testCookbokDefinitionParsing() throws URISyntaxException { + CookbookDefinition.Version v510 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build(); + CookbookDefinition.Version v420 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build(); + CookbookDefinition definition = CookbookDefinition.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build(); + assertEquals(handler.apply(HttpResponse .builder() .statusCode(200) @@ -63,9 +69,6 @@ public class ParseCookbookDefinitionFromJsonv10Test { + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + "\"version\" => \"5.1.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," - + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), - new CookbookDefinition(new URI("http://localhost:4000/cookbooks/apache2"), - ImmutableSet.of(new CookbookDefinition.Version(new URI("http://localhost:4000/cookbooks/apache2/5.1.0"), "5.1.0"), - new CookbookDefinition.Version(new URI("http://localhost:4000/cookbooks/apache2/4.2.0"), "4.2.0")))); + + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), definition); } } diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java b/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java index 95b26ea..d2cc882 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java @@ -54,6 +54,20 @@ public class ParseCookbookDefinitionListFromJsonv10Test { } public void testCookbokDefinitionListParsing() throws URISyntaxException { + CookbookDefinition.Version v510 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build(); + CookbookDefinition.Version v420 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build(); + CookbookDefinition apache2 = CookbookDefinition.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build(); + + CookbookDefinition.Version v100 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/nginx/1.0.0")).version("1.0.0").build(); + CookbookDefinition.Version v130 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/nginx/0.3.0")).version("0.3.0").build(); + CookbookDefinition nginx = CookbookDefinition.builder() + .url(new URI("http://localhost:4000/cookbooks/nginx")).version(v100).version(v130).build(); + assertEquals(handler.apply(HttpResponse .builder() .statusCode(200) @@ -73,11 +87,6 @@ public class ParseCookbookDefinitionListFromJsonv10Test { + "\"version\" => \"0.3.0\"}" + "]}" + "}").build()), - ImmutableSet.of(new CookbookDefinition(new URI("http://localhost:4000/cookbooks/apache2"), - ImmutableSet.of(new CookbookDefinition.Version(new URI("http://localhost:4000/cookbooks/apache2/5.1.0"), "5.1.0"), - new CookbookDefinition.Version(new URI("http://localhost:4000/cookbooks/apache2/4.2.0"), "4.2.0"))), - new CookbookDefinition(new URI("http://localhost:4000/cookbooks/nginx"), - ImmutableSet.of(new CookbookDefinition.Version(new URI("http://localhost:4000/cookbooks/nginx/1.0.0"), "1.0.0"), - new CookbookDefinition.Version(new URI("http://localhost:4000/cookbooks/nginx/0.3.0"), "0.3.0"))))); + ImmutableSet.of(apache2, nginx)); } } diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java b/core/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java index f5d0f1f..c1f21de 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java @@ -24,7 +24,6 @@ import java.net.URI; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefParserModule; -import org.jclouds.chef.domain.Attribute; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.Metadata; import org.jclouds.chef.domain.Resource; @@ -36,8 +35,6 @@ import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -48,6 +45,7 @@ import com.google.inject.TypeLiteral; * Tests behavior of {@code ParseCookbookVersionFromJson} * * @author Adrian Cole + * @author Ignasi Barrera */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseCookbookVersionFromJsonTest { @@ -70,7 +68,6 @@ public class ParseCookbookVersionFromJsonTest { })); } - @Test(enabled = false) public void testBrew() throws IOException { CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/brew-cookbook.json")).build()); @@ -79,7 +76,6 @@ public class ParseCookbookVersionFromJsonTest { handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); } - @Test(enabled = false) public void testTomcat() { CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/tomcat-cookbook.json")).build()); @@ -88,7 +84,6 @@ public class ParseCookbookVersionFromJsonTest { handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); } - @Test(enabled = false) public void testMysql() throws IOException { CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/mysql-cookbook.json")).build()); @@ -97,44 +92,41 @@ public class ParseCookbookVersionFromJsonTest { handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); } - @Test(enabled = false) public void testApache() { - - assertEquals( - handler.apply(HttpResponse - .builder() - .statusCode(200) - .message("ok") - .payload( - ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/apache-chef-demo-cookbook.json")) - .build()), - new CookbookVersion( - "apache-chef-demo-0.0.0", - ImmutableSet. of(), - ImmutableSet. of(), - ImmutableSet. of(), - new Metadata("Apache v2.0", "Your Name", ImmutableMap. of(), ImmutableMap - . of(), "youremail@example.com", ImmutableMap. of(), - "A fabulous new cookbook", ImmutableMap. of(), ImmutableMap - . of(), "0.0.0", ImmutableMap. of(), ImmutableMap - . of(), "apache-chef-demo", ImmutableMap. of(), "", - ImmutableMap. of(), ImmutableMap. of()), - ImmutableSet. of(), - "apache-chef-demo", - ImmutableSet. of(), - ImmutableSet. of(), - ImmutableSet. of(), - "0.0.0", - ImmutableSet. of(), - ImmutableSet. of( - new Resource( - "README", - URI.create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D"), - base16().lowerCase().decode("11637f98942eafbf49c71b7f2f048b78"), "README", "default"), - new Resource( - "Rakefile", - URI.create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D"), - base16().lowerCase().decode("ebcf925a1651b4e04b9cd8aac2bc54eb"), "Rakefile", "default")))); - + CookbookVersion fromJson = handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/apache-chef-demo-cookbook.json")) + .build()); + + CookbookVersion expected = CookbookVersion + .builder("apache-chef-demo", "0.0.0") + .metadata(Metadata.builder() // + .license("Apache v2.0") // + .maintainer("Your Name") // + .maintainerEmail("youremail@example.com") // + .description("A fabulous new cookbook") // + .version("0.0.0").name("apache-chef-demo") // + .longDescription("") // + .build()) + .rootFile( + Resource + .builder() + .name("README") + .path("README") + .checksum(base16().lowerCase().decode("11637f98942eafbf49c71b7f2f048b78")) + .url(URI + .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D")) // + .build()) + .rootFile( + Resource + .builder() + .name("Rakefile") + .path("Rakefile") + .checksum(base16().lowerCase().decode("ebcf925a1651b4e04b9cd8aac2bc54eb")) + .url(URI + .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D")) + .build()) // + .build(); + + assertEquals(fromJson, expected); } } diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java b/core/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java index d0d9070..5f825dd 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java @@ -19,7 +19,6 @@ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; -import java.util.Collections; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefParserModule; @@ -32,7 +31,6 @@ import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableMap; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -63,10 +61,12 @@ public class ParseNodeFromJsonTest { } public void test() { - - Node node = new Node("adrian-jcloudstest", ImmutableMap. of("tomcat6", new JsonBall( - "{\"ssl_port\":8433}")), ImmutableMap. of(), ImmutableMap. of(), - ImmutableMap. of(), Collections.singleton("recipe[java]"), "prod"); + Node node = Node.builder() // + .name("adrian-jcloudstest") // + .normalAttribute("tomcat6", new JsonBall("{\"ssl_port\":8433}")) // + .runListElement("recipe[java]") // + .environment("prod") // + .build(); assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java b/core/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java index 76edffd..13843ee 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java @@ -31,7 +31,6 @@ import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -67,8 +66,8 @@ public class ParseSandboxFromJsonTest { assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseSandboxFromJsonTest.class.getResourceAsStream("/sandbox.json")).build()), - new Sandbox("1-8c27b0ea4c2b7aaedbb44cfbdfcc11b2", false, dateService - .iso8601SecondsDateParse("2010-07-07T03:36:00+00:00"), ImmutableSet. of(), - "f9d6d9b72bae465890aae87969f98a9c", "f9d6d9b72bae465890aae87969f98a9c")); + Sandbox.builder().rev("1-8c27b0ea4c2b7aaedbb44cfbdfcc11b2").isCompleted(false) + .createTime(dateService.iso8601SecondsDateParse("2010-07-07T03:36:00+00:00")) + .name("f9d6d9b72bae465890aae87969f98a9c").guid("f9d6d9b72bae465890aae87969f98a9c").build()); } } diff --git a/core/src/test/java/org/jclouds/chef/functions/ParseUploadSandboxFromJsonTest.java b/core/src/test/java/org/jclouds/chef/functions/ParseUploadSandboxFromJsonTest.java index e992e79..03e61ca 100644 --- a/core/src/test/java/org/jclouds/chef/functions/ParseUploadSandboxFromJsonTest.java +++ b/core/src/test/java/org/jclouds/chef/functions/ParseUploadSandboxFromJsonTest.java @@ -22,7 +22,6 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; -import java.util.List; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefParserModule; @@ -35,7 +34,6 @@ import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableMap; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -70,14 +68,22 @@ public class ParseUploadSandboxFromJsonTest { assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseUploadSandboxFromJsonTest.class.getResourceAsStream("/upload-site.json")).build()), - new UploadSandbox( - URI.create("https://api.opscode.com/organizations/jclouds/sandboxes/d454f71e2a5f400c808d0c5d04c2c88c"), - ImmutableMap., ChecksumStatus> of( + UploadSandbox + .builder() + .uri(URI + .create("https://api.opscode.com/organizations/jclouds/sandboxes/d454f71e2a5f400c808d0c5d04c2c88c")) + .checksum( asList(base16().lowerCase().decode("0c5ecd7788cf4f6c7de2a57193897a6c")), - new ChecksumStatus( - URI.create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/sandbox-d454f71e2a5f400c808d0c5d04c2c88c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277344702&Signature=FtKyqvYEjhhEKmRY%2B0M8aGPMM7g%3D"), - true), asList(base16().lowerCase().decode("0189e76ccc476701d6b374e5a1a27347")), - new ChecksumStatus(), asList(base16().lowerCase().decode("1dda05ed139664f1f89b9dec482b77c0")), - new ChecksumStatus()), "d454f71e2a5f400c808d0c5d04c2c88c")); + ChecksumStatus + .builder() + .url(URI + .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/sandbox-d454f71e2a5f400c808d0c5d04c2c88c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277344702&Signature=FtKyqvYEjhhEKmRY%2B0M8aGPMM7g%3D")) + .needsUpload(true).build()) + .checksum(asList(base16().lowerCase().decode("0189e76ccc476701d6b374e5a1a27347")), + ChecksumStatus.builder().build()) + .checksum(asList(base16().lowerCase().decode("1dda05ed139664f1f89b9dec482b77c0")), + ChecksumStatus.builder().build()).sandboxId("d454f71e2a5f400c808d0c5d04c2c88c").build() + + ); } } diff --git a/core/src/test/java/org/jclouds/chef/functions/UriForResourceTest.java b/core/src/test/java/org/jclouds/chef/functions/UriForResourceTest.java index 2504b53..98c7d07 100644 --- a/core/src/test/java/org/jclouds/chef/functions/UriForResourceTest.java +++ b/core/src/test/java/org/jclouds/chef/functions/UriForResourceTest.java @@ -48,7 +48,7 @@ public class UriForResourceTest { @Test public void testWithValidResource() { Function function = new UriForResource(); - Resource res = new Resource("test", URI.create("http://foo/bar"), null, null, null); + Resource res = Resource.builder().name("test").url(URI.create("http://foo/bar")).build(); URI result = function.apply(res); assertEquals(res.getUrl().toString(), result.toString()); } diff --git a/core/src/test/java/org/jclouds/chef/internal/BaseChefApiLiveTest.java b/core/src/test/java/org/jclouds/chef/internal/BaseChefApiLiveTest.java index adf11cf..529df68 100644 --- a/core/src/test/java/org/jclouds/chef/internal/BaseChefApiLiveTest.java +++ b/core/src/test/java/org/jclouds/chef/internal/BaseChefApiLiveTest.java @@ -17,6 +17,7 @@ package org.jclouds.chef.internal; import static com.google.common.base.Throwables.propagate; +import static com.google.common.collect.Iterables.isEmpty; import static com.google.common.hash.Hashing.md5; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.jclouds.io.ByteSources.asByteSource; @@ -25,6 +26,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; import java.io.File; import java.io.IOException; @@ -40,6 +42,7 @@ import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.Environment; +import org.jclouds.chef.domain.Metadata; import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Resource; import org.jclouds.chef.domain.Role; @@ -78,71 +81,88 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv protected DatabagItem databagItem; public void testCreateNewCookbook() throws Exception { - - // define the file you want in the cookbook + // Define the file you want in the cookbook FilePayload content = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml")); content.getContentMetadata().setContentType("application/x-binary"); - // get an md5 so that you can see if the server already has it or not + // Get an md5 so that you can see if the server already has it or not Payloads.calculateMD5(content); // Note that java collections cannot effectively do equals or hashcodes on - // byte arrays, - // so let's convert to a list of bytes. + // byte arrays, so let's convert to a list of bytes. List md5 = Bytes.asList(content.getContentMetadata().getContentMD5()); - // request an upload site for this file + // Request an upload site for this file UploadSandbox site = api.getUploadSandboxForChecksums(ImmutableSet.of(md5)); + assertTrue(site.getChecksums().containsKey(md5), md5 + " not in " + site.getChecksums()); try { - assert site.getChecksums().containsKey(md5) : md5 + " not in " + site.getChecksums(); - + // Upload the file contents, if still not uploaded ChecksumStatus status = site.getChecksums().get(md5); if (status.needsUpload()) { - // context.utils().http().put(status.getUrl(), content); api.uploadContent(status.getUrl(), content); } - api.commitSandbox(site.getSandboxId(), true); - } catch (RuntimeException e) { api.commitSandbox(site.getSandboxId(), false); + fail("Could not upload content"); } - // create a new cookbook - CookbookVersion cookbook = new CookbookVersion(PREFIX, "0.0.0"); - cookbook.getRootFiles().add(new Resource(content)); + // Create the metadata of the cookbook + Metadata metadata = Metadata.builder() // + .name(PREFIX) // + .version("0.0.0") // + .description("Jclouds test uploaded cookbook") // + .maintainer("jclouds") // + .maintainerEmail("someone@jclouds.org") // + .license("Apache 2.0") // + .build(); + + // Create a new cookbook + CookbookVersion cookbook = CookbookVersion.builder(PREFIX, "0.0.0") // + .metadata(metadata) // + .rootFile(Resource.builder().fromPayload(content).build()) // + .build(); // upload the cookbook to the remote server api.updateCookbook(PREFIX, "0.0.0", cookbook); } - @Test(dependsOnMethods = "testCreateClient") - public void testGenerateKeyForClient() throws Exception { - String credential = Pems.pem(api.generateKeyForClient(PREFIX).getPrivateKey()); - assertClientCreated(PREFIX, credential); - } - - @Test public void testListCookbooks() throws Exception { Set cookbookNames = api.listCookbooks(); - assertFalse(cookbookNames.isEmpty()); - - for (String cookbook : cookbookNames) { - for (String version : api.getVersionsOfCookbook(cookbook)) { - CookbookVersion cookbookO = api.getCookbook(cookbook, version); - for (Resource resource : ImmutableList. builder().addAll(cookbookO.getDefinitions()) - .addAll(cookbookO.getFiles()).addAll(cookbookO.getLibraries()).addAll(cookbookO.getSuppliers()) - .addAll(cookbookO.getRecipes()).addAll(cookbookO.getResources()).addAll(cookbookO.getRootFiles()) - .addAll(cookbookO.getTemplates()).build()) { - try { - InputStream stream = api.getResourceContents(resource); - byte[] md5 = asByteSource(stream).hash(md5()).asBytes(); - assertEquals(md5, resource.getChecksum()); - } catch (NullPointerException e) { - assert false : "resource not found: " + resource; - } - } + assertFalse(cookbookNames.isEmpty(), "No cookbooks were found"); + + for (String cookbookName : cookbookNames) { + Set versions = api.getVersionsOfCookbook(cookbookName); + assertFalse(versions.isEmpty(), "There are no versions of the cookbook: " + cookbookName); + + for (String version : api.getVersionsOfCookbook(cookbookName)) { + CookbookVersion cookbook = api.getCookbook(cookbookName, version); + assertNotNull(cookbook, "Could not get cookbook: " + cookbookName); + } + } + } + + @Test(dependsOnMethods = "testListCookbooks") + public void testListCookbookVersionsWithChefService() throws Exception { + Iterable cookbooks = chefService.listCookbookVersions(); + assertFalse(isEmpty(cookbooks), "No cookbooks were found"); + } + + @Test(dependsOnMethods = "testListCookbookVersionsWithChefService") + public void testDownloadCookbooks() throws Exception { + Iterable cookbooks = chefService.listCookbookVersions(); + for (CookbookVersion cookbook : cookbooks) { + for (Resource resource : ImmutableList. builder().addAll(cookbook.getDefinitions()) + .addAll(cookbook.getFiles()).addAll(cookbook.getLibraries()).addAll(cookbook.getSuppliers()) + .addAll(cookbook.getRecipes()).addAll(cookbook.getResources()).addAll(cookbook.getRootFiles()) + .addAll(cookbook.getTemplates()).build()) { + + InputStream stream = api.getResourceContents(resource); + assertNotNull(stream, "Resource contents are null for resource: " + resource.getName()); + + byte[] md5 = asByteSource(stream).hash(md5()).asBytes(); + assertEquals(md5, resource.getChecksum()); } } } @@ -150,12 +170,13 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test(dependsOnMethods = "testCreateNewCookbook") public void testUpdateCookbook() throws Exception { CookbookVersion cookbook = api.getCookbook(PREFIX, "0.0.0"); - assertNotNull(api.updateCookbook(PREFIX, "0.0.0", cookbook)); + assertNotNull(cookbook, "Cookbook not found: " + PREFIX); + assertNotNull(api.updateCookbook(PREFIX, "0.0.0", cookbook), "Updated cookbook was null"); } @Test(dependsOnMethods = { "testCreateNewCookbook", "testUpdateCookbook" }) public void testDeleteCookbook() throws Exception { - assertNotNull(api.deleteCookbook(PREFIX, "0.0.0")); + assertNotNull(api.deleteCookbook(PREFIX, "0.0.0"), "Deleted cookbook was null"); } @Test @@ -172,34 +193,30 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv assertClientCreated(ADMIN_PREFIX, credential); } - @Test - public void testClientExists() throws Exception { - assertNotNull(api.clientExists(identity)); + @Test(dependsOnMethods = "testCreateClient") + public void testGenerateKeyForClient() throws Exception { + String credential = Pems.pem(api.generateKeyForClient(PREFIX).getPrivateKey()); + assertClientCreated(PREFIX, credential); } @Test public void testListNodes() throws Exception { Set nodes = api.listNodes(); - assertNotNull(nodes); + assertNotNull(nodes, "No nodes were found"); } @Test(dependsOnMethods = "testCreateRole") public void testCreateNode() throws Exception { api.deleteNode(PREFIX); - api.createNode(new Node(PREFIX, Collections.singleton("role[" + PREFIX + "]"), "_default")); + api.createNode(Node.builder().name(PREFIX).runListElement("role[" + PREFIX + "]").environment("_default").build()); node = api.getNode(PREFIX); // TODO check recipes - assertNotNull(node); + assertNotNull(node, "Created node should not be null"); Set nodes = api.listNodes(); - assert nodes.contains(PREFIX) : String.format("node %s not in %s", PREFIX, nodes); + assertTrue(nodes.contains(PREFIX), String.format("node %s not in %s", PREFIX, nodes)); } @Test(dependsOnMethods = "testCreateNode") - public void testNodeExists() throws Exception { - assertNotNull(api.nodeExists(PREFIX)); - } - - @Test(dependsOnMethods = "testNodeExists") public void testUpdateNode() throws Exception { for (String nodename : api.listNodes()) { Node node = api.getNode(nodename); @@ -210,25 +227,20 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test public void testListRoles() throws Exception { Set roles = api.listRoles(); - assertNotNull(roles); + assertNotNull(roles, "Role list was null"); } @Test public void testCreateRole() throws Exception { api.deleteRole(PREFIX); - api.createRole(new Role(PREFIX, Collections.singleton("recipe[java]"))); + api.createRole(Role.builder().name(PREFIX).runListElement("recipe[java]").build()); role = api.getRole(PREFIX); - assertNotNull(role); + assertNotNull(role, "Created role should not be null"); assertEquals(role.getName(), PREFIX); assertEquals(role.getRunList(), Collections.singleton("recipe[java]")); } @Test(dependsOnMethods = "testCreateRole") - public void testRoleExists() throws Exception { - assertNotNull(api.roleExists(PREFIX)); - } - - @Test(dependsOnMethods = "testRoleExists") public void testUpdateRole() throws Exception { for (String rolename : api.listRoles()) { Role role = api.getRole(rolename); @@ -239,7 +251,7 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test public void testListDatabags() throws Exception { Set databags = api.listDatabags(); - assertNotNull(databags); + assertNotNull(databags, "Data bag list was null"); } @Test @@ -248,15 +260,10 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv api.createDatabag(PREFIX); } - @Test(dependsOnMethods = "testCreateDatabag") - public void testDatabagExists() throws Exception { - assertNotNull(api.databagExists(PREFIX)); - } - @Test(dependsOnMethods = "testCreateDatabagItem") public void testListDatabagItems() throws Exception { Set databagItems = api.listDatabagItems(PREFIX); - assertNotNull(databagItems); + assertNotNull(databagItems, "Data bag item list was null"); } @Test(dependsOnMethods = "testCreateDatabag") @@ -265,7 +272,7 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv config.setProperty("foo", "bar"); api.deleteDatabagItem(PREFIX, PREFIX); databagItem = api.createDatabagItem(PREFIX, new DatabagItem("config", json.toJson(config))); - assertNotNull(databagItem); + assertNotNull(databagItem, "Created data bag item should not be null"); assertEquals(databagItem.getId(), "config"); // The databagItem json contains extra keys: (the name and the type if the @@ -278,11 +285,6 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv } @Test(dependsOnMethods = "testCreateDatabagItem") - public void testDatabagItemExists() throws Exception { - assertNotNull(api.databagItemExists(PREFIX, PREFIX)); - } - - @Test(dependsOnMethods = "testDatabagItemExists") public void testUpdateDatabagItem() throws Exception { for (String databagItemId : api.listDatabagItems(PREFIX)) { DatabagItem databagItem = api.getDatabagItem(PREFIX, databagItemId); @@ -293,16 +295,16 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test public void testListSearchIndexes() throws Exception { Set indexes = api.listSearchIndexes(); - assertNotNull(indexes); - assert indexes.contains("node") : indexes; - assert indexes.contains("client") : indexes; - assert indexes.contains("role") : indexes; + assertNotNull(indexes, "The index list should not be null"); + assertTrue(indexes.contains("node")); + assertTrue(indexes.contains("client")); + assertTrue(indexes.contains("role")); } @Test public void testSearchNodes() throws Exception { SearchResult results = api.searchNodes(); - assertNotNull(results); + assertNotNull(results, "Node result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateNode" }) @@ -330,7 +332,7 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test public void testSearchClients() throws Exception { SearchResult results = api.searchClients(); - assertNotNull(results); + assertNotNull(results, "Client result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateClient" }) @@ -358,7 +360,7 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test public void testSearchRoles() throws Exception { SearchResult results = api.searchRoles(); - assertNotNull(results); + assertNotNull(results, "Role result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateRole" }) @@ -383,13 +385,13 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv assertTrue(waitForIndex.apply(options)); } - @Test(dependsOnMethods = { "testListSearchIndexes", "testDatabagItemExists" }) + @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" }) public void testSearchDatabag() throws Exception { SearchResult results = api.searchDatabag(PREFIX); - assertNotNull(results); + assertNotNull(results, "Data bag item result list should not be null"); } - @Test(dependsOnMethods = { "testListSearchIndexes", "testDatabagItemExists" }) + @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" }) public void testSearchDatabagWithOptions() throws Exception { Predicate waitForIndex = retry(new Predicate() { @Override @@ -414,15 +416,15 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test(expectedExceptions = ResourceNotFoundException.class, dependsOnMethods = "testListSearchIndexes") public void testSearchDatabagNotFound() throws Exception { SearchResult results = api.searchDatabag("whoopie"); - assertNotNull(results); + assertNotNull(results, "Data bag item result list should not be null"); } @Test public void testCreateEnvironment() { api.deleteEnvironment(PREFIX); - api.createEnvironment(new Environment(PREFIX, PREFIX)); + api.createEnvironment(Environment.builder().name(PREFIX).description(PREFIX).build()); Environment env = api.getEnvironment(PREFIX); - assertNotNull(env); + assertNotNull(env, "Created environment should not be null"); assertEquals(env.getName(), PREFIX); assertEquals(env.getDescription(), PREFIX); } @@ -430,14 +432,14 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv @Test(dependsOnMethods = "testCreateEnvironment") public void testListEnvironment() { Set envList = api.listEnvironments(); - assertNotNull(envList); + assertNotNull(envList, "Environment list was null"); assertTrue(envList.contains(PREFIX)); } @Test(dependsOnMethods = "testCreateEnvironment") public void testSearchEnvironments() throws Exception { SearchResult results = api.searchEnvironments(); - assertNotNull(results); + assertNotNull(results, "Environment result list was null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateEnvironment" }) @@ -462,12 +464,6 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv assertTrue(waitForIndex.apply(options)); } - @Test - public void testListCookbookVersionsWithChefService() throws Exception { - Iterable cookbooks = chefService.listCookbookVersions(); - assertNotNull(cookbooks); - } - @AfterClass(groups = { "live", "integration" }) @Override public void tearDown() { @@ -489,7 +485,7 @@ public abstract class BaseChefApiLiveTest extends BaseChefLiv try { Client client = clientApi.getClient(identity); - assertNotNull(client); + assertNotNull(client, "Client not found: " + identity); } finally { try { Closeables.close(clientApi, true); diff --git a/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplLiveTest.java b/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplLiveTest.java index a904569..4b55efd 100644 --- a/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplLiveTest.java +++ b/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplLiveTest.java @@ -55,7 +55,7 @@ public class CreateNodeAndPopulateAutomaticAttributesImplLiveTest extends BaseCh Node node = api.getNode(prefix); assertEquals(node.getName(), prefix); assertEquals(node.getRunList(), runList); - assertEquals(node.getAutomatic().get("current_user").toString(), currentUserProvider.get().toString()); + assertEquals(node.getAutomaticAttributes().get("current_user").toString(), currentUserProvider.get().toString()); } finally { api.deleteNode(prefix); } diff --git a/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplTest.java b/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplTest.java index 776247f..ace63e1 100644 --- a/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplTest.java +++ b/core/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplTest.java @@ -44,17 +44,11 @@ public class CreateNodeAndPopulateAutomaticAttributesImplTest { public void testWithNoRunlist() { ChefApi chef = createMock(ChefApi.class); - Map automatic = ImmutableMap. of(); + Supplier> automaticSupplier = Suppliers.> ofInstance(ImmutableMap. of()); - Node node = new Node("name", ImmutableSet. of(), "_default"); + Node nodeWithAutomatic = Node.builder().name("name").environment("_default") + .automaticAttributes(automaticSupplier.get()).build(); - Supplier> automaticSupplier = Suppliers.> ofInstance(automatic); - - Node nodeWithAutomatic = new Node("name", ImmutableMap. of(), - ImmutableMap. of(), ImmutableMap. of(), automatic, - ImmutableSet. of(), "_default"); - - node.getAutomatic().putAll(automaticSupplier.get()); chef.createNode(nodeWithAutomatic); replay(chef); diff --git a/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplLiveTest.java b/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplLiveTest.java index 755576c..e8681d2 100644 --- a/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplLiveTest.java +++ b/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplLiveTest.java @@ -50,12 +50,12 @@ public class UpdateAutomaticAttributesOnNodeImplLiveTest extends BaseChefLiveTes public void testExecute() { Set runList = ImmutableSet.of("role[" + prefix + "]"); try { - api.createNode(new Node(prefix, runList, "_default")); + api.createNode(Node.builder().name(prefix).runList(runList).environment("_default").build()); strategy.execute(prefix); Node node = api.getNode(prefix); assertEquals(node.getName(), prefix); assertEquals(node.getRunList(), runList); - assertEquals(node.getAutomatic().get("current_user").toString(), currentUserProvider.get().toString()); + assertEquals(node.getAutomaticAttributes().get("current_user").toString(), currentUserProvider.get().toString()); } finally { api.deleteNode(prefix); } diff --git a/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplTest.java b/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplTest.java index bf4a0e4..792e391 100644 --- a/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplTest.java +++ b/core/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplTest.java @@ -16,10 +16,10 @@ */ package org.jclouds.chef.strategy.internal; +import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; -import static org.easymock.classextension.EasyMock.createMock; -import static org.easymock.classextension.EasyMock.replay; -import static org.easymock.classextension.EasyMock.verify; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; import java.util.Map; @@ -31,7 +31,6 @@ import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; /** * Tests behavior of {@code UpdateAutomaticAttributesOnNodeImpl} @@ -46,17 +45,13 @@ public class UpdateAutomaticAttributesOnNodeImplTest { ChefApi chef = createMock(ChefApi.class); Map automatic = ImmutableMap. of(); - - Node node = new Node("name", ImmutableSet. of(), "_default"); - Supplier> automaticSupplier = Suppliers.> ofInstance(automatic); - Node nodeWithAutomatic = new Node("name", ImmutableMap. of(), - ImmutableMap. of(), ImmutableMap. of(), automatic, - ImmutableSet. of(), "_default"); + Node node = Node.builder().name("name").environment("_default").build(); + Node nodeWithAutomatic = Node.builder().name("name").environment("_default").automaticAttributes(automatic) + .build(); expect(chef.getNode("name")).andReturn(node); - node.getAutomatic().putAll(automaticSupplier.get()); expect(chef.updateNode(nodeWithAutomatic)).andReturn(null); replay(chef); diff --git a/core/src/test/java/org/jclouds/chef/test/TransientChefApiIntegrationTest.java b/core/src/test/java/org/jclouds/chef/test/TransientChefApiIntegrationTest.java index d11b1cf..13c002e 100644 --- a/core/src/test/java/org/jclouds/chef/test/TransientChefApiIntegrationTest.java +++ b/core/src/test/java/org/jclouds/chef/test/TransientChefApiIntegrationTest.java @@ -50,12 +50,7 @@ public class TransientChefApiIntegrationTest extends BaseChefLiveTest { api.createDatabag(PREFIX); } - @Test(dependsOnMethods = "testCreateDatabag") - public void testDatabagExists() { - assertNotNull(api.databagExists(PREFIX)); - } - - @Test(dependsOnMethods = { "testDatabagExists" }) + @Test(dependsOnMethods = { "testCreateDatabag" }) public void testCreateDatabagItem() { Properties config = new Properties(); config.setProperty("foo", "bar"); @@ -66,11 +61,6 @@ public class TransientChefApiIntegrationTest extends BaseChefLiveTest { } @Test(dependsOnMethods = "testCreateDatabagItem") - public void testDatabagItemExists() { - assertNotNull(api.databagItemExists(PREFIX, PREFIX)); - } - - @Test(dependsOnMethods = "testDatabagItemExists") public void testUpdateDatabagItem() { for (String databagItemId : api.listDatabagItems(PREFIX)) { DatabagItem databagItem = api.getDatabagItem(PREFIX, databagItemId); diff --git a/core/src/test/resources/apache-chef-demo-cookbook.json b/core/src/test/resources/apache-chef-demo-cookbook.json index 0a3e384..228a3c0 100644 --- a/core/src/test/resources/apache-chef-demo-cookbook.json +++ b/core/src/test/resources/apache-chef-demo-cookbook.json @@ -6,14 +6,23 @@ "json_class": "Chef::CookbookVersion", "providers": [], "metadata": { - "dependencies": {}, "name": "apache-chef-demo", + "dependencies": {}, + "name": "apache-chef-demo", "maintainer_email": "youremail@example.com", - "attributes": {}, "license": "Apache v2.0", + "attributes": {}, + "license": "Apache v2.0", "maintainer": "Your Name", - "suggestions": {}, "platforms": {}, "long_description": "", - "recommendations": {}, "version": "0.0.0", - "groupings": {}, "recipes": {}, "conflicting": {}, "description": "A fabulous new cookbook", - "replacing": {}, "providing": {} + "suggestions": {}, + "platforms": {}, + "long_description": "", + "recommendations": {}, + "version": "0.0.0", + "groupings": {}, + "recipes": {}, + "conflicting": {}, + "description": "A fabulous new cookbook", + "replacing": {}, + "providing": {} }, "libraries": [], "resources": [], "templates": [], diff --git a/core/src/test/resources/brew-cookbook.json b/core/src/test/resources/brew-cookbook.json index f0b09ed..dcf7aca 100644 --- a/core/src/test/resources/brew-cookbook.json +++ b/core/src/test/resources/brew-cookbook.json @@ -1 +1,48 @@ -{"name":"brew-0.0.0","definitions":[],"json_class":"Chef::CookbookVersion","attributes":[],"files":[],"metadata":{"dependencies":{},"name":"brew","maintainer_email":"youremail@example.com","license":"Apache v2.0","attributes":{},"maintainer":"Your Name","suggestions":{},"platforms":{},"long_description":"","version":"0.0.0","recommendations":{},"conflicting":{},"recipes":{"brew":""},"groupings":{},"description":"A fabulous new cookbook","replacing":{},"providing":{"brew":[]}},"providers":[{"name":"brew.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=brTA3YkBF7iDnjPGCCHxgm7AHko%3D","checksum":"0c5ecd7788cf4f6c7de2a57193897a6c","path":"providers/brew.rb","specificity":"default"}],"cookbook_name":"brew","resources":[{"name":"brew.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-0189e76ccc476701d6b374e5a1a27347?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=ufrI1k6pKJ1%2FBRMAaIGr6icJlpc%3D","checksum":"0189e76ccc476701d6b374e5a1a27347","path":"resources/brew.rb","specificity":"default"}],"templates":[],"libraries":[],"version":"0.0.0","recipes":[{"name":"default.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1dda05ed139664f1f89b9dec482b77c0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=dOzPk64at92zOfZlxt1suDpGuPs%3D","checksum":"1dda05ed139664f1f89b9dec482b77c0","path":"recipes/default.rb","specificity":"default"}],"root_files":[],"chef_type":"cookbook_version"} \ No newline at end of file +{ "attributes" : [ ], + "chef_type" : "cookbook_version", + "cookbook_name" : "brew", + "definitions" : [ ], + "files" : [ ], + "json_class" : "Chef::CookbookVersion", + "libraries" : [ ], + "metadata" : { "attributes" : { }, + "conflicting" : { }, + "dependencies" : { }, + "description" : "A fabulous new cookbook", + "groupings" : { }, + "license" : "Apache v2.0", + "long_description" : "", + "maintainer" : "Your Name", + "maintainer_email" : "youremail@example.com", + "name" : "brew", + "platforms" : { }, + "providing" : { "brew" : "0.0.0" }, + "recipes" : { "brew" : "" }, + "recommendations" : { }, + "replacing" : { }, + "suggestions" : { }, + "version" : "0.0.0" + }, + "name" : "brew-0.0.0", + "providers" : [ { "checksum" : "0c5ecd7788cf4f6c7de2a57193897a6c", + "name" : "brew.rb", + "path" : "providers/brew.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=brTA3YkBF7iDnjPGCCHxgm7AHko%3D" + } ], + "recipes" : [ { "checksum" : "1dda05ed139664f1f89b9dec482b77c0", + "name" : "default.rb", + "path" : "recipes/default.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1dda05ed139664f1f89b9dec482b77c0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=dOzPk64at92zOfZlxt1suDpGuPs%3D" + } ], + "resources" : [ { "checksum" : "0189e76ccc476701d6b374e5a1a27347", + "name" : "brew.rb", + "path" : "resources/brew.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-0189e76ccc476701d6b374e5a1a27347?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=ufrI1k6pKJ1%2FBRMAaIGr6icJlpc%3D" + } ], + "root_files" : [ ], + "templates" : [ ], + "version" : "0.0.0" +} \ No newline at end of file diff --git a/core/src/test/resources/client.json b/core/src/test/resources/client.json index 15ff8d0..eef7c71 100644 --- a/core/src/test/resources/client.json +++ b/core/src/test/resources/client.json @@ -1 +1,8 @@ -{"orgname":"jclouds","certificate":"-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n-----END CERTIFICATE-----\n","uri":"https://api.opscode.com/organizations/jclouds/clients/adriancole-jcloudstest","private_key":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n","clientname":"adriancole-jcloudstest","name":"adriancole-jcloudstest","validator":false} \ No newline at end of file +{ "certificate" : "-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n-----END CERTIFICATE-----\n", + "clientname" : "adriancole-jcloudstest", + "name" : "adriancole-jcloudstest", + "orgname" : "jclouds", + "private_key" : "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n", + "uri" : "https://api.opscode.com/organizations/jclouds/clients/adriancole-jcloudstest", + "validator" : false +} \ No newline at end of file diff --git a/core/src/test/resources/client.txt b/core/src/test/resources/client.txt deleted file mode 100644 index 5023370..0000000 --- a/core/src/test/resources/client.txt +++ /dev/null @@ -1,7 +0,0 @@ -{ - "certificate": "-----BEGIN CERTIFICATE-----\ndXQ==\n-----END CERTIFICATE-----\n", - "orgname": "jclouds", - "clientname": "adrian-jcloudstest", - "name": "adrian-jcloudstest", - "validator": false -} \ No newline at end of file diff --git a/core/src/test/resources/logback.xml b/core/src/test/resources/logback.xml index 50b810a..f9c023f 100644 --- a/core/src/test/resources/logback.xml +++ b/core/src/test/resources/logback.xml @@ -2,15 +2,12 @@ target/test-data/jclouds.log - %d %-5p [%c] [%thread] %m%n - target/test-data/jclouds-wire.log - %d %-5p [%c] [%thread] %m%n @@ -24,12 +21,10 @@ - - diff --git a/core/src/test/resources/mysql-cookbook.json b/core/src/test/resources/mysql-cookbook.json index b0f8bc4..b0450ae 100644 --- a/core/src/test/resources/mysql-cookbook.json +++ b/core/src/test/resources/mysql-cookbook.json @@ -1 +1,268 @@ -{"definitions":[],"name":"mysql-0.21.2","attributes":[{"name":"server.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-548fa4bc548b8b59ac98fffee8e81f4a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=MsgggSKS0T1q1Lc72nJpHORBQX0%3D","checksum":"548fa4bc548b8b59ac98fffee8e81f4a","path":"attributes/server.rb","specificity":"default"}],"files":[],"json_class":"Chef::CookbookVersion","providers":[{"name":"database.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b994881a2aba60e32c4b6408ffba993d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2XMRbryCmEqirCWLCvrXoenYubw%3D","checksum":"b994881a2aba60e32c4b6408ffba993d","path":"providers/database.rb","specificity":"default"}],"metadata":{"dependencies":{"openssl":[]},"name":"mysql","maintainer_email":"cookbooks@opscode.com","attributes":{"mysql/server_root_password":{"required":"optional","calculated":false,"default":"randomly generated","choice":[],"type":"string","recipes":[],"display_name":"MySQL Server Root Password","description":"Randomly generated password for the mysqld root user"},"mysql/tunable/max_heap_table_size":{"required":"optional","calculated":false,"default":"32M","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Max Heap Table Size"},"mysql/bind_address":{"required":"optional","calculated":false,"default":"ipaddress","choice":[],"type":"string","recipes":[],"display_name":"MySQL Bind Address","description":"Address that mysqld should listen on"},"mysql/datadir":{"required":"optional","calculated":false,"default":"/var/lib/mysql","choice":[],"type":"string","recipes":[],"display_name":"MySQL Data Directory","description":"Location of mysql databases"},"mysql/tunable/wait_timeout":{"required":"optional","calculated":false,"default":"180","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Wait Timeout"},"mysql/tunable/back_log":{"required":"optional","calculated":false,"default":"128","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Back Log"},"mysql/tunable/net_read_timeout":{"required":"optional","calculated":false,"default":"30","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Net Read Timeout"},"mysql/tunable/max_connections":{"required":"optional","calculated":false,"default":"800","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Max Connections"},"mysql/tunable":{"required":"optional","calculated":false,"choice":[],"type":"hash","recipes":[],"display_name":"MySQL Tunables","description":"Hash of MySQL tunable attributes"},"mysql/tunable/table_cache":{"required":"optional","calculated":false,"default":"128","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Table Cache"},"mysql/ec2_path":{"required":"optional","calculated":false,"default":"/mnt/mysql","choice":[],"type":"string","recipes":[],"display_name":"MySQL EC2 Path","description":"Location of mysql directory on EC2 instance EBS volumes"},"mysql/tunable/key_buffer":{"required":"optional","calculated":false,"default":"250M","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tuntable Key Buffer"},"mysql/tunable/net_write_timeout":{"required":"optional","calculated":false,"default":"30","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Net Write Timeout"}},"license":"Apache 2.0","maintainer":"Opscode, Inc.","suggestions":{},"platforms":{"debian":[],"ubuntu":[]},"long_description":"= DESCRIPTION:\n\nInstalls and configures MySQL client or server.\n\n= REQUIREMENTS:\n\n== Platform:\n\nBest tested on Ubuntu 9.04,9.10. On EC2, requires platform that supports -o bind option for the 'mount' command.\n\n== Cookbooks:\n\nRequires Opscode's openssl cookbook for secure password generation.\n\n= ATTRIBUTES: \n\n* mysql[:server_root_password] - Set the server's root password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_repl_password] - Set the replication user 'repl' password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_debian_password] - Set the debian-sys-maint user password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:bind_address] - Listen address for MySQLd, default is node's ipaddress.\n* mysql[:datadir] - Location for mysql data directory, default is \"/var/lib/mysql\" \n* mysql[:ec2_path] - location of mysql datadir on EC2 nodes, default \"/mnt/mysql\" \n\nPerformance tuning attributes, each corresponds to the same-named parameter in my.cnf; default values listed\n\n* mysql[:tunable][:key_buffer] = \"250M\"\n* mysql[:tunable][:max_connections] = \"800\" \n* mysql[:tunable][:wait_timeout] = \"180\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:back_log] = \"128\" \n* mysql[:tunable][:table_cache] = \"128\" \n* mysql[:tunable][:max_heap_table_size] = \"32M\" \n\n= USAGE:\n\nOn client nodes,\n\n include_recipe \"mysql::client\"\n \nAs the common use case is on systems with Ruby, we also install the MySQL RubyGem. Because we may want to be able to use the gem within another Chef recipe, we make sure the mysql development package and gem are installed first. The key is this:\n\n r = package ... do\n action :nothing\n end\n \n r.run_action(:install)\n \nThis creates a resource object for the package and does the installation before other recipes are parsed. You'll need to have the C compiler and such (ie, build-essential on Ubuntu) before running the recipes, but we already do that when installing Chef :-). If you want to be able to access a MySQL database via Ruby within another recipe, you could do so, like so:\n\n Gem.clear_paths # needed for Chef to find the gem...\n require 'mysql' # requires the mysql gem\n\n execute \"create #{node[:railsapp][:db][:database]} database\" do\n command \"/usr/bin/mysqladmin -u root -p#{node[:mysql][:server_root_password]} create #{node[:railsapp][:db][:database]}\"\n not_if do\n m = Mysql.new(\"localhost\", \"root\", @node[:mysql][:server_root_password])\n m.list_dbs.include?(@node[:railsapp][:db][:database])\n end\n end\n\nOn server nodes, \n\n include_recipe \"mysql::server\"\n \nOn Debian/Ubuntu this will preseed the MySQL package with the randomly generated root password. You can of course change the password afterward, but this makes sure that there's a good password set. You can view it in the node data in the Chef Server webui. Sets a new password for debian-sys-maint user as well.\n\nAlso sets up 'repl' user grants for replication slaves.\n\nOn EC2 nodes,\n\n include_recipe \"mysql::server_ec2\"\n \nWhen the ec2_path doesn't exist we look for a mounted filesystem (eg, EBS) and move the datadir there.\n\nThe client recipe is already included by server and 'default' recipes.\n\n= LICENSE and AUTHOR:\n \nAuthor:: Joshua Timberman ()\nAuthor:: AJ Christensen ()\n\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","recommendations":{},"version":"0.21.2","groupings":{},"recipes":{"mysql::client":"Installs packages required for mysql clients using run_action magic","mysql::server_ec2":"Performs EC2-specific mountpoint manipulation","mysql::server":"Installs packages required for mysql servers w/o manual intervention"},"conflicting":{},"description":"Installs and configures mysql for client or server","replacing":{},"providing":{}},"libraries":[{"name":"database.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b2eb0760c07734be9c637dcffc86175a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=CvVbxzrA%2Fuxc59ZjLR5BsMozfxk%3D","checksum":"b2eb0760c07734be9c637dcffc86175a","path":"libraries/database.rb","specificity":"default"}],"resources":[{"name":"database.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8aa8e2cafe54c2932c7aa65d62ec2695?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=6URS94f1HpRibHC%2FhBkr7Eg3dVA%3D","checksum":"8aa8e2cafe54c2932c7aa65d62ec2695","path":"resources/database.rb","specificity":"default"}],"templates":[{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D","checksum":"689c1b6fbb242b6c508384e56646341d","path":"templates/ubuntu-9.10/my.cnf.erb","specificity":"ubuntu-9.10"},{"name":"mysql-server.seed.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-16b036a0bb31957a77e9b825cf616cc5?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=50bRvt6GQqFEcfYtaIsq1d4a4c8%3D","checksum":"16b036a0bb31957a77e9b825cf616cc5","path":"templates/default/mysql-server.seed.erb","specificity":"default"},{"name":"grants.sql.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-932b51ddddcbd24ee10a76ecae33b8ba?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=RHR0obLFcsN1M9tL28IH4Tcur5g%3D","checksum":"932b51ddddcbd24ee10a76ecae33b8ba","path":"templates/default/grants.sql.erb","specificity":"default"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-7746560b37ac8d4a0cf68befbecbd8a3?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=W7Nqkvhw2TBrlDvcM2rlA4Oj5%2Bk%3D","checksum":"7746560b37ac8d4a0cf68befbecbd8a3","path":"templates/default/my.cnf.erb","specificity":"default"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D","checksum":"63bd67fae6d297e8f658e9c0ad01a411","path":"templates/centos/my.cnf.erb","specificity":"centos"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D","checksum":"689c1b6fbb242b6c508384e56646341d","path":"templates/ubuntu-10.04/my.cnf.erb","specificity":"ubuntu-10.04"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D","checksum":"63bd67fae6d297e8f658e9c0ad01a411","path":"templates/redhat/my.cnf.erb","specificity":"redhat"},{"name":"port_mysql.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d2244150a145b3f658cd37c13269fafc?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=23iHcjwpNOvlNf%2BlrKcV2pkU7uo%3D","checksum":"d2244150a145b3f658cd37c13269fafc","path":"templates/default/port_mysql.erb","specificity":"default"},{"name":"debian.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2e08553db526f5f80c28b343f6a616cb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=VdcFYxnLUkj1tS3k8DovrzZEA7E%3D","checksum":"2e08553db526f5f80c28b343f6a616cb","path":"templates/default/debian.cnf.erb","specificity":"default"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1e5068eec65b51f5a327580fb0af4677?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=D5lPeu1UQvA9pEXZm5nVOwj3WIo%3D","checksum":"1e5068eec65b51f5a327580fb0af4677","path":"templates/ubuntu-8.04/my.cnf.erb","specificity":"ubuntu-8.04"}],"cookbook_name":"mysql","version":"0.21.2","recipes":[{"name":"server_ec2.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-f51bd8122b7dccc9f4656319fef3252a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=BUR2mosCvmoOKq4Mkh3JUG0MY38%3D","checksum":"f51bd8122b7dccc9f4656319fef3252a","path":"recipes/server_ec2.rb","specificity":"default"},{"name":"server.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-80daa897597560372d017c58c4df0e3c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=bU3j9Nw%2BnuIroXKrlJZe7tjaugA%3D","checksum":"80daa897597560372d017c58c4df0e3c","path":"recipes/server.rb","specificity":"default"},{"name":"default.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-bd3ba2d05dea6a8cf0dc2a45f540cc32?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=7haumT5EtEM2h8l32efqV%2Fik%2BdY%3D","checksum":"bd3ba2d05dea6a8cf0dc2a45f540cc32","path":"recipes/default.rb","specificity":"default"},{"name":"client.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-a1d679c7480267cd9b69e3194c7e45ab?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=ZhfTiwv1aXC7HZMnW8A7i4vkMCM%3D","checksum":"a1d679c7480267cd9b69e3194c7e45ab","path":"recipes/client.rb","specificity":"default"}],"root_files":[{"name":"README.rdoc","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e9278fc99fd668bdce33d72dc71fade9?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=KPgAGqShEO5SGzz8oRdwIInPUOc%3D","checksum":"e9278fc99fd668bdce33d72dc71fade9","path":"README.rdoc","specificity":"default"},{"name":"metadata.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8d2f9635f4817ff905a4124e09ec6c59?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=fPF2iY7tNrq%2FuNrCjRLImP9vRbA%3D","checksum":"8d2f9635f4817ff905a4124e09ec6c59","path":"metadata.rb","specificity":"default"},{"name":"metadata.json","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e6804b8f3e6dfdbbece9d319537ffea1?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=EVsALLreeAA41%2BiPAfPt%2FxFEIYI%3D","checksum":"e6804b8f3e6dfdbbece9d319537ffea1","path":"metadata.json","specificity":"default"}],"chef_type":"cookbook_version"} \ No newline at end of file +{ "attributes" : [ { "checksum" : "548fa4bc548b8b59ac98fffee8e81f4a", + "name" : "server.rb", + "path" : "attributes/server.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-548fa4bc548b8b59ac98fffee8e81f4a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=MsgggSKS0T1q1Lc72nJpHORBQX0%3D" + } ], + "chef_type" : "cookbook_version", + "cookbook_name" : "mysql", + "definitions" : [ ], + "files" : [ ], + "json_class" : "Chef::CookbookVersion", + "libraries" : [ { "checksum" : "b2eb0760c07734be9c637dcffc86175a", + "name" : "database.rb", + "path" : "libraries/database.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b2eb0760c07734be9c637dcffc86175a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=CvVbxzrA%2Fuxc59ZjLR5BsMozfxk%3D" + } ], + "metadata" : { "attributes" : { "mysql/bind_address" : { "calculated" : false, + "choice" : [ ], + "default" : "ipaddress", + "description" : "Address that mysqld should listen on", + "display_name" : "MySQL Bind Address", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/datadir" : { "calculated" : false, + "choice" : [ ], + "default" : "/var/lib/mysql", + "description" : "Location of mysql databases", + "display_name" : "MySQL Data Directory", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/ec2_path" : { "calculated" : false, + "choice" : [ ], + "default" : "/mnt/mysql", + "description" : "Location of mysql directory on EC2 instance EBS volumes", + "display_name" : "MySQL EC2 Path", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/server_root_password" : { "calculated" : false, + "choice" : [ ], + "default" : "randomly generated", + "description" : "Randomly generated password for the mysqld root user", + "display_name" : "MySQL Server Root Password", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable" : { "calculated" : false, + "choice" : [ ], + "description" : "Hash of MySQL tunable attributes", + "display_name" : "MySQL Tunables", + "recipes" : [ ], + "required" : "optional", + "type" : "hash" + }, + "mysql/tunable/back_log" : { "calculated" : false, + "choice" : [ ], + "default" : "128", + "display_name" : "MySQL Tunable Back Log", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/key_buffer" : { "calculated" : false, + "choice" : [ ], + "default" : "250M", + "display_name" : "MySQL Tuntable Key Buffer", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/max_connections" : { "calculated" : false, + "choice" : [ ], + "default" : "800", + "display_name" : "MySQL Tunable Max Connections", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/max_heap_table_size" : { "calculated" : false, + "choice" : [ ], + "default" : "32M", + "display_name" : "MySQL Tunable Max Heap Table Size", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/net_read_timeout" : { "calculated" : false, + "choice" : [ ], + "default" : "30", + "display_name" : "MySQL Tunable Net Read Timeout", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/net_write_timeout" : { "calculated" : false, + "choice" : [ ], + "default" : "30", + "display_name" : "MySQL Tunable Net Write Timeout", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/table_cache" : { "calculated" : false, + "choice" : [ ], + "default" : "128", + "display_name" : "MySQL Tunable Table Cache", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + }, + "mysql/tunable/wait_timeout" : { "calculated" : false, + "choice" : [ ], + "default" : "180", + "display_name" : "MySQL Tunable Wait Timeout", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + } + }, + "conflicting" : { }, + "dependencies" : { "openssl" : "" }, + "description" : "Installs and configures mysql for client or server", + "groupings" : { }, + "license" : "Apache 2.0", + "long_description" : "= DESCRIPTION:\n\nInstalls and configures MySQL client or server.\n\n= REQUIREMENTS:\n\n== Platform:\n\nBest tested on Ubuntu 9.04,9.10. On EC2, requires platform that supports -o bind option for the 'mount' command.\n\n== Cookbooks:\n\nRequires Opscode's openssl cookbook for secure password generation.\n\n= ATTRIBUTES: \n\n* mysql[:server_root_password] - Set the server's root password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_repl_password] - Set the replication user 'repl' password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_debian_password] - Set the debian-sys-maint user password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:bind_address] - Listen address for MySQLd, default is node's ipaddress.\n* mysql[:datadir] - Location for mysql data directory, default is \"/var/lib/mysql\" \n* mysql[:ec2_path] - location of mysql datadir on EC2 nodes, default \"/mnt/mysql\" \n\nPerformance tuning attributes, each corresponds to the same-named parameter in my.cnf; default values listed\n\n* mysql[:tunable][:key_buffer] = \"250M\"\n* mysql[:tunable][:max_connections] = \"800\" \n* mysql[:tunable][:wait_timeout] = \"180\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:back_log] = \"128\" \n* mysql[:tunable][:table_cache] = \"128\" \n* mysql[:tunable][:max_heap_table_size] = \"32M\" \n\n= USAGE:\n\nOn client nodes,\n\n include_recipe \"mysql::client\"\n \nAs the common use case is on systems with Ruby, we also install the MySQL RubyGem. Because we may want to be able to use the gem within another Chef recipe, we make sure the mysql development package and gem are installed first. The key is this:\n\n r = package ... do\n action :nothing\n end\n \n r.run_action(:install)\n \nThis creates a resource object for the package and does the installation before other recipes are parsed. You'll need to have the C compiler and such (ie, build-essential on Ubuntu) before running the recipes, but we already do that when installing Chef :-). If you want to be able to access a MySQL database via Ruby within another recipe, you could do so, like so:\n\n Gem.clear_paths # needed for Chef to find the gem...\n require 'mysql' # requires the mysql gem\n\n execute \"create #{node[:railsapp][:db][:database]} database\" do\n command \"/usr/bin/mysqladmin -u root -p#{node[:mysql][:server_root_password]} create #{node[:railsapp][:db][:database]}\"\n not_if do\n m = Mysql.new(\"localhost\", \"root\", @node[:mysql][:server_root_password])\n m.list_dbs.include?(@node[:railsapp][:db][:database])\n end\n end\n\nOn server nodes, \n\n include_recipe \"mysql::server\"\n \nOn Debian/Ubuntu this will preseed the MySQL package with the randomly generated root password. You can of course change the password afterward, but this makes sure that there's a good password set. You can view it in the node data in the Chef Server webui. Sets a new password for debian-sys-maint user as well.\n\nAlso sets up 'repl' user grants for replication slaves.\n\nOn EC2 nodes,\n\n include_recipe \"mysql::server_ec2\"\n \nWhen the ec2_path doesn't exist we look for a mounted filesystem (eg, EBS) and move the datadir there.\n\nThe client recipe is already included by server and 'default' recipes.\n\n= LICENSE and AUTHOR:\n \nAuthor:: Joshua Timberman ()\nAuthor:: AJ Christensen ()\n\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", + "maintainer" : "Opscode, Inc.", + "maintainer_email" : "cookbooks@opscode.com", + "name" : "mysql", + "platforms" : { "debian" : "", + "ubuntu" : "" + }, + "providing" : { }, + "recipes" : { "mysql::client" : "Installs packages required for mysql clients using run_action magic", + "mysql::server" : "Installs packages required for mysql servers w/o manual intervention", + "mysql::server_ec2" : "Performs EC2-specific mountpoint manipulation" + }, + "recommendations" : { }, + "replacing" : { }, + "suggestions" : { }, + "version" : "0.21.2" + }, + "name" : "mysql-0.21.2", + "providers" : [ { "checksum" : "b994881a2aba60e32c4b6408ffba993d", + "name" : "database.rb", + "path" : "providers/database.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b994881a2aba60e32c4b6408ffba993d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2XMRbryCmEqirCWLCvrXoenYubw%3D" + } ], + "recipes" : [ { "checksum" : "f51bd8122b7dccc9f4656319fef3252a", + "name" : "server_ec2.rb", + "path" : "recipes/server_ec2.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-f51bd8122b7dccc9f4656319fef3252a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=BUR2mosCvmoOKq4Mkh3JUG0MY38%3D" + }, + { "checksum" : "80daa897597560372d017c58c4df0e3c", + "name" : "server.rb", + "path" : "recipes/server.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-80daa897597560372d017c58c4df0e3c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=bU3j9Nw%2BnuIroXKrlJZe7tjaugA%3D" + }, + { "checksum" : "bd3ba2d05dea6a8cf0dc2a45f540cc32", + "name" : "default.rb", + "path" : "recipes/default.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-bd3ba2d05dea6a8cf0dc2a45f540cc32?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=7haumT5EtEM2h8l32efqV%2Fik%2BdY%3D" + }, + { "checksum" : "a1d679c7480267cd9b69e3194c7e45ab", + "name" : "client.rb", + "path" : "recipes/client.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-a1d679c7480267cd9b69e3194c7e45ab?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=ZhfTiwv1aXC7HZMnW8A7i4vkMCM%3D" + } + ], + "resources" : [ { "checksum" : "8aa8e2cafe54c2932c7aa65d62ec2695", + "name" : "database.rb", + "path" : "resources/database.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8aa8e2cafe54c2932c7aa65d62ec2695?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=6URS94f1HpRibHC%2FhBkr7Eg3dVA%3D" + } ], + "root_files" : [ { "checksum" : "e9278fc99fd668bdce33d72dc71fade9", + "name" : "README.rdoc", + "path" : "README.rdoc", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e9278fc99fd668bdce33d72dc71fade9?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=KPgAGqShEO5SGzz8oRdwIInPUOc%3D" + }, + { "checksum" : "8d2f9635f4817ff905a4124e09ec6c59", + "name" : "metadata.rb", + "path" : "metadata.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8d2f9635f4817ff905a4124e09ec6c59?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=fPF2iY7tNrq%2FuNrCjRLImP9vRbA%3D" + }, + { "checksum" : "e6804b8f3e6dfdbbece9d319537ffea1", + "name" : "metadata.json", + "path" : "metadata.json", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e6804b8f3e6dfdbbece9d319537ffea1?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=EVsALLreeAA41%2BiPAfPt%2FxFEIYI%3D" + } + ], + "templates" : [ { "checksum" : "689c1b6fbb242b6c508384e56646341d", + "name" : "my.cnf.erb", + "path" : "templates/ubuntu-9.10/my.cnf.erb", + "specificity" : "ubuntu-9.10", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D" + }, + { "checksum" : "16b036a0bb31957a77e9b825cf616cc5", + "name" : "mysql-server.seed.erb", + "path" : "templates/default/mysql-server.seed.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-16b036a0bb31957a77e9b825cf616cc5?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=50bRvt6GQqFEcfYtaIsq1d4a4c8%3D" + }, + { "checksum" : "932b51ddddcbd24ee10a76ecae33b8ba", + "name" : "grants.sql.erb", + "path" : "templates/default/grants.sql.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-932b51ddddcbd24ee10a76ecae33b8ba?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=RHR0obLFcsN1M9tL28IH4Tcur5g%3D" + }, + { "checksum" : "7746560b37ac8d4a0cf68befbecbd8a3", + "name" : "my.cnf.erb", + "path" : "templates/default/my.cnf.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-7746560b37ac8d4a0cf68befbecbd8a3?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=W7Nqkvhw2TBrlDvcM2rlA4Oj5%2Bk%3D" + }, + { "checksum" : "63bd67fae6d297e8f658e9c0ad01a411", + "name" : "my.cnf.erb", + "path" : "templates/centos/my.cnf.erb", + "specificity" : "centos", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D" + }, + { "checksum" : "689c1b6fbb242b6c508384e56646341d", + "name" : "my.cnf.erb", + "path" : "templates/ubuntu-10.04/my.cnf.erb", + "specificity" : "ubuntu-10.04", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D" + }, + { "checksum" : "63bd67fae6d297e8f658e9c0ad01a411", + "name" : "my.cnf.erb", + "path" : "templates/redhat/my.cnf.erb", + "specificity" : "redhat", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D" + }, + { "checksum" : "d2244150a145b3f658cd37c13269fafc", + "name" : "port_mysql.erb", + "path" : "templates/default/port_mysql.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d2244150a145b3f658cd37c13269fafc?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=23iHcjwpNOvlNf%2BlrKcV2pkU7uo%3D" + }, + { "checksum" : "2e08553db526f5f80c28b343f6a616cb", + "name" : "debian.cnf.erb", + "path" : "templates/default/debian.cnf.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2e08553db526f5f80c28b343f6a616cb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=VdcFYxnLUkj1tS3k8DovrzZEA7E%3D" + }, + { "checksum" : "1e5068eec65b51f5a327580fb0af4677", + "name" : "my.cnf.erb", + "path" : "templates/ubuntu-8.04/my.cnf.erb", + "specificity" : "ubuntu-8.04", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1e5068eec65b51f5a327580fb0af4677?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=D5lPeu1UQvA9pEXZm5nVOwj3WIo%3D" + } + ], + "version" : "0.21.2" +} \ No newline at end of file diff --git a/core/src/test/resources/newclient.txt b/core/src/test/resources/newclient.txt deleted file mode 100644 index c1e9368..0000000 --- a/core/src/test/resources/newclient.txt +++ /dev/null @@ -1 +0,0 @@ -{"clientname":"adriancole-jcloudstest","private_key":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\npopCBQwjpOnlgpdd/+C+TESl30ojauvVej9AbgJb30Jl7e7dEX4Brncnj03G+mo+\nG4osf7I2PA/6+9Ol7xamK9GL/cs8nOb17cRTWmhTRW7+3Rrli/s6wzqQXjGjWzgz\nthXv7FOPHA87UjJzrePBFta7+S8BxKCG2QaTxzNGytSAy8KBX8BUrSt5+X22QjEM\nQF3zA4TPtoWp/lcDRzCMdffMYoVPZzKqIeEFSexwvNlJ/qU6hbcyAxab1lYawjKU\nRgvPCflVYTIw6teHNqkyvTPX+lpIAVXigSVQXwIDAQABAoIBAHz81xvTSSjzaYFO\n9Gh13QcnuSdSEi0fo4f/zdLOBY2UVVo3nW9umskX46w0ZAAd4qn0d9gfdMZwjtjR\nfoLRO8i2VnPltnt1n64P/DtoXcb03EVPLQvh4feXGVJcMOpz0TKgYmyax+W3DE6M\ne+Az1JplUELo6crgLCSapA63SK85PEuWAcMUQg9s6MnzB/qXz95yJlzgjVMIJUyb\n9jFdq2s0gefTpK2cKeSYWQAFPd41Ea5v/3j0LN8qs/dImNnzxDXu+hi8+16/4PTK\npl+1bJXwE9YkWPdd39EfjVkk6q/HyFijK3VpHnOy7n3iaJTUKwBJLRsFrQ5Eor3U\nvNKyGXECgYEA3RZdFC6MRBAo76GKd9axbA0G9Bmct9pQT4B+od2AGGOdiYzYRWfF\nlyTgctY9dcfsX5DBQFUHNnYXMHHI0wHQk1m20UpFLa7IV3RWkW5JwYkbQHmeP4pn\np8GtJEXC+4PrT0Pc32acfWozArokUju7nLLazCPCDdfc8t9MPX1W230CgYEA2MbB\ndwdwLZx9zEqZ0MciRxjsOA30b6OYPOqMP1ADVeExPN8fHLCAQjwUExQa86+FMV4H\nOtu+DXlisp+TSTRQzpXMfGppupbK1j5cqz2sU37upKuz/uf0XyeyBLOi0y9/DMl5\njG2StLLIMawRqJRUuq/fyA/6oTzADNwoW6LjCgsCgYBGvCj7lAj8nc77HEwZG2+Y\ninJ3Ftq1V/vp88qQLzYUl4qHv7BSRGlLelj1ZOY1EMnnqYCq/IlaO14f+ceu+x2o\nh0OeooyPmSQwFuC7lvWyHhPCBSdEXRvc6HJk8Iz5u7NFoQjB0SqwVZIMhVGpncLg\n17h5J9emZjIi4p6Z7cgkYQKBgHt+/8in3Cif9qrj9S0TxVtrv2dPy+mt8ZUCqlOH\nad8LI9nh4v+dLfSN9YHI+nHJlL/DKatGdMeIV8obTvVtcHvAq3ZVyVYbggL8FB8a\nS4plzd7SUwDtdDKhkrFLBX/6lw7Z2P0/j0ySbaqetJCtsHeKqpp3P/mLen3ZDsTl\nzyJxAoGBAIxl1SGzu3lO3BQ5+EPaprNw3eN3nzG4WLQvnzZwpeAFS+E5pllMkIfs\nu01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\nlMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n-----END RSA PRIVATE KEY-----\n","uri":"https://api.opscode.com/organizations/jclouds/clients/adriancole-jcloudstest","certificate":"-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDYwNDIzMzM0NloXDTIwMDYwMTIzMzM0NlowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBALs2hOms4FMcBEl9awhnSecaXa3NVwt9dWzhmQQh\nPDQPgqRYdqaKQgUMI6Tp5YKXXf/gvkxEpd9KI2rr1Xo/QG4CW99CZe3u3RF+Aa53\nJ49NxvpqPhuKLH+yNjwP+vvTpe8WpivRi/3LPJzm9e3EU1poU0Vu/t0a5Yv7OsM6\nkF4xo1s4M7YV7+xTjxwPO1Iyc63jwRbWu/kvAcSghtkGk8czRsrUgMvCgV/AVK0r\nefl9tkIxDEBd8wOEz7aFqf5XA0cwjHX3zGKFT2cyqiHhBUnscLzZSf6lOoW3MgMW\nm9ZWGsIylEYLzwn5VWEyMOrXhzapMr0z1/paSAFV4oElUF8CAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQCTllbpWNagYjCiaU5UnjIFXn0YyNfZzqCh8SQ0Asj8MtksVbFG\nAErp03+Cb9a7GTdNE7fIyPsLTnGzFhqTwKN+3jIj4wgxhrbYXF73x1+rDRyHjJu7\na7gdTEYZqWiAHdW47vXj69W1dB5e4vNm1F29gOSL/x7BMAyjLFWbdbKw0w==\n-----END CERTIFICATE-----\n","orgname":"jclouds} \ No newline at end of file diff --git a/core/src/test/resources/node.json b/core/src/test/resources/node.json index ecdb470..c8ddaef 100644 --- a/core/src/test/resources/node.json +++ b/core/src/test/resources/node.json @@ -1,2 +1,10 @@ -{"normal":{"tomcat6":{"ssl_port":8433}},"name":"adrian-jcloudstest","override":{},"default":{},"json_class":"Chef::Node","automatic":{},"run_list":["recipe[java]"],"chef_type":"node","chef_environment": "prod"} - +{ "automatic" : { }, + "chef_environment" : "prod", + "chef_type" : "node", + "default" : { }, + "json_class" : "Chef::Node", + "name" : "adrian-jcloudstest", + "normal" : { "tomcat6" : { "ssl_port" : 8433 } }, + "override" : { }, + "run_list" : [ "recipe[java]" ] +} \ No newline at end of file diff --git a/core/src/test/resources/tomcat-cookbook.json b/core/src/test/resources/tomcat-cookbook.json index 6331b51..992f401 100644 --- a/core/src/test/resources/tomcat-cookbook.json +++ b/core/src/test/resources/tomcat-cookbook.json @@ -1 +1,121 @@ -{"definitions":[],"name":"tomcat6-0.1.0","files":[{"name":"org.apache.tomcat.tomcat6.plist","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-18e534a72652f3d53b197ca4e5027009?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=M3fBL4t7uuYVXVah2PyZ8eL1QCc%3D","checksum":"18e534a72652f3d53b197ca4e5027009","path":"files/default/org.apache.tomcat.tomcat6.plist","specificity":"default"},{"name":"logging.properties","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6a35ce92050296862ea63b784529d2e0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=vRlKoye2%2Fwz8mdQI%2F3Ht916sllE%3D","checksum":"6a35ce92050296862ea63b784529d2e0","path":"files/default/logging.properties","specificity":"default"}],"attributes":[{"name":"tomcat6.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6e3fd0d16a87a55c569da108194ecb29?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zvYjsgUXIC7Xj3MT8Wd93esDGJM%3D","checksum":"6e3fd0d16a87a55c569da108194ecb29","path":"attributes/tomcat6.rb","specificity":"default"}],"json_class":"Chef::CookbookVersion","providers":[],"metadata":{"dependencies":{},"name":"tomcat6","maintainer_email":"cookbooks@opscode.com","license":"Apache 2.0","attributes":{"tomcat6/with_native":{"required":"optional","calculated":false,"default":"false","choice":[],"type":"string","recipes":[],"display_name":"Tomcat native support","description":"works for centos, install tomcat-native libraries"}},"maintainer":"Opscode, Inc.","suggestions":{},"platforms":{"debian":[],"centos":[],"ubuntu":[],"redhat":[]},"long_description":"= DESCRIPTION:\n\nInstalls Tomcat6\n\n= REQUIREMENTS:\n\n== Platform and Application Environment:\n\nTested on Centos 5.2 8.10. May work on other platforms, esp Redhat.\nNeeds Java at least Java 5\n\n== Cookbooks:\n\nOpscode cookbooks, http://github.com/opscode/cookbooks/tree/master:\n\n* java\n\n= ATTRIBUTES: \n\n= USAGE:\n\n\n= LICENSE and AUTHOR:\n \nAuthor:: Edmund Haselwanter ()\nCopyright:: 2009, Edmund Haselwanter\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","version":"0.1.0","recommendations":{},"conflicting":{},"recipes":{"tomcat6":"Main Tomcat 6 configuration"},"groupings":{},"description":"Installs and configures all aspects of tomcat6 using custom local installation","replacing":{},"providing":{}},"libraries":[{"name":"tomcat_manager.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2b6f7847142bb36823c570899669c54b?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zxIoUKcGYWo9ir6qf1tTy3wvKZ4%3D","checksum":"2b6f7847142bb36823c570899669c54b","path":"libraries/tomcat_manager.rb","specificity":"default"},{"name":"tomcat.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-24db7b7dd6f04f8da5fa2b282910ac08?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=c4Gbn5kX0ZaPbWvk5LAcR77sITg%3D","checksum":"24db7b7dd6f04f8da5fa2b282910ac08","path":"libraries/tomcat.rb","specificity":"default"}],"templates":[{"name":"tomcat-users.xml.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-107263b81e4700cf0adad7af2a133bbd?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=QC7MNIauR2ox5MVlohf2i73uM1s%3D","checksum":"107263b81e4700cf0adad7af2a133bbd","path":"templates/default/tomcat-users.xml.erb","specificity":"default"},{"name":"sv-tomcat6-run.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-fa4432b353fa57b9da26a4bff44285f2?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=q2rDeJFeh4oyhfv9ExMifGB0wxo%3D","checksum":"fa4432b353fa57b9da26a4bff44285f2","path":"templates/default/sv-tomcat6-run.erb","specificity":"default"},{"name":"manager.xml.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-33fd6f63133e7ebe28bc62e58773c408?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=rIijEhwLPf5PWTJOg%2BElbOquPBM%3D","checksum":"33fd6f63133e7ebe28bc62e58773c408","path":"templates/default/manager.xml.erb","specificity":"default"},{"name":"sv-tomcat6-log-run.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-09f2bf988663175cd1b7973198dfb5eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=UnfNDP4pDzPM3PoLcLWyTnTa%2FKI%3D","checksum":"09f2bf988663175cd1b7973198dfb5eb","path":"templates/default/sv-tomcat6-log-run.erb","specificity":"default"}],"resources":[],"cookbook_name":"tomcat6","version":"0.1.0","recipes":[{"name":"default.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d45661e4b50f9677de7b8684af26ff9d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=r3CvyVe7dcOzB%2F0fNAun5ldGwr8%3D","checksum":"d45661e4b50f9677de7b8684af26ff9d","path":"recipes/default.rb","specificity":"default"}],"root_files":[{"name":"README.rdoc","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-14f6977f68c3674484e8289e361fb5a4?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=VNZxN%2B7CxO7ZbDHJOS%2FaTtpkPaE%3D","checksum":"14f6977f68c3674484e8289e361fb5a4","path":"README.rdoc","specificity":"default"},{"name":"metadata.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-abc416ffba9ea64ca71635191cb87af6?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=pemynt9Q1F%2BxlS26kLaz%2F4NDGO4%3D","checksum":"abc416ffba9ea64ca71635191cb87af6","path":"metadata.rb","specificity":"default"},{"name":"metadata.json","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-dd8473a8a7f2b446250ecdefb1882a5e?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=sHpayqP%2Fe4Luv20EMa3q%2FaMN4ms%3D","checksum":"dd8473a8a7f2b446250ecdefb1882a5e","path":"metadata.json","specificity":"default"}],"chef_type":"cookbook_version"} \ No newline at end of file +{ "attributes" : [ { "checksum" : "6e3fd0d16a87a55c569da108194ecb29", + "name" : "tomcat6.rb", + "path" : "attributes/tomcat6.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6e3fd0d16a87a55c569da108194ecb29?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zvYjsgUXIC7Xj3MT8Wd93esDGJM%3D" + } ], + "chef_type" : "cookbook_version", + "cookbook_name" : "tomcat6", + "definitions" : [ ], + "files" : [ { "checksum" : "18e534a72652f3d53b197ca4e5027009", + "name" : "org.apache.tomcat.tomcat6.plist", + "path" : "files/default/org.apache.tomcat.tomcat6.plist", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-18e534a72652f3d53b197ca4e5027009?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=M3fBL4t7uuYVXVah2PyZ8eL1QCc%3D" + }, + { "checksum" : "6a35ce92050296862ea63b784529d2e0", + "name" : "logging.properties", + "path" : "files/default/logging.properties", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6a35ce92050296862ea63b784529d2e0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=vRlKoye2%2Fwz8mdQI%2F3Ht916sllE%3D" + } + ], + "json_class" : "Chef::CookbookVersion", + "libraries" : [ { "checksum" : "2b6f7847142bb36823c570899669c54b", + "name" : "tomcat_manager.rb", + "path" : "libraries/tomcat_manager.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2b6f7847142bb36823c570899669c54b?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zxIoUKcGYWo9ir6qf1tTy3wvKZ4%3D" + }, + { "checksum" : "24db7b7dd6f04f8da5fa2b282910ac08", + "name" : "tomcat.rb", + "path" : "libraries/tomcat.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-24db7b7dd6f04f8da5fa2b282910ac08?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=c4Gbn5kX0ZaPbWvk5LAcR77sITg%3D" + } + ], + "metadata" : { "attributes" : { "tomcat6/with_native" : { "calculated" : false, + "choice" : [ ], + "default" : "false", + "description" : "works for centos, install tomcat-native libraries", + "display_name" : "Tomcat native support", + "recipes" : [ ], + "required" : "optional", + "type" : "string" + } }, + "conflicting" : { }, + "dependencies" : { }, + "description" : "Installs and configures all aspects of tomcat6 using custom local installation", + "groupings" : { }, + "license" : "Apache 2.0", + "long_description" : "= DESCRIPTION:\n\nInstalls Tomcat6\n\n= REQUIREMENTS:\n\n== Platform and Application Environment:\n\nTested on Centos 5.2 8.10. May work on other platforms, esp Redhat.\nNeeds Java at least Java 5\n\n== Cookbooks:\n\nOpscode cookbooks, http://github.com/opscode/cookbooks/tree/master:\n\n* java\n\n= ATTRIBUTES: \n\n= USAGE:\n\n\n= LICENSE and AUTHOR:\n \nAuthor:: Edmund Haselwanter ()\nCopyright:: 2009, Edmund Haselwanter\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", + "maintainer" : "Opscode, Inc.", + "maintainer_email" : "cookbooks@opscode.com", + "name" : "tomcat6", + "platforms" : { "centos" : "", + "debian" : "", + "redhat" : "", + "ubuntu" : "" + }, + "providing" : { }, + "recipes" : { "tomcat6" : "Main Tomcat 6 configuration" }, + "recommendations" : { }, + "replacing" : { }, + "suggestions" : { }, + "version" : "0.1.0" + }, + "name" : "tomcat6-0.1.0", + "providers" : [ ], + "recipes" : [ { "checksum" : "d45661e4b50f9677de7b8684af26ff9d", + "name" : "default.rb", + "path" : "recipes/default.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d45661e4b50f9677de7b8684af26ff9d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=r3CvyVe7dcOzB%2F0fNAun5ldGwr8%3D" + } ], + "resources" : [ ], + "root_files" : [ { "checksum" : "14f6977f68c3674484e8289e361fb5a4", + "name" : "README.rdoc", + "path" : "README.rdoc", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-14f6977f68c3674484e8289e361fb5a4?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=VNZxN%2B7CxO7ZbDHJOS%2FaTtpkPaE%3D" + }, + { "checksum" : "abc416ffba9ea64ca71635191cb87af6", + "name" : "metadata.rb", + "path" : "metadata.rb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-abc416ffba9ea64ca71635191cb87af6?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=pemynt9Q1F%2BxlS26kLaz%2F4NDGO4%3D" + }, + { "checksum" : "dd8473a8a7f2b446250ecdefb1882a5e", + "name" : "metadata.json", + "path" : "metadata.json", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-dd8473a8a7f2b446250ecdefb1882a5e?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=sHpayqP%2Fe4Luv20EMa3q%2FaMN4ms%3D" + } + ], + "templates" : [ { "checksum" : "107263b81e4700cf0adad7af2a133bbd", + "name" : "tomcat-users.xml.erb", + "path" : "templates/default/tomcat-users.xml.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-107263b81e4700cf0adad7af2a133bbd?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=QC7MNIauR2ox5MVlohf2i73uM1s%3D" + }, + { "checksum" : "fa4432b353fa57b9da26a4bff44285f2", + "name" : "sv-tomcat6-run.erb", + "path" : "templates/default/sv-tomcat6-run.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-fa4432b353fa57b9da26a4bff44285f2?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=q2rDeJFeh4oyhfv9ExMifGB0wxo%3D" + }, + { "checksum" : "33fd6f63133e7ebe28bc62e58773c408", + "name" : "manager.xml.erb", + "path" : "templates/default/manager.xml.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-33fd6f63133e7ebe28bc62e58773c408?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=rIijEhwLPf5PWTJOg%2BElbOquPBM%3D" + }, + { "checksum" : "09f2bf988663175cd1b7973198dfb5eb", + "name" : "sv-tomcat6-log-run.erb", + "path" : "templates/default/sv-tomcat6-log-run.erb", + "specificity" : "default", + "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-09f2bf988663175cd1b7973198dfb5eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=UnfNDP4pDzPM3PoLcLWyTnTa%2FKI%3D" + } + ], + "version" : "0.1.0" +} \ No newline at end of file diff --git a/enterprise/src/main/java/org/jclouds/enterprisechef/EnterpriseChefApi.java b/enterprise/src/main/java/org/jclouds/enterprisechef/EnterpriseChefApi.java index 04a7dda..0e0b2a6 100644 --- a/enterprise/src/main/java/org/jclouds/enterprisechef/EnterpriseChefApi.java +++ b/enterprise/src/main/java/org/jclouds/enterprisechef/EnterpriseChefApi.java @@ -29,7 +29,6 @@ import javax.ws.rs.PathParam; import javax.ws.rs.core.MediaType; import org.jclouds.Constants; -import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.chef.ChefApi; import org.jclouds.chef.filters.SignedHeaderAuth; @@ -56,20 +55,6 @@ import org.jclouds.rest.annotations.ResponseParser; @Headers(keys = "X-Chef-Version", values = "{" + Constants.PROPERTY_API_VERSION + "}") public interface EnterpriseChefApi extends ChefApi { - - /** - * Check if there exists a node with the given name. - * - * @return true if the specified node name exists. - */ - @Override - // Use get instead of HEAD - @Named("node:exists") - @GET - @Path("/nodes/{nodename}") - @Fallback(FalseOnNotFoundOr404.class) - boolean nodeExists(@PathParam("nodename") String nodename); - /** * Retrieves an existing user. * diff --git a/enterprise/src/main/java/org/jclouds/enterprisechef/domain/Group.java b/enterprise/src/main/java/org/jclouds/enterprisechef/domain/Group.java index 056acf4..2c0f058 100644 --- a/enterprise/src/main/java/org/jclouds/enterprisechef/domain/Group.java +++ b/enterprise/src/main/java/org/jclouds/enterprisechef/domain/Group.java @@ -16,11 +16,15 @@ */ package org.jclouds.enterprisechef.domain; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; import java.util.Set; -import com.google.common.collect.Sets; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; /** * Group object. @@ -28,22 +32,102 @@ import com.google.common.collect.Sets; * @author Ignasi Barrera */ public class Group { - private String name; - private String groupname; - private String orgname; - private Set actors = Sets.newHashSet(); - private Set clients = Sets.newHashSet(); - private Set groups = Sets.newHashSet(); - private Set users = Sets.newHashSet(); - - // When creating groups, only the group name property is considered - public Group(String groupname) { - this.groupname = checkNotNull(groupname, "groupname"); + public static Builder builder(String groupname) { + return new Builder(groupname); } - // Only for deserialization - Group() { + public static class Builder { + private String name; + private String groupname; + private String orgname; + private ImmutableSet.Builder actors = ImmutableSet.builder(); + private ImmutableSet.Builder clients = ImmutableSet.builder(); + private ImmutableSet.Builder groups = ImmutableSet.builder(); + private ImmutableSet.Builder users = ImmutableSet.builder(); + + public Builder(String groupname) { + this.groupname = groupname; + } + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder groupname(String groupname) { + this.groupname = checkNotNull(groupname, "groupname"); + return this; + } + + public Builder orgname(String orgname) { + this.orgname = checkNotNull(orgname, "orgname"); + return this; + } + + public Builder actor(String actor) { + this.actors.add(checkNotNull(actor, "actor")); + return this; + } + + public Builder actors(Iterable actors) { + this.actors.addAll(checkNotNull(actors, "actors")); + return this; + } + + public Builder client(String client) { + this.clients.add(checkNotNull(client, "client")); + return this; + } + + public Builder clients(Iterable clients) { + this.clients.addAll(checkNotNull(clients, "clients")); + return this; + } + + public Builder group(String group) { + this.groups.add(checkNotNull(group, "group")); + return this; + } + + public Builder groups(Iterable groups) { + this.groups.addAll(checkNotNull(groups, "groups")); + return this; + } + + public Builder user(String user) { + this.users.add(checkNotNull(user, "user")); + return this; + } + + public Builder users(Iterable users) { + this.users.addAll(checkNotNull(users, "users")); + return this; + } + + public Group build() { + return new Group(name, checkNotNull(groupname, "groupname"), orgname, actors.build(), clients.build(), + groups.build(), users.build()); + } + } + + private final String name; + private final String groupname; + private final String orgname; + private final Set actors; + private final Set clients; + private final Set groups; + private final Set users; + + @ConstructorProperties({ "name", "groupname", "orgname", "actors", "clients", "groups", "users" }) + public Group(String name, String groupname, String orgname, @Nullable Set actors, + @Nullable Set clients, @Nullable Set groups, @Nullable Set users) { + this.name = name; + this.groupname = groupname; + this.orgname = orgname; + this.actors = copyOfOrEmpty(actors); + this.clients = copyOfOrEmpty(clients); + this.groups = copyOfOrEmpty(groups); + this.users = copyOfOrEmpty(users); } public String getName() { @@ -74,18 +158,6 @@ public class Group { return users; } - public void setClients(Set clients) { - this.clients = clients; - } - - public void setGroups(Set groups) { - this.groups = groups; - } - - public void setUsers(Set users) { - this.users = users; - } - @Override public int hashCode() { final int prime = 31; diff --git a/enterprise/src/main/java/org/jclouds/enterprisechef/domain/User.java b/enterprise/src/main/java/org/jclouds/enterprisechef/domain/User.java index 247d1a8..c2c71fa 100644 --- a/enterprise/src/main/java/org/jclouds/enterprisechef/domain/User.java +++ b/enterprise/src/main/java/org/jclouds/enterprisechef/domain/User.java @@ -16,6 +16,9 @@ */ package org.jclouds.enterprisechef.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; import java.security.PublicKey; import com.google.gson.annotations.SerializedName; @@ -26,24 +29,110 @@ import com.google.gson.annotations.SerializedName; * @author Ignasi Barrera */ public class User { - private String username; + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String username; + private String firstName; + private String middleName; + private String lastName; + private String displayName; + private String email; + private PublicKey publicKey; + + public Builder username(String username) { + this.username = checkNotNull(username, "username"); + return this; + } + + public Builder firstName(String firstName) { + this.firstName = checkNotNull(firstName, "firstName"); + return this; + } + + public Builder middleName(String middleName) { + this.middleName = checkNotNull(middleName, "middleName"); + return this; + } + + public Builder lastName(String lastName) { + this.lastName = checkNotNull(lastName, "lastName"); + return this; + } + + public Builder displayName(String displayName) { + this.displayName = checkNotNull(displayName, "displayName"); + return this; + } + + public Builder email(String email) { + this.email = checkNotNull(email, "email"); + return this; + } + + public Builder publicKey(PublicKey publicKey) { + this.publicKey = checkNotNull(publicKey, "publicKey"); + return this; + } + + public User build() { + return new User(username, firstName, middleName, lastName, displayName, email, publicKey); + } + } + + private final String username; @SerializedName("first_name") - private String firstName; + private final String firstName; @SerializedName("middle_name") - private String middleName; + private final String middleName; @SerializedName("last_name") - private String lastName; + private final String lastName; @SerializedName("display_name") - private String displayName; - private String email; + private final String displayName; + private final String email; @SerializedName("public_key") - private PublicKey publicKey; + private final PublicKey publicKey; + + @ConstructorProperties({ "username", "first_name", "middle_name", "last_name", "display_name", "email", "public_key" }) + protected User(String username, String firstName, String middleName, String lastName, String displayName, + String email, PublicKey publicKey) { + this.username = username; + this.firstName = firstName; + this.middleName = middleName; + this.lastName = lastName; + this.displayName = displayName; + this.email = email; + this.publicKey = publicKey; + } + + public String getUsername() { + return username; + } + + public String getFirstName() { + return firstName; + } - // TODO: Add a constructor to allow creating users. Need an Enterprise Chef instance! + public String getMiddleName() { + return middleName; + } - // Only for deserialization - User() { + public String getLastName() { + return lastName; + } + public String getDisplayName() { + return displayName; + } + + public String getEmail() { + return email; + } + + public PublicKey getPublicKey() { + return publicKey; } @Override @@ -124,34 +213,6 @@ public class User { return true; } - public String getUsername() { - return username; - } - - public String getFirstName() { - return firstName; - } - - public String getMiddleName() { - return middleName; - } - - public String getLastName() { - return lastName; - } - - public String getDisplayName() { - return displayName; - } - - public String getEmail() { - return email; - } - - public PublicKey getPublicKey() { - return publicKey; - } - @Override public String toString() { return "User [username=" + username + ", firstName=" + firstName + ", middleName=" + middleName + ", lastName=" diff --git a/enterprise/src/test/java/org/jclouds/enterprisechef/EnterpriseChefApiExpectTest.java b/enterprise/src/test/java/org/jclouds/enterprisechef/EnterpriseChefApiExpectTest.java index e859dc2..1ee2bdf 100644 --- a/enterprise/src/test/java/org/jclouds/enterprisechef/EnterpriseChefApiExpectTest.java +++ b/enterprise/src/test/java/org/jclouds/enterprisechef/EnterpriseChefApiExpectTest.java @@ -27,8 +27,6 @@ import javax.ws.rs.core.MediaType; import org.jclouds.chef.BaseChefApiExpectTest; import org.jclouds.chef.ChefApi; import org.jclouds.date.TimeStamp; -import org.jclouds.enterprisechef.EnterpriseChefApi; -import org.jclouds.enterprisechef.EnterpriseChefProviderMetadata; import org.jclouds.enterprisechef.config.EnterpriseChefHttpApiModule; import org.jclouds.enterprisechef.domain.Group; import org.jclouds.enterprisechef.domain.User; @@ -40,7 +38,6 @@ import org.jclouds.rest.ResourceNotFoundException; import org.testng.annotations.Test; import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableSet; import com.google.inject.Module; /** @@ -174,11 +171,7 @@ public class EnterpriseChefApiExpectTest extends BaseChefApiExpectTest