Although there are a few ways to do it, here is an example of how you can use the null_resource to make Terraform wait for an EC2 instance to be ready before continuning.
In this example we have an EC2 instance called mgmt_host which will using the “trigger” set the Terraform into a loop to wait. It uses the local-exec provisioner, which once the EC2 instance is deployed is started. Then let’s say you want to run an SSM command afterwards you just make that dependent on the null_resource.
If you were to try this without the wait_for_instance null_resource, what would happen is the SSM command would run immediately after the EC2 instance is deployed; i.e. before it is ready and able to be used by SSM.
resource "null_resource" "wait_for_instance" {
provisioner "local-exec" {
command = <<EOT
while [ $(aws ec2 describe-instance-status --instance-ids ${aws_instance.mgmt_host.id} --query "InstanceStatuses[].InstanceStatus.Status" --output text) != "ok" ]
do
echo "Waiting for instance to be ready...."
sleep 2
done
echo "Instance ready!"
EOT
}
triggers = {
instance_id = aws_instance.mgmt_host.id
}
}
resource "null_resource" "run_ssm_command_download" {
provisioner "local-exec" {
command = <<-EOT
aws ssm send-command \
--instance-ids ${aws_instance.mgmt_host.id} \
--document-name "AWS-RunShellScript" \
--parameters commands="echo HELLO!" \
--region eu-west-2
EOT
}
depends_on = [null_resource.wait_for_instance]
}
The aws ec2 describe-instance-status is waiting for the instance not only to be “started”, but also for the instance to be “ready”, which in the AWS Web GUI will show as “2 Checks Passed”.