leeroy_app 0.1.0
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 +7 -0
- data/.gitignore +40 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +103 -0
- data/LICENSE +21 -0
- data/README.md +40 -0
- data/Rakefile +5 -0
- data/bin/leeroy +18 -0
- data/hierarchy.md +39 -0
- data/leeroy.gemspec +42 -0
- data/lib/leeroy/app.rb +132 -0
- data/lib/leeroy/env.rb +116 -0
- data/lib/leeroy/helpers/aws.rb +403 -0
- data/lib/leeroy/helpers/dumpable.rb +72 -0
- data/lib/leeroy/helpers/env.rb +42 -0
- data/lib/leeroy/helpers/logging.rb +36 -0
- data/lib/leeroy/helpers/polling.rb +67 -0
- data/lib/leeroy/helpers/state.rb +59 -0
- data/lib/leeroy/helpers.rb +9 -0
- data/lib/leeroy/state.rb +70 -0
- data/lib/leeroy/task/base.rb +61 -0
- data/lib/leeroy/task/image.rb +126 -0
- data/lib/leeroy/task/instantiate.rb +200 -0
- data/lib/leeroy/task/sleep.rb +29 -0
- data/lib/leeroy/task/stub.rb +40 -0
- data/lib/leeroy/task/terminate.rb +49 -0
- data/lib/leeroy/task.rb +17 -0
- data/lib/leeroy/types/dash.rb +17 -0
- data/lib/leeroy/types/image.rb +53 -0
- data/lib/leeroy/types/instance.rb +67 -0
- data/lib/leeroy/types/mash.rb +17 -0
- data/lib/leeroy/types/packedstring.rb +25 -0
- data/lib/leeroy/types/phase.rb +20 -0
- data/lib/leeroy/types/semaphore.rb +30 -0
- data/lib/leeroy/types/statedata.rb +44 -0
- data/lib/leeroy/types/statemetadata.rb +29 -0
- data/lib/leeroy/types/userdata.rb +13 -0
- data/lib/leeroy/version.rb +3 -0
- data/lib/leeroy.rb +7 -0
- data/spec/spec_helper.rb +105 -0
- data/spec/support/aruba.rb +1 -0
- data/spec/use_aruba_with_rspec_spec.rb +11 -0
- metadata +333 -0
data/lib/leeroy/state.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'leeroy/types/dash'
|
2
|
+
require 'leeroy/types/statedata'
|
3
|
+
require 'leeroy/types/statemetadata'
|
4
|
+
require 'leeroy/helpers/logging'
|
5
|
+
require 'leeroy/helpers/polling'
|
6
|
+
require 'leeroy/helpers/state'
|
7
|
+
|
8
|
+
module Leeroy
|
9
|
+
class State < Leeroy::Types::Dash
|
10
|
+
include Leeroy::Helpers::Dumpable
|
11
|
+
include Leeroy::Helpers::Logging
|
12
|
+
include Leeroy::Helpers::Polling
|
13
|
+
include Leeroy::Helpers::State
|
14
|
+
|
15
|
+
# state properties
|
16
|
+
property :data, coerce: Leeroy::Types::StateData, default: {}
|
17
|
+
property :metadata, coerce: Leeroy::Types::StateMetadata, default: {}
|
18
|
+
|
19
|
+
def fetch(*args, &block)
|
20
|
+
begin
|
21
|
+
self.data.send(:fetch, *args, &block)
|
22
|
+
|
23
|
+
rescue KeyError => e
|
24
|
+
logger.debug e.message
|
25
|
+
|
26
|
+
not_found = args[0]
|
27
|
+
logger.info "property '#{not_found}' not found in statedata, checking state"
|
28
|
+
|
29
|
+
begin
|
30
|
+
self.send(not_found.to_sym, &block)
|
31
|
+
|
32
|
+
rescue KeyError => e
|
33
|
+
logger.debug e.message
|
34
|
+
|
35
|
+
logger.warn "property '#{not_found}' not found in statedata or state"
|
36
|
+
end
|
37
|
+
|
38
|
+
rescue StandardError => e
|
39
|
+
raise e
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(method, *args, &block)
|
44
|
+
begin
|
45
|
+
self.data.send(method.to_sym, *args, &block)
|
46
|
+
|
47
|
+
rescue NoMethodError => e
|
48
|
+
logger.debug e.message
|
49
|
+
if self.respond_to?(method.to_sym)
|
50
|
+
self.send(method.to_sym, *args, &block)
|
51
|
+
else
|
52
|
+
raise e
|
53
|
+
end
|
54
|
+
|
55
|
+
rescue StandardError => e
|
56
|
+
raise e
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(*args, &block)
|
61
|
+
super
|
62
|
+
|
63
|
+
self.dump_properties = [
|
64
|
+
:data,
|
65
|
+
:metadata,
|
66
|
+
]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'leeroy'
|
2
|
+
require 'leeroy/env'
|
3
|
+
require 'leeroy/helpers'
|
4
|
+
require 'leeroy/helpers/env'
|
5
|
+
require 'leeroy/helpers/logging'
|
6
|
+
require 'leeroy/helpers/state'
|
7
|
+
require 'leeroy/state'
|
8
|
+
require 'leeroy/task'
|
9
|
+
require 'leeroy/types/mash'
|
10
|
+
|
11
|
+
module Leeroy
|
12
|
+
module Task
|
13
|
+
class Base
|
14
|
+
|
15
|
+
include Leeroy::Task
|
16
|
+
include Leeroy::Helpers
|
17
|
+
include Leeroy::Helpers::Env
|
18
|
+
include Leeroy::Helpers::Logging
|
19
|
+
include Leeroy::Helpers::State
|
20
|
+
|
21
|
+
def initialize(params = {})
|
22
|
+
begin
|
23
|
+
@global_options = params.fetch(:global_options, {})
|
24
|
+
logger.debug("global_options: #{self.global_options.to_s}")
|
25
|
+
|
26
|
+
logger.debug("setting options")
|
27
|
+
@options = params.fetch(:options, {})
|
28
|
+
logger.debug("options: #{self.options.to_s}")
|
29
|
+
|
30
|
+
logger.debug("setting args")
|
31
|
+
@args = params.fetch(:args, {})
|
32
|
+
logger.debug("args: #{self.args.to_s}")
|
33
|
+
|
34
|
+
logger.debug("setting env")
|
35
|
+
@env = Leeroy::Env.new({}, params.fetch(:env, ENV))
|
36
|
+
logger.debug("env: #{self.env.to_s}")
|
37
|
+
|
38
|
+
logger.debug("setting state")
|
39
|
+
@state = Leeroy::State.new(state_from_pipe(params.fetch(:state, {})))
|
40
|
+
rotate_task_metadata
|
41
|
+
logger.debug("state: #{self.state}")
|
42
|
+
|
43
|
+
logger.debug("base initialization of #{self.class.to_s} complete")
|
44
|
+
rescue StandardError => e
|
45
|
+
raise e
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def perform(args = self.args, options = self.options, global_options = self.global_options)
|
50
|
+
begin
|
51
|
+
self.logger.info("performing #{self.class.to_s}")
|
52
|
+
self.logger.debug("args: #{args.inspect}")
|
53
|
+
self.logger.debug("options: #{options.inspect}")
|
54
|
+
|
55
|
+
rescue StandardError => e
|
56
|
+
raise e
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'leeroy'
|
2
|
+
require 'leeroy/task'
|
3
|
+
require 'leeroy/helpers/aws'
|
4
|
+
require 'leeroy/helpers/polling'
|
5
|
+
require 'leeroy/types/image'
|
6
|
+
require 'leeroy/types/phase'
|
7
|
+
|
8
|
+
module Leeroy
|
9
|
+
module Task
|
10
|
+
class Image < Leeroy::Task::Base
|
11
|
+
include Leeroy::Helpers::AWS
|
12
|
+
include Leeroy::Helpers::Polling
|
13
|
+
|
14
|
+
def perform(args = self.args, options = self.options, global_options = self.global_options)
|
15
|
+
begin
|
16
|
+
super(args, options, global_options)
|
17
|
+
|
18
|
+
phase = Leeroy::Types::Phase.new(self.state.fetch('phase', options[:phase]))
|
19
|
+
self.state.phase = phase
|
20
|
+
|
21
|
+
# create image
|
22
|
+
image_params = _genImageParams(phase)
|
23
|
+
|
24
|
+
logger.debug "image_params: #{image_params.inspect}"
|
25
|
+
|
26
|
+
image = Leeroy::Types::Image.new(image_params)
|
27
|
+
resp = ec2Request(:create_image, image.run_params)
|
28
|
+
|
29
|
+
imageid = resp.image_id
|
30
|
+
logger.debug "imageid: #{imageid}"
|
31
|
+
|
32
|
+
self.state.imageid = imageid
|
33
|
+
|
34
|
+
_prepImageCreationPolling
|
35
|
+
poll(imageid)
|
36
|
+
|
37
|
+
dump_state
|
38
|
+
|
39
|
+
logger.debug "done performing for #{self.class}"
|
40
|
+
|
41
|
+
rescue StandardError => e
|
42
|
+
raise e
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def _prepImageCreationPolling
|
49
|
+
# poll to make sure image is created
|
50
|
+
self.poll_callback = lambda do |imageid|
|
51
|
+
begin
|
52
|
+
run_params = { :image_ids => [imageid], :owners => ['self'] }
|
53
|
+
resp = ec2Request(:describe_images, run_params)
|
54
|
+
|
55
|
+
state = resp.images[0].state
|
56
|
+
|
57
|
+
if state == 'pending'
|
58
|
+
logger.debug "image #{imageid} still pending"
|
59
|
+
nil
|
60
|
+
elsif state == 'available'
|
61
|
+
logger.debug "image #{imageid} available"
|
62
|
+
imageid
|
63
|
+
else
|
64
|
+
raise "image creation failed: #{resp.images[0].state_reason.message}"
|
65
|
+
end
|
66
|
+
|
67
|
+
rescue Aws::EC2::Errors::InvalidAMIIDNotFound => e
|
68
|
+
logger.debug "instance #{instanceid} not found"
|
69
|
+
nil
|
70
|
+
rescue StandardError => e
|
71
|
+
raise e
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
self.poll_timeout = checkEnv('LEEROY_POLL_TIMEOUT').to_i
|
76
|
+
self.poll_interval = checkEnv('LEEROY_POLL_INTERVAL').to_i
|
77
|
+
end
|
78
|
+
|
79
|
+
def _genImageParams(phase, state = self.state, env = self.env, ec2 = self.ec2, options = self.options)
|
80
|
+
begin
|
81
|
+
logger.debug "generating params for creating an EC2 image"
|
82
|
+
|
83
|
+
image_params = Leeroy::Types::Mash.new
|
84
|
+
|
85
|
+
image_params.phase = phase
|
86
|
+
|
87
|
+
# get instance_id from state or options
|
88
|
+
instance_id = state.instanceid? ? state.instanceid : options[:instance]
|
89
|
+
raise "Unable to determine instance ID, exiting." if instance_id.nil?
|
90
|
+
logger.debug "instance_id: #{instance_id}"
|
91
|
+
image_params.instance_id = instance_id
|
92
|
+
|
93
|
+
# were we given an app_name?
|
94
|
+
app_name = state.app_name? ? state.app_name : checkEnv('LEEROY_APP_NAME')
|
95
|
+
logger.debug "app_name: #{app_name}"
|
96
|
+
|
97
|
+
# were we given an image index?
|
98
|
+
index = _genImageIndex(state, env, ec2, options).to_s
|
99
|
+
logger.debug "index: #{index}"
|
100
|
+
|
101
|
+
# build target depends on phase
|
102
|
+
build_target = phase == 'gold_master' ? 'master' : checkEnv('LEEROY_BUILD_TARGET')
|
103
|
+
|
104
|
+
image_params.name = [app_name, build_target, index].join('-')
|
105
|
+
|
106
|
+
image_params
|
107
|
+
|
108
|
+
rescue StandardError => e
|
109
|
+
raise e
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def _genImageIndex(state = self.state, env = self.env, ec2 = self.ec2, options = self.options)
|
114
|
+
begin
|
115
|
+
logger.debug "determining gold master instance ID"
|
116
|
+
|
117
|
+
options[:index] or getGoldMasterImageIndex.to_i + 1
|
118
|
+
|
119
|
+
rescue StandardError => e
|
120
|
+
raise e
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'leeroy'
|
2
|
+
require 'leeroy/task'
|
3
|
+
require 'leeroy/helpers/aws'
|
4
|
+
require 'leeroy/helpers/polling'
|
5
|
+
|
6
|
+
module Leeroy
|
7
|
+
module Task
|
8
|
+
class Instantiate < Leeroy::Task::Base
|
9
|
+
include Leeroy::Helpers::AWS
|
10
|
+
include Leeroy::Helpers::Polling
|
11
|
+
|
12
|
+
def perform(args = self.args, options = self.options, global_options = self.global_options)
|
13
|
+
begin
|
14
|
+
super(args, options, global_options)
|
15
|
+
|
16
|
+
phase = Leeroy::Types::Phase.new(self.state.fetch('phase', options[:phase]))
|
17
|
+
self.state.phase = phase
|
18
|
+
|
19
|
+
# resolve various AWS resources from human-readable inputs
|
20
|
+
_resolveResources
|
21
|
+
|
22
|
+
# create instance
|
23
|
+
instance = Leeroy::Types::Instance.new(_genInstanceParams)
|
24
|
+
resp = ec2Request(:run_instances, instance.run_params)
|
25
|
+
instanceid = resp.instances[0].instance_id
|
26
|
+
self.state.instanceid = instanceid
|
27
|
+
|
28
|
+
# wait until instance is starting
|
29
|
+
_prepInstanceCreationPolling
|
30
|
+
poll(instanceid)
|
31
|
+
|
32
|
+
# tag instance
|
33
|
+
instance_name = phase == 'gold_master' ? getGoldMasterInstanceName : getApplicationInstanceName
|
34
|
+
createTags({'Name' => instance_name})
|
35
|
+
|
36
|
+
# write semaphore
|
37
|
+
s3_object = buildS3ObjectName(instanceid, 'semaphores')
|
38
|
+
payload = _readSemaphore(phase)
|
39
|
+
semaphore = setSemaphore(genSemaphore(s3_object, payload))
|
40
|
+
self.state.semaphore = semaphore
|
41
|
+
|
42
|
+
# wait until instance is done provisioning
|
43
|
+
_prepInstanceProvisionPolling
|
44
|
+
poll(semaphore)
|
45
|
+
|
46
|
+
dump_state
|
47
|
+
|
48
|
+
logger.debug "done performing for #{self.class}"
|
49
|
+
|
50
|
+
rescue StandardError => e
|
51
|
+
raise e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(*args, &block)
|
56
|
+
super
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def _prepInstanceCreationPolling
|
63
|
+
# poll to make sure instance is created
|
64
|
+
self.poll_callback = lambda do |instanceid|
|
65
|
+
begin
|
66
|
+
run_params = { :instance_ids => [instanceid] }
|
67
|
+
resp = ec2Request(:describe_instances, run_params)
|
68
|
+
|
69
|
+
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound => e
|
70
|
+
logger.debug "instance #{instanceid} not found"
|
71
|
+
nil
|
72
|
+
rescue StandardError => e
|
73
|
+
raise e
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
self.poll_timeout = 30
|
78
|
+
self.poll_interval = 2
|
79
|
+
end
|
80
|
+
|
81
|
+
def _prepInstanceProvisionPolling
|
82
|
+
# poll until semaphore has been removed
|
83
|
+
self.poll_callback = lambda {|s| checkSemaphore(s).nil?}
|
84
|
+
self.poll_timeout = checkEnv('LEEROY_POLL_TIMEOUT').to_i
|
85
|
+
self.poll_interval = checkEnv('LEEROY_POLL_INTERVAL').to_i
|
86
|
+
end
|
87
|
+
|
88
|
+
def _readSemaphore(phase)
|
89
|
+
begin
|
90
|
+
template = File.join(checkEnv('LEEROY_PROVISIONING_TEMPLATE_PREFIX'), "#{phase}.erb")
|
91
|
+
logger.debug "processing template '#{template}'"
|
92
|
+
|
93
|
+
# this is heinous
|
94
|
+
# http://stackoverflow.com/a/22777806/17597
|
95
|
+
rendered = String.new
|
96
|
+
|
97
|
+
begin
|
98
|
+
old_stdout = $stdout
|
99
|
+
$stdout = StringIO.new('','w')
|
100
|
+
ERB.new(File.read(template)).run
|
101
|
+
rendered = $stdout.string
|
102
|
+
ensure
|
103
|
+
$stdout = old_stdout
|
104
|
+
end
|
105
|
+
|
106
|
+
rendered
|
107
|
+
|
108
|
+
rescue StandardError => e
|
109
|
+
raise e
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def _resolveResources(state = self.state, env = self.env, ec2 = self.ec2, options = self.options)
|
114
|
+
begin
|
115
|
+
# resolve VPC ID
|
116
|
+
if state.vpcid?
|
117
|
+
vpcid = state.vpcid
|
118
|
+
else
|
119
|
+
vpcname = checkEnv('LEEROY_BUILD_VPC')
|
120
|
+
vpcid = getVpcId(vpcname)
|
121
|
+
state.vpcid = vpcid
|
122
|
+
end
|
123
|
+
|
124
|
+
# resolve security group
|
125
|
+
if state.sgid?
|
126
|
+
sgid = state.sgid
|
127
|
+
else
|
128
|
+
sgname = checkEnv('LEEROY_BUILD_SECURITY_GROUP')
|
129
|
+
sgid = getSgId(sgname, vpcname, vpcid)
|
130
|
+
state.sgid = sgid
|
131
|
+
end
|
132
|
+
|
133
|
+
# resolve subnet
|
134
|
+
if state.subnetid?
|
135
|
+
subnetid = state.subnetid
|
136
|
+
else
|
137
|
+
subnetname = checkEnv('LEEROY_BUILD_SUBNET')
|
138
|
+
subnetid = getSubnetId(subnetname, vpcid)
|
139
|
+
state.subnetid = subnetid
|
140
|
+
end
|
141
|
+
|
142
|
+
rescue StandardError => e
|
143
|
+
raise e
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def _genInstanceParams(state = self.state, env = self.env, ec2 = self.ec2, options = self.options)
|
148
|
+
begin
|
149
|
+
logger.debug "generating params for creating an EC2 instance"
|
150
|
+
|
151
|
+
# gather the necessary parameters
|
152
|
+
instance_params = Leeroy::Types::Mash.new
|
153
|
+
|
154
|
+
instance_params.security_group_ids = Array(state.sgid)
|
155
|
+
instance_params.subnet_id = state.subnetid
|
156
|
+
|
157
|
+
instance_params.key_name = checkEnv('LEEROY_BUILD_SSH_KEYPAIR')
|
158
|
+
instance_params.instance_type = checkEnv('LEEROY_BUILD_INSTANCE_TYPE')
|
159
|
+
|
160
|
+
instance_params.min_count = 1
|
161
|
+
instance_params.max_count = 1
|
162
|
+
|
163
|
+
instance_params.store('iam_instance_profile', {:name => checkEnv('LEEROY_BUILD_PROFILE_NAME')})
|
164
|
+
|
165
|
+
# some parameters depend on phase
|
166
|
+
phase = options[:phase]
|
167
|
+
logger.debug "phase is #{phase}"
|
168
|
+
|
169
|
+
# AMI id depends on phase
|
170
|
+
if phase == 'gold_master'
|
171
|
+
image_id = checkEnv('LEEROY_AWS_LINUX_AMI')
|
172
|
+
elsif phase == 'application'
|
173
|
+
image_id = state.imageid
|
174
|
+
end
|
175
|
+
|
176
|
+
instance_params.phase = phase
|
177
|
+
|
178
|
+
raise "unable to determine image ID for phase '#{phase}'" if image_id.nil?
|
179
|
+
|
180
|
+
instance_params.image_id = image_id
|
181
|
+
|
182
|
+
# user_data file depends on phase
|
183
|
+
user_data = File.join(checkEnv('LEEROY_USER_DATA_PREFIX'), phase)
|
184
|
+
if File.readable?(user_data)
|
185
|
+
instance_params.user_data = IO.readlines(user_data).join('')
|
186
|
+
else
|
187
|
+
raise "You must provide a readable user data script at #{user_data}."
|
188
|
+
end
|
189
|
+
|
190
|
+
logger.debug "instance_params: #{instance_params.inspect}"
|
191
|
+
|
192
|
+
instance_params
|
193
|
+
|
194
|
+
rescue StandardError => e
|
195
|
+
raise e
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'leeroy/task'
|
2
|
+
|
3
|
+
module Leeroy
|
4
|
+
module Task
|
5
|
+
class Sleep < Leeroy::Task::Base
|
6
|
+
|
7
|
+
def perform(args = self.args, options = self.options, global_options = self.global_options)
|
8
|
+
super(args, options, global_options)
|
9
|
+
|
10
|
+
begin
|
11
|
+
logger.debug "performing for #{self.class}"
|
12
|
+
logger.debug "state: #{self.state}"
|
13
|
+
|
14
|
+
interval = self.options[:interval].to_i
|
15
|
+
logger.debug "sleeping: #{interval} seconds"
|
16
|
+
|
17
|
+
sleep interval
|
18
|
+
|
19
|
+
dump_state
|
20
|
+
|
21
|
+
logger.debug "done performing for #{self.class}"
|
22
|
+
|
23
|
+
rescue StandardError => e
|
24
|
+
raise e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'leeroy/task'
|
2
|
+
|
3
|
+
module Leeroy
|
4
|
+
module Task
|
5
|
+
class Stub < Leeroy::Task::Base
|
6
|
+
|
7
|
+
def perform(args = self.args, options = self.options, global_options = self.global_options)
|
8
|
+
super
|
9
|
+
|
10
|
+
begin
|
11
|
+
logger.debug "performing for #{self.class}"
|
12
|
+
logger.debug "state: #{self.state}"
|
13
|
+
message = self.state.message
|
14
|
+
|
15
|
+
increment = self.options[:increment].to_i
|
16
|
+
logger.debug "increment: #{increment}"
|
17
|
+
|
18
|
+
logger.info "old message: #{message}"
|
19
|
+
|
20
|
+
if message.nil?
|
21
|
+
message = increment
|
22
|
+
else
|
23
|
+
message = message.to_i + increment
|
24
|
+
end
|
25
|
+
|
26
|
+
state.message = message
|
27
|
+
|
28
|
+
logger.info "new message: #{message}"
|
29
|
+
|
30
|
+
dump_state
|
31
|
+
|
32
|
+
logger.debug "done performing for #{self.class}"
|
33
|
+
|
34
|
+
rescue StandardError => e
|
35
|
+
raise e
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'leeroy'
|
2
|
+
require 'leeroy/task'
|
3
|
+
require 'leeroy/helpers/aws'
|
4
|
+
|
5
|
+
module Leeroy
|
6
|
+
module Task
|
7
|
+
class Terminate < Leeroy::Task::Base
|
8
|
+
include Leeroy::Helpers::AWS
|
9
|
+
|
10
|
+
def perform(args = self.args, options = self.options, global_options = self.global_options)
|
11
|
+
begin
|
12
|
+
super(args, options, global_options)
|
13
|
+
|
14
|
+
# destroy instance
|
15
|
+
terminated = destroyInstance
|
16
|
+
|
17
|
+
instanceid = self.state.instanceid
|
18
|
+
if terminated.include?(instanceid)
|
19
|
+
# clean up semaphore if present
|
20
|
+
semaphore = self.state.semaphore
|
21
|
+
|
22
|
+
if semaphore.nil?
|
23
|
+
# guess at semaphore from instance ID
|
24
|
+
s3_object = buildS3ObjectName(instanceid, 'semaphores')
|
25
|
+
bucket = checkEnv('LEEROY_S3_BUCKET')
|
26
|
+
semaphore = Leeroy::Types::Semaphore.new(bucket: bucket, object: s3_object, payload: '')
|
27
|
+
end
|
28
|
+
|
29
|
+
unless semaphore.nil?
|
30
|
+
logger.debug "clearing semaphore #{semaphore}"
|
31
|
+
clearSemaphore(semaphore)
|
32
|
+
end
|
33
|
+
|
34
|
+
logger.debug "clearing instanceid #{instanceid} from state"
|
35
|
+
self.state.instanceid = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
dump_state
|
39
|
+
|
40
|
+
logger.debug "done performing for #{self.class}"
|
41
|
+
|
42
|
+
rescue StandardError => e
|
43
|
+
raise e
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/leeroy/task.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'leeroy'
|
2
|
+
require 'leeroy/helpers'
|
3
|
+
require 'leeroy/helpers/env'
|
4
|
+
require 'leeroy/helpers/logging'
|
5
|
+
require 'leeroy/helpers/state'
|
6
|
+
require 'leeroy/task/base'
|
7
|
+
|
8
|
+
module Leeroy
|
9
|
+
module Task
|
10
|
+
include Leeroy::Helpers
|
11
|
+
include Leeroy::Helpers::Env
|
12
|
+
include Leeroy::Helpers::State
|
13
|
+
include Leeroy::Helpers::Logging
|
14
|
+
attr_reader :global_options, :options, :args
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Leeroy
|
4
|
+
module Types
|
5
|
+
class Dash < Hashie::Dash
|
6
|
+
include Hashie::Extensions::KeyConversion
|
7
|
+
include Hashie::Extensions::MethodAccess
|
8
|
+
include Hashie::Extensions::IndifferentAccess
|
9
|
+
include Hashie::Extensions::Dash::Coercion
|
10
|
+
|
11
|
+
def dumper
|
12
|
+
self.to_hash
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'leeroy'
|
2
|
+
require 'leeroy/types/dash'
|
3
|
+
require 'leeroy/types/mash'
|
4
|
+
require 'leeroy/types/phase'
|
5
|
+
require 'leeroy/helpers/dumpable'
|
6
|
+
require 'leeroy/helpers/logging'
|
7
|
+
|
8
|
+
module Leeroy
|
9
|
+
module Types
|
10
|
+
class Image < Leeroy::Types::Dash
|
11
|
+
include Leeroy::Helpers::Dumpable
|
12
|
+
include Leeroy::Helpers::Logging
|
13
|
+
|
14
|
+
property :phase, required: true, coerce: Leeroy::Types::Phase
|
15
|
+
property :aws_params
|
16
|
+
|
17
|
+
# AWS-specific params
|
18
|
+
property :instance_id, required: true
|
19
|
+
property :name, required: true
|
20
|
+
|
21
|
+
def initialize(*args, &block)
|
22
|
+
self.aws_params = [
|
23
|
+
:instance_id,
|
24
|
+
:name,
|
25
|
+
]
|
26
|
+
|
27
|
+
self.dump_properties = self.aws_params
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_params
|
33
|
+
begin
|
34
|
+
run_params = Leeroy::Types::Mash.new
|
35
|
+
|
36
|
+
self.aws_params.each {|key| run_params.store(key.to_s, self.fetch(key))}
|
37
|
+
|
38
|
+
logger.debug "run_params: #{run_params.inspect}"
|
39
|
+
|
40
|
+
run_params
|
41
|
+
|
42
|
+
rescue StandardError => e
|
43
|
+
raise e
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
self.instance_id
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|