mirror of https://github.com/apache/jclouds.git
Issue 191: updated to fix an attribute bug and added RunListBuilder
This commit is contained in:
parent
0b11e7d652
commit
df6d350820
|
@ -20,6 +20,12 @@
|
||||||
package org.jclouds.chef.compute;
|
package org.jclouds.chef.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.any;
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static com.google.common.collect.Iterables.getLast;
|
||||||
|
import static org.jclouds.chef.predicates.CookbookVersionPredicates.containsRecipe;
|
||||||
|
import static org.jclouds.chef.predicates.CookbookVersionPredicates.containsRecipes;
|
||||||
|
import static org.jclouds.compute.options.TemplateOptions.Builder.runScript;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -27,16 +33,17 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Collections;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.chef.ChefContext;
|
import org.jclouds.chef.ChefContext;
|
||||||
import org.jclouds.chef.ChefContextFactory;
|
import org.jclouds.chef.ChefContextFactory;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.util.RunListBuilder;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
import org.jclouds.compute.RunNodesException;
|
import org.jclouds.compute.RunNodesException;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
|
||||||
import org.jclouds.compute.predicates.NodePredicates;
|
import org.jclouds.compute.predicates.NodePredicates;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
@ -48,7 +55,6 @@ import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
@ -101,24 +107,38 @@ public class ChefComputeServiceLiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCanUpdateRunList() throws IOException {
|
public void testCanUpdateRunList() throws IOException {
|
||||||
chefContext.getChefService().updateRunListForTag(Collections.singleton("recipe[apache2]"), tag);
|
String recipe = "apache2";
|
||||||
assertEquals(chefContext.getChefService().getRunListForTag(tag), Collections.singleton("recipe[apache2]"));
|
|
||||||
|
Iterable<? extends CookbookVersion> cookbookVersions = chefContext.getChefService().listCookbookVersions();
|
||||||
|
|
||||||
|
if (any(cookbookVersions, containsRecipe(recipe))) {
|
||||||
|
List<String> runList = new RunListBuilder().addRecipe(recipe).build();
|
||||||
|
chefContext.getChefService().updateRunListForTag(runList, tag);
|
||||||
|
assertEquals(chefContext.getChefService().getRunListForTag(tag), runList);
|
||||||
|
} else {
|
||||||
|
assert false : String.format("recipe %s not in %s", recipe, cookbookVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO move this to a unit test
|
||||||
|
assert any(cookbookVersions, containsRecipe("apache2::mod_proxy"));
|
||||||
|
assert any(cookbookVersions, containsRecipes("apache2", "apache2::mod_proxy", "apache2::mod_proxy_http"));
|
||||||
|
assert !any(cookbookVersions, containsRecipe("apache2::bar"));
|
||||||
|
assert !any(cookbookVersions, containsRecipe("foo::bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCanUpdateRunList")
|
@Test(dependsOnMethods = "testCanUpdateRunList")
|
||||||
public void testRunNodesWithBootstrap() throws IOException {
|
public void testRunNodesWithBootstrap() throws IOException {
|
||||||
|
|
||||||
Payload bootstrap = chefContext.getChefService().createClientAndBootstrapScriptForTag(tag);
|
Payload bootstrap = chefContext.getChefService().createClientAndBootstrapScriptForTag(tag);
|
||||||
TemplateOptions options = computeContext.getComputeService().templateOptions().runScript(bootstrap);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nodes = computeContext.getComputeService().runNodesWithTag(tag, 1, options);
|
nodes = computeContext.getComputeService().runNodesWithTag(tag, 1, runScript(bootstrap));
|
||||||
} catch (RunNodesException e) {
|
} catch (RunNodesException e) {
|
||||||
nodes = Iterables.concat(e.getSuccessfulNodes(), e.getNodeErrors().keySet());
|
nodes = concat(e.getSuccessfulNodes(), e.getNodeErrors().keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NodeMetadata node : nodes) {
|
for (NodeMetadata node : nodes) {
|
||||||
URI uri = URI.create("http://" + Iterables.getLast(node.getPublicAddresses()));
|
URI uri = URI.create("http://" + getLast(node.getPublicAddresses()));
|
||||||
InputStream content = computeContext.utils().http().get(uri);
|
InputStream content = computeContext.utils().http().get(uri);
|
||||||
String string = Utils.toStringAndClose(content);
|
String string = Utils.toStringAndClose(content);
|
||||||
assert string.indexOf("It works!") >= 0 : string;
|
assert string.indexOf("It works!") >= 0 : string;
|
||||||
|
|
|
@ -129,7 +129,37 @@ unit testing"
|
||||||
"Retrieve the existing nodes in your chef server including all details."
|
"Retrieve the existing nodes in your chef server including all details."
|
||||||
([] (nodes *chef*))
|
([] (nodes *chef*))
|
||||||
([#^ChefService chef]
|
([#^ChefService chef]
|
||||||
(seq (.listNodesDetails chef))))
|
(seq (.listNodes chef))))
|
||||||
|
|
||||||
|
(defn clients
|
||||||
|
"Retrieve the names of the existing clients in your chef server."
|
||||||
|
([] (clients *chef*))
|
||||||
|
([#^ChefService chef]
|
||||||
|
(seq (.listClients (as-chef-api chef)))))
|
||||||
|
|
||||||
|
(defn clients-with-details
|
||||||
|
"Retrieve the existing clients in your chef server including all details."
|
||||||
|
([] (clients *chef*))
|
||||||
|
([#^ChefService chef]
|
||||||
|
(seq (.listClients chef))))
|
||||||
|
|
||||||
|
(defn cookbooks
|
||||||
|
"Retrieve the names of the existing cookbooks in your chef server."
|
||||||
|
([] (cookbooks *chef*))
|
||||||
|
([#^ChefService chef]
|
||||||
|
(seq (.listCookbooks (as-chef-api chef)))))
|
||||||
|
|
||||||
|
(defn cookbook-versions
|
||||||
|
"Retrieve the versions of an existing cookbook in your chef server."
|
||||||
|
([name] (cookbook-versions *chef*))
|
||||||
|
([#^ChefService name chef]
|
||||||
|
(seq (.getVersionsOfCookbook (as-chef-api chef) name))))
|
||||||
|
|
||||||
|
(defn cookbook-versions-with-details
|
||||||
|
"Retrieve the existing cookbook versions in your chef server including all details."
|
||||||
|
([] (cookbook-versions *chef*))
|
||||||
|
([#^ChefService chef]
|
||||||
|
(seq (.listCookbookVersions chef))))
|
||||||
|
|
||||||
(defn update-run-list
|
(defn update-run-list
|
||||||
"Updates the run-list associated with a tag"
|
"Updates the run-list associated with a tag"
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jclouds.chef.domain.Client;
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
import org.jclouds.chef.domain.Node;
|
import org.jclouds.chef.domain.Node;
|
||||||
import org.jclouds.chef.internal.BaseChefService;
|
import org.jclouds.chef.internal.BaseChefService;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
|
@ -97,9 +98,9 @@ public interface ChefService {
|
||||||
|
|
||||||
void deleteAllNodesInList(Iterable<String> names);
|
void deleteAllNodesInList(Iterable<String> names);
|
||||||
|
|
||||||
Iterable<? extends Node> listNodesDetails();
|
Iterable<? extends Node> listNodes();
|
||||||
|
|
||||||
Iterable<? extends Node> listNodesDetailsMatching(Predicate<String> nodeNameSelector);
|
Iterable<? extends Node> listNodesMatching(Predicate<String> nodeNameSelector);
|
||||||
|
|
||||||
Iterable<? extends Node> listNodesNamed(Iterable<String> names);
|
Iterable<? extends Node> listNodesNamed(Iterable<String> names);
|
||||||
|
|
||||||
|
@ -111,5 +112,11 @@ public interface ChefService {
|
||||||
|
|
||||||
Iterable<? extends Client> listClientsNamed(Iterable<String> names);
|
Iterable<? extends Client> listClientsNamed(Iterable<String> names);
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> listCookbookVersions();
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> listCookbookVersionsMatching(Predicate<String> cookbookNameSelector);
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> listCookbookVersionsNamed(Iterable<String> cookbookNames);
|
||||||
|
|
||||||
void updateAutomaticAttributesOnNode(String nodeName);
|
void updateAutomaticAttributesOnNode(String nodeName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ package org.jclouds.chef.domain;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.domain.JsonBall;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
@ -37,14 +39,14 @@ public class Attribute {
|
||||||
private boolean calculated;
|
private boolean calculated;
|
||||||
private List<String> choice = Lists.newArrayList();
|
private List<String> choice = Lists.newArrayList();
|
||||||
@SerializedName("default")
|
@SerializedName("default")
|
||||||
private String defaultValue;
|
private JsonBall defaultValue;
|
||||||
private String type;
|
private String type;
|
||||||
private List<String> recipes = Lists.newArrayList();
|
private List<String> recipes = Lists.newArrayList();
|
||||||
@SerializedName("display_name")
|
@SerializedName("display_name")
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
public Attribute(String required, boolean calculated, Set<String> choice, String defaultValue, String type,
|
public Attribute(String required, boolean calculated, Set<String> choice, JsonBall defaultValue, String type,
|
||||||
List<String> recipes, String displayName, String description) {
|
List<String> recipes, String displayName, String description) {
|
||||||
this.required = required;
|
this.required = required;
|
||||||
this.calculated = calculated;
|
this.calculated = calculated;
|
||||||
|
@ -71,7 +73,7 @@ public class Attribute {
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDefaultValue() {
|
public JsonBall getDefaultValue() {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class CookbookVersion {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private Set<Resource> definitions = Sets.newLinkedHashSet();
|
private Set<Resource> definitions = Sets.newLinkedHashSet();
|
||||||
private Set<Resource> attributes = Sets.newLinkedHashSet();
|
private Set<Attribute> attributes = Sets.newLinkedHashSet();
|
||||||
private Set<Resource> files = Sets.newLinkedHashSet();
|
private Set<Resource> files = Sets.newLinkedHashSet();
|
||||||
private Metadata metadata = new Metadata();
|
private Metadata metadata = new Metadata();
|
||||||
private Set<Resource> providers = Sets.newLinkedHashSet();
|
private Set<Resource> providers = Sets.newLinkedHashSet();
|
||||||
|
@ -62,7 +62,7 @@ public class CookbookVersion {
|
||||||
this.name = cookbookName + "-" + version;
|
this.name = cookbookName + "-" + version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CookbookVersion(String name, Set<Resource> definitions, Set<Resource> attributes, Set<Resource> files,
|
public CookbookVersion(String name, Set<Resource> definitions, Set<Attribute> attributes, Set<Resource> files,
|
||||||
Metadata metadata, Set<Resource> providers, String cookbookName, Set<Resource> resources,
|
Metadata metadata, Set<Resource> providers, String cookbookName, Set<Resource> resources,
|
||||||
Set<Resource> templates, Set<Resource> libraries, String version, Set<Resource> recipes,
|
Set<Resource> templates, Set<Resource> libraries, String version, Set<Resource> recipes,
|
||||||
Set<Resource> rootFiles) {
|
Set<Resource> rootFiles) {
|
||||||
|
@ -94,7 +94,7 @@ public class CookbookVersion {
|
||||||
return definitions;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Resource> getAttributes() {
|
public Set<Attribute> getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import javax.inject.Singleton;
|
||||||
import org.jclouds.chef.ChefContext;
|
import org.jclouds.chef.ChefContext;
|
||||||
import org.jclouds.chef.ChefService;
|
import org.jclouds.chef.ChefService;
|
||||||
import org.jclouds.chef.domain.Client;
|
import org.jclouds.chef.domain.Client;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
import org.jclouds.chef.domain.DatabagItem;
|
import org.jclouds.chef.domain.DatabagItem;
|
||||||
import org.jclouds.chef.domain.Node;
|
import org.jclouds.chef.domain.Node;
|
||||||
import org.jclouds.chef.functions.RunListForTag;
|
import org.jclouds.chef.functions.RunListForTag;
|
||||||
|
@ -46,6 +47,7 @@ import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes;
|
||||||
import org.jclouds.chef.strategy.DeleteAllClientsInList;
|
import org.jclouds.chef.strategy.DeleteAllClientsInList;
|
||||||
import org.jclouds.chef.strategy.DeleteAllNodesInList;
|
import org.jclouds.chef.strategy.DeleteAllNodesInList;
|
||||||
import org.jclouds.chef.strategy.ListClients;
|
import org.jclouds.chef.strategy.ListClients;
|
||||||
|
import org.jclouds.chef.strategy.ListCookbookVersions;
|
||||||
import org.jclouds.chef.strategy.ListNodes;
|
import org.jclouds.chef.strategy.ListNodes;
|
||||||
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
|
import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
|
@ -83,14 +85,16 @@ public class BaseChefService implements ChefService {
|
||||||
private final TagToBootScript tagToBootScript;
|
private final TagToBootScript tagToBootScript;
|
||||||
private final String databag;
|
private final String databag;
|
||||||
private final RunListForTag runListForTag;
|
private final RunListForTag runListForTag;
|
||||||
|
private final ListCookbookVersions listCookbookVersions;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseChefService(ChefContext chefContext, CleanupStaleNodesAndClients cleanupStaleNodesAndClients,
|
protected BaseChefService(ChefContext chefContext, CleanupStaleNodesAndClients cleanupStaleNodesAndClients,
|
||||||
CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes,
|
CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes,
|
||||||
DeleteAllNodesInList deleteAllNodesInList, ListNodes listNodes,
|
DeleteAllNodesInList deleteAllNodesInList, ListNodes listNodes,
|
||||||
DeleteAllClientsInList deleteAllClientsInList, ListClients listClients,
|
DeleteAllClientsInList deleteAllClientsInList, ListClients listClients,
|
||||||
UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode, Provider<PrivateKey> privateKey,
|
ListCookbookVersions listCookbookVersions, UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode,
|
||||||
@Named(CHEF_BOOTSTRAP_DATABAG) String databag, TagToBootScript tagToBootScript, RunListForTag runListForTag) {
|
Provider<PrivateKey> privateKey, @Named(CHEF_BOOTSTRAP_DATABAG) String databag,
|
||||||
|
TagToBootScript tagToBootScript, RunListForTag runListForTag) {
|
||||||
this.chefContext = checkNotNull(chefContext, "chefContext");
|
this.chefContext = checkNotNull(chefContext, "chefContext");
|
||||||
this.cleanupStaleNodesAndClients = checkNotNull(cleanupStaleNodesAndClients, "cleanupStaleNodesAndClients");
|
this.cleanupStaleNodesAndClients = checkNotNull(cleanupStaleNodesAndClients, "cleanupStaleNodesAndClients");
|
||||||
this.createNodeAndPopulateAutomaticAttributes = checkNotNull(createNodeAndPopulateAutomaticAttributes,
|
this.createNodeAndPopulateAutomaticAttributes = checkNotNull(createNodeAndPopulateAutomaticAttributes,
|
||||||
|
@ -99,6 +103,7 @@ public class BaseChefService implements ChefService {
|
||||||
this.listNodes = checkNotNull(listNodes, "listNodes");
|
this.listNodes = checkNotNull(listNodes, "listNodes");
|
||||||
this.deleteAllClientsInList = checkNotNull(deleteAllClientsInList, "deleteAllClientsInList");
|
this.deleteAllClientsInList = checkNotNull(deleteAllClientsInList, "deleteAllClientsInList");
|
||||||
this.listClients = checkNotNull(listClients, "listClients");
|
this.listClients = checkNotNull(listClients, "listClients");
|
||||||
|
this.listCookbookVersions = checkNotNull(listCookbookVersions, "listCookbookVersions");
|
||||||
this.updateAutomaticAttributesOnNode = checkNotNull(updateAutomaticAttributesOnNode,
|
this.updateAutomaticAttributesOnNode = checkNotNull(updateAutomaticAttributesOnNode,
|
||||||
"updateAutomaticAttributesOnNode");
|
"updateAutomaticAttributesOnNode");
|
||||||
this.privateKey = checkNotNull(privateKey, "privateKey");
|
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||||
|
@ -123,12 +128,12 @@ public class BaseChefService implements ChefService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends Node> listNodesDetails() {
|
public Iterable<? extends Node> listNodes() {
|
||||||
return listNodes.execute();
|
return listNodes.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends Node> listNodesDetailsMatching(Predicate<String> nodeNameSelector) {
|
public Iterable<? extends Node> listNodesMatching(Predicate<String> nodeNameSelector) {
|
||||||
return listNodes.execute(nodeNameSelector);
|
return listNodes.execute(nodeNameSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +162,22 @@ public class BaseChefService implements ChefService {
|
||||||
return listClients.execute(names);
|
return listClients.execute(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersions() {
|
||||||
|
return listCookbookVersions.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersionsMatching(Predicate<String> cookbookNameSelector) {
|
||||||
|
return listCookbookVersions.execute(cookbookNameSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> listCookbookVersionsNamed(Iterable<String> names) {
|
||||||
|
return listCookbookVersions.execute(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAutomaticAttributesOnNode(String nodeName) {
|
public void updateAutomaticAttributesOnNode(String nodeName) {
|
||||||
updateAutomaticAttributesOnNode.execute(nodeName);
|
updateAutomaticAttributesOnNode.execute(nodeName);
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.chef.predicates;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.any;
|
||||||
|
import static com.google.common.collect.Iterables.get;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.LinkedListMultimap;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for cookbook filters (predicates).
|
||||||
|
*
|
||||||
|
* This class has static methods that create customized predicates to use with
|
||||||
|
* {@link org.jclouds.chef.ChefService}.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class CookbookVersionPredicates {
|
||||||
|
/**
|
||||||
|
* @see #containsRecipes
|
||||||
|
*/
|
||||||
|
public static Predicate<CookbookVersion> containsRecipe(String recipe) {
|
||||||
|
return containsRecipes(checkNotNull(recipe, "recipe must be defined"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that the default recipe of a cookbook is its name. Otherwise, you prefix the recipe with
|
||||||
|
* the name of the cookbook. ex. {@code apache2} will be the default recipe where {@code
|
||||||
|
* apache2::mod_proxy} is a specific one in the cookbook.
|
||||||
|
*
|
||||||
|
* @param recipes
|
||||||
|
* names of the recipes.
|
||||||
|
* @return true if the cookbook version contains a recipe in the list.
|
||||||
|
*/
|
||||||
|
public static Predicate<CookbookVersion> containsRecipes(String... recipes) {
|
||||||
|
checkNotNull(recipes, "recipes must be defined");
|
||||||
|
final Multimap<String, String> search = LinkedListMultimap.create();
|
||||||
|
for (String recipe : recipes) {
|
||||||
|
if (recipe.indexOf("::") != -1) {
|
||||||
|
Iterable<String> nameRecipe = Splitter.on("::").split(recipe);
|
||||||
|
search.put(get(nameRecipe, 0), get(nameRecipe, 1) + ".rb");
|
||||||
|
} else {
|
||||||
|
search.put(recipe, "default.rb");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Predicate<CookbookVersion>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(final CookbookVersion cookbookVersion) {
|
||||||
|
return search.containsKey(cookbookVersion.getCookbookName())
|
||||||
|
&& any(search.get(cookbookVersion.getCookbookName()), new Predicate<String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(final String recipeName) {
|
||||||
|
return any(cookbookVersion.getRecipes(), new Predicate<Resource>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Resource resource) {
|
||||||
|
return resource.getName().equals(recipeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "containsRecipes(" + search + ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.chef.strategy;
|
||||||
|
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.strategy.internal.ListCookbookVersionsImpl;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@ImplementedBy(ListCookbookVersionsImpl.class)
|
||||||
|
public interface ListCookbookVersions {
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute();
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(Predicate<String> cookbookNameSelector);
|
||||||
|
|
||||||
|
Iterable<? extends CookbookVersion> execute(Iterable<String> cookbookNames);
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.chef.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.chef.ChefAsyncClient;
|
||||||
|
import org.jclouds.chef.ChefClient;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
|
import org.jclouds.chef.reference.ChefConstants;
|
||||||
|
import org.jclouds.chef.strategy.ListCookbookVersions;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ListCookbookVersionsImpl implements ListCookbookVersions {
|
||||||
|
|
||||||
|
protected final ChefClient chefClient;
|
||||||
|
protected final ChefAsyncClient chefAsyncClient;
|
||||||
|
protected final ExecutorService userExecutor;
|
||||||
|
@Resource
|
||||||
|
@Named(ChefConstants.CHEF_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject(optional = true)
|
||||||
|
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||||
|
protected Long maxTime;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ListCookbookVersionsImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||||
|
ChefClient getAllCookbookVersion, ChefAsyncClient ablobstore) {
|
||||||
|
this.userExecutor = userExecutor;
|
||||||
|
this.chefAsyncClient = ablobstore;
|
||||||
|
this.chefClient = getAllCookbookVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute() {
|
||||||
|
return execute(chefClient.listCookbooks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(Predicate<String> cookbookNameSelector) {
|
||||||
|
return execute(filter(chefClient.listCookbooks(), cookbookNameSelector));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> execute(Iterable<String> toGet) {
|
||||||
|
return concat(transform(toGet, new Function<String, Iterable<? extends CookbookVersion>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends CookbookVersion> apply(final String cookbook) {
|
||||||
|
// TODO getting each version could also go parallel
|
||||||
|
return transformParallel(chefClient.getVersionsOfCookbook(cookbook),
|
||||||
|
new Function<String, Future<CookbookVersion>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<CookbookVersion> apply(String version) {
|
||||||
|
return chefAsyncClient.getCookbook(cookbook, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, userExecutor, maxTime, logger, "getting versions of cookbook " + cookbook);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.chef.util;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.addAll;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static com.google.common.collect.Lists.transform;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds a run list in the correct syntax for chef.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class RunListBuilder {
|
||||||
|
private List<String> list = newArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following recipe to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRecipe(String recipe) {
|
||||||
|
return addRecipes(checkNotNull(recipe, "recipe"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following recipes to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRecipes(String... recipes) {
|
||||||
|
addAll(list, transform(Arrays.asList(checkNotNull(recipes, "recipes")), new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
return "recipe[" + from + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following role to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRole(String role) {
|
||||||
|
return addRoles(checkNotNull(role, "role"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the following roles to the run list
|
||||||
|
*/
|
||||||
|
public RunListBuilder addRoles(String... roles) {
|
||||||
|
addAll(list, transform(Arrays.asList(checkNotNull(roles, "roles")), new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
return "role[" + from + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> build() {
|
||||||
|
return ImmutableList.copyOf(list);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,12 +20,14 @@
|
||||||
package org.jclouds.chef;
|
package org.jclouds.chef;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.chef.config.ChefParserModule;
|
import org.jclouds.chef.config.ChefParserModule;
|
||||||
|
import org.jclouds.chef.domain.CookbookVersion;
|
||||||
import org.jclouds.json.Json;
|
import org.jclouds.json.Json;
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
@ -106,6 +108,12 @@ public class ChefClientLiveTest extends BaseChefClientLiveTest {
|
||||||
clientConnection = createConnection(PREFIX, clientKey);
|
clientConnection = createConnection(PREFIX, clientKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testListCookbookVersionsWithChefService() throws Exception {
|
||||||
|
Iterable<? extends CookbookVersion> cookbooks = adminConnection.getChefService().listCookbookVersions();
|
||||||
|
assertNotNull(cookbooks);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void closeContexts() {
|
protected void closeContexts() {
|
||||||
if (clientConnection != null)
|
if (clientConnection != null)
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class ParseCookbookVersionFromJsonTest {
|
||||||
new CookbookVersion(
|
new CookbookVersion(
|
||||||
"apache-chef-demo-0.0.0",
|
"apache-chef-demo-0.0.0",
|
||||||
ImmutableSet.<Resource> of(),
|
ImmutableSet.<Resource> of(),
|
||||||
ImmutableSet.<Resource> of(),
|
ImmutableSet.<Attribute> of(),
|
||||||
ImmutableSet.<Resource> of(),
|
ImmutableSet.<Resource> of(),
|
||||||
new Metadata("Apache v2.0", "Your Name", ImmutableMap.<String, String> of(), ImmutableMap
|
new Metadata("Apache v2.0", "Your Name", ImmutableMap.<String, String> of(), ImmutableMap
|
||||||
.<String, Set<String>> of(), "youremail@example.com", ImmutableMap
|
.<String, Set<String>> of(), "youremail@example.com", ImmutableMap
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.chef.util;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests possible uses of RunListBuilder
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class RunListBuilderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRecipeAndRole() {
|
||||||
|
RunListBuilder options = new RunListBuilder();
|
||||||
|
options.addRecipe("recipe").addRole("role");
|
||||||
|
assertEquals(options.build(),ImmutableList.of("recipe[recipe]","role[role]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRecipe() {
|
||||||
|
RunListBuilder options = new RunListBuilder();
|
||||||
|
options.addRecipe("test");
|
||||||
|
assertEquals(options.build(),ImmutableList.of("recipe[test]"));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testRecipes() {
|
||||||
|
RunListBuilder options = new RunListBuilder();
|
||||||
|
options.addRecipes("test", "test2");
|
||||||
|
assertEquals(options.build(),ImmutableList.of("recipe[test]","recipe[test2]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRole() {
|
||||||
|
RunListBuilder options = new RunListBuilder();
|
||||||
|
options.addRole("test");
|
||||||
|
assertEquals(options.build(),ImmutableList.of("role[test]"));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testRoles() {
|
||||||
|
RunListBuilder options = new RunListBuilder();
|
||||||
|
options.addRoles("test", "test2");
|
||||||
|
assertEquals(options.build(),ImmutableList.of("role[test]","role[test2]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoneRecipe() {
|
||||||
|
RunListBuilder options = new RunListBuilder();
|
||||||
|
assertEquals(options.build(), ImmutableList.<String>of());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue