// CreateKeyPair creates a KeyPair of a specified class in the specified region func CreateKeyPair(class, region string, dryRun bool) error { if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } // KeyPair Class Config keypairCfg, err := config.LoadKeyPairClass(class) if err != nil { return err } terminal.Information("Found KeyPair class configuration for [" + class + "]!") // Validate the region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } // Import the KeyPair to the requested region err = importKeyPair(region, class, []byte(keypairCfg.PublicKey), dryRun) if err != nil { return err } return nil }
// DeleteItemsByType batch deletes classes from SimpleDB func DeleteItemsByType(classType string) error { svc := simpledb.New(session.New(&aws.Config{Region: aws.String("us-east-1")})) // TODO handle default region preference existingItems, err := GetItemsByType(classType) if err != nil { return err } params := &simpledb.BatchDeleteAttributesInput{ DomainName: aws.String("awsm"), //Items: deleteList, } for _, item := range existingItems { itemName := aws.StringValue(item.Name) params.Items = append(params.Items, &simpledb.DeletableItem{ Name: item.Name, }) terminal.Information("Deleting [" + classType + "/" + itemName + "] Configuration...") } _, err = svc.BatchDeleteAttributes(params) if err != nil { return err } terminal.Information("Done!") return nil }
// UpdateAutoScaleGroups updates existing AutoScale Groups that match the given search term to the provided version of Launch Configuration func UpdateAutoScaleGroups(name, version string, double, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } asgList, _ := GetAutoScaleGroups(name) if len(*asgList) > 0 { // Print the table asgList.PrintTable() } else { return errors.New("No AutoScaling Groups found, Aborting!") } // Confirm if !terminal.PromptBool("Are you sure you want to update these AutoScaling Groups?") { return errors.New("Aborting!") } // Delete 'Em err = updateAutoScaleGroups(asgList, version, double, dryRun) if err == nil { terminal.Information("Done!") } return }
// InstallKeyPair installs a keypair locally func InstallKeyPair(class string, dryRun bool) error { // KeyPair Class Config keypairCfg, err := config.LoadKeyPairClass(class) if err != nil { return err } terminal.Information("Found KeyPair class configuration for [" + class + "]!") if !dryRun { currentUser, _ := user.Current() sshLocation := currentUser.HomeDir + "/.ssh/" privateKeyPath := sshLocation + class + ".pem" publicKeyPath := sshLocation + class + ".pub" // Private Key if _, err := os.Stat(privateKeyPath); !os.IsNotExist(err) { terminal.Information("Local private key named [" + class + "] already exists!") } else { privateKey := []byte(keypairCfg.PrivateKey1 + keypairCfg.PrivateKey2 + keypairCfg.PrivateKey3 + keypairCfg.PrivateKey4) err = ioutil.WriteFile(privateKeyPath, privateKey, 0655) if err != nil { return err } terminal.Information("Created private key at [" + privateKeyPath + "]") } // Public Key if _, err := os.Stat(publicKeyPath); !os.IsNotExist(err) { terminal.Information("Local public key named [" + class + "] already exists!") } else { err = ioutil.WriteFile(publicKeyPath, []byte(keypairCfg.PublicKey), 0655) if err != nil { return err } terminal.Information("Created public key at [" + publicKeyPath + "]") } } return nil }
// DeleteSimpleDBDomains deletes one or more SimpleDB Domains func DeleteSimpleDBDomains(search, region string) (err error) { domainList := new(SimpleDBDomains) // Check if we were given a region or not if region != "" { err = GetRegionSimpleDBDomains(aws.String(region), domainList, search) } else { domainList, _ = GetSimpleDBDomains(search) } if err != nil { terminal.ErrorLine("Error gathering SimpleDB domains list") return } if len(*domainList) > 0 { // Print the table domainList.PrintTable() } else { terminal.ErrorLine("No SimpleDB Domains found, Aborting!") return } // Confirm if !terminal.PromptBool("Are you sure you want to delete these SimpleDB Domains?") { terminal.ErrorLine("Aborting!") return } // Delete 'Em for _, domain := range *domainList { svc := simpledb.New(session.New(&aws.Config{Region: aws.String(domain.Region)})) params := &simpledb.DeleteDomainInput{ DomainName: aws.String(domain.Name), } _, err = svc.DeleteDomain(params) if err != nil { terminal.ErrorLine("Error while deleting SimpleDB Domain [" + domain.Name + "] in [" + domain.Region + "], Aborting!") return } terminal.Information("Deleted SimpleDB Domain [" + domain.Name + "] in [" + domain.Region + "]!") } terminal.Information("Done!") return }
// CreateVpc creates a new VPC func CreateVpc(class, name, ip, region string, dryRun bool) error { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } // Class Config cfg, err := config.LoadVpcClass(class) if err != nil { return err } terminal.Information("Found VPC Class Configuration for [" + class + "]!") // Validate the region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } // TODO limit to one VPC of a class per region, so that we can target VPCs by class instead of name. svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)})) // Create the VPC vpcParams := &ec2.CreateVpcInput{ CidrBlock: aws.String(ip + cfg.CIDR), DryRun: aws.Bool(dryRun), InstanceTenancy: aws.String(cfg.Tenancy), } createVpcResp, err := svc.CreateVpc(vpcParams) if err != nil { return err } terminal.Information("Created VPC [" + *createVpcResp.Vpc.VpcId + "] named [" + name + "] in [" + region + "]!") // Add Tags err = SetEc2NameAndClassTags(createVpcResp.Vpc.VpcId, name, class, region) if err != nil { return err } return nil }
// Private function without the confirmation terminal prompts func rebootInstances(instList *Instances, dryRun bool) (err error) { for _, instance := range *instList { azs, _ := regions.GetAZs() svc := ec2.New(session.New(&aws.Config{Region: aws.String(azs.GetRegion(instance.AvailabilityZone))})) params := &ec2.RebootInstancesInput{ InstanceIds: []*string{ aws.String(instance.InstanceID), }, DryRun: aws.Bool(dryRun), } _, err := svc.RebootInstances(params) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } terminal.Information("Rebooted Instance [" + instance.InstanceID + "] named [" + instance.Name + "] in [" + instance.AvailabilityZone + "]!") } return nil }
// CreateAddress creates a new Elastic IP Address in the given region and domain func CreateAddress(region, domain string, dryRun bool) error { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } // Validate the region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } // Validate the domain if !(domain == "vpc" || domain != "classic") { return errors.New("Domain should be either [vpc] or [classic].") } svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)})) // Create the address params := &ec2.AllocateAddressInput{ Domain: aws.String(domain), DryRun: aws.Bool(dryRun), } _, err := svc.AllocateAddress(params) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } return nil }
// Private function without the confirmation terminal prompts func deleteAutoScaleGroups(asgList *AutoScaleGroups, force, dryRun bool) (err error) { for _, asg := range *asgList { svc := autoscaling.New(session.New(&aws.Config{Region: aws.String(asg.Region)})) params := &autoscaling.DeleteAutoScalingGroupInput{ AutoScalingGroupName: aws.String(asg.Name), ForceDelete: aws.Bool(force), } // Delete it! if !dryRun { _, err := svc.DeleteAutoScalingGroup(params) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } terminal.Information("Deleted AutoScaling Group [" + asg.Name + "] in [" + asg.Region + "]!") } else { fmt.Println(params) } } return nil }
// ResumeProcesses resumes AutoScaling actions on AutoScaling Groups that match the provided search term and (optional) region func ResumeProcesses(search, region string, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } asgList := new(AutoScaleGroups) // Check if we were given a region or not if region != "" { err = GetRegionAutoScaleGroups(region, asgList, search) } else { asgList, _ = GetAutoScaleGroups(search) } if err != nil { return errors.New("Error gathering Autoscale Group list") } if len(*asgList) > 0 { // Print the table asgList.PrintTable() } else { return errors.New("No Autoscale Groups found!") } // Confirm if !terminal.PromptBool("Are you sure you want to resume these Autoscale Groups?") { return errors.New("Aborting!") } // Resume 'Em if !dryRun { err = resumeProcesses(asgList) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } terminal.Information("Done!") } return }
// DeleteKeyPairs deletes an existing KeyPair from AWS func DeleteKeyPairs(name string, dryRun bool) error { if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } keyList, err := GetKeyPairs(name) if err != nil { terminal.ErrorLine("Error gathering KeyPair list") return nil } if len(*keyList) > 0 { // Print the table keyList.PrintTable() } else { terminal.ErrorLine("No KeyPairs found, Aborting!") return nil } // Confirm if !terminal.PromptBool("Are you sure you want to delete these KeyPairs?") { terminal.ErrorLine("Aborting!") return nil } // Delete 'Em for _, key := range *keyList { svc := ec2.New(session.New(&aws.Config{Region: aws.String(key.Region)})) params := &ec2.DeleteKeyPairInput{ KeyName: aws.String(key.KeyName), DryRun: aws.Bool(dryRun), } _, err := svc.DeleteKeyPair(params) if err != nil { terminal.ErrorLine(err.Error()) } else { terminal.Information("Deleted KeyPair [" + key.KeyName + "] in region [" + key.Region + "]!") } } return nil }
// AttachVolume attaches an EBS Volume to an Instance func AttachVolume(volume, instance string, dryRun bool) error { // Get the instance instances, _ := GetInstances(instance, true) instCount := len(*instances) if instCount == 0 { return errors.New("No instances found for search term.") } else if instCount > 1 { return errors.New("Please limit your search terms to return only one instance.") } inst := (*instances)[0] region := inst.Region // Look for the volume in the same region as the instance volList := new(Volumes) err := GetRegionVolumes(region, volList, volume, true) if err != nil { return err } volCount := len(*volList) if volCount == 0 { return errors.New("No volumes found in the same region as instance with your search term.") } else if volCount > 1 { return errors.New("Please limit your search terms to return only one volume.") } vol := (*volList)[0] // Class Config volCfg, err := config.LoadVolumeClass(vol.Class) if err != nil { return err } terminal.Information("Found Volume Class Configuration for [" + vol.Class + "]!") // Attach it svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)})) params := &ec2.AttachVolumeInput{ Device: aws.String(volCfg.DeviceName), InstanceId: aws.String(inst.InstanceID), VolumeId: aws.String(vol.VolumeID), DryRun: aws.Bool(dryRun), } _, err = svc.AttachVolume(params) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } return nil }
// UpdateSecurityGroups updates one or more Security Groups that match the provided search term and optional region func UpdateSecurityGroups(search, region string, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } secGrpList := new(SecurityGroups) // Check if we were given a region or not if region != "" { err = GetRegionSecurityGroups(region, secGrpList, search) } else { secGrpList, _ = GetSecurityGroups(search) } if err != nil { return errors.New("Error gathering Security Groups list") } if len(*secGrpList) > 0 { // Print the table secGrpList.PrintTable() } else { return errors.New("No Security Groups found, Aborting!") } // Confirm if !terminal.PromptBool("Are you sure you want to update these Security Groups?") { return errors.New("Aborting!") } // Update 'Em err = updateSecurityGroups(secGrpList, dryRun) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } terminal.Information("Done!") return nil }
// DeleteSnapshots deletes one or more EBS Snapshots based on the given search term an optional region input. func DeleteSnapshots(search, region string, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } snapList := new(Snapshots) // Check if we were given a region or not if region != "" { err = GetRegionSnapshots(region, snapList, search, false) } else { snapList, _ = GetSnapshots(search, false) } if err != nil { return errors.New("Error gathering Snapshots list") } if len(*snapList) > 0 { // Print the table snapList.PrintTable() } else { return errors.New("No available Snapshots found, Aborting!") } // Confirm if !terminal.PromptBool("Are you sure you want to delete these Snapshots?") { return errors.New("Aborting!") } // Delete 'Em err = deleteSnapshots(snapList, dryRun) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } terminal.Information("Done!") return nil }
// DeleteLaunchConfigurations deletes one or more Launch Configurations that match the provided search term and optional region func DeleteLaunchConfigurations(search, region string, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } lcList := new(LaunchConfigs) // Check if we were given a region or not if region != "" { err = GetRegionLaunchConfigurations(region, lcList, search) } else { lcList, _ = GetLaunchConfigurations(search) } if err != nil { return errors.New("Error gathering Launch Configuration list") } if len(*lcList) > 0 { // Print the table lcList.PrintTable() } else { return errors.New("No Launch Configurations found!") } // Confirm if !terminal.PromptBool("Are you sure you want to delete these Launch Configurations?") { return errors.New("Aborting!") } // Delete 'Em err = deleteLaunchConfigurations(lcList, dryRun) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } terminal.Information("Done!") return nil }
// CopySnapshot copies a Snapshot to another region func CopySnapshot(search, region string, dryRun bool) error { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } // Validate the destination region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } // Get the source snapshot snapshots, _ := GetSnapshots(search, true) snapCount := len(*snapshots) if snapCount == 0 { return errors.New("No available snapshots found for your search terms.") } if snapCount > 1 { snapshots.PrintTable() return errors.New("Please limit your search to return only one snapshot.") } snapshot := (*snapshots)[0] copySnapResp, err := copySnapshot(snapshot, region, dryRun) if err != nil { return err } terminal.Information("Created Snapshot [" + *copySnapResp.SnapshotId + "] named [" + snapshot.Name + "] to [" + region + "]!") // Add Tags err = SetEc2NameAndClassTags(copySnapResp.SnapshotId, snapshot.Name, snapshot.Class, region) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } return nil }
// DeleteAutoScaleGroups deletes one or more AutoScale Groups that match the provided name and optionally the provided region func DeleteAutoScaleGroups(name, region string, force, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } asgList := new(AutoScaleGroups) // Check if we were given a region or not if region != "" { err = GetRegionAutoScaleGroups(region, asgList, name) } else { asgList, _ = GetAutoScaleGroups(name) } if err != nil { return errors.New("Error gathering AutoScaling Groups list") } if len(*asgList) > 0 { // Print the table asgList.PrintTable() } else { return errors.New("No AutoScaling Groups found, Aborting!") } // Confirm if !terminal.PromptBool("Are you sure you want to delete these AutoScaling Groups?") { return errors.New("Aborting!") } // Delete 'Em err = deleteAutoScaleGroups(asgList, force, dryRun) if err != nil { return err } terminal.Information("Done!") return nil }
// DeleteSubnets deletes one or more VPC Subnets based on the given name and optional region input. func DeleteSubnets(name, region string, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } subnetList := new(Subnets) // Check if we were given a region or not if region != "" { err = GetRegionSubnets(region, subnetList, name) } else { subnetList, _ = GetSubnets(name) } if err != nil { return errors.New("Error gathering Subnet list") } if len(*subnetList) > 0 { // Print the table subnetList.PrintTable() } else { return errors.New("No Subnets found, Aborting!") } // Confirm if !terminal.PromptBool("Are you sure you want to delete these Subnets?") { return errors.New("Aborting!") } // Delete 'Em err = deleteSubnets(subnetList, dryRun) if err != nil { return err } terminal.Information("Done!") return nil }
// RebootInstances reboots one or more instances based on the given search term an optional region input func RebootInstances(search, region string, dryRun bool) (err error) { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } instList := new(Instances) // Check if we were given a region or not if region != "" { err = GetRegionInstances(region, instList, search, true) } else { instList, _ = GetInstances(search, true) } if err != nil { return errors.New("Error gathering Instance list") } if len(*instList) > 0 { // Print the table instList.PrintTable() } else { return errors.New("No Instances found, Aborting!") } // Confirm if !terminal.PromptBool("Are you sure you want to reboot these Instances?") { return errors.New("Aborting!") } // Reboot 'Em err = rebootInstances(instList, dryRun) if err != nil { return err } terminal.Information("Done!") return nil }
// DeleteWidget deletes a widget from SimpleDB func DeleteWidget(widgetName string) error { svc := simpledb.New(session.New(&aws.Config{Region: aws.String("us-east-1")})) // TODO handle default region preference itemName := "widgets/" + widgetName params := &simpledb.DeleteAttributesInput{ DomainName: aws.String("awsm"), ItemName: aws.String(itemName), } terminal.Information("Deleting [" + itemName + "] Configuration...") _, err := svc.DeleteAttributes(params) if err != nil { return err } terminal.Information("Done!") return nil }
// CreateSecurityGroup creates a new Security Group based on the provided class, region, and VPC ID func CreateSecurityGroup(class, region, vpcID string, dryRun bool) error { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } // Validate the region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } // Verify the security group class input cfg, err := config.LoadSecurityGroupClass(class) if err != nil { return err } terminal.Information("Found Security Group class configuration for [" + class + "]") svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)})) // Create the security group params := &ec2.CreateSecurityGroupInput{ Description: aws.String(cfg.Description), GroupName: aws.String(class), DryRun: aws.Bool(dryRun), VpcId: aws.String(vpcID), } _, err = svc.CreateSecurityGroup(params) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return errors.New(awsErr.Message()) } return err } return nil }
// DeleteIAMUsers deletes one or more IAM Users that match the provided username func DeleteIAMUsers(username string) (err error) { userList, err := GetIAMUsers(username) if err != nil { terminal.ErrorLine("Error gathering SimpleDB domains list") return } if len(*userList) > 0 { // Print the table userList.PrintTable() } else { terminal.ErrorLine("No IAM Users found, Aborting!") return } // Confirm if !terminal.PromptBool("Are you sure you want to delete these IAM Users?") { terminal.ErrorLine("Aborting!") return } // Delete 'Em for _, user := range *userList { svc := iam.New(session.New()) params := &iam.DeleteUserInput{ UserName: aws.String(user.UserName), } _, err := svc.DeleteUser(params) if err != nil { terminal.ErrorLine("Error while deleting IAM User [" + user.UserName + "], Aborting!") return err } terminal.Information("Deleted IAM User [" + user.UserName + "]!") } terminal.Information("Done!") return }
// CreateSimpleDBDomain creates a new SimpleDB Domain func CreateSimpleDBDomain(domain, region string) error { // Validate the region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } svc := simpledb.New(session.New(&aws.Config{Region: aws.String(region)})) params := &simpledb.CreateDomainInput{ DomainName: aws.String(domain), } terminal.Information("Creating SimpleDB Domain [" + domain + "] in [" + region + "]...") _, err := svc.CreateDomain(params) if err == nil { terminal.Information("Done!") } return err }
// private function without terminal prompts func updateSecurityGroups(secGrpList *SecurityGroups, dryRun bool) error { for _, secGrp := range *secGrpList { // Verify the security group class input cfg, err := config.LoadSecurityGroupClass(secGrp.Class) if err != nil { terminal.Information("Skipping Security Group [" + secGrp.Name + "]") terminal.ErrorLine(err.Error()) continue } else { terminal.Information("Found Security Group class configuration for [" + secGrp.Class + "]") } // TODO fmt.Println("\n\n") fmt.Println("aws\n") fmt.Println(secGrp.SecurityGroupGrants) fmt.Println("awsm\n") fmt.Println(cfg.SecurityGroupGrants) fmt.Println("\n\n") hash1, err := hashstructure.Hash(secGrp.SecurityGroupGrants, nil) if err != nil { panic(err) } fmt.Printf("\n\n%d\n\n", hash1) hash2, err := hashstructure.Hash(cfg.SecurityGroupGrants, nil) if err != nil { panic(err) } fmt.Printf("\n\n%d\n\n", hash2) } return nil }
// addCredsDialog is the dialog for the new creds setup func (a *awsmCreds) addCredsDialog() { // TODO prompt for default, or named alternatives accessKey := terminal.PromptString("What is your AWS Access Key Id?") secretKey := terminal.PromptString("What is your AWS Secret Access Key?") // Add Credentials to the ~/.aws/credentials file profile := Profile{Name: "default", AccessKeyID: accessKey, SecretAccessKey: secretKey} a.Profiles = append(a.Profiles, profile) err := a.SaveCreds() if err != nil { terminal.Information("There was a problem saving the config to [~/.aws/credentials]!") } creds, err := testCreds() if err != nil || len(creds.ProviderName) == 0 { terminal.Information("There was a problem with auth, please try again.") a.addCredsDialog() } }
// RotateLaunchConfigurations rotates out older Launch Configurations func RotateLaunchConfigurations(class string, cfg config.LaunchConfigurationClass, dryRun bool) error { var wg sync.WaitGroup var errs []error autoScaleGroups, err := GetAutoScaleGroups("") if err != nil { return errors.New("Error while retrieving the list of launch configurations to exclude from rotation!") } excludedConfigs := autoScaleGroups.LockedLaunchConfigurations() regions := regions.GetRegionList() for _, region := range regions { wg.Add(1) go func(region *ec2.Region) { defer wg.Done() // Get all the launch configs of this class in this region launchConfigs, err := GetLaunchConfigurationsByName(*region.RegionName, class) if err != nil { terminal.ShowErrorMessage(fmt.Sprintf("Error gathering launch configuration list for region [%s]", *region.RegionName), err.Error()) errs = append(errs, err) } // Exclude the launch configs being used in Autoscale Groups for i, lc := range launchConfigs { if excludedConfigs[lc.Name] { terminal.Information("Launch Configuration [" + lc.Name + ") ] is being used in an autoscale group, skipping!") launchConfigs = append(launchConfigs[:i], launchConfigs[i+1:]...) } } // Delete the oldest ones if we have more than the retention number if len(launchConfigs) > cfg.Retain { sort.Sort(launchConfigs) // important! ds := launchConfigs[cfg.Retain:] deleteLaunchConfigurations(&ds, dryRun) } }(region) } wg.Wait() if errs != nil { return errors.New("Error rotating snapshots for [" + class + "]!") } return nil }
// rotateSnapshots rotates out older Snapshots func rotateSnapshots(class string, cfg config.SnapshotClass, dryRun bool) error { var wg sync.WaitGroup var errs []error launchConfigs, err := GetLaunchConfigurations("") if err != nil { return errors.New("Error while retrieving the list of assets to exclude from rotation!") } excludedSnaps := launchConfigs.LockedSnapshotIds() regions := regions.GetRegionList() for _, region := range regions { wg.Add(1) go func(region *ec2.Region) { defer wg.Done() // Get all the snapshots of this class in this region snapshots, err := GetSnapshotsByTag(*region.RegionName, "Class", class) if err != nil { terminal.ShowErrorMessage(fmt.Sprintf("Error gathering snapshot list for region [%s]", *region.RegionName), err.Error()) errs = append(errs, err) } // Exclude the snapshots being used in Launch Configurations for i, snap := range snapshots { if excludedSnaps[snap.SnapshotID] { terminal.Information("Snapshot [" + snap.Name + " (" + snap.SnapshotID + ") ] is being used in a launch configuration, skipping!") snapshots = append(snapshots[:i], snapshots[i+1:]...) } } // Delete the oldest ones if we have more than the retention number if len(snapshots) > cfg.Retain { sort.Sort(snapshots) // important! ds := snapshots[cfg.Retain:] deleteSnapshots(&ds, dryRun) } }(region) } wg.Wait() if errs != nil { return errors.New("Error rotating snapshots for [" + class + "]!") } return nil }
// CopyImage copies an existing AMI to another region func CopyImage(search, region string, dryRun bool) error { // --dry-run flag if dryRun { terminal.Information("--dry-run flag is set, not making any actual changes!") } // Validate the destination region if !regions.ValidRegion(region) { return errors.New("Region [" + region + "] is Invalid!") } // Get the source image images, _ := GetImages(search, true) imgCount := len(*images) if imgCount == 0 { return errors.New("No available images found for your search terms.") } if imgCount > 1 { images.PrintTable() return errors.New("Please limit your search to return only one image.") } image := (*images)[0] // Copy image to the destination region copyImageResp, err := copyImage(image, region, dryRun) if err != nil { return err } terminal.Information("Created Image [" + *copyImageResp.ImageId + "] named [" + image.Name + "] to [" + region + "]!") // Add Tags return SetEc2NameAndClassTags(copyImageResp.ImageId, image.Name, image.Class, region) }
// CheckCreds Runs before everything, verifying we have proper authentication or asking us to set some up func CheckCreds() bool { creds, err := testCreds() if err != nil || len(creds.ProviderName) == 0 { // Try to read the config file cfg, err := readCreds() if err != nil || len(cfg.Profiles) == 0 { // No Config Found, ask if we want to create one create := terminal.BoxPromptBool("No AWS Credentials found!", "Do you want to add them now?") if !create { terminal.Information("Ok then, maybe next time.. ") return false } cfg.addCredsDialog() } } return true }
func resumeProcesses(asgList *AutoScaleGroups) error { for _, asg := range *asgList { svc := autoscaling.New(session.New(&aws.Config{Region: aws.String(asg.Region)})) params := &autoscaling.ScalingProcessQuery{ AutoScalingGroupName: aws.String(asg.Name), } _, err := svc.ResumeProcesses(params) if err != nil { return err } terminal.Information("Resumed processes on Autoscale Group [" + asg.Name + "] in [" + asg.Region + "]!") } return nil }