rouster 0.57 → 0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +67 -0
- data/README.md +179 -2
- data/Rakefile +8 -7
- data/Vagrantfile +24 -9
- data/examples/aws.rb +85 -0
- data/lib/rouster.rb +128 -61
- data/lib/rouster/deltas.rb +266 -130
- data/lib/rouster/puppet.rb +2 -2
- data/lib/rouster/testing.rb +28 -6
- data/lib/rouster/vagrant.rb +52 -16
- data/path_helper.rb +3 -4
- data/plugins/aws.rb +347 -0
- data/test/functional/deltas/test_get_packages.rb +50 -6
- data/test/functional/test_caching.rb +2 -2
- data/test/functional/test_new.rb +45 -4
- data/test/functional/test_passthroughs.rb +2 -2
- data/test/puppet/test_apply.rb +1 -1
- data/test/unit/test_new.rb +65 -0
- data/test/unit/testing/resources/osx-launchd +285 -0
- data/test/unit/testing/resources/rhel-systemv +40 -0
- data/test/unit/testing/resources/rhel-upstart +20 -0
- data/test/unit/testing/test_get_services.rb +151 -0
- data/test/unit/testing/test_validate_package.rb +36 -10
- metadata +11 -4
- data/test/puppet/test_roles.rb +0 -186
data/lib/rouster/puppet.rb
CHANGED
|
@@ -459,7 +459,7 @@ class Rouster
|
|
|
459
459
|
opts[:manifest_file].each do |file|
|
|
460
460
|
raise InternalError.new(sprintf('invalid manifest file specified[%s]', file)) unless self.is_file?(file)
|
|
461
461
|
|
|
462
|
-
cmd = 'puppet apply'
|
|
462
|
+
cmd = 'puppet apply --detailed-exitcodes'
|
|
463
463
|
cmd << sprintf(' --modulepath=%s', opts[:module_dir]) unless opts[:module_dir].nil?
|
|
464
464
|
cmd << sprintf(' --hiera_config=%s', opts[:hiera_config]) unless opts[:hiera_config].nil? or puppet_version < '3.0'
|
|
465
465
|
cmd << sprintf(' --environment %s', opts[:environment]) unless opts[:environment].nil?
|
|
@@ -481,7 +481,7 @@ class Rouster
|
|
|
481
481
|
|
|
482
482
|
manifests.each do |m|
|
|
483
483
|
|
|
484
|
-
cmd = 'puppet apply'
|
|
484
|
+
cmd = 'puppet apply --detailed-exitcodes'
|
|
485
485
|
cmd << sprintf(' --modulepath=%s', opts[:module_dir]) unless opts[:module_dir].nil?
|
|
486
486
|
cmd << sprintf(' --hiera_config=%s', opts[:hiera_config]) unless opts[:hiera_config].nil? or puppet_version < '3.0'
|
|
487
487
|
cmd << sprintf(' --environment %s', opts[:environment]) unless opts[:environment].nil?
|
data/lib/rouster/testing.rb
CHANGED
|
@@ -459,17 +459,39 @@ class Rouster
|
|
|
459
459
|
local = v.to_s.match(/absent|false/).nil? ? false : true
|
|
460
460
|
end
|
|
461
461
|
when :version
|
|
462
|
+
# TODO support determination based on multiple versions of the same package installed (?)
|
|
462
463
|
if packages.has_key?(name)
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
464
|
+
|
|
465
|
+
lps = packages[name].is_a?(Array) ? packages[name] : [ packages[name] ]
|
|
466
|
+
|
|
467
|
+
lps.each do |lp|
|
|
468
|
+
if v.split("\s").size > 1
|
|
469
|
+
## generic comparator functionality
|
|
470
|
+
comp, expectation = v.split("\s")
|
|
471
|
+
local = generic_comparator(lp[:version], comp, expectation)
|
|
472
|
+
break unless local.eql?(true)
|
|
473
|
+
else
|
|
474
|
+
local = ! v.to_s.match(/#{lp[:version]}/).nil?
|
|
475
|
+
break unless local.eql?(true)
|
|
476
|
+
end
|
|
469
477
|
end
|
|
470
478
|
else
|
|
471
479
|
local = false
|
|
472
480
|
end
|
|
481
|
+
when :arch, :architecture
|
|
482
|
+
if packages.has_key?(name)
|
|
483
|
+
archs = []
|
|
484
|
+
lps = packages[name].is_a?(Array) ? packages[name] : [ packages[name] ]
|
|
485
|
+
lps.each { |p| archs << p[:arch] }
|
|
486
|
+
if v.is_a?(Array)
|
|
487
|
+
v.each do |arch|
|
|
488
|
+
local = archs.member?(arch)
|
|
489
|
+
break unless local.eql?(true) # fail fast - if we are looking for an arch that DNE, bail out
|
|
490
|
+
end
|
|
491
|
+
else
|
|
492
|
+
local = archs.member?(v)
|
|
493
|
+
end
|
|
494
|
+
end
|
|
473
495
|
when :type
|
|
474
496
|
# noop allowing parse_catalog() output to be passed directly
|
|
475
497
|
else
|
data/lib/rouster/vagrant.rb
CHANGED
|
@@ -42,23 +42,52 @@ class Rouster
|
|
|
42
42
|
|
|
43
43
|
##
|
|
44
44
|
# up
|
|
45
|
-
# runs `vagrant up
|
|
45
|
+
# runs `vagrant up <name>` from the Vagrantfile path
|
|
46
46
|
# if :sshtunnel is passed to the object during instantiation, the tunnel is created here as well
|
|
47
47
|
def up
|
|
48
48
|
@logger.info('up()')
|
|
49
|
-
|
|
49
|
+
|
|
50
|
+
# don't like putting this here, may be refactored
|
|
51
|
+
if self.is_passthrough? and (self.passthrough[:type].equal?(:aws) or self.passthrough[:type].equal?(:raiden))
|
|
52
|
+
self.aws_up()
|
|
53
|
+
else
|
|
54
|
+
self.vagrant(sprintf('up %s', @name))
|
|
55
|
+
end
|
|
50
56
|
|
|
51
57
|
@ssh_info = nil # in case the ssh-info has changed, a la destroy/rebuild
|
|
52
58
|
self.connect_ssh_tunnel() if @sshtunnel
|
|
53
59
|
end
|
|
54
60
|
|
|
61
|
+
##
|
|
62
|
+
# halt
|
|
63
|
+
# runs `vagrant halt <name>` from the Vagrantfile path
|
|
64
|
+
def halt
|
|
65
|
+
@logger.info('halt()')
|
|
66
|
+
self.vagrant(sprintf('halt %s', @name))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# package -- though vagrant docs still refer to 'repackage'
|
|
71
|
+
# runs `vagrant package <name> <provider>`
|
|
72
|
+
def package(provider='virtualbox') # TODO get the provider as a first class citizen on the rouster object
|
|
73
|
+
@logger.info(sprintf('package(%s)', provider))
|
|
74
|
+
self.vagrant(sprintf('package %s %s', @name, provider))
|
|
75
|
+
end
|
|
76
|
+
|
|
55
77
|
##
|
|
56
78
|
# destroy
|
|
57
79
|
# runs `vagrant destroy <name>` from the Vagrantfile path
|
|
58
80
|
def destroy
|
|
59
81
|
@logger.info('destroy()')
|
|
82
|
+
|
|
83
|
+
# don't like putting this here, may be refactored
|
|
84
|
+
if self.is_passthrough? and (self.passthrough[:type].equal?(:aws) or self.passthrough[:type].equal?(:raiden))
|
|
85
|
+
self.aws_destroy()
|
|
86
|
+
else
|
|
87
|
+
self.vagrant(sprintf('destroy -f %s', @name))
|
|
88
|
+
end
|
|
89
|
+
|
|
60
90
|
disconnect_ssh_tunnel
|
|
61
|
-
self.vagrant(sprintf('destroy -f %s', @name))
|
|
62
91
|
end
|
|
63
92
|
|
|
64
93
|
##
|
|
@@ -78,21 +107,28 @@ class Rouster
|
|
|
78
107
|
end
|
|
79
108
|
end
|
|
80
109
|
|
|
110
|
+
# don't like putting this here, may be refactored
|
|
81
111
|
@logger.info('status()')
|
|
82
|
-
self.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
112
|
+
if self.is_passthrough? and (self.passthrough[:type].equal?(:aws) or self.passthrough[:type].equal?(:raiden))
|
|
113
|
+
status = self.aws_status()
|
|
114
|
+
else
|
|
115
|
+
self.vagrant(sprintf('status %s', @name))
|
|
116
|
+
|
|
117
|
+
# else case here (both for nil/non-matching output) is handled by non-0 exit code
|
|
118
|
+
output = self.get_output()
|
|
119
|
+
if output.nil?
|
|
120
|
+
if self.is_passthrough?() and self.passthrough[:type].eql?(:local)
|
|
121
|
+
status = 'running'
|
|
122
|
+
else
|
|
123
|
+
status = 'not-created'
|
|
124
|
+
end
|
|
125
|
+
elsif output.match(/^#{@name}\s*(.*\s?\w+)\s\((.+)\)$/)
|
|
126
|
+
# vagrant 1.2+, $1 = status, $2 = provider
|
|
127
|
+
status = $1
|
|
128
|
+
elsif output.match(/^#{@name}\s+(.+)$/)
|
|
129
|
+
# vagrant 1.2-, $1 = status
|
|
130
|
+
status = $1
|
|
89
131
|
end
|
|
90
|
-
elsif output.match(/^#{@name}\s*(.*\s?\w+)\s\((.+)\)$/)
|
|
91
|
-
# vagrant 1.2+, $1 = status, $2 = provider
|
|
92
|
-
status = $1
|
|
93
|
-
elsif output.match(/^#{@name}\s+(.+)$/)
|
|
94
|
-
# vagrant 1.2-, $1 = status
|
|
95
|
-
status = $1
|
|
96
132
|
end
|
|
97
133
|
|
|
98
134
|
if @cache_timeout
|
data/path_helper.rb
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# this gets us Rouster, still need to figure out how to find vagrant
|
|
4
4
|
$LOAD_PATH << File.join([File.dirname(__FILE__), 'lib'])
|
|
5
|
+
$LOAD_PATH << File.join([File.dirname(__FILE__), 'plugins'])
|
|
6
|
+
$LOAD_PATH << File.expand_path(sprintf('%s/..', File.dirname(__FILE__)))
|
|
7
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
|
5
8
|
|
|
6
9
|
require 'rubygems'
|
|
7
10
|
|
|
8
11
|
# debugging help
|
|
9
|
-
begin
|
|
10
|
-
require 'debugger'
|
|
11
|
-
rescue LoadError
|
|
12
|
-
end
|
|
13
12
|
|
|
14
13
|
class Object
|
|
15
14
|
def my_methods
|
data/plugins/aws.rb
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
## plugins/aws.rb - provide helper functions for Rouster objects running on AWS/EC2
|
|
3
|
+
|
|
4
|
+
require sprintf('%s/../%s', File.dirname(File.expand_path(__FILE__)), 'path_helper')
|
|
5
|
+
|
|
6
|
+
require 'fog'
|
|
7
|
+
require 'uri'
|
|
8
|
+
|
|
9
|
+
class Rouster
|
|
10
|
+
|
|
11
|
+
attr_reader :ec2, :elb # expose AWS workers
|
|
12
|
+
attr_reader :instance_data # the result of the runInstances request
|
|
13
|
+
|
|
14
|
+
def aws_get_url(url)
|
|
15
|
+
# convenience method to run curls from inside the VM
|
|
16
|
+
self.run(sprintf('curl -s %s', url))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# TODO should this be 'aws_ip'?
|
|
20
|
+
def aws_get_ip (method = :internal, type = :public)
|
|
21
|
+
# allowed methods: :internal (check meta-data inside VM), :aws (ask API)
|
|
22
|
+
# allowed types: :public, :private
|
|
23
|
+
self.aws_describe_instance
|
|
24
|
+
|
|
25
|
+
if method.equal?(:internal)
|
|
26
|
+
key = type.equal?(:public) ? 'public-ipv4' : 'local-ipv4'
|
|
27
|
+
murl = sprintf('http://169.254.169.254/latest/meta-data/%s', key)
|
|
28
|
+
result = self.aws_get_url(murl)
|
|
29
|
+
else
|
|
30
|
+
key = type.equal?(:public) ? 'ipAddress' : 'privateIpAddress'
|
|
31
|
+
result = @instance_data[key]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
result
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def aws_get_userdata
|
|
38
|
+
murl = 'http://169.254.169.254/latest/user-data/'
|
|
39
|
+
result = self.aws_get_url(murl)
|
|
40
|
+
|
|
41
|
+
if result.match(/\S=\S/)
|
|
42
|
+
# TODO should we really be doing this?
|
|
43
|
+
userdata = Hash.new()
|
|
44
|
+
result.split("\n").each do |line|
|
|
45
|
+
if line.match(/^(.*?)=(.*)/)
|
|
46
|
+
userdata[$1] = $2
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
userdata = result
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
userdata
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# return a hash containing meta-data items
|
|
57
|
+
def aws_get_metadata
|
|
58
|
+
murl = 'http://169.254.169.254/latest/meta-data/'
|
|
59
|
+
result = self.aws_get_url(murl)
|
|
60
|
+
metadata = Hash.new()
|
|
61
|
+
|
|
62
|
+
# TODO this isn't entirely right.. if the element ends in '/', it's actually another level of hash..
|
|
63
|
+
result.split("\n").each do |element|
|
|
64
|
+
metadata[element] = self.aws_get_url(sprintf('%s%s', murl, element))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
metadata
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def aws_get_hostname (method = :internal, type = :public)
|
|
71
|
+
# allowed methods: :internal (check meta-data inside VM), :aws (ask API)
|
|
72
|
+
# allowed types: :public, :private
|
|
73
|
+
self.aws_describe_instance
|
|
74
|
+
|
|
75
|
+
result = nil
|
|
76
|
+
|
|
77
|
+
if method.equal?(:internal)
|
|
78
|
+
key = type.equal?(:public) ? 'public-hostname' : 'local-hostname'
|
|
79
|
+
murl = sprintf('http://169.254.169.254/latest/meta-data/%s', key)
|
|
80
|
+
result = self.aws_get_url(murl)
|
|
81
|
+
else
|
|
82
|
+
key = type.equal?(:public) ? 'dnsName' : 'privateDnsName'
|
|
83
|
+
result = @instance_data[key]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
result
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def aws_get_instance ()
|
|
90
|
+
if ! @instance_data.nil? and @instance_data.has_key?('instanceId')
|
|
91
|
+
return @instance_data['instanceId'] # we already know the id
|
|
92
|
+
elsif @passthrough.has_key?(:instance)
|
|
93
|
+
return @passthrough[:instance] # we know the id we want
|
|
94
|
+
else
|
|
95
|
+
@logger.debug(sprintf('unable to determine ami-id from instance_data[%s] or passthrough specification[%s]', @instance_data, @passthrough))
|
|
96
|
+
return nil # we don't have an id yet, likely a up() call
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def aws_get_ami ()
|
|
101
|
+
if ! @instance_data.nil? and @instance_data.has_key?('ami')
|
|
102
|
+
return @instance_data['ami']
|
|
103
|
+
else
|
|
104
|
+
return @passthrough[:ami]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def aws_up
|
|
109
|
+
# wait for machine to transition to running state and become sshable (TODO maybe make the second half optional)
|
|
110
|
+
self.aws_connect
|
|
111
|
+
|
|
112
|
+
status = self.status()
|
|
113
|
+
|
|
114
|
+
if status.eql?('running')
|
|
115
|
+
self.connect_ssh_tunnel
|
|
116
|
+
self.passthrough[:instance] = self.aws_get_instance
|
|
117
|
+
return self.aws_get_instance
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# TODO provide more context
|
|
121
|
+
@logger.info(sprintf('calling RunInstances ami[%s], size[%s], keypair[%s]',
|
|
122
|
+
self.passthrough[:ami],
|
|
123
|
+
self.passthrough[:size],
|
|
124
|
+
self.passthrough[:keypair]
|
|
125
|
+
))
|
|
126
|
+
|
|
127
|
+
server = @ec2.run_instances(
|
|
128
|
+
self.passthrough[:ami],
|
|
129
|
+
self.passthrough[:min_count],
|
|
130
|
+
self.passthrough[:max_count],
|
|
131
|
+
{
|
|
132
|
+
'InstanceType' => self.passthrough[:size],
|
|
133
|
+
'KeyName' => self.passthrough[:keypair],
|
|
134
|
+
'SecurityGroup' => self.passthrough[:security_groups],
|
|
135
|
+
'UserData' => self.passthrough[:userdata],
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
@instance_data = server.data[:body]['instancesSet'][0]
|
|
140
|
+
|
|
141
|
+
# wait until the machine starts
|
|
142
|
+
ceiling = 9
|
|
143
|
+
sleep_time = 20
|
|
144
|
+
status = nil
|
|
145
|
+
0.upto(ceiling) do |try|
|
|
146
|
+
status = self.aws_status
|
|
147
|
+
|
|
148
|
+
@logger.debug(sprintf('describeInstances[%s]: [%s] [#%s]', self.aws_get_instance, status, try))
|
|
149
|
+
|
|
150
|
+
if status.eql?('running') or status.eql?('16')
|
|
151
|
+
@logger.info(sprintf('[%s] transitioned to state[%s]', self.aws_get_instance, self.aws_status))
|
|
152
|
+
break
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
sleep sleep_time
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
raise sprintf('instance[%s] did not transition to running state, stopped trying at[%s]', self.aws_get_instance, status) unless status.eql?('running') or status.eql?('16')
|
|
159
|
+
|
|
160
|
+
# TODO don't be this hacky
|
|
161
|
+
self.aws_describe_instance # the server.data response doesn't include public hostname/ip
|
|
162
|
+
if @passthrough[:type].eql?(:aws)
|
|
163
|
+
@passthrough[:host] = @instance_data['dnsName']
|
|
164
|
+
else
|
|
165
|
+
@passthrough[:host] = self.find_ssh_elb(true)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
self.connect_ssh_tunnel
|
|
169
|
+
|
|
170
|
+
self.passthrough[:instance] = self.aws_get_instance
|
|
171
|
+
self.passthrough[:instance]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def aws_destroy
|
|
175
|
+
self.aws_connect
|
|
176
|
+
|
|
177
|
+
server = @ec2.terminate_instances(self.aws_get_instance)
|
|
178
|
+
|
|
179
|
+
if @passthrough.has_key?(:created_elb)
|
|
180
|
+
elb = @passthrough[:created_elb]
|
|
181
|
+
|
|
182
|
+
@logger.info(sprintf('deleting ELB[%s]', elb))
|
|
183
|
+
@elb.delete_load_balancer(elb)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
self.aws_status
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def aws_describe_instance(instance = aws_get_instance)
|
|
190
|
+
|
|
191
|
+
if @cache_timeout
|
|
192
|
+
if @cache.has_key?(:aws_describe_instance)
|
|
193
|
+
if (Time.now.to_i - @cache[:aws_describe_instance][:time]) < @cache_timeout
|
|
194
|
+
@logger.debug(sprintf('using cached aws_describe_instance?[%s] from [%s]', @cache[:aws_describe_instance][:instance], @cache[:aws_describe_instance][:time]))
|
|
195
|
+
return @cache[:aws_describe_instance][:instance]
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
return nil if instance.nil?
|
|
201
|
+
|
|
202
|
+
self.aws_connect
|
|
203
|
+
server = @ec2.describe_instances('instance-id' => [ instance ])
|
|
204
|
+
response = server.data[:body]['reservationSet'][0]['instancesSet'][0]
|
|
205
|
+
|
|
206
|
+
if instance.eql?(self.aws_get_instance)
|
|
207
|
+
@instance_data = response
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if @cache_timeout
|
|
211
|
+
@cache[:aws_describe_instance] = Hash.new unless @cache[:aws_describe_instance].class.eql?(Hash)
|
|
212
|
+
@cache[:aws_describe_instance][:time] = Time.now.to_i
|
|
213
|
+
@cache[:aws_describe_instance][:instance] = response
|
|
214
|
+
@logger.debug(sprintf('caching is_available_via_ssh?[%s] at [%s]', @cache[:aws_describe_instance][:instance], @cache[:aws_decribe_instance][:time]))
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
response
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def aws_status
|
|
221
|
+
self.aws_describe_instance
|
|
222
|
+
return 'not-created' if @instance_data.nil?
|
|
223
|
+
@instance_data['instanceState']['name'].nil? ? @instance_data['instanceState']['code'] : @instance_data['instanceState']['name']
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def aws_connect_to_elb (id, elbname, listeners = [{ 'InstancePort' => 22, 'LoadBalancerPort' => 22, 'Protocol' => 'TCP' }])
|
|
227
|
+
self.elb_connect
|
|
228
|
+
|
|
229
|
+
# allow either hash or array of hash specification for listeners
|
|
230
|
+
listeners = [ listeners ] unless listeners.is_a?(Array)
|
|
231
|
+
required_params = [ 'InstancePort', 'LoadBalancerPort', 'Protocol' ] # figure out plan re: InstanceProtocol/LoadbalancerProtocol vs. Protocol
|
|
232
|
+
|
|
233
|
+
listeners.each do |l|
|
|
234
|
+
required_params.each do |r|
|
|
235
|
+
raise sprintf('listener[%s] does not include required parameter[%s]', l, r) unless l[r]
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
@logger.debug(sprintf('confirming ELB name uniqueness[%s]', elbname))
|
|
241
|
+
response = @elb.describe_load_balancers()
|
|
242
|
+
response.body['DescribeLoadBalancersResult']['LoadBalancerDescriptions'].each do |elb|
|
|
243
|
+
if elb['LoadBalancerName'].eql?(elbname)
|
|
244
|
+
# terminate
|
|
245
|
+
@logger.debug(sprintf('terminating ELB[%s]', elbname))
|
|
246
|
+
@elb.delete_load_balancer(elbname)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# create the ELB/VIP
|
|
251
|
+
@logger.debug(sprintf('creating a load balancer[%s] with listeners[%s]', elbname, listeners))
|
|
252
|
+
response = @elb.create_load_balancer(
|
|
253
|
+
[], # availability zones not needed on raiden
|
|
254
|
+
elbname,
|
|
255
|
+
listeners
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
dnsname = response.body['CreateLoadBalancerResult']['DNSName']
|
|
259
|
+
|
|
260
|
+
# string it up to the id passed
|
|
261
|
+
response = @elb.register_instances_with_load_balancer(id, elbname)
|
|
262
|
+
|
|
263
|
+
# i hate this so much.
|
|
264
|
+
@logger.debug(sprintf('sleeping[%s] to allow DNS propagation', self.passthrough[:dns_propagation_sleep]))
|
|
265
|
+
sleep self.passthrough[:dns_propagation_sleep]
|
|
266
|
+
|
|
267
|
+
return dnsname
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# TODO this will throw at the first error - should we catch?
|
|
271
|
+
# run some commands, return an array of the output
|
|
272
|
+
def aws_bootstrap (commands)
|
|
273
|
+
self.aws_connect
|
|
274
|
+
commands = (commands.is_a?(Array)) ? commands : [ commands ]
|
|
275
|
+
output = Array.new
|
|
276
|
+
|
|
277
|
+
commands.each do |command|
|
|
278
|
+
output << self.run(command)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
return output
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def aws_connect
|
|
285
|
+
return @ec2 unless @ec2.nil?
|
|
286
|
+
|
|
287
|
+
config = {
|
|
288
|
+
:provider => 'AWS',
|
|
289
|
+
:region => self.passthrough[:region],
|
|
290
|
+
:aws_access_key_id => self.passthrough[:key_id],
|
|
291
|
+
:aws_secret_access_key => self.passthrough[:secret_key],
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
config[:endpoint] = self.passthrough[:ec2_endpoint] unless self.passthrough[:ec2_endpoint].nil?
|
|
295
|
+
@ec2 = Fog::Compute.new(config)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def elb_connect
|
|
299
|
+
return @elb unless @elb.nil?
|
|
300
|
+
|
|
301
|
+
if self.passthrough[:elb_endpoint]
|
|
302
|
+
endpoint = URI.parse(self.passthrough[:elb_endpoint])
|
|
303
|
+
elsif self.passthrough[:ec2_endpoint]
|
|
304
|
+
endpoint = URI.parse(self.passthrough[:ec2_endpoint])
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
config = {
|
|
308
|
+
:region => self.passthrough[:region],
|
|
309
|
+
:aws_access_key_id => self.passthrough[:key_id],
|
|
310
|
+
:aws_secret_access_key => self.passthrough[:secret_key],
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
unless endpoint.nil?
|
|
314
|
+
# if not specifying an endpoint, don't add to the config
|
|
315
|
+
config[:host] = endpoint.host
|
|
316
|
+
config[:path] = endpoint.path
|
|
317
|
+
config[:port] = endpoint.port
|
|
318
|
+
config[:scheme] = endpoint.scheme
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
@elb = Fog::AWS::ELB.new(config)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def find_ssh_elb (create_if_not_found = false, instance = aws_get_instance)
|
|
325
|
+
# given an instance, see if there is already an ELB that it is connected to - and potentially create one
|
|
326
|
+
self.elb_connect
|
|
327
|
+
result = nil
|
|
328
|
+
|
|
329
|
+
response = @elb.describe_load_balancers
|
|
330
|
+
elbs = response.body['DescribeLoadBalancersResult']['LoadBalancerDescriptions']
|
|
331
|
+
|
|
332
|
+
elbs.each do |elb|
|
|
333
|
+
if elb['Instances'].member?(instance)
|
|
334
|
+
result = elb['DNSName']
|
|
335
|
+
break
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
if create_if_not_found and result.nil?
|
|
340
|
+
result = self.aws_connect_to_elb(instance, sprintf('%s-ssh', self.name))
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
result
|
|
344
|
+
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
end
|