Skip to content

Instantly share code, notes, and snippets.

@dipankardas011
Last active January 3, 2024 07:42
Show Gist options
  • Save dipankardas011/3f848018d741cbd3d2985009d9ce7bfe to your computer and use it in GitHub Desktop.
Save dipankardas011/3f848018d741cbd3d2985009d9ce7bfe to your computer and use it in GitHub Desktop.
AWS Waiter in action
package main
import (
"context"
"fmt"
"log"
"os"
"sort"
"strings"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
)
func createSG(client *ec2.Client) (*string, error) {
sgInput := &ec2.CreateSecurityGroupInput{
Description: aws.String("testrun"),
GroupName: aws.String("test"),
}
// Create the security group
createSGResp, err := client.CreateSecurityGroup(context.TODO(), sgInput)
if err != nil {
return nil, fmt.Errorf("failed to create security group: %w", err)
}
// Get the ID of the created security group
securityGroupID := createSGResp.GroupId
// Add an inbound rule to allow incoming traffic on port 22 (SSH)
ingressInput := &ec2.AuthorizeSecurityGroupIngressInput{
GroupId: securityGroupID,
IpProtocol: aws.String("tcp"),
FromPort: aws.Int32(22),
ToPort: aws.Int32(22),
CidrIp: aws.String("0.0.0.0/0"), // Allow from any IP address
}
// Authorize the security group ingress rule
_, err = client.AuthorizeSecurityGroupIngress(context.TODO(), ingressInput)
if err != nil {
return nil, fmt.Errorf("failed to authorize ingress rule: %w", err)
}
return securityGroupID, nil
}
func CreateInstance(client *ec2.Client, sgId *string) (*string, error) {
amiID, err := getLatestAmazonLinux2AMI(client)
if err != nil {
log.Fatalf("failed to get AMI ID: %v", err)
return nil, err
}
fmt.Println("amiid:", amiID)
//
instanceInput := &ec2.RunInstancesInput{
ImageId: aws.String(amiID),
InstanceType: types.InstanceTypeT2Micro,
MinCount: aws.Int32(1),
MaxCount: aws.Int32(1),
KeyName: aws.String("abcd"),
SecurityGroupIds: []string{*sgId},
}
resp, err := client.RunInstances(context.TODO(), instanceInput)
if err != nil {
log.Fatalf("failed to launch instance, %v", err)
return nil, err
}
instanceID := resp.Instances[0].InstanceId
fmt.Printf("Launched EC2 instance with ID: %s\n", *instanceID)
ec2RunningWaiter := ec2.NewInstanceRunningWaiter(client, func(irwo *ec2.InstanceRunningWaiterOptions) {
irwo.MaxDelay = 300 * time.Second
irwo.MinDelay = 20 * time.Second
})
describeEc2Inp := &ec2.DescribeInstancesInput{
InstanceIds: []string{*instanceID},
}
err = ec2RunningWaiter.Wait(context.TODO(), describeEc2Inp, 300*time.Second)
if err != nil {
log.Fatal(err)
return nil, err
}
fmt.Println("Your instance is up and running, id=", *instanceID)
out, err := client.DescribeInstances(context.TODO(), describeEc2Inp)
if err != nil {
log.Fatal(err)
return nil, err
}
// Check if any instances were found
if len(out.Reservations) == 0 || len(out.Reservations[0].Instances) == 0 {
return nil, fmt.Errorf("instance not found with ID: %s", *instanceID)
}
// Get the public IP address of the instance (assuming it has only one network interface)
pubIP := out.Reservations[0].Instances[0].PublicIpAddress
privateIP := out.Reservations[0].Instances[0].PrivateIpAddress
fmt.Println("PrivateIP=", privateIP)
fmt.Printf("Use $ ssh -i abcd.pem ubuntu@%s\n", *pubIP)
return instanceID, nil
}
func DeleteInstance(client *ec2.Client, instanceID *string) error {
_, err := client.TerminateInstances(context.TODO(), &ec2.TerminateInstancesInput{InstanceIds: []string{*instanceID}})
if err != nil {
log.Fatalf("failed to delete instance, %v", err)
return err
}
ec2TerminatedWaiter := ec2.NewInstanceTerminatedWaiter(client, func(itwo *ec2.InstanceTerminatedWaiterOptions) {
itwo.MaxDelay = 300 * time.Second
itwo.MinDelay = 20 * time.Second
})
describeEc2Inp := &ec2.DescribeInstancesInput{
InstanceIds: []string{*instanceID},
}
err = ec2TerminatedWaiter.Wait(context.TODO(), describeEc2Inp, 300*time.Second)
if err != nil {
log.Fatal(err)
return err
}
return nil
}
func deleteSG(client *ec2.Client, sgId *string) error {
// Create the security group
_, err := client.DeleteSecurityGroup(context.TODO(), &ec2.DeleteSecurityGroupInput{GroupId: sgId})
if err != nil {
return fmt.Errorf("failed to create security group: %w", err)
}
return nil
}
func waiter() {
fmt.Println("Enter 0 to continue towards deletion")
ch := 0
_, err := fmt.Scanf("%d", &ch)
if err != nil {
panic(err)
}
if ch == 0 {
return
} else {
fmt.Println("Existed...")
os.Exit(0)
}
}
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithSharedConfigProfile("ksctl"), config.WithRegion("ap-south-1"))
if err != nil {
log.Fatal(err)
}
client := ec2.NewFromConfig(cfg)
sgId, err := createSG(client)
if err != nil {
panic(err)
}
instID, err := CreateInstance(client, sgId)
if err != nil {
panic(err)
}
waiter()
if err := DeleteInstance(client, instID); err != nil {
panic(err)
}
if err := deleteSG(client, sgId); err != nil {
panic(err)
}
fmt.Println("Delete the Resources")
}
// helper recieved from https://ubuntu.com/tutorials/search-and-launch-ubuntu-22-04-in-aws-using-cli#2-search-for-the-right-ami
func trustedSource(id string) bool {
// 679593333241
// 099720109477
if strings.Compare(id, "679593333241") != 0 && strings.Compare(id, "099720109477") != 0 {
return false
}
return true
}
func getLatestAmazonLinux2AMI(client *ec2.Client) (string, error) {
// Specify the filter for Amazon Linux 2 images
imageFilter := &ec2.DescribeImagesInput{
Filters: []types.Filter{
{
Name: aws.String("name"),
Values: []string{"ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server*"},
},
{
Name: aws.String("architecture"),
Values: []string{"x86_64"},
},
{
Name: aws.String("owner-alias"),
Values: []string{"amazon"},
},
},
}
// Get the latest Amazon Linux 2 AMI
resp, err := client.DescribeImages(context.TODO(), imageFilter)
if err != nil {
return "", fmt.Errorf("failed to describe images: %w", err)
}
if len(resp.Images) == 0 {
return "", fmt.Errorf("no images found")
}
var savedImages []types.Image
for _, i := range resp.Images {
if trustedSource(*i.OwnerId) && *i.Public {
savedImages = append(savedImages, i)
}
}
sort.Slice(savedImages, func(i, j int) bool {
return *savedImages[i].CreationDate > *savedImages[j].CreationDate
})
for x := 0; x < 2; x++ {
i := savedImages[x]
fmt.Println("=======")
if i.ImageOwnerAlias != nil {
fmt.Printf("%#+v\n", *i.ImageOwnerAlias)
}
fmt.Printf("%#v\n", *i.CreationDate)
fmt.Printf("%#v\n", *i.Public)
fmt.Printf("%#v\n", *i.OwnerId)
fmt.Printf("%#v\n", i.Architecture.Values())
fmt.Printf("%#v\n", *i.Name)
fmt.Printf("%#v\n", *i.ImageId)
fmt.Println("=======")
}
// Get the latest image ID
latestAMI := savedImages[0].ImageId
return *latestAMI, nil
}
package main
import (
"context"
"log"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithSharedConfigProfile("ksctl"), config.WithRegion("ap-south-1"))
if err != nil {
log.Fatal(err)
}
input := &ec2.CreateVpcInput{
TagSpecifications: []types.TagSpecification{
{
ResourceType: types.ResourceTypeVpc,
Tags: []types.Tag{
{
Key: aws.String("Name"),
Value: aws.String("abcd"),
},
},
},
},
CidrBlock: aws.String("10.0.0.0/16"),
}
client := ec2.NewFromConfig(cfg)
o, err := client.CreateVpc(context.TODO(), input)
if err != nil {
log.Fatal(err)
}
// is there a poller
log.Printf("vpc: %#+v", o.Vpc.VpcId)
vpcExistsWaiter := ec2.NewVpcExistsWaiter(client, func(vewo *ec2.VpcExistsWaiterOptions) {
vewo.MinDelay = 10 * time.Second
vewo.MaxDelay = 300 * time.Second
})
describeVpcsInput := &ec2.DescribeVpcsInput{
VpcIds: []string{*o.Vpc.VpcId},
}
err = vpcExistsWaiter.Wait(context.TODO(), describeVpcsInput, 300*time.Second)
if err != nil {
log.Fatal(err)
}
log.Printf("vpc: %#+v", o.Vpc.VpcId)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment