aws-kicker 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +62 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/README.rdoc +19 -0
- data/Rakefile +61 -0
- data/aws-kicker.gemspec +32 -0
- data/bin/aws-kicker +79 -0
- data/features/kicker.feature +13 -0
- data/features/step_definitions/kicker_steps.rb +1 -0
- data/features/support/env.rb +16 -0
- data/lib/kicker/version.rb +3 -0
- data/lib/kicker.rb +5 -0
- data/lib/stack.rb +215 -0
- data/test/tc_something.rb +7 -0
- metadata +155 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
aws-kicker (0.0.2)
|
5
|
+
fog (~> 1.7.0)
|
6
|
+
methadone (~> 1.2.4)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
aruba (0.5.1)
|
12
|
+
childprocess (~> 0.3.6)
|
13
|
+
cucumber (>= 1.1.1)
|
14
|
+
rspec-expectations (>= 2.7.0)
|
15
|
+
builder (3.1.4)
|
16
|
+
childprocess (0.3.7)
|
17
|
+
ffi (~> 1.0, >= 1.0.6)
|
18
|
+
cucumber (1.2.1)
|
19
|
+
builder (>= 2.1.2)
|
20
|
+
diff-lcs (>= 1.1.3)
|
21
|
+
gherkin (~> 2.11.0)
|
22
|
+
json (>= 1.4.6)
|
23
|
+
diff-lcs (1.1.3)
|
24
|
+
excon (0.16.10)
|
25
|
+
ffi (1.3.1)
|
26
|
+
fog (1.7.0)
|
27
|
+
builder
|
28
|
+
excon (~> 0.14)
|
29
|
+
formatador (~> 0.2.0)
|
30
|
+
mime-types
|
31
|
+
multi_json (~> 1.0)
|
32
|
+
net-scp (~> 1.0.4)
|
33
|
+
net-ssh (>= 2.1.3)
|
34
|
+
nokogiri (~> 1.5.0)
|
35
|
+
ruby-hmac
|
36
|
+
formatador (0.2.4)
|
37
|
+
gherkin (2.11.6)
|
38
|
+
json (>= 1.7.6)
|
39
|
+
json (1.7.6)
|
40
|
+
methadone (1.2.4)
|
41
|
+
bundler
|
42
|
+
mime-types (1.19)
|
43
|
+
multi_json (1.3.7)
|
44
|
+
net-scp (1.0.4)
|
45
|
+
net-ssh (>= 1.99.1)
|
46
|
+
net-ssh (2.2.2)
|
47
|
+
nokogiri (1.5.5)
|
48
|
+
rake (0.9.6)
|
49
|
+
rdoc (3.12)
|
50
|
+
json (~> 1.4)
|
51
|
+
rspec-expectations (2.12.1)
|
52
|
+
diff-lcs (~> 1.1.3)
|
53
|
+
ruby-hmac (0.4.0)
|
54
|
+
|
55
|
+
PLATFORMS
|
56
|
+
ruby
|
57
|
+
|
58
|
+
DEPENDENCIES
|
59
|
+
aruba
|
60
|
+
aws-kicker!
|
61
|
+
rake (~> 0.9.2)
|
62
|
+
rdoc
|
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/aws-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 = "aws-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
|
data/bin/aws-kicker
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "rubygems"
|
3
|
+
require "bundler/setup"
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'methadone'
|
7
|
+
require 'kicker'
|
8
|
+
require 'stack'
|
9
|
+
|
10
|
+
class App
|
11
|
+
include Methadone::Main
|
12
|
+
include Methadone::CLILogging
|
13
|
+
|
14
|
+
main do |stack|
|
15
|
+
config = Stack.load_config(options['configfile'], stack)
|
16
|
+
if config.nil?
|
17
|
+
exit_now!("#{stack} doesn't exist in #{options['configfile']}")
|
18
|
+
end
|
19
|
+
|
20
|
+
if options['show-stack']
|
21
|
+
puts stack
|
22
|
+
hostnames = Stack.generate_hostnames(config)
|
23
|
+
hostnames.each { |hostname| puts " #{hostname}" }
|
24
|
+
end
|
25
|
+
|
26
|
+
if options['show-running']
|
27
|
+
Stack.show_running(config)
|
28
|
+
end
|
29
|
+
|
30
|
+
if options['show-dns']
|
31
|
+
Stack.show_dns(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
if options['show-details']
|
35
|
+
Stack.show_details(config)
|
36
|
+
end
|
37
|
+
|
38
|
+
if options['deploy-all']
|
39
|
+
Stack.deploy_all(config)
|
40
|
+
end
|
41
|
+
|
42
|
+
if options['delete-node']
|
43
|
+
info { "delete-node passed #{options['delete-node']}" }
|
44
|
+
Stack.delete_node(config, options['delete-node'])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# supplemental methods here
|
49
|
+
|
50
|
+
# Declare command-line interface here
|
51
|
+
|
52
|
+
description "Deploy your stack to the cloud"
|
53
|
+
#
|
54
|
+
# Accept flags via:
|
55
|
+
# on("--flag VAL","Some flag")
|
56
|
+
# on("--flag VAL","Some flag")
|
57
|
+
# options[flag] will contain VAL
|
58
|
+
#
|
59
|
+
# Specify switches via:
|
60
|
+
# on("--[no-]switch","Some switch")
|
61
|
+
|
62
|
+
arg :stack
|
63
|
+
options['configfile'] = 'Stackfile'
|
64
|
+
on("--configfile configfile", "Specify an alternative to ./Stackfile")
|
65
|
+
on("--show-stack", "Show the nodes defined in a stack")
|
66
|
+
on("--show-details", "Show the nodes defined in a stack in detail")
|
67
|
+
on("--show-running", "Show the running nodes")
|
68
|
+
on("--show-dns", "Show the current DNS config")
|
69
|
+
on("--deploy-all", "Deploy the stack, skipping existing nodes")
|
70
|
+
on("--replace-node NODE", "Replace a give node")
|
71
|
+
on("--delete-node NODE", "Destroy a node, including any shared CM & DNS")
|
72
|
+
on("--validate", "Validate the config, check as much as possible with out creating nodes")
|
73
|
+
|
74
|
+
version Kicker::VERSION
|
75
|
+
|
76
|
+
use_log_level_option
|
77
|
+
|
78
|
+
go!
|
79
|
+
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/lib/kicker.rb
ADDED
data/lib/stack.rb
ADDED
@@ -0,0 +1,215 @@
|
|
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
|
+
# generate the hostnames & details from the config & apply defaults where required
|
51
|
+
Stack.populate_config(config)
|
52
|
+
|
53
|
+
# create a connection
|
54
|
+
connection = Stack.connect(config)
|
55
|
+
|
56
|
+
running_instances = Stack.get_running(config)
|
57
|
+
config[:roles].each do |role, role_details|
|
58
|
+
hostname = role.to_s
|
59
|
+
fqdn = role.to_s + '.' + config[:dns_domain]
|
60
|
+
|
61
|
+
if !running_instances[fqdn].nil?
|
62
|
+
puts "Skipping #{fqdn} as it already exists"
|
63
|
+
next
|
64
|
+
end
|
65
|
+
|
66
|
+
# Ubuntu 8.04/Hardy doesn't do full cloud-init, so we have to script setting the hostname
|
67
|
+
user_data = File.read('user-data.sh')
|
68
|
+
user_data.gsub!(/rentpro-unconfigured/, hostname)
|
69
|
+
user_data.gsub!(/rentpro-stage.local/, config[:dns_domain])
|
70
|
+
|
71
|
+
# pp multipart
|
72
|
+
#
|
73
|
+
puts "Bootstraping new instance - #{fqdn}, in #{config[:availability_zone]}"
|
74
|
+
server = connection.servers.create({
|
75
|
+
:name => fqdn,
|
76
|
+
:hostname => fqdn,
|
77
|
+
:availability_zone => config[:availability_zone],
|
78
|
+
:flavor_id => config[:node_details][fqdn][:flavor_id],
|
79
|
+
:image_id => config[:image_id],
|
80
|
+
:key_name => config[:keypair],
|
81
|
+
:user_data => user_data,
|
82
|
+
:tags => { 'Name' => fqdn },
|
83
|
+
})
|
84
|
+
|
85
|
+
print "Waiting for instance to be ready..."
|
86
|
+
server.wait_for { ready? }
|
87
|
+
puts "#{role.to_s} is booted, #{server.public_ip_address}/#{server.private_ip_address}"
|
88
|
+
|
89
|
+
# create/update the public & private DNS for this host
|
90
|
+
Stack.update_dns(role.to_s + '-public.' + config[:dns_domain], server.public_ip_address, config)
|
91
|
+
Stack.update_dns(role.to_s + '-private.' + config[:dns_domain], server.private_ip_address, config)
|
92
|
+
|
93
|
+
# create the dns
|
94
|
+
if (role_details[:publish_private_ip] == true && (!role_details[:publish_private_ip].nil?))
|
95
|
+
ip_address = server.private_ip_address
|
96
|
+
else
|
97
|
+
ip_address = server.public_ip_address
|
98
|
+
end
|
99
|
+
Stack.update_dns(fqdn, ip_address, config)
|
100
|
+
#
|
101
|
+
# is this a wildcard DNS host, then claim the *.domain.net
|
102
|
+
if (role_details[:dns_wildcard] == true && (!role_details[:dns_wildcard].nil?))
|
103
|
+
wildcard = "*." + config[:dns_domain]
|
104
|
+
Stack.update_dns(wildcard, ip_address, config)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def Stack.update_dns(fqdn, ip_address, config)
|
110
|
+
# now register it in DNS
|
111
|
+
dns = Fog::DNS.new({ :provider => config[:provider],
|
112
|
+
:aws_access_key_id => config[:aws_access_key_id],
|
113
|
+
:aws_secret_access_key => config[:aws_secret_access_key] })
|
114
|
+
|
115
|
+
# pp dns.get_hosted_zone(config[:dns_id])
|
116
|
+
|
117
|
+
bmtw = dns.zones.get(config[:dns_id])
|
118
|
+
|
119
|
+
record = bmtw.records.get(fqdn)
|
120
|
+
if record
|
121
|
+
record.modify(:value => ip_address) if record
|
122
|
+
else
|
123
|
+
bmtw.records.create(:value => ip_address, :name => fqdn, :type => 'A')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def Stack.show_dns(config)
|
128
|
+
# now register it in DNS
|
129
|
+
dns = Fog::DNS.new({ :provider => config[:provider],
|
130
|
+
:aws_access_key_id => config[:aws_access_key_id],
|
131
|
+
:aws_secret_access_key => config[:aws_secret_access_key] })
|
132
|
+
|
133
|
+
zone = dns.zones.get(config[:dns_id])
|
134
|
+
if zone.records.empty?
|
135
|
+
puts "No DNS records found in #{config[:dns_domain]}"
|
136
|
+
else
|
137
|
+
printf("%40s %20s %5s %5s\n", 'fqdn', 'value', 'type', 'ttl')
|
138
|
+
zone.records.each do |record|
|
139
|
+
printf("%40s %20s %5s %5d\n", record.name, record.value, record.type, record.ttl)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def Stack.get_running(config)
|
145
|
+
# create a connection
|
146
|
+
connection = Stack.connect(config)
|
147
|
+
|
148
|
+
# generate all the names that this stack will use
|
149
|
+
stack_hostnames = Stack.generate_hostnames(config)
|
150
|
+
|
151
|
+
# Amazon EC2, use the tags hash to find hostnames
|
152
|
+
running_instances = Hash.new
|
153
|
+
connection.servers.each do |instance|
|
154
|
+
# pp instance
|
155
|
+
if (!instance.tags['Name'].nil? && instance.state != 'terminated' && instance.state != 'shutting-down')
|
156
|
+
hostname = instance.tags['Name']
|
157
|
+
if stack_hostnames.include?(hostname)
|
158
|
+
running_instances[hostname] = instance
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
running_instances
|
163
|
+
end
|
164
|
+
|
165
|
+
def Stack.show_running(config)
|
166
|
+
running_instances = Stack.get_running(config)
|
167
|
+
running_instances.each do |instance, instance_details|
|
168
|
+
# display some details
|
169
|
+
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}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def Stack.delete_node(config, fqdn)
|
174
|
+
running_instances = Stack.get_running(config)
|
175
|
+
if running_instances[fqdn].nil?
|
176
|
+
puts "ERROR: #{fqdn} isn't running!"
|
177
|
+
exit
|
178
|
+
else
|
179
|
+
connection = Stack.connect(config)
|
180
|
+
pp running_instances[fqdn]
|
181
|
+
running_instances[fqdn].destroy
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def Stack.show_details(config)
|
186
|
+
# create a connection
|
187
|
+
connection = Stack.connect(config)
|
188
|
+
|
189
|
+
pp connection.describe_regions
|
190
|
+
pp connection.describe_availability_zones
|
191
|
+
|
192
|
+
pp connection.servers
|
193
|
+
|
194
|
+
Stack.populate_config(config)
|
195
|
+
pp config[:node_details]
|
196
|
+
end
|
197
|
+
|
198
|
+
def upload_keys(config)
|
199
|
+
if (key_pair = connection.key_pairs.get(config[:keypair]).nil?)
|
200
|
+
key_pair = connection.key_pairs.create( :name => config[:keypair], :public_key => File.read("rentpro-deploy.pub") )
|
201
|
+
else
|
202
|
+
puts "#{config[:keypair]} key_pair already exists"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def shutdown_all(config)
|
207
|
+
# shutdown all instances
|
208
|
+
connection.servers.select do |server|
|
209
|
+
puts "Running server:"
|
210
|
+
# pp server
|
211
|
+
# server.ready? && server.destroy
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aws-kicker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Simon McCartney
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-21 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
|
+
- aws-kicker
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- Gemfile
|
104
|
+
- Gemfile.lock
|
105
|
+
- LICENSE.txt
|
106
|
+
- README.md
|
107
|
+
- README.rdoc
|
108
|
+
- Rakefile
|
109
|
+
- aws-kicker.gemspec
|
110
|
+
- bin/aws-kicker
|
111
|
+
- features/kicker.feature
|
112
|
+
- features/step_definitions/kicker_steps.rb
|
113
|
+
- features/support/env.rb
|
114
|
+
- lib/kicker.rb
|
115
|
+
- lib/kicker/version.rb
|
116
|
+
- lib/stack.rb
|
117
|
+
- test/tc_something.rb
|
118
|
+
homepage: https://github.com/simonmcc/kicker
|
119
|
+
licenses: []
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ! '>='
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 1.8.24
|
139
|
+
signing_key:
|
140
|
+
specification_version: 3
|
141
|
+
summary: ! 'Stacks are built from a collection of instances required to build an application
|
142
|
+
stack. Each instance is described in the Stackfile & provisioned using variety
|
143
|
+
of methods. Supported models include: EC2 Create with user-data, cloud-init from
|
144
|
+
user-data (installs masterless puppet), puppet provision the instance. Other models
|
145
|
+
could include using a puppet master, Chef Solo or Chef Server/Hosted. Amazon EC2
|
146
|
+
interaction is done through fog, so other providers should be easily added. The
|
147
|
+
guiding principle is that your Stackfile should be shareable & re-useable by others,
|
148
|
+
and support templates, so that other users can use the template and easily adjust
|
149
|
+
items in the stack (such as the instance size used, DNS Domain updated during deploy,
|
150
|
+
EC2 account & location)'
|
151
|
+
test_files:
|
152
|
+
- features/kicker.feature
|
153
|
+
- features/step_definitions/kicker_steps.rb
|
154
|
+
- features/support/env.rb
|
155
|
+
- test/tc_something.rb
|