Skip to content

Instantly share code, notes, and snippets.

@niski84
Created April 24, 2024 06:54
Show Gist options
  • Save niski84/2a09e09f7477113d0866cabd445f84b2 to your computer and use it in GitHub Desktop.
Save niski84/2a09e09f7477113d0866cabd445f84b2 to your computer and use it in GitHub Desktop.
go get github.com/aws/aws-sdk-go-v2
go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/service/ec2
package main
import (
"context"
"fmt"
"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"
)
// ReportRow defines a row in the report.
type ReportRow map[string]string
// DescribeSnapshotVolumes retrieves and describes EC2 snapshots and their volumes.
func DescribeSnapshotVolumes(ctx context.Context) ([][]ReportRow, error) {
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load AWS SDK config: %w", err)
}
ec2Client := ec2.NewFromConfig(cfg)
paginator := ec2.NewDescribeSnapshotsPaginator(ec2Client, &ec2.DescribeSnapshotsInput{
OwnerIds: []string{"self"},
})
var report [][]ReportRow
for paginator.HasMorePages() {
fmt.Println("Fetching snapshots page...")
out, err := paginator.NextPage(ctx)
if err != nil {
return nil, fmt.Errorf("failed to fetch snapshots page: %w", err)
}
for _, snapshot := range out.Snapshots {
fmt.Printf("Processing snapshot %s...\n", *snapshot.SnapshotId)
volDesc, err := ec2Client.DescribeVolumes(ctx, &ec2.DescribeVolumesInput{
VolumeIds: []string{*snapshot.VolumeId},
})
if err != nil {
return nil, fmt.Errorf("failed to describe volume %s: %w", *snapshot.VolumeId, err)
}
for _, volume := range volDesc.Volumes {
if *volume.State == types.VolumeStateInUse {
fmt.Printf("Volume %s is in-use, describing attached instance...\n", *volume.VolumeId)
var instanceID string
for _, attachment := range volume.Attachments {
instanceID = *attachment.InstanceId
break
}
instanceDesc, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{
InstanceIds: []string{instanceID},
})
if err != nil {
return nil, fmt.Errorf("failed to describe instance %s: %w", instanceID, err)
}
instance := instanceDesc.Reservations[0].Instances[0]
lastRun := "never"
if instance.State.Name == types.InstanceStateNameRunning {
lastRun = time.Now().Format("2006-01-02")
} else if instance.LaunchTime != nil {
lastRun = instance.LaunchTime.Format("2006-01-02")
}
row := ReportRow{
"SnapshotID": *snapshot.SnapshotId,
"VolumeID": *volume.VolumeId,
"InstanceID": instanceID,
"EC2_LastRun": lastRun,
"Volume_Status": string(volume.State),
}
report = append(report, []ReportRow{row})
}
}
}
}
fmt.Println("Final report generated.")
return report, nil
}
func main() {
ctx := context.Background()
report, err := DescribeSnapshotVolumes(ctx)
if err != nil {
fmt.Printf("Error: %s\n", err)
} else {
fmt.Println("Report:")
for i, site := range report {
fmt.Printf("Site %d:\n", i+1)
for _, row := range site {
for field, value := range row {
fmt.Printf("%s: %s\n", field, value)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment