simplerubysteps 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1db80d874fc5708a39f631983f7bf584ed63eb3840a2f212db85efff25b06486
4
- data.tar.gz: 14ee38786322a3962cb48bcc64ba5c5d0606750fc24f422ef2c0ed17d962680b
3
+ metadata.gz: 41e3a9ed5b8d6c32357fa880c2826cdf18a16fb9195260c5d10c7063b7dcb474
4
+ data.tar.gz: '07180493d6f6456f41164cd74f1410fb8bcd6649a645d109011c85ec9133c463'
5
5
  SHA512:
6
- metadata.gz: 9b43275998e160fb9d47db290b973d73b56da8b829ff5e35f408f6cdb093a3dcbf7c990ceabf063733730cbd131be6a9b0369c29113a11f18317c124391656ac
7
- data.tar.gz: 5d224524a8d5f42f69cdd5e5b1fc778744e847d918e5cefca08f2115cd23503b8828f154b1f98292df0d1fd4082f79645444f67ddcccb16ff86e15a9bfffed1f
6
+ metadata.gz: 0620c89b84893c3e58078ab8dc66a211aaef5a52101a45e7392bde32bfdab3be3cc9d83bdee6e9adcfd1f3ecdc1e3420dd9068f58bea07550aad1993d0775a90
7
+ data.tar.gz: 50f9d29b51926176a2a3edc900694233f38d44511ef5115433cc756f88c74df5ffca90bc924406644580c43e1f9ca6e2b1e2f79187aa0b3c9eca003f14b2daae
data/README.md CHANGED
@@ -7,20 +7,15 @@ This is software in the experimental stage and should not really be used by anyo
7
7
  ## Installation
8
8
 
9
9
  Prerequisites (for alpha version):
10
- * Linux-like environment (the deployment tools are currently implemented with shell scripts)
11
10
  * AWS CLI installed
12
11
 
13
- Add this line to your application's Gemfile:
14
-
15
- ```ruby
16
- require "simplerubysteps"
17
- ```
18
-
19
- And install the gem:
12
+ ## Usage
20
13
 
21
- $ gem install simplerubysteps
14
+ ### Install the gem and the simplerubysteps CLI
22
15
 
23
- ## Usage
16
+ ```
17
+ gem install simplerubysteps
18
+ ```
24
19
 
25
20
  ### Create AWS Step Functions State Machine with ruby DSL
26
21
 
@@ -29,12 +24,12 @@ cd samples/sample1
29
24
  vi workflow.rb
30
25
  ```
31
26
 
32
- ### Create CloudFormation stack with Step Functions State Machine and supporting Lambda functions
27
+ ### Create CloudFormation stack with Step Functions State Machine and supporting Lambda function
33
28
 
34
29
  ```
35
30
  export AWS_PROFILE=...
36
31
  cd samples/sample1
37
- simplerubysteps-deploy
32
+ simplerubysteps deploy
38
33
  ```
39
34
 
40
35
  ### Trigger State Machine Execution and wait for completion
@@ -42,7 +37,11 @@ simplerubysteps-deploy
42
37
  ```
43
38
  export AWS_PROFILE=...
44
39
  cd samples/sample1
45
- echo '{"foo": "James Bond"}' | simplerubysteps-workflow-run
40
+
41
+ ./start-directbranch.sh
42
+
43
+ ./sample-task-worker.sh &
44
+ ./start-callbackbranch.sh
46
45
  ```
47
46
 
48
47
  ### Delete CloudFormation stack
@@ -50,19 +49,16 @@ echo '{"foo": "James Bond"}' | simplerubysteps-workflow-run
50
49
  ```
51
50
  export AWS_PROFILE=...
52
51
  cd samples/sample1
