Issue 191: added json literal support with default mapping on JsonBall class; updated chef implementation

This commit is contained in:
Adrian Cole 2010-07-21 01:50:44 -07:00
parent 76f75049f1
commit 7c2b014f25
26 changed files with 1569 additions and 300 deletions

View File

@ -41,15 +41,17 @@ import org.jclouds.chef.binders.BindClientnameToJsonPayload;
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload; import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
import org.jclouds.chef.binders.BindIsCompletedToJsonPayload; import org.jclouds.chef.binders.BindIsCompletedToJsonPayload;
import org.jclouds.chef.binders.NodeName; import org.jclouds.chef.binders.NodeName;
import org.jclouds.chef.binders.RoleName;
import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.Client;
import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Node;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox; import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.chef.filters.SignedHeaderAuth;
import org.jclouds.chef.functions.ParseKeyFromJson; import org.jclouds.chef.functions.ParseKeyFromJson;
import org.jclouds.chef.functions.ParseKeySetFromJson; import org.jclouds.chef.functions.ParseKeySetFromJson;
import org.jclouds.http.functions.ReturnStringIf2xx; import org.jclouds.domain.JsonBall;
import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Headers;
@ -180,7 +182,6 @@ public interface ChefAsyncClient {
@DELETE @DELETE
@Path("clients/{clientname}") @Path("clients/{clientname}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(ReturnStringIf2xx.class)
ListenableFuture<Client> deleteClient(@PathParam("clientname") String clientname); ListenableFuture<Client> deleteClient(@PathParam("clientname") String clientname);
/** /**
@ -239,4 +240,102 @@ public interface ChefAsyncClient {
@ResponseParser(ParseKeySetFromJson.class) @ResponseParser(ParseKeySetFromJson.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<String>> listNodes(); ListenableFuture<Set<String>> listNodes();
/**
* @see ChefClient#createRole
*/
@POST
@Path("roles")
ListenableFuture<Role> createRole(@BinderParam(BindToJsonPayload.class) Role role);
/**
* @see ChefClient#updateRole
*/
@PUT
@Path("roles/{rolename}")
ListenableFuture<Role> updateRole(
@PathParam("rolename") @ParamParser(RoleName.class) @BinderParam(BindToJsonPayload.class) Role role);
/**
* @see ChefRole#roleExists
*/
@HEAD
@Path("roles/{rolename}")
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
ListenableFuture<Boolean> roleExists(@PathParam("rolename") String rolename);
/**
* @see ChefRole#getRole
*/
@GET
@Path("roles/{rolename}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Role> getRole(@PathParam("rolename") String rolename);
/**
* @see ChefRole#deleteRole
*/
@DELETE
@Path("roles/{rolename}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Role> deleteRole(@PathParam("rolename") String rolename);
/**
* @see ChefRole#listRoles
*/
@GET
@Path("roles")
@ResponseParser(ParseKeySetFromJson.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<String>> listRoles();
/**
* @see ChefClient#createDataBag
*/
@POST
@Path("data")
ListenableFuture<JsonBall> createDataBag(@BinderParam(BindToJsonPayload.class) JsonBall node);
/**
* @see ChefClient#updateDataBag
*/
@PUT
@Path("data/{path}")
ListenableFuture<JsonBall> updateDataBag(
@PathParam("path") String path, @BinderParam(BindToJsonPayload.class) JsonBall node);
/**
* @see ChefDataBag#nodeExists
*/
@HEAD
@Path("data/{path}")
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
ListenableFuture<Boolean> dataBagExists(@PathParam("path") String path);
/**
* @see ChefDataBag#getDataBag
*/
@GET
@Path("data/{path}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<JsonBall> getDataBag(@PathParam("path") String path);
/**
* @see ChefDataBag#deleteDataBag
*/
@DELETE
@Path("data/{path}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<JsonBall> deleteDataBag(@PathParam("path") String path);
/**
* @see ChefDataBag#listDataBags
*/
@GET
@Path("data")
@ResponseParser(ParseKeySetFromJson.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<String>> listDataBags();
} }

View File

@ -47,6 +47,8 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.Client;
import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox; import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
@ -89,18 +91,9 @@ public interface ChefClient {
Set<String> listCookbooks(); Set<String> listCookbooks();
/** /**
* Creates or updates (uploads) a cookbook with the name present from the * Creates or updates (uploads) a cookbook //TODO document
* tar/gz file.
* *
* @param cookbookName * @param cookbookName
* matches the root directory path of the archive
* @param tgzArchive
* tar gz archive, with a base path of {@code cookbookName}
* <p/>
* "401 Unauthorized" if the caller is not a recognized user.
* <p/>
* "403 Forbidden" if you do not have permission to create
* cookbooks.
* @throws HttpResponseException * @throws HttpResponseException
* "409 Conflict" if the cookbook already exists * "409 Conflict" if the cookbook already exists
*/ */
@ -227,4 +220,150 @@ public interface ChefClient {
* "403 Forbidden" if you do not have view rights on the client. * "403 Forbidden" if you do not have view rights on the client.
*/ */
Client getClient(String name); Client getClient(String name);
/**
* creates a new node
*
* @return //TODO
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if the caller is not a recognized user.
* <p/>
* "403 Forbidden" if the caller is not authorized to create a
* node.
* @throws HttpResponseException
* "409 Conflict" if the node already exists
*/
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
Node createNode(Node node);
/**
* Creates or updates (uploads) a node //TODO document
*
* @param nodeName
* @throws HttpResponseException
* "409 Conflict" if the node already exists
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
Node updateNode(Node node);
/**
* @return list of node names.
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have rights to list nodes.
*/
Set<String> listNodes();
/**
*
* @return true if the specified node name exists.
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have rights to view the node.
*/
boolean nodeExists(String name);
/**
* deletes an existing node.
*
* @return last state of the node you deleted or null, if not found
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have Delete rights on the node.
*/
Node deleteNode(String name);
/**
* gets an existing node.
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have view rights on the node.
*/
Node getNode(String name);
/**
* creates a new role
*
* @return //TODO
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if the caller is not a recognized user.
* <p/>
* "403 Forbidden" if the caller is not authorized to create a
* role.
* @throws HttpResponseException
* "409 Conflict" if the role already exists
*/
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
Role createRole(Role role);
/**
* Creates or updates (uploads) a role //TODO document
*
* @param roleName
* @throws HttpResponseException
* "409 Conflict" if the role already exists
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
Role updateRole(Role role);
/**
* @return list of role names.
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have rights to list roles.
*/
Set<String> listRoles();
/**
*
* @return true if the specified role name exists.
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have rights to view the role.
*/
boolean roleExists(String name);
/**
* deletes an existing role.
*
* @return last state of the role you deleted or null, if not found
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have Delete rights on the role.
*/
Role deleteRole(String name);
/**
* gets an existing role.
*
* @throws AuthorizationException
* <p/>
* "401 Unauthorized" if you are not a recognized user.
* <p/>
* "403 Forbidden" if you do not have view rights on the role.
*/
Role getRole(String name);
} }

View File

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

View File

@ -0,0 +1,83 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.chef.config;
import java.lang.reflect.Type;
import java.util.Map;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.chef.domain.DataBagItem;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonLiteral;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
import com.google.inject.Provides;
/**
*
*
* @author Adrian Cole
*/
public class ChefParserModule extends AbstractModule {
@ImplementedBy(DataBagItemAdapterImpl.class)
public static interface DataBagItemAdapter extends JsonSerializer<DataBagItem>, JsonDeserializer<DataBagItem> {
}
@Singleton
public static class DataBagItemAdapterImpl implements DataBagItemAdapter {
@Override
public JsonElement serialize(DataBagItem src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonLiteral(src.toString());
}
@Override
public DataBagItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
IdHolder idHolder = context.deserialize(json, IdHolder.class);
return new DataBagItem(idHolder.id, json.toString());
}
}
private static class IdHolder {
private String id;
}
@Provides
@Singleton
@Named(Constants.PROPERTY_GSON_ADAPTERS)
public Map<Type, Object> provideCustomAdapterBindings(DataBagItemAdapter adapter) {
return ImmutableMap.<Type, Object> of(DataBagItem.class, adapter);
}
@Override
protected void configure() {
}
}

View File

@ -48,9 +48,8 @@ public class Attribute {
private String displayName; private String displayName;
private String description; private String description;
public Attribute(String required, boolean calculated, Set<String> choice, public Attribute(String required, boolean calculated, Set<String> choice, String defaultValue, String type,
String defaultValue, String type, List<String> recipes, List<String> recipes, String displayName, String description) {
String displayName, String description) {
this.required = required; this.required = required;
this.calculated = calculated; this.calculated = calculated;
Iterables.addAll(this.choice, choice); Iterables.addAll(this.choice, choice);
@ -102,12 +101,9 @@ public class Attribute {
int result = 1; int result = 1;
result = prime * result + (calculated ? 1231 : 1237); result = prime * result + (calculated ? 1231 : 1237);
result = prime * result + ((choice == null) ? 0 : choice.hashCode()); result = prime * result + ((choice == null) ? 0 : choice.hashCode());
result = prime * result result = prime * result + ((defaultValue == null) ? 0 : defaultValue.hashCode());
+ ((defaultValue == null) ? 0 : defaultValue.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result result = prime * result + ((displayName == null) ? 0 : displayName.hashCode());
+ ((description == null) ? 0 : description.hashCode());
result = prime * result
+ ((displayName == null) ? 0 : displayName.hashCode());
result = prime * result + ((recipes == null) ? 0 : recipes.hashCode()); result = prime * result + ((recipes == null) ? 0 : recipes.hashCode());
result = prime * result + ((required == null) ? 0 : required.hashCode()); result = prime * result + ((required == null) ? 0 : required.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode());
@ -165,10 +161,9 @@ public class Attribute {
@Override @Override
public String toString() { public String toString() {
return "Attribute [calculated=" + calculated + ", choice=" + choice return "Attribute [calculated=" + calculated + ", choice=" + choice + ", defaultValue=" + defaultValue
+ ", defaultValue=" + defaultValue + ", description=" + description + ", description=" + description + ", displayName=" + displayName + ", recipes=" + recipes + ", required="
+ ", displayName=" + displayName + ", recipes=" + recipes + required + ", type=" + type + "]";
+ ", required=" + required + ", type=" + type + "]";
} }
} }

View File

@ -61,10 +61,10 @@ public class CookbookVersion {
this.name = cookbookName + "-" + version; this.name = cookbookName + "-" + version;
} }
public CookbookVersion(String name, Set<Resource> definitions, Set<Resource> attributes, public CookbookVersion(String name, Set<Resource> definitions, Set<Resource> attributes, Set<Resource> files,
Set<Resource> files, Metadata metadata, Set<Resource> providers, String cookbookName, Metadata metadata, Set<Resource> providers, String cookbookName, Set<Resource> resources,
Set<Resource> resources, Set<Resource> templates, Set<Resource> libraries, Set<Resource> templates, Set<Resource> libraries, String version, Set<Resource> recipes,
String version, Set<Resource> recipes, Set<Resource> rootFiles) { Set<Resource> rootFiles) {
this.name = name; this.name = name;
Iterables.addAll(this.definitions, definitions); Iterables.addAll(this.definitions, definitions);
Iterables.addAll(this.attributes, attributes); Iterables.addAll(this.attributes, attributes);
@ -236,11 +236,10 @@ public class CookbookVersion {
@Override @Override
public String toString() { public String toString() {
return "Cookbook [attributes=" + attributes + ", cookbookName=" + cookbookName return "Cookbook [attributes=" + attributes + ", cookbookName=" + cookbookName + ", definitions=" + definitions
+ ", definitions=" + definitions + ", files=" + files + ", libraries=" + libraries + ", files=" + files + ", libraries=" + libraries + ", metadata=" + metadata + ", name=" + name
+ ", metadata=" + metadata + ", name=" + name + ", providers=" + providers + ", providers=" + providers + ", recipes=" + recipes + ", resources=" + resources + ", rootFiles="
+ ", recipes=" + recipes + ", resources=" + resources + ", rootFiles=" + rootFiles + rootFiles + ", templates=" + templates + ", version=" + version + "]";
+ ", templates=" + templates + ", version=" + version + "]";
} }
} }

View File

@ -0,0 +1,49 @@
package org.jclouds.chef.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.domain.JsonBall;
/**
*
* @author Adrian Cole
*/
public class DataBagItem extends JsonBall {
private static final long serialVersionUID = 7905637919304343493L;
private final String id;
public DataBagItem(String id, String value) {
super(value);
this.id = checkNotNull(id, "id");
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
DataBagItem other = (DataBagItem) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
public String getId() {
return id;
}
}

View File

@ -51,15 +51,11 @@ public class Metadata {
private Map<String, Attribute> attributes = Maps.newLinkedHashMap(); private Map<String, Attribute> attributes = Maps.newLinkedHashMap();
private Map<String, String> recommendations = Maps.newLinkedHashMap(); private Map<String, String> recommendations = Maps.newLinkedHashMap();
public Metadata(String license, String maintainer, public Metadata(String license, String maintainer, Map<String, String> suggestions,
Map<String, String> suggestions, Map<String, Set<String>> dependencies, String maintainerEmail, Map<String, Set<String>> conflicting,
Map<String, Set<String>> dependencies, String maintainerEmail, String description, Map<String, Set<String>> providing, Map<String, Set<String>> platforms, String version,
Map<String, Set<String>> conflicting, String description, Map<String, String> recipes, Map<String, Set<String>> replacing, String name, Map<String, String> groupings,
Map<String, Set<String>> providing, String longDescription, Map<String, Attribute> attributes, Map<String, String> recommendations) {
Map<String, Set<String>> platforms, String version,
Map<String, String> recipes, Map<String, Set<String>> replacing,
String name, Map<String, String> groupings, String longDescription,
Map<String, Attribute> attributes, Map<String, String> recommendations) {
this.license = license; this.license = license;
this.maintainer = maintainer; this.maintainer = maintainer;
this.suggestions.putAll(suggestions); this.suggestions.putAll(suggestions);
@ -154,35 +150,22 @@ public class Metadata {
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
+ ((attributes == null) ? 0 : attributes.hashCode()); result = prime * result + ((conflicting == null) ? 0 : conflicting.hashCode());
result = prime * result result = prime * result + ((dependencies == null) ? 0 : dependencies.hashCode());
+ ((conflicting == null) ? 0 : conflicting.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result result = prime * result + ((groupings == null) ? 0 : groupings.hashCode());
+ ((dependencies == null) ? 0 : dependencies.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
result = prime * result
+ ((groupings == null) ? 0 : groupings.hashCode());
result = prime * result + ((license == null) ? 0 : license.hashCode()); result = prime * result + ((license == null) ? 0 : license.hashCode());
result = prime * result result = prime * result + ((longDescription == null) ? 0 : longDescription.hashCode());
+ ((longDescription == null) ? 0 : longDescription.hashCode()); result = prime * result + ((maintainer == null) ? 0 : maintainer.hashCode());
result = prime * result result = prime * result + ((maintainerEmail == null) ? 0 : maintainerEmail.hashCode());
+ ((maintainer == null) ? 0 : maintainer.hashCode());
result = prime * result
+ ((maintainerEmail == null) ? 0 : maintainerEmail.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result result = prime * result + ((platforms == null) ? 0 : platforms.hashCode());
+ ((platforms == null) ? 0 : platforms.hashCode()); result = prime * result + ((providing == null) ? 0 : providing.hashCode());
result = prime * result
+ ((providing == null) ? 0 : providing.hashCode());
result = prime * result + ((recipes == null) ? 0 : recipes.hashCode()); result = prime * result + ((recipes == null) ? 0 : recipes.hashCode());
result = prime * result result = prime * result + ((recommendations == null) ? 0 : recommendations.hashCode());
+ ((recommendations == null) ? 0 : recommendations.hashCode()); result = prime * result + ((replacing == null) ? 0 : replacing.hashCode());
result = prime * result result = prime * result + ((suggestions == null) ? 0 : suggestions.hashCode());
+ ((replacing == null) ? 0 : replacing.hashCode());
result = prime * result
+ ((suggestions == null) ? 0 : suggestions.hashCode());
result = prime * result + ((version == null) ? 0 : version.hashCode()); result = prime * result + ((version == null) ? 0 : version.hashCode());
return result; return result;
} }
@ -286,15 +269,12 @@ public class Metadata {
@Override @Override
public String toString() { public String toString() {
return "Metadata [attributes=" + attributes + ", conflicting=" return "Metadata [attributes=" + attributes + ", conflicting=" + conflicting + ", dependencies=" + dependencies
+ conflicting + ", dependencies=" + dependencies + ", description=" + ", description=" + description + ", groupings=" + groupings + ", license=" + license
+ description + ", groupings=" + groupings + ", license=" + license + ", longDescription=" + longDescription + ", maintainer=" + maintainer + ", maintainerEmail="
+ ", longDescription=" + longDescription + ", maintainer=" + maintainerEmail + ", name=" + name + ", platforms=" + platforms + ", providing=" + providing
+ maintainer + ", maintainerEmail=" + maintainerEmail + ", name=" + ", recipes=" + recipes + ", recommendations=" + recommendations + ", replacing=" + replacing
+ name + ", platforms=" + platforms + ", providing=" + providing + ", suggestions=" + suggestions + ", version=" + version + "]";
+ ", recipes=" + recipes + ", recommendations=" + recommendations
+ ", replacing=" + replacing + ", suggestions=" + suggestions
+ ", version=" + version + "]";
} }
} }

View File

@ -21,6 +21,8 @@ package org.jclouds.chef.domain;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.jclouds.domain.JsonBall;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -34,22 +36,20 @@ import com.google.gson.annotations.SerializedName;
public class Node { public class Node {
private String name; private String name;
private Map<String, Attribute> normal = Maps.newLinkedHashMap(); private Map<String, JsonBall> normal = Maps.newLinkedHashMap();
private Map<String, Attribute> override = Maps.newLinkedHashMap(); private Map<String, JsonBall> override = Maps.newLinkedHashMap();
@SerializedName("default") @SerializedName("default")
private Map<String, Attribute> defaultA = Maps.newLinkedHashMap(); private Map<String, JsonBall> defaultA = Maps.newLinkedHashMap();
private Map<String, Attribute> automatic = Maps.newLinkedHashMap(); private Map<String, JsonBall> automatic = Maps.newLinkedHashMap();
@SerializedName("run_list") @SerializedName("run_list")
private List<String> runList = Lists.newArrayList(); private List<String> runList = Lists.newArrayList();
// internal // internal
@SuppressWarnings("unused")
@SerializedName("json_class") @SerializedName("json_class")
private String _jsonClass = "Chef::Node"; private String _jsonClass = "Chef::Node";
public Node(String name, Map<String, Attribute> normal, public Node(String name, Map<String, JsonBall> normal, Map<String, JsonBall> override,
Map<String, Attribute> override, Map<String, Attribute> defaultA, Map<String, JsonBall> defaultA, Map<String, JsonBall> automatic, Iterable<String> runList) {
Map<String, Attribute> automatic, Iterable<String> runList) {
this.name = name; this.name = name;
this.normal.putAll(normal); this.normal.putAll(normal);
this.override.putAll(override); this.override.putAll(override);
@ -60,9 +60,8 @@ public class Node {
@Override @Override
public String toString() { public String toString() {
return "Node [name=" + name + ", runList=" + runList + ", normal=" return "Node [name=" + name + ", runList=" + runList + ", normal=" + normal + ", default=" + defaultA
+ normal + ", default=" + defaultA + ", override=" + override + ", override=" + override + ", automatic=" + automatic + "]";
+ ", automatic=" + automatic + "]";
} }
public Node(String name, Iterable<String> runList) { public Node(String name, Iterable<String> runList) {
@ -79,19 +78,19 @@ public class Node {
return name; return name;
} }
public Map<String, Attribute> getNormal() { public Map<String, JsonBall> getNormal() {
return normal; return normal;
} }
public Map<String, Attribute> getOverride() { public Map<String, JsonBall> getOverride() {
return override; return override;
} }
public Map<String, Attribute> getDefault() { public Map<String, JsonBall> getDefault() {
return defaultA; return defaultA;
} }
public Map<String, Attribute> getAutomatic() { public Map<String, JsonBall> getAutomatic() {
return automatic; return automatic;
} }
@ -100,15 +99,15 @@ public class Node {
} }
@SerializedName("chef_type") @SerializedName("chef_type")
@SuppressWarnings("unused")
private String _chefType = "node"; private String _chefType = "node";
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode());
+ ((automatic == null) ? 0 : automatic.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 + ((defaultA == null) ? 0 : defaultA.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((normal == null) ? 0 : normal.hashCode()); result = prime * result + ((normal == null) ? 0 : normal.hashCode());
@ -126,6 +125,16 @@ public class Node {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
Node other = (Node) obj; Node other = (Node) obj;
if (_chefType == null) {
if (other._chefType != null)
return false;
} else if (!_chefType.equals(other._chefType))
return false;
if (_jsonClass == null) {
if (other._jsonClass != null)
return false;
} else if (!_jsonClass.equals(other._jsonClass))
return false;
if (automatic == null) { if (automatic == null) {
if (other.automatic != null) if (other.automatic != null)
return false; return false;

View File

@ -125,8 +125,8 @@ public class Organization implements Comparable<Organization> {
@Override @Override
public String toString() { public String toString() {
return "Organization [clientname=" + clientname + ", fullName=" + fullName + ", name=" + name return "Organization [clientname=" + clientname + ", fullName=" + fullName + ", name=" + name + ", orgType="
+ ", orgType=" + orgType + "]"; + orgType + "]";
} }
} }

View File

@ -0,0 +1,159 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.chef.domain;
import java.util.List;
import java.util.Map;
import org.jclouds.domain.JsonBall;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.annotations.SerializedName;
/**
* Sandbox object.
*
* @author Adrian Cole
*/
public class Role {
private String name;
private String description;
@SerializedName("override_attributes")
private Map<String, JsonBall> override = Maps.newLinkedHashMap();
@SerializedName("default_attributes")
private Map<String, JsonBall> defaultA = Maps.newLinkedHashMap();
@SerializedName("run_list")
private List<String> runList = Lists.newArrayList();
// internal
@SerializedName("json_class")
private String _jsonClass = "Chef::Role";
@SerializedName("chef_type")
private String _chefType = "role";
public Role(String name, String description, Map<String, JsonBall> defaultA, List<String> runList,
Map<String, JsonBall> override) {
this.name = name;
this.description = description;
this.defaultA = defaultA;
this.runList = runList;
this.override = override;
}
public Role(String name, Iterable<String> runList) {
this.name = name;
Iterables.addAll(this.runList, runList);
}
// hidden but needs to be here for json deserialization to work
Role() {
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Map<String, JsonBall> getOverride() {
return override;
}
public Map<String, JsonBall> getDefault() {
return defaultA;
}
public List<String> getRunList() {
return runList;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode());
result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode());
result = prime * result + ((defaultA == null) ? 0 : defaultA.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((override == null) ? 0 : override.hashCode());
result = prime * result + ((runList == null) ? 0 : runList.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Role other = (Role) obj;
if (_chefType == null) {
if (other._chefType != null)
return false;
} else if (!_chefType.equals(other._chefType))
return false;
if (_jsonClass == null) {
if (other._jsonClass != null)
return false;
} else if (!_jsonClass.equals(other._jsonClass))
return false;
if (defaultA == null) {
if (other.defaultA != null)
return false;
} else if (!defaultA.equals(other.defaultA))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (override == null) {
if (other.override != null)
return false;
} else if (!override.equals(other.override))
return false;
if (runList == null) {
if (other.runList != null)
return false;
} else if (!runList.equals(other.runList))
return false;
return true;
}
@Override
public String toString() {
return "[name=" + name + ", description=" + description + ", defaultA=" + defaultA + ", override=" + override
+ ", runList=" + runList + "]";
}
}

View File

@ -50,8 +50,7 @@ public class Sandbox {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private String _chefType = "sandbox"; private String _chefType = "sandbox";
public Sandbox(String rev, boolean isCompleted, Date createTime, Iterable<String> checksums, public Sandbox(String rev, boolean isCompleted, Date createTime, Iterable<String> checksums, String name, String guid) {
String name, String guid) {
this.rev = rev; this.rev = rev;
this.isCompleted = isCompleted; this.isCompleted = isCompleted;
this.createTime = createTime; this.createTime = createTime;
@ -142,7 +141,7 @@ public class Sandbox {
@Override @Override
public String toString() { public String toString() {
return "Sandbox [checksums=" + checksums + ", createTime=" + createTime + ", guid=" + guid return "Sandbox [checksums=" + checksums + ", createTime=" + createTime + ", guid=" + guid + ", isCompleted="
+ ", isCompleted=" + isCompleted + ", name=" + name + ", rev=" + rev + "]"; + isCompleted + ", name=" + name + ", rev=" + rev + "]";
} }
} }

View File

@ -171,9 +171,8 @@ public class User implements Comparable<User> {
@Override @Override
public String toString() { public String toString() {
return "User [displayName=" + displayName + ", email=" + email + ", firstName=" + firstName return "User [displayName=" + displayName + ", email=" + email + ", firstName=" + firstName + ", lastName="
+ ", lastName=" + lastName + ", middleName=" + middleName + ", password=" + password + lastName + ", middleName=" + middleName + ", password=" + password + ", username=" + username + "]";
+ ", username=" + username + "]";
} }
} }

View File

@ -32,6 +32,8 @@ import java.util.Set;
import org.jclouds.chef.config.ChefRestClientModule; import org.jclouds.chef.config.ChefRestClientModule;
import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.chef.filters.SignedHeaderAuth;
import org.jclouds.chef.filters.SignedHeaderAuthTest; import org.jclouds.chef.filters.SignedHeaderAuthTest;
import org.jclouds.chef.functions.ParseKeyFromJson; import org.jclouds.chef.functions.ParseKeyFromJson;
@ -41,7 +43,6 @@ import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ParseJson;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
@ -196,7 +197,7 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false); assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class); assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
@ -204,21 +205,6 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
} }
public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\", \"private_key\": true}", "application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testCreateClient() throws SecurityException, NoSuchMethodException, IOException { public void testCreateClient() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("createClient", String.class); Method method = ChefAsyncClient.class.getMethod("createClient", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client"); GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
@ -251,6 +237,193 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
} }
public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\", \"private_key\": true}", "application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testNodeExists() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("nodeExists", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "node");
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/nodes/node HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDeleteNode() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("deleteNode", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "node");
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/nodes/node HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testCreateNode() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("createNode", Node.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Node("testnode",
ImmutableSet.of("recipe[java]")));
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/nodes HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(
httpRequest,
"{\"name\":\"testnode\",\"normal\":{},\"override\":{},\"default\":{},\"automatic\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Node\",\"chef_type\":\"node\"}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testUpdateNode() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("updateNode", Node.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Node("testnode",
ImmutableSet.of("recipe[java]")));
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/nodes/testnode HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(
httpRequest,
"{\"name\":\"testnode\",\"normal\":{},\"override\":{},\"default\":{},\"automatic\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Node\",\"chef_type\":\"node\"}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testListNodes() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("listNodes");
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/nodes HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testRoleExists() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("roleExists", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "role");
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/roles/role HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDeleteRole() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("deleteRole", String.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "role");
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/roles/role HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testCreateRole() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("createRole", Role.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Role("testrole",
ImmutableSet.of("recipe[java]")));
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/roles HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(
httpRequest,
"{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testUpdateRole() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("updateRole", Role.class);
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, new Role("testrole",
ImmutableSet.of("recipe[java]")));
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/roles/testrole HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(
httpRequest,
"{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{},\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testListRoles() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncClient.class.getMethod("listRoles");
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/roles HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.6\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override @Override
protected void checkFilters(HttpRequest request) { protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1); assertEquals(request.getFilters().size(), 1);

View File

@ -30,13 +30,16 @@ import static org.testng.Assert.assertNotNull;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.jclouds.chef.domain.ChecksumStatus; import org.jclouds.chef.domain.ChecksumStatus;
import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.domain.Resource; import org.jclouds.chef.domain.Resource;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.FilePayload; import org.jclouds.io.payloads.FilePayload;
@ -70,6 +73,8 @@ public class ChefClientLiveTest {
private String endpoint; private String endpoint;
private String validator; private String validator;
private String user; private String user;
private Node node;
private Role role;
public static final String PREFIX = System.getProperty("user.name") + "-jcloudstest"; public static final String PREFIX = System.getProperty("user.name") + "-jcloudstest";
@ -86,52 +91,32 @@ public class ChefClientLiveTest {
String keyfile = System.getProperty("jclouds.test.credential"); String keyfile = System.getProperty("jclouds.test.credential");
if (keyfile == null || keyfile.equals("")) if (keyfile == null || keyfile.equals(""))
keyfile = System.getProperty("user.home") + "/.chef/" + user + ".pem"; keyfile = System.getProperty("user.home") + "/.chef/" + user + ".pem";
validatorConnection = createConnection(validator, Files.toString(new File(validatorKey), validatorConnection = createConnection(validator, Files.toString(new File(validatorKey), Charsets.UTF_8));
Charsets.UTF_8));
adminConnection = createConnection(user, Files.toString(new File(keyfile), Charsets.UTF_8)); adminConnection = createConnection(user, Files.toString(new File(keyfile), Charsets.UTF_8));
} }
private RestContext<ChefClient, ChefAsyncClient> createConnection(String identity, String key) private RestContext<ChefClient, ChefAsyncClient> createConnection(String identity, String key) throws IOException {
throws IOException {
Properties props = new Properties(); Properties props = new Properties();
props.setProperty("chef.endpoint", endpoint); props.setProperty("chef.endpoint", endpoint);
return new RestContextFactory().createContext("chef", identity, key, ImmutableSet return new RestContextFactory().createContext("chef", identity, key, ImmutableSet
.<Module> of(new Log4JLoggingModule()), props); .<Module> of(new Log4JLoggingModule()), props);
} }
@Test
public void testListClients() throws Exception {
Set<String> clients = validatorConnection.getApi().listClients();
assertNotNull(clients);
assert clients.contains(validator) : "validator: " + validator + " not in: " + clients;
}
@Test(dependsOnMethods = "testListClients")
public void testCreateClient() throws Exception {
validatorConnection.getApi().deleteClient(PREFIX);
clientKey = validatorConnection.getApi().createClient(PREFIX);
assertNotNull(clientKey);
System.out.println(clientKey);
clientConnection = createConnection(PREFIX, clientKey);
clientConnection.getApi().clientExists(PREFIX);
}
public void testCreateNewCookbook() throws Exception { 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"), FilePayload content = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml"));
"pom.xml"));
// 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
adminConnection.utils().encryption().generateMD5BufferingIfNotRepeatable(content); adminConnection.utils().encryption().generateMD5BufferingIfNotRepeatable(content);
// Note that java collections cannot effectively do equals or hashcodes on byte arrays, // Note that java collections cannot effectively do equals or hashcodes on
// byte arrays,
// so let's convert to a list of bytes. // so let's convert to a list of bytes.
List<Byte> md5 = Bytes.asList(content.getContentMD5()); List<Byte> md5 = Bytes.asList(content.getContentMD5());
// request an upload site for this file // request an upload site for this file
UploadSandbox site = adminConnection.getApi().getUploadSandboxForChecksums( UploadSandbox site = adminConnection.getApi().getUploadSandboxForChecksums(ImmutableSet.of(md5));
ImmutableSet.of(md5));
try { try {
assert site.getChecksums().containsKey(md5) : md5 + " not in " + site.getChecksums(); assert site.getChecksums().containsKey(md5) : md5 + " not in " + site.getChecksums();
@ -165,22 +150,16 @@ public class ChefClientLiveTest {
clientConnection.getApi().clientExists(PREFIX); clientConnection.getApi().clientExists(PREFIX);
} }
@Test(dependsOnMethods = "testCreateClient")
public void testClientExists() throws Exception {
assertNotNull(validatorConnection.getApi().clientExists(PREFIX));
}
@Test(dependsOnMethods = "testCreateNewCookbook") @Test(dependsOnMethods = "testCreateNewCookbook")
public void testListCookbooks() throws Exception { public void testListCookbooks() throws Exception {
for (String cookbook : adminConnection.getApi().listCookbooks()) for (String cookbook : adminConnection.getApi().listCookbooks())
for (String version : adminConnection.getApi().getVersionsOfCookbook(cookbook)) { for (String version : adminConnection.getApi().getVersionsOfCookbook(cookbook)) {
System.err.printf("%s/%s:%n", cookbook, version); System.err.printf("%s/%s:%n", cookbook, version);
CookbookVersion cookbookO = adminConnection.getApi().getCookbook(cookbook, version); CookbookVersion cookbookO = adminConnection.getApi().getCookbook(cookbook, version);
for (Resource resource : ImmutableList.<Resource> builder().addAll( for (Resource resource : ImmutableList.<Resource> builder().addAll(cookbookO.getDefinitions()).addAll(
cookbookO.getDefinitions()).addAll(cookbookO.getFiles()).addAll( cookbookO.getFiles()).addAll(cookbookO.getLibraries()).addAll(cookbookO.getProviders()).addAll(
cookbookO.getLibraries()).addAll(cookbookO.getProviders()).addAll( cookbookO.getRecipes()).addAll(cookbookO.getResources()).addAll(cookbookO.getRootFiles()).addAll(
cookbookO.getRecipes()).addAll(cookbookO.getResources()).addAll( cookbookO.getTemplates()).build()) {
cookbookO.getRootFiles()).addAll(cookbookO.getTemplates()).build()) {
try { try {
InputStream stream = adminConnection.utils().http().get(resource.getUrl()); InputStream stream = adminConnection.utils().http().get(resource.getUrl());
byte[] md5 = adminConnection.utils().encryption().md5(stream); byte[] md5 = adminConnection.utils().encryption().md5(stream);
@ -210,17 +189,96 @@ public class ChefClientLiveTest {
System.err.printf("%s/%s:%n", cookbook, version); System.err.printf("%s/%s:%n", cookbook, version);
CookbookVersion cook = adminConnection.getApi().getCookbook(cookbook, version); CookbookVersion cook = adminConnection.getApi().getCookbook(cookbook, version);
adminConnection.getApi().deleteCookbook(cookbook, version); adminConnection.getApi().deleteCookbook(cookbook, version);
assert adminConnection.getApi().getCookbook(cookbook, version) == null : cookbook assert adminConnection.getApi().getCookbook(cookbook, version) == null : cookbook + version;
+ version;
adminConnection.getApi().updateCookbook(cookbook, version, cook); adminConnection.getApi().updateCookbook(cookbook, version, cook);
} }
} }
@Test
public void testListClients() throws Exception {
Set<String> clients = validatorConnection.getApi().listClients();
assertNotNull(clients);
assert clients.contains(validator) : "validator: " + validator + " not in: " + clients;
}
@Test(dependsOnMethods = "testListClients")
public void testCreateClient() throws Exception {
validatorConnection.getApi().deleteClient(PREFIX);
clientKey = validatorConnection.getApi().createClient(PREFIX);
assertNotNull(clientKey);
System.out.println(clientKey);
clientConnection = createConnection(PREFIX, clientKey);
clientConnection.getApi().clientExists(PREFIX);
}
@Test(dependsOnMethods = "testCreateClient")
public void testClientExists() throws Exception {
assertNotNull(validatorConnection.getApi().clientExists(PREFIX));
}
@Test
public void testListNodes() throws Exception {
Set<String> nodes = adminConnection.getApi().listNodes();
assertNotNull(nodes);
}
@Test(dependsOnMethods = "testCreateRole")
public void testCreateNode() throws Exception {
adminConnection.getApi().deleteNode(PREFIX);
node = clientConnection.getApi().createNode(new Node(PREFIX, Collections.singleton("role[" + PREFIX + "]")));
// TODO check recipes
assertNotNull(node);
}
@Test(dependsOnMethods = "testCreateNode")
public void testNodeExists() throws Exception {
assertNotNull(clientConnection.getApi().nodeExists(PREFIX));
}
@Test(dependsOnMethods = "testNodeExists")
public void testUpdateNode() throws Exception {
for (String nodename : clientConnection.getApi().listNodes()) {
Node node = adminConnection.getApi().getNode(nodename);
adminConnection.getApi().updateNode(node);
}
}
@Test
public void testListRoles() throws Exception {
Set<String> roles = adminConnection.getApi().listRoles();
assertNotNull(roles);
}
@Test(dependsOnMethods = "testCreateClient")
public void testCreateRole() throws Exception {
adminConnection.getApi().deleteRole(PREFIX);
role = adminConnection.getApi().createRole(new Role(PREFIX, Collections.singleton("recipe[java]")));
// TODO check recipes
assertNotNull(role);
}
@Test(dependsOnMethods = "testCreateRole")
public void testRoleExists() throws Exception {
assertNotNull(clientConnection.getApi().roleExists(PREFIX));
}
@Test(dependsOnMethods = "testRoleExists")
public void testUpdateRole() throws Exception {
for (String rolename : clientConnection.getApi().listRoles()) {
Role role = adminConnection.getApi().getRole(rolename);
adminConnection.getApi().updateRole(role);
}
}
@AfterClass(groups = { "live" }) @AfterClass(groups = { "live" })
public void teardownClient() throws IOException { public void teardownClient() throws IOException {
if (validatorConnection.getApi().clientExists(PREFIX)) if (validatorConnection.getApi().clientExists(PREFIX))
validatorConnection.getApi().deleteClient(PREFIX); validatorConnection.getApi().deleteClient(PREFIX);
if (adminConnection.getApi().nodeExists(PREFIX))
adminConnection.getApi().deleteNode(PREFIX);
if (adminConnection.getApi().roleExists(PREFIX))
adminConnection.getApi().deleteRole(PREFIX);
if (clientConnection != null) if (clientConnection != null)
clientConnection.close(); clientConnection.close();
if (validatorConnection != null) if (validatorConnection != null)

View File

@ -41,71 +41,55 @@ public class ParseCookbookVersionFromJsonTest {
@BeforeTest @BeforeTest
protected void setUpInjector() throws IOException { protected void setUpInjector() throws IOException {
injector = Guice.createInjector(new ParserModule()); injector = Guice.createInjector(new ParserModule());
handler = injector.getInstance(Key handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<CookbookVersion>>() {
.get(new TypeLiteral<ParseJson<CookbookVersion>>() {
})); }));
} }
@Test(enabled = false) @Test(enabled = false)
public void testBrew() throws IOException { public void testBrew() throws IOException {
CookbookVersion cookbook = handler.apply(new HttpResponse(200, "ok", CookbookVersion cookbook = handler.apply(new HttpResponse(200, "ok", Payloads
Payloads.newPayload(ParseCookbookVersionFromJsonTest.class .newPayload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/brew-cookbook.json"))));
.getResourceAsStream("/brew-cookbook.json"))));
assertEquals(cookbook, handler.apply(new HttpResponse(200, "ok", Payloads assertEquals(cookbook, handler.apply(new HttpResponse(200, "ok", Payloads.newPayload(Utils
.newPayload(Utils.toInputStream(new Gson().toJson(cookbook)))))); .toInputStream(new Gson().toJson(cookbook))))));
} }
@Test(enabled = false) @Test(enabled = false)
public void testTomcat() { public void testTomcat() {
CookbookVersion cookbook = handler.apply(new HttpResponse(200, "ok", CookbookVersion cookbook = handler.apply(new HttpResponse(200, "ok", Payloads
Payloads.newPayload(ParseCookbookVersionFromJsonTest.class .newPayload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/tomcat-cookbook.json"))));
.getResourceAsStream("/tomcat-cookbook.json"))));
assertEquals(cookbook, handler.apply(new HttpResponse(200, "ok", Payloads assertEquals(cookbook, handler.apply(new HttpResponse(200, "ok", Payloads.newPayload(Utils
.newPayload(Utils.toInputStream(new Gson().toJson(cookbook)))))); .toInputStream(new Gson().toJson(cookbook))))));
} }
@Test(enabled = false) @Test(enabled = false)
public void testMysql() throws IOException { public void testMysql() throws IOException {
CookbookVersion cookbook = handler.apply(new HttpResponse(200, "ok", CookbookVersion cookbook = handler.apply(new HttpResponse(200, "ok", Payloads
Payloads.newPayload(ParseCookbookVersionFromJsonTest.class .newPayload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/mysql-cookbook.json"))));
.getResourceAsStream("/mysql-cookbook.json"))));
assertEquals(cookbook, handler.apply(new HttpResponse(200, "ok", Payloads assertEquals(cookbook, handler.apply(new HttpResponse(200, "ok", Payloads.newPayload(Utils
.newPayload(Utils.toInputStream(new Gson().toJson(cookbook)))))); .toInputStream(new Gson().toJson(cookbook))))));
} }
@Test(enabled = false) @Test(enabled = false)
public void testApache() { public void testApache() {
EncryptionService encryptionService = injector EncryptionService encryptionService = injector.getInstance(EncryptionService.class);
.getInstance(EncryptionService.class);
assertEquals( assertEquals(
handler handler.apply(new HttpResponse(200, "ok", Payloads.newPayload(ParseCookbookVersionFromJsonTest.class
.apply(new HttpResponse(
200,
"ok",
Payloads
.newPayload(ParseCookbookVersionFromJsonTest.class
.getResourceAsStream("/apache-chef-demo-cookbook.json")))), .getResourceAsStream("/apache-chef-demo-cookbook.json")))),
new CookbookVersion( new CookbookVersion(
"apache-chef-demo-0.0.0", "apache-chef-demo-0.0.0",
ImmutableSet.<Resource> of(), ImmutableSet.<Resource> of(),
ImmutableSet.<Resource> of(), ImmutableSet.<Resource> of(),
ImmutableSet.<Resource> of(), ImmutableSet.<Resource> of(),
new Metadata("Apache v2.0", "Your Name", ImmutableMap new Metadata("Apache v2.0", "Your Name", ImmutableMap.<String, String> of(), ImmutableMap
.<String, String> of(), ImmutableMap .<String, Set<String>> of(), "youremail@example.com", ImmutableMap.<String, Set<String>> of(),
.<String, Set<String>> of(), "youremail@example.com", "A fabulous new cookbook", ImmutableMap.<String, Set<String>> of(), ImmutableMap
ImmutableMap.<String, Set<String>> of(), .<String, Set<String>> of(), "0.0.0", ImmutableMap.<String, String> of(), ImmutableMap
"A fabulous new cookbook", ImmutableMap .<String, Set<String>> of(), "apache-chef-demo", ImmutableMap.<String, String> of(), "",
.<String, Set<String>> of(), ImmutableMap ImmutableMap.<String, Attribute> of(), ImmutableMap.<String, String> of()),
.<String, Set<String>> of(), "0.0.0",
ImmutableMap.<String, String> of(), ImmutableMap
.<String, Set<String>> of(), "apache-chef-demo",
ImmutableMap.<String, String> of(), "", ImmutableMap
.<String, Attribute> of(), ImmutableMap
.<String, String> of()),
ImmutableSet.<Resource> of(), ImmutableSet.<Resource> of(),
"apache-chef-demo", "apache-chef-demo",
ImmutableSet.<Resource> of(), ImmutableSet.<Resource> of(),
@ -119,16 +103,13 @@ public class ParseCookbookVersionFromJsonTest {
"README", "README",
URI URI
.create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D"), .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D"),
encryptionService encryptionService.fromHex("11637f98942eafbf49c71b7f2f048b78"), "README", "default"),
.fromHex("11637f98942eafbf49c71b7f2f048b78"),
"README", "default"),
new Resource( new Resource(
"Rakefile", "Rakefile",
URI URI
.create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D"), .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D"),
encryptionService encryptionService.fromHex("ebcf925a1651b4e04b9cd8aac2bc54eb"), "Rakefile",
.fromHex("ebcf925a1651b4e04b9cd8aac2bc54eb"), "default"))));
"Rakefile", "default"))));
} }
} }

View File

@ -0,0 +1,44 @@
package org.jclouds.chef.functions;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.chef.domain.DataBagItem;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.io.Payloads;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.gson.Gson;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author AdrianCole
*/
@Test(groups = "unit", testName = "chef.ParseDataBagItemFromJsonTest")
public class ParseDataBagItemFromJsonTest {
private ParseJson<DataBagItem> handler;
private Gson mapper;
@BeforeTest
protected void setUpInjector() throws IOException {
Injector injector = Guice.createInjector(new ParserModule(), new ChefParserModule());
handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<DataBagItem>>() {
}));
mapper = injector.getInstance(Gson.class);
}
public void test1() {
String json = "{\"my_key\":\"my_data\",\"id\":\"item1\"}";
DataBagItem item = new DataBagItem("item1", json);
assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))), item);
assertEquals(mapper.toJson(item), json);
}
}

View File

@ -0,0 +1,49 @@
package org.jclouds.chef.functions;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Collections;
import org.jclouds.chef.domain.Node;
import org.jclouds.domain.JsonBall;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.io.Payloads;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code ParseNodeFromJson}
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "chef.ParseNodeFromJsonTest")
public class ParseNodeFromJsonTest {
private ParseJson<Node> handler;
@BeforeTest
protected void setUpInjector() throws IOException {
Injector injector = Guice.createInjector(new ParserModule());
handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Node>>() {
}));
}
public void test() {
Node node = new Node("adrian-jcloudstest", ImmutableMap.<String, JsonBall> of("tomcat6",new JsonBall("{\"ssl_port\":8433}")), ImmutableMap
.<String, JsonBall> of(), ImmutableMap.<String, JsonBall> of(), ImmutableMap.<String, JsonBall> of(),
Collections.singleton("recipe[java]"));
assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newPayload(ParseCookbookVersionFromJsonTest.class
.getResourceAsStream("/node.json")))), node);
}
}

View File

@ -0,0 +1 @@
{"normal":{"tomcat6":{"ssl_port":8433}},"name":"adrian-jcloudstest","override":{},"default":{},"json_class":"Chef::Node","automatic":{},"run_list":["recipe[java]"],"chef_type":"node"}

View File

@ -0,0 +1,162 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
import java.io.IOException;
/**
* The only reason I am pasting this class and changing 2 lines is because the
* gson project uses abstract classes and final otherwise for every part one
* might want to extend. We simply need to control the formatting of json
* literals, and hopefully one day gson will allow us to subclass something.
*
* @author Adrian Cole
* @author Inderjeet Singh
*/
public class JcloudsCompactFormatter implements JsonFormatter {
static class FormattingVisitor implements JsonElementVisitor {
private final Appendable writer;
private final Escaper escaper;
private final boolean serializeNulls;
FormattingVisitor(Appendable writer, Escaper escaper, boolean serializeNulls) {
this.writer = writer;
this.escaper = escaper;
this.serializeNulls = serializeNulls;
}
public void visitLiteral(JsonLiteral primitive) throws IOException {
primitive.toString(writer, escaper);
}
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
primitive.toString(writer, escaper);
}
public void visitNull() throws IOException {
writer.append("null");
}
public void startArray(JsonArray array) throws IOException {
writer.append('[');
}
public void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
member.toString(writer, escaper);
}
public void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
}
public void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
}
public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
}
public void endArray(JsonArray array) throws IOException {
writer.append(']');
}
public void startObject(JsonObject object) throws IOException {
writer.append('{');
}
public void visitObjectMember(JsonObject parent, String memberName, JsonLiteral member, boolean isFirst)
throws IOException {
if (!isFirst) {
writer.append(',');
}
writer.append('"');
writer.append(memberName);
writer.append("\":");
member.toString(writer, escaper);
}
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member, boolean isFirst)
throws IOException {
if (!isFirst) {
writer.append(',');
}
writer.append('"');
writer.append(memberName);
writer.append("\":");
member.toString(writer, escaper);
}
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member, boolean isFirst)
throws IOException {
if (!isFirst) {
writer.append(',');
}
writer.append('"');
writer.append(memberName);
writer.append("\":");
}
public void visitObjectMember(JsonObject parent, String memberName, JsonObject member, boolean isFirst)
throws IOException {
if (!isFirst) {
writer.append(',');
}
writer.append('"');
writer.append(memberName);
writer.append("\":");
}
public void visitNullObjectMember(JsonObject parent, String memberName, boolean isFirst) throws IOException {
if (serializeNulls) {
visitObjectMember(parent, memberName, (JsonObject) null, isFirst);
}
}
public void endObject(JsonObject object) throws IOException {
writer.append('}');
}
}
private final boolean escapeHtmlChars;
public JcloudsCompactFormatter() {
this(true);
}
JcloudsCompactFormatter(boolean escapeHtmlChars) {
this.escapeHtmlChars = escapeHtmlChars;
}
public void format(JsonElement root, Appendable writer, boolean serializeNulls) throws IOException {
if (root == null) {
return;
}
FormattingVisitor visitor = new FormattingVisitor(writer, new Escaper(escapeHtmlChars), serializeNulls);
JcloudsTreeNavigator navigator = new JcloudsTreeNavigator(visitor, serializeNulls);
navigator.navigate(root);
}
}

View File

@ -0,0 +1,119 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
import java.io.IOException;
import java.util.Map;
import com.google.gson.JcloudsCompactFormatter.FormattingVisitor;
/**
* from JsonTreeNavigator modified so that we can use JsonLiteral.
*
* @author Inderjeet Singh
*/
public class JcloudsTreeNavigator {
private final FormattingVisitor visitor;
private final boolean visitNulls;
JcloudsTreeNavigator(FormattingVisitor visitor, boolean visitNulls) {
this.visitor = visitor;
this.visitNulls = visitNulls;
}
public void navigate(JsonElement element) throws IOException {
if (element.isJsonNull()) {
visitor.visitNull();
} else if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
visitor.startArray(array);
boolean isFirst = true;
for (JsonElement child : array) {
visitChild(array, child, isFirst);
if (isFirst) {
isFirst = false;
}
}
visitor.endArray(array);
} else if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
visitor.startObject(object);
boolean isFirst = true;
for (Map.Entry<String, JsonElement> member : object.entrySet()) {
boolean visited = visitChild(object, member.getKey(), member.getValue(), isFirst);
if (visited && isFirst) {
isFirst = false;
}
}
visitor.endObject(object);
} else if (element instanceof JsonLiteral) {
visitor.visitLiteral(JsonLiteral.class.cast(element));
} else { // must be JsonPrimitive
visitor.visitPrimitive(element.getAsJsonPrimitive());
}
}
/**
* Returns true if the child was visited, false if it was skipped.
*/
private boolean visitChild(JsonObject parent, String childName, JsonElement child, boolean isFirst)
throws IOException {
if (child.isJsonNull()) {
if (visitNulls) {
visitor.visitNullObjectMember(parent, childName, isFirst);
navigate(child.getAsJsonNull());
} else { // Null value is being skipped.
return false;
}
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitObjectMember(parent, childName, childAsArray, isFirst);
navigate(childAsArray);
} else if (child.isJsonObject()) {
JsonObject childAsObject = child.getAsJsonObject();
visitor.visitObjectMember(parent, childName, childAsObject, isFirst);
navigate(childAsObject);
} else if (child instanceof JsonLiteral) {
visitor.visitObjectMember(parent, childName, JsonLiteral.class.cast(child), isFirst);
} else { // is a JsonPrimitive
visitor.visitObjectMember(parent, childName, child.getAsJsonPrimitive(), isFirst);
}
return true;
}
/**
* Returns true if the child was visited, false if it was skipped.
*/
private void visitChild(JsonArray parent, JsonElement child, boolean isFirst) throws IOException {
if (child instanceof JsonLiteral) {
visitor.visitLiteral(JsonLiteral.class.cast(child));
} else if (child.isJsonNull()) {
visitor.visitNullArrayMember(parent, isFirst);
navigate(child);
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitArrayMember(parent, childAsArray, isFirst);
navigate(childAsArray);
} else if (child.isJsonObject()) {
JsonObject childAsObject = child.getAsJsonObject();
visitor.visitArrayMember(parent, childAsObject, isFirst);
navigate(childAsObject);
} else { // is a JsonPrimitive
visitor.visitArrayMember(parent, child.getAsJsonPrimitive(), isFirst);
}
}
}

