leeroy_app 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|