Enable properties to configure Chef gems

Added context properties to allow users customize how RubyGems is
installed and also the version of the Chef gems that is installed when
bootstrapping nodes.
This commit is contained in:
Ignasi Barrera 2013-03-06 18:18:15 +01:00
parent efd8c4a1f8
commit 167f4f7204
5 changed files with 162 additions and 13 deletions

View File

@ -23,12 +23,15 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG;
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.reflect.Reflection2.typeToken;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.chef.config.ChefBootstrapModule;
import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.chef.config.ChefRestClientModule;
import org.jclouds.ohai.config.JMXOhaiModule;
@ -70,6 +73,8 @@ public class ChefApiMetadata extends BaseRestApiMetadata {
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createEnvironment", MINUTES.toMillis(2) + "");
properties.setProperty(PROPERTY_SESSION_INTERVAL, "1");
properties.setProperty(CHEF_BOOTSTRAP_DATABAG, "bootstrap");
properties.setProperty(CHEF_UPDATE_GEM_SYSTEM, "false");
properties.setProperty(CHEF_UPDATE_GEMS, "false");
return properties;
}
@ -91,7 +96,7 @@ public class ChefApiMetadata extends BaseRestApiMetadata {
.context(typeToken(ChefContext.class))
.defaultModules(
ImmutableSet.<Class<? extends Module>> of(ChefRestClientModule.class, ChefParserModule.class,
JMXOhaiModule.class));
ChefBootstrapModule.class, JMXOhaiModule.class));
}
@Override

View File

@ -0,0 +1,101 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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 org.jclouds.chef.config.ChefProperties.CHEF_GEM_SYSTEM_VERSION;
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_VERSION;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.scriptbuilder.statements.chef.InstallChefGems;
import org.jclouds.scriptbuilder.statements.ruby.InstallRuby;
import org.jclouds.scriptbuilder.statements.ruby.InstallRubyGems;
import com.google.common.base.Optional;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
/**
* Provides bootstrap configuration for nodes.
*
* @author Ignasi Barrera
*/
public class ChefBootstrapModule extends AbstractModule {
@Provides
@Named("installChefGems")
@Singleton
Statement installChef(BootstrapProperties bootstrapProperties) {
InstallRubyGems installRubyGems = InstallRubyGems.builder()
.version(bootstrapProperties.gemSystemVersion().orNull())
.updateSystem(bootstrapProperties.updateGemSystem(), bootstrapProperties.gemSystemVersion().orNull())
.updateExistingGems(bootstrapProperties.updateGems()) //
.build();
Statement installChef = InstallChefGems.builder().version(bootstrapProperties.chefVersion().orNull()).build();
return new StatementList(new InstallRuby(), installRubyGems, installChef);
}
@Singleton
private static class BootstrapProperties {
@Named(CHEF_VERSION)
@Inject(optional = true)
private String chefVersionProperty;
@Named(CHEF_GEM_SYSTEM_VERSION)
@Inject(optional = true)
private String gemSystemVersionProperty;
@Named(CHEF_UPDATE_GEM_SYSTEM)
@Inject
private String updateGemSystemProeprty;
@Named(CHEF_UPDATE_GEMS)
@Inject
private String updateGemsProperty;
public Optional<String> chefVersion() {
return Optional.fromNullable(chefVersionProperty);
}
public Optional<String> gemSystemVersion() {
return Optional.fromNullable(gemSystemVersionProperty);
}
public boolean updateGemSystem() {
return Boolean.parseBoolean(updateGemSystemProeprty);
}
public boolean updateGems() {
return Boolean.parseBoolean(updateGemsProperty);
}
}
@Override
protected void configure() {
}
}

View File

@ -63,4 +63,47 @@ public interface ChefProperties {
*/
public static final String CHEF_VALIDATOR_CREDENTIAL = "chef.validator-credential";
/**
* The version of the Chef gem to install when bootstrapping nodes.
* <p>
* If this property is not set, by default the latest available Chef gem will
* be installed. The values can be fixed versions such as '0.10.8' or
* constrained values such as '>= 0.10.8'.
* <p>
* This property must be set prior to running the
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
*/
public static final String CHEF_VERSION = "chef.version";
/**
* Boolean property. Default (false).
* <p>
* When bootstrapping a node, forces a gem system update before installing
* the Chef gems.
* <p>
* This property must be set prior to running the
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
*/
public static final String CHEF_UPDATE_GEM_SYSTEM = "chef.update-gem-system";
/**
* To be used in conjunction with {@link #CHEF_UPDATE_GEM_SYSTEM}. This
* property will force the version of RubyGems to update the system to.
* <p>
* This property must be set prior to running the
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
*/
public static final String CHEF_GEM_SYSTEM_VERSION = "chef.gem-system-version";
/**
* Boolean property. Default (false).
* <p>
* When bootstrapping a node, updates teh existing gems before installing
* Chef.
* <p>
* This property must be set prior to running the
* {@link ChefService#createBootstrapScriptForGroup(String)} method.
*/
public static final String CHEF_UPDATE_GEMS = "chef.update-gems";
}

View File

@ -32,12 +32,9 @@ import org.jclouds.chef.functions.ClientForGroup;
import org.jclouds.chef.functions.RunListForGroup;
import org.jclouds.domain.JsonBall;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.statements.chef.InstallChefGems;
import com.google.common.cache.CacheLoader;
import com.google.inject.Provides;
import com.google.inject.name.Names;
/**
* Configures the Chef connection.
@ -69,10 +66,4 @@ public class ChefRestClientModule extends BaseChefRestClientModule<ChefApi, Chef
return CacheLoader.from(clientForGroup);
}
@Override
protected void configure() {
bind(Statement.class).annotatedWith(Names.named("installChefGems")).to(InstallChefGems.class);
super.configure();
}
}

View File

@ -22,6 +22,8 @@ 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.testng.Assert.assertEquals;
import java.io.IOException;
@ -29,6 +31,7 @@ import java.net.URI;
import java.security.PrivateKey;
import org.jclouds.chef.ChefAsyncApi;
import org.jclouds.chef.config.ChefBootstrapModule;
import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.chef.domain.DatabagItem;
import org.jclouds.crypto.PemsTest;
@ -39,7 +42,6 @@ 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.jclouds.scriptbuilder.statements.chef.InstallChefGems;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
@ -52,6 +54,8 @@ 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;
/**
* @author Adrian Cole
@ -63,11 +67,13 @@ public class GroupToBootScriptTest {
@Override
protected void configure() {
bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefAsyncApi.VERSION);
bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true");
bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true");
}
}, new ChefParserModule(), new GsonModule());
}, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule());
Json json = injector.getInstance(Json.class);
Statement installChefGems = new InstallChefGems();
Statement installChefGems = injector.getInstance(Key.get(Statement.class, Names.named("installChefGems")));
Optional<String> validatorName = Optional.<String> of("chef-validator");
Optional<PrivateKey> validatorCredential = Optional.<PrivateKey> of(createMock(PrivateKey.class));
@ -117,6 +123,9 @@ public class GroupToBootScriptTest {
fn.apply("foo").render(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));