53
- simplerubysteps-destroy
52
+ simplerubysteps destroy
54
53
  ```
55
54
 
56
55
  ## Development
57
56
 
58
- After checking out the repo, run `bin/setup` to install dependencies.
59
-
60
57
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
61
58
 
62
59
  ### TODOs
63
60
 
64
- * Custom IAM role policies (Step Functions and Lambda)
65
- * sls-like tooling in ruby with AWS SDK
61
+ * Custom IAM policies per Lambda task
66
62
  * Workflow action unit test support
67
63
  * ...
68
64
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ bin_dir = File.expand_path(File.dirname(__FILE__))
4
+ include_path = File.join(bin_dir, "../lib/tool.rb")
5
+
6
+ require include_path
data/lib/function.rb CHANGED
@@ -2,9 +2,9 @@ require "json"
2
2
  require "./workflow.rb"
3
3
 
4
4
  def handler(event:, context:)
5
- puts ENV.inspect # FIXME remove DEBUG code
6
- puts event # FIXME remove DEBUG code
7
- puts context.inspect # FIXME remove DEBUG code
5
+ puts ENV.inspect if ENV["DEBUG"]
6
+ puts event if ENV["DEBUG"]
7
+ puts context.inspect if ENV["DEBUG"]
8
8
 
9
9
  if event["Token"]
10
10
  $sm.states[event["Task"].to_sym].perform_action event["Input"], event["Token"]
@@ -1,3 +1,3 @@
1
1
  module Simplerubysteps
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.7"
3
3
  end
data/lib/tool.rb ADDED
@@ -0,0 +1,448 @@
1
+ require "aws-sdk-cloudformation"
2
+ require "aws-sdk-s3"
3
+ require "aws-sdk-states"
4
+ require "digest"
5
+ require "zip"
6
+ require "tempfile"
7
+ require "json"
8
+ require "optparse"
9
+ require "aws-sdk-cloudwatchlogs"
10
+ require "time"
11
+
12
+ $cloudformation_client = Aws::CloudFormation::Client.new
13
+ $s3_client = Aws::S3::Client.new
14
+ $states_client = Aws::States::Client.new
15
+ $logs_client = Aws::CloudWatchLogs::Client.new
16
+
17
+ def tail_follow_logs(log_group_name, extract_pattern = nil) # FIXME too hacky and not really working
18
+ Signal.trap("INT") do
19
+ exit
20
+ end
21
+
22
+ first_event_time = Time.now.to_i * 1000
23
+
24
+ next_tokens = {}
25
+ first_round = true
26
+ loop do
27
+ log_streams = $logs_client.describe_log_streams(
28
+ log_group_name: log_group_name,
29
+ order_by: "LastEventTime",
30
+ descending: true,
31
+ ).log_streams
32
+
33
+ log_streams.each do |log_stream|
34
+ get_log_events_params = {
35
+ log_group_name: log_group_name,
36
+ log_stream_name: log_stream.log_stream_name,
37
+ }
38
+
39
+ if next_tokens.key?(log_stream.log_stream_name)
40
+ get_log_events_params[:next_token] = next_tokens[log_stream.log_stream_name]
41
+ else
42
+ get_log_events_params[:start_time] = first_round ? log_stream.last_event_timestamp : first_event_time
43
+ end
44
+
45
+ response = $logs_client.get_log_events(get_log_events_params)
46
+
47
+ response.events.each do |event|
48
+ if event.timestamp >= first_event_time
49
+ if extract_pattern
50
+ if /#{extract_pattern}/ =~ event.message
51
+ puts $1
52
+ exit
53
+ end
54
+ else
55
+ puts "#{Time.at(event.timestamp / 1000).utc} - #{log_stream.log_stream_name} - #{event.message}"
56
+ end
57
+ end
58
+ end
59
+
60
+ next_tokens[log_stream.log_stream_name] = response.next_forward_token
61
+ end
62
+
63
+ sleep 5
64
+
65
+ first_round = false
66
+ end
67
+ end
68
+
69
+ def stack_outputs(stack_name)
70
+ begin
71
+ response = $cloudformation_client.describe_stacks(stack_name: stack_name)
72
+ outputs = {}
73
+ response.stacks.first.outputs.each do |output|
74
+ outputs[output.output_key] = output.output_value
75
+ end
76
+ outputs
77
+ rescue Aws::CloudFormation::Errors::ServiceError => error
78
+ return nil if error.message =~ /Stack .* does not exist/
79
+ raise error
80
+ end
81
+ end
82
+
83
+ def stack_params(stack_name, template, parameters)
84
+ params = {
85
+ stack_name: stack_name,
86
+ template_body: template,
87
+ capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
88
+ parameters: [],
89
+ }
90
+ parameters.each do |k, v|
91
+ params[:parameters].push({
92
+ parameter_key: k,
93
+ parameter_value: v,
94
+ })
95
+ end
96
+ params
97
+ end
98
+
99
+ def stack_create(stack_name, template, parameters)
100
+ $cloudformation_client.create_stack(stack_params(stack_name, template, parameters))
101
+ $cloudformation_client.wait_until(:stack_create_complete, stack_name: stack_name)
102
+ stack_outputs(stack_name)
103
+ end
104
+
105
+ def stack_update(stack_name, template, parameters)
106
+ begin
107
+ $cloudformation_client.update_stack(stack_params(stack_name, template, parameters))
108
+ $cloudformation_client.wait_until(:stack_update_complete, stack_name: stack_name)
109
+ stack_outputs(stack_name)
110
+ rescue Aws::CloudFormation::Errors::ServiceError => error
111
+ return stack_outputs(stack_name).merge({ :no_update => true }) if error.message =~ /No updates are to be performed/
112
+ raise unless error.message =~ /No updates are to be performed/
113
+ end
114
+ end
115
+
116
+ def upload_to_s3(bucket, key, body)
117
+ $s3_client.put_object(
118
+ bucket: bucket,
119
+ key: key,
120
+ body: body,
121
+ )
122
+ end
123
+
124
+ def upload_file_to_s3(bucket, key, file_path)
125
+ File.open(file_path, "rb") do |file|
126
+ upload_to_s3(bucket, key, file)
127
+ end
128
+ end
129
+
130
+ def empty_s3_bucket(bucket_name)
131
+ $s3_client.list_objects_v2(bucket: bucket_name).contents.each do |object|
132
+ $s3_client.delete_object(bucket: bucket_name, key: object.key)
133
+ end
134
+ end
135
+
136
+ def create_zip(zip_file, files_by_name)
137
+ Zip::File.open(zip_file, create: true) do |zipfile|
138
+ base_dir = File.expand_path(File.dirname(__FILE__))
139
+ files_by_name.each do |n, f|
140
+ zipfile.add n, f
141
+ end
142
+ end
143
+ end
144
+
145
+ def dir_files(base_dir, glob)
146
+ files_by_name = {}
147
+ base_dir = File.expand_path(base_dir)
148
+ Dir.glob("#{base_dir}/#{glob}").select { |path| File.file?(path) }.each do |f|
149
+ files_by_name[File.expand_path(f)[base_dir.length + 1..-1]] = f
150
+ end
151
+ files_by_name
152
+ end
153
+
154
+ def stack_name_from_current_dir
155
+ File.basename(File.expand_path("."))
156
+ end
157
+
158
+ def workflow_files
159
+ dir_files ".", "**/*.rb"
160
+ end
161
+
162
+ def my_lib_files
163
+ dir_files File.dirname(__FILE__), "**/*.rb"
164
+ end
165
+
166
+ def cloudformation_template
167
+ File.open("#{File.dirname(__FILE__)}/statemachine.yaml", "r") do |file|
168
+ return file.read
169
+ end
170
+ end
171
+
172
+ def log(extract_pattern = nil)
173
+ current_stack_outputs = stack_outputs(stack_name_from_current_dir)
174
+ function_name = current_stack_outputs["LambdaFunctionName"]
175
+ rause "State Machine is not deployed" unless function_name
176
+
177
+ tail_follow_logs "/aws/lambda/#{function_name}", extract_pattern
178
+ end
179
+
180
+ def destroy
181
+ current_stack_outputs = stack_outputs(stack_name_from_current_dir)
182
+ deploy_bucket = current_stack_outputs["DeployBucket"]
183
+ rause "No CloudFormation stack to destroy" unless deploy_bucket
184
+
185
+ empty_s3_bucket deploy_bucket
186
+
187
+ puts "Bucket emptied: #{deploy_bucket}"
188
+
189
+ $cloudformation_client.delete_stack(stack_name: stack_name_from_current_dir)
190
+ $cloudformation_client.wait_until(:stack_delete_complete, stack_name: stack_name_from_current_dir)
191
+
192
+ puts "Stack deleted"
193
+ end
194
+
195
+ def deploy(workflow_type)
196
+ current_stack_outputs = stack_outputs(stack_name_from_current_dir)
197
+
198
+ unless current_stack_outputs
199
+ current_stack_outputs = stack_create(stack_name_from_current_dir, cloudformation_template, {
200
+ "DeployLambda" => "no",
201
+ "DeployStepfunctions" => "no",
202
+ "LambdaS3" => "",
203
+ "StepFunctionsS3" => "",
204
+ "StateMachineType" => "",
205
+ })
206
+
207
+ puts "Deployment bucket created"
208
+ end
209
+
210
+ deploy_bucket = current_stack_outputs["DeployBucket"]
211
+ puts "Deployment bucket: #{deploy_bucket}"
212
+
213
+ function_zip_temp = Tempfile.new("function")
214
+ create_zip function_zip_temp.path, my_lib_files.merge(workflow_files)
215
+ lambda_sha = Digest::SHA1.file function_zip_temp.path
216
+ lambda_zip_name = "function-#{lambda_sha}.zip"
217
+ upload_file_to_s3 deploy_bucket, lambda_zip_name, function_zip_temp.path
218
+ puts "Uploaded: #{lambda_zip_name}"
219
+
220
+ unless current_stack_outputs["LambdaFunctionARN"]
221
+ current_stack_outputs = stack_update(stack_name_from_current_dir, cloudformation_template, {
222
+ "DeployLambda" => "yes",
223
+ "DeployStepfunctions" => "no",
224
+ "LambdaS3" => lambda_zip_name,
225
+ "StepFunctionsS3" => "",
226
+ "StateMachineType" => "",
227
+ })
228
+
229
+ puts "Lambda function created"
230
+ end
231
+
232
+ lambda_arn = current_stack_outputs["LambdaFunctionARN"]
233
+ puts "Lambda function: #{lambda_arn}"
234
+
235
+ state_machine_json = JSON.parse(`LAMBDA_FUNCTION_ARN=#{lambda_arn} ruby -e 'require "./workflow.rb";puts $sm.render.to_json'`).to_json
236
+ state_machine_json_sha = Digest::SHA1.hexdigest state_machine_json
237
+ state_machine_json_name = "statemachine-#{state_machine_json_sha}.json"
238
+ upload_to_s3 deploy_bucket, state_machine_json_name, state_machine_json
239
+ puts "Uploaded: #{state_machine_json_name}"
240
+
241
+ current_stack_outputs = stack_update(stack_name_from_current_dir, cloudformation_template, {
242
+ "DeployLambda" => "yes",
243
+ "DeployStepfunctions" => "yes",
244
+ "LambdaS3" => lambda_zip_name,
245
+ "StepFunctionsS3" => state_machine_json_name,
246
+ "StateMachineType" => workflow_type,
247
+ })
248
+
249
+ if current_stack_outputs[:no_update]
250
+ puts "Stack not updated"
251
+ else
252
+ puts "Stack updated"
253
+ end
254
+
255
+ puts "State machine: #{current_stack_outputs["StepFunctionsStateMachineARN"]}"
256
+ end
257
+
258
+ def start_sync_execution(state_machine_arn, input)
259
+ $states_client.start_sync_execution(
260
+ state_machine_arn: state_machine_arn,
261
+ input: input,
262
+ )
263
+ end
264
+
265
+ def start_async_execution(state_machine_arn, input)
266
+ $states_client.start_execution(
267
+ state_machine_arn: state_machine_arn,
268
+ input: input,
269
+ )
270
+ end
271
+
272
+ def describe_execution(execution_arn)
273
+ $states_client.describe_execution(
274
+ execution_arn: execution_arn,
275
+ )
276
+ end
277
+
278
+ def wait_for_async_execution_completion(execution_arn)
279
+ response = nil
280
+
281
+ loop do
282
+ response = describe_execution(execution_arn)
283
+ status = response.status
284
+
285
+ break if %w[SUCCEEDED FAILED TIMED_OUT].include?(status)
286
+
287
+ sleep 5
288
+ end
289
+
290
+ response
291
+ end
292
+
293
+ def start(workflow_type, wait = true, input = $stdin)
294
+ current_stack_outputs = stack_outputs(stack_name_from_current_dir)
295
+ state_machine_arn = current_stack_outputs["StepFunctionsStateMachineARN"]
296
+ raise "State Machine is not deployed" unless state_machine_arn
297
+
298
+ input_json = JSON.parse(input.read).to_json
299
+
300
+ if workflow_type == "STANDARD"
301
+ start_response = start_async_execution(state_machine_arn, input_json)
302
+
303
+ unless wait
304
+ puts start_response.to_json
305
+ else
306
+ execution_arn = start_response.execution_arn
307
+
308
+ puts wait_for_async_execution_completion(execution_arn).to_json
309
+ end
310
+ elsif workflow_type == "EXPRESS"
311
+ puts start_sync_execution(state_machine_arn, input_json).to_json
312
+ else
313
+ raise "Unknown state machine type: #{workflow_type}"
314
+ end
315
+ end
316
+
317
+ def send_task_success(task_token, output = $stdin)
318
+ raise "No token" unless task_token
319
+
320
+ output_json = JSON.parse(output.read).to_json
321
+
322
+ puts $states_client.send_task_success(
323
+ task_token: task_token,
324
+ output: output_json,
325
+ ).to_json
326
+ end
327
+
328
+ options = {
329
+ :workflow_type => "STANDARD",
330
+ :wait => false,
331
+ :input => $stdin,
332
+ }
333
+
334
+ subcommands = {
335
+ "deploy" => OptionParser.new do |opts|
336
+ opts.banner = "Usage: #{$0} deploy [options]"
337
+
338
+ opts.on("--type VALUE", "STANDARD (default) or EXPRESS") do |value|
339
+ options[:workflow_type] = value
340
+ end
341
+
342
+ opts.on("-h", "--help", "Display this help message") do
343
+ puts opts
344
+ exit
345
+ end
346
+ end,
347
+ "destroy" => OptionParser.new do |opts|
348
+ opts.banner = "Usage: #{$0} destroy [options]"
349
+
350
+ opts.on("-h", "--help", "Display this help message") do
351
+ puts opts
352
+ exit
353
+ end
354
+ end,
355
+ "log" => OptionParser.new do |opts|
356
+ opts.banner = "Usage: #{$0} log [options]"
357
+
358
+ opts.on("--extract_pattern VALUE", "Waits for and extracts pattern") do |value|
359
+ options[:extract_pattern] = value
360
+ end
361
+
362
+ opts.on("-h", "--help", "Display this help message") do
363
+ puts opts
364
+ exit
365
+ end
366
+ end,
367
+ "start" => OptionParser.new do |opts|
368
+ opts.banner = "Usage: #{$0} start [options]"
369
+
370
+ opts.on("--type VALUE", "STANDARD (default) or EXPRESS") do |value|
371
+ options[:workflow_type] = value
372
+ end
373
+
374
+ opts.on("--wait VALUE", "true (default and always true for EXPRESS) or false (default for STANDARD)") do |value|
375
+ options[:wait] = "true" == value
376
+ end
377
+
378
+ opts.on("--input VALUE", "/path/to/file (STDIN will be used per default)") do |value|
379
+ options[:input] = File.new(value)
380
+ end
381
+
382
+ opts.on("-h", "--help", "Display this help message") do
383
+ puts opts
384
+ exit
385
+ end
386
+ end,
387
+ "task-success" => OptionParser.new do |opts|
388
+ opts.banner = "Usage: #{$0} task-success [options]"
389
+
390
+ opts.on("--input VALUE", "/path/to/file (STDIN will be used per default)") do |value|
391
+ options[:input] = File.new(value)
392
+ end
393
+
394
+ opts.on("--token VALUE", "The task token") do |value|
395
+ options[:token] = value
396
+ end
397
+
398
+ opts.on("-h", "--help", "Display this help message") do
399
+ puts opts
400
+ exit
401
+ end
402
+ end,
403
+ }
404
+
405
+ global = OptionParser.new do |opts|
406
+ opts.banner = "Usage: #{$0} [command] [options]"
407
+ opts.separator ""
408
+ opts.separator "Commands:"
409
+ opts.separator " deploy Create Step Functions State Machine"
410
+ opts.separator " destroy Delete Step Functions State Machine"
411
+ opts.separator " log Continuously prints Lambda function log output"
412
+ opts.separator " start Start State Machine execution"
413
+ opts.separator " task-success Continue Start State Machine execution"
414
+ opts.separator ""
415
+
416
+ opts.on_tail("-h", "--help", "Display this help message") do
417
+ puts opts
418
+ exit
419
+ end
420
+ end
421
+
422
+ begin
423
+ global.order!(ARGV)
424
+ command = ARGV.shift
425
+ options[:command] = command
426
+ subcommands.fetch(command).parse!(ARGV)
427
+ rescue KeyError
428
+ puts "Unknown command: '#{command}'"
429
+ puts
430
+ puts global
431
+ exit 1
432
+ rescue OptionParser::ParseError => error
433
+ puts error.message
434
+ puts subcommands.fetch(command)
435
+ exit 1
436
+ end
437
+
438
+ if options[:command] == "deploy"
439
+ deploy options[:workflow_type]
440
+ elsif options[:command] == "start"
441
+ start options[:workflow_type], options[:wait], options[:input]
442
+ elsif options[:command] == "log"
443
+ log options[:extract_pattern]
444
+ elsif options[:command] == "task-success"
445
+ send_task_success options[:token], options[:input]
446
+ elsif options[:command] == "destroy"
447
+ destroy
448
+ end
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ TOKEN=$(simplerubysteps log --extract_pattern 'callback_token=(.+)')
4
+
5
+ echo '{"willo":"billo"}'|simplerubysteps task-success --token $TOKEN
@@ -1,3 +1,3 @@
1
1
  #!/bin/bash
