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 2013/11/05 12:32:21 UTC
git commit: JCLOUDS-274 Implement listCookbookVersionsInEnvironment
in ChefService API
Updated Branches:
refs/heads/master a882f90d6 -> a4097894a
JCLOUDS-274 Implement listCookbookVersionsInEnvironment in ChefService API
Project: http://git-wip-us.apache.org/repos/asf/jclouds-chef/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-chef/commit/a4097894
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-chef/tree/a4097894
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-chef/diff/a4097894
Branch: refs/heads/master
Commit: a4097894a262fec2e0c79e91b9ce35febf81bb01
Parents: a882f90
Author: Noorul Islam K M <no...@noorul.com>
Authored: Fri Oct 4 14:09:05 2013 +0530
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue Nov 5 12:10:58 2013 +0100
----------------------------------------------------------------------
.../main/java/org/jclouds/chef/ChefService.java | 19 +++
.../jclouds/chef/internal/BaseChefService.java | 16 +-
.../ListCookbookVersionsInEnvironment.java | 41 +++++
.../ListCookbookVersionsInEnvironmentImpl.java | 113 ++++++++++++
...okbookVersionsInEnvironmentImplLiveTest.java | 171 +++++++++++++++++++
5 files changed, 359 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-chef/blob/a4097894/core/src/main/java/org/jclouds/chef/ChefService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/chef/ChefService.java b/core/src/main/java/org/jclouds/chef/ChefService.java
index f20df68..8006b88 100644
--- a/core/src/main/java/org/jclouds/chef/ChefService.java
+++ b/core/src/main/java/org/jclouds/chef/ChefService.java
@@ -187,6 +187,25 @@ public interface ChefService {
Iterable<? extends CookbookVersion> listCookbookVersions();
/**
+ * Lists the details of all existing cookbooks in an environment.
+ *
+ * @param environmentName The environment name.
+ * @return The details of all existing cookbooks in an environment.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName);
+
+ /**
+ * Lists the details of all existing cookbooks in an environment
+ * limiting number of versions.
+ *
+ * @param environmentName The environment name.
+ * @param numVersions The number of cookbook versions to include.
+ * Use 'all' to return all cookbook versions.
+ * @return The details of all existing cookbooks in environment.
+ */
+ Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName, String numVersions);
+
+ /**
* Lists the details of all existing environments.
*
* @return The details of all existing environments.
http://git-wip-us.apache.org/repos/asf/jclouds-chef/blob/a4097894/core/src/main/java/org/jclouds/chef/internal/BaseChefService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/chef/internal/BaseChefService.java b/core/src/main/java/org/jclouds/chef/internal/BaseChefService.java
index 4600ffc..a841922 100644
--- a/core/src/main/java/org/jclouds/chef/internal/BaseChefService.java
+++ b/core/src/main/java/org/jclouds/chef/internal/BaseChefService.java
@@ -49,6 +49,7 @@ import org.jclouds.chef.strategy.DeleteAllClientsInList;
import org.jclouds.chef.strategy.DeleteAllNodesInList;
import org.jclouds.chef.strategy.ListClients;
import org.jclouds.chef.strategy.ListCookbookVersions;
+import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment;
import org.jclouds.chef.strategy.ListNodesInEnvironment;
import org.jclouds.chef.strategy.ListEnvironments;
import org.jclouds.chef.strategy.ListNodes;
@@ -88,6 +89,7 @@ public class BaseChefService implements ChefService {
private final BootstrapConfigForGroup bootstrapConfigForGroup;
private final RunListForGroup runListForGroup;
private final ListCookbookVersions listCookbookVersions;
+ private final ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment;
private final ListEnvironments listEnvironments;
private final ListNodesInEnvironment listNodesInEnvironment;
private final Json json;
@@ -104,7 +106,8 @@ public class BaseChefService implements ChefService {
UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode, Supplier<PrivateKey> privateKey,
@Named(CHEF_BOOTSTRAP_DATABAG) String databag, GroupToBootScript groupToBootScript,
BootstrapConfigForGroup bootstrapConfigForGroup, RunListForGroup runListForGroup,
- ListEnvironments listEnvironments, ListNodesInEnvironment listNodesInEnvironment, Json json) {
+ ListEnvironments listEnvironments, ListNodesInEnvironment listNodesInEnvironment,
+ ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment, Json json) {
this.chefContext = checkNotNull(chefContext, "chefContext");
this.api = checkNotNull(api, "api");
this.cleanupStaleNodesAndClients = checkNotNull(cleanupStaleNodesAndClients, "cleanupStaleNodesAndClients");
@@ -124,6 +127,7 @@ public class BaseChefService implements ChefService {
this.runListForGroup = checkNotNull(runListForGroup, "runListForGroup");
this.listEnvironments = checkNotNull(listEnvironments, "listEnvironments");
this.listNodesInEnvironment = checkNotNull(listNodesInEnvironment, "listNodesInEnvironment");
+ this.listCookbookVersionsInEnvironment = checkNotNull(listCookbookVersionsInEnvironment, "listCookbookVersionsInEnvironment");
this.json = checkNotNull(json, "json");
}
@@ -238,6 +242,16 @@ public class BaseChefService implements ChefService {
}
@Override
+ public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName) {
+ return listCookbookVersionsInEnvironment.execute(environmentName);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName, String numVersions) {
+ return listCookbookVersionsInEnvironment.execute(environmentName, numVersions);
+ }
+
+ @Override
public Iterable<? extends Environment> listEnvironments() {
return listEnvironments.execute();
}
http://git-wip-us.apache.org/repos/asf/jclouds-chef/blob/a4097894/core/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java b/core/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java
new file mode 100644
index 0000000..e19918c
--- /dev/null
+++ b/core/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java
@@ -0,0 +1,41 @@
+/*
+ * 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.strategy;
+
+import org.jclouds.chef.domain.CookbookDefinition;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.strategy.internal.ListCookbookVersionsInEnvironmentImpl;
+
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.ImplementedBy;
+
+/**
+ *
+ * @author Noorul Islam K M
+ */
+@ImplementedBy(ListCookbookVersionsInEnvironmentImpl.class)
+public interface ListCookbookVersionsInEnvironment {
+
+ Iterable<? extends CookbookVersion> execute(String environmentName);
+
+ Iterable<? extends CookbookVersion> execute(String environmentName, String numVersions);
+
+ Iterable<? extends CookbookVersion> execute(ListeningExecutorService executor, String environmentName);
+
+ Iterable<? extends CookbookVersion> execute(ListeningExecutorService executor, String environmentName, String numVersions);
+}
http://git-wip-us.apache.org/repos/asf/jclouds-chef/blob/a4097894/core/src/main/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImpl.java b/core/src/main/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImpl.java
new file mode 100644
index 0000000..48d563e
--- /dev/null
+++ b/core/src/main/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImpl.java
@@ -0,0 +1,113 @@
+/*
+ * 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.strategy.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.util.concurrent.Futures.allAsList;
+import static com.google.common.util.concurrent.Futures.getUnchecked;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.chef.ChefApi;
+import org.jclouds.chef.config.ChefProperties;
+import org.jclouds.chef.domain.CookbookDefinition;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.Inject;
+
+/**
+ *
+ * @author Noorul Islam K M
+ */
+@Singleton
+public class ListCookbookVersionsInEnvironmentImpl implements ListCookbookVersionsInEnvironment {
+
+ protected final ChefApi api;
+ protected final ListeningExecutorService userExecutor;
+ @Resource
+ @Named(ChefProperties.CHEF_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ ListCookbookVersionsInEnvironmentImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) {
+ this.userExecutor = checkNotNull(userExecutor, "userExecuor");
+ this.api = checkNotNull(api, "api");
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> execute(String environmentName) {
+ return execute(userExecutor, environmentName);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> execute(String environmentName, String numVersions) {
+ return execute(userExecutor, environmentName, numVersions);
+ }
+
+ public Iterable<? extends CookbookVersion> execute(ListeningExecutorService executor, String environmentName) {
+ return execute(executor, api.listCookbooksInEnvironment(environmentName));
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> execute(ListeningExecutorService executor, String environmentName, String numVersions) {
+ return execute(executor, api.listCookbooksInEnvironment(environmentName, numVersions));
+ }
+
+ private Iterable<? extends CookbookVersion> execute(final ListeningExecutorService executor,
+ Iterable<CookbookDefinition> cookbookDefs) {
+ return concat(transform(cookbookDefs, new Function<CookbookDefinition, Iterable<? extends CookbookVersion>>() {
+
+ @Override
+ public Iterable<? extends CookbookVersion> apply(final CookbookDefinition cookbookDef) {
+ // TODO getting each version could also go parallel
+ Set<CookbookDefinition.Version> cookbookVersions = cookbookDef.getVersions();
+ ListenableFuture<List<CookbookVersion>> futures = allAsList(transform(cookbookVersions,
+ new Function<CookbookDefinition.Version, ListenableFuture<CookbookVersion>>() {
+ @Override
+ public ListenableFuture<CookbookVersion> apply(final CookbookDefinition.Version version) {
+ return executor.submit(new Callable<CookbookVersion>() {
+ @Override
+ public CookbookVersion call() throws Exception {
+ return api.getCookbook(cookbookDef.getName(), version.getVersion());
+ }
+ });
+ }
+ }));
+
+ logger.trace(String.format("getting versions of cookbook %s: ", cookbookDef.getName()));
+ return getUnchecked(futures);
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-chef/blob/a4097894/core/src/test/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImplLiveTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImplLiveTest.java b/core/src/test/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImplLiveTest.java
new file mode 100644
index 0000000..1868256
--- /dev/null
+++ b/core/src/test/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImplLiveTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.strategy.internal;
+
+import static com.google.common.collect.Iterables.size;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import org.jclouds.chef.ChefApi;
+import org.jclouds.chef.domain.ChecksumStatus;
+import org.jclouds.chef.domain.CookbookDefinition;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.domain.Metadata;
+import org.jclouds.chef.domain.Resource;
+import org.jclouds.chef.domain.Sandbox;
+import org.jclouds.chef.domain.UploadSandbox;
+import org.jclouds.chef.internal.BaseChefLiveTest;
+import org.jclouds.io.Payloads;
+import org.jclouds.io.payloads.FilePayload;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.List;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.primitives.Bytes;
+
+/**
+ * Tests behavior of {@code ListCookbookVersionsInEnvironmentImpl} strategies
+ *
+ * @author Noorul Islam K M
+ */
+@Test(groups = "live", testName = "ListCookbookVersionsInEnvironmentImplLiveTest")
+public class ListCookbookVersionsInEnvironmentImplLiveTest extends BaseChefLiveTest<ChefApi> {
+ public static final String PREFIX = "jcloudstest-strategy-" + System.getProperty("user.name");
+
+ private ListCookbookVersionsInEnvironmentImpl strategy;
+ private CreateNodeAndPopulateAutomaticAttributesImpl creator;
+
+ @Override
+ protected void initialize() {
+ super.initialize();
+
+ try {
+ createCookbooksWithMultipleVersions(PREFIX);
+ createCookbooksWithMultipleVersions(PREFIX + 1);
+ } catch (Exception e) {
+ fail("Could not create cookbooks", e);
+ }
+
+ this.strategy = injector.getInstance(ListCookbookVersionsInEnvironmentImpl.class);
+ }
+
+ @AfterClass(groups = { "integration", "live" })
+ @Override
+ protected void tearDown() {
+ api.deleteCookbook(PREFIX, "0.0.0");
+ api.deleteCookbook(PREFIX, "1.0.0");
+ api.deleteCookbook(PREFIX + 1, "0.0.0");
+ api.deleteCookbook(PREFIX + 1, "1.0.0");
+ super.tearDown();
+ }
+
+ @Test
+ public void testExecute() {
+ assertTrue(size(strategy.execute("_default")) > 0, "Expected one or more elements");
+ }
+
+ @Test
+ public void testExecuteWithNumVersions() {
+ assertTrue(size(strategy.execute("_default", "2")) > 0, "Expected one or more elements");
+ }
+
+ @Test
+ public void testExecuteWithNumVersionsAll() {
+ assertTrue(size(strategy.execute("_default", "all")) > 0, "Expected one or more elements");
+ }
+
+ private FilePayload uploadContent(String fileName) throws Exception {
+ // Define the file you want in the cookbook
+ FilePayload content = Payloads.newFilePayload(new File(System.getProperty("user.dir"), fileName));
+ content.getContentMetadata().setContentType("application/x-binary");
+
+ // Get an md5 so that you can see if the server already has it or not
+ Payloads.calculateMD5(content);
+
+ // Note that java collections cannot effectively do equals or hashcodes on
+ // byte arrays, so let's convert to a list of bytes.
+ List<Byte> md5 = Bytes.asList(content.getContentMetadata().getContentMD5());
+
+ // Request an upload site for this file
+ UploadSandbox site = api.createUploadSandboxForChecksums(ImmutableSet.of(md5));
+ assertTrue(site.getChecksums().containsKey(md5), md5 + " not in " + site.getChecksums());
+
+ try {
+ // Upload the file contents, if still not uploaded
+ ChecksumStatus status = site.getChecksums().get(md5);
+ if (status.needsUpload()) {
+ api.uploadContent(status.getUrl(), content);
+ }
+ Sandbox sandbox = api.commitSandbox(site.getSandboxId(), true);
+ assertTrue(sandbox.isCompleted(), "Sandbox should be completed after uploading");
+ } catch (RuntimeException e) {
+ api.commitSandbox(site.getSandboxId(), false);
+ fail("Could not upload content", e);
+ }
+
+ return content;
+ }
+
+ private void createCookbooksWithMultipleVersions(String cookbookName) throws Exception {
+ FilePayload v0content = uploadContent("pom.xml");
+ FilePayload v1content = uploadContent("../README.md");
+
+ // Create the metadata of the cookbook
+ Metadata metadata = Metadata.builder() //
+ .name(cookbookName) //
+ .version("0.0.0") //
+ .description("Jclouds test uploaded cookbook") //
+ .maintainer("jclouds") //
+ .maintainerEmail("someone@jclouds.org") //
+ .license("Apache 2.0") //
+ .build();
+
+ // Create new cookbook version
+ CookbookVersion cookbook = CookbookVersion.builder(cookbookName, "0.0.0") //
+ .metadata(metadata) //
+ .rootFile(Resource.builder().fromPayload(v0content).build()) //
+ .build();
+
+ // upload the cookbook to the remote server
+ api.updateCookbook(cookbookName, "0.0.0", cookbook);
+
+ // Create the metadata of the cookbook
+ metadata = Metadata.builder() //
+ .name(cookbookName) //
+ .version("1.0.0") //
+ .description("Jclouds test uploaded cookbook") //
+ .maintainer("jclouds") //
+ .maintainerEmail("someone@jclouds.org") //
+ .license("Apache 2.0") //
+ .build();
+
+ // Create a new cookbook version
+ cookbook = CookbookVersion.builder(cookbookName, "1.0.0") //
+ .metadata(metadata) //
+ .rootFile(Resource.builder().fromPayload(v1content).build()) //
+ .build();
+
+ // upload the cookbook to the remote server
+ api.updateCookbook(cookbookName, "1.0.0", cookbook);
+ }
+}