stemcell 0.0.11 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,28 +1,92 @@
1
- # Stemcell
1
+ # Stemcell #
2
2
 
3
- Stemcell launches instances
3
+ Stemcell launches instances in EC2.
4
+ These instances are created to your specification, with knobs like AMI, instance type, and region exposed.
5
+ The instances are bootstrapped with chef-solo, using a specified git repo and branch as the source of roles and recipes.
4
6
 
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
8
10
 
9
- gem 'stemcell'
11
+ ```bash
12
+ gem 'stemcell'
13
+ ```
10
14
 
11
15
  And then execute:
12
16
 
13
- $ bundle
17
+ ```bash
18
+ $ bundle
19
+ ```
14
20
 
15
21
  Or install it yourself as:
16
22
 
17
- $ gem install stemcell
23
+ ```bash
24
+ $ gem install stemcell
25
+ ```
26
+
27
+ ## Configuration
28
+
29
+ You should create an rc file for stemcell with your standard options
30
+ (and place it in the root dir as .stemcellrc?). You can see an example
31
+ in examples/stemcellrc. You can get most of the options from your
32
+ .chef/knife.rb but you will need to get the new chef deploy key so
33
+ that instances that you launch can download code.
18
34
 
19
35
  ## Usage
20
36
 
37
+ ### Include your base config:
38
+
39
+ ```bash
40
+ $ source .stemcellrc
41
+ ```
42
+
43
+ ### Simple launch:
44
+
45
+ ```bash
46
+ $ ./bin/stemcell --chef-role $your_chef_role --git-branch $your_chef_branch
47
+ ```
48
+
49
+ This will cause instance(s) to be launched and their ip's and instance
50
+ id to be printed to the screen.
51
+
52
+ ### More options:
53
+
54
+ ```bash
55
+ $ ./bin/stemcell --help
56
+ ```
57
+
58
+ ### Watching install:
59
+
60
+ ```bash
61
+ $ ssh unbutu@$IP 'tail -f /var/log/init*'
62
+ ```
63
+
64
+ ### Terminating:
65
+
66
+ This still needs to be completed. For now, you can kill using the
67
+ amazon cli tools or the web ui.
68
+
69
+ ## Automation ##
70
+
71
+ This README presents `stemcell` as a tool for administrators to use to create instances.
72
+ However, we designed `stemcell` to be easily useful for automated systems which control server infrastructure.
73
+ These automated systems can call out to `stemcell` on the command-line or use the ruby classes directly.
74
+
75
+ To see how we manage our cloud, check out the rest of SmartStack, especially Cortex, our auto-scaling system.
76
+
77
+ ## Similar Tools ##
78
+
79
+ There are a few additional tools which bootstrap EC2 instances with chef-solo.
80
+ If you're using chef-server, obvious answer is [knife-ec2](https://github.com/opscode/knife-ec2).
81
+ Unless you're working on a big team where lots of people edit cookbooks simultaneously, we strongly recommend this approach!
82
+ It's especially excellent when paired with [hosted chef](http://www.opscode.com/hosted-chef/), which makes getting off the ground with configuration management fast and easy.
21
83
 
