gaptool 0.10.9 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/bin/gt +2 -1
- data/gaptool.gemspec +2 -1
- data/lib/app.rb +77 -39
- data/lib/plugins/Base/config.yml +42 -21
- data/lib/plugins/Base/plugin.rb +83 -141
- metadata +27 -16
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/bin/gt
CHANGED
@@ -4,11 +4,12 @@ require 'rubygems'
|
|
4
4
|
require 'net/ssh'
|
5
5
|
require 'trollop'
|
6
6
|
require 'yaml'
|
7
|
-
require 'aws'
|
7
|
+
require 'aws-sdk'
|
8
8
|
require 'json'
|
9
9
|
require 'peach'
|
10
10
|
require 'erb'
|
11
11
|
require 'rainbow'
|
12
|
+
require 'crack'
|
12
13
|
require File.expand_path(File.dirname(__FILE__) + "/../lib/app.rb")
|
13
14
|
|
14
15
|
# Make sure lang isn't fucked
|
data/gaptool.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "gaptool"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.11.0"
|
4
4
|
s.authors = ['Matt Bailey']
|
5
5
|
s.email = ['m@mdb.io']
|
6
6
|
s.homepage = 'http://mdb.io'
|
@@ -16,5 +16,6 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.add_dependency "json"
|
17
17
|
s.add_dependency "peach"
|
18
18
|
s.add_dependency "rainbow"
|
19
|
+
s.add_dependency "crack"
|
19
20
|
end
|
20
21
|
|
data/lib/app.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
def setup
|
2
2
|
yaml = Hash.new
|
3
|
-
unless File.directory?("#{ENV['HOME']}/.gaptool") || File.exists?("#{ENV['HOME']}/.gaptool")
|
4
|
-
puts "Welcome to gaptool setup\nThis will set up your ~/.gaptool configuration\nYou will need very little info here if you are NOT creating new nodes (e.g. just configuring and deploying)\nIf you ARE using the the 'init' facility, you will need your AWS ID, Secret, and EC2 PEM keys for relevant Availability Zones.".color(:red)
|
3
|
+
unless File.directory?("#{ENV['HOME']}/.gaptool-ma") || File.exists?("#{ENV['HOME']}/.gaptool-ma")
|
4
|
+
puts "Welcome to gaptool setup\nThis will set up your ~/.gaptool-ma configuration\nYou will need very little info here if you are NOT creating new nodes (e.g. just configuring and deploying)\nIf you ARE using the the 'init' facility, you will need your AWS ID, Secret, and EC2 PEM keys for relevant Availability Zones.".color(:red)
|
5
5
|
puts "Starting with your AWS ID/Secret.\nIf you don't have these, just press enter.".color(:cyan)
|
6
6
|
print "Enter your AWS ID: "
|
7
7
|
yaml['aws_id'] = gets.chomp
|
@@ -24,11 +24,11 @@ def setup
|
|
24
24
|
data = [ key.to_blob ].pack('m0')
|
25
25
|
yaml['mykey'] = key.to_pem
|
26
26
|
yaml['mypub'] = "#{type} #{data}"
|
27
|
-
Dir.mkdir("#{ENV['HOME']}/.gaptool")
|
28
|
-
Dir.mkdir("#{ENV['HOME']}/.gaptool/plugins")
|
29
|
-
File.open("#{ENV['HOME']}/.gaptool/plugins.yml", "w") {}
|
30
|
-
File.open(File.expand_path("~/.gaptool/user.yml"), 'w') {|f| f.write(yaml.to_yaml) }
|
31
|
-
puts "Your ~/.gaptool directory and user.yml have been configured\nPlease ask your administrator to provide you with a env.yml\nAdd the following public key to your github profile (or your git repo server)\nas well as in the authorized_keys file in your chef recipe for the admin user.".color(:cyan)
|
27
|
+
Dir.mkdir("#{ENV['HOME']}/.gaptool-ma")
|
28
|
+
Dir.mkdir("#{ENV['HOME']}/.gaptool-ma/plugins")
|
29
|
+
File.open("#{ENV['HOME']}/.gaptool-ma/plugins.yml", "w") {}
|
30
|
+
File.open(File.expand_path("~/.gaptool-ma/user.yml"), 'w') {|f| f.write(yaml.to_yaml) }
|
31
|
+
puts "Your ~/.gaptool-ma directory and user.yml have been configured\nPlease ask your administrator to provide you with a env.yml\nAdd the following public key to your github profile (or your git repo server)\nas well as in the authorized_keys file in your chef recipe for the admin user.".color(:cyan)
|
32
32
|
puts yaml['mypub']
|
33
33
|
exit 0
|
34
34
|
end
|
@@ -36,18 +36,19 @@ end
|
|
36
36
|
setup()
|
37
37
|
|
38
38
|
$dist_plugins = [ 'Base' ]
|
39
|
-
if YAML::load(File.open("#{ENV['HOME']}/.gaptool/plugins.yml"))
|
40
|
-
$plugins = $dist_plugins + YAML::load(File.open("#{ENV['HOME']}/.gaptool/plugins.yml"))
|
39
|
+
if YAML::load(File.open("#{ENV['HOME']}/.gaptool-ma/plugins.yml"))
|
40
|
+
$plugins = $dist_plugins + YAML::load(File.open("#{ENV['HOME']}/.gaptool-ma/plugins.yml"))
|
41
41
|
else
|
42
42
|
$plugins = $dist_plugins
|
43
43
|
end
|
44
44
|
|
45
45
|
$commands = Hash.new
|
46
|
+
$c = Array.new
|
46
47
|
$plugins.each do |plugin|
|
47
48
|
if $dist_plugins.include? plugin
|
48
49
|
$commands.merge!(YAML::load(File.open(File.expand_path(File.dirname(__FILE__) + "/plugins/#{plugin}/config.yml"))))
|
49
50
|
else
|
50
|
-
$commands.merge!(YAML::load(File.open("#{ENV['HOME']}/.gaptool/plugins/#{plugin.to_s}/config.yml")))
|
51
|
+
$commands.merge!(YAML::load(File.open("#{ENV['HOME']}/.gaptool-ma/plugins/#{plugin.to_s}/config.yml")))
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
@@ -69,24 +70,18 @@ else
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
72
|
-
|
73
73
|
class GTBase
|
74
74
|
def isCluster?
|
75
|
-
|
76
|
-
return true
|
77
|
-
else
|
78
|
-
return false
|
79
|
-
end
|
75
|
+
return false
|
80
76
|
end
|
81
77
|
def getCluster
|
82
78
|
hosts = Array.new
|
83
|
-
if
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
else
|
88
|
-
hosts << "#{@args[:app]}-#{@args[:environment]}.#{@env_settings['domain']}"
|
79
|
+
if @args[:role]
|
80
|
+
nodes = $c.select {|f| f[:role] == @args[:role] }.select {|i| i[:environment] == @args[:environment]}
|
81
|
+
elsif @args[:app]
|
82
|
+
nodes = $c.select {|i| i[:environment] == @args[:environment]}.select {|f| f[:apps].include? @args[:app]}
|
89
83
|
end
|
84
|
+
nodes.each {|f| hosts += [f[:hostname]]}
|
90
85
|
return hosts
|
91
86
|
end
|
92
87
|
def sshcmd(host, commands, options = {})
|
@@ -101,6 +96,7 @@ class GTBase
|
|
101
96
|
key = @user_settings['mykey']
|
102
97
|
end
|
103
98
|
Net::SSH.start(host, user, :key_data => [key], :config => false, :keys_only => true, :paranoid => false) do |ssh|
|
99
|
+
ENV['SSH_AUTH_SOCK'] = ''
|
104
100
|
commands.each do |command|
|
105
101
|
if !options[:quiet]
|
106
102
|
puts command.color(:cyan)
|
@@ -149,35 +145,79 @@ class GTBase
|
|
149
145
|
return true
|
150
146
|
end
|
151
147
|
def singleHost
|
152
|
-
|
153
|
-
puts "The environment you're accessing is a cluster.\nYou've selected an action that acts only on a single node, but have not specified a node with --node/-n\nAborting."
|
154
|
-
exit 100
|
155
|
-
end
|
156
|
-
if isCluster?
|
157
|
-
return "#{@args[:app]}-#{@args[:environment]}-#{@args[:node]}.#{@env_settings['domain']}"
|
158
|
-
else
|
159
|
-
return "#{@args[:app]}-#{@args[:environment]}.#{@env_settings['domain']}"
|
160
|
-
end
|
148
|
+
return "#{@args[:role]}-#{@args[:environment]}-#{@args[:number]}.#{@env_settings['domain']}"
|
161
149
|
end
|
162
150
|
def initialize(args)
|
163
151
|
@args = args
|
164
152
|
if ENV['GT_ENV_SETTINGS']
|
165
153
|
@env_settings = YAML::load(File.open(File.expand_path(ENV['GT_ENV_CONFIG'])))
|
166
154
|
else
|
167
|
-
@env_settings = YAML::load(File.open(File.expand_path("#{ENV['HOME']}/.gaptool/env.yml")))
|
155
|
+
@env_settings = YAML::load(File.open(File.expand_path("#{ENV['HOME']}/.gaptool-ma/env.yml")))
|
168
156
|
end
|
169
157
|
if ENV['GT_USER_SETTINGS']
|
170
158
|
@user_settings = YAML::load(File.open(File.expand_path(ENV['GT_USER_CONFIG'])))
|
171
159
|
else
|
172
|
-
@user_settings = YAML::load(File.open(File.expand_path("#{ENV['HOME']}/.gaptool/user.yml")))
|
160
|
+
@user_settings = YAML::load(File.open(File.expand_path("#{ENV['HOME']}/.gaptool-ma/user.yml")))
|
173
161
|
end
|
174
162
|
chef_extra = {
|
175
163
|
'rails_env' => @args[:environment],
|
176
|
-
'server_names' => getCluster()
|
177
164
|
}
|
178
|
-
@chefsettings = @
|
179
|
-
@chefsettings.merge!(@args)
|
165
|
+
@chefsettings = @args
|
180
166
|
@chefsettings.merge!(chef_extra)
|
167
|
+
if @args[:zone].to_s == ''
|
168
|
+
zone = @env_settings['default_zone']
|
169
|
+
else
|
170
|
+
zone = @args[:zone]
|
171
|
+
end
|
172
|
+
az = zone.chop
|
173
|
+
AWS.config(:access_key_id => @user_settings['aws_id'], :secret_access_key => @user_settings['aws_secret'], :ec2_endpoint => "ec2.#{az}.amazonaws.com")
|
174
|
+
@ec2 = AWS::EC2.new
|
175
|
+
def cgen
|
176
|
+
c = Array.new
|
177
|
+
tags = @ec2.instances.inject({}) { |m, i| m[i.id] = i.tags.to_h; m }
|
178
|
+
tags.keys.each do |key|
|
179
|
+
if tags[key]['gaptool'] != nil
|
180
|
+
gaptags = eval(tags[key]['gaptool'])
|
181
|
+
hostname = "#{gaptags[:role]}-#{gaptags[:environment]}-#{gaptags[:number]}.#{@env_settings['domain']}"
|
182
|
+
c += [{
|
183
|
+
:hostname => hostname,
|
184
|
+
:recipe => gaptags[:recipe],
|
185
|
+
:deploy => gaptags[:deploy],
|
186
|
+
:number => gaptags[:number],
|
187
|
+
:role => gaptags[:role],
|
188
|
+
:environment => gaptags[:environment],
|
189
|
+
:apps => eval(gaptags[:apps])
|
190
|
+
}]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
return c
|
194
|
+
end
|
195
|
+
if File.exists?("#{ENV['HOME']}/.gaptool-ma/aws.yml")
|
196
|
+
$c = YAML::load(File.open(File.expand_path("#{ENV['HOME']}/.gaptool-ma/aws.yml")))
|
197
|
+
else
|
198
|
+
$c = cgen()
|
199
|
+
end
|
200
|
+
cwrite = fork do
|
201
|
+
File.open(File.expand_path("#{ENV['HOME']}/.gaptool-ma/aws.yml"), 'w') {|f| f.write(cgen().to_yaml)}
|
202
|
+
end
|
203
|
+
Process.detach(cwrite)
|
204
|
+
end
|
205
|
+
def recipeRun(host, run_list, settings={})
|
206
|
+
host_settings = {
|
207
|
+
'this_server' => host,
|
208
|
+
'run_list' => [ "recipe[#{run_list}]" ],
|
209
|
+
'app_user' => @env_settings['user'],
|
210
|
+
}
|
211
|
+
@chefsettings.merge!(host_settings)
|
212
|
+
@chefsettings.merge!(settings)
|
213
|
+
@chefsettings.merge!($c.select {|f| f[:hostname] == host}.first)
|
214
|
+
run = [
|
215
|
+
"cd ~admin/ops; git pull",
|
216
|
+
"echo '#{@chefsettings.to_json}' > ~admin/solo.json",
|
217
|
+
"sudo chef-solo -c ~admin/ops/cookbooks/solo.rb -j ~admin/solo.json"
|
218
|
+
]
|
219
|
+
putkey(host)
|
220
|
+
sshcmd(host, run)
|
181
221
|
end
|
182
222
|
end
|
183
223
|
|
@@ -186,13 +226,11 @@ class GTCluster < GTBase
|
|
186
226
|
if $dist_plugins.include?(plugin)
|
187
227
|
require File.expand_path(File.dirname(__FILE__) + "/plugins/#{plugin}/plugin.rb")
|
188
228
|
else
|
189
|
-
require File.expand_path(ENV['HOME'] + "/.gaptool/plugins/#{plugin}/plugin.rb")
|
229
|
+
require File.expand_path(ENV['HOME'] + "/.gaptool-ma/plugins/#{plugin}/plugin.rb")
|
190
230
|
end
|
191
231
|
include Object.const_get(plugin)
|
192
232
|
end
|
193
233
|
end
|
194
234
|
|
195
|
-
|
196
|
-
|
197
235
|
cluster = GTCluster.new(cmd_opts)
|
198
236
|
cluster.send cmd
|
data/lib/plugins/Base/config.yml
CHANGED
@@ -7,14 +7,34 @@ default: &withoutnode
|
|
7
7
|
environment:
|
8
8
|
short: -e
|
9
9
|
type: string
|
10
|
-
help:
|
10
|
+
help: environment, e.g. staging
|
11
11
|
default: nil
|
12
12
|
chefrun:
|
13
|
-
|
14
|
-
recipe:
|
13
|
+
role:
|
15
14
|
short: -r
|
16
|
-
|
15
|
+
type: string
|
16
|
+
help: server role, e.g. app
|
17
|
+
default: nil
|
18
|
+
environment:
|
19
|
+
short: -e
|
20
|
+
type: string
|
21
|
+
help: environment, e.g. staging
|
22
|
+
default: nil
|
23
|
+
recipe:
|
24
|
+
short: -c
|
25
|
+
help: specific recipe, default is main
|
26
|
+
default: main
|
27
|
+
add:
|
28
|
+
template:
|
29
|
+
short: -t
|
30
|
+
type: string
|
31
|
+
help: template file for adding server
|
17
32
|
default: nil
|
33
|
+
zone:
|
34
|
+
short: -z
|
35
|
+
type: string
|
36
|
+
help: availability zone to start the new server in, default is us-east-1d
|
37
|
+
default: us-east-1d
|
18
38
|
scpto: &node
|
19
39
|
<< : *withoutnode
|
20
40
|
node:
|
@@ -25,14 +45,28 @@ scpto: &node
|
|
25
45
|
scpfrom:
|
26
46
|
<< : *node
|
27
47
|
ssh:
|
28
|
-
|
48
|
+
role:
|
49
|
+
short: -r
|
50
|
+
type: string
|
51
|
+
help: server role, e.g. app
|
52
|
+
default: nil
|
53
|
+
environment:
|
54
|
+
short: -e
|
55
|
+
type: string
|
56
|
+
help: environment, e.g. staging
|
57
|
+
default: nil
|
58
|
+
number:
|
59
|
+
short: -n
|
60
|
+
type: string
|
61
|
+
help: node number, e.g. 1
|
62
|
+
default: nil
|
29
63
|
deploy:
|
30
64
|
<< : *withoutnode
|
31
65
|
migrate:
|
32
66
|
short: -m
|
33
67
|
help: "Toggle migrations, default off"
|
34
68
|
defaut: nil
|
35
|
-
branch:
|
69
|
+
branch:
|
36
70
|
short: -r
|
37
71
|
help: "Choose git branch, default defined in your gt_env.yml"
|
38
72
|
type: string
|
@@ -43,24 +77,12 @@ rollback:
|
|
43
77
|
short: -m
|
44
78
|
help: "Toggle migrations, default off"
|
45
79
|
defaut: nil
|
46
|
-
branch:
|
80
|
+
branch:
|
47
81
|
short: -r
|
48
82
|
help: "Choose git branch, default defined in your gt_env.yml"
|
49
83
|
type: string
|
50
84
|
default: nil
|
51
|
-
|
52
|
-
<< : *node
|
53
|
-
zone:
|
54
|
-
short: -z
|
55
|
-
help: "availability zone to deploy in, default in your gt_env.yml"
|
56
|
-
type: string
|
57
|
-
default: nil
|
58
|
-
arch:
|
59
|
-
short: -r
|
60
|
-
help: "CPU architecture, currently i686 or x86_64"
|
61
|
-
type: string
|
62
|
-
default: nil
|
63
|
-
web:
|
85
|
+
toggle:
|
64
86
|
<< : *withoutnode
|
65
87
|
enable:
|
66
88
|
short: -n
|
@@ -79,4 +101,3 @@ log:
|
|
79
101
|
help: "Log type, as defined in the plugin's log.yml"
|
80
102
|
type: string
|
81
103
|
default: nil
|
82
|
-
|
data/lib/plugins/Base/plugin.rb
CHANGED
@@ -29,26 +29,10 @@ module Base
|
|
29
29
|
end
|
30
30
|
def chefrun
|
31
31
|
if sshReachable?
|
32
|
+
run_list = $c.detect{|f| f[:role] == @args[:role] }[:recipe] || @args[:recipe]
|
32
33
|
hosts = getCluster()
|
33
|
-
run_list = @chefsettings['normal_recipe']
|
34
|
-
unless eval(@args[:recipe]).nil?
|
35
|
-
run_list = @args[:recipe]
|
36
|
-
end
|
37
34
|
hosts.peach do |host|
|
38
|
-
|
39
|
-
'this_server' => host,
|
40
|
-
'run_list' => [ "recipe[#{run_list}]" ],
|
41
|
-
'app_user' => @env_settings['user'],
|
42
|
-
'app_name' => @args[:app]
|
43
|
-
}
|
44
|
-
json = @chefsettings.merge!(host_settings).to_json
|
45
|
-
run = [
|
46
|
-
"cd ~admin/ops; git pull",
|
47
|
-
"echo '#{json}' > ~admin/solo.json",
|
48
|
-
"sudo chef-solo -c ~admin/ops/cookbooks/solo.rb -j ~admin/solo.json"
|
49
|
-
]
|
50
|
-
putkey(host)
|
51
|
-
sshcmd(host, run)
|
35
|
+
recipeRun(host, run_list)
|
52
36
|
end
|
53
37
|
end
|
54
38
|
end
|
@@ -72,156 +56,114 @@ module Base
|
|
72
56
|
end
|
73
57
|
def deploy
|
74
58
|
if sshReachable?
|
75
|
-
if @args[:branch] == "nil" || @args[:branch].nil?
|
76
|
-
branch = @env_settings['applications'][@args[:app]][@args[:environment]]['default_branch']
|
77
|
-
else
|
78
|
-
branch = @args[:branch]
|
79
|
-
end
|
80
59
|
hosts = getCluster()
|
81
60
|
hosts.peach do |host|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
'
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
61
|
+
begin
|
62
|
+
run_list = $apps[@args[:app]][:deploy]
|
63
|
+
rescue
|
64
|
+
run_list = 'deploy'
|
65
|
+
end
|
66
|
+
unless @args[:branch].to_s == 'nil'
|
67
|
+
@branch = @args[:branch]
|
68
|
+
end
|
69
|
+
@deploy_settings = {
|
70
|
+
'branch' => @branch,
|
71
|
+
'app_name' => @args[:app],
|
72
|
+
'rollback' => false
|
90
73
|
}
|
91
|
-
|
92
|
-
run = [
|
93
|
-
"cd ~admin/ops; git pull",
|
94
|
-
"echo '#{json}' > ~admin/solo.json",
|
95
|
-
"sudo chef-solo -c ~admin/ops/cookbooks/solo.rb -j ~admin/solo.json"
|
96
|
-
]
|
97
|
-
putkey(host)
|
98
|
-
sshcmd(host, run)
|
74
|
+
recipeRun(host, run_list, @deploy_settings)
|
99
75
|
end
|
100
76
|
end
|
101
77
|
end
|
102
78
|
def rollback
|
103
79
|
if sshReachable?
|
104
|
-
if @args[:branch] == "nil" || @args[:branch].nil?
|
105
|
-
branch = @env_settings['applications'][@args[:app]][@args[:environment]]['default_branch']
|
106
|
-
else
|
107
|
-
branch = @args[:branch]
|
108
|
-
end
|
109
80
|
hosts = getCluster()
|
110
81
|
hosts.peach do |host|
|
111
|
-
|
112
|
-
|
113
|
-
'
|
114
|
-
'
|
115
|
-
'branch' => branch,
|
116
|
-
'app_user' => @env_settings['user'],
|
117
|
-
'app_name' => @args[:app],
|
118
|
-
'rollback' => true
|
82
|
+
run_list = $c.detect{|f| f[:hostname] == host }[:deploy]
|
83
|
+
@deploy_settings = {
|
84
|
+
'app_name' => @args[:app],
|
85
|
+
'rollback' => true
|
119
86
|
}
|
120
|
-
|
121
|
-
run = [
|
122
|
-
"cd ~admin/ops; git pull",
|
123
|
-
"echo '#{json}' > ~admin/solo.json",
|
124
|
-
"sudo chef-solo -c ~admin/ops/cookbooks/solo.rb -j ~admin/solo.json"
|
125
|
-
]
|
126
|
-
putkey(host)
|
127
|
-
sshcmd(host, run)
|
87
|
+
recipeRun(host, run_list, @deploy_settings)
|
128
88
|
end
|
129
89
|
end
|
130
90
|
end
|
131
|
-
def
|
91
|
+
def toggle
|
132
92
|
if sshRachable?
|
133
93
|
hosts = getCluster()
|
134
94
|
if @args[:enable]
|
135
|
-
|
136
|
-
sshcmd(host, "sudo -u #{@env_settings['user']} rm /data/#{@args[:app]}/shared/system/maintenance.html 2> /dev/null", :quiet => true)
|
137
|
-
puts "#{host} : web enabled"
|
138
|
-
end
|
95
|
+
@settings = { 'toggle' => 'enable' }
|
139
96
|
end
|
140
97
|
if @args[:disable]
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
98
|
+
@settings = { 'toggle' => 'disable' }
|
99
|
+
end
|
100
|
+
hosts.peach do |host|
|
101
|
+
recipeRun(host, 'toggle', @deploy_settings)
|
145
102
|
end
|
146
103
|
end
|
147
104
|
end
|
148
|
-
def
|
149
|
-
|
150
|
-
zone = @env_settings['default_zone']
|
151
|
-
else
|
152
|
-
zone = @args[:zone]
|
153
|
-
end
|
154
|
-
az = zone.chop
|
155
|
-
if @args[:arch] == 'nil'
|
156
|
-
arch = @env_settings['default_arch']
|
157
|
-
else
|
158
|
-
arch = @args[:arch]
|
159
|
-
end
|
160
|
-
ami = @env_settings['amis'][az][arch]['id']
|
161
|
-
user = @env_settings['amis'][az][arch]['user']
|
162
|
-
if @args[:node] == 'solo' && isCluster?
|
163
|
-
hosts = getCluster()
|
164
|
-
end
|
165
|
-
if @args[:node] != 'solo' || !isCluster?
|
166
|
-
hosts = [ singleHost() ]
|
167
|
-
end
|
105
|
+
def add
|
106
|
+
$c = cgen()
|
168
107
|
begin
|
169
|
-
|
108
|
+
@initfile = YAML::load(File.open(@args[:template]))
|
170
109
|
rescue
|
171
|
-
puts "
|
172
|
-
exit 100
|
110
|
+
puts "Please input a valid yaml file for the template"
|
173
111
|
end
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
ec2 = AWS::EC2.new
|
180
|
-
hosts.peach do |host|
|
181
|
-
host_settings = {
|
182
|
-
'this_server' => host,
|
183
|
-
'run_list' => [ "recipe[#{@chefsettings['init_recipe']}]" ],
|
184
|
-
'do_migrate' => @args[:migrate],
|
185
|
-
'branch' => @args[:branch],
|
186
|
-
'app_user' => @env_settings['user'],
|
187
|
-
'app_name' => @args[:app]
|
188
|
-
}
|
189
|
-
json = @chefsettings.merge!(host_settings).to_json
|
190
|
-
instance = ec2.instances.create(:image_id => ami, :availability_zone => zone, :instance_type => itype, :key_name => keyname, :security_group_ids => sg)
|
191
|
-
print "Waiting for instanace to start".color(:cyan)
|
192
|
-
while instance.status != :running do
|
193
|
-
sleep 5
|
194
|
-
print ".".color(:yellow)
|
195
|
-
end
|
196
|
-
puts ""
|
197
|
-
print "Waiting for SSH to respoond".color(:cyan)
|
198
|
-
loop do
|
199
|
-
begin
|
200
|
-
ip = instance.ip_address
|
201
|
-
sshcmd(ip, ["exit 0"], :user => user, :key => key)
|
202
|
-
break
|
203
|
-
rescue
|
204
|
-
print ".".color(:yellow)
|
112
|
+
if @initfile['number'].to_i == 0
|
113
|
+
numbers = [0]
|
114
|
+
$c.each do |host|
|
115
|
+
if host[:role] == @initfile['role'] && host[:environment] == @initfile['environment']
|
116
|
+
numbers << host[:number]
|
205
117
|
end
|
206
|
-
sleep 2
|
207
118
|
end
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
119
|
+
number = numbers.max+1
|
120
|
+
else
|
121
|
+
number = @initfile['role'].to_i
|
122
|
+
end
|
123
|
+
AWS.config(:access_key_id => @user_settings['aws_id'], :secret_access_key => @user_settings['aws_secret'], :ec2_endpoint => "ec2.amazonaws.com")
|
124
|
+
ec2 = AWS::EC2.new
|
125
|
+
init = {
|
126
|
+
:number => number,
|
127
|
+
:hostname => "#{@initfile['role']}-#{@initfile['environment']}-#{number}.#{@initfile['domain']}",
|
128
|
+
:recipe => 'init',
|
129
|
+
:run_list => ["recipe[init]"]
|
130
|
+
}
|
131
|
+
@initfile.keys.each do |key|
|
132
|
+
@initfile[(key.to_sym rescue key) || key] = @initfile.delete(key)
|
133
|
+
end
|
134
|
+
init.merge! @initfile
|
135
|
+
@json = init.to_json
|
136
|
+
script = <<INITSCRIPT
|
137
|
+
#!/usr/bin/env bash
|
138
|
+
apt-get install -y zsh git libssl-dev ruby1.9.1-full build-essential
|
139
|
+
REALLY_GEM_UPDATE_SYSTEM=true gem update --system
|
140
|
+
gem install --bindir /usr/local/bin --no-ri --no-rdoc chef
|
141
|
+
cat << 'EOFKEY' > /root/.ssh/id_rsa
|
142
|
+
#{init[:identity]}
|
143
|
+
EOFKEY
|
144
|
+
chmod 600 /root/.ssh/id_rsa
|
145
|
+
echo 'StrictHostKeyChecking no' > /root/.ssh/config
|
146
|
+
git clone -b #{init[:chefbranch]} #{init[:chefrepo]} /root/ops
|
147
|
+
echo '#{@json}' > /root/init.json
|
148
|
+
while [ ! -b '/dev/xvdf' ]; do sleep 1; done
|
149
|
+
while [ ! -b '/dev/xvdg' ]; do sleep 1; done
|
150
|
+
chef-solo -c /root/ops/cookbooks/init.rb -j /root/init.json && (r53_update.sh; rm /root/.ssh/id_rsa; userdel -r ubuntu)
|
151
|
+
INITSCRIPT
|
152
|
+
instance = ec2.instances.create(:image_id => init[:ami], :availability_zone => @args[:zone], :instance_type => init[:itype], :key_name => init[:keyname], :security_group_ids => init[:sg], :user_data => script)
|
153
|
+
sleep 1 until instance.status == :running
|
154
|
+
volume = ec2.volumes.create(:size => init[:datasize], :availability_zone => @args[:zone])
|
155
|
+
attachment = volume.attach_to(instance, "/dev/sdf")
|
156
|
+
vol2id = 'nil'
|
157
|
+
if init[:environment] == 'production'
|
158
|
+
volume2 = ec2.volumes.create(:size => init[:datasize], :availability_zone => @args[:zone])
|
159
|
+
attachment2 = volume2.attach_to(instance, "/dev/sdg")
|
160
|
+
sleep 1 until attachment2.status != :attaching
|
161
|
+
vol2id = volume2.id
|
225
162
|
end
|
163
|
+
instance.add_tag('Name' , :value => "#{init[:role]}-#{init[:environment]}-#{number}")
|
164
|
+
instance.add_tag('dns', :value => "#{init[:role]}-#{init[:environment]}-#{number}.#{init[:domain]}")
|
165
|
+
instance.add_tag('gaptool', :value => "{:role => '#{init[:role]}', :number => #{number}, :environment => '#{init[:environment]}', :apps => '#{init[:apps].to_s}', :volid => '#{volume.id}', :vol2id => '#{vol2id}'}")
|
166
|
+
sleep 2
|
167
|
+
File.open(File.expand_path("#{ENV['HOME']}/.gaptool-ma/aws.yml"), 'w') {|f| f.write(cgen().to_yaml)}
|
226
168
|
end
|
227
169
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gaptool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-17 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
16
|
-
requirement: &
|
16
|
+
requirement: &70242726597920 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70242726597920
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: net-scp
|
27
|
-
requirement: &
|
27
|
+
requirement: &70242726595840 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70242726595840
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: trollop
|
38
|
-
requirement: &
|
38
|
+
requirement: &70242726593860 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70242726593860
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: aws-sdk
|
49
|
-
requirement: &
|
49
|
+
requirement: &70242726589620 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70242726589620
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: json
|
60
|
-
requirement: &
|
60
|
+
requirement: &70242726587840 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70242726587840
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: peach
|
71
|
-
requirement: &
|
71
|
+
requirement: &70242726585820 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70242726585820
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rainbow
|
82
|
-
requirement: &
|
82
|
+
requirement: &70242726583840 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,18 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70242726583840
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: crack
|
93
|
+
requirement: &70242726582300 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70242726582300
|
91
102
|
description: This command line tool will service a chef repo for building out, configuring,
|
92
103
|
and deploying environments in EC2 and EC2 compatable infrastructure clouds
|
93
104
|
email:
|