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.BindGenerateKeyForClientToJsonPayload;
|
||||
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.Sandbox;
|
||||
import org.jclouds.chef.domain.UploadSite;
|
||||
|
@ -81,8 +81,8 @@ public interface ChefAsyncClient {
|
|||
@POST
|
||||
@Path("sandboxes")
|
||||
@ResponseParser(ParseUploadSiteFromJson.class)
|
||||
ListenableFuture<UploadSite> getUploadSiteForChecksums(
|
||||
@BinderParam(BindMD5sToJsonPayload.class) Set<byte[]> md5s);
|
||||
ListenableFuture<UploadSite> getUploadSiteForHexEncodedChecksums(
|
||||
@BinderParam(BindHexEncodedMD5sToJsonPayload.class) Set<String> hexEncodedmd5s);
|
||||
|
||||
/**
|
||||
* @see ChefClient#closeSandbox
|
||||
|
|
|
@ -61,7 +61,7 @@ import org.jclouds.rest.AuthorizationException;
|
|||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface ChefClient {
|
||||
UploadSite getUploadSiteForChecksums(Set<byte[]> md5s);
|
||||
UploadSite getUploadSiteForHexEncodedChecksums(Set<String> hexEncodedmd5s);
|
||||
|
||||
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> attributes = Sets.newLinkedHashSet();
|
||||
private Set<Resource> files = Sets.newLinkedHashSet();
|
||||
private Metadata metadata;
|
||||
private Metadata metadata = new Metadata();
|
||||
private Set<Resource> providers = Sets.newLinkedHashSet();
|
||||
@SerializedName("cookbook_name")
|
||||
private String cookbookName;
|
||||
|
|
|
@ -40,7 +40,6 @@ import org.jclouds.chef.functions.ParseKeySetFromJson;
|
|||
import org.jclouds.chef.functions.ParseSandboxFromJson;
|
||||
import org.jclouds.chef.functions.ParseUploadSiteFromJson;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.functions.CloseContentAndReturn;
|
||||
|
@ -90,15 +89,14 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
|
||||
}
|
||||
|
||||
public void testGetUploadSiteForChecksums() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
EncryptionService encservice = injector.getInstance(EncryptionService.class);
|
||||
public void testGetUploadSiteForHexEncodedChecksums() throws SecurityException,
|
||||
NoSuchMethodException, IOException {
|
||||
|
||||
Method method = ChefAsyncClient.class.getMethod("getUploadSiteForChecksums", Set.class);
|
||||
Method method = ChefAsyncClient.class.getMethod("getUploadSiteForHexEncodedChecksums",
|
||||
Set.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
ImmutableSet.of(encservice.fromHex("0189e76ccc476701d6b374e5a1a27347"), encservice
|
||||
.fromHex("0c5ecd7788cf4f6c7de2a57193897a6c"), encservice
|
||||
.fromHex("1dda05ed139664f1f89b9dec482b77c0")));
|
||||
ImmutableSet.of("0189e76ccc476701d6b374e5a1a27347",
|
||||
"0c5ecd7788cf4f6c7de2a57193897a6c", "1dda05ed139664f1f89b9dec482b77c0"));
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/sandboxes HTTP/1.1");
|
||||
assertHeadersEqual(
|
||||
httpRequest,
|
||||
|
@ -153,17 +151,16 @@ public class ChefAsyncClientTest extends RestClientTest<ChefAsyncClient> {
|
|||
Method method = ChefAsyncClient.class.getMethod("updateCookbook", String.class, String.class,
|
||||
CookbookVersion.class);
|
||||
GeneratedHttpRequest<ChefAsyncClient> httpRequest = processor.createRequest(method,
|
||||
"cookbook", "1.0.1", new CookbookVersion());
|
||||
"cookbook", "1.0.1", new CookbookVersion("cookbook", "1.0.1"));
|
||||
|
||||
assertRequestLineEquals(httpRequest,
|
||||
"PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1");
|
||||
assertHeadersEqual(
|
||||
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(
|
||||
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);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
|
|
@ -116,31 +116,9 @@ public class ChefClientLiveTest {
|
|||
clientConnection.getApi().clientExists(PREFIX);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateClient")
|
||||
public void testCreateNewCookbook() throws Exception {
|
||||
Payload pom = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml"));
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
// TODO when uploading files, there are a few headers that are needed or else request signing
|
||||
// fails
|
||||
// make this a method on ChefClient to avoid exposing these details to the api users
|
||||
static class PutContentOptions extends BaseHttpRequestOptions {
|
||||
|
||||
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")
|
||||
public void testGenerateKeyForClient() throws Exception {
|
||||
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