simplerubysteps 0.0.7 → 0.0.9
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/README.md +68 -25
- data/exe/simplerubysteps +3 -3
- data/exe/srs +6 -0
- data/lib/function.rb +6 -3
- data/lib/{statemachine.yaml → simplerubysteps/cloudformation.rb} +77 -60
- data/lib/simplerubysteps/dsl.rb +86 -0
- data/lib/simplerubysteps/model.rb +204 -0
- data/lib/simplerubysteps/tool.rb +599 -0
- data/lib/simplerubysteps/version.rb +1 -1
- data/lib/simplerubysteps.rb +2 -273
- data/simplerubysteps.gemspec +2 -4
- metadata +10 -16
- data/.gitignore +0 -9
- data/Gemfile +0 -5
- data/LICENSE.txt +0 -21
- data/bin/console +0 -7
- data/bin/setup +0 -6
- data/lib/tool.rb +0 -448
- data/samples/sample1/sample-task-worker.sh +0 -5
- data/samples/sample1/start-callbackbranch.sh +0 -3
- data/samples/sample1/start-directbranch.sh +0 -3
- data/samples/sample1/workflow.rb +0 -39
- data/samples/sample2/workflow.rb +0 -42
@@ -0,0 +1,599 @@
|
|
1
|
+
require "simplerubysteps/version"
|
2
|
+
require "simplerubysteps/cloudformation"
|
3
|
+
require "aws-sdk-cloudformation"
|
4
|
+
require "aws-sdk-s3"
|
5
|
+
require "aws-sdk-states"
|
6
|
+
require "digest"
|
7
|
+
require "zip"
|
8
|
+
require "tempfile"
|
9
|
+
require "json"
|
10
|
+
require "optparse"
|
11
|
+
require "aws-sdk-cloudwatchlogs"
|
12
|
+
require "time"
|
13
|
+
require "thread"
|
14
|
+
|
15
|
+
module Simplerubysteps
|
16
|
+
class Tool
|
17
|
+
def initialize
|
18
|
+
@cloudformation_client = Aws::CloudFormation::Client.new
|
19
|
+
@s3_client = Aws::S3::Client.new
|
20
|
+
@states_client = Aws::States::Client.new
|
21
|
+
@logs_client = Aws::CloudWatchLogs::Client.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def tail_follow_logs(log_group_name, extract_pattern = nil) # FIXME too hacky
|
25
|
+
Signal.trap("INT") do
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
first_event_time = Time.now.to_i * 1000
|
30
|
+
|
31
|
+
next_tokens = {}
|
32
|
+
first_round = true
|
33
|
+
loop do
|
34
|
+
log_streams = @logs_client.describe_log_streams(
|
35
|
+
log_group_name: log_group_name,
|
36
|
+
order_by: "LastEventTime",
|
37
|
+
descending: true,
|
38
|
+
).log_streams
|
39
|
+
|
40
|
+
log_streams.each do |log_stream|
|
41
|
+
get_log_events_params = {
|
42
|
+
log_group_name: log_group_name,
|
43
|
+
log_stream_name: log_stream.log_stream_name,
|
44
|
+
}
|
45
|
+
|
46
|
+
if next_tokens.key?(log_stream.log_stream_name)
|
47
|
+
get_log_events_params[:next_token] = next_tokens[log_stream.log_stream_name]
|
48
|
+
else
|
49
|
+
get_log_events_params[:start_time] = first_round ? log_stream.last_event_timestamp : first_event_time
|
50
|
+
end
|
51
|
+
|
52
|
+
response = @logs_client.get_log_events(get_log_events_params)
|
53
|
+
|
54
|
+
response.events.each do |event|
|
55
|
+
if event.timestamp >= first_event_time
|
56
|
+
if extract_pattern
|
57
|
+
if /#{extract_pattern}/ =~ event.message
|
58
|
+
puts $1
|
59
|
+
exit
|
60
|
+
end
|
61
|
+
else
|
62
|
+
puts "#{Time.at(event.timestamp / 1000).utc} - #{log_stream.log_stream_name} - #{event.message}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
next_tokens[log_stream.log_stream_name] = response.next_forward_token
|
68
|
+
end
|
69
|
+
|
70
|
+
sleep 5
|
71
|
+
|
72
|
+
first_round = false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def stack_outputs(stack_name)
|
77
|
+
begin
|
78
|
+
response = @cloudformation_client.describe_stacks(stack_name: stack_name)
|
79
|
+
outputs = {}
|
80
|
+
response.stacks.first.outputs.each do |output|
|
81
|
+
outputs[output.output_key] = output.output_value
|
82
|
+
end
|
83
|
+
outputs
|
84
|
+
rescue Aws::CloudFormation::Errors::ServiceError => error
|
85
|
+
return nil if error.message =~ /Stack .* does not exist/
|
86
|
+
raise error
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def stack_params(stack_name, template, parameters)
|
91
|
+
params = {
|
92
|
+
stack_name: stack_name,
|
93
|
+
template_body: template,
|
94
|
+
capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
|
95
|
+
parameters: [],
|
96
|
+
}
|
97
|
+
parameters.each do |k, v|
|
98
|
+
params[:parameters].push({
|
99
|
+
parameter_key: k,
|
100
|
+
parameter_value: v,
|
101
|
+
})
|
102
|
+
end
|
103
|
+
params
|
104
|
+
end
|
105
|
+
|
106
|
+
def stack_create(stack_name, template, parameters)
|
107
|
+
@cloudformation_client.create_stack(stack_params(stack_name, template, parameters))
|
108
|
+
@cloudformation_client.wait_until(:stack_create_complete, stack_name: stack_name)
|
109
|
+
stack_outputs(stack_name)
|
110
|
+
end
|
111
|
+
|
112
|
+
def stack_update(stack_name, template, parameters)
|
113
|
+
begin
|
114
|
+
@cloudformation_client.update_stack(stack_params(stack_name, template, parameters))
|
115
|
+
@cloudformation_client.wait_until(:stack_update_complete, stack_name: stack_name)
|
116
|
+
stack_outputs(stack_name)
|
117
|
+
rescue Aws::CloudFormation::Errors::ServiceError => error
|
118
|
+
return stack_outputs(stack_name).merge({ :no_update => true }) if error.message =~ /No updates are to be performed/
|
119
|
+
raise unless error.message =~ /No updates are to be performed/
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def list_stacks_with_prefix(prefix)
|
124
|
+
stack_list = []
|
125
|
+
next_token = nil
|
126
|
+
loop do
|
127
|
+
response = @cloudformation_client.list_stacks({
|
128
|
+
next_token: next_token,
|
129
|
+
stack_status_filter: %w[
|
130
|
+
CREATE_COMPLETE
|
131
|
+
UPDATE_COMPLETE
|
132
|
+
ROLLBACK_COMPLETE
|
133
|
+
],
|
134
|
+
})
|
135
|
+
|
136
|
+
response.stack_summaries.each do |stack|
|
137
|
+
if stack.stack_name =~ /^#{prefix}$|^#{prefix}-(.+)/
|
138
|
+
stack_list << stack.stack_name
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
next_token = response.next_token
|
143
|
+
break if next_token.nil?
|
144
|
+
end
|
145
|
+
|
146
|
+
stack_list
|
147
|
+
end
|
148
|
+
|
149
|
+
def most_recent_stack_with_prefix(prefix)
|
150
|
+
stack_list = {}
|
151
|
+
next_token = nil
|
152
|
+
loop do
|
153
|
+
response = @cloudformation_client.list_stacks({
|
154
|
+
next_token: next_token,
|
155
|
+
stack_status_filter: %w[
|
156
|
+
CREATE_COMPLETE
|
157
|
+
UPDATE_COMPLETE
|
158
|
+
ROLLBACK_COMPLETE
|
159
|
+
],
|
160
|
+
})
|
161
|
+
|
162
|
+
response.stack_summaries.each do |stack|
|
163
|
+
if stack.stack_name =~ /^#{prefix}$|^#{prefix}-(.+)/
|
164
|
+
stack_list[stack.creation_time] = stack.stack_name
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
next_token = response.next_token
|
169
|
+
break if next_token.nil?
|
170
|
+
end
|
171
|
+
|
172
|
+
stack_list.empty? ? nil : stack_list[stack_list.keys.sort.last]
|
173
|
+
end
|
174
|
+
|
175
|
+
def upload_to_s3(bucket, key, body)
|
176
|
+
@s3_client.put_object(
|
177
|
+
bucket: bucket,
|
178
|
+
key: key,
|
179
|
+
body: body,
|
180
|
+
)
|
181
|
+
end
|
182
|
+
|
183
|
+
def upload_file_to_s3(bucket, key, file_path)
|
184
|
+
File.open(file_path, "rb") do |file|
|
185
|
+
upload_to_s3(bucket, key, file)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def empty_s3_bucket(bucket_name)
|
190
|
+
@s3_client.list_objects_v2(bucket: bucket_name).contents.each do |object|
|
191
|
+
@s3_client.delete_object(bucket: bucket_name, key: object.key)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def create_zip(zip_file, files_by_name)
|
196
|
+
Zip::File.open(zip_file, create: true) do |zipfile|
|
197
|
+
base_dir = File.expand_path(File.dirname(__FILE__))
|
198
|
+
files_by_name.each do |n, f|
|
199
|
+
zipfile.add n, f
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def dir_files(base_dir, glob)
|
205
|
+
files_by_name = {}
|
206
|
+
base_dir = File.expand_path(base_dir)
|
207
|
+
Dir.glob("#{base_dir}/#{glob}").select { |path| File.file?(path) }.each do |f|
|
208
|
+
files_by_name[File.expand_path(f)[base_dir.length + 1..-1]] = f
|
209
|
+
end
|
210
|
+
files_by_name
|
211
|
+
end
|
212
|
+
|
213
|
+
def unversioned_stack_name_from_current_dir
|
214
|
+
File.basename(File.expand_path("."))
|
215
|
+
end
|
216
|
+
|
217
|
+
def workflow_files
|
218
|
+
dir_files ".", "**/*.rb"
|
219
|
+
end
|
220
|
+
|
221
|
+
def workflow_files_hash
|
222
|
+
file_hashes = []
|
223
|
+
workflow_files.each do |name, file|
|
224
|
+
file_hashes.push Digest::SHA1.file(file)
|
225
|
+
end
|
226
|
+
Digest::SHA1.hexdigest file_hashes.join(",")
|
227
|
+
end
|
228
|
+
|
229
|
+
def versioned_stack_name_from_current_dir(version)
|
230
|
+
if version
|
231
|
+
"#{unversioned_stack_name_from_current_dir}-#{version}"
|
232
|
+
else
|
233
|
+
"#{unversioned_stack_name_from_current_dir}-#{workflow_files_hash()[0...8]}"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def my_lib_files
|
238
|
+
files = dir_files(File.dirname(__FILE__) + "/..", "**/*.rb").filter { |f| not(f =~ /cloudformation\.rb|tool\.rb/) }
|
239
|
+
end
|
240
|
+
|
241
|
+
def cloudformation_template(lambda_cf_config, deploy_state_machine)
|
242
|
+
data = {
|
243
|
+
state_machine: deploy_state_machine,
|
244
|
+
}
|
245
|
+
|
246
|
+
if lambda_cf_config
|
247
|
+
data[:functions] = lambda_cf_config # see StateMachine.cloudformation_config()
|
248
|
+
end
|
249
|
+
|
250
|
+
Simplerubysteps::cloudformation_yaml(data)
|
251
|
+
end
|
252
|
+
|
253
|
+
def log(extract_pattern, version)
|
254
|
+
stack = nil
|
255
|
+
if version
|
256
|
+
stack = versioned_stack_name_from_current_dir(version)
|
257
|
+
else
|
258
|
+
stack = most_recent_stack_with_prefix unversioned_stack_name_from_current_dir
|
259
|
+
end
|
260
|
+
raise "State Machine is not deployed" unless stack
|
261
|
+
|
262
|
+
current_stack_outputs = stack_outputs(stack)
|
263
|
+
raise "State Machine is not deployed" unless current_stack_outputs
|
264
|
+
|
265
|
+
last_thread = nil
|
266
|
+
(0..current_stack_outputs["LambdaCount"].to_i - 1).each do |i|
|
267
|
+
function_name = current_stack_outputs["LambdaFunctionName#{i}"]
|
268
|
+
last_thread = Thread.new do # FIXME Less brute force approach (?)
|
269
|
+
tail_follow_logs "/aws/lambda/#{function_name}", extract_pattern
|
270
|
+
end
|
271
|
+
end
|
272
|
+
last_thread.join if last_thread
|
273
|
+
end
|
274
|
+
|
275
|
+
def destroy_stack(stack)
|
276
|
+
current_stack_outputs = stack_outputs(stack)
|
277
|
+
raise "No CloudFormation stack to destroy" unless current_stack_outputs
|
278
|
+
|
279
|
+
deploy_bucket = current_stack_outputs["DeployBucket"]
|
280
|
+
raise "No CloudFormation stack to destroy" unless deploy_bucket
|
281
|
+
|
282
|
+
empty_s3_bucket deploy_bucket
|
283
|
+
|
284
|
+
puts "Bucket emptied: #{deploy_bucket}"
|
285
|
+
|
286
|
+
@cloudformation_client.delete_stack(stack_name: stack)
|
287
|
+
@cloudformation_client.wait_until(:stack_delete_complete, stack_name: stack)
|
288
|
+
|
289
|
+
puts "Stack deleted: #{stack}"
|
290
|
+
end
|
291
|
+
|
292
|
+
def destroy(optional_version)
|
293
|
+
if optional_version
|
294
|
+
destroy_stack versioned_stack_name_from_current_dir(optional_version)
|
295
|
+
else
|
296
|
+
list_stacks_with_prefix(unversioned_stack_name_from_current_dir).each do |stack|
|
297
|
+
destroy_stack stack
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def deploy(version)
|
303
|
+
stack = versioned_stack_name_from_current_dir(version)
|
304
|
+
|
305
|
+
puts "Stack: #{stack}"
|
306
|
+
|
307
|
+
current_stack_outputs = stack_outputs(stack)
|
308
|
+
|
309
|
+
unless current_stack_outputs
|
310
|
+
current_stack_outputs = stack_create(stack, cloudformation_template(nil, false), {})
|
311
|
+
|
312
|
+
puts "Deployment bucket created"
|
313
|
+
end
|
314
|
+
|
315
|
+
deploy_bucket = current_stack_outputs["DeployBucket"]
|
316
|
+
|
317
|
+
puts "Deployment bucket: #{deploy_bucket}"
|
318
|
+
|
319
|
+
function_zip_temp = Tempfile.new("function")
|
320
|
+
create_zip function_zip_temp.path, my_lib_files.merge(workflow_files)
|
321
|
+
lambda_sha = Digest::SHA1.file function_zip_temp.path
|
322
|
+
lambda_zip_name = "function-#{lambda_sha}.zip"
|
323
|
+
upload_file_to_s3 deploy_bucket, lambda_zip_name, function_zip_temp.path
|
324
|
+
|
325
|
+
puts "Uploaded: #{lambda_zip_name}"
|
326
|
+
|
327
|
+
lambda_cf_config = JSON.parse(`ruby -e 'require "./workflow.rb";puts $sm.cloudformation_config.to_json'`)
|
328
|
+
|
329
|
+
if current_stack_outputs["LambdaCount"].nil? or current_stack_outputs["LambdaCount"].to_i != lambda_cf_config.length # FIXME Do not implicitly delete the state machine when versioning is turned off.
|
330
|
+
current_stack_outputs = stack_update(stack, cloudformation_template(lambda_cf_config, false), {
|
331
|
+
"LambdaS3" => lambda_zip_name,
|
332
|
+
})
|
333
|
+
|
334
|
+
puts "Lambda function created"
|
335
|
+
end
|
336
|
+
|
337
|
+
lambda_arns = []
|
338
|
+
(0..current_stack_outputs["LambdaCount"].to_i - 1).each do |i|
|
339
|
+
lambda_arn = current_stack_outputs["LambdaFunctionARN#{i}"]
|
340
|
+
|
341
|
+
puts "Lambda function: #{lambda_arn}"
|
342
|
+
|
343
|
+
lambda_arns.push lambda_arn
|
344
|
+
end
|
345
|
+
|
346
|
+
workflow_type = `ruby -e 'require "./workflow.rb";puts $sm.kind'`.strip
|
347
|
+
|
348
|
+
state_machine_json = JSON.parse(`LAMBDA_FUNCTION_ARNS=#{lambda_arns.join(",")} ruby -e 'require "./workflow.rb";puts $sm.render.to_json'`).to_json
|
349
|
+
state_machine_json_sha = Digest::SHA1.hexdigest state_machine_json
|
350
|
+
state_machine_json_name = "statemachine-#{state_machine_json_sha}.json"
|
351
|
+
upload_to_s3 deploy_bucket, state_machine_json_name, state_machine_json
|
352
|
+
|
353
|
+
puts "Uploaded: #{state_machine_json_name}"
|
354
|
+
|
355
|
+
current_stack_outputs = stack_update(stack, cloudformation_template(lambda_cf_config, true), { # FIXME when versioning is turned off: 1) create additional lambdas 2) update State Machine
|
356
|
+
"LambdaS3" => lambda_zip_name,
|
357
|
+
"StepFunctionsS3" => state_machine_json_name,
|
358
|
+
"StateMachineType" => workflow_type,
|
359
|
+
})
|
360
|
+
|
361
|
+
if current_stack_outputs[:no_update]
|
362
|
+
puts "Stack not updated"
|
363
|
+
else
|
364
|
+
puts "Stack updated"
|
365
|
+
end
|
366
|
+
|
367
|
+
puts "State machine: #{current_stack_outputs["StepFunctionsStateMachineARN"]}"
|
368
|
+
end
|
369
|
+
|
370
|
+
def start_sync_execution(state_machine_arn, input)
|
371
|
+
@states_client.start_sync_execution(
|
372
|
+
state_machine_arn: state_machine_arn,
|
373
|
+
input: input,
|
374
|
+
)
|
375
|
+
end
|
376
|
+
|
377
|
+
def start_async_execution(state_machine_arn, input)
|
378
|
+
@states_client.start_execution(
|
379
|
+
state_machine_arn: state_machine_arn,
|
380
|
+
input: input,
|
381
|
+
)
|
382
|
+
end
|
383
|
+
|
384
|
+
def describe_execution(execution_arn)
|
385
|
+
@states_client.describe_execution(
|
386
|
+
execution_arn: execution_arn,
|
387
|
+
)
|
388
|
+
end
|
389
|
+
|
390
|
+
def wait_for_async_execution_completion(execution_arn)
|
391
|
+
response = nil
|
392
|
+
|
393
|
+
loop do
|
394
|
+
response = describe_execution(execution_arn)
|
395
|
+
status = response.status
|
396
|
+
|
397
|
+
break if %w[SUCCEEDED FAILED TIMED_OUT].include?(status)
|
398
|
+
|
399
|
+
sleep 5
|
400
|
+
end
|
401
|
+
|
402
|
+
response
|
403
|
+
end
|
404
|
+
|
405
|
+
def start(wait, input, version)
|
406
|
+
stack = nil
|
407
|
+
if version
|
408
|
+
stack = versioned_stack_name_from_current_dir(version)
|
409
|
+
else
|
410
|
+
stack = most_recent_stack_with_prefix unversioned_stack_name_from_current_dir
|
411
|
+
end
|
412
|
+
raise "State Machine is not deployed" unless stack
|
413
|
+
|
414
|
+
current_stack_outputs = stack_outputs(stack)
|
415
|
+
raise "State Machine is not deployed" unless current_stack_outputs
|
416
|
+
|
417
|
+
state_machine_arn = current_stack_outputs["StepFunctionsStateMachineARN"]
|
418
|
+
|
419
|
+
input_json = JSON.parse(input.read).to_json
|
420
|
+
|
421
|
+
if current_stack_outputs["StateMachineType"] == "STANDARD"
|
422
|
+
start_response = start_async_execution(state_machine_arn, input_json)
|
423
|
+
|
424
|
+
unless wait
|
425
|
+
puts start_response.to_json
|
426
|
+
else
|
427
|
+
execution_arn = start_response.execution_arn
|
428
|
+
|
429
|
+
puts wait_for_async_execution_completion(execution_arn).to_json
|
430
|
+
end
|
431
|
+
elsif current_stack_outputs["StateMachineType"] == "EXPRESS"
|
432
|
+
puts start_sync_execution(state_machine_arn, input_json).to_json
|
433
|
+
else
|
434
|
+
raise "Unknown state machine type: #{current_stack_outputs["StateMachineType"]}"
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
def send_task_success(task_token, output = $stdin)
|
439
|
+
raise "No token" unless task_token
|
440
|
+
|
441
|
+
output_json = JSON.parse(output.read).to_json
|
442
|
+
|
443
|
+
puts @states_client.send_task_success(
|
444
|
+
task_token: task_token,
|
445
|
+
output: output_json,
|
446
|
+
).to_json
|
447
|
+
end
|
448
|
+
|
449
|
+
def run
|
450
|
+
options = {
|
451
|
+
:wait => false,
|
452
|
+
:input => $stdin,
|
453
|
+
:version => "latest",
|
454
|
+
:destroy_all => true,
|
455
|
+
}
|
456
|
+
|
457
|
+
subcommands = {
|
458
|
+
"deploy" => OptionParser.new do |opts|
|
459
|
+
opts.banner = "Usage: #{$0} deploy [options]"
|
460
|
+
|
461
|
+
opts.on("--version VALUE", "fix version (\"latest\" per default)") do |value|
|
462
|
+
options[:version] = value
|
463
|
+
end
|
464
|
+
|
465
|
+
opts.on("--versioned", "enable auto versioning (\"latest\" per default)") do |value|
|
466
|
+
options[:version] = nil
|
467
|
+
end
|
468
|
+
|
469
|
+
opts.on("-h", "--help", "Display this help message") do
|
470
|
+
puts opts
|
471
|
+
exit
|
472
|
+
end
|
473
|
+
end,
|
474
|
+
"destroy" => OptionParser.new do |opts|
|
475
|
+
opts.banner = "Usage: #{$0} destroy [options]"
|
476
|
+
|
477
|
+
opts.on("--version VALUE", "fix version (all versions per default)") do |value|
|
478
|
+
options[:version] = value
|
479
|
+
options[:destroy_all] = nil
|
480
|
+
end
|
481
|
+
|
482
|
+
opts.on("-h", "--help", "Display this help message") do
|
483
|
+
puts opts
|
484
|
+
exit
|
485
|
+
end
|
486
|
+
end,
|
487
|
+
"log" => OptionParser.new do |opts|
|
488
|
+
opts.banner = "Usage: #{$0} log [options]"
|
489
|
+
|
490
|
+
opts.on("--extract_pattern VALUE", "Wait for and extract pattern") do |value|
|
491
|
+
options[:extract_pattern] = value
|
492
|
+
end
|
493
|
+
|
494
|
+
opts.on("--version VALUE", "fix version (\"latest\" per default)") do |value|
|
495
|
+
options[:version] = value
|
496
|
+
end
|
497
|
+
|
498
|
+
opts.on("--most-recent-version", "Use the version of the last stack created") do |value|
|
499
|
+
options[:version] = nil
|
500
|
+
end
|
501
|
+
|
502
|
+
opts.on("-h", "--help", "Display this help message") do
|
503
|
+
puts opts
|
504
|
+
exit
|
505
|
+
end
|
506
|
+
end,
|
507
|
+
"start" => OptionParser.new do |opts|
|
508
|
+
opts.banner = "Usage: #{$0} start [options]"
|
509
|
+
|
510
|
+
opts.on("--wait", "Wait for STANDARD state machine to complete") do
|
511
|
+
options[:wait] = true
|
512
|
+
end
|
513
|
+
|
514
|
+
opts.on("--input VALUE", "/path/to/file (STDIN will be used per default)") do |value|
|
515
|
+
options[:input] = File.new(value)
|
516
|
+
end
|
517
|
+
|
518
|
+
opts.on("--version VALUE", "fix version (\"latest\" per default)") do |value|
|
519
|
+
options[:version] = value
|
520
|
+
end
|
521
|
+
|
522
|
+
opts.on("--most-recent-version", "Use the version of the last stack created") do |value|
|
523
|
+
options[:version] = nil
|
524
|
+
end
|
525
|
+
|
526
|
+
opts.on("-h", "--help", "Display this help message") do
|
527
|
+
puts opts
|
528
|
+
exit
|
529
|
+
end
|
530
|
+
end,
|
531
|
+
"task-success" => OptionParser.new do |opts|
|
532
|
+
opts.banner = "Usage: #{$0} task-success [options]"
|
533
|
+
|
534
|
+
opts.on("--input VALUE", "/path/to/file (STDIN will be used per default)") do |value|
|
535
|
+
options[:input] = File.new(value)
|
536
|
+
end
|
537
|
+
|
538
|
+
opts.on("--token VALUE", "The task token") do |value|
|
539
|
+
options[:token] = value
|
540
|
+
end
|
541
|
+
|
542
|
+
opts.on("-h", "--help", "Display this help message") do
|
543
|
+
puts opts
|
544
|
+
exit
|
545
|
+
end
|
546
|
+
end,
|
547
|
+
}
|
548
|
+
|
549
|
+
global = OptionParser.new do |opts|
|
550
|
+
opts.banner = "Usage: #{$0} [command] [options]"
|
551
|
+
opts.separator ""
|
552
|
+
opts.separator "Commands (#{Simplerubysteps::VERSION}):"
|
553
|
+
opts.separator " deploy Create Step Functions State Machine"
|
554
|
+
opts.separator " destroy Delete Step Functions State Machine"
|
555
|
+
opts.separator " log Continuously prints Lambda function log output"
|
556
|
+
opts.separator " start Start State Machine execution"
|
557
|
+
opts.separator " task-success Continue Start State Machine execution"
|
558
|
+
opts.separator ""
|
559
|
+
|
560
|
+
opts.on_tail("-h", "--help", "Display this help message") do
|
561
|
+
puts opts
|
562
|
+
exit
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
begin
|
567
|
+
global.order!(ARGV)
|
568
|
+
command = ARGV.shift
|
569
|
+
options[:command] = command
|
570
|
+
subcommands.fetch(command).parse!(ARGV)
|
571
|
+
rescue KeyError
|
572
|
+
puts "Unknown command: '#{command}'"
|
573
|
+
puts
|
574
|
+
puts global
|
575
|
+
exit 1
|
576
|
+
rescue OptionParser::ParseError => error
|
577
|
+
puts error.message
|
578
|
+
puts subcommands.fetch(command)
|
579
|
+
exit 1
|
580
|
+
end
|
581
|
+
|
582
|
+
if options[:command] == "deploy"
|
583
|
+
deploy options[:version]
|
584
|
+
elsif options[:command] == "start"
|
585
|
+
start options[:wait], options[:input], options[:version]
|
586
|
+
elsif options[:command] == "log"
|
587
|
+
log options[:extract_pattern], options[:version]
|
588
|
+
elsif options[:command] == "task-success"
|
589
|
+
send_task_success options[:token], options[:input]
|
590
|
+
elsif options[:command] == "destroy"
|
591
|
+
if options[:destroy_all]
|
592
|
+
destroy(nil)
|
593
|
+
else
|
594
|
+
destroy(options[:version])
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|