armara
armara

Reputation: 557

CDK scope-error when executing external jobs

I've created a setup that works to generate state machines, however for some reason it does not work for the two specific Tasks 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

Answers (1)

gshpychka
gshpychka

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

Related Questions