如何在AWS StepFunction中将JSON传递给ECS任务?

时间:2020-03-07 00:10:26

标签: amazon-web-services amazon-ecs aws-step-functions

我正在尝试创建一个AWS StepFunctions工作流程,其中有一个 Lambda 任务,然后是一个 ECS / Fargate 任务。

Lambda接受ID作为输入,并以JSON形式输出一些数据,该数据由ECS任务使用,该任务在其容器环境中运行Python脚本。我想在StepFunctions中执行以下流程:

{ id: 1234 } -> [Lambda] -> { id: 1234, data: {...} }

{ id: 1234, data: {...} } -> [ECS] -> { id: 1234, result: "bar"}

作为参考,以下是ECS任务的示例配置: https://docs.aws.amazon.com/step-functions/latest/dg/sample-project-container-task-notification.html

我无法找到将ECS任务的结构化JSON input传递给运行该任务的容器的任何方式。

这是我到目前为止发现的东西:

  • 我可以使用JSONPath选择输入的各个字段并将它们设置为环境变量,从而将JSON输入的各个字段传递给容器。但是,如果我将整个input对象($)分配给一个环境变量,那么它将在运行时失败,并出现序列化错误([Object] cannot be converted to a string)。
  • 我可以创建一个中间lambda来接受输入并将其转换为存储在output中的单个键值中的JSON字符串,然后将此单个字符串键值分配给以下环境变量: ECS Task并对其进行解析。但是,这需要添加整个额外的Task以及几秒钟的运行时+成本。

这是我不能做的一些事情:

  • boto3中似乎没有任何机制来获取现有ECS任务的input。我可以获取未分配活动的input,也可以获取整个执行的输入。但是,即使我有一个任务令牌,也没有API可以仅获取现有的,正在运行的Task的输入。
  • 我无法修改原始Lambda来将JSON作为字符串输出。我在多个位置(并行任务)中使用此结果,其他任务是Lambda,它们将output的特定子字段用作其input

将定义为input的结构化JSON对象传递给Task到ECS / Fargate Task的执行容器的预期机制是什么?

3 个答案:

答案 0 :(得分:2)

您可以在运行任务之前使用intrinsic functions格式化请求:

const formatRequest = new sfn.Pass(this, 'FormatRequest', {
    parameters: {
        'request.$': 'States.JsonToString($)'
    }
})

答案 1 :(得分:1)

鉴于您未在运行Lambda的步骤中指定结果路径,则容器的输入将是Lambda的输出,其转换为:

"Overrides": {
   "ContainerOverrides": [
      {
        "Name": "container-name",
        "Environment": [
          {
            "Name": "SOME_ENV_VAR",
            "Value.$": "$"
          },

但是,即使这仅限于可以存储为ENV的内容,因此您需要确保JSON实际上是一个字符串

答案 2 :(得分:0)

传递结构化JSON对象的预期机制是什么 定义为任务到执行容器的输入 ECS / Fargate任务?

看看Input and OutPut处理文档:https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html

这将帮助您确定要传递给“运行Fargate任务”状态的JSON输入(从您在问题中链接的示例中)

Step函数支持ECS的“ RunTask”和几个参数:https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html

例如

  1. 假设我的Lambda函数输出此JSON

    {
        "commands": [
            "foo": { "bar" },
            "some command 1",
            "some command 2"
        ]
    }
    
  2. 我希望我的“运行Fargate任务”避开一个仅获取所有输入的输入路径。在我的状态机中,在"Type": "Task",之后,我将输入:

    "InputPath":"$.commands",
    
  3. 然后在"Parameters"之后在我的"NetworkConfigurations:{....},"中执行Fargate任务,我将使用JSON Path语法:https://github.com/json-path/JsonPath放置所需的容器替代。但是,我不希望来自JSON的所有输入,仅希望"foo"

    的值
    "Overrides": {
        "ContainerOverrides": [
            {
                "Name": "container-name",
                "Command.$": "$.commands.foo"
            }
        ]
    }
    

您可以使用此处使用的语法:https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html