stack-kicker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ results.html
3
+ pkg
4
+ html
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kicker.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Simon McCartney
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Kicker
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kicker'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kicker
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = kicker - DESCRIBE YOUR GEM
2
+
3
+ Author:: YOUR NAME (YOUR EMAIL)
4
+ Copyright:: Copyright (c) 2013 YOUR NAME
5
+
6
+
7
+ DESCRIBE YOUR GEM HERE
8
+
9
+ == Links
10
+
11
+ * {Source on Github}[LINK TO GITHUB]
12
+ * RDoc[LINK TO RDOC.INFO]
13
+
14
+ == Install
15
+
16
+ == Examples
17
+
18
+ == Contributing
19
+
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ def dump_load_path
2
+ puts $LOAD_PATH.join("\n")
3
+ found = nil
4
+ $LOAD_PATH.each do |path|
5
+ if File.exists?(File.join(path,"rspec"))
6
+ puts "Found rspec in #{path}"
7
+ if File.exists?(File.join(path,"rspec","core"))
8
+ puts "Found core"
9
+ if File.exists?(File.join(path,"rspec","core","rake_task"))
10
+ puts "Found rake_task"
11
+ found = path
12
+ else
13
+ puts "!! no rake_task"
14
+ end
15
+ else
16
+ puts "!!! no core"
17
+ end
18
+ end
19
+ end
20
+ if found.nil?
21
+ puts "Didn't find rspec/core/rake_task anywhere"
22
+ else
23
+ puts "Found in #{path}"
24
+ end
25
+ end
26
+ require 'bundler'
27
+ require 'rake/clean'
28
+
29
+ require 'rake/testtask'
30
+
31
+ require 'cucumber'
32
+ require 'cucumber/rake/task'
33
+ gem 'rdoc' # we need the installed RDoc gem, not the system one
34
+ require 'rdoc/task'
35
+
36
+ include Rake::DSL
37
+
38
+ Bundler::GemHelper.install_tasks
39
+
40
+
41
+ Rake::TestTask.new do |t|
42
+ t.pattern = 'test/tc_*.rb'
43
+ end
44
+
45
+
46
+ CUKE_RESULTS = 'results.html'
47
+ CLEAN << CUKE_RESULTS
48
+ Cucumber::Rake::Task.new(:features) do |t|
49
+ t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty --no-source -x"
50
+ t.fork = false
51
+ end
52
+
53
+ Rake::RDocTask.new do |rd|
54
+
55
+ rd.main = "README.rdoc"
56
+
57
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
58
+ end
59
+
60
+ task :default => [:test,:features]
61
+
data/bin/kicker ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'methadone'
5
+ require 'kicker'
6
+ require 'stack'
7
+
8
+ class App
9
+ include Methadone::Main
10
+ include Methadone::CLILogging
11
+
12
+ main do |stack|
13
+ config = Stack.load_config(options['configfile'], stack)
14
+ if config.nil?
15
+ exit_now!("#{stack} doesn't exist in #{options['configfile']}")
16
+ end
17
+
18
+ if options['show-stack']
19
+ puts stack
20
+ hostnames = Stack.generate_hostnames(config)
21
+ hostnames.each { |hostname| puts " #{hostname}" }
22
+ end
23
+
24
+ if options['show-running']
25
+ Stack.show_running(config)
26
+ end
27
+
28
+ if options['show-dns']
29
+ Stack.show_dns(config)
30
+ end
31
+
32
+ if options['show-details']
33
+ Stack.show_details(config)
34
+ end
35
+
36
+ if options['deploy-all']
37
+ Stack.deploy_all(config)
38
+ end
39
+
40
+ if options['delete-node']
41
+ info { "delete-node passed #{options['delete-node']}" }
42
+ Stack.delete_node(config, options['delete-node'])
43
+ end
44
+ end
45
+
46
+ # supplemental methods here
47
+
48
+ # Declare command-line interface here
49
+
50
+ description "Deploy your stack to the cloud"
51
+ #
52
+ # Accept flags via:
53
+ # on("--flag VAL","Some flag")
54
+ # on("--flag VAL","Some flag")
55
+ # options[flag] will contain VAL
56
+ #
57
+ # Specify switches via:
58
+ # on("--[no-]switch","Some switch")
59
+
60
+ arg :stack
61
+ options['configfile'] = 'Stackfile'
62
+ on("--configfile configfile", "Specify an alternative to ./Stackfile")
63
+ on("--show-stack", "Show the nodes defined in a stack")
64
+ on("--show-details", "Show the nodes defined in a stack in detail")
65
+ on("--show-running", "Show the running nodes")
66
+ on("--show-dns", "Show the current DNS config")
67
+ on("--deploy-all", "Deploy the stack, skipping existing nodes")
68
+ on("--replace-node NODE", "Replace a give node")
69
+ on("--delete-node NODE", "Destroy a node, including any shared CM & DNS")
70
+ on("--validate", "Validate the config, check as much as possible with out creating nodes")
71
+
72
+ version Kicker::VERSION
73
+
74
+ use_log_level_option
75
+
76
+ go!
77
+ end
@@ -0,0 +1,13 @@
1
+ Feature: My bootstrapped app kinda works
2
+ In order to get going on coding my awesome app
3
+ I want to have aruba and cucumber setup
4
+ So I don't have to do it myself
5
+
6
+ Scenario: App just runs
7
+ When I get help for "kicker"
8
+ Then the exit status should be 0
9
+ And the banner should be present
10
+ And the banner should document that this app takes options
11
+ And the following options should be documented:
12
+ |--version|
13
+ And the banner should document that this app takes no arguments
@@ -0,0 +1 @@
1
+ # Put your step definitions here
@@ -0,0 +1,16 @@
1
+ require 'aruba/cucumber'
2
+ require 'methadone/cucumber'
3
+
4
+ ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
5
+ LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
6
+
7
+ Before do
8
+ # Using "announce" causes massive warnings on 1.9.2
9
+ @puts = true
10
+ @original_rubylib = ENV['RUBYLIB']
11
+ ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
12
+ end
13
+
14
+ After do
15
+ ENV['RUBYLIB'] = @original_rubylib
16
+ end
data/kicker.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kicker/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "stack-kicker"
8
+ gem.version = Kicker::VERSION
9
+ gem.authors = ["Simon McCartney"]
10
+ gem.email = ["simon@mccartney.ie"]
11
+ gem.description = %q{Utility for kicking an application stack into life on Amazon EC2}
12
+ gem.summary = %q{Stacks are built from a collection of instances required to build an application stack.
13
+ Each instance is described in the Stackfile & provisioned using variety of methods. Supported models include:
14
+ EC2 Create with user-data, cloud-init from user-data (installs masterless puppet), puppet provision the instance.
15
+
16
+ Other models could include using a puppet master, Chef Solo or Chef Server/Hosted.
17
+ Amazon EC2 interaction is done through fog, so other providers should be easily added.
18
+
19
+ The guiding principle is that your Stackfile should be shareable & re-useable by others, and support templates, so that other users can use the template and easily adjust items in the stack (such as the instance size used, DNS Domain updated during deploy, EC2 account & location)
20
+ }
21
+ gem.homepage = "https://github.com/simonmcc/kicker"
22
+
23
+ gem.files = `git ls-files`.split($/)
24
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
25
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
26
+ gem.require_paths = ["lib"]
27
+ gem.add_development_dependency('rdoc')
28
+ gem.add_development_dependency('aruba')
29
+ gem.add_development_dependency('rake', '~> 0.9.2')
30
+ gem.add_dependency('methadone', '~> 1.2.4')
31
+ gem.add_dependency('fog', '~> 1.7.0')
32
+ end
@@ -0,0 +1,3 @@
1
+ module Kicker
2
+ VERSION = "0.0.1"
3
+ end
data/lib/kicker.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "kicker/version"
2
+
3
+ module Kicker
4
+ # Your code goes here...
5
+ end
data/lib/stack.rb ADDED
@@ -0,0 +1,212 @@
1
+ require 'pp'
2
+ require 'fog'
3
+
4
+ module Stack
5
+
6
+ def Stack.load_config(configfile, stack)
7
+ config_raw = File.read(configfile)
8
+ eval(config_raw)
9
+ config = StackConfig::Stacks[stack]
10
+ config
11
+ end
12
+
13
+ def Stack.connect(config)
14
+ connection = Fog::Compute.new({ :provider => config[:provider],
15
+ :aws_access_key_id => config[:aws_access_key_id],
16
+ :aws_secret_access_key => config[:aws_secret_access_key],
17
+ :region => config[:region] })
18
+ connection
19
+ end
20
+
21
+ def Stack.populate_config(config)
22
+ # build out the full config for each node, supplying defaults from the
23
+ # global config if explicitly supplied
24
+ config[:node_details] = Hash.new if config[:node_details].nil?
25
+
26
+ config[:roles].each do |role, role_details|
27
+ fqdn = role.to_s + '.' + config[:dns_domain]
28
+
29
+ config[:node_details][fqdn] = {
30
+ # set the node details from the role, if not specified in the role, use the config global
31
+ # (takes advantage of left to right evaluation of ||)
32
+ :flavor_id => (role_details[:flavor_id] || config[:flavor_id]),
33
+ :count => (role_details[:count] || 1),
34
+ :publish_private_ip => (role_details[:publish_private_ip] || false),
35
+ :dns_wildcard => (role_details[:dns_wildcard] || false)
36
+ }
37
+ end
38
+ end
39
+
40
+ def Stack.generate_hostnames(config)
41
+ stack_hostnames = Array.new
42
+ config[:roles].each do |role, role_details|
43
+ fqdn = role.to_s + '.' + config[:dns_domain]
44
+ stack_hostnames << fqdn
45
+ end
46
+ stack_hostnames
47
+ end
48
+
49
+ def Stack.deploy_all(config)
50
+ # create a connection
51
+ connection = Stack.connect(config)
52
+
53
+ running_instances = Stack.get_running(config)
54
+ config[:roles].each do |role, role_details|
55
+ hostname = role.to_s
56
+ fqdn = role.to_s + '.' + config[:dns_domain]
57
+
58
+ if !running_instances[fqdn].nil?
59
+ puts "Skipping #{fqdn} as it already exists"
60
+ next
61
+ end
62
+
63
+ # Ubuntu 8.04/Hardy doesn't do full cloud-init, so we have to script setting the hostname
64
+ user_data = File.read('user-data.sh')
65
+ user_data.gsub!(/rentpro-unconfigured/, hostname)
66
+ user_data.gsub!(/rentpro-stage.local/, config[:dns_domain])
67
+
68
+ # pp multipart
69
+ #
70
+ puts "Bootstraping new instance - #{fqdn}"
71
+ server = connection.servers.create({
72
+ :name => fqdn,
73
+ :hostname => fqdn,
74
+ :availability_zone => config[:availability_zone],
75
+ :flavor_id => config[:node_details][fqdn],
76
+ :image_id => config[:image_id],
77
+ :key_name => config[:keypair],
78
+ :user_data => user_data,
79
+ :tags => { 'Name' => fqdn },
80
+ })
81
+
82
+ print "Waiting for instance to be ready..."
83
+ server.wait_for { ready? }
84
+ puts "#{role.to_s} is booted, #{server.public_ip_address}/#{server.private_ip_address}"
85
+
86
+ # create/update the public & private DNS for this host
87
+ Stack.update_dns(role.to_s + '-public.' + config[:dns_domain], server.public_ip_address, config)
88
+ Stack.update_dns(role.to_s + '-private.' + config[:dns_domain], server.private_ip_address, config)
89
+
90
+ # create the dns
91
+ if (role_details[:publish_private_ip] == true && (!role_details[:publish_private_ip].nil?))
92
+ ip_address = server.private_ip_address
93
+ else
94
+ ip_address = server.public_ip_address
95
+ end
96
+ Stack.update_dns(fqdn, ip_address, config)
97
+ #
98
+ # is this a wildcard DNS host, then claim the *.domain.net
99
+ if (role_details[:dns_wildcard] == true && (!role_details[:dns_wildcard].nil?))
100
+ wildcard = "*." + config[:dns_domain]
101
+ Stack.update_dns(wildcard, ip_address, config)
102
+ end
103
+ end
104
+ end
105
+
106
+ def Stack.update_dns(fqdn, ip_address, config)
107
+ # now register it in DNS
108
+ dns = Fog::DNS.new({ :provider => config[:provider],
109
+ :aws_access_key_id => config[:aws_access_key_id],
110
+ :aws_secret_access_key => config[:aws_secret_access_key] })
111
+
112
+ # pp dns.get_hosted_zone(config[:dns_id])
113
+
114
+ bmtw = dns.zones.get(config[:dns_id])
115
+
116
+ record = bmtw.records.get(fqdn)
117
+ if record
118
+ record.modify(:value => ip_address) if record
119
+ else
120
+ bmtw.records.create(:value => ip_address, :name => fqdn, :type => 'A')
121
+ end
122
+ end
123
+
124
+ def Stack.show_dns(config)
125
+ # now register it in DNS
126
+ dns = Fog::DNS.new({ :provider => config[:provider],
127
+ :aws_access_key_id => config[:aws_access_key_id],
128
+ :aws_secret_access_key => config[:aws_secret_access_key] })
129
+
130
+ zone = dns.zones.get(config[:dns_id])
131
+ if zone.records.empty?
132
+ puts "No DNS records found in #{config[:dns_domain]}"
133
+ else
134
+ printf("%40s %20s %5s %5s\n", 'fqdn', 'value', 'type', 'ttl')
135
+ zone.records.each do |record|
136
+ printf("%40s %20s %5s %5d\n", record.name, record.value, record.type, record.ttl)
137
+ end
138
+ end
139
+ end
140
+
141
+ def Stack.get_running(config)
142
+ # create a connection
143
+ connection = Stack.connect(config)
144
+
145
+ # generate all the names that this stack will use
146
+ stack_hostnames = Stack.generate_hostnames(config)
147
+
148
+ # Amazon EC2, use the tags hash to find hostnames
149
+ running_instances = Hash.new
150
+ connection.servers.each do |instance|
151
+ # pp instance
152
+ if (!instance.tags['Name'].nil? && instance.state != 'terminated' && instance.state != 'shutting-down')
153
+ hostname = instance.tags['Name']
154
+ if stack_hostnames.include?(hostname)
155
+ running_instances[hostname] = instance
156
+ end
157
+ end
158
+ end
159
+ running_instances
160
+ end
161
+
162
+ def Stack.show_running(config)
163
+ running_instances = Stack.get_running(config)
164
+ running_instances.each do |instance, instance_details|
165
+ # display some details
166
+ puts "#{instance} id=#{instance_details.id} flavor_id=#{instance_details.flavor_id} public_ip=#{instance_details.public_ip_address} private_ip=#{instance_details.private_ip_address}"
167
+ end
168
+ end
169
+
170
+ def Stack.delete_node(config, fqdn)
171
+ running_instances = Stack.get_running(config)
172
+ if running_instances[fqdn].nil?
173
+ puts "ERROR: #{fqdn} isn't running!"
174
+ exit
175
+ else
176
+ connection = Stack.connect(config)
177
+ pp running_instances[fqdn]
178
+ running_instances[fqdn].destroy
179
+ end
180
+ end
181
+
182
+ def Stack.show_details(config)
183
+ # create a connection
184
+ connection = Stack.connect(config)
185
+
186
+ pp connection.describe_regions
187
+ pp connection.describe_availability_zones
188
+
189
+ pp connection.servers
190
+
191
+ Stack.populate_config(config)
192
+ pp config[:node_details]
193
+ end
194
+
195
+ def upload_keys(config)
196
+ if (key_pair = connection.key_pairs.get(config[:keypair]).nil?)
197
+ key_pair = connection.key_pairs.create( :name => config[:keypair], :public_key => File.read("rentpro-deploy.pub") )
198
+ else
199
+ puts "#{config[:keypair]} key_pair already exists"
200
+ end
201
+ end
202
+
203
+ def shutdown_all(config)
204
+ # shutdown all instances
205
+ connection.servers.select do |server|
206
+ puts "Running server:"
207
+ # pp server
208
+ # server.ready? && server.destroy
209
+ end
210
+ end
211
+
212
+ end
@@ -0,0 +1,7 @@
1
+ require 'test/unit'
2
+
3
+ class TestSomething < Test::Unit::TestCase
4
+ def test_truth
5
+ assert true
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stack-kicker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Simon McCartney
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: aruba
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: methadone
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.2.4
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.2.4
78
+ - !ruby/object:Gem::Dependency
79
+ name: fog
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.7.0
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.7.0
94
+ description: Utility for kicking an application stack into life on Amazon EC2
95
+ email:
96
+ - simon@mccartney.ie
97
+ executables:
98
+ - kicker
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - Gemfile
104
+ - LICENSE.txt
105
+ - README.md
106
+ - README.rdoc
107
+ - Rakefile
108
+ - bin/kicker
109
+ - features/kicker.feature
110
+ - features/step_definitions/kicker_steps.rb
111
+ - features/support/env.rb
112
+ - kicker.gemspec
113
+ - lib/kicker.rb
114
+ - lib/kicker/version.rb
115
+ - lib/stack.rb
116
+ - test/tc_something.rb
117
+ homepage: https://github.com/simonmcc/kicker
118
+ licenses: []
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 1.8.24
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: ! 'Stacks are built from a collection of instances required to build an application
141
+ stack. Each instance is described in the Stackfile & provisioned using variety
142
+ of methods. Supported models include: EC2 Create with user-data, cloud-init from
143
+ user-data (installs masterless puppet), puppet provision the instance. Other models
144
+ could include using a puppet master, Chef Solo or Chef Server/Hosted. Amazon EC2
145
+ interaction is done through fog, so other providers should be easily added. The
146
+ guiding principle is that your Stackfile should be shareable & re-useable by others,
147
+ and support templates, so that other users can use the template and easily adjust
148
+ items in the stack (such as the instance size used, DNS Domain updated during deploy,
149
+ EC2 account & location)'
150
+ test_files:
151
+ - features/kicker.feature
152
+ - features/step_definitions/kicker_steps.rb
153
+ - features/support/env.rb
154
+ - test/tc_something.rb