Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.

Commit dcad614

Browse files
author
Andrei Savu
committed
WHIRR-347. Support provider-independent environment variables for cloud credentials (asavu)
git-svn-id: https://svn.apache.org/repos/asf/whirr/trunk@1243842 13f79535-47bb-0310-9956-ffa450edef68
1 parent e5c8960 commit dcad614

27 files changed

+349
-318
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ target
88
**/*.log
99
services/voldemort/lib/
1010
whirr.log
11+
conf/credentials

CHANGES.txt

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ Trunk (unreleased changes)
5353
WHIRR-422. Integration tests should fail or succeed in a limited
5454
amount of time (asavu)
5555

56+
WHIRR-347. Support provider-independent environment variables for
57+
cloud credentials (asavu)
58+
5659
BUG FIXES
5760

5861
WHIRR-367. Wrong groupId for zookeeper (Joe Crobak via asavu)

bin/whirr

+20
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ case "`uname`" in
2424
CYGWIN*) cygwin=true;
2525
esac
2626

27+
if [ -e ~/.whirr/credentials ]; then
28+
. ~/.whirr/credentials
29+
elif [ -e $BIN/../conf/credentials ]; then
30+
. $BIN/../conf/credentials
31+
fi
32+
33+
# Override cloud provider credentials as needed
34+
export WHIRR_PROVIDER=${WHIRR_PROVIDER:-$PROVIDER}
35+
export WHIRR_IDENTITY=${WHIRR_IDENTITY:-$IDENTITY}
36+
export WHIRR_CREDENTIAL=${WHIRR_CREDENTIAL:-$CREDENTIAL}
37+
38+
# Override blob store credentials as needed
39+
export WHIRR_BLOBSTORE_PROVIDER=${WHIRR_BLOBSTORE_PROVIDER:-$BLOBSTORE_PROVIDER}
40+
export WHIRR_BLOBSTORE_IDENTITY=${WHIRR_BLOBSTORE_IDENTITY:-$BLOBSTORE_IDENTITY}
41+
export WHIRR_BLOBSTORE_CREDENTIAL=${WHIRR_BLOBSTORE_CREDENTIAL:-$BLOBSTORE_CREDENTIAL}
42+
43+
# Build the classpath
2744
if [ -d "$BIN/../cli/target/lib" ]; then
2845
CLASSPATH="$BIN/../conf/:$BIN/..:$BIN/../cli/target/lib/*:$BIN/../cli/target/*"
2946
else
@@ -36,5 +53,8 @@ if $cygwin; then
3653
CLASSPATH=`cygpath -wp $CLASSPATH`;
3754
fi
3855

56+
echo Starting cluster on "$WHIRR_PROVIDER" using identity "$WHIRR_IDENTITY"
57+
58+
# Start the application
3959
java $LOGGING_OPTS $WHIRR_CLI_OPTS -cp "$CLASSPATH" org.apache.whirr.cli.Main "$@"
4060

cli/src/main/java/org/apache/whirr/cli/command/CleanupClusterCommand.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public CleanupClusterCommand(ClusterControllerFactory factory,
5252
public int run(InputStream in, PrintStream out, PrintStream err,
5353
List<String> args) throws Exception {
5454

55-
OptionSet optionSet = parser.parse(args.toArray(new String[0]));
55+
OptionSet optionSet = parser.parse(args.toArray(new String[args.size()]));
5656
if (!optionSet.nonOptionArguments().isEmpty()) {
5757
printUsage(err);
5858
return -1;

cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public DestroyClusterCommand(ClusterControllerFactory factory) {
4646
public int run(InputStream in, PrintStream out, PrintStream err,
4747
List<String> args) throws Exception {
4848

49-
OptionSet optionSet = parser.parse(args.toArray(new String[0]));
49+
OptionSet optionSet = parser.parse(args.toArray(new String[args.size()]));
5050

5151
if (!optionSet.nonOptionArguments().isEmpty()) {
5252
printUsage(err);

conf/credentials.sample

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# In this file users can store their cloud login credentials for convenience
17+
# If this file exists it is sourced by Whirr scripts.
18+
#
19+
# Whirr will look for this file in the home directory first (~/.whirr/credentials)
20+
# If not found it will look for it in the conf directory.
21+
#
22+
# Preset environment variables will take precedence over these files.
23+
#
24+
# VARIABLES:
25+
#
26+
# PROVIDER - The cloud provider to use in Whirr
27+
# IDENTITY - The identity to use in Whirr
28+
# CREDENTIAL - The credential to use in Whirr
29+
#
30+
# BLOBSTORE_* - Overrides the base variables (e.g. PROVIDER) specifically for
31+
# blobstore contexts. Base variables are still used for compute access
32+
# If BLOBSTORE_* variables are not defined Whirr will use the base variables
33+
# for blobstore access.
34+
35+
# Users can assign these variables the values they want to assign to
36+
# their WHIRR_* variable counterparts. If a WHIRR_* variable is found in env
37+
# then it takes precedence (to be able to do one-off overrides on recipes)
38+
# otherwise WHIRR_* variables take the value from this file. Finally .properties
39+
# files override both this file and previous env variables
40+
41+
# Set cloud provider connection details
42+
43+
PROVIDER=
44+
IDENTITY=
45+
CREDENTIAL=
46+
47+
# Set blob store connection details. If not defined they are computed
48+
# from the cloud provider connection details defined above
49+
50+
# BLOBSTORE_PROVIDER=
51+
# BLOBSTORE_IDENTITY=
52+
# BLOBSTORE_CREDENTIAL=
53+

core/src/main/java/org/apache/whirr/ClusterSpec.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,8 @@ private Configuration composeWithDefaults(Configuration userConfig)
434434
throws ConfigurationException {
435435
CompositeConfiguration composed = new CompositeConfiguration();
436436
composed.addConfiguration(userConfig);
437-
composed.addConfiguration(new PropertiesConfiguration(getClass().getClassLoader().getResource(DEFAULT_PROPERTIES)));
437+
composed.addConfiguration(new PropertiesConfiguration(
438+
getClass().getClassLoader().getResource(DEFAULT_PROPERTIES)));
438439
return composed;
439440
}
440441

core/src/main/java/org/apache/whirr/command/AbstractClusterCommand.java

+18-14
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,15 @@
1818

1919
package org.apache.whirr.command;
2020

21-
import static org.apache.whirr.ClusterSpec.Property.CLUSTER_NAME;
22-
import static org.apache.whirr.ClusterSpec.Property.IDENTITY;
23-
import static org.apache.whirr.ClusterSpec.Property.INSTANCE_TEMPLATES;
24-
2521
import com.google.common.collect.Maps;
26-
2722
import java.io.IOException;
2823
import java.io.PrintStream;
2924
import java.util.EnumSet;
3025
import java.util.Map;
31-
3226
import joptsimple.ArgumentAcceptingOptionSpec;
3327
import joptsimple.OptionParser;
3428
import joptsimple.OptionSet;
3529
import joptsimple.OptionSpec;
36-
3730
import org.apache.commons.configuration.CompositeConfiguration;
3831
import org.apache.commons.configuration.Configuration;
3932
import org.apache.commons.configuration.ConfigurationException;
@@ -43,6 +36,12 @@
4336
import org.apache.whirr.ClusterControllerFactory;
4437
import org.apache.whirr.ClusterSpec;
4538
import org.apache.whirr.ClusterSpec.Property;
39+
import static org.apache.whirr.ClusterSpec.Property.CLUSTER_NAME;
40+
import static org.apache.whirr.ClusterSpec.Property.CREDENTIAL;
41+
import static org.apache.whirr.ClusterSpec.Property.IDENTITY;
42+
import static org.apache.whirr.ClusterSpec.Property.INSTANCE_TEMPLATES;
43+
import static org.apache.whirr.ClusterSpec.Property.PRIVATE_KEY_FILE;
44+
import static org.apache.whirr.ClusterSpec.Property.PROVIDER;
4645
import org.apache.whirr.state.ClusterStateStore;
4746
import org.apache.whirr.state.ClusterStateStoreFactory;
4847
import org.slf4j.Logger;
@@ -100,12 +99,14 @@ protected ClusterSpec getClusterSpec(OptionSet optionSet) throws ConfigurationEx
10099
for (Map.Entry<Property, OptionSpec<?>> entry : optionSpecs.entrySet()) {
101100
Property property = entry.getKey();
102101
OptionSpec<?> option = entry.getValue();
102+
Object value;
103103
if (property.hasMultipleArguments()) {
104-
optionsConfig.setProperty(property.getConfigName(),
105-
optionSet.valuesOf(option));
104+
value = optionSet.valuesOf(option);
106105
} else {
107-
optionsConfig.setProperty(property.getConfigName(),
108-
optionSet.valueOf(option));
106+
value = optionSet.valueOf(option);
107+
}
108+
if (value != null) {
109+
optionsConfig.setProperty(property.getConfigName(), value);
109110
}
110111
}
111112
CompositeConfiguration config = new CompositeConfiguration();
@@ -114,14 +115,17 @@ protected ClusterSpec getClusterSpec(OptionSet optionSet) throws ConfigurationEx
114115
Configuration defaults = new PropertiesConfiguration(optionSet.valueOf(configOption));
115116
config.addConfiguration(defaults);
116117
}
118+
ClusterSpec clusterSpec = new ClusterSpec(config);
117119

118-
for (Property required : EnumSet.of(CLUSTER_NAME, IDENTITY, INSTANCE_TEMPLATES)) {
119-
if (config.getString(required.getConfigName()) == null) {
120+
for (Property required : EnumSet.of(CLUSTER_NAME, PROVIDER, IDENTITY, CREDENTIAL,
121+
INSTANCE_TEMPLATES, PRIVATE_KEY_FILE)) {
122+
if (clusterSpec.getConfiguration().getString(required.getConfigName()) == null) {
120123
throw new IllegalArgumentException(String.format("Option '%s' not set.",
121124
required.getSimpleName()));
122125
}
123126
}
124-
return new ClusterSpec(config);
127+
128+
return clusterSpec;
125129
}
126130

127131
/**

core/src/main/resources/whirr-default.properties

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ whirr.private-key-file=${sys:user.home}/.ssh/id_rsa
1515
# whirr.public-key-file = ${whirr.private-key-file}.pub
1616
# this is created in ClusterSpec class constructor
1717

18+
whirr.provider=${env:WHIRR_PROVIDER}
19+
whirr.identity=${env:WHIRR_IDENTITY}
20+
whirr.credential=${env:WHIRR_CREDENTIAL}
21+
1822
whirr.version=${version}
1923

2024
whirr.max-startup-retries=1

core/src/test/java/org/apache/whirr/command/AbstractClusterCommandTest.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@
1818

1919
package org.apache.whirr.command;
2020

21-
import static org.hamcrest.Matchers.is;
22-
import static org.junit.Assert.assertThat;
21+
import joptsimple.OptionSet;
22+
import org.apache.whirr.ClusterControllerFactory;
23+
import org.apache.whirr.ClusterSpec;
24+
import org.apache.whirr.util.KeyPair;
25+
import org.junit.Test;
2326

2427
import java.io.File;
2528
import java.io.InputStream;
2629
import java.io.PrintStream;
2730
import java.util.List;
2831
import java.util.Map;
2932

30-
import joptsimple.OptionSet;
31-
32-
import org.apache.whirr.ClusterControllerFactory;
33-
import org.apache.whirr.ClusterSpec;
34-
import org.apache.whirr.util.KeyPair;
35-
import org.junit.Test;
33+
import static org.hamcrest.Matchers.is;
34+
import static org.junit.Assert.assertThat;
3635

3736
public class AbstractClusterCommandTest {
3837

@@ -62,6 +61,7 @@ public int run(InputStream in, PrintStream out, PrintStream err,
6261
* Ensure that an invalid service name uses the default (after logging a
6362
* warning).
6463
*/
64+
@Test
6565
public void testCreateServerWithInvalidClusterControllerName() throws Exception {
6666
AbstractClusterCommand clusterCommand = new AbstractClusterCommand("name",
6767
"description", new ClusterControllerFactory()) {

recipes/cassandra-ec2.properties recipes/cassandra.properties

+7-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#
1717

1818
#
19-
# Cassandra Cluster on AWS EC2
19+
# Setup an Apache Cassandra Cluster
2020
#
2121

2222
# Read the Configuration Guide for more info:
@@ -25,14 +25,15 @@
2525
# Change the cluster name here
2626
whirr.cluster-name=cassandra
2727

28+
# Setup your cloud credentials by copying conf/credentials.sample
29+
# to ~/.whirr/credentials and editing as needed
30+
31+
# Change the name of cluster admin user
32+
whirr.cluster-user=${sys:user.name}
33+
2834
# Change the number of machines in the cluster here
2935
whirr.instance-templates=3 cassandra
3036

31-
# For EC2 set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.
32-
whirr.provider=aws-ec2
33-
whirr.identity=${env:AWS_ACCESS_KEY_ID}
34-
whirr.credential=${env:AWS_SECRET_ACCESS_KEY}
35-
3637
# By default use the user system SSH keys. Override them here.
3738
# whirr.private-key-file=${sys:user.home}/.ssh/id_rsa
3839
# whirr.public-key-file=${whirr.private-key-file}.pub

recipes/elasticsearch-rackspace.properties

-91
This file was deleted.

0 commit comments

Comments
 (0)