首页 > 解决方案 > 使用 CloudFormation 从外部定义文件部署 StepFunctions

问题描述

我正在尝试使用 CloudFormation 部署 stepfunction,并且我想从 S3 中的外部文件中引用实际的 stepfunction 定义。

模板如下所示:

StepFunction1: 
    Type: "AWS::StepFunctions::StateMachine"
    Properties:
      StateMachineName: !Ref StepFunction1SampleName
      RoleArn: !GetAtt StepFunctionExecutionRole.Arn
      DefinitionString:  
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: 
              Fn::Sub: 's3://${ArtifactsBucketName}/StepFunctions/StepFunction1/definition.json'

但是,这似乎不受支持,因为我们遇到了错误

Property validation failure: [Value of property {/DefinitionString} does not match type {String}]

我正在为 API 做类似的事情,从外部 swagger 文件中引用实际的 API 定义,这似乎工作正常。

例子:

SearchAPI:
    Type: "AWS::Serverless::Api"
    Properties:
      Name: myAPI
      StageName: latest
      DefinitionBody: 
        Fn::Transform:
          Name: AWS::Include
          Parameters:            
            Location: 
              Fn::Sub: 's3://${ArtifactsBucketName}/ApiGateway/myAPI/swagger.yaml'

我怎样才能使这项工作?

标签: amazon-web-servicesamazon-cloudformationaws-step-functions

解决方案


诀窍是转义 StepFunction DefinitionString 属性,并在外部 CloudFormation 引用文件中包含实际属性 DefinitionString。仅转义 stepfunction 定义字符串会失败,CloudFormation 抱怨引用的 Transform/Include 模板不是有效的 yaml/json。下面是它的样子: 模板:

StepFunction1: 
    Type: "AWS::StepFunctions::StateMachine"
    Properties:
      StateMachineName: !Ref StepFunction1SampleName
      RoleArn: !GetAtt StepFunctionExecutionRole.Arn      
      Fn::Transform:
        Name: AWS::Include
        Parameters:
          Location: 
            Fn::Sub: 's3://${ArtifactsBucketName}/StepFunctions/StepFunction1/definition.json'

外部阶跃函数定义文件:

{
    "DefinitionString" : {"Fn::Sub" : "{\r\n  \"Comment\": \"A Retry example of the Amazon States Language using an AWS Lambda Function\",\r\n  \"StartAt\": \"HelloWorld\",\r\n  \"States\": {\r\n    \"HelloWorld\": {\r\n      \"Type\": \"Task\",\r\n      \"Resource\": \"arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${HelloWorldLambdaFunctionName}\",      \r\n      \"End\": true\r\n    }\r\n  }\r\n}"}
}

现在,虽然这解决了问题,但在源代码管理中以这种形式维护 StepFunction 定义有点困难。

所以我考虑过使用由 lambda 函数支持的 CloudFormation 自定义资源。lambda 函数将处理实际的 StepFunction DefinitionString 转义部分。

下面是它的样子: 模板:

StepFunctionParser:
    Type: Custom::AMIInfo
    Properties:
      ServiceToken: myLambdaArn
      DefinitionString: 
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: 
              Fn::Sub: 's3://${ArtifactsBucketName}/StepFunctions/StepFunctionX/definition.json'   
  StepFunctionX: 
    Type: "AWS::StepFunctions::StateMachine"
    Properties:
      StateMachineName: StepFunction1SampleNameX
      RoleArn: !GetAtt StepFunctionExecutionRole.Arn      
      DefinitionString: !GetAtt StepFunctionParser.DefinitionString

外部 StepFunction 定义文件:

{
  "Comment": "A Retry example of the Amazon States Language using an AWS Lambda Function",
  "StartAt": "HelloWorld",
  "States": {
    "HelloWorld": {
      "Type": "Task",
      "Resource": {"Fn::Sub" : "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${HelloWorldLambdaFunctionName}" },
      "End": true
    }
  }
}

这是创建 AWS Lambda 支持的自定义资源的文档。

这个还是有问题的。Transform/Include 将外部模板布尔属性转换为字符串属性。因此,定义字符串

"DefinitionString": {
            "States": {
                "HelloWorld": {
                    "Type": "Task",
                    "Resource": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${HelloWorldLambdaFunctionName}",
                    **"End": true**
                }
            },
            "Comment": "A Retry example of the Amazon States Language using an AWS Lambda Function",
            "StartAt": "HelloWorld"
        }

变成

"DefinitionString": {
            "States": {
                "HelloWorld": {
                    "Type": "Task",
                    "Resource": _realLambdaFunctionArn_,
                    **"End": "true"**
                }
            },
            "Comment": "A Retry example of the Amazon States Language using an AWS Lambda Function",
            "StartAt": "HelloWorld"
        }

CloudFormation 然后抱怨 StepFunction 定义无效:

Invalid State Machine Definition: 'SCHEMA_VALIDATION_FAILED: Expected value of type Boolean at /States/HelloWorld/End' 

这是 CloudFormation 转换/包含问题吗?AWS 的人可以就此发表声明吗?


推荐阅读