使用参数运行AWS Lambda的YAML SSM运行文档

发布于 2025-02-05 03:05:42 字数 410 浏览 4 评论 0原文

我正在尝试从python aws lambda中运行yaml ssm文档,使用boto3 ssm.send_command_command带有参数,但是即使我是只是想运行样本“ Hello World”,我就会得到:

“ errormessage”:“调用sendcommand操作时发生错误(无效的Parameters):document testmessage不支持参数。

RUN RUN DOMANTY无问题工作,因此似乎以JSON格式传递了这些参数,但是我打算的文档我打算打算使用。这包含一个相对较长的powershell脚本,json需要在一行上运行它,这很尴尬,我希望避免需要从S3存储桶中运行它。 lambda的参数?

I am trying to run a YAML SSM document from a Python AWS Lambda, using boto3 ssm.send_command with parameters, but even if I'm just trying to run the sample "Hello World", I get:

"errorMessage": "An error occurred (InvalidParameters) when calling the SendCommand operation: document TestMessage does not support parameters.

JSON Run Documents work without an issue, so it seems like the parameters are being passed in JSON format, but the document I intend this for contains a relatively long Powershell script, JSON needing to run it all on a single line would be awkward, and I am hoping to avoid needing to run it from an S3 bucket. Can anyone suggest a way to run a YAML Run Document with parameters from the Lambda?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伴我老 2025-02-12 03:05:43

据我所知,AWS Lambda总是将其作为JSON的事件。我的建议是,在lambda_handler.py文件中声明这样的新变量:

import json
import yaml

def handler_name(event, context): 
    yaml_event = yaml.dump(json.load(event))
    #rest of the code...

这种方式将以yaml格式进行yaml格式,您可以使用该变量而不是以JSON格式的事件。

As far as I know AWS lambda always gets it's events as JSON. My suggestion would be that in the lambda_handler.py file declare a new variable like this:

import json
import yaml

def handler_name(event, context): 
    yaml_event = yaml.dump(json.load(event))
    #rest of the code...

This way the event will be in YAML format and you can use that variable instead of the event, which is in JSON format.

梦里南柯 2025-02-12 03:05:43

这是使用boto3 ssm.send_command在运行python 3.8中运行yaml运行命令文档的示例。使用环境变量或SSM参数存储将变量传递给LAMBDA。该脚本从S3检索,并接受一个格式为JSON字符串的单个参数,该参数传递给了在Linux上运行的bash脚本(对不起,我没有PowerShell一个)。

SSM文档是使用CloudFormation部署的,但您也可以通过控制台或CLI创建它。基于您引用的错误消息,也许验证文档类型被设置为“命令”。

SSM文档(用云形式模板包裹,请参阅content属性)

  Neo4jLoadQueryDocument: 
    Type: AWS::SSM::Document
    Properties:
      DocumentType: "Command"
      DocumentFormat: "YAML"
      TargetType: "/AWS::EC2::Instance"
      Content:
        schemaVersion: "2.2"
        description: !Sub "Load Neo4j for ${AppName}"
        parameters:
          sourceType:
            type: "String"
            description: "S3"
            default: "S3"
          sourceInfo:
            type: "StringMap"
            description: !Sub "Downloads all files under the ${AppName} scripts prefix"
            default:
              path: !Sub 'https://{{resolve:ssm:/${AppName}/${Stage}/${AWS::Region}/DataBucketName}}.s3.amazonaws.com/config/scripts/'
          commandLine:
            type: "String"
            description: "These commands are invoked by a Lambda script which sets the correct parameters (Refer to documentation)."
            default: 'bash start_task.sh'
          workingDirectory:
            type: "String"
            description: "Working directory"
            default: "/home/ubuntu"
          executionTimeout:
            type: "String"
            description: "(Optional) The time in seconds for a command to complete before it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800 (8 hours)."
            default: "86400"
        mainSteps:
          - action: "aws:downloadContent"
            name: "downloadContent"
            inputs:
              sourceType: "{{ sourceType }}"
              sourceInfo: "{{ sourceInfo }}"
              destinationPath: "{{ workingDirectory }}"
          - action: "aws:runShellScript"
            name: "runShellScript"
            inputs: 
              runCommand:
                - ""
                - "directory=$(pwd)"
                - "export PATH=$PATH:$directory"
                - " {{ commandLine }} " 
                - ""
              workingDirectory: "{{ workingDirectory }}"
              timeoutSeconds: "{{ executionTimeout }}"

json文档中的lambda函数

import os
import boto3

neo4j_load_query_document_name = os.environ["NEO4J_LOAD_QUERY_DOCUMENT_NAME"]
# neo4j_database_instance_id = os.environ["NEO4J_DATABASE_INSTANCE_ID"]
neo4j_database_instance_id_param = os.environ["NEO4J_DATABASE_INSTANCE_ID_SSM_PARAM"]
load_neo4j_activity = os.environ["LOAD_NEO4J_ACTIVITY"]
app_name = os.environ["APP_NAME"]

# Get SSM Document Neo4jLoadQuery
ssm = boto3.client('ssm')
response = ssm.get_document(Name=neo4j_load_query_document_name)
neo4j_load_query_document_content = json.loads(response["Content"])

# Get Instance ID
neo4j_database_instance_id = ssm.get_parameter(Name=neo4j_database_instance_id_param)["Parameter"]["Value"]

# Extract document parameters
neo4j_load_query_document_parameters = neo4j_load_query_document_content["parameters"]
command_line_default = neo4j_load_query_document_parameters["commandLine"]["default"]
source_info_default = neo4j_load_query_document_parameters["sourceInfo"]["default"]

def lambda_handler(event, context):

    params = {
        "params": {
            "app_name": app_name,
            "activity_arn": load_neo4j_activity,
        }
    }

    # Include params JSON as command line argument
    cmd = f"{command_line_default} \'{json.dumps(params)}\'"

    try:
        response = ssm.send_command(
            InstanceIds=[
                neo4j_database_instance_id,
            ],
            DocumentName=neo4j_load_query_document_name,
            Parameters={
                "commandLine":[cmd],
                "sourceInfo":[json.dumps(source_info_default)]
            },
            MaxConcurrency='1')

        if response['ResponseMetadata']['HTTPStatusCode'] != 200:
            logger.error(json.dumps(response, cls=DatetimeEncoder))
            raise Exception("Failed to send command")
        else:
            logger.info(f"Command `{cmd}` invoked on instance {neo4j_database_instance_id}")
    
    except Exception as err:
        logger.error(err)
        raise err

    return

参数不一定在JSON本身中,它们很容易成为字符串或数字值(更可能是IMO)。如果要以JSON格式传递参数(与JSON文档不同),请注意引号并逃脱。

Here is an example of running a YAML Run Command document using boto3 ssm.send_command in a Lambda running Python 3.8. Variables are passed to the Lambda using either environment variables or SSM Parameter Store. The script is retrieved from S3 and accepts a single parameter formatted as a JSON string which is passed to the bash script running on Linux (sorry I don't have one for PowerShell).

The SSM Document is deployed using CloudFormation but you could also create it through the console or CLI. Based on the error message you cited, perhaps verify the Document Type is set as "Command".

SSM Document (wrapped in CloudFormation template, refer to the Content property)

  Neo4jLoadQueryDocument: 
    Type: AWS::SSM::Document
    Properties:
      DocumentType: "Command"
      DocumentFormat: "YAML"
      TargetType: "/AWS::EC2::Instance"
      Content:
        schemaVersion: "2.2"
        description: !Sub "Load Neo4j for ${AppName}"
        parameters:
          sourceType:
            type: "String"
            description: "S3"
            default: "S3"
          sourceInfo:
            type: "StringMap"
            description: !Sub "Downloads all files under the ${AppName} scripts prefix"
            default:
              path: !Sub 'https://{{resolve:ssm:/${AppName}/${Stage}/${AWS::Region}/DataBucketName}}.s3.amazonaws.com/config/scripts/'
          commandLine:
            type: "String"
            description: "These commands are invoked by a Lambda script which sets the correct parameters (Refer to documentation)."
            default: 'bash start_task.sh'
          workingDirectory:
            type: "String"
            description: "Working directory"
            default: "/home/ubuntu"
          executionTimeout:
            type: "String"
            description: "(Optional) The time in seconds for a command to complete before it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800 (8 hours)."
            default: "86400"
        mainSteps:
          - action: "aws:downloadContent"
            name: "downloadContent"
            inputs:
              sourceType: "{{ sourceType }}"
              sourceInfo: "{{ sourceInfo }}"
              destinationPath: "{{ workingDirectory }}"
          - action: "aws:runShellScript"
            name: "runShellScript"
            inputs: 
              runCommand:
                - ""
                - "directory=$(pwd)"
                - "export PATH=$PATH:$directory"
                - " {{ commandLine }} " 
                - ""
              workingDirectory: "{{ workingDirectory }}"
              timeoutSeconds: "{{ executionTimeout }}"

Lambda function

import os
import boto3

neo4j_load_query_document_name = os.environ["NEO4J_LOAD_QUERY_DOCUMENT_NAME"]
# neo4j_database_instance_id = os.environ["NEO4J_DATABASE_INSTANCE_ID"]
neo4j_database_instance_id_param = os.environ["NEO4J_DATABASE_INSTANCE_ID_SSM_PARAM"]
load_neo4j_activity = os.environ["LOAD_NEO4J_ACTIVITY"]
app_name = os.environ["APP_NAME"]

# Get SSM Document Neo4jLoadQuery
ssm = boto3.client('ssm')
response = ssm.get_document(Name=neo4j_load_query_document_name)
neo4j_load_query_document_content = json.loads(response["Content"])

# Get Instance ID
neo4j_database_instance_id = ssm.get_parameter(Name=neo4j_database_instance_id_param)["Parameter"]["Value"]

# Extract document parameters
neo4j_load_query_document_parameters = neo4j_load_query_document_content["parameters"]
command_line_default = neo4j_load_query_document_parameters["commandLine"]["default"]
source_info_default = neo4j_load_query_document_parameters["sourceInfo"]["default"]

def lambda_handler(event, context):

    params = {
        "params": {
            "app_name": app_name,
            "activity_arn": load_neo4j_activity,
        }
    }

    # Include params JSON as command line argument
    cmd = f"{command_line_default} \'{json.dumps(params)}\'"

    try:
        response = ssm.send_command(
            InstanceIds=[
                neo4j_database_instance_id,
            ],
            DocumentName=neo4j_load_query_document_name,
            Parameters={
                "commandLine":[cmd],
                "sourceInfo":[json.dumps(source_info_default)]
            },
            MaxConcurrency='1')

        if response['ResponseMetadata']['HTTPStatusCode'] != 200:
            logger.error(json.dumps(response, cls=DatetimeEncoder))
            raise Exception("Failed to send command")
        else:
            logger.info(f"Command `{cmd}` invoked on instance {neo4j_database_instance_id}")
    
    except Exception as err:
        logger.error(err)
        raise err

    return

Parameters in a JSON document are not necessarily in JSON themselves, they can easily be string or numeric values (more likely IMO). If you want to pass a parameter in JSON format (not the same as a JSON document), pay attention to quotes and escaping.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文