diff --git a/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java b/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java index b26474783d..e3bde64672 100644 --- a/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java +++ b/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java @@ -23,12 +23,10 @@ */ package org.jclouds.chef; -import java.io.File; import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; -import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.HEAD; 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.BindClientnameToJsonPayload; import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload; +import org.jclouds.chef.domain.Cookbook; import org.jclouds.chef.domain.Sandbox; import org.jclouds.chef.filters.SignedHeaderAuth; +import org.jclouds.chef.functions.ParseCookbookFromJson; import org.jclouds.chef.functions.ParseKeyFromJson; import org.jclouds.chef.functions.ParseKeySetFromJson; import org.jclouds.chef.functions.ParseSandboxFromJson; +import org.jclouds.chef.functions.ParseValueSetFromJson; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; -import org.jclouds.rest.annotations.PartParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; @@ -78,7 +79,7 @@ public interface ChefAsyncClient { @Path("sandboxes") @ResponseParser(ParseSandboxFromJson.class) ListenableFuture getUploadUrisForContent( - @BinderParam(BindChecksumsToJsonPayload.class) Set checksums); + @BinderParam(BindChecksumsToJsonPayload.class) Set checksums); /** * @see ChefCookbooks#listCookbooks @@ -89,55 +90,45 @@ public interface ChefAsyncClient { ListenableFuture> listCookbooks(); /** - * @see ChefClient#createCookbook(String,File) - */ - @POST - @Path("cookbooks") - ListenableFuture createCookbook(@FormParam("name") String cookbookName, - @PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM) File content); - - /** - * @see ChefClient#createCookbook(String,byte[]) - */ - @POST - @Path("cookbooks") - ListenableFuture createCookbook( - @FormParam("name") String cookbookName, - @PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM, filename = "{name}.tar.gz") byte[] content); - - /** - * @see ChefClient#updateCookbook(String,File) + * @see ChefClient#updateCookbook */ @PUT - @Path("cookbooks/{cookbookname}/_content") + @Path("cookbooks/{cookbookname}/{version}") ListenableFuture updateCookbook( - @PathParam("cookbookname") @FormParam("name") String cookbookName, - @PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM) File content); + @PathParam("cookbookname") String cookbookName, + @PathParam("version") String version, + @BinderParam(BindToJsonPayload.class) Cookbook cookbook); /** - * @see ChefClient#updateCookbook(String,byte[]) - */ - @PUT - @Path("cookbooks/{cookbookname}/_content") - ListenableFuture updateCookbook( - @PathParam("cookbookname") @FormParam("name") String cookbookName, - @PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM, filename = "{name}.tar.gz") byte[] content); - - /** - * @see ChefCookbook#deleteCookbook + * @see ChefCookbook#deleteCookbook(String) */ @DELETE - @Path("cookbooks/{cookbookname}") + @Path("cookbooks/{cookbookname}/{version}") @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture deleteCookbook(@PathParam("cookbookname") String cookbookName); + ListenableFuture deleteCookbook( + @PathParam("cookbookname") String cookbookName, + @PathParam("version") String version); + + /** + * @see ChefCookbook#getVersionsOfCookbook + */ + @GET + @Path("cookbooks/{cookbookname}") + @ResponseParser(ParseValueSetFromJson.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture> getVersionsOfCookbook( + @PathParam("cookbookname") String cookbookName); /** * @see ChefCookbook#getCookbook */ @GET - @Path("cookbooks/{cookbookname}") + @Path("cookbooks/{cookbookname}/{version}") + @ResponseParser(ParseCookbookFromJson.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getCookbook(@PathParam("cookbookname") String cookbookName); + ListenableFuture getCookbook( + @PathParam("cookbookname") String cookbookName, + @PathParam("version") String version); /** * @see ChefClient#createClient @@ -146,7 +137,7 @@ public interface ChefAsyncClient { @Path("clients") @ResponseParser(ParseKeyFromJson.class) ListenableFuture createClient( - @BinderParam(BindClientnameToJsonPayload.class) String clientname); + @BinderParam(BindClientnameToJsonPayload.class) String clientname); /** * @see ChefClient#generateKeyForClient @@ -155,7 +146,7 @@ public interface ChefAsyncClient { @Path("clients/{clientname}") @ResponseParser(ParseKeyFromJson.class) ListenableFuture generateKeyForClient( - @PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientname); + @PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientname); /** * @see ChefClient#clientExists @@ -163,7 +154,8 @@ public interface ChefAsyncClient { @HEAD @Path("clients/{clientname}") @ExceptionParser(ReturnFalseOnNotFoundOr404.class) - ListenableFuture clientExists(@PathParam("clientname") String clientname); + ListenableFuture clientExists( + @PathParam("clientname") String clientname); /** * @see ChefClient#getClient @@ -171,7 +163,8 @@ public interface ChefAsyncClient { @GET @Path("clients/{clientname}") @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getClient(@PathParam("clientname") String clientname); + ListenableFuture getClient( + @PathParam("clientname") String clientname); /** * @see ChefClient#deleteClient @@ -179,7 +172,8 @@ public interface ChefAsyncClient { @DELETE @Path("clients/{clientname}") @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture deleteClient(@PathParam("clientname") String clientname); + ListenableFuture deleteClient( + @PathParam("clientname") String clientname); /** * @see ChefClient#listClients diff --git a/chef/src/main/java/org/jclouds/chef/ChefClient.java b/chef/src/main/java/org/jclouds/chef/ChefClient.java index 82e22428eb..125e8144b6 100644 --- a/chef/src/main/java/org/jclouds/chef/ChefClient.java +++ b/chef/src/main/java/org/jclouds/chef/ChefClient.java @@ -41,15 +41,14 @@ */ package org.jclouds.chef; -import java.io.File; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.jclouds.chef.domain.Cookbook; import org.jclouds.chef.domain.Sandbox; import org.jclouds.concurrent.Timeout; import org.jclouds.http.HttpResponseException; import org.jclouds.rest.AuthorizationException; -import org.jclouds.rest.ResourceNotFoundException; /** * Provides synchronous access to Chef. @@ -76,7 +75,8 @@ public interface ChefClient { Set 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 * matches the root directory path of the archive @@ -91,39 +91,7 @@ public interface ChefClient { * "409 Conflict" if the cookbook already exists */ @Timeout(duration = 10, timeUnit = TimeUnit.MINUTES) - void createCookbook(String cookbookName, File tgzArchive); - - /** - * 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} - *

- * "401 Unauthorized" if the caller is not a recognized user. - *

- * "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); + void updateCookbook(String cookbookName, String version, Cookbook cookbook); /** * deletes an existing cookbook. @@ -136,7 +104,20 @@ public interface ChefClient { * "403 Forbidden" if you do not have Delete rights on the * cookbook. */ - String deleteCookbook(String cookbookName); + String deleteCookbook(String cookbookName, String version); + + /** + * + * @return the versions of a cookbook or null, if not found + * + * @throws AuthorizationException + *

+ * "401 Unauthorized" if the caller is not a recognized user. + *

+ * "403 Forbidden" if the caller is not authorized to view the + * cookbook. + */ + Set getVersionsOfCookbook(String cookbookName); /** * 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 * cookbook. */ - String getCookbook(String cookbookName); + Cookbook getCookbook(String cookbookName, String version); /** * creates a new client diff --git a/chef/src/main/java/org/jclouds/chef/domain/Attribute.java b/chef/src/main/java/org/jclouds/chef/domain/Attribute.java index cc06c1595a..87cf61cda3 100644 --- a/chef/src/main/java/org/jclouds/chef/domain/Attribute.java +++ b/chef/src/main/java/org/jclouds/chef/domain/Attribute.java @@ -39,7 +39,7 @@ public class Attribute { private String required; private boolean calculated; - private Set choice; + private List choice = Lists.newArrayList(); @SerializedName("default") private String defaultValue; private String type; @@ -72,7 +72,7 @@ public class Attribute { return calculated; } - public Set getChoice() { + public List getChoice() { return choice; } @@ -170,5 +170,5 @@ public class Attribute { + ", displayName=" + displayName + ", recipes=" + recipes + ", required=" + required + ", type=" + type + "]"; } - + } \ No newline at end of file diff --git a/chef/src/main/java/org/jclouds/chef/domain/Metadata.java b/chef/src/main/java/org/jclouds/chef/domain/Metadata.java index e6e21101f1..98ffe9c2d0 100644 --- a/chef/src/main/java/org/jclouds/chef/domain/Metadata.java +++ b/chef/src/main/java/org/jclouds/chef/domain/Metadata.java @@ -34,17 +34,16 @@ public class Metadata { private String license; private String maintainer; private Map suggestions = Maps.newLinkedHashMap(); - private Map dependencies = Maps.newLinkedHashMap(); + private Map> dependencies = Maps.newLinkedHashMap(); @SerializedName("maintainer_email") private String maintainerEmail; - private Map conflicting = Maps.newLinkedHashMap(); + private Map> conflicting = Maps.newLinkedHashMap(); private String description; - private Map providing = Maps.newLinkedHashMap(); - private Map>> platforms = Maps - .newLinkedHashMap(); + private Map> providing = Maps.newLinkedHashMap(); + private Map> platforms = Maps.newLinkedHashMap(); private String version; - private Map> recipes = Maps.newLinkedHashMap(); - private Map replacing = Maps.newLinkedHashMap(); + private Map recipes = Maps.newLinkedHashMap(); + private Map> replacing = Maps.newLinkedHashMap(); private String name; private Map groupings = Maps.newLinkedHashMap(); @SerializedName("long_description") @@ -53,13 +52,13 @@ public class Metadata { private Map recommendations = Maps.newLinkedHashMap(); public Metadata(String license, String maintainer, - Map suggestions, Map dependencies, - String maintainerEmail, Map conflicting, - String description, Map providing, - Map>> platforms, String version, - Map> recipes, - Map replacing, String name, - Map groupings, String longDescription, + Map suggestions, + Map> dependencies, String maintainerEmail, + Map> conflicting, String description, + Map> providing, + Map> platforms, String version, + Map recipes, Map> replacing, + String name, Map groupings, String longDescription, Map attributes, Map recommendations) { this.license = license; this.maintainer = maintainer; @@ -95,7 +94,7 @@ public class Metadata { return suggestions; } - public Map getDependencies() { + public Map> getDependencies() { return dependencies; } @@ -103,7 +102,7 @@ public class Metadata { return maintainerEmail; } - public Map getConflicting() { + public Map> getConflicting() { return conflicting; } @@ -111,11 +110,11 @@ public class Metadata { return description; } - public Map getProviding() { + public Map> getProviding() { return providing; } - public Map>> getPlatforms() { + public Map> getPlatforms() { return platforms; } @@ -123,11 +122,11 @@ public class Metadata { return version; } - public Map> getRecipes() { + public Map getRecipes() { return recipes; } - public Map getReplacing() { + public Map> getReplacing() { return replacing; } @@ -297,5 +296,5 @@ public class Metadata { + ", replacing=" + replacing + ", suggestions=" + suggestions + ", version=" + version + "]"; } - + } \ No newline at end of file diff --git a/chef/src/main/java/org/jclouds/chef/domain/Resource.java b/chef/src/main/java/org/jclouds/chef/domain/Resource.java index 8c674ca114..d25de523b2 100644 --- a/chef/src/main/java/org/jclouds/chef/domain/Resource.java +++ b/chef/src/main/java/org/jclouds/chef/domain/Resource.java @@ -18,6 +18,8 @@ */ package org.jclouds.chef.domain; +import java.net.URI; + /** * Cookbook object. * @@ -26,12 +28,15 @@ package org.jclouds.chef.domain; public class Resource { private String name; + private URI url; private String checksum; private String path; 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.url = url; this.checksum = checksum; this.path = path; this.specificity = specificity; @@ -44,6 +49,9 @@ public class Resource { return name; } + public URI getUrl() { + return url; + } public String getChecksum() { return checksum; } @@ -65,6 +73,7 @@ public class Resource { result = prime * result + ((path == null) ? 0 : path.hashCode()); result = prime * result + ((specificity == null) ? 0 : specificity.hashCode()); + result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; } @@ -97,14 +106,18 @@ public class Resource { return false; } else if (!specificity.equals(other.specificity)) return false; + if (url == null) { + if (other.url != null) + return false; + } else if (!url.equals(other.url)) + return false; return true; } @Override public String toString() { return "Resource [checksum=" + checksum + ", name=" + name + ", path=" - + path + ", specificity=" + specificity + "]"; + + path + ", specificity=" + specificity + ", url=" + url + "]"; } - } \ No newline at end of file diff --git a/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookFromJson.java b/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookFromJson.java new file mode 100644 index 0000000000..3762dc2959 --- /dev/null +++ b/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookFromJson.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + @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); + } + } +} \ No newline at end of file diff --git a/chef/src/main/java/org/jclouds/chef/functions/ParseValueSetFromJson.java b/chef/src/main/java/org/jclouds/chef/functions/ParseValueSetFromJson.java new file mode 100644 index 0000000000..6d91b2ff96 --- /dev/null +++ b/chef/src/main/java/org/jclouds/chef/functions/ParseValueSetFromJson.java @@ -0,0 +1,83 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + * + * ==================================================================== + * 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> { + @Inject + public ParseValueSetFromJson(Gson gson) { + super(gson); + } + + @SuppressWarnings("unchecked") + @Override + protected Set apply(InputStream stream) { + try { + Type map = new TypeToken>>() { + }.getType(); + return Iterables.get( + ((Map>) gson.fromJson(new InputStreamReader( + stream, "UTF-8"), map)).entrySet(), 0).getValue(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("jclouds requires UTF-8 encoding", e); + } + } +} \ No newline at end of file diff --git a/chef/src/test/java/org/jclouds/chef/ChefAsyncClientTest.java b/chef/src/test/java/org/jclouds/chef/ChefAsyncClientTest.java index 3bc8f937d4..47304da292 100644 --- a/chef/src/test/java/org/jclouds/chef/ChefAsyncClientTest.java +++ b/chef/src/test/java/org/jclouds/chef/ChefAsyncClientTest.java @@ -25,15 +25,16 @@ package org.jclouds.chef; import static org.testng.Assert.assertEquals; -import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.Properties; import java.util.Set; import org.jclouds.chef.config.ChefRestClientModule; +import org.jclouds.chef.domain.Cookbook; import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.chef.filters.SignedHeaderAuthTest; +import org.jclouds.chef.functions.ParseCookbookFromJson; import org.jclouds.chef.functions.ParseKeyFromJson; import org.jclouds.chef.functions.ParseKeySetFromJson; 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.collect.ImmutableSet; -import com.google.common.io.Files; import com.google.inject.Module; import com.google.inject.TypeLiteral; @@ -67,22 +67,27 @@ import com.google.inject.TypeLiteral; @Test(groups = "unit", testName = "chef.ChefAsyncClientTest") public class ChefAsyncClientTest extends RestClientTest { - public void testGetUploadUrisForContent() throws SecurityException, NoSuchMethodException, - IOException { - Method method = ChefAsyncClient.class.getMethod("getUploadUrisForContent", Set.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, - ImmutableSet.of("0189e76ccc476701d6b374e5a1a27347", - "0c5ecd7788cf4f6c7de2a57193897a6c", "1dda05ed139664f1f89b9dec482b77c0")); + public void testGetUploadUrisForContent() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod( + "getUploadUrisForContent", Set.class); + GeneratedHttpRequest httpRequest = processor + .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( - httpRequest, - "Accept: application/json\nContent-Length: 135\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); + httpRequest, + "Accept: application/json\nContent-Length: 135\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); assertPayloadEquals( - httpRequest, - "{\"checksums\":{\"0189e76ccc476701d6b374e5a1a27347\":null,\"0c5ecd7788cf4f6c7de2a57193897a6c\":null,\"1dda05ed139664f1f89b9dec482b77c0\":null}}"); + httpRequest, + "{\"checksums\":{\"0189e76ccc476701d6b374e5a1a27347\":null,\"0c5ecd7788cf4f6c7de2a57193897a6c\":null,\"1dda05ed139664f1f89b9dec482b77c0\":null}}"); - assertResponseParserClassEquals(method, httpRequest, ParseSandboxFromJson.class); + assertResponseParserClassEquals(method, httpRequest, + ParseSandboxFromJson.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -90,15 +95,20 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testGetCookbook() throws SecurityException, NoSuchMethodException, IOException { - Method method = ChefAsyncClient.class.getMethod("getCookbook", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, - "cookbook"); - assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks/cookbook HTTP/1.1"); - assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n"); + public void testGetCookbook() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("getCookbook", + String.class, String.class); + GeneratedHttpRequest httpRequest = processor + .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); - assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class); + assertResponseParserClassEquals(method, httpRequest, + ParseCookbookFromJson.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); @@ -106,16 +116,20 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testDeleteCookbook() throws SecurityException, NoSuchMethodException, IOException { - Method method = ChefAsyncClient.class.getMethod("deleteCookbook", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, - "cookbook"); + public void testDeleteCookbook() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("deleteCookbook", + String.class, String.class); + GeneratedHttpRequest httpRequest = processor + .createRequest(method, "cookbook", "1.0.0"); assertRequestLineEquals(httpRequest, - "DELETE http://localhost:4000/cookbooks/cookbook HTTP/1.1"); - assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n"); + "DELETE 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); - assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class); + assertResponseParserClassEquals(method, httpRequest, + CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); @@ -123,79 +137,24 @@ public class ChefAsyncClientTest extends RestClientTest { } - private static final String COOOKBOOK_BODY = - - "----JCLOUDS--\r\n" + "Content-Disposition: form-data; name=\"name\"\r\n\r\n" + "cookbook\r\n" - + "----JCLOUDS--\r\n" - + "Content-Disposition: form-data; name=\"file\"; filename=\"cookbook.tar.gz\"\r\n" - + "Content-Type: application/octet-stream\r\n\r\n\r\n" + "----JCLOUDS----\r\n"; - - 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 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 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 httpRequest = processor.createRequest(method, - "cookbook", file); + public void testUpdateCookbook() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("updateCookbook", + String.class, String.class, Cookbook.class); + GeneratedHttpRequest httpRequest = processor + .createRequest(method, "cookbook", "1.0.1", new Cookbook()); 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( - 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())); + httpRequest, + "Accept: application/json\nContent-Length: 134\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); + assertPayloadEquals( + httpRequest, + "{\"definitions\":[],\"attributes\":[],\"files\":[],\"providers\":[],\"resources\":[],\"templates\":[],\"libraries\":[],\"recipes\":[],\"root_files\":[]}"); - assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class); + assertResponseParserClassEquals(method, httpRequest, + CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -203,36 +162,20 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testUpdateCookbookByte() throws SecurityException, NoSuchMethodException, - IOException { - Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, byte[].class); - GeneratedHttpRequest 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 { + public void testListCookbooks() throws SecurityException, + NoSuchMethodException, IOException { Method method = ChefAsyncClient.class.getMethod("listCookbooks"); - GeneratedHttpRequest httpRequest = processor.createRequest(method); + GeneratedHttpRequest httpRequest = processor + .createRequest(method); - assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks HTTP/1.1"); - assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n"); + assertRequestLineEquals(httpRequest, + "GET http://localhost:4000/cookbooks HTTP/1.1"); + assertHeadersEqual(httpRequest, + "Accept: application/json\nX-Chef-Version: 0.9.0\n"); assertPayloadEquals(httpRequest, null); - assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class); + assertResponseParserClassEquals(method, httpRequest, + ParseKeySetFromJson.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -240,14 +183,20 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testClientExists() throws SecurityException, NoSuchMethodException, IOException { - Method method = ChefAsyncClient.class.getMethod("clientExists", String.class); - GeneratedHttpRequest 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"); + public void testClientExists() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("clientExists", + String.class); + GeneratedHttpRequest 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); - assertResponseParserClassEquals(method, httpRequest, ReturnTrueIf2xx.class); + assertResponseParserClassEquals(method, httpRequest, + ReturnTrueIf2xx.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class); @@ -255,14 +204,20 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testDeleteClient() throws SecurityException, NoSuchMethodException, IOException { - Method method = ChefAsyncClient.class.getMethod("deleteClient", String.class); - GeneratedHttpRequest 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"); + public void testDeleteClient() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("deleteClient", + String.class); + GeneratedHttpRequest 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); - assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class); + assertResponseParserClassEquals(method, httpRequest, + ReturnStringIf200.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); @@ -270,17 +225,22 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException, - IOException { - Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, "client"); - assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1"); + public void testGenerateKeyForClient() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("generateKeyForClient", + String.class); + GeneratedHttpRequest httpRequest = processor + .createRequest(method, "client"); + assertRequestLineEquals(httpRequest, + "PUT http://localhost:4000/clients/client HTTP/1.1"); assertHeadersEqual( - httpRequest, - "Accept: application/json\nContent-Length: 44\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); - assertPayloadEquals(httpRequest, "{\"clientname\":\"client\", \"private_key\": true}"); + httpRequest, + "Accept: application/json\nContent-Length: 44\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); + assertPayloadEquals(httpRequest, + "{\"clientname\":\"client\", \"private_key\": true}"); - assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class); + assertResponseParserClassEquals(method, httpRequest, + ParseKeyFromJson.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -288,17 +248,22 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testCreateClient() throws SecurityException, NoSuchMethodException, IOException { - Method method = ChefAsyncClient.class.getMethod("createClient", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, "client"); + public void testCreateClient() throws SecurityException, + NoSuchMethodException, IOException { + Method method = ChefAsyncClient.class.getMethod("createClient", + String.class); + GeneratedHttpRequest 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( - httpRequest, - "Accept: application/json\nContent-Length: 23\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); + httpRequest, + "Accept: application/json\nContent-Length: 23\nContent-Type: application/json\nX-Chef-Version: 0.9.0\n"); assertPayloadEquals(httpRequest, "{\"clientname\":\"client\"}"); - assertResponseParserClassEquals(method, httpRequest, ParseKeyFromJson.class); + assertResponseParserClassEquals(method, httpRequest, + ParseKeyFromJson.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -306,15 +271,20 @@ public class ChefAsyncClientTest extends RestClientTest { } - public void testListClients() throws SecurityException, NoSuchMethodException, IOException { + public void testListClients() throws SecurityException, + NoSuchMethodException, IOException { Method method = ChefAsyncClient.class.getMethod("listClients"); - GeneratedHttpRequest httpRequest = processor.createRequest(method); + GeneratedHttpRequest httpRequest = processor + .createRequest(method); - assertRequestLineEquals(httpRequest, "GET http://localhost:4000/clients HTTP/1.1"); - assertHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: 0.9.0\n"); + assertRequestLineEquals(httpRequest, + "GET http://localhost:4000/clients HTTP/1.1"); + assertHeadersEqual(httpRequest, + "Accept: application/json\nX-Chef-Version: 0.9.0\n"); assertPayloadEquals(httpRequest, null); - assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class); + assertResponseParserClassEquals(method, httpRequest, + ParseKeySetFromJson.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -325,7 +295,8 @@ public class ChefAsyncClientTest extends RestClientTest { @Override protected void checkFilters(GeneratedHttpRequest httpRequest) { assertEquals(httpRequest.getFilters().size(), 1); - assertEquals(httpRequest.getFilters().get(0).getClass(), SignedHeaderAuth.class); + assertEquals(httpRequest.getFilters().get(0).getClass(), + SignedHeaderAuth.class); } @Override @@ -352,6 +323,6 @@ public class ChefAsyncClientTest extends RestClientTest { @Override public ContextSpec createContextSpec() { return new RestContextFactory().createContextSpec("chef", "user", - SignedHeaderAuthTest.PRIVATE_KEY, new Properties()); + SignedHeaderAuthTest.PRIVATE_KEY, new Properties()); } } diff --git a/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java b/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java index 5b0d684905..51b8654d76 100644 --- a/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java +++ b/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java @@ -28,11 +28,10 @@ import static org.testng.Assert.assertNotNull; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.net.URI; import java.util.Properties; import java.util.Set; +import org.jclouds.chef.domain.Cookbook; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContextFactory; @@ -42,7 +41,6 @@ import org.testng.annotations.Test; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableSet; -import com.google.common.io.ByteStreams; import com.google.common.io.Files; import com.google.inject.Module; @@ -54,7 +52,7 @@ import com.google.inject.Module; @Test(groups = "live", testName = "chef.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 RestContext validatorConnection; private RestContext clientConnection; @@ -67,39 +65,45 @@ public class ChefClientLiveTest { private byte[] cookbookContent; 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" }) 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"); if (validator == null || validator.equals("")) validator = "chef-validator"; String validatorKey = System.getProperty("jclouds.test.validator.key"); if (validatorKey == null || validatorKey.equals("")) - validatorKey = System.getProperty("user.home") + "/.chef/validation.pem"; - user = checkNotNull(System.getProperty("jclouds.test.identity")); + validatorKey = System.getProperty("user.home") + + "/.chef/validation.pem"; + user = checkNotNull(System.getProperty("jclouds.test.identity"), + "jclouds.test.identity"); String keyfile = System.getProperty("jclouds.test.credential"); if (keyfile == null || keyfile.equals("")) keyfile = System.getProperty("user.home") + "/.chef/" + user + ".pem"; - validatorConnection = createConnection(validator, Files.toString(new File(validatorKey), - Charsets.UTF_8)); - adminConnection = createConnection(user, Files.toString(new File(keyfile), Charsets.UTF_8)); + validatorConnection = createConnection(validator, Files.toString( + new File(validatorKey), Charsets.UTF_8)); + adminConnection = createConnection(user, Files.toString( + new File(keyfile), Charsets.UTF_8)); } - private RestContext createConnection(String identity, String key) - throws IOException { + private RestContext createConnection( + String identity, String key) throws IOException { Properties props = new Properties(); props.setProperty("chef.endpoint", endpoint); - return new RestContextFactory().createContext("chef", identity, key, ImmutableSet - . of(new Log4JLoggingModule()), props); + return new RestContextFactory().createContext("chef", identity, key, + ImmutableSet. of(new Log4JLoggingModule()), props); } @Test public void testListClients() throws Exception { Set clients = validatorConnection.getApi().listClients(); assertNotNull(clients); - assert clients.contains(validator) : "validator: " + validator + " not in: " + clients; + assert clients.contains(validator) : "validator: " + validator + + " not in: " + clients; } @Test(dependsOnMethods = "testListClients") @@ -127,39 +131,43 @@ public class ChefClientLiveTest { } @Test - public void testCreateCookbook() throws Exception { - adminConnection.getApi().deleteCookbook(COOKBOOK_NAME); - InputStream in = null; - try { - in = URI.create(COOKBOOK_URI).toURL().openStream(); - - cookbookContent = ByteStreams.toByteArray(in); - - 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(); - } + public void testListCookbooks() throws Exception { + for (String cookbook : adminConnection.getApi().listCookbooks()) + for (String version : adminConnection.getApi().getVersionsOfCookbook( + cookbook)) { + System.err.printf("%s/%s:%n", cookbook, version); + System.err.printf("%s%n", adminConnection.getApi().getCookbook( + cookbook, version)); + } } - @Test(dependsOnMethods = "testCreateCookbook") + @Test(dependsOnMethods = "testListCookbooks") public void testUpdateCookbook() throws Exception { - adminConnection.getApi().updateCookbook(COOKBOOK_NAME, cookbookFile); - // TODO verify timestamp or something - adminConnection.getApi().updateCookbook(COOKBOOK_NAME, cookbookContent); + for (String cookbook : adminConnection.getApi().listCookbooks()) + for (String version : adminConnection.getApi().getVersionsOfCookbook( + 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") - public void testListCookbooks() throws Exception { + public void testCreateCookbook() throws Exception { 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" }) diff --git a/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookFromJsonTest.java b/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookFromJsonTest.java new file mode 100644 index 0000000000..0cbe4f66f4 --- /dev/null +++ b/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookFromJsonTest.java @@ -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. of(), + "Chef::CookbookVersion", + ImmutableSet. of(), + ImmutableSet. of(), + new Metadata("Apache v2.0", "Your Name", ImmutableMap + . of(), ImmutableMap + .> of(), "youremail@example.com", + ImmutableMap.> of(), + "A fabulous new cookbook", ImmutableMap + .> of(), ImmutableMap + .> of(), "0.0.0", + ImmutableMap. of(), ImmutableMap + .> of(), "apache-chef-demo", + ImmutableMap. of(), "", ImmutableMap + . of(), ImmutableMap + . of()), + ImmutableSet. of(), + "apache-chef-demo", + ImmutableSet. of(), + ImmutableSet. of(), + ImmutableSet. of(), + "0.0.0", + ImmutableSet. of(), + ImmutableSet + . of( + new Resource( + "README", + URI + .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D"), + "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")); + + } +} diff --git a/chef/src/test/java/org/jclouds/chef/functions/ParseValueSetFromJsonTest.java b/chef/src/test/java/org/jclouds/chef/functions/ParseValueSetFromJsonTest.java new file mode 100644 index 0000000000..cf5629693d --- /dev/null +++ b/chef/src/test/java/org/jclouds/chef/functions/ParseValueSetFromJsonTest.java @@ -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")); + } +} diff --git a/chef/src/test/resources/apache-chef-demo-cookbook.json b/chef/src/test/resources/apache-chef-demo-cookbook.json new file mode 100644 index 0000000000..0a3e384039 --- /dev/null +++ b/chef/src/test/resources/apache-chef-demo-cookbook.json @@ -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" +} \ No newline at end of file diff --git a/chef/src/test/resources/brew-cookbook.json b/chef/src/test/resources/brew-cookbook.json new file mode 100644 index 0000000000..f0b09ede2a --- /dev/null +++ b/chef/src/test/resources/brew-cookbook.json @@ -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"} \ No newline at end of file diff --git a/chef/src/test/resources/mysql-cookbook.json b/chef/src/test/resources/mysql-cookbook.json index d694abfda5..b0f8bc4ee6 100644 --- a/chef/src/test/resources/mysql-cookbook.json +++ b/chef/src/test/resources/mysql-cookbook.json @@ -1,304 +1 @@ -{ - "templates": [ - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?version=9.10&id=my.cnf.erb&platform=ubuntu", - "specificity": "ubuntu-9.10", - "name": "my.cnf.erb", - "checksum": "fbab8006536e2504b46e457b46554ab7c54727e7830201331567542e8df70ab4" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?version=8.04&id=my.cnf.erb&platform=ubuntu", - "specificity": "ubuntu-8.04", - "name": "my.cnf.erb", - "checksum": "5ef04441604a866a675153ce3bd8ec3db18d9c7392e38e4388fd33e949db3615" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=port_mysql.erb", - "specificity": "default", - "name": "port_mysql.erb", - "checksum": "0146b4b31f9a4dba0526d1c586a8b8370d671dbf0031ef06dd82b439424a6692" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=mysql-server.seed.erb", - "specificity": "default", - "name": "mysql-server.seed.erb", - "checksum": "797c295e0d5d2a30f1ed999b39b85b067e1043e58cb4bd9d365479ebcf2ceef2" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=debian.cnf.erb", - "specificity": "default", - "name": "debian.cnf.erb", - "checksum": "a5e6a34ed8c2a85192f63af7864e9afb9df19a128e561202b4a816c3da636c6e" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=grants.sql.erb", - "specificity": "default", - "name": "grants.sql.erb", - "checksum": "e11013b7bf2b78b386dcd4c97091b783eff217a4ec85bb4d13cf5dae0f3cb0d6" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=my.cnf.erb", - "specificity": "default", - "name": "my.cnf.erb", - "checksum": "dea2a28182d835501f4d4096b0f9c5cb478fd57383d607b061ab04242d5f0954" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?version=10.04&id=my.cnf.erb&platform=ubuntu", - "specificity": "ubuntu-10.04", - "name": "my.cnf.erb", - "checksum": "fbab8006536e2504b46e457b46554ab7c54727e7830201331567542e8df70ab4" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=my.cnf.erb&platform=redhat", - "specificity": "redhat", - "name": "my.cnf.erb", - "checksum": "664eb39f181c03cfa1d93a6097d30cc9f259e1534490e89c5fa69841f5da572d" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/templates?id=my.cnf.erb&platform=centos", - "specificity": "centos", - "name": "my.cnf.erb", - "checksum": "664eb39f181c03cfa1d93a6097d30cc9f259e1534490e89c5fa69841f5da572d" - } - ], - "attributes": [ - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/attributes?id=server.rb", - "name": "server.rb", - "checksum": "6d3936ea2d5c40dac2120951af0b9fc76b7077567341f770a98cbfd6915531f9" - } - ], - "definitions": [ - ], - "metadata": { - "conflicting": { - }, - "attributes": { - "mysql/server_root_password": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "randomly generated", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Server Root Password", - "description": "Randomly generated password for the mysqld root user" - }, - "mysql/tunable/max_heap_table_size": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "32M", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Max Heap Table Size" - }, - "mysql/bind_address": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "ipaddress", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Bind Address", - "description": "Address that mysqld should listen on" - }, - "mysql/datadir": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "/var/lib/mysql", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Data Directory", - "description": "Location of mysql databases" - }, - "mysql/tunable/wait_timeout": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "180", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Wait Timeout" - }, - "mysql/tunable/back_log": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "128", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Back Log" - }, - "mysql/tunable/net_read_timeout": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "30", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Net Read Timeout" - }, - "mysql/tunable/max_connections": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "800", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Max Connections" - }, - "mysql/tunable": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "type": "hash", - "recipes": [ - ], - "display_name": "MySQL Tunables", - "description": "Hash of MySQL tunable attributes" - }, - "mysql/tunable/table_cache": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "128", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Table Cache" - }, - "mysql/ec2_path": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "/mnt/mysql", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL EC2 Path", - "description": "Location of mysql directory on EC2 instance EBS volumes" - }, - "mysql/tunable/key_buffer": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "250M", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tuntable Key Buffer" - }, - "mysql/tunable/net_write_timeout": { - "required": "optional", - "calculated": false, - "choice": [ - ], - "default": "30", - "type": "string", - "recipes": [ - ], - "display_name": "MySQL Tunable Net Write Timeout" - } - }, - "providing": { - }, - "license": "Apache 2.0", - "replacing": { - }, - "long_description": "= DESCRIPTION:\n\nInstalls and configures MySQL client or server.\n\n= REQUIREMENTS:\n\n== Platform:\n\nBest tested on Ubuntu 9.04,9.10. On EC2, requires platform that supports -o bind option for the 'mount' command.\n\n== Cookbooks:\n\nRequires Opscode's openssl cookbook for secure password generation.\n\n= ATTRIBUTES: \n\n* mysql[:server_root_password] - Set the server's root password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_repl_password] - Set the replication user 'repl' password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_debian_password] - Set the debian-sys-maint user password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:bind_address] - Listen address for MySQLd, default is node's ipaddress.\n* mysql[:datadir] - Location for mysql data directory, default is \"/var/lib/mysql\" \n* mysql[:ec2_path] - location of mysql datadir on EC2 nodes, default \"/mnt/mysql\" \n\nPerformance tuning attributes, each corresponds to the same-named parameter in my.cnf; default values listed\n\n* mysql[:tunable][:key_buffer] = \"250M\"\n* mysql[:tunable][:max_connections] = \"800\" \n* mysql[:tunable][:wait_timeout] = \"180\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:back_log] = \"128\" \n* mysql[:tunable][:table_cache] = \"128\" \n* mysql[:tunable][:max_heap_table_size] = \"32M\" \n\n= USAGE:\n\nOn client nodes,\n\n include_recipe \"mysql::client\"\n \nAs the common use case is on systems with Ruby, we also install the MySQL RubyGem. Because we may want to be able to use the gem within another Chef recipe, we make sure the mysql development package and gem are installed first. The key is this:\n\n r = package ... do\n action :nothing\n end\n \n r.run_action(:install)\n \nThis creates a resource object for the package and does the installation before other recipes are parsed. You'll need to have the C compiler and such (ie, build-essential on Ubuntu) before running the recipes, but we already do that when installing Chef :-). If you want to be able to access a MySQL database via Ruby within another recipe, you could do so, like so:\n\n Gem.clear_paths # needed for Chef to find the gem...\n require 'mysql' # requires the mysql gem\n\n execute \"create #{node[:railsapp][:db][:database]} database\" do\n command \"/usr/bin/mysqladmin -u root -p#{node[:mysql][:server_root_password]} create #{node[:railsapp][:db][:database]}\"\n not_if do\n m = Mysql.new(\"localhost\", \"root\", @node[:mysql][:server_root_password])\n m.list_dbs.include?(@node[:railsapp][:db][:database])\n end\n end\n\nOn server nodes, \n\n include_recipe \"mysql::server\"\n \nOn Debian/Ubuntu this will preseed the MySQL package with the randomly generated root password. You can of course change the password afterward, but this makes sure that there's a good password set. You can view it in the node data in the Chef Server webui. Sets a new password for debian-sys-maint user as well.\n\nAlso sets up 'repl' user grants for replication slaves.\n\nOn EC2 nodes,\n\n include_recipe \"mysql::server_ec2\"\n \nWhen the ec2_path doesn't exist we look for a mounted filesystem (eg, EBS) and move the datadir there.\n\nThe client recipe is already included by server and 'default' recipes.\n\n= LICENSE and AUTHOR:\n \nAuthor:: Joshua Timberman ()\nAuthor:: AJ Christensen ()\n\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", - "dependencies": { - "openssl": [ - ] - }, - "groupings": { - }, - "recommendations": { - }, - "platforms": { - "debian": [ - ], - "ubuntu": [ - ] - }, - "description": "Installs and configures mysql for client or server", - "version": "0.21.2", - "maintainer": "Opscode, Inc.", - "name": "mysql", - "recipes": { - "mysql::client": "Installs packages required for mysql clients using run_action magic", - "mysql::server_ec2": "Performs EC2-specific mountpoint manipulation", - "mysql::server": "Installs packages required for mysql servers w/o manual intervention" - }, - "suggestions": { - }, - "maintainer_email": "cookbooks@opscode.com" - }, - "resources": [ - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/resources?id=database.rb", - "name": "database.rb", - "checksum": "84e759036cf80ba08eb23a232dca11ca0942f947798dba42fb7c7eebba7bf964" - } - ], - "files": [ - ], - "name": "mysql", - "libraries": [ - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/libraries?id=database.rb", - "name": "database.rb", - "checksum": "515056944a9fc6eb966ee2c527862b4823d5adc7c3f7e27004631fa5a5d495a1" - } - ], - "recipes": [ - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/recipes?id=server.rb", - "name": "server.rb", - "checksum": "9fb286a7968954503e7839acaa083c00bf399e7c56f60a74bc64644894c4b07e" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/recipes?id=server_ec2.rb", - "name": "server_ec2.rb", - "checksum": "ab13e15228f33190c6333d7b13d0af7636ceae6c7ccd2cd18b1f144c4b0e459b" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/recipes?id=default.rb", - "name": "default.rb", - "checksum": "2a220ff3c2323ee8d25369901376643ecc33e61dafcfb29982577ac3a5ab7716" - }, - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/recipes?id=client.rb", - "name": "client.rb", - "checksum": "729dbd2ec84130fac5a76497d515265ce648690cb278425d55e0e91d6e590f3a" - } - ], - "providers": [ - { - "uri": "https://api.opscode.com/organizations/jclouds/cookbooks/mysql/providers?id=database.rb", - "name": "database.rb", - "checksum": "091b5faefaf0eebbc83c5361e1889baf4de2394749b7cf10f9509262e987d1f8" - } - ] -} \ No newline at end of file +{"definitions":[],"name":"mysql-0.21.2","attributes":[{"name":"server.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-548fa4bc548b8b59ac98fffee8e81f4a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=MsgggSKS0T1q1Lc72nJpHORBQX0%3D","checksum":"548fa4bc548b8b59ac98fffee8e81f4a","path":"attributes/server.rb","specificity":"default"}],"files":[],"json_class":"Chef::CookbookVersion","providers":[{"name":"database.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b994881a2aba60e32c4b6408ffba993d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2XMRbryCmEqirCWLCvrXoenYubw%3D","checksum":"b994881a2aba60e32c4b6408ffba993d","path":"providers/database.rb","specificity":"default"}],"metadata":{"dependencies":{"openssl":[]},"name":"mysql","maintainer_email":"cookbooks@opscode.com","attributes":{"mysql/server_root_password":{"required":"optional","calculated":false,"default":"randomly generated","choice":[],"type":"string","recipes":[],"display_name":"MySQL Server Root Password","description":"Randomly generated password for the mysqld root user"},"mysql/tunable/max_heap_table_size":{"required":"optional","calculated":false,"default":"32M","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Max Heap Table Size"},"mysql/bind_address":{"required":"optional","calculated":false,"default":"ipaddress","choice":[],"type":"string","recipes":[],"display_name":"MySQL Bind Address","description":"Address that mysqld should listen on"},"mysql/datadir":{"required":"optional","calculated":false,"default":"/var/lib/mysql","choice":[],"type":"string","recipes":[],"display_name":"MySQL Data Directory","description":"Location of mysql databases"},"mysql/tunable/wait_timeout":{"required":"optional","calculated":false,"default":"180","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Wait Timeout"},"mysql/tunable/back_log":{"required":"optional","calculated":false,"default":"128","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Back Log"},"mysql/tunable/net_read_timeout":{"required":"optional","calculated":false,"default":"30","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Net Read Timeout"},"mysql/tunable/max_connections":{"required":"optional","calculated":false,"default":"800","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Max Connections"},"mysql/tunable":{"required":"optional","calculated":false,"choice":[],"type":"hash","recipes":[],"display_name":"MySQL Tunables","description":"Hash of MySQL tunable attributes"},"mysql/tunable/table_cache":{"required":"optional","calculated":false,"default":"128","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Table Cache"},"mysql/ec2_path":{"required":"optional","calculated":false,"default":"/mnt/mysql","choice":[],"type":"string","recipes":[],"display_name":"MySQL EC2 Path","description":"Location of mysql directory on EC2 instance EBS volumes"},"mysql/tunable/key_buffer":{"required":"optional","calculated":false,"default":"250M","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tuntable Key Buffer"},"mysql/tunable/net_write_timeout":{"required":"optional","calculated":false,"default":"30","choice":[],"type":"string","recipes":[],"display_name":"MySQL Tunable Net Write Timeout"}},"license":"Apache 2.0","maintainer":"Opscode, Inc.","suggestions":{},"platforms":{"debian":[],"ubuntu":[]},"long_description":"= DESCRIPTION:\n\nInstalls and configures MySQL client or server.\n\n= REQUIREMENTS:\n\n== Platform:\n\nBest tested on Ubuntu 9.04,9.10. On EC2, requires platform that supports -o bind option for the 'mount' command.\n\n== Cookbooks:\n\nRequires Opscode's openssl cookbook for secure password generation.\n\n= ATTRIBUTES: \n\n* mysql[:server_root_password] - Set the server's root password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_repl_password] - Set the replication user 'repl' password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_debian_password] - Set the debian-sys-maint user password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:bind_address] - Listen address for MySQLd, default is node's ipaddress.\n* mysql[:datadir] - Location for mysql data directory, default is \"/var/lib/mysql\" \n* mysql[:ec2_path] - location of mysql datadir on EC2 nodes, default \"/mnt/mysql\" \n\nPerformance tuning attributes, each corresponds to the same-named parameter in my.cnf; default values listed\n\n* mysql[:tunable][:key_buffer] = \"250M\"\n* mysql[:tunable][:max_connections] = \"800\" \n* mysql[:tunable][:wait_timeout] = \"180\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:back_log] = \"128\" \n* mysql[:tunable][:table_cache] = \"128\" \n* mysql[:tunable][:max_heap_table_size] = \"32M\" \n\n= USAGE:\n\nOn client nodes,\n\n include_recipe \"mysql::client\"\n \nAs the common use case is on systems with Ruby, we also install the MySQL RubyGem. Because we may want to be able to use the gem within another Chef recipe, we make sure the mysql development package and gem are installed first. The key is this:\n\n r = package ... do\n action :nothing\n end\n \n r.run_action(:install)\n \nThis creates a resource object for the package and does the installation before other recipes are parsed. You'll need to have the C compiler and such (ie, build-essential on Ubuntu) before running the recipes, but we already do that when installing Chef :-). If you want to be able to access a MySQL database via Ruby within another recipe, you could do so, like so:\n\n Gem.clear_paths # needed for Chef to find the gem...\n require 'mysql' # requires the mysql gem\n\n execute \"create #{node[:railsapp][:db][:database]} database\" do\n command \"/usr/bin/mysqladmin -u root -p#{node[:mysql][:server_root_password]} create #{node[:railsapp][:db][:database]}\"\n not_if do\n m = Mysql.new(\"localhost\", \"root\", @node[:mysql][:server_root_password])\n m.list_dbs.include?(@node[:railsapp][:db][:database])\n end\n end\n\nOn server nodes, \n\n include_recipe \"mysql::server\"\n \nOn Debian/Ubuntu this will preseed the MySQL package with the randomly generated root password. You can of course change the password afterward, but this makes sure that there's a good password set. You can view it in the node data in the Chef Server webui. Sets a new password for debian-sys-maint user as well.\n\nAlso sets up 'repl' user grants for replication slaves.\n\nOn EC2 nodes,\n\n include_recipe \"mysql::server_ec2\"\n \nWhen the ec2_path doesn't exist we look for a mounted filesystem (eg, EBS) and move the datadir there.\n\nThe client recipe is already included by server and 'default' recipes.\n\n= LICENSE and AUTHOR:\n \nAuthor:: Joshua Timberman ()\nAuthor:: AJ Christensen ()\n\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","recommendations":{},"version":"0.21.2","groupings":{},"recipes":{"mysql::client":"Installs packages required for mysql clients using run_action magic","mysql::server_ec2":"Performs EC2-specific mountpoint manipulation","mysql::server":"Installs packages required for mysql servers w/o manual intervention"},"conflicting":{},"description":"Installs and configures mysql for client or server","replacing":{},"providing":{}},"libraries":[{"name":"database.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b2eb0760c07734be9c637dcffc86175a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=CvVbxzrA%2Fuxc59ZjLR5BsMozfxk%3D","checksum":"b2eb0760c07734be9c637dcffc86175a","path":"libraries/database.rb","specificity":"default"}],"resources":[{"name":"database.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8aa8e2cafe54c2932c7aa65d62ec2695?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=6URS94f1HpRibHC%2FhBkr7Eg3dVA%3D","checksum":"8aa8e2cafe54c2932c7aa65d62ec2695","path":"resources/database.rb","specificity":"default"}],"templates":[{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D","checksum":"689c1b6fbb242b6c508384e56646341d","path":"templates/ubuntu-9.10/my.cnf.erb","specificity":"ubuntu-9.10"},{"name":"mysql-server.seed.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-16b036a0bb31957a77e9b825cf616cc5?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=50bRvt6GQqFEcfYtaIsq1d4a4c8%3D","checksum":"16b036a0bb31957a77e9b825cf616cc5","path":"templates/default/mysql-server.seed.erb","specificity":"default"},{"name":"grants.sql.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-932b51ddddcbd24ee10a76ecae33b8ba?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=RHR0obLFcsN1M9tL28IH4Tcur5g%3D","checksum":"932b51ddddcbd24ee10a76ecae33b8ba","path":"templates/default/grants.sql.erb","specificity":"default"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-7746560b37ac8d4a0cf68befbecbd8a3?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=W7Nqkvhw2TBrlDvcM2rlA4Oj5%2Bk%3D","checksum":"7746560b37ac8d4a0cf68befbecbd8a3","path":"templates/default/my.cnf.erb","specificity":"default"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D","checksum":"63bd67fae6d297e8f658e9c0ad01a411","path":"templates/centos/my.cnf.erb","specificity":"centos"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D","checksum":"689c1b6fbb242b6c508384e56646341d","path":"templates/ubuntu-10.04/my.cnf.erb","specificity":"ubuntu-10.04"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D","checksum":"63bd67fae6d297e8f658e9c0ad01a411","path":"templates/redhat/my.cnf.erb","specificity":"redhat"},{"name":"port_mysql.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d2244150a145b3f658cd37c13269fafc?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=23iHcjwpNOvlNf%2BlrKcV2pkU7uo%3D","checksum":"d2244150a145b3f658cd37c13269fafc","path":"templates/default/port_mysql.erb","specificity":"default"},{"name":"debian.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2e08553db526f5f80c28b343f6a616cb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=VdcFYxnLUkj1tS3k8DovrzZEA7E%3D","checksum":"2e08553db526f5f80c28b343f6a616cb","path":"templates/default/debian.cnf.erb","specificity":"default"},{"name":"my.cnf.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1e5068eec65b51f5a327580fb0af4677?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=D5lPeu1UQvA9pEXZm5nVOwj3WIo%3D","checksum":"1e5068eec65b51f5a327580fb0af4677","path":"templates/ubuntu-8.04/my.cnf.erb","specificity":"ubuntu-8.04"}],"cookbook_name":"mysql","version":"0.21.2","recipes":[{"name":"server_ec2.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-f51bd8122b7dccc9f4656319fef3252a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=BUR2mosCvmoOKq4Mkh3JUG0MY38%3D","checksum":"f51bd8122b7dccc9f4656319fef3252a","path":"recipes/server_ec2.rb","specificity":"default"},{"name":"server.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-80daa897597560372d017c58c4df0e3c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=bU3j9Nw%2BnuIroXKrlJZe7tjaugA%3D","checksum":"80daa897597560372d017c58c4df0e3c","path":"recipes/server.rb","specificity":"default"},{"name":"default.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-bd3ba2d05dea6a8cf0dc2a45f540cc32?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=7haumT5EtEM2h8l32efqV%2Fik%2BdY%3D","checksum":"bd3ba2d05dea6a8cf0dc2a45f540cc32","path":"recipes/default.rb","specificity":"default"},{"name":"client.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-a1d679c7480267cd9b69e3194c7e45ab?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=ZhfTiwv1aXC7HZMnW8A7i4vkMCM%3D","checksum":"a1d679c7480267cd9b69e3194c7e45ab","path":"recipes/client.rb","specificity":"default"}],"root_files":[{"name":"README.rdoc","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e9278fc99fd668bdce33d72dc71fade9?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=KPgAGqShEO5SGzz8oRdwIInPUOc%3D","checksum":"e9278fc99fd668bdce33d72dc71fade9","path":"README.rdoc","specificity":"default"},{"name":"metadata.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8d2f9635f4817ff905a4124e09ec6c59?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=fPF2iY7tNrq%2FuNrCjRLImP9vRbA%3D","checksum":"8d2f9635f4817ff905a4124e09ec6c59","path":"metadata.rb","specificity":"default"},{"name":"metadata.json","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e6804b8f3e6dfdbbece9d319537ffea1?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=EVsALLreeAA41%2BiPAfPt%2FxFEIYI%3D","checksum":"e6804b8f3e6dfdbbece9d319537ffea1","path":"metadata.json","specificity":"default"}],"chef_type":"cookbook_version"} \ No newline at end of file diff --git a/chef/src/test/resources/runit-cookbook.json b/chef/src/test/resources/runit-cookbook.json deleted file mode 100644 index e4bc3ed609..0000000000 --- a/chef/src/test/resources/runit-cookbook.json +++ /dev/null @@ -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": [ - ] -} \ No newline at end of file diff --git a/chef/src/test/resources/tomcat-cookbook.json b/chef/src/test/resources/tomcat-cookbook.json new file mode 100644 index 0000000000..6331b514ac --- /dev/null +++ b/chef/src/test/resources/tomcat-cookbook.json @@ -0,0 +1 @@ +{"definitions":[],"name":"tomcat6-0.1.0","files":[{"name":"org.apache.tomcat.tomcat6.plist","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-18e534a72652f3d53b197ca4e5027009?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=M3fBL4t7uuYVXVah2PyZ8eL1QCc%3D","checksum":"18e534a72652f3d53b197ca4e5027009","path":"files/default/org.apache.tomcat.tomcat6.plist","specificity":"default"},{"name":"logging.properties","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6a35ce92050296862ea63b784529d2e0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=vRlKoye2%2Fwz8mdQI%2F3Ht916sllE%3D","checksum":"6a35ce92050296862ea63b784529d2e0","path":"files/default/logging.properties","specificity":"default"}],"attributes":[{"name":"tomcat6.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6e3fd0d16a87a55c569da108194ecb29?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zvYjsgUXIC7Xj3MT8Wd93esDGJM%3D","checksum":"6e3fd0d16a87a55c569da108194ecb29","path":"attributes/tomcat6.rb","specificity":"default"}],"json_class":"Chef::CookbookVersion","providers":[],"metadata":{"dependencies":{},"name":"tomcat6","maintainer_email":"cookbooks@opscode.com","license":"Apache 2.0","attributes":{"tomcat6/with_native":{"required":"optional","calculated":false,"default":"false","choice":[],"type":"string","recipes":[],"display_name":"Tomcat native support","description":"works for centos, install tomcat-native libraries"}},"maintainer":"Opscode, Inc.","suggestions":{},"platforms":{"debian":[],"centos":[],"ubuntu":[],"redhat":[]},"long_description":"= DESCRIPTION:\n\nInstalls Tomcat6\n\n= REQUIREMENTS:\n\n== Platform and Application Environment:\n\nTested on Centos 5.2 8.10. May work on other platforms, esp Redhat.\nNeeds Java at least Java 5\n\n== Cookbooks:\n\nOpscode cookbooks, http://github.com/opscode/cookbooks/tree/master:\n\n* java\n\n= ATTRIBUTES: \n\n= USAGE:\n\n\n= LICENSE and AUTHOR:\n \nAuthor:: Edmund Haselwanter ()\nCopyright:: 2009, Edmund Haselwanter\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","version":"0.1.0","recommendations":{},"conflicting":{},"recipes":{"tomcat6":"Main Tomcat 6 configuration"},"groupings":{},"description":"Installs and configures all aspects of tomcat6 using custom local installation","replacing":{},"providing":{}},"libraries":[{"name":"tomcat_manager.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2b6f7847142bb36823c570899669c54b?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zxIoUKcGYWo9ir6qf1tTy3wvKZ4%3D","checksum":"2b6f7847142bb36823c570899669c54b","path":"libraries/tomcat_manager.rb","specificity":"default"},{"name":"tomcat.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-24db7b7dd6f04f8da5fa2b282910ac08?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=c4Gbn5kX0ZaPbWvk5LAcR77sITg%3D","checksum":"24db7b7dd6f04f8da5fa2b282910ac08","path":"libraries/tomcat.rb","specificity":"default"}],"templates":[{"name":"tomcat-users.xml.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-107263b81e4700cf0adad7af2a133bbd?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=QC7MNIauR2ox5MVlohf2i73uM1s%3D","checksum":"107263b81e4700cf0adad7af2a133bbd","path":"templates/default/tomcat-users.xml.erb","specificity":"default"},{"name":"sv-tomcat6-run.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-fa4432b353fa57b9da26a4bff44285f2?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=q2rDeJFeh4oyhfv9ExMifGB0wxo%3D","checksum":"fa4432b353fa57b9da26a4bff44285f2","path":"templates/default/sv-tomcat6-run.erb","specificity":"default"},{"name":"manager.xml.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-33fd6f63133e7ebe28bc62e58773c408?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=rIijEhwLPf5PWTJOg%2BElbOquPBM%3D","checksum":"33fd6f63133e7ebe28bc62e58773c408","path":"templates/default/manager.xml.erb","specificity":"default"},{"name":"sv-tomcat6-log-run.erb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-09f2bf988663175cd1b7973198dfb5eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=UnfNDP4pDzPM3PoLcLWyTnTa%2FKI%3D","checksum":"09f2bf988663175cd1b7973198dfb5eb","path":"templates/default/sv-tomcat6-log-run.erb","specificity":"default"}],"resources":[],"cookbook_name":"tomcat6","version":"0.1.0","recipes":[{"name":"default.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d45661e4b50f9677de7b8684af26ff9d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=r3CvyVe7dcOzB%2F0fNAun5ldGwr8%3D","checksum":"d45661e4b50f9677de7b8684af26ff9d","path":"recipes/default.rb","specificity":"default"}],"root_files":[{"name":"README.rdoc","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-14f6977f68c3674484e8289e361fb5a4?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=VNZxN%2B7CxO7ZbDHJOS%2FaTtpkPaE%3D","checksum":"14f6977f68c3674484e8289e361fb5a4","path":"README.rdoc","specificity":"default"},{"name":"metadata.rb","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-abc416ffba9ea64ca71635191cb87af6?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=pemynt9Q1F%2BxlS26kLaz%2F4NDGO4%3D","checksum":"abc416ffba9ea64ca71635191cb87af6","path":"metadata.rb","specificity":"default"},{"name":"metadata.json","url":"https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-dd8473a8a7f2b446250ecdefb1882a5e?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=sHpayqP%2Fe4Luv20EMa3q%2FaMN4ms%3D","checksum":"dd8473a8a7f2b446250ecdefb1882a5e","path":"metadata.json","specificity":"default"}],"chef_type":"cookbook_version"} \ No newline at end of file