2
2
 
3
- echo '{"foo": "John Wick"}'|simplerubysteps-workflow-run
3
+ echo '{"foo": "John Wick"}'|simplerubysteps start --wait true|jq
@@ -1,3 +1,3 @@
1
1
  #!/bin/bash
2
2
 
3
- echo '{"foo": "James Bond"}'|simplerubysteps-workflow-run
3
+ echo '{"foo": "James Bond"}'|simplerubysteps start --wait true|jq -r ".output"|jq
@@ -13,7 +13,7 @@ task :t1 do
13
13
  string_matches "$.Foo1", "ja" do
14
14
  callback :t3 do
15
15
  action do |input, token|
16
- puts "Callback t3: #{input}, #{token}" # The logged token is picked up by continue-callbackbranch.sh
16
+ puts "Callback t3: #{input}, callback_token=#{token}" # The logged token is picked up by continue-callbackbranch.sh
17
17
  end
18
18
 
19
19
  transition :t5
@@ -24,4 +24,10 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 1.17"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
+
28
+ spec.add_dependency "aws-sdk-cloudformation"
29
+ spec.add_dependency "aws-sdk-s3"
30
+ spec.add_dependency "aws-sdk-states"
31
+ spec.add_dependency "aws-sdk-cloudwatchlogs"
32
+ spec.add_dependency "rubyzip"
27
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simplerubysteps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Tschenett
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-12 00:00:00.000000000 Z
11
+ date: 2023-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,15 +38,81 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: aws-sdk-cloudformation
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aws-sdk-s3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk-states
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: aws-sdk-cloudwatchlogs
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubyzip
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
41
111
  description:
42
112
  email:
43
113
  - simplerubysteps@furthermore.ch
44
114
  executables:
45
- - simplerubysteps-deploy
46
- - simplerubysteps-destroy
47
- - simplerubysteps-logs
48
- - simplerubysteps-workflow-run
49
- - simplerubysteps-workflow-run-sync
115
+ - simplerubysteps
50
116
  extensions: []
51
117
  extra_rdoc_files: []
52
118
  files:
@@ -57,22 +123,13 @@ files:
57
123
  - Rakefile
58
124
  - bin/console
59
125
  - bin/setup
60
- - exe/simplerubysteps-deploy
61
- - exe/simplerubysteps-destroy
62
- - exe/simplerubysteps-logs
63
- - exe/simplerubysteps-workflow-run
64
- - exe/simplerubysteps-workflow-run-sync
65
- - lib/deploy.sh
66
- - lib/destroy.sh
126
+ - exe/simplerubysteps
67
127
  - lib/function.rb
68
- - lib/logs.sh
69
128
  - lib/simplerubysteps.rb
70
129
  - lib/simplerubysteps/version.rb
71
130
  - lib/statemachine.yaml
72
- - lib/workflow-run-sync.sh
73
- - lib/workflow-run.sh
74
- - samples/sample1/continue-callbackbranch.sh
75
- - samples/sample1/send-task-success.sh
131
+ - lib/tool.rb
132
+ - samples/sample1/sample-task-worker.sh
76
133
  - samples/sample1/start-callbackbranch.sh