View File

@ -0,0 +1,44 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package com.google.gson;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
/**
* The gson project use package to control access to their objects. However,
* this prevents us from doing valid work, like controling the json emitted on a
* per-object basis. This is here to afford us to do this.
*
* @author Adrian Cole
*/
public final class JsonLiteral extends JsonElement {
private final CharSequence literal;
public JsonLiteral(CharSequence literal) {
this.literal = checkNotNull(literal, "literal");
}
@Override
protected void toString(Appendable sb, Escaper escaper) throws IOException {
sb.append(literal);
}
}

View File

@ -0,0 +1,88 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.domain;
import static com.google.common.base.Preconditions.checkNotNull;
/**
*
* As String is final, using a different marker to imply this is a json object
*
* @author Adrian Cole
*/
public class JsonBall implements java.io.Serializable, Comparable<String>, CharSequence {
private static final long serialVersionUID = -8168997021767065199L;
private final String value;
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
JsonBall other = (JsonBall) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public String toString() {
return value;
}
public JsonBall(String value) {
this.value = checkNotNull(value, "value");
}
@Override
public char charAt(int index) {
return value.charAt(index);
}
@Override
public int length() {
return value.length();
}
@Override
public CharSequence subSequence(int start, int end) {
return value.subSequence(start, end);
}
@Override
public int compareTo(String o) {
return value.compareTo(o);
}
}

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.http.functions.config; package org.jclouds.http.functions.config;
import java.lang.reflect.Field;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -30,6 +31,7 @@ import javax.xml.parsers.SAXParserFactory;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.domain.JsonBall;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseSax.HandlerWithResult; import org.jclouds.http.functions.ParseSax.HandlerWithResult;
@ -39,9 +41,11 @@ import com.google.common.collect.Maps;
import com.google.common.primitives.Bytes; import com.google.common.primitives.Bytes;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JcloudsCompactFormatter;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonLiteral;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
@ -92,18 +96,26 @@ public class ParserModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
Gson provideGson(JsonObjectAdapter jsonObjectAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter, Gson provideGson(JsonBallAdapter jsonObjectAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, GsonAdapterBindings bindings) { ByteArrayAdapter byteArrayAdapter, GsonAdapterBindings bindings) throws SecurityException,
GsonBuilder gson = new GsonBuilder(); NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
gson.registerTypeAdapter(JsonElement.class, jsonObjectAdapter); GsonBuilder builder = new GsonBuilder();
gson.registerTypeAdapter(Date.class, adapter); builder.registerTypeAdapter(JsonBall.class, jsonObjectAdapter);
gson.registerTypeAdapter(new TypeToken<List<Byte>>() { builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(new TypeToken<List<Byte>>() {
}.getType(), byteListAdapter); }.getType(), byteListAdapter);
gson.registerTypeAdapter(byte[].class, byteArrayAdapter); builder.registerTypeAdapter(byte[].class, byteArrayAdapter);
for (Map.Entry<Type, Object> binding : bindings.getBindings().entrySet()) { for (Map.Entry<Type, Object> binding : bindings.getBindings().entrySet()) {
gson.registerTypeAdapter(binding.getKey(), binding.getValue()); builder.registerTypeAdapter(binding.getKey(), binding.getValue());
} }
return gson.create(); JcloudsCompactFormatter formatter = new JcloudsCompactFormatter();
Gson gson = builder.create();
// allow us to print json literals
Field statFinField = Gson.class.getDeclaredField("formatter");
statFinField.setAccessible(true);
statFinField.set(gson, formatter);
return gson;
} }
@ImplementedBy(CDateAdapter.class) @ImplementedBy(CDateAdapter.class)
@ -211,21 +223,21 @@ public class ParserModule extends AbstractModule {
} }
@ImplementedBy(JsonObjectAdapterImpl.class) @ImplementedBy(JsonBallAdapterImpl.class)
public static interface JsonObjectAdapter extends JsonSerializer<JsonElement>, JsonDeserializer<JsonElement> { public static interface JsonBallAdapter extends JsonSerializer<JsonBall>, JsonDeserializer<JsonBall> {
} }
@Singleton @Singleton
public static class JsonObjectAdapterImpl implements JsonObjectAdapter { public static class JsonBallAdapterImpl implements JsonBallAdapter {
public JsonElement serialize(JsonElement src, Type typeOfSrc, JsonSerializationContext context) { public JsonElement serialize(JsonBall src, Type typeOfSrc, JsonSerializationContext context) {
return src; return new JsonLiteral(src);
} }
public JsonElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
return json; return new JsonBall(json.toString());
} }
} }

