Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CommandComplete waiter to ssm GetCommandInvocation operation #90

Closed
stobrien89 opened this issue Jun 7, 2021 · 6 comments
Closed
Assignees
Labels
closed-for-staleness This issue was closed because it didn't receive updates feature-request New feature or request ssm

Comments

@stobrien89
Copy link
Member

Originated from: boto/botocore#1744
Linked PR: boto/botocore#1753

@stobrien89 stobrien89 added the feature-request New feature or request label Jun 7, 2021
@stobrien89 stobrien89 self-assigned this Jun 7, 2021
@stobrien89 stobrien89 added the service-api This issue pertains to the AWS API label Jun 7, 2021
@stobrien89
Copy link
Member Author

P48336721

@iainelder
Copy link

@stobrien89 , thanks for creating this.

Would it be a new waiter to accompany or replace the existing command-executed waiter?

I'd really like a waiter that doesn't fail because "doesn't exist yet" and doesn't fail because the command failed. I just need to know when I can retrive the result of the invocation.

I find that command-executed behaves very strangely in boto3 1.17.102. I created the following function to learn how SSM works:

def test_ec2():
    ssm = boto3.client("ssm")

    instance_id = "i-1111111111111111"

    response = ssm.send_command(
        InstanceIds=[instance_id],
        DocumentName="AWS-RunShellScript",
        Parameters={"commands": ["missing"]}
    )

    command_id = response["Command"]["CommandId"]

    waiter = ssm.get_waiter("command_executed")

    while True:
        try:
            waiter.wait(
                CommandId=command_id,
                InstanceId=instance_id
            )
        except WaiterError as ex:
            print("!" * 40)
            print(ex.last_response)

            error = ex.last_response.get("Error")

            if error:
                if error["Code"] == "InvocationDoesNotExist":
                    time.sleep(0.1)
                    continue

            if ex.last_response["Status"] == "Failed":
                break

            raise ex

    output = ssm.get_command_invocation(
        CommandId=command_id,
        InstanceId=instance_id
    )

    print(output)

The function just tries to run a command that shouldn't exist on an EC2 instance and gets the result.

It needs to run the waiter in a loop with a complex try-catch inside to get the behavior I want.

You can see the waiter first raises an exception because of an InvocationDoesNotExist error, and then raises another exception because the comand failed.

Apart from the request ID, the content of the exception from command failure seems identical to the invocation result.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{'Error': {'Message': '', 'Code': 'InvocationDoesNotExist'}, 'ResponseMetadata': {'RequestId': '11111111-1111-1111-1111-111111111111', 'HTTPStatusCode': 400, 'HTTPHeaders': {'server': 'Server', 'date': 'Sat, 03 Jul 2021 18:47:13 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '35', 'connection': 'keep-alive', 'x-amzn-requestid': '11111111-1111-1111-1111-111111111111'}, 'RetryAttempts': 0}}
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{'CommandId': '22222222-2222-2222-2222-222222222222', 'InstanceId': 'i-1111111111111111', 'Comment': '', 'DocumentName': 'AWS-RunShellScript', 'DocumentVersion': '$DEFAULT', 'PluginName': 'aws:runShellScript', 'ResponseCode': 127, 'ExecutionStartDateTime': '2021-07-03T18:47:14.275Z', 'ExecutionElapsedTime': 'PT0.042S', 'ExecutionEndDateTime': '2021-07-03T18:47:14.275Z', 'Status': 'Failed', 'StatusDetails': 'Failed', 'StandardOutputContent': '', 'StandardOutputUrl': '', 'StandardErrorContent': '/var/lib/amazon/ssm/i-1111111111111111/document/orchestration/22222222-2222-2222-2222-222222222222/awsrunShellScript/0.awsrunShellScript/_script.sh: line 1: missing: command not found\nfailed to run commands: exit status 127', 'StandardErrorUrl': '', 'CloudWatchOutputConfig': {'CloudWatchLogGroupName': '', 'CloudWatchOutputEnabled': False}, 'ResponseMetadata': {'RequestId': '33333333-3333-3333-3333-333333333333', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Sat, 03 Jul 2021 18:47:19 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '807', 'connection': 'keep-alive', 'x-amzn-requestid': '33333333-3333-3333-3333-333333333333'}, 'RetryAttempts': 0}
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{'CommandId': '22222222-2222-2222-2222-222222222222', 'InstanceId': 'i-1111111111111111', 'Comment': '', 'DocumentName': 'AWS-RunShellScript', 'DocumentVersion': '$DEFAULT', 'PluginName': 'aws:runShellScript', 'ResponseCode': 127, 'ExecutionStartDateTime': '2021-07-03T18:47:14.275Z', 'ExecutionElapsedTime': 'PT0.042S', 'ExecutionEndDateTime': '2021-07-03T18:47:14.275Z', 'Status': 'Failed', 'StatusDetails': 'Failed', 'StandardOutputContent': '', 'StandardOutputUrl': '', 'StandardErrorContent': '/var/lib/amazon/ssm/i-1111111111111111/document/orchestration/22222222-2222-2222-2222-222222222222/awsrunShellScript/0.awsrunShellScript/_script.sh: line 1: missing: command not found\nfailed to run commands: exit status 127', 'StandardErrorUrl': '', 'CloudWatchOutputConfig': {'CloudWatchLogGroupName': '', 'CloudWatchOutputEnabled': False}, 'ResponseMetadata': {'RequestId': '44444444-4444-4444-4444-444444444444', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Sat, 03 Jul 2021 18:47:19 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '807', 'connection': 'keep-alive', 'x-amzn-requestid': '44444444-4444-4444-4444-444444444444'}, 'RetryAttempts': 0}

@stobrien89
Copy link
Member Author

Hi @iainelder,

This waiter would accompany the existing command-executed waiter, if implemented, as many people have been requesting this functionality. In the meantime, I'd suggest using a custom polling loop to get the desired behavior.

@stobrien89
Copy link
Member Author

@iainelder,

Heard back from the ssm team today— They've added this request to their backlog, which is a good sign, but we don't have an estimated date of completion. I'll provide any additional updates I receive from them.

@stobrien89 stobrien89 added ssm and removed service-api This issue pertains to the AWS API labels Jul 26, 2021
@github-actions
Copy link

This issue has not received any attention in 1 year. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

@github-actions github-actions bot added the closing-soon This issue will be closed soon label Aug 11, 2022
@github-actions github-actions bot added closed-for-staleness This issue was closed because it didn't receive updates and removed closing-soon This issue will be closed soon labels Aug 19, 2022
@vparmeland
Copy link

Any updates?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-for-staleness This issue was closed because it didn't receive updates feature-request New feature or request ssm
Projects
None yet
Development

No branches or pull requests

3 participants