Search code examples
pythonamazon-web-servicesamazon-ec2boto3aws-ssm

ssm is not available after instance_running waiter is done


I want to start a stopped ec2 instance and run a bash script on it using ssm.

Here's the code I have:

import boto3
instanceid = 'i-123456789'

ec2 = boto3.resource('ec2')
instance = ec2.Instance(instanceid)
response = instance.start()

waiter = boto3.client('ec2').get_waiter('instance_running')
waiter.wait(InstanceIds=[instanceid])

ssm_client = boto3.client('ssm')
ssm_client.send_command(
        InstanceIds=[instanceid],
        DocumentName="AWS-RunShellScript",
        Parameters={'commands': ['ls']})

It fails on send_command with an exception:

botocore.errorfactory.InvalidInstanceId: An error occurred (InvalidInstanceId) when calling the SendCommand operation: Instances [[i-123456789]] not in a valid state for account

If I amend my code above with:

import time
time.sleep(20)

Between the waiter and ssm_client, it works. But is there a better way to wait for ssm to be up, rather than sleeping?


Solution

  • As per @Paolo suggestion added this check (docs):

        for i in range(1, 100):
            response = ssm_client.describe_instance_information(Filters=[{'Key': 'InstanceIds', 'Values': [instanceid]}])
            if len(response["InstanceInformationList"]) > 0 and \
                    response["InstanceInformationList"][0]["PingStatus"] == "Online" and \
                    response["InstanceInformationList"][0]["InstanceId"] == instanceid:
                break
            time.sleep(1)