View File

@ -0,0 +1,68 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.domain;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Map;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.io.Payloads;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "jclouds.JsonBallTest")
public class JsonBallTest {
private ParseJson<Map<String, JsonBall>> handler;
private Gson mapper;
@BeforeTest
protected void setUpInjector() throws IOException {
Injector injector = Guice.createInjector(new ParserModule());
handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Map<String, JsonBall>>>() {
}));
mapper = injector.getInstance(Gson.class);
}
public void test() {
String json = "{\"tomcat6\":{\"ssl_port\":8433}}";
Map<String, JsonBall> map = ImmutableMap.<String, JsonBall> of("tomcat6", new JsonBall("{\"ssl_port\":8433}"));
assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads
.newStringPayload(json))), map);
assertEquals(mapper.toJson(map), json);
}
}

View File

@ -1,78 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.ibmdev.compute;
import static org.testng.Assert.assertEquals;
import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient;
import org.jclouds.ibmdev.IBMDeveloperCloudClient;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "ibmdevelopercloud.IBMDeveloperCloudComputeServiceLiveTest")
public class IBMDeveloperCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@BeforeClass
@Override
public void setServiceDefaults() {
provider = "ibmdev";
}
@Test
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_32);
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.RHEL);
assertEquals(defaultTemplate.getLocation().getId(), "1");
assertEquals(defaultTemplate.getSize().getCores(), 2.0d);
}
@Override
public void testListNodes() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getProviderId() != null;
// assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
@Override
protected JschSshClientModule getSshModule() {
return new JschSshClientModule();
}
public void testAssignability() throws Exception {
@SuppressWarnings("unused")
RestContext<IBMDeveloperCloudClient, IBMDeveloperCloudAsyncClient> tmContext = new ComputeServiceContextFactory()
.createContext(provider, identity, credential).getProviderSpecificContext();
}
}