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?
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)