Json 将变量传递到步骤函数start_execution()输入参数

Json 将变量传递到步骤函数start_execution()输入参数,json,python-3.x,amazon-web-services,boto3,aws-step-functions,Json,Python 3.x,Amazon Web Services,Boto3,Aws Step Functions,我正在使用boto3和python3.6来启动一个步骤函数执行。Step函数旨在跨我的所有帐户共享我的基本AMI。我有4个变量需要传递到input参数以启动执行。这些是AMI ID、我拥有的帐户列表、源帐户和KMS密钥。AMI ID和帐户列表在我的代码中构造,是需要动态传递的变量。根据文档,input是一个字符串,它包含用于执行的JSON输入数据,并给出以下示例:“input”:“{\“ami\u id\”:\“ami\u id\”}”。我的问题是如何将相关变量作为值传递给此参数?下面是我的代码

我正在使用
boto3
python3.6
来启动一个步骤函数执行。Step函数旨在跨我的所有帐户共享我的基本AMI。我有4个变量需要传递到
input
参数以启动执行。这些是AMI ID、我拥有的帐户列表、源帐户和KMS密钥。AMI ID和帐户列表在我的代码中构造,是需要动态传递的变量。根据文档,
input
是一个
字符串,它包含用于执行的JSON输入数据
,并给出以下示例:
“input”:“{\“ami\u id\”:\“ami\u id\”}”
。我的问题是如何将相关变量作为值传递给此参数?下面是我的代码和回溯:

code:

import boto3
import json

#   Get an STS token to assume roles into AWS accounts
def get_sts_token(**kwargs):
    role_arn = kwargs['RoleArn']
    region_name = kwargs['RegionName']
    sts = boto3.client(
        'sts',
    region_name=region_name,
    )
    token = sts.assume_role(
        RoleArn=role_arn,
        RoleSessionName='GetInstances',
        DurationSeconds=900,
    )
    return token["Credentials"]

def get_accounts():
    role_arn = "arn:aws:iam::xxxxxxxxxx:role/list-accounts-role"
    region_name = "us-east-1"

    token = get_sts_token(RoleArn=role_arn, RegionName=region_name)

    access_key = token['AccessKeyId']
    secret_key = token['SecretAccessKey']       
    session_token = token['SessionToken']

    client = boto3.client('organizations', 
    aws_access_key_id=access_key,
    aws_secret_access_key=secret_key,
    aws_session_token=session_token)

    moreAccounts=True
    nexttoken=''
    global accountList
    accountList =[]

    while moreAccounts:
        if (len(nexttoken)>0):
            accounts=client.list_accounts(NextToken=nexttoken)
        else:
            accounts=client.list_accounts()
        if 'NextToken' in accounts:
            nexttoken=accounts['NextToken']
        else:
            moreAccounts=False
        for account in accounts['Accounts']:
            if account['Status'] != 'SUSPENDED' and account['Status'] != 'CLOSED' :
                account_id = account['Id']
                accountList.append(account_id)


    print(accountList)

def trigger_sfn():
    ssm = boto3.client('ssm')
    role_arn = "arn:aws:iam::xxxxxxxx:role/execute-sfn"
    region_name = "us-east-1"

    ami_id = ssm.get_parameter(Name='/BaseAMI/newest')['Parameter']['Value']
    print(ami_id)

    token = get_sts_token(RoleArn=role_arn, RegionName=region_name)
    print(token)

    access_key = token['AccessKeyId']
    secret_key = token['SecretAccessKey']       
    session_token = token['SessionToken']

    sfn = boto3.client('stepfunctions', 
    aws_access_key_id=access_key,
    aws_secret_access_key=secret_key,
    aws_session_token=session_token)

    response = sfn.start_execution(
    stateMachineArn='arn:aws:states:us-east-1:xxxxxxxx:stateMachine:ami-share',
    input="{\"ami_id\": ami_id, \"source_account_id\": \"112233445566\", \"accountList\": accountList, \"kms_key_arn\": \"alias/aws/ebs\"}"
)

    print(response)
跟踪:

An error occurred (InvalidExecutionInput) when calling the 
StartExecution operation: Invalid State Machine Execution Input: 
'com.fasterxml.jackson.core.JsonParseException: Unrecognized token 
'ami_id': was expecting ('true', 'false' or 'null')
at [Source: (String)"{"ami_id": ami_id, "source_account_id": 
"112233445566", "accountList": accountList, "kms_key_arn": 
"alias/aws/ebs"}"; line: 1, column: 18]': InvalidExecutionInput
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 6, in lambda_handler
trigger_sfn()
File "/var/task/lambda_function.py", line 96, in trigger_sfn
input="{\"ami_id\": ami_id, \"source_account_id\": \"112233445566\", 
\"accountList\": accountList, \"kms_key_arn\": \"alias/aws/ebs\"}"
File "/var/runtime/botocore/client.py", line 314, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/runtime/botocore/client.py", line 612, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.errorfactory.InvalidExecutionInput: An error occurred 
(InvalidExecutionInput) when calling the StartExecution operation: 
Invalid State Machine Execution Input: 
'com.fasterxml.jackson.core.JsonParseException: Unrecognized token 
'ami_id': was expecting ('true', 'false' or 'null')
at [Source: (String)"{"ami_id": ami_id, "source_account_id": 
"112233445566", "accountList": accountList, "kms_key_arn": 
"alias/aws/ebs"}"; line: 1, column: 18]'

您可以将变量的值添加到字符串中,如下所示:

input="{\"ami_id\": \"" + ami_id + "\", \"source_account_id\": \"112233445566\", \"accountList\": accountList, \"kms_key_arn\": \"alias/aws/ebs\"}"

您的代码当前发送的是文字字符串“ami_id”,而不是ami_id的变量值,这在测试后有效。有关于json变量的文档吗?它展示了如何使用.dump函数将json转换为字符串。您现在采用的方法是从一开始就以字符串格式编写JSON,这就是为什么我们将ami_id字符串添加到字符串的其余部分时它会起作用。如果您想让它更整洁,您可以使用JSON.dumpsOK形成JSON,因此输出现在再次失败,因为
ami_id
值周围没有引号。有没有一种方法可以传递变量并在其周围添加引号?是的,我编辑了我的答案,因为从技术上讲应该是用引号的