mirror of https://github.com/apache/jclouds.git
Issue 191: updated to version 0.9 for cookbook commands
This commit is contained in:
parent
360af6f42c
commit
7c719f206f
|
@ -23,12 +23,10 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.chef;
|
package org.jclouds.chef;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.FormParam;
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.HEAD;
|
import javax.ws.rs.HEAD;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
|
@ -40,17 +38,20 @@ import javax.ws.rs.core.MediaType;
|
||||||
import org.jclouds.chef.binders.BindChecksumsToJsonPayload;
|
import org.jclouds.chef.binders.BindChecksumsToJsonPayload;
|
||||||
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
|
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
|
||||||
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
|
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
|
||||||
|
import org.jclouds.chef.domain.Cookbook;
|
||||||
import org.jclouds.chef.domain.Sandbox;
|
import org.jclouds.chef.domain.Sandbox;
|
||||||
import org.jclouds.chef.filters.SignedHeaderAuth;
|
import org.jclouds.chef.filters.SignedHeaderAuth;
|
||||||
|
import org.jclouds.chef.functions.ParseCookbookFromJson;
|
||||||
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.chef.functions.ParseSandboxFromJson;
|
import org.jclouds.chef.functions.ParseSandboxFromJson;
|
||||||
|
import org.jclouds.chef.functions.ParseValueSetFromJson;
|
||||||
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;
|
||||||
import org.jclouds.rest.annotations.PartParam;
|
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.ResponseParser;
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||||
|
@ -78,7 +79,7 @@ public interface ChefAsyncClient {
|
||||||
@Path("sandboxes")
|
@Path("sandboxes")
|
||||||
@ResponseParser(ParseSandboxFromJson.class)
|
@ResponseParser(ParseSandboxFromJson.class)
|
||||||
ListenableFuture<Sandbox> getUploadUrisForContent(
|
ListenableFuture<Sandbox> getUploadUrisForContent(
|
||||||
@BinderParam(BindChecksumsToJsonPayload.class) Set<String> checksums);
|
@BinderParam(BindChecksumsToJsonPayload.class) Set<String> checksums);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefCookbooks#listCookbooks
|
* @see ChefCookbooks#listCookbooks
|
||||||
|
@ -89,55 +90,45 @@ public interface ChefAsyncClient {
|
||||||
ListenableFuture<Set<String>> listCookbooks();
|
ListenableFuture<Set<String>> listCookbooks();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#createCookbook(String,File)
|
* @see ChefClient#updateCookbook
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
@Path("cookbooks")
|
|
||||||
ListenableFuture<Void> createCookbook(@FormParam("name") String cookbookName,
|
|
||||||
@PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM) File content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ChefClient#createCookbook(String,byte[])
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
@Path("cookbooks")
|
|
||||||
ListenableFuture<Void> createCookbook(
|
|
||||||
@FormParam("name") String cookbookName,
|
|
||||||
@PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM, filename = "{name}.tar.gz") byte[] content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ChefClient#updateCookbook(String,File)
|
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
@Path("cookbooks/{cookbookname}/_content")
|
@Path("cookbooks/{cookbookname}/{version}")
|
||||||
ListenableFuture<Void> updateCookbook(
|
ListenableFuture<Void> updateCookbook(
|
||||||
@PathParam("cookbookname") @FormParam("name") String cookbookName,
|
@PathParam("cookbookname") String cookbookName,
|
||||||
@PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM) File content);
|
@PathParam("version") String version,
|
||||||
|
@BinderParam(BindToJsonPayload.class) Cookbook cookbook);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#updateCookbook(String,byte[])
|
* @see ChefCookbook#deleteCookbook(String)
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Path("cookbooks/{cookbookname}/_content")
|
|
||||||
ListenableFuture<Void> updateCookbook(
|
|
||||||
@PathParam("cookbookname") @FormParam("name") String cookbookName,
|
|
||||||
@PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM, filename = "{name}.tar.gz") byte[] content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ChefCookbook#deleteCookbook
|
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("cookbooks/{cookbookname}")
|
@Path("cookbooks/{cookbookname}/{version}")
|
||||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||||
ListenableFuture<Void> deleteCookbook(@PathParam("cookbookname") String cookbookName);
|
ListenableFuture<Void> deleteCookbook(
|
||||||
|
@PathParam("cookbookname") String cookbookName,
|
||||||
|
@PathParam("version") String version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ChefCookbook#getVersionsOfCookbook
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("cookbooks/{cookbookname}")
|
||||||
|
@ResponseParser(ParseValueSetFromJson.class)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<String>> getVersionsOfCookbook(
|
||||||
|
@PathParam("cookbookname") String cookbookName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefCookbook#getCookbook
|
* @see ChefCookbook#getCookbook
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("cookbooks/{cookbookname}")
|
@Path("cookbooks/{cookbookname}/{version}")
|
||||||
|
@ResponseParser(ParseCookbookFromJson.class)
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<String> getCookbook(@PathParam("cookbookname") String cookbookName);
|
ListenableFuture<Cookbook> getCookbook(
|
||||||
|
@PathParam("cookbookname") String cookbookName,
|
||||||
|
@PathParam("version") String version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#createClient
|
* @see ChefClient#createClient
|
||||||
|
@ -146,7 +137,7 @@ public interface ChefAsyncClient {
|
||||||
@Path("clients")
|
@Path("clients")
|
||||||
@ResponseParser(ParseKeyFromJson.class)
|
@ResponseParser(ParseKeyFromJson.class)
|
||||||
ListenableFuture<String> createClient(
|
ListenableFuture<String> createClient(
|
||||||
@BinderParam(BindClientnameToJsonPayload.class) String clientname);
|
@BinderParam(BindClientnameToJsonPayload.class) String clientname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#generateKeyForClient
|
* @see ChefClient#generateKeyForClient
|
||||||
|
@ -155,7 +146,7 @@ public interface ChefAsyncClient {
|
||||||
@Path("clients/{clientname}")
|
@Path("clients/{clientname}")
|
||||||
@ResponseParser(ParseKeyFromJson.class)
|
@ResponseParser(ParseKeyFromJson.class)
|
||||||
ListenableFuture<String> generateKeyForClient(
|
ListenableFuture<String> generateKeyForClient(
|
||||||
@PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientname);
|
@PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#clientExists
|
* @see ChefClient#clientExists
|
||||||
|
@ -163,7 +154,8 @@ public interface ChefAsyncClient {
|
||||||
@HEAD
|
@HEAD
|
||||||
@Path("clients/{clientname}")
|
@Path("clients/{clientname}")
|
||||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
ListenableFuture<Boolean> clientExists(@PathParam("clientname") String clientname);
|
ListenableFuture<Boolean> clientExists(
|
||||||
|
@PathParam("clientname") String clientname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#getClient
|
* @see ChefClient#getClient
|
||||||
|
@ -171,7 +163,8 @@ public interface ChefAsyncClient {
|
||||||
@GET
|
@GET
|
||||||
@Path("clients/{clientname}")
|
@Path("clients/{clientname}")
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<Boolean> getClient(@PathParam("clientname") String clientname);
|
ListenableFuture<Boolean> getClient(
|
||||||
|
@PathParam("clientname") String clientname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#deleteClient
|
* @see ChefClient#deleteClient
|
||||||
|
@ -179,7 +172,8 @@ public interface ChefAsyncClient {
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("clients/{clientname}")
|
@Path("clients/{clientname}")
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<String> deleteClient(@PathParam("clientname") String clientname);
|
ListenableFuture<String> deleteClient(
|
||||||
|
@PathParam("clientname") String clientname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#listClients
|
* @see ChefClient#listClients
|
||||||
|
|
|
@ -41,15 +41,14 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.chef;
|
package org.jclouds.chef;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Cookbook;
|
||||||
import org.jclouds.chef.domain.Sandbox;
|
import org.jclouds.chef.domain.Sandbox;
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides synchronous access to Chef.
|
* Provides synchronous access to Chef.
|
||||||
|
@ -76,7 +75,8 @@ public interface ChefClient {
|
||||||
Set<String> listCookbooks();
|
Set<String> listCookbooks();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates (uploads) a cookbook with the name present from the tar/gz file.
|
* Creates or updates (uploads) a cookbook with the name present from the
|
||||||
|
* tar/gz file.
|
||||||
*
|
*
|
||||||
* @param cookbookName
|
* @param cookbookName
|
||||||
* matches the root directory path of the archive
|
* matches the root directory path of the archive
|
||||||
|
@ -91,39 +91,7 @@ public interface ChefClient {
|
||||||
* "409 Conflict" if the cookbook already exists
|
* "409 Conflict" if the cookbook already exists
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
||||||
void createCookbook(String cookbookName, File tgzArchive);
|
void updateCookbook(String cookbookName, String version, Cookbook cookbook);
|
||||||
|
|
||||||
/**
|
|
||||||
* like {@link #createCookbook(String, File)}, except that a byte stream is
|
|
||||||
* allowed.
|
|
||||||
*/
|
|
||||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
|
||||||
void createCookbook(String cookbookName, byte[] tgzArchive);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides (uploads) a cookbook with the content in the tar/gz file.
|
|
||||||
*
|
|
||||||
* @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 update
|
|
||||||
* cookbooks.
|
|
||||||
* @throws ResourceNotFoundException
|
|
||||||
* if the cookbook does not exist
|
|
||||||
*/
|
|
||||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
|
||||||
void updateCookbook(String cookbookName, File tgzArchive);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* like {@link #updateCookbook(String, File)}, except that a byte stream is
|
|
||||||
* allowed.
|
|
||||||
*/
|
|
||||||
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
|
|
||||||
void updateCookbook(String cookbookName, byte[] tgzArchive);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deletes an existing cookbook.
|
* deletes an existing cookbook.
|
||||||
|
@ -136,7 +104,20 @@ public interface ChefClient {
|
||||||
* "403 Forbidden" if you do not have Delete rights on the
|
* "403 Forbidden" if you do not have Delete rights on the
|
||||||
* cookbook.
|
* cookbook.
|
||||||
*/
|
*/
|
||||||
String deleteCookbook(String cookbookName);
|
String deleteCookbook(String cookbookName, String version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the versions of a cookbook or null, if not found
|
||||||
|
*
|
||||||
|
* @throws AuthorizationException
|
||||||
|
* <p/>
|
||||||
|
* "401 Unauthorized" if the caller is not a recognized user.
|
||||||
|
* <p/>
|
||||||
|
* "403 Forbidden" if the caller is not authorized to view the
|
||||||
|
* cookbook.
|
||||||
|
*/
|
||||||
|
Set<String> getVersionsOfCookbook(String cookbookName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a description of the cookbook, with links to all of its component
|
* Returns a description of the cookbook, with links to all of its component
|
||||||
|
@ -151,7 +132,7 @@ public interface ChefClient {
|
||||||
* "403 Forbidden" if the caller is not authorized to view the
|
* "403 Forbidden" if the caller is not authorized to view the
|
||||||
* cookbook.
|
* cookbook.
|
||||||
*/
|
*/
|
||||||
String getCookbook(String cookbookName);
|
Cookbook getCookbook(String cookbookName, String version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a new client
|
* creates a new client
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class Attribute {
|
||||||
|
|
||||||
private String required;
|
private String required;
|
||||||
private boolean calculated;
|
private boolean calculated;
|
||||||
private Set<String> choice;
|
private List<String> choice = Lists.newArrayList();
|
||||||
@SerializedName("default")
|
@SerializedName("default")
|
||||||
private String defaultValue;
|
private String defaultValue;
|
||||||
private String type;
|
private String type;
|
||||||
|
@ -72,7 +72,7 @@ public class Attribute {
|
||||||
return calculated;
|
return calculated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getChoice() {
|
public List<String> getChoice() {
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,5 +170,5 @@ public class Attribute {
|
||||||
+ ", displayName=" + displayName + ", recipes=" + recipes
|
+ ", displayName=" + displayName + ", recipes=" + recipes
|
||||||
+ ", required=" + required + ", type=" + type + "]";
|
+ ", required=" + required + ", type=" + type + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -34,17 +34,16 @@ public class Metadata {
|
||||||
private String license;
|
private String license;
|
||||||
private String maintainer;
|
private String maintainer;
|
||||||
private Map<String, String> suggestions = Maps.newLinkedHashMap();
|
private Map<String, String> suggestions = Maps.newLinkedHashMap();
|
||||||
private Map<String, String> dependencies = Maps.newLinkedHashMap();
|
private Map<String, Set<String>> dependencies = Maps.newLinkedHashMap();
|
||||||
@SerializedName("maintainer_email")
|
@SerializedName("maintainer_email")
|
||||||
private String maintainerEmail;
|
private String maintainerEmail;
|
||||||
private Map<String, String> conflicting = Maps.newLinkedHashMap();
|
private Map<String, Set<String>> conflicting = Maps.newLinkedHashMap();
|
||||||
private String description;
|
private String description;
|
||||||
private Map<String, String> providing = Maps.newLinkedHashMap();
|
private Map<String, Set<String>> providing = Maps.newLinkedHashMap();
|
||||||
private Map<String, Map<String, Set<String>>> platforms = Maps
|
private Map<String, Set<String>> platforms = Maps.newLinkedHashMap();
|
||||||
.newLinkedHashMap();
|
|
||||||
private String version;
|
private String version;
|
||||||
private Map<String, Map<String, String>> recipes = Maps.newLinkedHashMap();
|
private Map<String, String> recipes = Maps.newLinkedHashMap();
|
||||||
private Map<String, String> replacing = Maps.newLinkedHashMap();
|
private Map<String, Set<String>> replacing = Maps.newLinkedHashMap();
|
||||||
private String name;
|
private String name;
|
||||||
private Map<String, String> groupings = Maps.newLinkedHashMap();
|
private Map<String, String> groupings = Maps.newLinkedHashMap();
|
||||||
@SerializedName("long_description")
|
@SerializedName("long_description")
|
||||||
|
@ -53,13 +52,13 @@ public class Metadata {
|
||||||
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> dependencies,
|
Map<String, String> suggestions,
|
||||||
String maintainerEmail, Map<String, String> conflicting,
|
Map<String, Set<String>> dependencies, String maintainerEmail,
|
||||||
String description, Map<String, String> providing,
|
Map<String, Set<String>> conflicting, String description,
|
||||||
Map<String, Map<String, Set<String>>> platforms, String version,
|
Map<String, Set<String>> providing,
|
||||||
Map<String, Map<String, String>> recipes,
|
Map<String, Set<String>> platforms, String version,
|
||||||
Map<String, String> replacing, String name,
|
Map<String, String> recipes, Map<String, Set<String>> replacing,
|
||||||
Map<String, String> groupings, String longDescription,
|
String name, Map<String, String> groupings, String longDescription,
|
||||||
Map<String, Attribute> attributes, Map<String, String> recommendations) {
|
Map<String, Attribute> attributes, Map<String, String> recommendations) {
|
||||||
this.license = license;
|
this.license = license;
|
||||||
this.maintainer = maintainer;
|
this.maintainer = maintainer;
|
||||||
|
@ -95,7 +94,7 @@ public class Metadata {
|
||||||
return suggestions;
|
return suggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getDependencies() {
|
public Map<String, Set<String>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +102,7 @@ public class Metadata {
|
||||||
return maintainerEmail;
|
return maintainerEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getConflicting() {
|
public Map<String, Set<String>> getConflicting() {
|
||||||
return conflicting;
|
return conflicting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,11 +110,11 @@ public class Metadata {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getProviding() {
|
public Map<String, Set<String>> getProviding() {
|
||||||
return providing;
|
return providing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Map<String, Set<String>>> getPlatforms() {
|
public Map<String, Set<String>> getPlatforms() {
|
||||||
return platforms;
|
return platforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,11 +122,11 @@ public class Metadata {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Map<String, String>> getRecipes() {
|
public Map<String, String> getRecipes() {
|
||||||
return recipes;
|
return recipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getReplacing() {
|
public Map<String, Set<String>> getReplacing() {
|
||||||
return replacing;
|
return replacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,5 +296,5 @@ public class Metadata {
|
||||||
+ ", replacing=" + replacing + ", suggestions=" + suggestions
|
+ ", replacing=" + replacing + ", suggestions=" + suggestions
|
||||||
+ ", version=" + version + "]";
|
+ ", version=" + version + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.chef.domain;
|
package org.jclouds.chef.domain;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cookbook object.
|
* Cookbook object.
|
||||||
*
|
*
|
||||||
|
@ -26,12 +28,15 @@ package org.jclouds.chef.domain;
|
||||||
public class Resource {
|
public class Resource {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
private URI url;
|
||||||
private String checksum;
|
private String checksum;
|
||||||
private String path;
|
private String path;
|
||||||
private String specificity;
|
private String specificity;
|
||||||
|
|
||||||
public Resource(String name, String checksum, String path, String specificity) {
|
public Resource(String name, URI url, String checksum, String path,
|
||||||
|
String specificity) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.url = url;
|
||||||
this.checksum = checksum;
|
this.checksum = checksum;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.specificity = specificity;
|
this.specificity = specificity;
|
||||||
|
@ -44,6 +49,9 @@ public class Resource {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public URI getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
public String getChecksum() {
|
public String getChecksum() {
|
||||||
return checksum;
|
return checksum;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +73,7 @@ public class Resource {
|
||||||
result = prime * result + ((path == null) ? 0 : path.hashCode());
|
result = prime * result + ((path == null) ? 0 : path.hashCode());
|
||||||
result = prime * result
|
result = prime * result
|
||||||
+ ((specificity == null) ? 0 : specificity.hashCode());
|
+ ((specificity == null) ? 0 : specificity.hashCode());
|
||||||
|
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,14 +106,18 @@ public class Resource {
|
||||||
return false;
|
return false;
|
||||||
} else if (!specificity.equals(other.specificity))
|
} else if (!specificity.equals(other.specificity))
|
||||||
return false;
|
return false;
|
||||||
|
if (url == null) {
|
||||||
|
if (other.url != null)
|
||||||
|
return false;
|
||||||
|
} else if (!url.equals(other.url))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Resource [checksum=" + checksum + ", name=" + name + ", path="
|
return "Resource [checksum=" + checksum + ", name=" + name + ", path="
|
||||||
+ path + ", specificity=" + specificity + "]";
|
+ path + ", specificity=" + specificity + ", url=" + url + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.chef.functions;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Cookbook;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseCookbookFromJson extends ParseJson<Cookbook> {
|
||||||
|
@Inject
|
||||||
|
public ParseCookbookFromJson(Gson gson) {
|
||||||
|
super(gson);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Cookbook apply(InputStream stream) {
|
||||||
|
try {
|
||||||
|
return gson.fromJson(new InputStreamReader(stream, "UTF-8"),
|
||||||
|
Cookbook.class);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.chef.functions;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ParseValueSetFromJson extends ParseJson<Set<String>> {
|
||||||
|
@Inject
|
||||||
|
public ParseValueSetFromJson(Gson gson) {
|
||||||
|
super(gson);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected Set<String> apply(InputStream stream) {
|
||||||
|
try {
|
||||||
|
Type map = new TypeToken<Map<String, Set<String>>>() {
|
||||||
|
}.getType();
|
||||||
|
return Iterables.get(
|
||||||
|
((Map<String, Set<String>>) gson.fromJson(new InputStreamReader(
|
||||||
|
stream, "UTF-8"), map)).entrySet(), 0).getValue();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,15 +25,16 @@ package org.jclouds.chef;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.chef.config.ChefRestClientModule;
|
import org.jclouds.chef.config.ChefRestClientModule;
|
||||||
|
import org.jclouds.chef.domain.Cookbook;
|
||||||
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.ParseCookbookFromJson;
|
||||||
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.chef.functions.ParseSandboxFromJson;
|
import org.jclouds.chef.functions.ParseSandboxFromJson;
|
||||||
|
@ -55,7 +56,6 @@ import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.Files;
|
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@ -67,22 +67,27 @@ import com.google.inject.TypeLiteral;
|
||||||
@Test(groups = "unit", testName = "chef.ChefAsyncClientTest")
|
@Test(groups = "unit", testName = "chef.ChefAsyncClientTest")
|
||||||
public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
public void testGetUploadUrisForContent() throws SecurityException, NoSuchMethodException,
|
public void testGetUploadUrisForContent() throws SecurityException,
|
||||||
IOException {
|
NoSuchMethodException, IOException {
|
||||||
Method method = ChefAsyncClient.class.getMethod("getUploadUrisForContent", Set.class);
|
Method method = ChefAsyncClient.class.getMethod(
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
"getUploadUrisForContent", Set.class);
|
||||||
ImmutableSet.of("0189e76ccc476701d6b374e5a1a27347",
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
"0c5ecd7788cf4f6c7de2a57193897a6c", "1dda05ed139664f1f89b9dec482b77c0"));
|
.createRequest(method, ImmutableSet.of(
|
||||||
|
"0189e76ccc476701d6b374e5a1a27347",
|
||||||
|
"0c5ecd7788cf4f6c7de2a57193897a6c",
|
||||||
|
"1dda05ed139664f1f89b9dec482b77c0"));
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/sandboxes HTTP/1.1");
|
assertRequestLineEquals(httpRequest,
|
||||||
|
"POST http://localhost:4000/sandboxes HTTP/1.1");
|
||||||
assertHeadersEqual(
|
assertHeadersEqual(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"Accept: application/json\nContent-Length: 135\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
"Accept: application/json\nContent-Length: 135\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(
|
assertPayloadEquals(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"{\"checksums\":{\"0189e76ccc476701d6b374e5a1a27347\":null,\"0c5ecd7788cf4f6c7de2a57193897a6c\":null,\"1dda05ed139664f1f89b9dec482b77c0\":null}}");
|
"{\"checksums\":{\"0189e76ccc476701d6b374e5a1a27347\":null,\"0c5ecd7788cf4f6c7de2a57193897a6c\":null,\"1dda05ed139664f1f89b9dec482b77c0\":null}}");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ParseSandboxFromJson.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ParseSandboxFromJson.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
@ -90,15 +95,20 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetCookbook() throws SecurityException, NoSuchMethodException, IOException {
|
public void testGetCookbook() throws SecurityException,
|
||||||
Method method = ChefAsyncClient.class.getMethod("getCookbook", String.class);
|
NoSuchMethodException, IOException {
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
Method method = ChefAsyncClient.class.getMethod("getCookbook",
|
||||||
"cookbook");
|
String.class, String.class);
|
||||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks/cookbook HTTP/1.1");
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
.createRequest(method, "cookbook", "1.0.0");
|
||||||
|
assertRequestLineEquals(httpRequest,
|
||||||
|
"GET http://localhost:4000/cookbooks/cookbook/1.0.0 HTTP/1.1");
|
||||||
|
assertHeadersEqual(httpRequest,
|
||||||
|
"Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, null);
|
assertPayloadEquals(httpRequest, null);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ParseCookbookFromJson.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
@ -106,16 +116,20 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDeleteCookbook() throws SecurityException, NoSuchMethodException, IOException {
|
public void testDeleteCookbook() throws SecurityException,
|
||||||
Method method = ChefAsyncClient.class.getMethod("deleteCookbook", String.class);
|
NoSuchMethodException, IOException {
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
Method method = ChefAsyncClient.class.getMethod("deleteCookbook",
|
||||||
"cookbook");
|
String.class, String.class);
|
||||||
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method, "cookbook", "1.0.0");
|
||||||
assertRequestLineEquals(httpRequest,
|
assertRequestLineEquals(httpRequest,
|
||||||
"DELETE http://localhost:4000/cookbooks/cookbook HTTP/1.1");
|
"DELETE http://localhost:4000/cookbooks/cookbook/1.0.0 HTTP/1.1");
|
||||||
assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
assertHeadersEqual(httpRequest,
|
||||||
|
"Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, null);
|
assertPayloadEquals(httpRequest, null);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
CloseContentAndReturn.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
|
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
@ -123,79 +137,24 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String COOOKBOOK_BODY =
|
public void testUpdateCookbook() throws SecurityException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
"----JCLOUDS--\r\n" + "Content-Disposition: form-data; name=\"name\"\r\n\r\n" + "cookbook\r\n"
|
Method method = ChefAsyncClient.class.getMethod("updateCookbook",
|
||||||
+ "----JCLOUDS--\r\n"
|
String.class, String.class, Cookbook.class);
|
||||||
+ "Content-Disposition: form-data; name=\"file\"; filename=\"cookbook.tar.gz\"\r\n"
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
+ "Content-Type: application/octet-stream\r\n\r\n\r\n" + "----JCLOUDS----\r\n";
|
.createRequest(method, "cookbook", "1.0.1", new Cookbook());
|
||||||
|
|
||||||
public void testCreateCookbookFile() throws SecurityException, NoSuchMethodException,
|
|
||||||
IOException {
|
|
||||||
Method method = ChefAsyncClient.class.getMethod("createCookbook", String.class, File.class);
|
|
||||||
|
|
||||||
File file = File.createTempFile("jclouds-chef=test", ".tar.gz");
|
|
||||||
file.deleteOnExit();
|
|
||||||
Files.write("".getBytes(), file);
|
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
|
||||||
"cookbook", file);
|
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/cookbooks HTTP/1.1");
|
|
||||||
assertHeadersEqual(
|
|
||||||
httpRequest,
|
|
||||||
"Accept: application/json\nContent-Length: "
|
|
||||||
+ (file.getName().length() + 206)
|
|
||||||
+ "\nContent-Type: multipart/form-data; boundary=--JCLOUDS--\nX-Chef-Version: 0.9.0\n");
|
|
||||||
assertPayloadEquals(httpRequest, COOOKBOOK_BODY.replace("cookbook.tar.gz", file.getName()));
|
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
|
||||||
assertExceptionParserClassEquals(method, null);
|
|
||||||
|
|
||||||
checkFilters(httpRequest);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCreateCookbookByte() throws SecurityException, NoSuchMethodException,
|
|
||||||
IOException {
|
|
||||||
Method method = ChefAsyncClient.class.getMethod("createCookbook", String.class, byte[].class);
|
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
|
||||||
"cookbook", "".getBytes());
|
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/cookbooks HTTP/1.1");
|
|
||||||
assertHeadersEqual(
|
|
||||||
httpRequest,
|
|
||||||
"Accept: application/json\nContent-Length: 221\nContent-Type: multipart/form-data; boundary=--JCLOUDS--\nX-Chef-Version: 0.9.0\n");
|
|
||||||
assertPayloadEquals(httpRequest, COOOKBOOK_BODY);
|
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
|
||||||
assertExceptionParserClassEquals(method, null);
|
|
||||||
|
|
||||||
checkFilters(httpRequest);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testUpdateCookbookFile() throws SecurityException, NoSuchMethodException,
|
|
||||||
IOException {
|
|
||||||
Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, File.class);
|
|
||||||
|
|
||||||
File file = File.createTempFile("jclouds-chef=test", ".tar.gz");
|
|
||||||
file.deleteOnExit();
|
|
||||||
Files.write("".getBytes(), file);
|
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
|
||||||
"cookbook", file);
|
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest,
|
assertRequestLineEquals(httpRequest,
|
||||||
"PUT http://localhost:4000/cookbooks/cookbook/_content HTTP/1.1");
|
"PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1");
|
||||||
assertHeadersEqual(
|
assertHeadersEqual(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"Accept: application/json\nContent-Length: "
|
"Accept: application/json\nContent-Length: 134\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
+ (file.getName().length() + 206)
|
assertPayloadEquals(
|
||||||
+ "\nContent-Type: multipart/form-data; boundary=--JCLOUDS--\nX-Chef-Version: 0.9.0\n");
|
httpRequest,
|
||||||
assertPayloadEquals(httpRequest, COOOKBOOK_BODY.replace("cookbook.tar.gz", file.getName()));
|
"{\"definitions\":[],\"attributes\":[],\"files\":[],\"providers\":[],\"resources\":[],\"templates\":[],\"libraries\":[],\"recipes\":[],\"root_files\":[]}");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
CloseContentAndReturn.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
@ -203,36 +162,20 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpdateCookbookByte() throws SecurityException, NoSuchMethodException,
|
public void testListCookbooks() throws SecurityException,
|
||||||
IOException {
|
NoSuchMethodException, IOException {
|
||||||
Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, byte[].class);
|
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
|
||||||
"cookbook", "".getBytes());
|
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest,
|
|
||||||
"PUT http://localhost:4000/cookbooks/cookbook/_content HTTP/1.1");
|
|
||||||
assertHeadersEqual(
|
|
||||||
httpRequest,
|
|
||||||
"Accept: application/json\nContent-Length: 221\nContent-Type: multipart/form-data; boundary=--JCLOUDS--\nX-Chef-Version: 0.9.0\n");
|
|
||||||
assertPayloadEquals(httpRequest, COOOKBOOK_BODY);
|
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
|
||||||
assertExceptionParserClassEquals(method, null);
|
|
||||||
|
|
||||||
checkFilters(httpRequest);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListCookbooks() throws SecurityException, NoSuchMethodException, IOException {
|
|
||||||
Method method = ChefAsyncClient.class.getMethod("listCookbooks");
|
Method method = ChefAsyncClient.class.getMethod("listCookbooks");
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method);
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks HTTP/1.1");
|
assertRequestLineEquals(httpRequest,
|
||||||
assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
"GET http://localhost:4000/cookbooks HTTP/1.1");
|
||||||
|
assertHeadersEqual(httpRequest,
|
||||||
|
"Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, null);
|
assertPayloadEquals(httpRequest, null);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ParseKeySetFromJson.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
@ -240,14 +183,20 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClientExists() throws SecurityException, NoSuchMethodException, IOException {
|
public void testClientExists() throws SecurityException,
|
||||||
Method method = ChefAsyncClient.class.getMethod("clientExists", String.class);
|
NoSuchMethodException, IOException {
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
Method method = ChefAsyncClient.class.getMethod("clientExists",
|
||||||
assertRequestLineEquals(httpRequest, "HEAD http://localhost:4000/clients/client HTTP/1.1");
|
String.class);
|
||||||
assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method, "client");
|
||||||
|
assertRequestLineEquals(httpRequest,
|
||||||
|
"HEAD http://localhost:4000/clients/client HTTP/1.1");
|
||||||
|
assertHeadersEqual(httpRequest,
|
||||||
|
"Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, null);
|
assertPayloadEquals(httpRequest, null);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ReturnTrueIf2xx.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
@ -255,14 +204,20 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDeleteClient() throws SecurityException, NoSuchMethodException, IOException {
|
public void testDeleteClient() throws SecurityException,
|
||||||
Method method = ChefAsyncClient.class.getMethod("deleteClient", String.class);
|
NoSuchMethodException, IOException {
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
Method method = ChefAsyncClient.class.getMethod("deleteClient",
|
||||||
assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/clients/client HTTP/1.1");
|
String.class);
|
||||||
assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method, "client");
|
||||||
|
assertRequestLineEquals(httpRequest,
|
||||||
|
"DELETE http://localhost:4000/clients/client HTTP/1.1");
|
||||||
|
assertHeadersEqual(httpRequest,
|
||||||
|
"Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, null);
|
assertPayloadEquals(httpRequest, null);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ReturnStringIf200.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
@ -270,17 +225,22 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException,
|
public void testGenerateKeyForClient() throws SecurityException,
|
||||||
IOException {
|
NoSuchMethodException, IOException {
|
||||||
Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", String.class);
|
Method method = ChefAsyncClient.class.getMethod("generateKeyForClient",
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
String.class);
|
||||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1");
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method, "client");
|
||||||
|
assertRequestLineEquals(httpRequest,
|
||||||
|
"PUT http://localhost:4000/clients/client HTTP/1.1");
|
||||||
assertHeadersEqual(
|
assertHeadersEqual(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"Accept: application/json\nContent-Length: 44\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
"Accept: application/json\nContent-Length: 44\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\", \"private_key\": true}");
|
assertPayloadEquals(httpRequest,
|
||||||
|
"{\"clientname\":\"client\", \"private_key\": true}");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ParseKeyFromJson.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
@ -288,17 +248,22 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateClient() throws SecurityException, NoSuchMethodException, IOException {
|
public void testCreateClient() throws SecurityException,
|
||||||
Method method = ChefAsyncClient.class.getMethod("createClient", String.class);
|
NoSuchMethodException, IOException {
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method, "client");
|
Method method = ChefAsyncClient.class.getMethod("createClient",
|
||||||
|
String.class);
|
||||||
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method, "client");
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/clients HTTP/1.1");
|
assertRequestLineEquals(httpRequest,
|
||||||
|
"POST http://localhost:4000/clients HTTP/1.1");
|
||||||
assertHeadersEqual(
|
assertHeadersEqual(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"Accept: application/json\nContent-Length: 23\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
"Accept: application/json\nContent-Length: 23\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\"}");
|
assertPayloadEquals(httpRequest, "{\"clientname\":\"client\"}");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ParseKeyFromJson.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
@ -306,15 +271,20 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListClients() throws SecurityException, NoSuchMethodException, IOException {
|
public void testListClients() throws SecurityException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
Method method = ChefAsyncClient.class.getMethod("listClients");
|
Method method = ChefAsyncClient.class.getMethod("listClients");
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method);
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor
|
||||||
|
.createRequest(method);
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/clients HTTP/1.1");
|
assertRequestLineEquals(httpRequest,
|
||||||
assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
"GET http://localhost:4000/clients HTTP/1.1");
|
||||||
|
assertHeadersEqual(httpRequest,
|
||||||
|
"Accept: application/json\nX-Chef-Version: 0.9.0\n");
|
||||||
assertPayloadEquals(httpRequest, null);
|
assertPayloadEquals(httpRequest, null);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class);
|
assertResponseParserClassEquals(method, httpRequest,
|
||||||
|
ParseKeySetFromJson.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
@ -325,7 +295,8 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
@Override
|
@Override
|
||||||
protected void checkFilters(GeneratedHttpRequest<ChefAsyncClient> httpRequest) {
|
protected void checkFilters(GeneratedHttpRequest<ChefAsyncClient> httpRequest) {
|
||||||
assertEquals(httpRequest.getFilters().size(), 1);
|
assertEquals(httpRequest.getFilters().size(), 1);
|
||||||
assertEquals(httpRequest.getFilters().get(0).getClass(), SignedHeaderAuth.class);
|
assertEquals(httpRequest.getFilters().get(0).getClass(),
|
||||||
|
SignedHeaderAuth.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -352,6 +323,6 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
@Override
|
@Override
|
||||||
public ContextSpec<ChefClient, ChefAsyncClient> createContextSpec() {
|
public ContextSpec<ChefClient, ChefAsyncClient> createContextSpec() {
|
||||||
return new RestContextFactory().createContextSpec("chef", "user",
|
return new RestContextFactory().createContextSpec("chef", "user",
|
||||||
SignedHeaderAuthTest.PRIVATE_KEY, new Properties());
|
SignedHeaderAuthTest.PRIVATE_KEY, new Properties());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,10 @@ 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.net.URI;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Cookbook;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
@ -42,7 +41,6 @@ import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
@ -54,7 +52,7 @@ import com.google.inject.Module;
|
||||||
@Test(groups = "live", testName = "chef.ChefClientLiveTest")
|
@Test(groups = "live", testName = "chef.ChefClientLiveTest")
|
||||||
public class ChefClientLiveTest {
|
public class ChefClientLiveTest {
|
||||||
|
|
||||||
private static final String COOKBOOK_NAME = "runit";
|
private static final String COOKBOOK_NAME = "brew";
|
||||||
private static final String COOKBOOK_URI = "https://s3.amazonaws.com/opscode-community/cookbook_versions/tarballs/195/original/runit.tar.gz";
|
private static final String COOKBOOK_URI = "https://s3.amazonaws.com/opscode-community/cookbook_versions/tarballs/195/original/runit.tar.gz";
|
||||||
private RestContext<ChefClient, ChefAsyncClient> validatorConnection;
|
private RestContext<ChefClient, ChefAsyncClient> validatorConnection;
|
||||||
private RestContext<ChefClient, ChefAsyncClient> clientConnection;
|
private RestContext<ChefClient, ChefAsyncClient> clientConnection;
|
||||||
|
@ -67,39 +65,45 @@ public class ChefClientLiveTest {
|
||||||
private byte[] cookbookContent;
|
private byte[] cookbookContent;
|
||||||
private File cookbookFile;
|
private File cookbookFile;
|
||||||
|
|
||||||
public static final String PREFIX = System.getProperty("user.name") + "-jcloudstest";
|
public static final String PREFIX = System.getProperty("user.name")
|
||||||
|
+ "-jcloudstest";
|
||||||
|
|
||||||
@BeforeClass(groups = { "live" })
|
@BeforeClass(groups = { "live" })
|
||||||
public void setupClient() throws IOException {
|
public void setupClient() throws IOException {
|
||||||
endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint");
|
endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"),
|
||||||
|
"jclouds.test.endpoint");
|
||||||
validator = System.getProperty("jclouds.test.validator");
|
validator = System.getProperty("jclouds.test.validator");
|
||||||
if (validator == null || validator.equals(""))
|
if (validator == null || validator.equals(""))
|
||||||
validator = "chef-validator";
|
validator = "chef-validator";
|
||||||
String validatorKey = System.getProperty("jclouds.test.validator.key");
|
String validatorKey = System.getProperty("jclouds.test.validator.key");
|
||||||
if (validatorKey == null || validatorKey.equals(""))
|
if (validatorKey == null || validatorKey.equals(""))
|
||||||
validatorKey = System.getProperty("user.home") + "/.chef/validation.pem";
|
validatorKey = System.getProperty("user.home")
|
||||||
user = checkNotNull(System.getProperty("jclouds.test.identity"));
|
+ "/.chef/validation.pem";
|
||||||
|
user = checkNotNull(System.getProperty("jclouds.test.identity"),
|
||||||
|
"jclouds.test.identity");
|
||||||
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(
|
||||||
Charsets.UTF_8));
|
new File(validatorKey), 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(
|
||||||
throws IOException {
|
String identity, String key) 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,
|
||||||
.<Module> of(new Log4JLoggingModule()), props);
|
ImmutableSet.<Module> of(new Log4JLoggingModule()), props);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListClients() throws Exception {
|
public void testListClients() throws Exception {
|
||||||
Set<String> clients = validatorConnection.getApi().listClients();
|
Set<String> clients = validatorConnection.getApi().listClients();
|
||||||
assertNotNull(clients);
|
assertNotNull(clients);
|
||||||
assert clients.contains(validator) : "validator: " + validator + " not in: " + clients;
|
assert clients.contains(validator) : "validator: " + validator
|
||||||
|
+ " not in: " + clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testListClients")
|
@Test(dependsOnMethods = "testListClients")
|
||||||
|
@ -127,39 +131,43 @@ public class ChefClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateCookbook() throws Exception {
|
public void testListCookbooks() throws Exception {
|
||||||
adminConnection.getApi().deleteCookbook(COOKBOOK_NAME);
|
for (String cookbook : adminConnection.getApi().listCookbooks())
|
||||||
InputStream in = null;
|
for (String version : adminConnection.getApi().getVersionsOfCookbook(
|
||||||
try {
|
cookbook)) {
|
||||||
in = URI.create(COOKBOOK_URI).toURL().openStream();
|
System.err.printf("%s/%s:%n", cookbook, version);
|
||||||
|
System.err.printf("%s%n", adminConnection.getApi().getCookbook(
|
||||||
cookbookContent = ByteStreams.toByteArray(in);
|
cookbook, version));
|
||||||
|
}
|
||||||
cookbookFile = File.createTempFile("foo", ".tar.gz");
|
|
||||||
Files.write(cookbookContent, cookbookFile);
|
|
||||||
cookbookFile.deleteOnExit();
|
|
||||||
|
|
||||||
adminConnection.getApi().createCookbook(COOKBOOK_NAME, cookbookFile);
|
|
||||||
adminConnection.getApi().deleteCookbook(COOKBOOK_NAME);
|
|
||||||
adminConnection.getApi().createCookbook(COOKBOOK_NAME, cookbookContent);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (in != null)
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreateCookbook")
|
@Test(dependsOnMethods = "testListCookbooks")
|
||||||
public void testUpdateCookbook() throws Exception {
|
public void testUpdateCookbook() throws Exception {
|
||||||
adminConnection.getApi().updateCookbook(COOKBOOK_NAME, cookbookFile);
|
for (String cookbook : adminConnection.getApi().listCookbooks())
|
||||||
// TODO verify timestamp or something
|
for (String version : adminConnection.getApi().getVersionsOfCookbook(
|
||||||
adminConnection.getApi().updateCookbook(COOKBOOK_NAME, cookbookContent);
|
cookbook)) {
|
||||||
|
System.err.printf("%s/%s:%n", cookbook, version);
|
||||||
|
Cookbook cook = adminConnection.getApi().getCookbook(cookbook,
|
||||||
|
version);
|
||||||
|
adminConnection.getApi().updateCookbook(cookbook, version, cook);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testUpdateCookbook")
|
@Test(dependsOnMethods = "testUpdateCookbook")
|
||||||
public void testListCookbooks() throws Exception {
|
public void testCreateCookbook() throws Exception {
|
||||||
for (String cookbook : adminConnection.getApi().listCookbooks())
|
for (String cookbook : adminConnection.getApi().listCookbooks())
|
||||||
System.err.println(adminConnection.getApi().getCookbook(cookbook));
|
for (String version : adminConnection.getApi().getVersionsOfCookbook(
|
||||||
|
cookbook)) {
|
||||||
|
System.err.printf("%s/%s:%n", cookbook, version);
|
||||||
|
Cookbook cook = adminConnection.getApi().getCookbook(cookbook,
|
||||||
|
version);
|
||||||
|
adminConnection.getApi().deleteCookbook(cookbook, version);
|
||||||
|
assert adminConnection.getApi().getCookbook(cookbook, version) == null : cookbook
|
||||||
|
+ version;
|
||||||
|
|
||||||
|
adminConnection.getApi().updateCookbook(cookbook, version, cook);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass(groups = { "live" })
|
@AfterClass(groups = { "live" })
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
package org.jclouds.chef.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.Attribute;
|
||||||
|
import org.jclouds.chef.domain.Cookbook;
|
||||||
|
import org.jclouds.chef.domain.Metadata;
|
||||||
|
import org.jclouds.chef.domain.Resource;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.config.ParserModule;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
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.gson.Gson;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code ParseCookbookFromJson}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", sequential = true, testName = "chef.ParseCookbookFromJsonTest")
|
||||||
|
public class ParseCookbookFromJsonTest {
|
||||||
|
|
||||||
|
private ParseCookbookFromJson handler;
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
protected void setUpInjector() throws IOException {
|
||||||
|
Injector injector = Guice.createInjector(new ParserModule());
|
||||||
|
handler = injector.getInstance(ParseCookbookFromJson.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBrew() throws IOException {
|
||||||
|
Cookbook cookbook = handler.apply(new HttpResponse(
|
||||||
|
ParseCookbookFromJsonTest.class
|
||||||
|
.getResourceAsStream("/brew-cookbook.json")));
|
||||||
|
|
||||||
|
assertEquals(cookbook, handler.apply(new HttpResponse(Utils
|
||||||
|
.toInputStream(new Gson().toJson(cookbook)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTomcat() {
|
||||||
|
Cookbook cookbook = handler.apply(new HttpResponse(
|
||||||
|
ParseCookbookFromJsonTest.class
|
||||||
|
.getResourceAsStream("/tomcat-cookbook.json")));
|
||||||
|
|
||||||
|
assertEquals(cookbook, handler.apply(new HttpResponse(Utils
|
||||||
|
.toInputStream(new Gson().toJson(cookbook)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMysql() throws IOException {
|
||||||
|
Cookbook cookbook = handler.apply(new HttpResponse(
|
||||||
|
ParseCookbookFromJsonTest.class
|
||||||
|
.getResourceAsStream("/mysql-cookbook.json")));
|
||||||
|
|
||||||
|
assertEquals(cookbook, handler.apply(new HttpResponse(Utils
|
||||||
|
.toInputStream(new Gson().toJson(cookbook)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testApache() {
|
||||||
|
assertEquals(
|
||||||
|
handler.apply(new HttpResponse(ParseCookbookFromJsonTest.class
|
||||||
|
.getResourceAsStream("/apache-chef-demo-cookbook.json"))),
|
||||||
|
new Cookbook(
|
||||||
|
"apache-chef-demo-0.0.0",
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
"Chef::CookbookVersion",
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
new Metadata("Apache v2.0", "Your Name", ImmutableMap
|
||||||
|
.<String, String> of(), ImmutableMap
|
||||||
|
.<String, Set<String>> of(), "youremail@example.com",
|
||||||
|
ImmutableMap.<String, Set<String>> of(),
|
||||||
|
"A fabulous new cookbook", ImmutableMap
|
||||||
|
.<String, Set<String>> of(), ImmutableMap
|
||||||
|
.<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(),
|
||||||
|
"apache-chef-demo",
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
"0.0.0",
|
||||||
|
ImmutableSet.<Resource> of(),
|
||||||
|
ImmutableSet
|
||||||
|
.<Resource> 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"),
|
||||||
|
"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"),
|
||||||
|
"ebcf925a1651b4e04b9cd8aac2bc54eb",
|
||||||
|
"Rakefile", "default")), "cookbook_version"));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.jclouds.chef.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.config.ParserModule;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code ParseValueSetFromJson}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", sequential = true, testName = "chef.ParseValueSetFromJsonTest")
|
||||||
|
public class ParseValueSetFromJsonTest {
|
||||||
|
|
||||||
|
private ParseValueSetFromJson handler;
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
protected void setUpInjector() throws IOException {
|
||||||
|
Injector injector = Guice.createInjector(new ParserModule());
|
||||||
|
handler = injector.getInstance(ParseValueSetFromJson.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRegex() {
|
||||||
|
assertEquals(handler.apply(new HttpResponse(Utils
|
||||||
|
.toInputStream("{\"runit\":[\"0.7.0\",\"0.7.1\"]}"))), ImmutableSet
|
||||||
|
.of("0.7.0", "0.7.1"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"definitions": [],
|
||||||
|
"name": "apache-chef-demo-0.0.0",
|
||||||
|
"attributes": [],
|
||||||
|
"files": [],
|
||||||
|
"json_class": "Chef::CookbookVersion",
|
||||||
|
"providers": [],
|
||||||
|
"metadata": {
|
||||||
|
"dependencies": {}, "name": "apache-chef-demo",
|
||||||
|
"maintainer_email": "youremail@example.com",
|
||||||
|
"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": {}
|
||||||
|
}, "libraries": [],
|
||||||
|
"resources": [],
|
||||||
|
"templates": [],
|
||||||
|
"cookbook_name": "apache-chef-demo",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"recipes": [],
|
||||||
|
"root_files": [{
|
||||||
|
"name": "README",
|
||||||
|
"url": "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D",
|
||||||
|
"checksum": "11637f98942eafbf49c71b7f2f048b78",
|
||||||
|
"path": "README",
|
||||||
|
"specificity": "default"
|
||||||
|
}, {
|
||||||
|
"name": "Rakefile",
|
||||||
|
"url": "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D",
|
||||||
|
"checksum": "ebcf925a1651b4e04b9cd8aac2bc54eb",
|
||||||
|
"path": "Rakefile",
|
||||||
|
"specificity": "default"
|
||||||
|
}],
|
||||||
|
"chef_type": "cookbook_version"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
{"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"}
|
File diff suppressed because one or more lines are too long
|
@ -1,150 +0,0 @@
|
||||||
{
|
|
||||||
"templates": [
|
|
||||||
],
|
|
||||||
"attributes": [
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/attributes?id=default.rb",
|
|
||||||
"name": "default.rb",
|
|
||||||
"checksum": "1dffbe14afa3630aa4cb268508bb723b0fba33e2e33a8c517feedad981db3147"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"definitions": [
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/definitions?id=runit_service.rb",
|
|
||||||
"name": "runit_service.rb",
|
|
||||||
"checksum": "32fe6fe902b0dfe1870cfbd4aad475039e0c3d661353b12cd54ed29c5020a9e7"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"conflicting": {
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"runit/sv_dir": {
|
|
||||||
"required": "optional",
|
|
||||||
"calculated": false,
|
|
||||||
"choice": [
|
|
||||||
],
|
|
||||||
"default": "/etc/sv",
|
|
||||||
"type": "string",
|
|
||||||
"recipes": [
|
|
||||||
],
|
|
||||||
"display_name": "Runit sv directory",
|
|
||||||
"description": "Location of services managed by runit"
|
|
||||||
},
|
|
||||||
"runit/service_dir": {
|
|
||||||
"required": "optional",
|
|
||||||
"calculated": false,
|
|
||||||
"choice": [
|
|
||||||
],
|
|
||||||
"default": "/etc/service",
|
|
||||||
"type": "string",
|
|
||||||
"recipes": [
|
|
||||||
],
|
|
||||||
"display_name": "Runit service directory",
|
|
||||||
"description": "Symlinks to services managed under runit"
|
|
||||||
},
|
|
||||||
"runit": {
|
|
||||||
"required": "optional",
|
|
||||||
"calculated": false,
|
|
||||||
"choice": [
|
|
||||||
],
|
|
||||||
"type": "hash",
|
|
||||||
"recipes": [
|
|
||||||
],
|
|
||||||
"display_name": "Runit",
|
|
||||||
"description": "Hash of runit attributes"
|
|
||||||
},
|
|
||||||
"runit/sv_bin": {
|
|
||||||
"required": "optional",
|
|
||||||
"calculated": false,
|
|
||||||
"choice": [
|
|
||||||
],
|
|
||||||
"default": "/usr/bin/sv",
|
|
||||||
"type": "string",
|
|
||||||
"recipes": [
|
|
||||||
],
|
|
||||||
"display_name": "Runit sv bin",
|
|
||||||
"description": "Location of the sv binary"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"providing": {
|
|
||||||
},
|
|
||||||
"license": "Apache 2.0",
|
|
||||||
"replacing": {
|
|
||||||
},
|
|
||||||
"long_description": "",
|
|
||||||
"dependencies": {
|
|
||||||
},
|
|
||||||
"groupings": {
|
|
||||||
},
|
|
||||||
"recommendations": {
|
|
||||||
},
|
|
||||||
"platforms": {
|
|
||||||
"debian": [
|
|
||||||
],
|
|
||||||
"ubuntu": [
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"description": "Installs runit and provides runit_service definition",
|
|
||||||
"version": "0.11.0",
|
|
||||||
"maintainer": "Opscode, Inc.",
|
|
||||||
"name": "runit",
|
|
||||||
"recipes": {
|
|
||||||
},
|
|
||||||
"suggestions": {
|
|
||||||
},
|
|
||||||
"maintainer_email": "cookbooks@opscode.com"
|
|
||||||
},
|
|
||||||
"resources": [
|
|
||||||
],
|
|
||||||
"files": [
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/files?version=7.04&id=runsvdir&platform=ubuntu",
|
|
||||||
"specificity": "ubuntu-7.04",
|
|
||||||
"name": "runsvdir",
|
|
||||||
"checksum": "28c55f711453fd9d4fbf7cc747719e7976607f892fa61cfb348421858ef3dd5b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/files?version=8.04&id=runsvdir&platform=ubuntu",
|
|
||||||
"specificity": "ubuntu-8.04",
|
|
||||||
"name": "runsvdir",
|
|
||||||
"checksum": "28c55f711453fd9d4fbf7cc747719e7976607f892fa61cfb348421858ef3dd5b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/files?id=runsvdir",
|
|
||||||
"specificity": "default",
|
|
||||||
"name": "runsvdir",
|
|
||||||
"checksum": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/files?id=runit.seed",
|
|
||||||
"specificity": "default",
|
|
||||||
"name": "runit.seed",
|
|
||||||
"checksum": "9c675810fd4c0ec4fb8b2788ba8512990f436347834373445a9fb48c46d0aff0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/files?version=7.10&id=runsvdir&platform=ubuntu",
|
|
||||||
"specificity": "ubuntu-7.10",
|
|
||||||
"name": "runsvdir",
|
|
||||||
"checksum": "28c55f711453fd9d4fbf7cc747719e7976607f892fa61cfb348421858ef3dd5b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/files?version=6.10&id=runsvdir&platform=ubuntu",
|
|
||||||
"specificity": "ubuntu-6.10",
|
|
||||||
"name": "runsvdir",
|
|
||||||
"checksum": "61e090e43b0ce746bd22e121422d7d05c04e9b9883dac3632418bdf7dc539b38"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "runit",
|
|
||||||
"libraries": [
|
|
||||||
],
|
|
||||||
"recipes": [
|
|
||||||
{
|
|
||||||
"uri": "https://api.opscode.com/organizations/jclouds/cookbooks/runit/recipes?id=default.rb",
|
|
||||||
"name": "default.rb",
|
|
||||||
"checksum": "76589110f5db8cf8b0a045ce0b3fc500046f6bb63c2d16d50cee6cfaaaeff29a"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"providers": [
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue