diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/chef/ChefSolo.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/chef/ChefSolo.java index c39df68598..9da2eeb55d 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/chef/ChefSolo.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/chef/ChefSolo.java @@ -20,6 +20,8 @@ package org.jclouds.scriptbuilder.statements.chef; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; +import static org.jclouds.scriptbuilder.domain.Statements.createOrOverwriteFile; +import static org.jclouds.scriptbuilder.domain.Statements.exec; import java.util.List; @@ -30,6 +32,7 @@ import org.jclouds.scriptbuilder.domain.Statements; import com.google.common.base.Function; import com.google.common.base.Joiner; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; @@ -46,6 +49,7 @@ public class ChefSolo implements Statement { public static class Builder { private String cookbooksArchiveLocation; + private String jsonAttributes; private List recipes = Lists.newArrayList(); public Builder cookbooksArchiveLocation(String cookbooksArchiveLocation) { @@ -53,6 +57,11 @@ public class ChefSolo implements Statement { return this; } + public Builder jsonAttributes(String jsonAttributes) { + this.jsonAttributes = checkNotNull(jsonAttributes, "jsonAttributes"); + return this; + } + public Builder installRecipe(String recipe) { this.recipes.add(checkNotNull(recipe, "recipe")); return this; @@ -64,18 +73,20 @@ public class ChefSolo implements Statement { } public ChefSolo build() { - return new ChefSolo(cookbooksArchiveLocation, recipes); + return new ChefSolo(cookbooksArchiveLocation, recipes, Optional.fromNullable(jsonAttributes)); } } private String cookbooksArchiveLocation; + private Optional jsonAttributes; private List recipes; private final InstallChefGems installChefGems = new InstallChefGems(); - public ChefSolo(String cookbooksArchiveLocation, List recipes) { + public ChefSolo(String cookbooksArchiveLocation, List recipes, Optional jsonAttributes) { this.cookbooksArchiveLocation = checkNotNull(cookbooksArchiveLocation, "cookbooksArchiveLocation must be set"); - this.recipes = checkNotNull(recipes, "recipes must be set"); + this.recipes = ImmutableList.copyOf(checkNotNull(recipes, "recipes must be set")); + this.jsonAttributes = checkNotNull(jsonAttributes, "jsonAttributes must be set"); } @Override @@ -84,17 +95,25 @@ public class ChefSolo implements Statement { throw new UnsupportedOperationException("windows not yet implemented"); } + ImmutableList.Builder statements = ImmutableList.builder(); + statements.add(installChefGems); + ImmutableMap.Builder chefSoloOptions = ImmutableMap.builder(); chefSoloOptions.put("-N", "`hostname`"); chefSoloOptions.put("-r", cookbooksArchiveLocation); + + if (jsonAttributes.isPresent()) { + statements.add(exec("{md} /var/chef")); + statements.add(createOrOverwriteFile("/var/chef/node.json", jsonAttributes.asSet())); + chefSoloOptions.put("-j", "/var/chef/node.json"); + } + if (!recipes.isEmpty()) { chefSoloOptions.put("-o", recipesToRunlistString(recipes)); } String options = Joiner.on(' ').withKeyValueSeparator(" ").join(chefSoloOptions.build()); - ImmutableList.Builder statements = ImmutableList.builder(); - statements.add(installChefGems); statements.add(Statements.exec(String.format("chef-solo %s", options))); return new StatementList(statements.build()).render(family); diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/chef/ChefSoloTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/chef/ChefSoloTest.java index 7bdf74d436..9e9f975028 100644 --- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/chef/ChefSoloTest.java +++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/chef/ChefSoloTest.java @@ -27,7 +27,9 @@ import org.jclouds.scriptbuilder.domain.ShellToken; import org.testng.annotations.Test; import com.google.common.base.Charsets; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import com.google.common.io.Resources; @Test(groups = "unit", testName = "ChefSoloTest") @@ -40,7 +42,12 @@ public class ChefSoloTest { @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "recipes must be set") public void testChefSoloWithoutRecipes() { - new ChefSolo("/tmp/foo", null); + new ChefSolo("/tmp/foo", null, Optional. absent()); + } + + @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "jsonAttributes must be set") + public void testChefSoloWithoutAttributes() { + new ChefSolo("/tmp/foo", Lists. newArrayList(), null); } @Test(expectedExceptions = UnsupportedOperationException.class, expectedExceptionsMessageRegExp = "windows not yet implemented") @@ -86,4 +93,17 @@ public class ChefSoloTest { + "installChefGems || return 1\nchef-solo -N `hostname` -r /tmp/cookbooks -o recipe[apache2],recipe[mysql]\n"); } + public void testChefSoloWithCookbooksLocationAndAttributes() throws IOException { + String script = ChefSolo.builder().cookbooksArchiveLocation("/tmp/cookbooks").jsonAttributes("{\"foo\":\"bar\"}") + .installRecipe("apache2").build().render(OsFamily.UNIX); + assertEquals( + script, + Resources.toString(Resources.getResource("test_install_ruby." + ShellToken.SH.to(OsFamily.UNIX)), + Charsets.UTF_8) + + "installChefGems || return 1\n" + + "mkdir -p /var/chef\n" + + "cat > /var/chef/node.json <<-'END_OF_JCLOUDS_FILE'\n\t{\"foo\":\"bar\"}\nEND_OF_JCLOUDS_FILE\n" + + "chef-solo -N `hostname` -r /tmp/cookbooks -j /var/chef/node.json -o recipe[apache2]\n"); + } + }