blob: 0acd51d3bbca416c44ae0da3d71b991a22522106 [file] [log] [blame]
/*
* 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.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
import java.lang.reflect.Type;
import java.net.URI;
import java.security.PrivateKey;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.chef.config.Validator;
import org.jclouds.crypto.Pems;
import org.jclouds.json.Json;
import org.jclouds.location.Provider;
import org.jclouds.scriptbuilder.domain.Statement;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.TypeLiteral;
/**
*
* Generates a bootstrap script relevant for a particular group
*
* @author Adrian Cole
*/
@Singleton
public class GroupToBootScript implements Function<String, Statement> {
private static final Pattern newLinePattern = Pattern.compile("(\\r\\n)|(\\n)");
@VisibleForTesting
static final Type RUN_LIST_TYPE = new TypeLiteral<Map<String, List<String>>>() {
}.getType();
private final Supplier<URI> endpoint;
private final Json json;
private final Map<String, List<String>> runListForTag;
private final Statement installChefGems;
private final Optional<String> validatorName;
private final Optional<PrivateKey> validatorCredential;
@Inject
public GroupToBootScript(@Provider Supplier<URI> endpoint, Json json, Map<String, List<String>> runListForTag,
@Named("installChefGems") Statement installChefGems, @Validator Optional<String> validatorName,
@Validator Optional<PrivateKey> validatorCredential) {
this.endpoint = checkNotNull(endpoint, "endpoint");
this.json = checkNotNull(json, "json");
this.runListForTag = checkNotNull(runListForTag, "runListForTag");
this.installChefGems = checkNotNull(installChefGems, "installChefGems");
this.validatorName = checkNotNull(validatorName, "validatorName");
this.validatorCredential = checkNotNull(validatorCredential, validatorCredential);
}
public Statement apply(String tag) {
checkNotNull(tag, "tag");
String validatorClientName = validatorName.get();
PrivateKey validatorKey = validatorCredential.get();
List<String> runList = runListForTag.get(tag);
checkState(runList != null, "runList for %s was not found", tag);
checkState(runList.size() > 0, "runList for %s was empty", tag);
String chefConfigDir = "{root}etc{fs}chef";
Statement createChefConfigDir = exec("{md} " + chefConfigDir);
Statement createClientRb = appendFile(chefConfigDir + "{fs}client.rb", ImmutableList.of("require 'rubygems'",
"require 'ohai'", "o = Ohai::System.new", "o.all_plugins", String.format(
"node_name \"%s-\" + o[:ipaddress]", tag), "log_level :info", "log_location STDOUT", String
.format("validation_client_name \"%s\"", validatorClientName), String.format(
"chef_server_url \"%s\"", endpoint.get())));
Statement createValidationPem = appendFile(chefConfigDir + "{fs}validation.pem", Splitter.on(newLinePattern)
.split(Pems.pem(validatorKey)));
String chefBootFile = chefConfigDir + "{fs}first-boot.json";
Statement createFirstBoot = appendFile(chefBootFile, Collections.singleton(json.toJson(ImmutableMap
.<String, List<String>> of("run_list", runList), RUN_LIST_TYPE)));
Statement runChef = exec("chef-client -j " + chefBootFile);
return newStatementList(installChefGems, createChefConfigDir, createClientRb,
createValidationPem, createFirstBoot, runChef);
}
}