stemcell 0.0.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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