// SendMessage sends an SNS message to an SNS region. // See http://docs.aws.amazon.com/sdk-for-go/api/service/sns.html#type-PublishInput func SendMessage(region string, topic string, subject string, message string) { if region == "" { log.Fatal("SNS region is required") } if topic == "" { log.Fatal("SNS topic is required") } if subject == "" { log.Fatal("SNS subject is required") } if message == "" { log.Fatal("SNS message is required") } params := &sns.PublishInput{ Subject: aws.String(subject), Message: aws.String(message), TargetArn: aws.String(topic), } sns := sns.New(session.New(), aws.NewConfig().WithRegion(region)) _, err := sns.Publish(params) awserror.HandleError(err) }
// DestroySnapshots deletes snapshots greater than SnapshotManager's NumSnapshotsToRetain for a given volume func (mgr *SnapshotManager) DestroySnapshots(volume *ec2.Volume) (snapshotsDestroyed int) { if mgr.NumSnapshotsToRetain < 1 { log.Fatal("NumSnapshotsToRetain should be great than 0") } params := &ec2.DescribeSnapshotsInput{ Filters: []*ec2.Filter{ { Name: aws.String("volume-id"), Values: []*string{ aws.String(*volume.VolumeId), }, }, }, } resp, err := mgr.ec2.DescribeSnapshots(params) awserror.HandleError(err) snapshots := resp.Snapshots sort.Sort(ByStartTime(snapshots)) numberSnapshotsToDelete := len(snapshots) - mgr.NumSnapshotsToRetain for numberSnapshotsToDelete > 0 { params := &ec2.DeleteSnapshotInput{ SnapshotId: aws.String(*resp.Snapshots[numberSnapshotsToDelete-1].SnapshotId), } _, err := mgr.ec2.DeleteSnapshot(params) if err != nil && err.(awserr.Error).Code() != "InvalidSnapshot.InUse" { awserror.HandleError(err) } numberSnapshotsToDelete-- snapshotsDestroyed++ } return snapshotsDestroyed }
// TagResource creates tags for an EBS snapshot func (mgr *SnapshotManager) TagResource(id *string, tags []*ec2.Tag) { // remove tags containing "aws:", as these are reserved by AWS // and cannot be duplicated for other resources filteredTags := tags[:0] for _, tag := range tags { if !strings.Contains(*tag.Key, "aws:") { filteredTags = append(filteredTags, tag) } } params := &ec2.CreateTagsInput{ Resources: []*string{ aws.String(*id), }, Tags: filteredTags, } _, err := mgr.ec2.CreateTags(params) awserror.HandleError(err) }
// CreateSnapshot creates an EBS snapshot for a specific EBS volume, optionally copying // any volume tags depending on SnapshotManager's CopyVolumeTags. If the volume has a Name tag, // it is used as the snapshot's description. func (mgr *SnapshotManager) CreateSnapshot(volume *ec2.Volume) { description := fmt.Sprintf("Snapshot for volume %s", *volume.VolumeId) for _, tag := range volume.Tags { if *tag.Key == "Name" { description = *tag.Value } } params := &ec2.CreateSnapshotInput{ Description: aws.String(description), VolumeId: aws.String(*volume.VolumeId), } log.Printf("Starting snapshot for %s in region %s", *volume.VolumeId, mgr.Region) snapshot, err := mgr.ec2.CreateSnapshot(params) awserror.HandleError(err) if mgr.CopyVolumeTags && len(volume.Tags) > 0 { mgr.TagResource(snapshot.SnapshotId, volume.Tags) } }
// SnapshotVolumes is a helper method that wraps several operations. It queries for attached // EBS volumes in the SnapshotManager's region, generates new snapshots, optionally // copying any volume tags, and keeps the last X snapshots as specified by retainCount. func (mgr *SnapshotManager) SnapshotVolumes() (snapshotsGenerated int) { params := &ec2.DescribeVolumesInput{ Filters: []*ec2.Filter{ { Name: aws.String("attachment.status"), Values: []*string{ aws.String("attached"), }, }, }, } resp, err := mgr.ec2.DescribeVolumes(params) awserror.HandleError(err) for _, volume := range resp.Volumes { mgr.CreateSnapshot(volume) mgr.DestroySnapshots(volume) snapshotsGenerated++ } return snapshotsGenerated }