Reputation: 557
I've created a setup that works to generate state machines, however for some reason it does not work for the two specific Task
s GlueStartJobRun
and StepFunctionsStartExecution
. Here is part of my current setup:
.
├── app.py
├── cloudformation
│ ├── stepfunctions.py # includes `stack`
├── statemachines
│ ├── some_workflow.py
│ └── another_workflow.py
└── ...
Inside of the stepfunctions.py
, i define my stack and a way to generate state machines:
import dataclasses
from aws_cdk import aws_stepfunctions
from constructs import Construct
@dataclasses.dataclass
class StateMachineUtil:
name: str
definition: aws_stepfunctions.Chain
from aws_cdk import Stack
class StepfunctionStack(Stack):
def __init__(self, scope: Construct, env: Environment):
super().__init__(scope, env=env)
def generate_state_machines(self, state_machines):
[self.__generate_state_machine(state_machine) for state_machine in state_machines]
def __generate_state_machine(self, state_machine):
return aws_stepfunctions.StateMachine(
scope=self,
id=f"{state_machine.name}-statemachine",
definition=state_machine.definition,
state_machine_name=state_machine.name,
)
Then, i define a function inside the workflow-scripts which returns a definition
, which is
from aws_cdk.aws_stepfunctions_tasks import CallAwsService
from aws_cdk.aws_stepfunctions import Pass
def generate_some_definition(scope: Construct) -> aws_stepfunctions.Chain:
step_1 = Pass(
scope=scope,
id="some-id",
)
step_2 = CallAwsService(
scope=scope,
id="another-id",
service="glue",
action="GetTable",
iam=["*"],
parameters={...}
result_path="..."
)
step_3 = Pass(
scope=scope,
id="a-third-id",
)
return step_1.next(step_2).next(step_3)
The script app.py
should now simply put everything together:
from cloudformation.stepfunctions import StepfunctionStack, StateMachineUtil
from statemachines.some_workflow import generate_some_definition
from statemachines.another_workflow import generate_another_definition
app = aws_cdk.App()
env = aws_cdk.Environment(account=12345, region="eu-west-1")
mystack = StepfunctionStack(scope=app, env=env)
mystack.generate_state_machines(
[
StateMachineUtil(name="a-name", definition=generate_some_definition(scope=app)),
StateMachineUtil(name="another-name", definition=generate_another_definition(scope=app)),
]
)
This setup works perfectly fine. No problem, i run cdk synth
and i get no error message. However, if I try to setup a workflow.py
that uses StepFunctionsStartExecution
or GlueStartJobRun
, then i get the error message:
RuntimeError: StepFunctionsStartExecution at '' should be created in the scope of a Stack, but no Stack found
Here is what the workflow.py
could look like (same as before, but with 2 added tasks):
from aws_cdk.aws_stepfunctions_tasks import CallAwsService, GlueStartJobRun, StepFunctionsStartExecution
from aws_cdk.aws_stepfunctions import Pass, IntegrationPattern, TaskInput
def generate_some_definition(scope: Construct, crawler_state_machine: aws_stepfunctions.IStateMachine) -> aws_stepfunctions.Chain:
step_1 = Pass(
scope=scope,
id="a-fourth-id",
)
step_2 = StepFunctionsStartExecution(
scope=scope,
id="Run separate state machine",
state_machine=separate_state_machine,
integration_pattern=IntegrationPattern.RUN_JOB,
input=TaskInput.from_object({...}),
result_selector={...}
)
step_3 = GlueStartJobRun(
scope=scope,
id="Run glue job",
glue_job_name="...",
integration_pattern=IntegrationPattern.RUN_JOB,
arguments=TaskInput.from_json_path_at("...")
)
step_4 = CallAwsService(
scope=scope,
id="another-one-id",
service="glue",
action="GetTable",
iam=["*"],
parameters={...}
result_path="..."
)
step_5 = Pass(
scope=scope,
id="an-eighth-id",
)
return step_1.next(step_2).next(step_3).next(step_4).next(step_5)
And suddenly, it breaks down. Giving me the error message i posted above.
Upvotes: 0
Views: 1191
Reputation: 11589
As the error message says, the scope
parameter you pass to the StepFunctionsStartExecution
constructor should contain a stack at some point in the tree.
You are passing an App
, and there is no Stack
in the scope, so this fails.
Pass a stack as the scope. Alternatively, pass any construct created within the scope of a stack (or within the scope of a construct created within the scope of a stack - you get the point)
Upvotes: 4