77
134
  - samples/sample1/start-directbranch.sh
78
135
  - samples/sample1/workflow.rb
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- bin_dir = File.expand_path(File.dirname(__FILE__))
4
- shell_script_path = File.join(bin_dir, "../lib/deploy.sh")
5
-
6
- Kernel.exec(shell_script_path)
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- bin_dir = File.expand_path(File.dirname(__FILE__))
4
- shell_script_path = File.join(bin_dir, "../lib/destroy.sh")
5
-
6
- Kernel.exec(shell_script_path)
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- bin_dir = File.expand_path(File.dirname(__FILE__))
4
- shell_script_path = File.join(bin_dir, "../lib/logs.sh")
5
-
6
- Kernel.exec(shell_script_path)
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- bin_dir = File.expand_path(File.dirname(__FILE__))
4
- shell_script_path = File.join(bin_dir, "../lib/workflow-run.sh")
5
-
6
- Kernel.exec(shell_script_path)
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- bin_dir = File.expand_path(File.dirname(__FILE__))
4
- shell_script_path = File.join(bin_dir, "../lib/workflow-run-sync.sh")
5
-
6
- Kernel.exec(shell_script_path)
data/lib/deploy.sh DELETED
@@ -1,92 +0,0 @@
1
- #!/bin/bash
2
-
3
- SCRIPT_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
4
-
5
- export STACK_NAME=$(basename "$PWD")
6
-
7
- echo "CF Stack: $STACK_NAME"
8
-
9
- export CF_TEMPLATE=$SCRIPT_DIR/../lib/statemachine.yaml
10
-
11
- export DEPLOY_BUCKET=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep DeployBucket|awk '{print $2}')
12
-
13
- if [[ -n "$DEPLOY_BUCKET" ]]; then
14
- echo "Deployment bucket found: $DEPLOY_BUCKET"
15
- else
16
- echo "Creating deloyment bucket"
17
-
18
- echo '[{"ParameterKey":"DeployLambda","ParameterValue":"no"},{"ParameterKey":"DeployStepfunctions","ParameterValue":"no"}]' > /tmp/params.json
19
-
20
- aws cloudformation deploy \
21
- --template-file $CF_TEMPLATE \
22
- --stack-name $STACK_NAME \
23
- --capabilities '["CAPABILITY_IAM","CAPABILITY_NAMED_IAM"]' \
24
- --parameter-overrides file:///tmp/params.json
25
-
26
- aws cloudformation wait stack-create-complete \
27
- --stack-name $STACK_NAME || \
28
- { echo "Stack creation/update failed." >&2; exit 1; }
29
-
30
- export DEPLOY_BUCKET=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep DeployBucket|awk '{print $2}')
31
- fi
32
-
33
- echo "Uploading lambda ZIP"
34
-
35
- rm -f /tmp/function.zip
36
- zip /tmp/function.zip *.rb
37
- (cd $SCRIPT_DIR/../lib; zip -r /tmp/function.zip *.rb)
38
- (cd $SCRIPT_DIR/../lib; zip -r /tmp/function.zip simplerubysteps/*.rb)
39
-
40
- export LAMBDA_SHA=$(shasum /tmp/function.zip | awk '{print $1}')
41
- export UPLOADED_LAMBDA_ZIP=function-$LAMBDA_SHA.zip
42
- aws s3 cp /tmp/function.zip s3://$DEPLOY_BUCKET/$UPLOADED_LAMBDA_ZIP
43
-
44
- export LAMBDA_FUNCTION_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep LambdaFunctionARN|awk '{print $2}')
45
-
46
- if [[ -n "$LAMBDA_FUNCTION_ARN" ]]; then
47
- echo "Lambda ARN found: $LAMBDA_FUNCTION_ARN"
48
- else
49
- echo "Creating lambda"
50
-
51
- echo '[{"ParameterKey":"DeployLambda","ParameterValue":"yes"},{"ParameterKey":"DeployStepfunctions","ParameterValue":"no"},{"ParameterKey":"LambdaS3","ParameterValue":"'$UPLOADED_LAMBDA_ZIP'"}]' > /tmp/params.json
52
-
53
- aws cloudformation deploy \
54
- --template-file $CF_TEMPLATE \
55
- --stack-name $STACK_NAME \
56
- --capabilities '["CAPABILITY_IAM","CAPABILITY_NAMED_IAM"]' \
57
- --parameter-overrides file:///tmp/params.json
58
-
59
- aws cloudformation wait stack-update-complete \
60
- --stack-name $STACK_NAME || \
61
- { echo "Stack update failed." >&2; exit 1; }
62
-
63
- export LAMBDA_FUNCTION_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep LambdaFunctionARN|awk '{print $2}')
64
- fi
65
-
66
- echo "Uploading state machine JSON"
67
-
68
- ruby -e 'require "./workflow.rb";puts $sm.render.to_json' > /tmp/my-state-machine-definition.json
69
- export WF_TYPE=$(ruby -e 'require "./workflow.rb";puts $sm.kind')
70
- export STATE_MACHINE_JSON_SHA=$(shasum /tmp/my-state-machine-definition.json | awk '{print $1}')
71
- export UPLOADED_STATE_MACHINE_JSON=statemachine-$STATE_MACHINE_JSON_SHA.zip
72
- aws s3 cp /tmp/my-state-machine-definition.json s3://$DEPLOY_BUCKET/$UPLOADED_STATE_MACHINE_JSON
73
-
74
- echo "Updating CloudFormation Stack"
75
-
76
- echo '[{"ParameterKey":"DeployLambda","ParameterValue":"yes"},{"ParameterKey":"DeployStepfunctions","ParameterValue":"yes"},{"ParameterKey":"LambdaS3","ParameterValue":"'$UPLOADED_LAMBDA_ZIP'"},{"ParameterKey":"StepFunctionsS3","ParameterValue":"'$UPLOADED_STATE_MACHINE_JSON'"},{"ParameterKey":"StateMachineType","ParameterValue":"'$WF_TYPE'"}]' > /tmp/params.json
77
-
78
- aws cloudformation deploy \
79
- --template-file $CF_TEMPLATE \
80
- --stack-name $STACK_NAME \
81
- --capabilities '["CAPABILITY_IAM","CAPABILITY_NAMED_IAM"]' \
82
- --parameter-overrides file:///tmp/params.json
83
-
84
- aws cloudformation wait stack-update-complete \
85
- --stack-name $STACK_NAME || \
86
- { echo "Stack update failed." >&2; exit 1; }
87
-
88
- export STEP_FUNCTIONS_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep StepFunctionsStateMachineARN|awk '{print $2}')
89
-
90
- echo "StepFunctions ARN found: $STEP_FUNCTIONS_ARN"
91
-
92
- echo "Done"
data/lib/destroy.sh DELETED
@@ -1,10 +0,0 @@
1
- #!/bin/bash
2
-
3
- export STACK_NAME=$(basename "$PWD")
4
-
5
- export DEPLOY_BUCKET=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep DeployBucket|awk '{print $2}')
6
-
7
- aws s3 rm s3://$DEPLOY_BUCKET --recursive
8
-
9
- aws cloudformation delete-stack \
10
- --stack-name $STACK_NAME
data/lib/logs.sh DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
-
3
- export STACK_NAME=$(basename "$PWD")
4
-
5
- export FUNCTION_NAME=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep LambdaFunctionName|awk '{print $2}')
6
-
7
- aws logs tail /aws/lambda/$FUNCTION_NAME
@@ -1,10 +0,0 @@
1
- #!/bin/bash
2
-
3
- export STACK_NAME=$(basename "$PWD")
4
-
5
- export STEP_FUNCTIONS_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep StepFunctionsStateMachineARN|awk '{print $2}')
6
-
7
- tee /tmp/statemachineinput.json > /dev/null
8
- STATE_MACHINE_INPUT="$(cat /tmp/statemachineinput.json)"
9
-
10
- aws stepfunctions start-sync-execution --state-machine-arn $STEP_FUNCTIONS_ARN --input "$STATE_MACHINE_INPUT" --query "output" --output text
data/lib/workflow-run.sh DELETED
@@ -1,39 +0,0 @@
1
- #!/bin/bash
2
-
3
- export STACK_NAME=$(basename "$PWD")
4
-
5
- export STEP_FUNCTIONS_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --output text --query "Stacks[].Outputs[]"|grep StepFunctionsStateMachineARN|awk '{print $2}')
6
-
7
- tee /tmp/statemachineinput.json > /dev/null
8
- STATE_MACHINE_INPUT="$(cat /tmp/statemachineinput.json)"
9
-
10
- EXECUTION_ARN=$(aws stepfunctions start-execution \
11
- --state-machine-arn $STEP_FUNCTIONS_ARN \
12
- --input "$STATE_MACHINE_INPUT" \
13
- --query "executionArn" \
14
- --output text)
15
-
16
- echo "Started execution: $EXECUTION_ARN"
17
-
18
- while true; do
19
- STATUS=$(aws stepfunctions describe-execution \
20
- --execution-arn $EXECUTION_ARN \
21
- --query "status" \
22
- --output text)
23
-
24
- if [[ "$STATUS" == "SUCCEEDED" ]]; then
25
- break
26
- elif [[ "$STATUS" == "FAILED" || "$STATUS" == "TIMED_OUT" || "$STATUS" == "ABORTED" ]]; then
27
- echo "Execution failed with status: $STATUS"
28
- exit 1
29
- else
30
- sleep 5
31
- fi
32
- done
33
-
34
- OUTPUT=$(aws stepfunctions describe-execution \
35
- --execution-arn $EXECUTION_ARN \
36
- --query "output" \
37
- --output text)
38
-
39
- echo "Execution output: $OUTPUT"
@@ -1,5 +0,0 @@
1
- #!/bin/bash
2
-
3
- TOKEN=$(simplerubysteps-logs|grep Token|sort|tail -n 1|ruby -ne 'print $1 if /Token\"=>\"(.+)\"/')
4
-
5
- echo "{\"continued\":\"$(date)\"}"|./send-task-success.sh $TOKEN
@@ -1,6 +0,0 @@
1
- #!/bin/bash
2
-
3
- tee /tmp/taskoutput.json > /dev/null
4
- TASK_OUTPUT="$(cat /tmp/taskoutput.json)"
5
-
6
- aws stepfunctions send-task-success --task-token="$1" --task-output "$TASK_OUTPUT"