You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2014/07/28 22:02:55 UTC
[04/10] Move jclouds-chef to the main jclouds repo
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java b/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
new file mode 100644
index 0000000..9b1354e
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.config;
+
+import static com.google.common.base.Objects.equal;
+import static org.testng.Assert.assertEquals;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import org.jclouds.chef.config.ChefParserModule.KeepLastRepeatedKeyMapTypeAdapterFactory;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Unit tests for the {@link ChefParserModule} class.
+ */
+@Test(groups = "unit", testName = "ChefParserModuleTest")
+public class ChefParserModuleTest {
+
+ private static class KeyValue {
+ private final String key;
+ private final String value;
+
+ private KeyValue(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(key, value);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ KeyValue that = KeyValue.class.cast(obj);
+ return equal(this.key, that.key) && equal(this.value, that.value);
+ }
+ }
+
+ private Gson map = new GsonBuilder().registerTypeAdapterFactory(new KeepLastRepeatedKeyMapTypeAdapterFactory())
+ .create();
+ private Type mapType = new TypeToken<Map<String, String>>() {
+ private static final long serialVersionUID = 1L;
+ }.getType();
+ private Type mapkeyValueType = new TypeToken<Map<String, KeyValue>>() {
+ private static final long serialVersionUID = 1L;
+ }.getType();
+
+ public void testKeepLastRepeatedKeyMapTypeAdapter() {
+ Map<String, String> noNulls = map.fromJson("{\"value\":\"a test string!\"}", mapType);
+ assertEquals(noNulls, ImmutableMap.of("value", "a test string!"));
+ Map<String, String> withNull = map.fromJson("{\"value\":null}", mapType);
+ assertEquals(withNull, ImmutableMap.of());
+ Map<String, String> withEmpty = map.fromJson("{\"value\":\"\"}", mapType);
+ assertEquals(withEmpty, ImmutableMap.of("value", ""));
+ Map<String, KeyValue> keyValues = map.fromJson(
+ "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\"}}",
+ mapkeyValueType);
+ assertEquals(keyValues,
+ ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo"), "i-bar", new KeyValue("i-bar", "bar")));
+ Map<String, KeyValue> duplicates = map
+ .fromJson(
+ "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\", \"value\":\"foo2\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\",\"value\":\"bar2\"}}",
+ mapkeyValueType);
+ assertEquals(duplicates,
+ ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo2"), "i-bar", new KeyValue("i-bar", "bar2")));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java b/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java
new file mode 100644
index 0000000..bfba190
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.filters;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertEqualsNoOrder;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.security.PrivateKey;
+
+import javax.inject.Provider;
+import javax.ws.rs.HttpMethod;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.domain.Credentials;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.internal.SignatureWire;
+import org.jclouds.logging.config.NullLoggingModule;
+import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
+import org.jclouds.util.Strings2;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.net.HttpHeaders;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+@Test(groups = { "unit" })
+public class SignedHeaderAuthTest {
+
+ public static final String USER_ID = "spec-user";
+ public static final String BODY = "Spec Body";
+ // Base64.encode64(Digest::SHA1.digest("Spec Body")).chomp
+ public static final String HASHED_BODY = "DFteJZPVv6WKdQmMqZUQUumUyRs=";
+ public static final String TIMESTAMP_ISO8601 = "2009-01-01T12:00:00Z";
+
+ public static final String PATH = "/organizations/clownco";
+ // Base64.encode64(Digest::SHA1.digest("/organizations/clownco")).chomp
+
+ public static final String HASHED_CANONICAL_PATH = "YtBWDn1blGGuFIuKksdwXzHU9oE=";
+ public static final String REQUESTING_ACTOR_ID = "c0f8a68c52bffa1020222a56b23cccfa";
+
+ // Content hash is ???TODO
+ public static final String X_OPS_CONTENT_HASH = "DFteJZPVv6WKdQmMqZUQUumUyRs=";
+
+ public static final String[] X_OPS_AUTHORIZATION_LINES = new String[] {
+ "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4",
+ "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc",
+ "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O",
+ "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy",
+ "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0", "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" };
+
+ // We expect Mixlib::Authentication::SignedHeaderAuth//sign to return this
+ // if passed the BODY above.
+ public static final Multimap<String, String> EXPECTED_SIGN_RESULT = ImmutableMultimap.<String, String> builder()
+ .put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH).put("X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0")
+ .put("X-Ops-Authorization-1", X_OPS_AUTHORIZATION_LINES[0])
+ .put("X-Ops-Authorization-2", X_OPS_AUTHORIZATION_LINES[1])
+ .put("X-Ops-Authorization-3", X_OPS_AUTHORIZATION_LINES[2])
+ .put("X-Ops-Authorization-4", X_OPS_AUTHORIZATION_LINES[3])
+ .put("X-Ops-Authorization-5", X_OPS_AUTHORIZATION_LINES[4])
+ .put("X-Ops-Authorization-6", X_OPS_AUTHORIZATION_LINES[5]).put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build();
+
+ // Content hash for empty string
+ public static final String X_OPS_CONTENT_HASH_EMPTY = "2jmj7l5rSw0yVb/vlWAYkK/YBwk=";
+ public static final Multimap<String, String> EXPECTED_SIGN_RESULT_EMPTY = ImmutableMultimap
+ .<String, String> builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH_EMPTY).put("X-Ops-Userid", USER_ID)
+ .put("X-Ops-Sign", "version=1.0")
+ .put("X-Ops-Authorization-1", "N6U75kopDK64cEFqrB6vw+PnubnXr0w5LQeXnIGNGLRP2LvifwIeisk7QxEx")
+ .put("X-Ops-Authorization-2", "mtpQOWAw8HvnWErjzuk9AvUsqVmWpv14ficvkaD79qsPMvbje+aLcIrCGT1P")
+ .put("X-Ops-Authorization-3", "3d2uvf4w7iqwzrIscPnkxLR6o6pymR90gvJXDPzV7Le0jbfD8kmZ8AAK0sGG")
+ .put("X-Ops-Authorization-4", "09F1ftW80bLatJTA66Cw2wBz261r6x/abZhIKFJFDWLzyQGJ8ZNOkUrDDtgI")
+ .put("X-Ops-Authorization-5", "svLVXpOJKZZfKunsElpWjjsyNt3k8vpI1Y4ANO8Eg2bmeCPeEK+YriGm5fbC")
+ .put("X-Ops-Authorization-6", "DzWNPylHJqMeGKVYwGQKpg62QDfe5yXh3wZLiQcXow==")
+ .put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build();
+
+ public static String PUBLIC_KEY;
+ public static String PRIVATE_KEY;
+
+ static {
+ try {
+ PUBLIC_KEY = Strings2.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/pubkey.txt"));
+
+ PRIVATE_KEY = Strings2.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/privkey.txt"));
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ }
+ }
+
+ @Test
+ void canonicalizedPathRemovesMultipleSlashes() {
+ assertEquals(signing_obj.canonicalPath("///"), "/");
+ }
+
+ @Test
+ void canonicalizedPathRemovesTrailingSlash() {
+ assertEquals(signing_obj.canonicalPath("/path/"), "/path");
+ }
+
+ @Test
+ void shouldGenerateTheCorrectStringToSignAndSignature() {
+
+ HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost/" + PATH)
+ .payload(BODY).build();
+
+ String expected_string_to_sign = new StringBuilder().append("Method:POST").append("\n").append("Hashed Path:")
+ .append(HASHED_CANONICAL_PATH).append("\n").append("X-Ops-Content-Hash:").append(HASHED_BODY).append("\n")
+ .append("X-Ops-Timestamp:").append(TIMESTAMP_ISO8601).append("\n").append("X-Ops-UserId:").append(USER_ID)
+ .toString();
+
+ assertEquals(signing_obj.createStringToSign("POST", HASHED_CANONICAL_PATH, HASHED_BODY, TIMESTAMP_ISO8601),
+ expected_string_to_sign);
+ assertEquals(signing_obj.sign(expected_string_to_sign), Joiner.on("").join(X_OPS_AUTHORIZATION_LINES));
+
+ request = signing_obj.filter(request);
+ Multimap<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders());
+ headersWithoutContentLength.removeAll(HttpHeaders.CONTENT_LENGTH);
+ assertEqualsNoOrder(headersWithoutContentLength.values().toArray(), EXPECTED_SIGN_RESULT.values().toArray());
+ }
+
+ @Test
+ void shouldGenerateTheCorrectStringToSignAndSignatureWithNoBody() {
+
+ HttpRequest request = HttpRequest.builder().method(HttpMethod.DELETE).endpoint("http://localhost/" + PATH)
+ .build();
+
+ request = signing_obj.filter(request);
+ Multimap<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders());
+ assertEqualsNoOrder(headersWithoutContentLength.entries().toArray(), EXPECTED_SIGN_RESULT_EMPTY.entries()
+ .toArray());
+ }
+
+ @Test
+ void shouldNotChokeWhenSigningARequestForAResourceWithALongName() {
+ StringBuilder path = new StringBuilder("nodes/");
+ for (int i = 0; i < 100; i++)
+ path.append('A');
+ HttpRequest request = HttpRequest.builder().method(HttpMethod.PUT)
+ .endpoint("http://localhost/" + path.toString()).payload(BODY).build();
+
+ signing_obj.filter(request);
+ }
+
+ @Test
+ void shouldReplacePercentage3FWithQuestionMarkAtUrl() {
+ StringBuilder path = new StringBuilder("nodes/");
+ path.append("test/cookbooks/myCookBook%3Fnum_versions=5");
+ HttpRequest request = HttpRequest.builder().method(HttpMethod.GET)
+ .endpoint("http://localhost/" + path.toString()).payload(BODY).build();
+ request = signing_obj.filter(request);
+ assertTrue(request.getRequestLine().contains("?num_versions=5"));
+ }
+
+ private SignedHeaderAuth signing_obj;
+
+ /**
+ * before class, as we need to ensure that the filter is threadsafe.
+ *
+ * @throws IOException
+ *
+ */
+ @BeforeClass
+ protected void createFilter() throws IOException {
+
+ Injector injector = ContextBuilder.newBuilder(new ChefApiMetadata()).credentials(USER_ID, PRIVATE_KEY)
+ .modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule())).buildInjector();
+
+ HttpUtils utils = injector.getInstance(HttpUtils.class);
+ Crypto crypto = injector.getInstance(Crypto.class);
+
+ Supplier<PrivateKey> privateKey = injector.getInstance(Key.get(new TypeLiteral<Supplier<PrivateKey>>() {
+ }));
+
+ signing_obj = new SignedHeaderAuth(new SignatureWire(),
+ Suppliers.ofInstance(new Credentials(USER_ID, PRIVATE_KEY)), privateKey, new Provider<String>() {
+
+ @Override
+ public String get() {
+ return TIMESTAMP_ISO8601;
+ }
+
+ }, utils, crypto);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java
new file mode 100644
index 0000000..f326482
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApi;
+import org.jclouds.chef.domain.Client;
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.rest.annotations.Api;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "BootstrapConfigForGroupTest")
+public class BootstrapConfigForGroupTest {
+
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void testWhenNoDatabagItem() throws IOException {
+ ChefApi chefApi = createMock(ChefApi.class);
+ Client client = createMock(Client.class);
+
+ BootstrapConfigForGroup fn = new BootstrapConfigForGroup("jclouds", chefApi);
+
+ expect(chefApi.getDatabagItem("jclouds", "foo")).andReturn(null);
+
+ replay(client);
+ replay(chefApi);
+
+ fn.apply("foo");
+
+ verify(client);
+ verify(chefApi);
+ }
+
+ @Test
+ public void testReturnsItem() throws IOException {
+ ChefApi chefApi = createMock(ChefApi.class);
+ Api api = createMock(Api.class);
+
+ BootstrapConfigForGroup fn = new BootstrapConfigForGroup("jclouds", chefApi);
+ DatabagItem config = new DatabagItem("foo",
+ "{\"tomcat6\":{\"ssl_port\":8433},\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}");
+
+ expect(chefApi.getDatabagItem("jclouds", "foo")).andReturn(config);
+
+ replay(api);
+ replay(chefApi);
+
+ assertEquals(fn.apply("foo"), config);
+
+ verify(api);
+ verify(chefApi);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java
new file mode 100644
index 0000000..4be873c
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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 static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.security.PrivateKey;
+
+import org.jclouds.chef.ChefApi;
+import org.jclouds.chef.domain.Client;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+@Test(groups = "unit", testName = "ClientForGroupTest")
+public class ClientForGroupTest {
+
+ public void testWhenNoClientsInList() throws IOException {
+ ChefApi chefApi = createMock(ChefApi.class);
+ Client client = createMock(Client.class);
+ PrivateKey privateKey = createMock(PrivateKey.class);
+
+ ClientForGroup fn = new ClientForGroup(chefApi);
+
+ expect(chefApi.listClients()).andReturn(ImmutableSet.<String> of());
+ expect(chefApi.createClient("foo-client-00")).andReturn(client);
+ expect(client.getPrivateKey()).andReturn(privateKey);
+
+ replay(client);
+ replay(chefApi);
+
+ Client compare = fn.apply("foo");
+ assertEquals(compare.getClientname(), "foo-client-00");
+ assertEquals(compare.getName(), "foo-client-00");
+ assertEquals(compare.getPrivateKey(), privateKey);
+
+ verify(client);
+ verify(chefApi);
+ }
+
+ public void testWhenClientsInListAddsToEnd() throws IOException {
+ ChefApi chefApi = createMock(ChefApi.class);
+ Client client = createMock(Client.class);
+ PrivateKey privateKey = createMock(PrivateKey.class);
+
+ ClientForGroup fn = new ClientForGroup(chefApi);
+
+ expect(chefApi.listClients()).andReturn(
+ ImmutableSet.<String> of("foo-client-00", "foo-client-01", "foo-client-02"));
+ expect(chefApi.createClient("foo-client-03")).andReturn(client);
+ expect(client.getPrivateKey()).andReturn(privateKey);
+
+ replay(client);
+ replay(chefApi);
+
+ Client compare = fn.apply("foo");
+ assertEquals(compare.getClientname(), "foo-client-03");
+ assertEquals(compare.getName(), "foo-client-03");
+ assertEquals(compare.getPrivateKey(), privateKey);
+
+ verify(client);
+ verify(chefApi);
+ }
+
+ public void testWhenClientsInListReplacesMissing() throws IOException {
+ ChefApi chefApi = createMock(ChefApi.class);
+ Client client = createMock(Client.class);
+ PrivateKey privateKey = createMock(PrivateKey.class);
+
+ ClientForGroup fn = new ClientForGroup(chefApi);
+
+ expect(chefApi.listClients()).andReturn(ImmutableSet.<String> of("foo-client-00", "foo-client-02"));
+ expect(chefApi.createClient("foo-client-01")).andReturn(client);
+ expect(client.getPrivateKey()).andReturn(privateKey);
+
+ replay(client);
+ replay(chefApi);
+
+ Client compare = fn.apply("foo");
+ assertEquals(compare.getClientname(), "foo-client-01");
+ assertEquals(compare.getName(), "foo-client-01");
+ assertEquals(compare.getPrivateKey(), privateKey);
+
+ verify(client);
+ verify(chefApi);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java
new file mode 100644
index 0000000..8792025
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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 static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEMS;
+import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEM_SYSTEM;
+import static org.jclouds.chef.config.ChefProperties.CHEF_USE_OMNIBUS;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.security.PrivateKey;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefBootstrapModule;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.config.InstallChef;
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.crypto.PemsTest;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.json.Json;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.jclouds.scriptbuilder.domain.OsFamily;
+import org.jclouds.scriptbuilder.domain.ShellToken;
+import org.jclouds.scriptbuilder.domain.Statement;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Functions;
+import com.google.common.base.Optional;
+import com.google.common.base.Suppliers;
+import com.google.common.cache.CacheLoader;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Resources;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.name.Names;
+
+@Test(groups = "unit", testName = "GroupToBootScriptTest")
+public class GroupToBootScriptTest {
+
+ private Json json;
+ private Statement installChefGems;
+ private Statement installChefOmnibus;
+ private Optional<String> validatorName;
+
+ @BeforeClass
+ public void setup() {
+ Injector injectorGems = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true");
+ bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true");
+ bind(String.class).annotatedWith(Names.named(CHEF_USE_OMNIBUS)).toInstance("false");
+ }
+ }, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule());
+
+ Injector injectorOmnibus = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true");
+ bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true");
+ bind(String.class).annotatedWith(Names.named(CHEF_USE_OMNIBUS)).toInstance("true");
+ }
+ }, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule());
+
+ json = injectorGems.getInstance(Json.class);
+ installChefGems = injectorGems.getInstance(Key.get(Statement.class, InstallChef.class));
+ installChefOmnibus = injectorOmnibus.getInstance(Key.get(Statement.class, InstallChef.class));
+ validatorName = Optional.<String> of("chef-validator");
+ }
+
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void testMustHaveValidatorName() {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of())), installChefGems,
+ Optional.<String> absent(), validatorCredential);
+ fn.apply("foo");
+ }
+
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void testMustHaveValidatorCredential() {
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of())), installChefGems,
+ validatorName, Optional.<PrivateKey> absent());
+ fn.apply("foo");
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Key 'foo' not present in map")
+ public void testMustHaveRunScriptsName() {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of())), installChefGems,
+ validatorName, validatorCredential);
+ fn.apply("foo");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "null value in entry: foo=null")
+ public void testMustHaveRunScriptsValue() {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of("foo", (DatabagItem) null))),
+ installChefGems, validatorName, validatorCredential);
+ fn.apply("foo");
+ }
+
+ public void testOneRecipe() throws IOException {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall(
+ "{\"tomcat6\":{\"ssl_port\":8433},\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))),
+ installChefGems, validatorName, validatorCredential);
+
+ PrivateKey validatorKey = validatorCredential.get();
+ expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes());
+ replay(validatorKey);
+
+ assertEquals(
+ fn.apply("foo").render(OsFamily.UNIX),
+ exitInsteadOfReturn(
+ OsFamily.UNIX,
+ Resources.toString(Resources.getResource("test_install_ruby." + ShellToken.SH.to(OsFamily.UNIX)),
+ Charsets.UTF_8)
+ + Resources.toString(
+ Resources.getResource("test_install_rubygems." + ShellToken.SH.to(OsFamily.UNIX)),
+ Charsets.UTF_8)
+ + "gem install chef --no-rdoc --no-ri\n"
+ + Resources.toString(Resources.getResource("bootstrap.sh"), Charsets.UTF_8)));
+
+ verify(validatorKey);
+ }
+
+ public void testOneRecipeAndEnvironment() throws IOException {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall(
+ "{\"tomcat6\":{\"ssl_port\":8433},\"environment\":\"env\","
+ + "\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))), installChefGems,
+ validatorName, validatorCredential);
+
+ PrivateKey validatorKey = validatorCredential.get();
+ expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes());
+ replay(validatorKey);
+
+ assertEquals(
+ fn.apply("foo").render(OsFamily.UNIX),
+ exitInsteadOfReturn(
+ OsFamily.UNIX,
+ Resources.toString(Resources.getResource("test_install_ruby." + ShellToken.SH.to(OsFamily.UNIX)),
+ Charsets.UTF_8)
+ + Resources.toString(
+ Resources.getResource("test_install_rubygems." + ShellToken.SH.to(OsFamily.UNIX)),
+ Charsets.UTF_8)
+ + "gem install chef --no-rdoc --no-ri\n"
+ + Resources.toString(Resources.getResource("bootstrap-env.sh"), Charsets.UTF_8)));
+
+ verify(validatorKey);
+ }
+
+ public void testOneRecipeOmnibus() throws IOException {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall(
+ "{\"tomcat6\":{\"ssl_port\":8433},\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))),
+ installChefOmnibus, validatorName, validatorCredential);
+
+ PrivateKey validatorKey = validatorCredential.get();
+ expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes());
+ replay(validatorKey);
+
+ assertEquals(
+ fn.apply("foo").render(OsFamily.UNIX),
+ "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 "
+ + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n"
+ + Resources.toString(Resources.getResource("bootstrap.sh"), Charsets.UTF_8));
+
+ verify(validatorKey);
+ }
+
+ public void testOneRecipeAndEnvironmentOmnibus() throws IOException {
+ Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class));
+ GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json,
+ CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall(
+ "{\"tomcat6\":{\"ssl_port\":8433},\"environment\":\"env\","
+ + "\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))), installChefOmnibus,
+ validatorName, validatorCredential);
+
+ PrivateKey validatorKey = validatorCredential.get();
+ expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes());
+ replay(validatorKey);
+
+ assertEquals(
+ fn.apply("foo").render(OsFamily.UNIX),
+ "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 "
+ + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n"
+ + Resources.toString(Resources.getResource("bootstrap-env.sh"), Charsets.UTF_8));
+
+ verify(validatorKey);
+ }
+
+ private static String exitInsteadOfReturn(OsFamily family, String input) {
+ return input.replaceAll(ShellToken.RETURN.to(family), ShellToken.EXIT.to(family));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java
new file mode 100644
index 0000000..e8bebcb
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.Client;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.crypto.Pems;
+import org.jclouds.encryption.internal.JCECrypto;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.io.Payloads;
+import org.jclouds.io.payloads.RSADecryptingPayload;
+import org.jclouds.io.payloads.RSAEncryptingPayload;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.ByteSource;
+import com.google.common.io.ByteStreams;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Tests behavior of {@code ParseClientFromJson}
+ */
+@Test(groups = { "unit" })
+public class ParseClientFromJsonTest {
+
+ private static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGB
AMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n";
+ private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n--
---END CERTIFICATE-----\n";
+ private ParseJson<Client> handler;
+ private Crypto crypto;
+ private PrivateKey privateKey;
+ private X509Certificate certificate;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException, CertificateException, InvalidKeySpecException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Client>>() {
+ }));
+ crypto = injector.getInstance(Crypto.class);
+ certificate = Pems.x509Certificate(ByteSource.wrap(CERTIFICATE.getBytes(Charsets.UTF_8)), null);
+ privateKey = crypto.rsaKeyFactory().generatePrivate(Pems.privateKeySpec(ByteSource.wrap(PRIVATE_KEY.getBytes(Charsets.UTF_8))));
+ }
+
+ public void test() throws IOException, CertificateException, NoSuchAlgorithmException {
+
+ Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest")
+ .name("adriancole-jcloudstest").isValidator(false).privateKey(privateKey).build();
+
+ byte[] encrypted = ByteStreams.toByteArray(new RSAEncryptingPayload(new JCECrypto(), Payloads.newPayload("fooya"), user
+ .getCertificate().getPublicKey()));
+
+ assertEquals(
+ ByteStreams.toByteArray(new RSADecryptingPayload(new JCECrypto(), Payloads.newPayload(encrypted), user.getPrivateKey())),
+ "fooya".getBytes());
+
+ assertEquals(
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseClientFromJsonTest.class.getResourceAsStream("/client.json")).build()), user);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java
new file mode 100644
index 0000000..300c8e0
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 static org.testng.Assert.assertTrue;
+
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseCookbookDefinitionCheckingChefVersion}.
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookDefinitionCheckingChefVersionTest {
+
+ public void testParserFor09() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.9.8");
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ ParseCookbookDefinitionCheckingChefVersion parser = injector
+ .getInstance(ParseCookbookDefinitionCheckingChefVersion.class);
+ assertTrue(parser.parser instanceof ParseKeySetFromJson);
+ }
+
+ public void testParserFor010() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.10.8");
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ ParseCookbookDefinitionCheckingChefVersion parser = injector
+ .getInstance(ParseCookbookDefinitionCheckingChefVersion.class);
+ assertTrue(parser.parser instanceof ParseCookbookDefinitionFromJson);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java
new file mode 100644
index 0000000..736b283
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseCookbookDefinitionFromJson}.
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookDefinitionFromJsonTest {
+
+ private ParseCookbookDefinitionFromJson handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(ParseCookbookDefinitionFromJson.class);
+ }
+
+ public void testParse010Response() {
+ assertEquals(handler.apply(HttpResponse
+ .builder()
+ .statusCode(200)
+ .message("ok")
+ .payload(
+ "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\","
+ + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\","
+ + "\"version\" => \"5.1.0\"},"
+ + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\","
+ + "\"version\" => \"4.2.0\"}" + "]" + "}," + "\"nginx\" => {"
+ + "\"url\" => \"http://localhost:4000/cookbooks/nginx\"," + "\"versions\" => ["
+ + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/1.0.0\"," + "\"version\" => \"1.0.0\"},"
+ + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/0.3.0\"," + "\"version\" => \"0.3.0\"}"
+ + "]" + "}" + "}").build()), ImmutableSet.of("apache2", "nginx"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java
new file mode 100644
index 0000000..b5d8a8b
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java
@@ -0,0 +1,74 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.CookbookDefinition;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookDefinitionFromJsonv10Test {
+
+ private ParseCookbookDefinitionFromJsonv10 handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(ParseCookbookDefinitionFromJsonv10.class);
+ }
+
+ public void testCookbokDefinitionParsing() throws URISyntaxException {
+ CookbookDefinition.Version v510 = CookbookDefinition.Version.builder()
+ .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build();
+ CookbookDefinition.Version v420 = CookbookDefinition.Version.builder()
+ .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build();
+ CookbookDefinition definition = CookbookDefinition.builder()
+ .name("apache2").url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build();
+
+ assertEquals(handler.apply(HttpResponse
+ .builder()
+ .statusCode(200)
+ .message("ok")
+ .payload(
+ "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\","
+ + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\","
+ + "\"version\" => \"5.1.0\"},"
+ + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\","
+ + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), definition);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java
new file mode 100644
index 0000000..04f8e35
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java
@@ -0,0 +1,92 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.CookbookDefinition;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+@Test(groups = {"unit"}, singleThreaded = true)
+public class ParseCookbookDefinitionListFromJsonv10Test {
+
+ private ParseCookbookDefinitionListFromJsonv10 handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(ParseCookbookDefinitionListFromJsonv10.class);
+ }
+
+ public void testCookbokDefinitionListParsing() throws URISyntaxException {
+ CookbookDefinition.Version v510 = CookbookDefinition.Version.builder()
+ .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build();
+ CookbookDefinition.Version v420 = CookbookDefinition.Version.builder()
+ .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build();
+ CookbookDefinition apache2 = CookbookDefinition.builder()
+ .name("apache2").url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build();
+
+ CookbookDefinition.Version v100 = CookbookDefinition.Version.builder()
+ .url(new URI("http://localhost:4000/cookbooks/nginx/1.0.0")).version("1.0.0").build();
+ CookbookDefinition.Version v030 = CookbookDefinition.Version.builder()
+ .url(new URI("http://localhost:4000/cookbooks/nginx/0.3.0")).version("0.3.0").build();
+ CookbookDefinition nginx = CookbookDefinition.builder()
+ .name("nginx").url(new URI("http://localhost:4000/cookbooks/nginx")).version(v100).version(v030).build();
+
+ assertEquals(handler.apply(HttpResponse
+ .builder()
+ .statusCode(200)
+ .message("ok")
+ .payload(
+ "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\","
+ + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\","
+ + "\"version\" => \"5.1.0\"},"
+ + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\","
+ + "\"version\" => \"4.2.0\"}" + "]" + "},"
+ + "\"nginx\" => {"
+ + "\"url\" => \"http://localhost:4000/cookbooks/nginx\","
+ + "\"versions\" => ["
+ + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/1.0.0\","
+ + "\"version\" => \"1.0.0\"},"
+ + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/0.3.0\","
+ + "\"version\" => \"0.3.0\"}"
+ + "]}" +
+ "}").build()),
+ ImmutableSet.of(apache2, nginx));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java
new file mode 100644
index 0000000..7bc19bf
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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 static com.google.common.io.BaseEncoding.base16;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.domain.Metadata;
+import org.jclouds.chef.domain.Resource;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Tests behavior of {@code ParseCookbookVersionFromJson}
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookVersionFromJsonTest {
+
+ private ParseJson<CookbookVersion> handler;
+ private Injector injector;
+ private Json json;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ json = injector.getInstance(Json.class);
+ handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<CookbookVersion>>() {
+ }));
+ }
+
+ public void testBrew() throws IOException {
+ CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/brew-cookbook.json")).build());
+
+ assertEquals(cookbook,
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build()));
+ }
+
+ public void testTomcat() {
+ CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/tomcat-cookbook.json")).build());
+
+ assertEquals(cookbook,
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build()));
+ }
+
+ public void testMysql() throws IOException {
+ CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/mysql-cookbook.json")).build());
+
+ assertEquals(cookbook,
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build()));
+ }
+
+ public void testApache() {
+ CookbookVersion fromJson = handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/apache-chef-demo-cookbook.json"))
+ .build());
+
+ CookbookVersion expected = CookbookVersion
+ .builder("apache-chef-demo", "0.0.0")
+ .metadata(Metadata.builder() //
+ .license("Apache v2.0") //
+ .maintainer("Your Name") //
+ .maintainerEmail("youremail@example.com") //
+ .description("A fabulous new cookbook") //
+ .version("0.0.0").name("apache-chef-demo") //
+ .longDescription("") //
+ .build())
+ .rootFile(
+ Resource
+ .builder()
+ .name("README")
+ .path("README")
+ .checksum(base16().lowerCase().decode("11637f98942eafbf49c71b7f2f048b78"))
+ .url(URI
+ .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D")) //
+ .build())
+ .rootFile(
+ Resource
+ .builder()
+ .name("Rakefile")
+ .path("Rakefile")
+ .checksum(base16().lowerCase().decode("ebcf925a1651b4e04b9cd8aac2bc54eb"))
+ .url(URI
+ .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D"))
+ .build()) //
+ .build();
+
+ assertEquals(fromJson, expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java
new file mode 100644
index 0000000..bad0edf
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 static org.testng.Assert.assertTrue;
+
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseCookbookVersionsCheckingChefVersion}.
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookVersionsCheckingChefVersionTest {
+
+ public void testParserFor09() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.9.8");
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ ParseCookbookVersionsCheckingChefVersion parser = injector
+ .getInstance(ParseCookbookVersionsCheckingChefVersion.class);
+ assertTrue(parser.parser instanceof ParseCookbookVersionsV09FromJson);
+ }
+
+ public void testParserFor010() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.10.8");
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ ParseCookbookVersionsCheckingChefVersion parser = injector
+ .getInstance(ParseCookbookVersionsCheckingChefVersion.class);
+ assertTrue(parser.parser instanceof ParseCookbookVersionsV10FromJson);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java
new file mode 100644
index 0000000..08cf1d2
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseCookbookVersionsV09FromJson}
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookVersionsV09FromJsonTest {
+
+ private ParseCookbookVersionsV09FromJson handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(ParseCookbookVersionsV09FromJson.class);
+ }
+
+ public void testRegex() {
+ assertEquals(
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload("{\"apache2\": [\"0.1.8\", \"0.2\"]}").build()), ImmutableSet.of("0.1.8", "0.2"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java
new file mode 100644
index 0000000..e8b396a
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseCookbookVersionsV10FromJson}
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseCookbookVersionsV10FromJsonTest {
+
+ private ParseCookbookVersionsV10FromJson handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(ParseCookbookVersionsV10FromJson.class);
+ }
+
+ public void testRegex() {
+ assertEquals(handler.apply(HttpResponse
+ .builder()
+ .statusCode(200)
+ .message("ok")
+ .payload(
+ "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\","
+ + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\","
+ + "\"version\" => \"5.1.0\"},"
+ + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\","
+ + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), ImmutableSet.of("5.1.0", "4.2.0"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java
new file mode 100644
index 0000000..5dde523
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+
+@Test(groups = { "unit" })
+public class ParseDataBagItemFromJsonTest {
+ private ParseJson<DatabagItem> handler;
+ private Json mapper;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<DatabagItem>>() {
+ }));
+ mapper = injector.getInstance(Json.class);
+ }
+
+ public void test1() {
+ String json = "{\"my_key\":\"my_data\",\"id\":\"item1\"}";
+ DatabagItem item = new DatabagItem("item1", json);
+ assertEquals(handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json).build()), item);
+ assertEquals(mapper.toJson(item), json);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java
new file mode 100644
index 0000000..940e858
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.UnknownHostException;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ReturnStringIf2xx;
+import org.jclouds.util.Strings2;
+import org.testng.annotations.Test;
+
+@Test(groups = { "unit" })
+public class ParseErrorFromJsonOrReturnBodyTest {
+
+ @Test
+ public void testApplyInputStreamDetails() throws UnknownHostException {
+ InputStream is = Strings2
+ .toInputStream("{\"error\":[\"invalid tarball: tarball root must contain java-bytearray\"]}");
+
+ ParseErrorFromJsonOrReturnBody parser = new ParseErrorFromJsonOrReturnBody(new ReturnStringIf2xx());
+ String response = parser.apply(HttpResponse.builder().statusCode(200).message("ok").payload(is).build());
+ assertEquals(response, "invalid tarball: tarball root must contain java-bytearray");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java
new file mode 100644
index 0000000..8c646b2
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseKeySetFromJson}
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseKeySetFromJsonTest {
+
+ private ParseKeySetFromJson handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(ParseKeySetFromJson.class);
+ }
+
+ public void testRegex() {
+ assertEquals(
+ handler.apply(HttpResponse
+ .builder()
+ .statusCode(200)
+ .message("ok")
+ .payload(
+ "{\n\"opscode-validator\": \"https://api.opscode.com/...\", \"pimp-validator\": \"https://api.opscode.com/...\"}")
+ .build()), ImmutableSet.of("opscode-validator", "pimp-validator"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java
new file mode 100644
index 0000000..72b4956
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.Node;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Tests behavior of {@code ParseNodeFromJson}
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseNodeFromJsonTest {
+
+ private ParseJson<Node> handler;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Node>>() {
+ }));
+ }
+
+ public void test() {
+ Node node = Node.builder() //
+ .name("adrian-jcloudstest") //
+ .normalAttribute("tomcat6", new JsonBall("{\"ssl_port\":8433}")) //
+ .runListElement("recipe[java]") //
+ .environment("prod") //
+ .build();
+
+ assertEquals(
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/node.json")).build()), node);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java
new file mode 100644
index 0000000..dd31d38
--- /dev/null
+++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.chef.ChefApiMetadata;
+import org.jclouds.chef.config.ChefParserModule;
+import org.jclouds.chef.domain.Sandbox;
+import org.jclouds.date.DateService;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Tests behavior of {@code ParseSandboxFromJson}
+ */
+@Test(groups = { "unit" }, singleThreaded = true)
+public class ParseSandboxFromJsonTest {
+
+ private ParseJson<Sandbox> handler;
+ private DateService dateService;
+
+ @BeforeTest
+ protected void setUpInjector() throws IOException {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION);
+ }
+ }, new ChefParserModule(), new GsonModule());
+
+ handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Sandbox>>() {
+ }));
+ dateService = injector.getInstance(DateService.class);
+ }
+
+ public void test() {
+ assertEquals(
+ handler.apply(HttpResponse.builder().statusCode(200).message("ok")
+ .payload(ParseSandboxFromJsonTest.class.getResourceAsStream("/sandbox.json")).build()),
+ Sandbox.builder().rev("1-8c27b0ea4c2b7aaedbb44cfbdfcc11b2").isCompleted(false)
+ .createTime(dateService.iso8601SecondsDateParse("2010-07-07T03:36:00+00:00"))
+ .name("f9d6d9b72bae465890aae87969f98a9c").guid("f9d6d9b72bae465890aae87969f98a9c").build());
+ }
+}