diff --git a/main.go b/main.go index 4ca5190..f7a5ef4 100644 --- a/main.go +++ b/main.go @@ -45,12 +45,12 @@ func indexAllInstances(config state.Config) state.Config { cloudID := mtdaws.GetCloudID(instance) ip, err := netip.ParseAddr(instance.PublicIP) if err != nil { - fmt.Println("Error converting ip:", err) + fmt.Println("Error converting ip:\t", err) continue } newService, found := indexInstance(config, cloudID, ip) if !found { - fmt.Println("New instance found:", newService.CloudID) + fmt.Println("New instance found:\t", newService.CloudID) config.MTD.Services = append(config.MTD.Services, newService) state.SaveConf(ConfigPath, config) awsNewInstanceCounter++ diff --git a/mtdaws/mtd.go b/mtdaws/mtd.go index ab60d50..c307f50 100644 --- a/mtdaws/mtd.go +++ b/mtdaws/mtd.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/thefeli73/polemos/state" ) @@ -17,38 +18,60 @@ func AWSMoveInstance(config state.Config) (state.Config) { realInstance, err := getInstanceDetailsFromString(svc, instanceID) if err != nil { - fmt.Println("Error getting instance details:", err) + fmt.Println("Error getting instance details:\t", err) return config } imageName, err := createImage(svc, instanceID) if err != nil { - fmt.Println("Error creating image:", err) + fmt.Println("Error creating image:\t", err) return config } - fmt.Println("Created image: ", imageName) + fmt.Println("Created image:\t", imageName) err = waitForImageReady(svc, imageName, 5*time.Minute) if err != nil { - fmt.Println("Error waiting for image to be ready:", err) + fmt.Println("Error waiting for image to be ready:\t", err) return config } - fmt.Println("Image is ready:", imageName) + fmt.Println("Image is ready:\t", imageName) newInstanceID, err := launchInstance(svc, realInstance, imageName) if err != nil { - fmt.Println("Error launching instance:", err) + fmt.Println("Error launching instance:\t", err) return config } - fmt.Println("Launched new instance:", newInstanceID) + fmt.Println("Launched new instance:\t", newInstanceID) err = terminateInstance(svc, instanceID) if err != nil { - fmt.Println("Error terminating instance:", err) + fmt.Println("Error terminating instance:\t", err) return config } - fmt.Println("Terminated original instance:", instanceID) + fmt.Println("Terminated old instance:\t", instanceID) + image, err := describeImage(svc, imageName) + if err != nil { + fmt.Println("Error describing image:\t", err) + return config + } + + err = deregisterImage(svc, imageName) + if err != nil { + fmt.Println("Error deregistering image:\t", err) + return config + } + fmt.Println("Deregistered image:\t", imageName) + + if len(image.BlockDeviceMappings) > 0 { + snapshotID := aws.ToString(image.BlockDeviceMappings[0].Ebs.SnapshotId) + err = deleteSnapshot(svc, snapshotID) + if err != nil { + fmt.Println("Error deleting snapshot:\t", err) + return config + } + fmt.Println("Deleted snapshot:\t", snapshotID) + } return config } diff --git a/mtdaws/utils.go b/mtdaws/utils.go index 429ffb3..32e87ed 100644 --- a/mtdaws/utils.go +++ b/mtdaws/utils.go @@ -75,20 +75,6 @@ func GetInstances(config state.Config) []AwsInstance { return awsInstances } -// PrintInstanceInfo prints info about a specific instance in a region -func PrintInstanceInfo(instance *types.Instance) { - fmt.Println("\tInstance ID:", aws.ToString(instance.InstanceId)) - fmt.Println("\t\tInstance DNS name:", aws.ToString(instance.PublicDnsName)) - fmt.Println("\t\tInstance Type:", string(instance.InstanceType)) - fmt.Println("\t\tAMI ID:", aws.ToString(instance.ImageId)) - fmt.Println("\t\tState:", string(instance.State.Name)) - fmt.Println("\t\tAvailability Zone:", aws.ToString(instance.Placement.AvailabilityZone)) - if instance.PublicIpAddress != nil { - fmt.Println("\t\tPublic IP Address:", aws.ToString(instance.PublicIpAddress)) - } - fmt.Println("\t\tPrivate IP Address:", aws.ToString(instance.PrivateIpAddress)) -} - // Instances returns all instances for a config i.e. a region func Instances(config aws.Config) ([]types.Instance, error) { svc := ec2.NewFromConfig(config) @@ -197,6 +183,44 @@ func terminateInstance(svc *ec2.Client, instanceID string) error { return err } +// describeImage gets info about an image from string +func describeImage(svc *ec2.Client, imageID string) (*types.Image, error) { + input := &ec2.DescribeImagesInput{ + ImageIds: []string{imageID}, + } + + output, err := svc.DescribeImages(context.TODO(), input) + if err != nil { + return nil, err + } + + if len(output.Images) == 0 { + return nil, errors.New("image not found") + } + + return &output.Images[0], nil +} + +// deregisterImage deletes the AMI passed as string +func deregisterImage(svc *ec2.Client, imageID string) error { + input := &ec2.DeregisterImageInput{ + ImageId: aws.String(imageID), + } + + _, err := svc.DeregisterImage(context.TODO(), input) + return err +} + +// deleteSnapshot deletes the snapshot passed as string +func deleteSnapshot(svc *ec2.Client, snapshotID string) error { + input := &ec2.DeleteSnapshotInput{ + SnapshotId: aws.String(snapshotID), + } + + _, err := svc.DeleteSnapshot(context.TODO(), input) + return err +} + // getInstanceDetailsFromString does what the name says func getInstanceDetailsFromString(svc *ec2.Client, instanceID string) (*types.Instance, error) { input := &ec2.DescribeInstancesInput{