22
- ## Contributing
84
+ If you want to use knife-ec2 with chef-solo, you could use [knife solo](http://matschaffer.github.com/knife-solo/).
85
+ Another approach which is great for interactive usage involves [using fabric to bootstrap chef](http://unfoldthat.com/2012/06/02/quick-deploy-chef-solo-fabric.html)([with gist](https://gist.github.com/va1en0k/2859812)).
23
86
 
24
- 1. Fork it
25
- 2. Create your feature branch (`git checkout -b my-new-feature`)
26
- 3. Commit your changes (`git commit -am 'Add some feature'`)
27
- 4. Push to the branch (`git push origin my-new-feature`)
28
- 5. Create new Pull Request
87
+ Finally, we couldn't resist doing a bit of code archeology.
88
+ People have been using chef with EC2 for a long time!
89
+ One early article is [this one](http://web.archive.org/web/20110404114025/http://probablyinteractive.com/2009/3/29/Amazon%20EC2%20+%20Chef%20=%20Mmmmm.html), which isn't even on the web anymore.
90
+ However, it's spawned some recently-active tools like [this](https://github.com/conormullen/chef-bootstrap) and [this](https://github.com/grempe/chef-solo-bootstrap).
91
+ Similar approaches are mentioned [here](http://www.opinionatedprogrammer.com/2011/06/chef-solo-tutorial-managing-a-single-server-with-chef/), with code [herh](https://github.com/ciastek/ubuntu-chef-solo) or [here](https://github.com/riywo/ubuntu-chef-solo) (with accompanying [blog post](http://weblog.riywo.com/post/35976125760))
92
+ [This article](http://illuminatedcomputing.com/posts/2012/02/simple-chef-solo-tutorial/), also mentions many worthwhile predecessors.
data/bin/stemcell CHANGED
@@ -30,22 +30,22 @@ END_OF_BANNER
30
30
  :default => ENV['REGION'] ? ENV['REGION'] : 'us-east-1',
31
31
  )
32
32
 
33
- opt('machine_type',
34
- 'instance type to launch',
33
+ opt('instance_type',
34
+ 'machine type to launch',
35
35
  :type => String,
36
- :default => ENV['MACHINE_TYPE'] ? ENV['MACHINE_TYPE'] : 'm1.small',
36
+ :default => ENV['INSTANCE_TYPE'] ? ENV['INSTANCE_TYPE'] : 'm1.small',
37
37
  )
38
38
 
39
- opt('image',
39
+ opt('image_id',
40
40
  'ami to use for launch',
41
41
  :type => String,
42
- :default => ENV['AMI'] ? ENV['AMI'] : 'ami-d726abbe',
42
+ :default => ENV['IMAGE_ID'] ? ENV['IMAGE_ID'] : 'ami-d726abbe',
43
43
  )
44
44
 
45
- opt('security_group',
46
- 'security group to launch instance with',
45
+ opt('security_groups',
46
+ 'security groups to launch instance with',
47
47
  :type => String,
48
- :default => ENV['SECURITY_GROUP'] ? ENV['SECURITY_GROUP'] : 'default',
48
+ :default => ENV['SECURITY_GROUPS'] ? ENV['SECURITY_GROUPS'] : 'default',
49
49
  )
50
50
 
51
51
  opt('availability-zone',
@@ -55,7 +55,7 @@ END_OF_BANNER
55
55
  )
56
56
 
57
57
  opt('tags',
58
- 'tags to apply to image',
58
+ 'comma-separated list of key=value pairs to apply',
59
59
  :type => String,
60
60
  :default => ENV['TAGS'],
61
61
  )
@@ -78,6 +78,12 @@ END_OF_BANNER
78
78
  :default => ENV['CHEF_ROLE'],
79
79
  )
80
80
 
81
+ opt('chef_environment',
82
+ 'chef environment in which this instance will run',
83
+ :type => String,
84
+ :default => ENV['CHEF_ENVIRONMENT'],
85
+ )
86
+
81
87
  opt('git_origin',
82
88
  'git origin to use',
83
89
  :type => String,
@@ -87,7 +93,7 @@ END_OF_BANNER
87
93
  opt('git_branch',
88
94
  'git branch to run off',
89
95
  :type => String,
90
- :default => ENV['GIT_BRANCH'],
96
+ :default => ENV['GIT_BRANCH'] ? ENV['GIT_BRANCH'] : 'production',
91
97
  )
92
98
 
93
99
  opt('git_key',
@@ -98,8 +104,8 @@ END_OF_BANNER
98
104
 
99
105
  opt('count',
100
106
  'number of instances to launch',
101
- :type => String,
102
- :default => ENV['COUNT'],
107
+ :type => Integer,
108
+ :default => ENV['COUNT'] ? ENV['COUNT'] : 1,
103
109
  )
104
110
 
105
111
  end
@@ -108,6 +114,8 @@ required_parameters = [
108
114
  'aws_access_key',
109
115
  'aws_secret_key',
110
116
  'chef_role',
117
+ 'chef_environment',
118
+ 'chef_data_bag_secret',
111
119
  'git_branch',
112
120
  'git_key',
113
121
  'git_origin',
@@ -120,6 +128,7 @@ by the #{arg.upcase.gsub('-','_')} environment variable" if
120
128
  options[arg].nil? or ! options[arg]
121
129
  end
122
130
 
131
+
123
132
  # convert tags from string to ruby hash
124
133
  tags = {}
125
134
  if options['tags']
@@ -130,6 +139,30 @@ if options['tags']
130
139
  end
131
140
  options['tags'] = tags
132
141
 
133
- stemcell = Stemcell::Stemcell.new(options)
134
- stemcell.launch({'count' => options['count']})
135
142
 
143
+ # convert security_groups from comma seperated string to ruby array
144
+ options['security_groups'] = options['security_groups'].split(',')
145
+
146
+
147
+ # create stemcell object
148
+ stemcell = Stemcell::Stemcell.new({
149
+ 'aws_access_key' => options['aws_access_key'],
150
+ 'aws_secret_key' => options['aws_secret_key'],
151
+ 'region' => options['region'],
152
+ })
153
+
154
+
155
+ # launch instance(s)
156
+ stemcell.launch({
157
+ 'instance_type' => options['instance_type'],
158
+ 'image_id' => options['image_id'],
159
+ 'security_groups' => options['security_groups'],
160
+ 'chef_role' => options['chef_role'],
161
+ 'chef_environment' => options['chef_environment'],
162
+ 'chef_data_bag_secret' => options['chef_data_bag_secret'],
163
+ 'git_branch' => options['git_branch'],
164
+ 'git_key' => options['git_key'],
165
+ 'git_origin' => options['git_origin'],
166
+ 'key_name' => options['key_name'],
167
+ 'count' => options['count'],
168
+ })
@@ -0,0 +1,10 @@
1
+ # these options need to be set
2
+ export AWS_ACCESS_KEY=your_aws_access_key
3
+ export AWS_SECRET_KEY=your_aws_secret_key
4
+ export KEY_NAME=your_aws_ssh_key_name
5
+ export CHEF_DATA_BAG_SECRET=/path/to/encrypted/data/bag/secret
6
+ export GIT_KEY=/path/to/chef/deploy/key
7
+
8
+ # these options should not need to be set
9
+ export SECURITY_GROUP=default
10
+ export GIT_ORIGIN=git@github.com:airbnb/chef.git
@@ -31,12 +31,14 @@ exec 2> /var/log/init.err
31
31
 
32
32
 
33
33
  chef_version=11.4.0
34
- repo_dir=/etc/chef/src
35
- role=<%= @chef_role %>
36
- origin=<%= @git_origin %>
37
- branch=<%= @git_branch %>
38
- git_key='<%= @git_key_contents %>'
39
- data_bag_secret='<%= @chef_data_bag_secret %>'
34
+ chef_dir=/etc/chef
35
+ converge=/usr/local/bin/converge
36
+ role=<%= opts['chef_role'] %>
37
+ environment=<%= opts['chef_environment'] %>
38
+ origin=<%= opts['git_origin'] %>
39
+ branch=<%= opts['git_branch'] %>
40
+ git_key='<%= opts["git_key"] %>'
41
+ data_bag_secret='<%= opts["chef_data_bag_secret"] %>'
40
42
 
41
43
 
42
44
  ##
@@ -69,8 +71,6 @@ install_chef() {
69
71
  if ! which chef-solo > /dev/null ; then
70
72
  echo installing chef via omnibus...
71
73
  curl -L --silent https://www.opscode.com/chef/install.sh | sudo bash -s -- -v $chef_version 1>&2
72
- # TODO(mkr): this is a hack to get chef-solo-search working
73
- /opt/chef/embedded/bin/gem install --no-ri --no-rdoc treetop
74
74
  else
75
75
  echo chef is already installed
76
76
  fi
@@ -78,80 +78,86 @@ install_chef() {
78
78
 
79
79
 
80
80
  update_repo() {
81
- git_wrapper=/etc/chef/git_wrapper
82
- local keyfile=/etc/chef/git_key
81
+ echo -e "$git_key" > $keyfile
82
+ chmod 0400 $keyfile
83
+
84
+ echo "ssh -i $keyfile -o StrictHostKeyChecking=no \$1 \$2" > $git_wrapper
85
+ chmod 0500 $git_wrapper
86
+
83
87
  mkdir -p $(dirname $repo_dir)
84
- if [ -d $repo_dir ]; then
85
- echo updating source...
86
- (cd $repo_dir && GIT_SSH=$git_wrapper git fetch && git reset --hard origin/$branch && git clean -fdx)
87
- else
88
- echo -e "$git_key" > $keyfile
89
- chmod 0400 $keyfile
90
- echo "ssh -i $keyfile -o StrictHostKeyChecking=no \$1 \$2" > $git_wrapper
91
- chmod 0500 $git_wrapper
92
- echo downloading cookbook repo...
88
+ if [ ! -d $repo_dir ]; then
89
+ echo "downloading cookbook repo..."
93
90
  GIT_SSH=$git_wrapper git clone --branch $branch --depth 1 $origin $repo_dir
91
+ else
92
+ echo "cookbook repo already exists"
94
93
  fi
95
- echo done updating code
94
+
95
+ echo "done updating code"
96
96
  }
97
97
 
98
98
 
99
99
  configure_chef() {
100
- echo configuring chef...
101
- mkdir -p /etc/chef
102
- if [ -f $repo_dir/roles/${branch}.rb ]; then
103
- echo "setting runlist to role[$branch],role[$role]"
104
- cat<<EOF>/etc/chef/solo.json
105
- {
106
- "run_list": [
107
- "role[$branch]",
108
- "role[$role]"
109
- ],
110
- "branch": "$branch",
111
- "role": "$role"
112
- }
113
- EOF
114
- else
115
- echo "setting runlist to role[$role]"
116
- cat<<EOF>/etc/chef/solo.json
117
- {
118
- "run_list": "role[$role]",
119
- "branch": "$branch",
120
- "role": "$role"
121
- }
122
- EOF
123
- fi
100
+ echo "saving current branch ($branch), role ($role), and environment ($environment)"
101
+ echo "$branch" > $branchfile
102
+ chmod 644 $branchfile
103
+
104
+ echo "$role" > $rolefile
105
+ chmod 644 $rolefile
106
+
107
+ echo "$environment" > $envfile
108
+ chmod 644 $envfile
109
+
110
+ echo "configuring chef solo..."
111
+ cat<<EOF > ${chef_dir}/solo.rb
112
+ repo_dir = "${repo_dir}"
113
+ cookbook_path "#{repo_dir}/cookbooks"
114
+ role_path "#{repo_dir}/roles"
115
+ data_bag_path "#{repo_dir}/data_bags"
124
116
 
125
- cat<<EOF>/etc/chef/solo.rb
126
117
  log_level :info
127
118
  log_location STDOUT
128
- cookbook_path "$repo_dir/cookbooks"
129
- role_path "$repo_dir/roles"
130
- data_bag_path "$repo_dir/data_bags"
131
- json_attribs '/etc/chef/solo.json'
132
119
  EOF
133
- echo -e "$data_bag_secret" > /etc/chef/encrypted_data_bag_secret
134
- echo chef configured
120
+
121
+ echo -e "$data_bag_secret" > ${chef_dir}/encrypted_data_bag_secret
122
+ echo "chef configured"
135
123
  }
136
124
 
137
125
 
138
126
  configure_converger() {
139
- cat<<EOF>/usr/local/bin/converge
140
- #!/bin/bash -e
127
+ cat<<EOF > $converge
128
+ #!/bin/bash -eu
129
+
130
+ repo="${repo_dir}"
131
+ branch=\`cat ${branchfile}\`
132
+ role=\`cat ${rolefile}\`
133
+ env=\`cat ${envfile}\`
134
+
135
+ cd \${repo}
136
+
137
+ runlist="role[\${role}]"
138
+ if [ -f "roles/\${env}.rb" ]
139
+ then
140
+ runlist+=",role[\${env}]"
141
+ fi
141
142
 
142
- echo doing a hard reset to origin/$branch
143
- cd $repo_dir
144
- GIT_SSH=$git_wrapper git fetch
145
- git reset --hard origin/$branch
143
+ echo doing a hard reset to origin/\${branch}
144
+ GIT_SSH=${git_wrapper} git fetch
145
+ git reset --hard origin/\${branch}
146
146
  git clean -fdx
147
- chef-solo
147
+
148
+ json="{\"role\": \"\${role}\", \"env\": \"\${env}\", \"branch\": \"\${branch}\"}"
149
+ json_file=\`tempfile\`
150
+ echo \$json > \$json_file
151
+ trap "{ rm -f '\$json_file' ; }" EXIT
152
+
153
+ echo "running chef-solo with runlist \$runlist and json \$json (in file \$json_file)"
154
+ chef-solo -o "\${runlist}" -j \${json_file} "\$@"
148
155
  EOF
149
- chmod 0544 /usr/local/bin/converge
156
+ chmod 544 $converge
150
157
  }
151
158
 
152
-
153
159
  configure_chef_daemon() {
154
- cat<<EOF>/etc/init/chef-solo.conf
160
+ cat<<EOF > /etc/init/chef-solo.conf
155
161
  description "chef-solo"
156
162
  author "Martin Rhoads"
157
163
  start on networking
@@ -164,12 +170,11 @@ EOF
164
170
 
165
171
 
166
172
  run_chef() {
167
- echo running chef-solo...
168
- chef-solo 1>&2
169
- echo done running chef-solo
173
+ echo "doing initial chef run..."
174
+ $converge 1>&2
175
+ echo "initial chef run complete"
170
176
  }
171
177
 
172
-
173
178
  start_chef_daemon() {
174
179
  start chef-solo
175
180
  }
@@ -179,8 +184,16 @@ start_chef_daemon() {
179
184
  ## main
180
185
  ##
181
186
 
187
+ #some derived vars
188
+ repo_dir=${chef_dir}/src
189
+ keyfile=${chef_dir}/git_key
190
+ envfile=${chef_dir}/environment
191
+ rolefile=${chef_dir}/role
192
+ branchfile=${chef_dir}/branch
193
+ git_wrapper=${chef_dir}/git_wrapper
182
194
 
183
- echo starting chef bootstrapping...
195
+ echo "starting chef bootstrapping..."
196
+ mkdir -p ${chef_dir}
184
197
  update
185
198
  install curl
186
199
  install git
@@ -190,6 +203,7 @@ update_repo
190
203
  configure_chef
191
204
  configure_converger
192
205
  run_chef
206
+
193
207
  configure_chef_daemon
194
208
  # start_chef_daemon
195
209
 
@@ -1,3 +1,3 @@
1
1
  module Stemcell
2
- VERSION = "0.0.11"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/stemcell.rb CHANGED
@@ -8,65 +8,81 @@ module Stemcell
8
8
  class Stemcell
9
9
  def initialize(opts={})
10
10
  @log = Logger.new(STDOUT)
11
+ @log.level = Logger::INFO unless ENV['DEBUG']
12
+ @log.debug "creating new stemcell object"
11
13
  @log.debug "opts are #{opts.inspect}"
12
14
  ['aws_access_key',
13
15
  'aws_secret_key',
14
16
  'region',
15
- 'machine_type',
16
- 'image',
17
- 'security_group',
18
-
19
- 'chef_role',
20
- 'git_branch',
21
- 'git_key',
22
- 'git_origin',
23
- 'key_name',
24
17
  ].each do |req|
25
18
  raise ArgumentError, "missing required param #{req}" unless opts[req]
26
19
  instance_variable_set("@#{req}",opts[req])
27
20
  end
28
21
 
29
- @zone = opts.include?('availability_zone') ? opts['availability_zone'] : nil
30
22
  @ec2_url = "ec2.#{@region}.amazonaws.com"
31
23
  @timeout = 120
32
24
  @start_time = Time.new
33
25
 
34
- @tags = {
35
- 'Name' => "#{@chef_role}-#{@git_branch}",
36
- 'Group' => "#{@chef_role}-#{@git_branch}",
37
- 'created_by' => ENV['USER'],
38
- 'stemcell' => VERSION,
39
- }
40
- @tags.merge!(opts['tags']) if opts['tags']
41
-
42
- begin
43
- @git_key_contents = File.read(@git_key)
44
- rescue Object => e
45
- @git_key_contents = @git_key # assume content is passed in
46
- end
47
-
48
- if opts.include?('chef_data_bag_secret')
49
- begin
50
- @chef_data_bag_secret = File.read(opts['chef_data_bag_secret'])
51
- rescue Object => e
52
- @chef_data_bag_secret = opts['chef_data_bag_secret'] # assume secret is passed in
53
- end
54
- else
55
- @chef_data_bag_secret = ''
56
- end
57
-
58
26
  AWS.config({:access_key_id => @aws_access_key, :secret_access_key => @aws_secret_key})
59
27
  @ec2 = AWS::EC2.new(:ec2_endpoint => @ec2_url)
60
28
  @ec2_region = @ec2.regions[@region]
61
- @user_data = render_template
62
29
  end
63
30
 
31
+
64
32
  def launch(opts={})
65
- File.open('/tmp/user-data', 'w') {|f| f.write(@user_data) }
66
- instances = do_launch(opts)
33
+ verify_required_options(opts,[
34
+ 'image_id',
35
+ 'security_groups',
36
+ 'key_name',
37
+ 'count',
38
+ 'chef_role',
39
+ 'chef_environment',
40
+ 'chef_data_bag_secret',
41
+ 'git_branch',
42
+ 'git_key',
43
+ 'git_origin',
44
+ 'instance_type',
45
+ ])
46
+
47
+ # attempt to accept keys as file paths
48
+ opts['git_key'] = try_file(opts['git_key'])
49
+ opts['chef_data_bag_secret'] = try_file(opts['chef_data_bag_secret'])
50
+
51
+ # generate tags and merge in any that were specefied as in inputs
52
+ tags = {
53
+ 'Name' => "#{opts['chef_role']}-#{opts['chef_environment']}",
54
+ 'Group' => "#{opts['chef_role']}-#{opts['chef_environment']}",
55
+ 'created_by' => ENV['USER'],
56
+ 'stemcell' => VERSION,
57
+ }
58
+ tags.merge!(opts['tags']) if opts['tags']
59
+
60
+ # generate user data script to boot strap instance based on the
61
+ # opts that we were passed.
62
+ user_data = render_template(opts)
63
+
64
+ launch_options = {
65
+ :image_id => opts['image_id'],
66
+ :security_groups => opts['security_groups'],
67
+ :user_data => opts['user_data'],
68
+ :instance_type => opts['instance_type'],
69
+ :key_name => opts['key_name'],
70
+ :count => opts['count'],
71
+ :user_data => user_data,
72
+ }
73
+ launch_options.merge({:availability_zone => opts['availability_zone']}) if opts['availability_zone']
74
+
75
+ # launch instances
76
+ instances = do_launch(launch_options)
77
+
78
+ # wait for aws to report instance stats
67
79
  wait(instances)
68
- set_tags(instances)
80
+
81
+ # set tags on all instances launched
82
+ set_tags(instances, tags)
83
+
69
84
  print_run_info(instances)
85
+ @log.info "launched instances successfully"
70
86
  return instances
71
87
  end
72
88
 
@@ -83,7 +99,7 @@ module Stemcell
83
99
  end
84
100
 
85
101
  def wait(instances)
86
- @log.info "Waiting for #{instances.count} instances (#{instances.inspect}):"
102
+ @log.info "Waiting up to #{@timeout} seconds for #{instances.count} instances (#{instances.inspect}):"
87
103
 
88
104
  while true
89
105
  sleep 5
@@ -100,18 +116,18 @@ module Stemcell
100
116
  @log.info "all instances in running state"
101
117
  end
102
118
 
103
- def do_launch(opts={})
104
- options = {
105
- :image_id => @image,
106
- :security_groups => @security_group,
107
- :user_data => @user_data,
108
- :instance_type => @machine_type,
109
- :key_name => @key_name,
110
- }
111
- options[:availability_zone] = @zone if @zone
112
- options[:count] = opts['count'] if opts.include?('count')
119
+ def verify_required_options(params,required_options)
120
+ @log.debug "params is #{params}"
121
+ @log.debug "required_options are #{required_options}"
122
+ required_options.each do |required|
123
+ raise ArgumentError, "you need to provide option #{required}" unless params[required]
124
+ end
125
+ end
113
126
 
114
- instances = @ec2_region.instances.create(options)
127
+ def do_launch(opts={})
128
+ @log.debug "about to launch instance(s) with options #{opts}"
129
+ @log.info "launching instances"
130
+ instances = @ec2_region.instances.create(opts)
115
131
  instances = [instances] unless instances.class == Array
116
132
  instances.each do |instance|
117
133
  @log.info "launched instance #{instance.instance_id}"
@@ -119,19 +135,21 @@ module Stemcell
119
135
  return instances
120
136
  end
121
137
 
122
- def set_tags(instances=[])
138
+ def set_tags(instances=[],tags)
139
+ @log.info "setting tags on instance(s)"
123
140
  instances.each do |instance|
124
- instance.tags.set(@tags)
141
+ instance.tags.set(tags)
125
142
  end
126
143
  end
127
144
 
128
- def render_template
145
+ def render_template(opts={})
129
146
  this_file = File.expand_path __FILE__
130
147
  base_dir = File.dirname this_file
131
148
  template_file_path = File.join(base_dir,'stemcell','templates','bootstrap.sh.erb')
132
149
  template_file = File.read(template_file_path)
133
150
  erb_template = ERB.new(template_file)
134
151
  generated_template = erb_template.result(binding)
152
+ @log.debug "genereated template is #{generated_template}"
135
153
  return generated_template
136
154
  end
137
155
 
@@ -142,5 +160,15 @@ module Stemcell
142
160
  instance.delete
143
161
  end
144
162
  end
163
+
164
+ # attempt to accept keys as file paths
165
+ def try_file(opt="")
166
+ begin
167
+ return File.read(opt)
168
+ rescue Object => e
169
+ return opt
170
+ end
171
+ end
172
+
145
173
  end
146
174
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stemcell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-23 00:00:00.000000000 Z
12
+ date: 2013-02-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: trollop
@@ -57,6 +57,7 @@ files:
57
57
  - README.md
58
58
  - Rakefile
59
59
  - bin/stemcell
60
+ - examples/stemcellrc
60
61
  - lib/stemcell.rb
61
62
  - lib/stemcell/templates/bootstrap.sh.erb
62
63
  - lib/stemcell/version.rb