aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.57k stars 3.88k forks source link

stepfunctions: CDK to CFN template is serializing incorrectly #26111

Open srivastavr opened 1 year ago

srivastavr commented 1 year ago

Describe the bug

Issue Description

Hi,

We are passing array of array in payload from step function to a lambda function, below is the sample code

            lambdaFunction: serviceCallHandler,
            resultSelector: resultSelector,
            resultPath: resultPath,
            payload: TaskInput.fromObject({
                key1: [
                    [
                        {
                            key2: {
                                key3: 'value1',
                            },
                            key4: [
                                [
                                    {
                                        key5: {
                                            key6: 'value2',
                                        },
                                    },
                                ],
                            ],
                        },
                    ],
                ],
            }),
        }

but after building, the cloud formation template converts this into array of objects with 0 index at places which is incorrect.

like this

 {
        "Ref": "AWS::Partition"
       },
       ":states:::lambda:invoke\",\"Parameters\":{\"FunctionName\":\"",
       {
        "Fn::GetAtt": [
         "servicecallhandler3F6E12B2",
         "Arn"
        ]
       },
       "\",\"Payload\":{\"key1\":[{\"0\":{\"key2\":{\"key3\":\"value1\"},\"key4\":[{\"0\":{\"key5\":{\"key6\":\"value2\"}}}]}}]}}}

Expected Behavior

 {
        "Ref": "AWS::Partition"
       },
       ":states:::lambda:invoke\",\"Parameters\":{\"FunctionName\":\"",
       {
        "Fn::GetAtt": [
         "servicecallhandler3F6E12B2",
         "Arn"
        ]
       },
       "\",\"Payload\":{\"key1\":[[{\"key2\":{\"key3\":\"value1\"},\"key4\":[[{\"key5\":{\"key6\":\"value2\"}]}]}}]]}}

Observed Behavior

Test Cases

NA

Other Details

No response

Expected Behavior

 {
        "Ref": "AWS::Partition"
       },
       ":states:::lambda:invoke\",\"Parameters\":{\"FunctionName\":\"",
       {
        "Fn::GetAtt": [
         "servicecallhandler3F6E12B2",
         "Arn"
        ]
       },
       "\",\"Payload\":{\"key1\":[[{\"key2\":{\"key3\":\"value1\"},\"key4\":[[{\"key5\":{\"key6\":\"value2\"}]}]}}]]}}

Current Behavior

{
        "Ref": "AWS::Partition"
       },
       ":states:::lambda:invoke\",\"Parameters\":{\"FunctionName\":\"",
       {
        "Fn::GetAtt": [
         "servicecallhandler3F6E12B2",
         "Arn"
        ]
       },
       "\",\"Payload\":{\"key1\":[{\"0\":{\"key2\":{\"key3\":\"value1\"},\"key4\":[{\"0\":{\"key5\":{\"key6\":\"value2\"}}}]}}]}}}

Reproduction Steps

building the typescript code

Possible Solution

The serialization is implemented in CDK:

https://github.com/aws/aws-cdk/blob/a79794e3f2609e6efa5cf659eec039964a8ad61c/packages/aws-cdk-lib/aws-stepfunctions/lib/input.ts#L21-L23

Additional Information/Context

No response

CDK CLI Version

"aws-cdk": "^2.72.0"

Framework Version

No response

Node.js Version

NodeJS/releases/default.331411.0

OS

Linux

Language

Typescript

Language Version

"typescript": "^4.9.4"

Other information

No response

srivastavr commented 1 year ago

reference from CFN : https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/1722

pahud commented 1 year ago

This is the code I used to reproduce this issue

export class Demo2Stack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const obj = {
      key1: [
          [
              {
                  key2: {
                      key3: 'value1',
                  },
                  key4: [
                      [
                          {
                              key5: {
                                  key6: 'value2',
                              },
                          },
                      ],
                  ],
              },
          ],
      ],
    }
    const payload = sfn.TaskInput.fromObject(obj)
    const invoke = new sfntasks.LambdaInvoke(this, 'Invoke Func', {
      lambdaFunction: getLambdaFunction(this),
      payload,
    });

    new sfn.StateMachine(this, 'StateMachine', {
      definition: invoke,
    })

    new CfnOutput(this, 'input', { value: JSON.stringify(payload) })
  };
};

I can confirm the CfnOutput is serialized correctly:

Outputs:
  input:
    Value: '{"type":1,"value":{"key1":[[{"key2":{"key3":"value1"},"key4":[[{"key5":{"key6":"value2"}}]]}]]}}'

But the state machine DefinitionString is not serialized correctly:

 StateMachine2E01A3A5:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      RoleArn:
        Fn::GetAtt:
          - StateMachineRoleB840431D
          - Arn
      DefinitionString:
        Fn::Join:
          - ""
          - - '{"StartAt":"Invoke Func","States":{"Invoke Func":{"End":true,"Retry":[{"ErrorEquals":["Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2}],"Type":"Task","Resource":"arn:'
            - Ref: AWS::Partition
            - :states:::lambda:invoke","Parameters":{"FunctionName":"
            - Fn::GetAtt:
                - Func217E03A4
                - Arn
            - '","Payload":{"key1":[{"0":{"key2":{"key3":"value1"},"key4":[{"0":{"key5":{"key6":"value2"}}}]}}]}}}}}'
srivastavr commented 10 months ago

Hi, Any updates ?

sakurai-ryo commented 10 months ago

Hello @srivastavr, maybe this PR has solved the problem. https://github.com/aws/aws-cdk/pull/26055