mirror of https://github.com/apache/jclouds.git
Issue 191: fixed cookbook creation as it was missing metadata section
This commit is contained in:
parent
99e14159a0
commit
7efb519de9
|
@ -38,7 +38,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
|
import org.jclouds.chef.binders.BindClientnameToJsonPayload;
|
||||||
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
|
import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload;
|
||||||
import org.jclouds.chef.binders.BindIsCompletedToJsonPayload;
|
import org.jclouds.chef.binders.BindIsCompletedToJsonPayload;
|
||||||
import org.jclouds.chef.binders.BindMD5sToJsonPayload;
|
import org.jclouds.chef.binders.BindHexEncodedMD5sToJsonPayload;
|
||||||
import org.jclouds.chef.domain.CookbookVersion;
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
import org.jclouds.chef.domain.Sandbox;
|
import org.jclouds.chef.domain.Sandbox;
|
||||||
import org.jclouds.chef.domain.UploadSite;
|
import org.jclouds.chef.domain.UploadSite;
|
||||||
|
@ -81,8 +81,8 @@ public interface ChefAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("sandboxes")
|
@Path("sandboxes")
|
||||||
@ResponseParser(ParseUploadSiteFromJson.class)
|
@ResponseParser(ParseUploadSiteFromJson.class)
|
||||||
ListenableFuture<UploadSite> getUploadSiteForChecksums(
|
ListenableFuture<UploadSite> getUploadSiteForHexEncodedChecksums(
|
||||||
@BinderParam(BindMD5sToJsonPayload.class) Set<byte[]> md5s);
|
@BinderParam(BindHexEncodedMD5sToJsonPayload.class) Set<String> hexEncodedmd5s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChefClient#closeSandbox
|
* @see ChefClient#closeSandbox
|
||||||
|
|
|
@ -61,7 +61,7 @@ import org.jclouds.rest.AuthorizationException;
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||||
public interface ChefClient {
|
public interface ChefClient {
|
||||||
UploadSite getUploadSiteForChecksums(Set<byte[]> md5s);
|
UploadSite getUploadSiteForHexEncodedChecksums(Set<String> hexEncodedmd5s);
|
||||||
|
|
||||||
Sandbox closeSandbox(String id, boolean isCompleted);
|
Sandbox closeSandbox(String id, boolean isCompleted);
|
||||||
|
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.chef.binders;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.rest.binders.BindToStringPayload;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class BindMD5sToJsonPayload extends BindToStringPayload {
|
|
||||||
private final EncryptionService encryptionService;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
BindMD5sToJsonPayload(EncryptionService encryptionService) {
|
|
||||||
this.encryptionService = encryptionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
|
||||||
checkArgument(checkNotNull(input, "input") instanceof Set,
|
|
||||||
"this binder is only valid for Set!");
|
|
||||||
|
|
||||||
Set<byte[]> md5s = (Set<byte[]>) input;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("{\"checksums\":{");
|
|
||||||
|
|
||||||
for (byte[] md5 : md5s)
|
|
||||||
builder.append(String.format("\"%s\":null,", encryptionService.hex(md5)));
|
|
||||||
builder.deleteCharAt(builder.length() - 1);
|
|
||||||
builder.append("}}");
|
|
||||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
|
|
||||||
ImmutableSet.of(MediaType.APPLICATION_JSON));
|
|
||||||
super.bindToRequest(request, builder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -35,7 +35,7 @@ public class CookbookVersion {
|
||||||
private Set<Resource> definitions = Sets.newLinkedHashSet();
|
private Set<Resource> definitions = Sets.newLinkedHashSet();
|
||||||
private Set<Resource> attributes = Sets.newLinkedHashSet();
|
private Set<Resource> attributes = Sets.newLinkedHashSet();
|
||||||
private Set<Resource> files = Sets.newLinkedHashSet();
|
private Set<Resource> files = Sets.newLinkedHashSet();
|
||||||
private Metadata metadata;
|
private Metadata metadata = new Metadata();
|
||||||
private Set<Resource> providers = Sets.newLinkedHashSet();
|
private Set<Resource> providers = Sets.newLinkedHashSet();
|
||||||
@SerializedName("cookbook_name")
|
@SerializedName("cookbook_name")
|
||||||
private String cookbookName;
|
private String cookbookName;
|
||||||
|
|
|
@ -40,7 +40,6 @@ import org.jclouds.chef.functions.ParseKeySetFromJson;
|
||||||
import org.jclouds.chef.functions.ParseSandboxFromJson;
|
import org.jclouds.chef.functions.ParseSandboxFromJson;
|
||||||
import org.jclouds.chef.functions.ParseUploadSiteFromJson;
|
import org.jclouds.chef.functions.ParseUploadSiteFromJson;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
import org.jclouds.http.functions.CloseContentAndReturn;
|
import org.jclouds.http.functions.CloseContentAndReturn;
|
||||||
|
@ -90,15 +89,14 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetUploadSiteForChecksums() throws SecurityException, NoSuchMethodException,
|
public void testGetUploadSiteForHexEncodedChecksums() throws SecurityException,
|
||||||
IOException {
|
NoSuchMethodException, IOException {
|
||||||
EncryptionService encservice = injector.getInstance(EncryptionService.class);
|
|
||||||
|
|
||||||
Method method = ChefAsyncClient.class.getMethod("getUploadSiteForChecksums", Set.class);
|
Method method = ChefAsyncClient.class.getMethod("getUploadSiteForHexEncodedChecksums",
|
||||||
|
Set.class);
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||||
ImmutableSet.of(encservice.fromHex("0189e76ccc476701d6b374e5a1a27347"), encservice
|
ImmutableSet.of("0189e76ccc476701d6b374e5a1a27347",
|
||||||
.fromHex("0c5ecd7788cf4f6c7de2a57193897a6c"), encservice
|
"0c5ecd7788cf4f6c7de2a57193897a6c", "1dda05ed139664f1f89b9dec482b77c0"));
|
||||||
.fromHex("1dda05ed139664f1f89b9dec482b77c0")));
|
|
||||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/sandboxes HTTP/1.1");
|
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/sandboxes HTTP/1.1");
|
||||||
assertHeadersEqual(
|
assertHeadersEqual(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
|
@ -153,17 +151,16 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
||||||
Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, String.class,
|
Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, String.class,
|
||||||
CookbookVersion.class);
|
CookbookVersion.class);
|
||||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||||
"cookbook", "1.0.1", new CookbookVersion());
|
"cookbook", "1.0.1", new CookbookVersion("cookbook", "1.0.1"));
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest,
|
assertRequestLineEquals(httpRequest,
|
||||||
"PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1");
|
"PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1");
|
||||||
assertHeadersEqual(
|
assertHeadersEqual(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"Accept: application/json\nContent-Length: 202\nContent-Type: application/json\nX-Chef-Version: 0.9.6\n");
|
"Accept: application/json\nContent-Length: 446\nContent-Type: application/json\nX-Chef-Version: 0.9.6\n");
|
||||||
assertPayloadEquals(
|
assertPayloadEquals(
|
||||||
httpRequest,
|
httpRequest,
|
||||||
"{\"definitions\":[],\"attributes\":[],\"files\":[],\"providers\":[],\"resources\":[],\"templates\":[],\"libraries\":[],\"recipes\":[],\"root_files\":[],\"json_class\":\"Chef::CookbookVersion\",\"chef_type\":\"cookbook_version\"}");
|
"{\"name\":\"cookbook-1.0.1\",\"definitions\":[],\"attributes\":[],\"files\":[],\"metadata\":{\"suggestions\":{},\"dependencies\":{},\"conflicting\":{},\"providing\":{},\"platforms\":{},\"recipes\":{},\"replacing\":{},\"groupings\":{},\"attributes\":{},\"recommendations\":{}},\"providers\":[],\"cookbook_name\":\"cookbook\",\"resources\":[],\"templates\":[],\"libraries\":[],\"version\":\"1.0.1\",\"recipes\":[],\"root_files\":[],\"json_class\":\"Chef::CookbookVersion\",\"chef_type\":\"cookbook_version\"}");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
|
@ -116,31 +116,9 @@ public class ChefClientLiveTest {
|
||||||
clientConnection.getApi().clientExists(PREFIX);
|
clientConnection.getApi().clientExists(PREFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreateClient")
|
// TODO when uploading files, there are a few headers that are needed or else request signing
|
||||||
public void testCreateNewCookbook() throws Exception {
|
// fails
|
||||||
Payload pom = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml"));
|
// make this a method on ChefClient to avoid exposing these details to the api users
|
||||||
byte[] md5 = adminConnection.utils().encryption().md5(pom.getInput());
|
|
||||||
UploadSite site = adminConnection.getApi().getUploadSiteForChecksums(ImmutableSet.of(md5));
|
|
||||||
|
|
||||||
String md5Hex = adminConnection.utils().encryption().hex(md5);
|
|
||||||
try {
|
|
||||||
assert site.getChecksums().containsKey(md5Hex) : md5Hex + " not in " + site.getChecksums();
|
|
||||||
ChecksumStatus status = site.getChecksums().get(md5Hex);
|
|
||||||
if (status.needsUpload()) {
|
|
||||||
adminConnection.utils().http().put(status.getUrl(), pom,
|
|
||||||
new PutContentOptions(adminConnection.utils().encryption().base64(md5)));
|
|
||||||
}
|
|
||||||
adminConnection.getApi().closeSandbox(site.getSandboxId(), true);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
adminConnection.getApi().closeSandbox(site.getSandboxId(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
CookbookVersion cookbook = new CookbookVersion("test", "0.0.0");
|
|
||||||
cookbook.getRootFiles().add(new Resource("pom.xml", md5Hex, "pom.xml"));
|
|
||||||
adminConnection.getApi().updateCookbook("test", "0.0.0", cookbook);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class PutContentOptions extends BaseHttpRequestOptions {
|
static class PutContentOptions extends BaseHttpRequestOptions {
|
||||||
|
|
||||||
public PutContentOptions(String md5Base64) {
|
public PutContentOptions(String md5Base64) {
|
||||||
|
@ -153,6 +131,45 @@ public class ChefClientLiveTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: clean up this api so that it is simpler
|
||||||
|
public void testCreateNewCookbook() throws Exception {
|
||||||
|
// define the file you want in the cookbook
|
||||||
|
Payload pom = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml"));
|
||||||
|
|
||||||
|
// get an md5 so that you can see if the server already has it or not
|
||||||
|
byte[] md5 = adminConnection.utils().encryption().md5(pom.getInput());
|
||||||
|
String md5Hex = adminConnection.utils().encryption().hex(md5);
|
||||||
|
|
||||||
|
// request an upload site for this file
|
||||||
|
// TODO: this json ball is not named, and is different than SandBox, using UploadSite for now
|
||||||
|
UploadSite site = adminConnection.getApi().getUploadSiteForHexEncodedChecksums(ImmutableSet.of(md5Hex));
|
||||||
|
|
||||||
|
try {
|
||||||
|
assert site.getChecksums().containsKey(md5Hex) : md5Hex + " not in " + site.getChecksums();
|
||||||
|
|
||||||
|
ChecksumStatus status = site.getChecksums().get(md5Hex);
|
||||||
|
if (status.needsUpload()) {
|
||||||
|
// upload the file, adding a few other headers it was signed with
|
||||||
|
// note that we need to convert the md5 to base64
|
||||||
|
adminConnection.utils().http().put(status.getUrl(), pom,
|
||||||
|
new PutContentOptions(adminConnection.utils().encryption().base64(md5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we were able to get here, close the sandbox
|
||||||
|
adminConnection.getApi().closeSandbox(site.getSandboxId(), true);
|
||||||
|
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
adminConnection.getApi().closeSandbox(site.getSandboxId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new cookbook
|
||||||
|
CookbookVersion cookbook = new CookbookVersion("test3", "0.0.0");
|
||||||
|
cookbook.getRootFiles().add(new Resource("pom.xml", md5Hex, "pom.xml"));
|
||||||
|
|
||||||
|
// upload the cookbook to the remote server
|
||||||
|
adminConnection.getApi().updateCookbook("test3", "0.0.0", cookbook);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreateClient")
|
@Test(dependsOnMethods = "testCreateClient")
|
||||||
public void testGenerateKeyForClient() throws Exception {
|
public void testGenerateKeyForClient() throws Exception {
|
||||||
clientKey = validatorConnection.getApi().generateKeyForClient(PREFIX);
|
clientKey = validatorConnection.getApi().generateKeyForClient(PREFIX);
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.chef.binders;
|
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import javax.ws.rs.HttpMethod;
|
|
||||||
|
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.functions.config.ParserModule;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Test(groups = "unit", testName = "chef.BindMD5sToJsonPayloadTest")
|
|
||||||
public class BindMD5sToJsonPayloadTest {
|
|
||||||
|
|
||||||
Injector injector = Guice.createInjector(new ParserModule());
|
|
||||||
EncryptionService encservice = injector.getInstance(EncryptionService.class);
|
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
||||||
public void testMustBeIterable() {
|
|
||||||
BindMD5sToJsonPayload binder = new BindMD5sToJsonPayload(encservice);
|
|
||||||
injector.injectMembers(binder);
|
|
||||||
HttpRequest request = new HttpRequest(HttpMethod.POST, URI
|
|
||||||
.create("http://localhost"));
|
|
||||||
binder.bindToRequest(request, new File("foo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCorrect() {
|
|
||||||
BindMD5sToJsonPayload binder = new BindMD5sToJsonPayload(encservice);
|
|
||||||
injector.injectMembers(binder);
|
|
||||||
HttpRequest request = new HttpRequest(HttpMethod.POST, URI
|
|
||||||
.create("http://localhost"));
|
|
||||||
binder.bindToRequest(request, ImmutableSet.of(encservice.fromHex("abddef"), encservice.fromHex("1234")));
|
|
||||||
assertEquals(request.getPayload().getRawContent(),
|
|
||||||
"{\"checksums\":{\"abddef\":null,\"1234\":null}}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expectedExceptions = { NullPointerException.class,
|
|
||||||
IllegalStateException.class })
|
|
||||||
public void testNullIsBad() {
|
|
||||||
BindMD5sToJsonPayload binder = new BindMD5sToJsonPayload(encservice);
|
|
||||||
injector.injectMembers(binder);
|
|
||||||
HttpRequest request = new HttpRequest(HttpMethod.POST, URI
|
|
||||||
.create("http://localhost"));
|
|
||||||
binder.bindToRequest(request, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue