Skip to content

Commit c2df06a

Browse files
authored
feat: Add State Property to Schedule EventSource in StateMachine (#2468)
1 parent 9820834 commit c2df06a

8 files changed

+704
-7
lines changed

samtranslator/model/stepfunctions/events.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
from samtranslator.model import PropertyType, ResourceMacro
55
from samtranslator.model.events import EventsRule
66
from samtranslator.model.iam import IAMRole, IAMRolePolicies
7-
from samtranslator.model.types import dict_of, is_str, is_type, list_of, one_of
7+
from samtranslator.model.types import is_str, is_type
88
from samtranslator.model.intrinsics import fnSub
99
from samtranslator.translator import logical_id_generator
10-
from samtranslator.model.exceptions import InvalidEventException, InvalidResourceException
10+
from samtranslator.model.exceptions import InvalidEventException
1111
from samtranslator.model.eventbridge_utils import EventBridgeRuleUtils
1212
from samtranslator.model.eventsources.push import Api as PushApi
13-
from samtranslator.translator.arn_generator import ArnGenerator
1413
from samtranslator.swagger.swagger import SwaggerEditor
15-
from samtranslator.open_api.open_api import OpenApiEditor
1614

1715
CONDITION = "Condition"
1816
SFN_EVETSOURCE_METRIC_PREFIX = "SFNEventSource"
@@ -82,6 +80,7 @@ class Schedule(EventSource):
8280
"Schedule": PropertyType(True, is_str()),
8381
"Input": PropertyType(False, is_str()),
8482
"Enabled": PropertyType(False, is_type(bool)),
83+
"State": PropertyType(False, is_str()),
8584
"Name": PropertyType(False, is_str()),
8685
"Description": PropertyType(False, is_str()),
8786
"DeadLetterConfig": PropertyType(False, is_type(dict)),
@@ -105,8 +104,16 @@ def to_cloudformation(self, resource, **kwargs):
105104
resources.append(events_rule)
106105

107106
events_rule.ScheduleExpression = self.Schedule
107+
108+
if self.State and self.Enabled is not None:
109+
raise InvalidEventException(self.relative_id, "State and Enabled Properties cannot both be specified.")
110+
111+
if self.State:
112+
events_rule.State = self.State
113+
108114
if self.Enabled is not None:
109115
events_rule.State = "ENABLED" if self.Enabled else "DISABLED"
116+
110117
events_rule.Name = self.Name
111118
events_rule.Description = self.Description
112119

tests/model/stepfunctions/test_schedule_event.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from unittest import TestCase
33
from samtranslator.model.stepfunctions.events import Schedule
44
from samtranslator.model.exceptions import InvalidEventException
5+
from parameterized import parameterized
56

67

78
class ScheduleEventSource(TestCase):
@@ -72,12 +73,18 @@ def test_to_cloudformation_returns_eventrule_and_role_resources(self):
7273
def test_to_cloudformation_throws_when_no_resource(self):
7374
self.assertRaises(TypeError, self.schedule_event_source.to_cloudformation)
7475

75-
def test_to_cloudformation_when_event_is_disabled(self):
76+
def test_to_cloudformation_transforms_enabled_boolean_to_state(self):
77+
self.schedule_event_source.Enabled = True
78+
resources = self.schedule_event_source.to_cloudformation(resource=self.state_machine)
79+
self.assertEqual(len(resources), 2)
80+
schedule = resources[0]
81+
self.assertEqual(schedule.State, "ENABLED")
82+
7683
self.schedule_event_source.Enabled = False
7784
resources = self.schedule_event_source.to_cloudformation(resource=self.state_machine)
7885
self.assertEqual(len(resources), 2)
79-
event_rule = resources[0]
80-
self.assertEqual(event_rule.State, "DISABLED")
86+
schedule = resources[0]
87+
self.assertEqual(schedule.State, "DISABLED")
8188

8289
def test_to_cloudformation_with_input(self):
8390
input_to_service = '{"test_key": "test_value"}'
@@ -144,3 +151,19 @@ def test_to_cloudformation_with_dlq_generated_with_intrinsic_function_custom_log
144151
self.schedule_event_source.DeadLetterConfig = dead_letter_config
145152
with self.assertRaises(InvalidEventException):
146153
self.schedule_event_source.to_cloudformation(resource=self.state_machine)
154+
155+
@parameterized.expand(
156+
[
157+
(True, "Enabled"),
158+
(True, "Disabled"),
159+
(True, {"FN:FakeIntrinsic": "something"}),
160+
(False, "Enabled"),
161+
(False, "Disabled"),
162+
(False, {"FN:FakeIntrinsic": "something"}),
163+
]
164+
)
165+
def test_to_cloudformation_invalid_defined_both_enabled_and_state_provided(self, enabled_value, state_value):
166+
self.schedule_event_source.Enabled = enabled_value
167+
self.schedule_event_source.State = state_value
168+
with self.assertRaises(InvalidEventException):
169+
self.schedule_event_source.to_cloudformation(resource=self.state_machine)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Transform: "AWS::Serverless-2016-10-31"
2+
3+
Resources:
4+
ScheduledStateMachine:
5+
Type: 'AWS::Serverless::StateMachine'
6+
Properties:
7+
DefinitionUri: s3://sam-demo-bucket/my_state_machine.asl.json
8+
Role: arn:aws:iam::123456123456:role/service-role/SampleRole
9+
Events:
10+
Schedule1:
11+
Type: Schedule
12+
Properties:
13+
Schedule: 'rate(1 minute)'
14+
Name: TestSchedule
15+
Description: test schedule
16+
State: "Enabled"
17+
Enabled: True
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Transform: "AWS::Serverless-2016-10-31"
2+
3+
Resources:
4+
ScheduledStateMachine:
5+
Type: 'AWS::Serverless::StateMachine'
6+
Properties:
7+
DefinitionUri: s3://sam-demo-bucket/my_state_machine.asl.json
8+
Role: arn:aws:iam::123456123456:role/service-role/SampleRole
9+
Events:
10+
Schedule1:
11+
Type: Schedule
12+
Properties:
13+
Schedule: 'rate(1 minute)'
14+
Name: test-schedule
15+
Description: Test Schedule
16+
State: "Enabled"
17+
Schedule2:
18+
Type: Schedule
19+
Properties:
20+
Schedule: 'rate(1 minute)'
21+
Name: test-schedule
22+
Description: Test Schedule
23+
State: !Sub "Enabled"
24+
Schedule3:
25+
Type: Schedule
26+
Properties:
27+
Schedule: 'rate(1 minute)'
28+
Name: test-schedule
29+
Description: Test Schedule
30+
State: !Ref ScheduleState
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
{
2+
"Resources": {
3+
"ScheduledStateMachine": {
4+
"Type": "AWS::StepFunctions::StateMachine",
5+
"Properties": {
6+
"DefinitionS3Location": {
7+
"Bucket": "sam-demo-bucket",
8+
"Key": "my_state_machine.asl.json"
9+
},
10+
"RoleArn": "arn:aws:iam::123456123456:role/service-role/SampleRole",
11+
"Tags": [
12+
{
13+
"Key": "stateMachine:createdBy",
14+
"Value": "SAM"
15+
}
16+
]
17+
}
18+
},
19+
"ScheduledStateMachineSchedule1": {
20+
"Type": "AWS::Events::Rule",
21+
"Properties": {
22+
"Description": "Test Schedule",
23+
"Name": "test-schedule",
24+
"ScheduleExpression": "rate(1 minute)",
25+
"State": "Enabled",
26+
"Targets": [
27+
{
28+
"Arn": {
29+
"Ref": "ScheduledStateMachine"
30+
},
31+
"Id": "ScheduledStateMachineSchedule1StepFunctionsTarget",
32+
"RoleArn": {
33+
"Fn::GetAtt": [
34+
"ScheduledStateMachineSchedule1Role",
35+
"Arn"
36+
]
37+
}
38+
}
39+
]
40+
}
41+
},
42+
"ScheduledStateMachineSchedule1Role": {
43+
"Type": "AWS::IAM::Role",
44+
"Properties": {
45+
"AssumeRolePolicyDocument": {
46+
"Version": "2012-10-17",
47+
"Statement": [
48+
{
49+
"Action": [
50+
"sts:AssumeRole"
51+
],
52+
"Effect": "Allow",
53+
"Principal": {
54+
"Service": [
55+
"events.amazonaws.com"
56+
]
57+
}
58+
}
59+
]
60+
},
61+
"Policies": [
62+
{
63+
"PolicyName": "ScheduledStateMachineSchedule1RoleStartExecutionPolicy",
64+
"PolicyDocument": {
65+
"Statement": [
66+
{
67+
"Action": "states:StartExecution",
68+
"Effect": "Allow",
69+
"Resource": {
70+
"Ref": "ScheduledStateMachine"
71+
}
72+
}
73+
]
74+
}
75+
}
76+
]
77+
}
78+
},
79+
"ScheduledStateMachineSchedule2": {
80+
"Type": "AWS::Events::Rule",
81+
"Properties": {
82+
"Description": "Test Schedule",
83+
"Name": "test-schedule",
84+
"ScheduleExpression": "rate(1 minute)",
85+
"State": {
86+
"Fn::Sub": "Enabled"
87+
},
88+
"Targets": [
89+
{
90+
"Arn": {
91+
"Ref": "ScheduledStateMachine"
92+
},
93+
"Id": "ScheduledStateMachineSchedule2StepFunctionsTarget",
94+
"RoleArn": {
95+
"Fn::GetAtt": [
96+
"ScheduledStateMachineSchedule2Role",
97+
"Arn"
98+
]
99+
}
100+
}
101+
]
102+
}
103+
},
104+
"ScheduledStateMachineSchedule2Role": {
105+
"Type": "AWS::IAM::Role",
106+
"Properties": {
107+
"AssumeRolePolicyDocument": {
108+
"Version": "2012-10-17",
109+
"Statement": [
110+
{
111+
"Action": [
112+
"sts:AssumeRole"
113+
],
114+
"Effect": "Allow",
115+
"Principal": {
116+
"Service": [
117+
"events.amazonaws.com"
118+
]
119+
}
120+
}
121+
]
122+
},
123+
"Policies": [
124+
{
125+
"PolicyName": "ScheduledStateMachineSchedule2RoleStartExecutionPolicy",
126+
"PolicyDocument": {
127+
"Statement": [
128+
{
129+
"Action": "states:StartExecution",
130+
"Effect": "Allow",
131+
"Resource": {
132+
"Ref": "ScheduledStateMachine"
133+
}
134+
}
135+
]
136+
}
137+
}
138+
]
139+
}
140+
},
141+
"ScheduledStateMachineSchedule3": {
142+
"Type": "AWS::Events::Rule",
143+
"Properties": {
144+
"Description": "Test Schedule",
145+
"Name": "test-schedule",
146+
"ScheduleExpression": "rate(1 minute)",
147+
"State": {
148+
"Ref": "ScheduleState"
149+
},
150+
"Targets": [
151+
{
152+
"Arn": {
153+
"Ref": "ScheduledStateMachine"
154+
},
155+
"Id": "ScheduledStateMachineSchedule3StepFunctionsTarget",
156+
"RoleArn": {
157+
"Fn::GetAtt": [
158+
"ScheduledStateMachineSchedule3Role",
159+
"Arn"
160+
]
161+
}
162+
}
163+
]
164+
}
165+
},
166+
"ScheduledStateMachineSchedule3Role": {
167+
"Type": "AWS::IAM::Role",
168+
"Properties": {
169+
"AssumeRolePolicyDocument": {
170+
"Version": "2012-10-17",
171+
"Statement": [
172+
{
173+
"Action": [
174+
"sts:AssumeRole"
175+
],
176+
"Effect": "Allow",
177+
"Principal": {
178+
"Service": [
179+
"events.amazonaws.com"
180+
]
181+
}
182+
}
183+
]
184+
},
185+
"Policies": [
186+
{
187+
"PolicyName": "ScheduledStateMachineSchedule3RoleStartExecutionPolicy",
188+
"PolicyDocument": {
189+
"Statement": [
190+
{
191+
"Action": "states:StartExecution",
192+
"Effect": "Allow",
193+
"Resource": {
194+
"Ref": "ScheduledStateMachine"
195+
}
196+
}
197+
]
198+
}
199+
}
200+
]
201+
}
202+
}
203+
}
204+
}

0 commit comments

Comments
 (0)