0

I am trying to create step function using cloud formation. I want to pass the lambda arns as second argument to Fn::Sub function. It works if I pass just one Arn but fails when I pass multiple. (with Fn::Get). I checked the template with Yml validator and did not see any issues.

Cloud formation template definition for Step:

---
Resources:
  ContractDraftStateMachine:
    Type: "AWS::StepFunctions::StateMachine"
    Properties:
      RoleArn:
        Fn::GetAtt: [ StepFunctionExecutionRole, Arn ]
      DefinitionString:
        Fn::Sub:
        - |-
          {
            "Comment" : "Sample draft process",
            "StartAt" : "AdvanceWorkflowToDraftInProgress",
            "States" : {
              "AdvanceWorkflowToDraftInProgress" : {
                "Type" : "Task",
                "Resource": "${WorkflowStateChangeLambdaArn}",
                "InputPath":"$.contractId",
                "OutputPath":"$",
                "ResultPath":null,
                "Next" : "CheckQuestionnaireType",
                "Retry" : [
                  {
                    "ErrorEquals" : ["States.TaskTimeout"],
                    "MaxAttempts": 5,
                    "IntervalSeconds": 1
                  },
                  {
                    "ErrorEquals" : ["CustomErrorA"],
                    "MaxAttempts": 5
                  }
                 ],
                "Catch": [
                  {
                    "ErrorEquals": [ "States.ALL" ],
                    "Next": "FailureNotifier"
                  }
                ]
              },
 
              "CheckQuestionnaireType" : {
                "Type" : "Choice",
                "Choices" : [
                  {
                    "Variable" : "$.questionnaireType",
                    "StringEquals" : "CE",
                    "Next" : "PublishQuestionnaireAnswersToCE"
                  },
                  {
                    "Variable" : "$.questionnaireType",
                    "StringEquals" : "LEAF",
                    "Next" : "PublishQuestionnaireAnswersToLeaf"
                  }
                ]
              },
 
              "PublishQuestionnaireAnswersToCE" : {
                "Type" : "Task",
                "Resource": "${WorkflowStateChangeLambdaArn}",
                "Next" : "UpdateCEMetadataAndGenerateDocuments",
                "ResultPath" : null,
                "OutputPath" : "$",
                "Retry" : [
                  {
                    "ErrorEquals" : ["States.TaskTimeout"],
                    "MaxAttempts": 5,
                    "IntervalSeconds": 1
                  },
                  {
                    "ErrorEquals" : ["CustomErrorA"],
                    "MaxAttempts": 5
                  }
                 ],
                "Catch": [
                  {
                    "ErrorEquals": [ "States.ALL" ],
                    "Next": "FailureNotifier"
                  }
                ]
              },
 
              "PublishQuestionnaireAnswersToLeaflet" : {
                "Type" : "Task",
                "Resource": "${WorkflowStateChangeLambdaArn}",
                "End" : true,
                "Retry" : [
                  {
                    "ErrorEquals" : ["States.TaskTimeout"],
                    "MaxAttempts": 5,
                    "IntervalSeconds": 1
                  },
                  {
                    "ErrorEquals" : ["CustomErrorA"],
                    "MaxAttempts": 5
                  }
                 ],
                "Catch": [
                  {
                    "ErrorEquals": [ "States.ALL" ],
                    "Next": "FailureNotifier"
                  }
                ]
              },
 
              "UpdateCEMetadataAndGenerateDocuments" : {
                "Type" : "Task",
                "Resource": "${WorkflowStateChangeLambdaArn}",
                "End" : true,
                "Retry" : [
                  {
                    "ErrorEquals" : ["States.TaskTimeout"],
                    "MaxAttempts": 5,
                    "IntervalSeconds": 1
                  },
                  {
                    "ErrorEquals" : ["CustomErrorA"],
                    "MaxAttempts": 5
                  }
                 ],
                "Catch": [
                  {
                    "ErrorEquals": [ "States.ALL" ],
                    "Next": "FailureNotifier"
                  }
                ]
              },
              "FailureNotifier" : {
                "Type" : "Task",
                "Resource": "${FailureNotifierLambdaArn}",
                "End" : true,
                "Retry" : [
                  {
                    "ErrorEquals" : ["States.TaskTimeout"],
                    "MaxAttempts": 5,
                    "IntervalSeconds": 1
                  },
                  {
                    "ErrorEquals" : ["CustomErrorA"],
                    "MaxAttempts": 5
                  }
                ]
              }
            }
          }
        -  WorkflowStateChangeLambdaArn:
              Fn::GetAtt: [ CreateContractFromQuestionnaireFunction, Arn ]
        -  FailureNotifierLambdaArn:
              Fn::GetAtt: [ CreateContractFromQuestionnaireFunction, Arn ]

Error - Template error: One or more Fn::Sub intrinsic functions don't specify expected arguments. Specify a string as first argument, and an optional second argument to specify a mapping of values to replace in the string

This is just a sample with same lambda used multiple times but the problem is in passing list/map to Fn::Sub.

Could anyone help me resolve this issue or provide an alternate solution to achieve the same?

Thanks,

sujith
  • 665
  • 2
  • 9
  • 22

1 Answers1

1

Fn::Sub takes either a single string as a parameter or a list. When using the list method there should be just two elemenets in the list. The first element is a string (the template) and the second is a map.

From the Fn::Sub documentation

Fn::Sub:
  - String
  - { Var1Name: Var1Value, Var2Name: Var2Value }

Note: since you are just using Fn::Get attribute to build the substitution value you can just use ${CreateContractFromQuestionnaireFunction.Arn} and use the single string version of Fn::Sub.

E.g. (I've shortened the step function for clarity.

   Fn::Sub:|-
      {
        "Comment" : "Sample draft process",
        "StartAt" : "AdvanceWorkflowToDraftInProgress",
        "States" : {
          "AdvanceWorkflowToDraftInProgress" : {
            "Type" : "Task",
            "Resource": "${CreateContractFromQuestionnaireFunction.Arn}",
            "InputPath":"$.contractId",
            "OutputPath":"$",
            "ResultPath":null,
            "Next" : "CheckQuestionnaireType",
            "Retry" : [
      ...
cementblocks
  • 4,326
  • 18
  • 24
  • I tried referencing them directly using $ and it worked. I get the same error when I remove the second argument completely. I am passing a dummy second argument for now but shouldn't it be optional? – sujith Nov 21 '18 at 06:48