首页 > 解决方案 > 由于状态机定义错误,无服务器部署失败

问题描述

我正在尝试使用无服务器部署一个简单的应用程序,但无法完成部署。我收到以下错误:

Serverless Error ---------------------------------------

  ✕ State machine "checkAirtableSM" definition is invalid:
  [{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"http://asl-validator.cloud/fail#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"http://asl-validator.cloud/pass#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"http://asl-validator.cloud/succeed#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"pattern","dataPath":".States['CheckAirtable'].Resource","schemaPath":"http://asl-validator.cloud/task#/properties/Resource/oneOf/0/pattern","params":{"pattern":"^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-)*:[0-9]*:([a-z]|-)+:[a-zA-Z0-9-_.]+(:(\\$LATEST|[a-zA-Z0-9-_]+))?$"},"message":"should match pattern \"^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-)*:[0-9]*:([a-z]|-)+:[a-zA-Z0-9-_.]+(:(\\$LATEST|[a-zA-Z0-9-_]+))?$\""},{"keyword":"type","dataPath":".States['CheckAirtable'].Resource","schemaPath":"http://asl-validator.cloud/task#/properties/Resource/oneOf/1/type","params":{"type":"object"},"message":"should be object"},{"keyword":"oneOf","dataPath":".States['CheckAirtable'].Resource","schemaPath":"http://asl-validator.cloud/task#/properties/Resource/oneOf","params":{"passingSchemas":null},"message":"should match exactly one schema in oneOf"},{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"http://asl-validator.cloud/wait#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"additionalProperties","dataPath":".States['CheckAirtable']","schemaPath":"#/additionalProperties","params":{"additionalProperty":"Resource"},"message":"should NOT have additional properties"},{"keyword":"oneOf","dataPath":".States['CheckAirtable']","schemaPath":"#/oneOf","params":{"passingSchemas":null},"message":"should match exactly one schema in oneOf"}]

以下是我的 serverless.yml 文件:

# NOTE: update this with your service name
service: scheduler-api

# Create an optimized package for our functions 
package:
  individually: true

plugins:
  - serverless-bundle # Package our functions with Webpack
  - serverless-offline
  - serverless-dotenv-plugin # Load .env as environment variables
  - serverless-step-functions
  - serverless-pseudo-parameters

provider:
  name: aws
  runtime: nodejs10.x
  stage: dev
  region: us-east-2
  # To load environment variables externally
  # rename env.example to .env and uncomment
  # the following line. Also, make sure to not
  # commit your .env.
  #
  # These environment variables are made available to our functions
  # under process.env.
  environment:
    airtableBaseId: ${env:AIRTABLE_BASE_ID}
    airtableApiKey: ${env:AIRTABLE_API_KEY}
    STEP_FUNCTION_ARN: "arn:aws:states:#{AWS::Region}:#{AWS::AccountId}:stateMachine:${self:service}-${self:provider.stage}-scheduleTweetSM"
    twitter_consumer_key: ${env:TWITTER_CONSUMER_KEY}
    twitter_consumer_secret: ${env:TWITTER_CONSUMER_SECRET}
    twitter_access_token_key: ${env:TWITTER_ACCESS_TOKEN_KEY}
    twitter_access_token_secret: ${env:TWITTER_ACCESS_TOKEN_SECRET}

functions:
  checkairtable:
    handler: check.main
  pushtweet:
    handler: tweet.main

stepFunctions:
  validate: true
  stateMachines:
    checkAirtableSM:
      name: AirtableChecker
      definition:
        Comment: "Checks for posts that are complete and ready to be scheduled for posting in airtable and schedules them."
        StartAt: CheckAirtable
        States:
          CheckAirtable:
            Type: Task
            Resource: "arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${self:provider.stage}-checkairtable"
            End: true
      events:
        - schedule:
            rate: cron(0 0/6 * * ? *)
            enabled: true
    scheduleTweetSM:
      name: TweetScheduler
      definition:
        Comment: "Waits until the post time, then posts the tweet to Twitter."
        StartAt: WaitForPostTime
        States:
          WaitForPostTime:
            Type: Wait
            TimestampePath: $.postTime
            Next: PushPost
          PushPost:
            Type: Task
            Resource: "arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${self:provider.stage}-pushtweet"
            End: true

工作理论是,不知何故,无服务器伪参数没有按预期工作,并且正在使资源的 arn 畸形,然后抱怨畸形。serverless deploy在字符串被无服务器伪参数替换后,是否有检查命令对 serverless.yaml 所做的操作?

标签: serverless

解决方案


这里的问题实际上是validate: true在状态机定义中。如果删除它,一切正常。

插件的serverless-step-functions验证阶段在伪参数被评估并替换为它们的值之前运行。这似乎是这两个插件之间的兼容性错误。


顺便说一句,我还要补充一点,您实际上可以在状态机定义中不使用伪参数。您可以使用Fn::GetAtt来获取函数的 ARN。

service: scheduler-api

plugins:
  - serverless-step-functions

provider:
  name: aws
  runtime: nodejs10.x
  stage: dev
  region: eu-west-2

functions:
  checkairtable:
    handler: check.main

stepFunctions:
  validate: true
  stateMachines:
    checkAirtableSM:
      name: AirtableChecker
      definition:
        Comment: "Checks for posts that are complete and ready to be scheduled for posting in airtable and schedules them."
        StartAt: CheckAirtable
        States:
          CheckAirtable:
            Type: Task
            Resource:
              Fn::GetAtt: [checkairtable, Arn]
            End: true

推荐阅读