aws-flow 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/aws/decider/options.rb +23 -18
- data/lib/aws/decider/task_poller.rb +2 -2
- data/lib/aws/decider/utilities.rb +8 -3
- data/lib/aws/decider/version.rb +1 -1
- data/lib/aws/replayer.rb +113 -32
- data/spec/aws/decider/unit/decider_spec.rb +43 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDI2ZDNmZmEwMDNiODkwZWY0ODBkZDI0ZDM1OTFjZjBjZGU4YzJjZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzExMWQ1YjhkZjZmZWVlMTQ4MDU4NTFmNjkxYjUwNTVjMTU5YTIxMA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWRkNTIyNjk3ZmNkM2E4NWNjYTU3NTIyNTE0NjhjOGEzZjY5YjAwMDcwMTRj
|
10
|
+
YWNhOTNlM2E3M2E4ZDdhNGYzNGY4OTU4MjljMjBhOTIwMjIwNGNlYWVkM2Y0
|
11
|
+
MzVjODgyYjcyYjQ3NWU3NTJhNzM1M2RkNDNmNDI0MTJkMzUzNDQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjA3NDUyYWVmOTJiMzUwODMwZTVjOGY3ODhlYWY1YzBmYTM4NzdjOWUyYjZh
|
14
|
+
ZGU2YjMxNTBjYTgyMGYzY2RiNTEyMWM1NzZiOGNhZTI1MDc5ZjI1NjhiY2Yy
|
15
|
+
ZWI4ZTU5NWMzZTI1NTZkYzNiNjA4YTA5NTdjNTI1YzMyYmYxMmU=
|
data/lib/aws/decider/options.rb
CHANGED
@@ -537,43 +537,50 @@ module AWS
|
|
537
537
|
def data_converter; FlowConstants.default_data_converter; end
|
538
538
|
end
|
539
539
|
|
540
|
+
# Default values for a registered activity type. These values are set by
|
541
|
+
# default for all activities that use the activity type.
|
540
542
|
class ActivityRegistrationDefaults < ActivityDefaults
|
541
543
|
|
542
|
-
# The default schedule-to-start timeout for activity tasks.
|
543
|
-
# represents the time, in seconds, between when the activity
|
544
|
-
# scheduled to when it is started.
|
544
|
+
# *Optional*. The default schedule-to-start timeout for activity tasks.
|
545
|
+
# This timeout represents the time, in seconds, between when the activity
|
546
|
+
# task is first scheduled to when it is started.
|
545
547
|
#
|
546
548
|
# This default can be overridden when scheduling an activity task. You can
|
547
549
|
# set this value to "NONE" to imply no timeout value.
|
548
550
|
def default_task_schedule_to_start_timeout; Float::INFINITY; end
|
549
551
|
|
550
|
-
# The default schedule-to-close timeout for activity tasks.
|
551
|
-
# represents the time, in seconds, between when the activity
|
552
|
-
# scheduled to when it is closed (whether due to success,
|
553
|
-
# timeout).
|
552
|
+
# *Optional*. The default schedule-to-close timeout for activity tasks.
|
553
|
+
# This timeout represents the time, in seconds, between when the activity
|
554
|
+
# task is first scheduled to when it is closed (whether due to success,
|
555
|
+
# failure, or a timeout).
|
554
556
|
#
|
555
557
|
# This default can be overridden when scheduling an activity task. You can
|
556
558
|
# set this value to "NONE" to imply no timeout value.
|
557
|
-
def default_task_schedule_to_close_timeout;
|
559
|
+
def default_task_schedule_to_close_timeout; Float::INFINITY; end
|
558
560
|
|
559
|
-
# The default start-to-close timeout for activity tasks. This
|
560
|
-
# represents the time, in seconds, between when the activity task
|
561
|
-
# started to when it is closed (whether due to success, failure,
|
562
|
-
# timeout).
|
561
|
+
# *Optional*. The default start-to-close timeout for activity tasks. This
|
562
|
+
# timeout represents the time, in seconds, between when the activity task
|
563
|
+
# is first started to when it is closed (whether due to success, failure,
|
564
|
+
# or a timeout).
|
563
565
|
#
|
564
566
|
# This default can be overridden when scheduling an activity task. You can
|
565
567
|
# set this value to "NONE" to imply no timeout value.
|
566
568
|
def default_task_start_to_close_timeout; Float::INFINITY; end
|
567
569
|
|
568
|
-
# The default maximum time, in seconds, before which a worker
|
569
|
-
# task of this type must report progress.
|
570
|
-
# activity task is automatically timed out. If the worker
|
571
|
-
# attempts to record a heartbeat or returns a result, it will
|
570
|
+
# *Optional*. The default maximum time, in seconds, before which a worker
|
571
|
+
# processing a task of this type must report progress. If the timeout is
|
572
|
+
# exceeded, the activity task is automatically timed out. If the worker
|
573
|
+
# subsequently attempts to record a heartbeat or returns a result, it will
|
574
|
+
# be ignored.
|
572
575
|
#
|
573
576
|
# This default can be overridden when scheduling an activity task. You can
|
574
577
|
# set this value to "NONE" to imply no timeout value.
|
575
578
|
def default_task_heartbeat_timeout; Float::INFINITY; end
|
576
579
|
|
580
|
+
# *Optional*. The default task list to use for all activities that use
|
581
|
+
# this activity type. If not specified, the value
|
582
|
+
# `FlowConstants.use_worker_task_list` will be used, which causes the
|
583
|
+
# activities to use the task list specified for the activity worker.
|
577
584
|
def default_task_list; FlowConstants.use_worker_task_list; end
|
578
585
|
end
|
579
586
|
|
@@ -746,7 +753,6 @@ module AWS
|
|
746
753
|
end
|
747
754
|
result
|
748
755
|
end
|
749
|
-
|
750
756
|
end
|
751
757
|
|
752
758
|
# This class is used to capture the options passed during activity declaration.
|
@@ -786,7 +792,6 @@ module AWS
|
|
786
792
|
def get_registration_options
|
787
793
|
get_options(self.class.registration_options)
|
788
794
|
end
|
789
|
-
|
790
795
|
end
|
791
796
|
|
792
797
|
# Runtime options for an activity.
|
@@ -61,7 +61,7 @@ module AWS
|
|
61
61
|
@logger.debug "Didn't get a task on task_list: #{@task_list}"
|
62
62
|
return false
|
63
63
|
end
|
64
|
-
@logger.info Utilities.workflow_task_to_debug_string("Got decision task", task)
|
64
|
+
@logger.info Utilities.workflow_task_to_debug_string("Got decision task", task, @task_list)
|
65
65
|
|
66
66
|
task_completed_request = @handler.handle_decision_task(task)
|
67
67
|
@logger.debug "Response to the task will be #{task_completed_request.inspect}"
|
@@ -93,7 +93,7 @@ module AWS
|
|
93
93
|
end
|
94
94
|
@logger.error "#{task.workflow_type.inspect} failed with exception: #{e.inspect}"
|
95
95
|
end
|
96
|
-
@logger.info Utilities.workflow_task_to_debug_string("Finished executing task", task)
|
96
|
+
@logger.info Utilities.workflow_task_to_debug_string("Finished executing task", task, @task_list)
|
97
97
|
rescue AWS::SimpleWorkflow::Errors::UnknownResourceFault => e
|
98
98
|
@logger.error "Error in the poller, #{e.inspect}"
|
99
99
|
rescue Exception => e
|
@@ -33,11 +33,16 @@ module AWS
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def self.workflow_task_to_debug_string(message, task)
|
37
|
-
|
36
|
+
def self.workflow_task_to_debug_string(message, task, task_list)
|
37
|
+
"#{message} #{task.workflow_type.name}.#{task.workflow_type.version} "\
|
38
|
+
"for execution with workflow_id: #{task.workflow_execution.workflow_id}, "\
|
39
|
+
"run_id: #{task.workflow_execution.run_id}, task_list: #{task_list} with "\
|
40
|
+
"task_token: #{task.task_token}"
|
38
41
|
end
|
42
|
+
|
39
43
|
def self.activity_task_to_debug_string(message, task)
|
40
|
-
|
44
|
+
"#{message} #{task.activity_type.name}.#{task.activity_type.version} "\
|
45
|
+
"with input: #{task.input} and task_token: #{task.task_token}"
|
41
46
|
end
|
42
47
|
|
43
48
|
# The following two methods are used to generate an error string when
|
data/lib/aws/decider/version.rb
CHANGED
data/lib/aws/replayer.rb
CHANGED
@@ -1,32 +1,59 @@
|
|
1
1
|
module AWS
|
2
2
|
module Flow
|
3
|
+
# Provides a number of classes useful for debugging workflow executions. For
|
4
|
+
# an example of general use, see {WorkflowReplayer}.
|
5
|
+
#
|
3
6
|
module Replayer
|
4
7
|
require 'aws/decider'
|
5
8
|
include AWS::Flow
|
6
9
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
10
|
+
# Used by {Replayer} to fetch a [DecisionTask][] which will be used by
|
11
|
+
# {DecisionTaskHandler}.
|
12
|
+
#
|
13
|
+
# [DecisionTask]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/DecisionTask.html
|
14
|
+
#
|
15
|
+
# @abstract Implement the `get_history_page` and `get_execution_info` methods to
|
16
|
+
# use it.
|
11
17
|
class DecisionTaskProvider
|
12
18
|
|
13
|
-
#
|
14
|
-
# workflow type
|
15
|
-
# decider to work on
|
19
|
+
# Fetches the workflow history and wraps all the history events,
|
20
|
+
# workflow type and workflow execution inside a decision task for the
|
21
|
+
# decider to work on.
|
22
|
+
#
|
23
|
+
# @param replay_upto [Fixnum] *Optional*. The event_id of the last event
|
24
|
+
# to return. If set, returns the history only until the specified
|
25
|
+
# event is reached. If not set, then all available history will be
|
26
|
+
# returned. See [HistoryEvent][] for more information.
|
27
|
+
#
|
28
|
+
# [HistoryEvent]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/HistoryEvent.html
|
29
|
+
#
|
30
|
+
# @return [DecisionTask] the workflow history encapsulated in a
|
31
|
+
# [DecisionTask][], optionally truncated to the event ID passed to
|
32
|
+
# `replay_upto`.
|
33
|
+
#
|
34
|
+
# [DecisionTask]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/DecisionTask.html
|
35
|
+
#
|
16
36
|
def get_decision_task(replay_upto = nil)
|
37
|
+
|
17
38
|
# Get workflow execution info so that we can populate the workflowType
|
18
|
-
# and execution fields of the DecisionTask.
|
39
|
+
# and execution fields of the [DecisionTask][].
|
40
|
+
#
|
41
|
+
# [DecisionTask]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/DecisionTask.html
|
42
|
+
#
|
19
43
|
execution_info = get_execution_info
|
20
44
|
events = get_history
|
21
45
|
|
22
46
|
# Truncate history if replay_upto variable is set so that we only
|
23
47
|
# replay the history till the specified event
|
48
|
+
#
|
24
49
|
events = truncate_history(events, replay_upto)
|
25
50
|
return nil if events.nil?
|
26
51
|
|
27
|
-
# Generate the hash to instantiate a DecisionTask. We can set
|
28
|
-
# taskToken and nextPageToken to nil since we don't need the
|
29
|
-
# in the replayer
|
52
|
+
# Generate the hash to instantiate a [DecisionTask][]. We can set
|
53
|
+
# *taskToken* and *nextPageToken* to nil since we don't need the
|
54
|
+
# values in the replayer.
|
55
|
+
#
|
56
|
+
# [DecisionTask]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/DecisionTask.html
|
30
57
|
data = {
|
31
58
|
'taskToken' => nil,
|
32
59
|
'workflowExecution' => execution_info["execution"],
|
@@ -37,8 +64,17 @@ module AWS
|
|
37
64
|
AWS::SimpleWorkflow::DecisionTask.new(nil, nil, data)
|
38
65
|
end
|
39
66
|
|
40
|
-
#
|
41
|
-
#
|
67
|
+
# Truncates workflow history to a specified event id.
|
68
|
+
#
|
69
|
+
# @param events the workflow history (events) to truncate.
|
70
|
+
#
|
71
|
+
# @param replay_upto [Fixnum] *Optional*. The event ID of the final
|
72
|
+
# [HistoryEvent][] to return.
|
73
|
+
#
|
74
|
+
# [HistoryEvent]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/HistoryEvent.html
|
75
|
+
#
|
76
|
+
# @return the truncated list of events.
|
77
|
+
#
|
42
78
|
def truncate_history(events, replay_upto = nil)
|
43
79
|
return nil if events.nil? || events.empty?
|
44
80
|
|
@@ -52,21 +88,44 @@ module AWS
|
|
52
88
|
truncated
|
53
89
|
end
|
54
90
|
|
55
|
-
#
|
56
|
-
#
|
91
|
+
# Fetches the workflow history. Implementing classes *must* override
|
92
|
+
# this method.
|
93
|
+
#
|
94
|
+
# @param page_token *Optional*. A token used to get further pages of
|
95
|
+
# workflow history if all events could not be retrieved by the first
|
96
|
+
# call to the method.
|
97
|
+
#
|
98
|
+
# @return a list of [HistoryEvent][]s that comprise the workflow's
|
99
|
+
# available history.
|
100
|
+
#
|
101
|
+
# [HistoryEvent]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/HistoryEvent.html
|
102
|
+
#
|
57
103
|
def get_history(page_token = nil); end
|
58
104
|
|
59
|
-
#
|
60
|
-
# DecisionTask details. Implementing classes must override this
|
105
|
+
# Fetches the workflow execution information used to fill in the
|
106
|
+
# [DecisionTask][] details. Implementing classes *must* override this
|
107
|
+
# method.
|
108
|
+
#
|
109
|
+
# @return the workflow execution information as returned by
|
110
|
+
# [AWS::SimpleWorkflow::Client#describe_workflow_execution][].
|
111
|
+
#
|
112
|
+
# [AWS::SimpleWorkflow::Client#describe_workflow_execution]: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/SimpleWorkflow/Client.html#describe_workflow_execution-instance_method
|
61
113
|
def get_execution_info; end
|
62
114
|
|
63
115
|
end
|
64
116
|
|
65
|
-
#
|
66
|
-
# SimpleWorkflowService
|
117
|
+
# Loads a decision task directly from the AWS Simple Workflow Service.
|
67
118
|
class ServiceDecisionTaskProvider < DecisionTaskProvider
|
68
119
|
attr_reader :domain, :execution, :swf
|
69
120
|
|
121
|
+
# Initialize a new **ServiceDecisionTaskProvider**.
|
122
|
+
#
|
123
|
+
# @param options a hash of options to provide. Entries for `:domain` and
|
124
|
+
# `:execution` must be present in the hash.
|
125
|
+
#
|
126
|
+
# @raise |ArgumentError| if either `:domain` or `:execution` is missing
|
127
|
+
# from the *options* parameter.
|
128
|
+
#
|
70
129
|
def initialize(options = {})
|
71
130
|
raise ArgumentError.new("options hash must contain :domain") if options[:domain].nil?
|
72
131
|
raise ArgumentError.new("options hash must contain :execution") if options[:execution].nil?
|
@@ -75,6 +134,7 @@ module AWS
|
|
75
134
|
@swf = AWS::SimpleWorkflow.new.client
|
76
135
|
end
|
77
136
|
|
137
|
+
# Get the complete workflow history.
|
78
138
|
def get_history
|
79
139
|
events = []
|
80
140
|
# Get the first page of the workflow history
|
@@ -89,9 +149,12 @@ module AWS
|
|
89
149
|
events
|
90
150
|
end
|
91
151
|
|
92
|
-
#
|
152
|
+
# Fetches a page of workflow history.
|
153
|
+
#
|
154
|
+
# @param page_token *Optional*. A page token used to retrieve a
|
155
|
+
# particular page of results.
|
93
156
|
def get_history_page(page_token = nil)
|
94
|
-
#
|
157
|
+
# Generate the request options for the service call. Optionally merge
|
95
158
|
# next_page_token to the hash if the page_token value is not nil.
|
96
159
|
request_opts = {
|
97
160
|
domain: @domain,
|
@@ -101,8 +164,11 @@ module AWS
|
|
101
164
|
@swf.get_workflow_execution_history(request_opts)
|
102
165
|
end
|
103
166
|
|
104
|
-
#
|
105
|
-
# information
|
167
|
+
# Call AWS Simple Workflow Service to get workflow execution
|
168
|
+
# information.
|
169
|
+
#
|
170
|
+
# @return the execution information based on the `:execution` and
|
171
|
+
# `:domain` provided as input to the class constructor.
|
106
172
|
def get_execution_info
|
107
173
|
execution = @swf.describe_workflow_execution(
|
108
174
|
domain: @domain,
|
@@ -113,14 +179,15 @@ module AWS
|
|
113
179
|
|
114
180
|
end
|
115
181
|
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
182
|
+
# An AWS Flow Framework utility used to replay a workflow history in the
|
183
|
+
# decider against the workflow implementation. Primarily used for
|
184
|
+
# debugging workflows.
|
119
185
|
#
|
120
|
-
# Usage
|
186
|
+
# ## Usage
|
121
187
|
#
|
122
|
-
#
|
188
|
+
# **Create an instance of the replayer with the required options:**
|
123
189
|
#
|
190
|
+
# ~~~~
|
124
191
|
# replayer = AWS::Flow::Replayer::WorkflowReplayer.new(
|
125
192
|
# domain: '<domain_name>',
|
126
193
|
# execution: {
|
@@ -129,14 +196,25 @@ module AWS
|
|
129
196
|
# },
|
130
197
|
# workflow_class: WorkflowClass
|
131
198
|
# )
|
199
|
+
# ~~~~
|
132
200
|
#
|
133
|
-
#
|
201
|
+
# **Call the replay method (optionally) with the replay_upto event_id number**
|
134
202
|
#
|
203
|
+
# ~~~~
|
135
204
|
# decision = replayer.replay(20)
|
205
|
+
# ~~~~
|
136
206
|
#
|
137
207
|
class WorkflowReplayer
|
138
208
|
attr_reader :task_handler, :task_provider
|
139
209
|
|
210
|
+
# Initialize a new **WorkflowReplayer**.
|
211
|
+
#
|
212
|
+
# @param options A hash of options. The hash must contain at least
|
213
|
+
# `:workflow_class`.
|
214
|
+
#
|
215
|
+
# @raise |ArgumentError| if no options hash was passed in, or if the
|
216
|
+
# options are missing the `:workflow_class` key.
|
217
|
+
#
|
140
218
|
def initialize(options)
|
141
219
|
raise ArgumentError.new("You must pass in an options hash") if options.nil?
|
142
220
|
raise ArgumentError.new("options hash must contain :workflow_class") if options[:workflow_class].nil?
|
@@ -147,14 +225,17 @@ module AWS
|
|
147
225
|
@task_handler = DecisionTaskHandler.from_workflow_class(options[:workflow_class])
|
148
226
|
end
|
149
227
|
|
150
|
-
#
|
228
|
+
# Performs a replay of workflow history.
|
229
|
+
#
|
230
|
+
# @param replay_upto [Fixnum] *Optional*. If set, replays the history
|
231
|
+
# only until the specified event is reached. If not set, then all
|
232
|
+
# history will be returned.
|
233
|
+
#
|
151
234
|
def replay(replay_upto = nil)
|
152
235
|
task = @task_provider.get_decision_task(replay_upto)
|
153
236
|
@task_handler.handle_decision_task(task) unless task.nil?
|
154
237
|
end
|
155
|
-
|
156
238
|
end
|
157
|
-
|
158
239
|
end
|
159
240
|
end
|
160
241
|
end
|
@@ -1537,5 +1537,48 @@ describe "Workflow/Activity return values/exceptions" do
|
|
1537
1537
|
exception.details.should == "SIMULATED"
|
1538
1538
|
end
|
1539
1539
|
|
1540
|
+
|
1541
|
+
# A bug was introduced in the previous commit which resulted in unnecessary
|
1542
|
+
# calls to #describe_workflow_execution during logging of a DecisionTask. This
|
1543
|
+
# test ensures that we don't call describe_workflow_execution anymore.
|
1544
|
+
it "ensures describe_workflow_execution is not called during polling" do
|
1545
|
+
|
1546
|
+
swf = double("swf")
|
1547
|
+
domain = double("domain")
|
1548
|
+
allow(domain).to receive(:name).and_return("foo")
|
1549
|
+
allow(swf).to receive(:domain).and_return(domain)
|
1550
|
+
|
1551
|
+
# Set the expectations for the test
|
1552
|
+
expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125).to_not receive(:describe_workflow_execution)
|
1553
|
+
|
1554
|
+
class SomeWorkflow
|
1555
|
+
extend Workflows
|
1556
|
+
workflow(:start) do
|
1557
|
+
{
|
1558
|
+
version: "1.0",
|
1559
|
+
default_execution_start_to_close_timeout: 600,
|
1560
|
+
}
|
1561
|
+
end
|
1562
|
+
def start; end
|
1563
|
+
end
|
1564
|
+
|
1565
|
+
class SynchronousWorkflowTaskPoller < WorkflowTaskPoller
|
1566
|
+
def get_decision_task
|
1567
|
+
fake_workflow_type = FakeWorkflowType.new(nil, "SomeWorkflow.start", "1.0")
|
1568
|
+
domain = double("domain")
|
1569
|
+
TestHistoryWrapper.new(fake_workflow_type, AWS::SimpleWorkflow::WorkflowExecution.new(domain, "workflow_id", "run_id"),
|
1570
|
+
FakeEvents.new(["WorkflowExecutionStarted",
|
1571
|
+
"DecisionTaskScheduled",
|
1572
|
+
"DecisionTaskStarted",
|
1573
|
+
]))
|
1574
|
+
end
|
1575
|
+
end
|
1576
|
+
workflow_type = FakeWorkflowType.new(nil, "SomeWorkflow.entry_point", "1")
|
1577
|
+
client = workflow_client(swf, domain) { { from_class: "SomeWorkflow" } }
|
1578
|
+
|
1579
|
+
worker = SynchronousWorkflowWorker.new(swf, domain, "SomeWorkflow", SomeWorkflow)
|
1580
|
+
worker.start
|
1581
|
+
end
|
1582
|
+
|
1540
1583
|
end
|
1541
1584
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-flow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Steger, Paritosh Mohan, Jacques Thomas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-v1
|