import ( "context" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform/helper/resource" "testing" "time" ) func TestCreateEC2Instance(t *testing.T) { // Create an AWS session svc := ec2.New(session.Must(session.NewSession())) // Define EC2 instance parameters runParams := &ec2.RunInstancesInput{ ImageId: aws.String("ami-0c55b159cbfafe1f0"), InstanceType: aws.String("t3.micro"), MinCount: aws.Int64(1), MaxCount: aws.Int64(1), } // Create the EC2 instance _, err := svc.RunInstances(runParams) if err != nil { t.Fatal(err) } // Wait for the instance to be in the running state err = resource.Retry(10*time.Minute, func() *resource.RetryError { descParams := &ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ &ec2.Filter{ Name: aws.String("instance-state-name"), Values: []*string{aws.String("running")}, }, }, } descInstances, err := svc.DescribeInstances(descParams) if err != nil { return resource.NonRetryableError("Failed to describe instances: %s", err) } for _, res := range descInstances.Reservations { for _, inst := range res.Instances { if *inst.ImageId == "ami-0c55b159cbfafe1f0" && *inst.InstanceType == "t3.micro" { return nil } } } return resource.RetryableError(fmt.Errorf("Instance is not running")) }) if err != nil { t.Fatal(err) } t.Log("EC2 instance created and running.") }In this example, we use `StateChangeConf` to wait for the instance to be in the running state by describing the instances and checking their state until we find the instance with the desired parameters. If it takes longer than 10 minutes to find the running instance, the test will fail. Overall, the `StateChangeConf` package is incredibly useful when waiting for resources to transition to a specific state, and it's an essential package for infrastructure automation and testing.