Example #1
0
// CreateVolume creates a new EBS Volume
func CreateVolume(class, name, az string, dryRun bool) error {

	// --dry-run flag
	if dryRun {
		terminal.Information("--dry-run flag is set, not making any actual changes!")
	}

	// Class Config
	volCfg, err := config.LoadVolumeClass(class)
	if err != nil {
		return err
	}

	terminal.Information("Found Volume Class Configuration for [" + class + "]!")

	// Verify the az input
	azs, errs := regions.GetAZs()
	if errs != nil {
		return errors.New("Error Verifying Availability Zone input")
	}
	if !azs.ValidAZ(az) {
		return cli.NewExitError("Availability Zone ["+az+"] is Invalid!", 1)
	}

	terminal.Information("Found Availability Zone [" + az + "]!")

	region := azs.GetRegion(az)

	// Get the latest snapshot
	latestSnapshot, err := GetLatestSnapshotByTag(region, "Class", volCfg.Snapshot)
	if err != nil {
		return err
	}

	terminal.Information("Found Snapshot [" + latestSnapshot.SnapshotID + "] with class [" + latestSnapshot.Class + "] created [" + latestSnapshot.CreatedHuman + "]!")

	svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)}))

	params := &ec2.CreateVolumeInput{
		AvailabilityZone: aws.String(az),
		DryRun:           aws.Bool(dryRun),
		Size:             aws.Int64(int64(volCfg.VolumeSize)),
		SnapshotId:       aws.String(latestSnapshot.SnapshotID),
		VolumeType:       aws.String(volCfg.VolumeType),
		//Encrypted:      aws.Bool(true),
		//Iops:           aws.Int64(1),
		//KmsKeyId:       aws.String("String"),
	}
	createVolumeResp, err := svc.CreateVolume(params)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			return errors.New(awsErr.Message())
		}
		return err
	}

	terminal.Information("Created Volume [" + *createVolumeResp.VolumeId + "] named [" + name + "] in [" + region + "]!")

	// Add Tags
	err = SetEc2NameAndClassTags(createVolumeResp.VolumeId, name, class, region)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			return errors.New(awsErr.Message())
		}
		return err
	}

	return nil

}
Example #2
0
// Private function without the confirmation terminal prompts
func updateAutoScaleGroups(asgList *AutoScaleGroups, version string, double, dryRun bool) (err error) {

	for _, asg := range *asgList {

		// Get the ASG class config
		cfg, err := config.LoadAutoscalingGroupClass(asg.Class)
		if err != nil {
			return err
		}

		terminal.Information("Found Autoscaling group class configuration for [" + asg.Class + "]")

		// Get the Launch Configuration class config
		launchConfigurationCfg, err := config.LoadLaunchConfigurationClass(cfg.LaunchConfigurationClass)
		if err != nil {
			return err
		}

		terminal.Information("Found Launch Configuration class configuration for [" + cfg.LaunchConfigurationClass + "]")

		// Get the AZs
		azs, errs := regions.GetAZs()
		if errs != nil {
			return errors.New("Error gathering region list")
		}

		for region, regionAZs := range azs.GetRegionMap(cfg.AvailabilityZones) {

			// TODO check if exists yet ?

			// Verify that the latest Launch Configuration is available in this region
			lcName := GetLaunchConfigurationName(region, cfg.LaunchConfigurationClass, launchConfigurationCfg.Version)
			if lcName == "" {
				return fmt.Errorf("Launch Configuration [%s] version [%d] is not available in [%s]!", cfg.LaunchConfigurationClass, launchConfigurationCfg.Version, region)
			}
			terminal.Information(fmt.Sprintf("Found latest Launch Configuration [%s] version [%d] in [%s]", cfg.LaunchConfigurationClass, launchConfigurationCfg.Version, asg.Region))

			svc := autoscaling.New(session.New(&aws.Config{Region: aws.String(region)}))

			params := &autoscaling.UpdateAutoScalingGroupInput{
				AutoScalingGroupName: aws.String(asg.Name),
				AvailabilityZones: []*string{
					aws.String("XmlStringMaxLen255"), // Required
					// More values...
				},
				DefaultCooldown:         aws.Int64(int64(cfg.DefaultCooldown)),
				DesiredCapacity:         aws.Int64(int64(cfg.DesiredCapacity)),
				HealthCheckGracePeriod:  aws.Int64(int64(cfg.HealthCheckGracePeriod)),
				HealthCheckType:         aws.String(cfg.HealthCheckType),
				LaunchConfigurationName: aws.String(lcName),
				MaxSize:                 aws.Int64(int64(asg.MaxSize)),
				MinSize:                 aws.Int64(int64(asg.MinSize)),
				//NewInstancesProtectedFromScaleIn: aws.Bool(true), // TODO?
				//PlacementGroup:                   aws.String("XmlStringMaxLen255"), // TODO
			}

			subList := new(Subnets)
			var vpcZones []string

			if cfg.SubnetClass != "" {
				err := GetRegionSubnets(region, subList, "")
				if err != nil {
					return err
				}
			}

			// Set the AZs
			for _, az := range regionAZs {
				if !azs.ValidAZ(az) {
					return cli.NewExitError("Availability Zone ["+az+"] is Invalid!", 1)
				}
				terminal.Information("Found Availability Zone [" + az + "]!")

				params.AvailabilityZones = append(params.AvailabilityZones, aws.String(az))

				for _, sub := range *subList {
					if sub.Class == cfg.SubnetClass && sub.AvailabilityZone == az {
						vpcZones = append(vpcZones, sub.SubnetID)
					}
				}

			}

			// Set the VPCZoneIdentifier (SubnetIds seperated by comma)
			params.VPCZoneIdentifier = aws.String(strings.Join(vpcZones, ", "))

			// Set the Termination Policies
			for _, terminationPolicy := range cfg.LoadBalancerNames {
				params.TerminationPolicies = append(params.TerminationPolicies, aws.String(terminationPolicy)) // ??
			}

			// Update it!
			if !dryRun {
				_, err := svc.UpdateAutoScalingGroup(params)
				if err != nil {
					if awsErr, ok := err.(awserr.Error); ok {
						return errors.New(awsErr.Message())
					}
					return err
				}

				terminal.Information("Updated AutoScaling Group [" + asg.Name + "] in [" + region + "]!")

			} else {
				fmt.Println(params)
			}

		}

	}

	return nil
}
Example #3
0
// CreateAutoScaleGroups creates a new AutoScale Group of the given class
func CreateAutoScaleGroups(class string, dryRun bool) (err error) {

	// --dry-run flag
	if dryRun {
		terminal.Information("--dry-run flag is set, not making any actual changes!")
	}

	// Verify the asg config class input
	cfg, err := config.LoadAutoscalingGroupClass(class)
	if err != nil {
		return err
	}
	terminal.Information("Found Autoscaling group class configuration for [" + class + "]")

	// Verify the launchconfig class input
	launchConfigurationCfg, err := config.LoadLaunchConfigurationClass(cfg.LaunchConfigurationClass)
	if err != nil {
		return err
	}
	terminal.Information("Found Launch Configuration class configuration for [" + cfg.LaunchConfigurationClass + "]")

	// Get the AZs
	azs, errs := regions.GetAZs()
	if errs != nil {
		return errors.New("Error gathering region list")
	}

	for region, regionAZs := range azs.GetRegionMap(cfg.AvailabilityZones) {

		// Verify that the latest Launch Configuration is available in this region
		lcName := GetLaunchConfigurationName(region, cfg.LaunchConfigurationClass, launchConfigurationCfg.Version)
		if lcName == "" {
			return fmt.Errorf("Launch Configuration [%s] version [%d] is not available in [%s]!", cfg.LaunchConfigurationClass, launchConfigurationCfg.Version, region)
		}
		terminal.Information(fmt.Sprintf("Found latest Launch Configuration [%s] version [%d] in [%s]", cfg.LaunchConfigurationClass, launchConfigurationCfg.Version, region))

		svc := autoscaling.New(session.New(&aws.Config{Region: aws.String(region)}))

		params := &autoscaling.CreateAutoScalingGroupInput{
			AutoScalingGroupName:    aws.String(class),
			MaxSize:                 aws.Int64(int64(cfg.MaxSize)),
			MinSize:                 aws.Int64(int64(cfg.MinSize)),
			DefaultCooldown:         aws.Int64(int64(cfg.DefaultCooldown)),
			DesiredCapacity:         aws.Int64(int64(cfg.DesiredCapacity)),
			HealthCheckGracePeriod:  aws.Int64(int64(cfg.HealthCheckGracePeriod)),
			HealthCheckType:         aws.String(cfg.HealthCheckType),
			LaunchConfigurationName: aws.String(lcName),
			// InstanceId:                       aws.String("XmlStringMaxLen19"),  // TODO ?
			// NewInstancesProtectedFromScaleIn: aws.Bool(true),                   // TODO ?
			// PlacementGroup:                   aws.String("XmlStringMaxLen255"), // TODO ?
			Tags: []*autoscaling.Tag{
				{
					// Name
					Key:               aws.String("Name"),
					PropagateAtLaunch: aws.Bool(true),
					ResourceId:        aws.String(class),
					ResourceType:      aws.String("auto-scaling-group"),
					Value:             aws.String(lcName),
				},
				{
					// Class
					Key:               aws.String("Class"),
					PropagateAtLaunch: aws.Bool(true),
					ResourceId:        aws.String(class),
					ResourceType:      aws.String("auto-scaling-group"),
					Value:             aws.String(class),
				},
			},
		}

		subList := new(Subnets)
		var vpcZones []string

		if cfg.SubnetClass != "" {
			err := GetRegionSubnets(region, subList, "")
			if err != nil {
				return err
			}
		}

		// Set the AZs
		for _, az := range regionAZs {
			if !azs.ValidAZ(az) {
				return cli.NewExitError("Availability Zone ["+az+"] is Invalid!", 1)
			}
			terminal.Information("Found Availability Zone [" + az + "]!")

			params.AvailabilityZones = append(params.AvailabilityZones, aws.String(az))

			for _, sub := range *subList {
				if sub.Class == cfg.SubnetClass && sub.AvailabilityZone == az {
					vpcZones = append(vpcZones, sub.SubnetID)
				}
			}

		}

		// Set the VPCZoneIdentifier (SubnetIds seperated by comma)
		params.VPCZoneIdentifier = aws.String(strings.Join(vpcZones, ", "))

		// Set the Load Balancers
		for _, elb := range cfg.LoadBalancerNames {
			params.LoadBalancerNames = append(params.LoadBalancerNames, aws.String(elb))
		}

		// Set the Termination Policies
		for _, terminationPolicy := range cfg.LoadBalancerNames {
			params.TerminationPolicies = append(params.TerminationPolicies, aws.String(terminationPolicy)) // ??
		}

		// Create it!
		if !dryRun {
			_, err := svc.CreateAutoScalingGroup(params)
			if err != nil {
				if awsErr, ok := err.(awserr.Error); ok {
					return errors.New(awsErr.Message())
				}
				return err
			}

			terminal.Information("Created AutoScaling Group [" + aws.StringValue(params.AutoScalingGroupName) + "] in [" + region + "]!")

			terminal.Information("Done!")
		} else {
			fmt.Println(params)
		}

	}

	return nil

}
Example #4
0
// CreateSubnet creates a new VPC Subnet
func CreateSubnet(class, name, vpc, ip, az 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.LoadSubnetClass(class)
	if err != nil {
		return err
	}

	terminal.Information("Found Subnet Class Configuration for [" + class + "]!")

	// Verify the az input
	azs, errs := regions.GetAZs()
	if errs != nil {
		return errors.New("Error Verifying Availability Zone input")
	}
	if !azs.ValidAZ(az) {
		return cli.NewExitError("Availability Zone ["+az+"] is Invalid!", 1)
	}

	terminal.Information("Found Availability Zone [" + az + "]!")

	region := azs.GetRegion(az)

	// Verify the vpc input
	targetVpc, err := GetVpcByTag(region, "Class", vpc)
	if err != nil {
		return err
	}
	terminal.Information("Found [" + targetVpc.Name + "] VPC [" + targetVpc.VpcID + "]!")

	// Create the Subnet

	svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)}))

	params := &ec2.CreateSubnetInput{
		CidrBlock:        aws.String(ip + cfg.CIDR),
		VpcId:            aws.String(targetVpc.VpcID),
		DryRun:           aws.Bool(dryRun),
		AvailabilityZone: aws.String(az),
	}

	createSubnetResp, err := svc.CreateSubnet(params)

	if err != nil {
		return err
	}

	terminal.Information("Created Subnet [" + *createSubnetResp.Subnet.SubnetId + "] named [" + name + "] in [" + *createSubnetResp.Subnet.AvailabilityZone + "]!")

	// Add Tags
	err = SetEc2NameAndClassTags(createSubnetResp.Subnet.SubnetId, name, class, region)

	if err != nil {
		return err
	}

	terminal.Information("Done!")

	return nil
}
Example #5
0
File: awsm.go Project: murdinc/awsm
// Main Function
////////////////..........
func main() {

	// Check for Creds
	found := aws.CheckCreds()
	if !found {
		return
	}

	// Check for the awsm db
	if !config.CheckDB() {
		create := terminal.BoxPromptBool("No awsm database found!", "Do you want to create one now?")
		if !create {
			terminal.Information("Ok then, maybe next time.. ")
			return
		}
		err := config.CreateAwsmDatabase()
		if err != nil {
			terminal.ErrorLine(err.Error())
			return
		}
	}

	var dryRun bool
	var force bool
	var double bool // optional flag when updating an auto-scale group

	app := cli.NewApp()
	app.Name = "awsm"
	app.Usage = "AWSM Interface"
	app.Version = "1.0"
	app.Author = "Ahmad A"
	app.Email = "*****@*****.**"
	app.EnableBashCompletion = true

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "dry-run",
			Destination: &dryRun,
			Usage:       "dry-run (Don't make any real changes)",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:  "api",
			Usage: "Start the awsm api server",
			Action: func(c *cli.Context) error {
				api.StartAPI()
				return nil
			},
		},
		/*
			{
				Name:  "dashboard",
				Usage: "Launch the awsm Dashboard GUI",
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:        "dev-mode",
						Destination: &dryRun,
						Usage:       "dev-mode (Don't reopen dashboard on each restart)",
					},
				},
				Action: func(c *cli.Context) error {
					aws.RunDashboard(c.Bool("dev-mode"))
					return nil
				},
			},
		*/
		{
			Name:  "attachVolume",
			Usage: "Attach an AWS EBS Volume to an EC2 Instance",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "volume",
					Description: "The volume to attach",
					Optional:    false,
				},
				cli.Argument{
					Name:        "instance",
					Description: "The instance to attach the volume to",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.AttachVolume(c.NamedArg("volume"), c.NamedArg("instance"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "installKeyPair",
			Usage: "Installs a Key Pair locally",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of the key pair",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.InstallKeyPair(c.NamedArg("class"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "copyImage",
			Usage: "Copy an AWS Machine Image to another region",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The image to copy",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to copy the image to",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CopyImage(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "copySnapshot",
			Usage: "Copy an AWS EBS Snapshot to another region",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The snapshot to copy",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to copy the snapshot to",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CopySnapshot(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createAddress",
			Usage: "Create an AWS Elastic IP Address",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "region",
					Description: "The region to create the elastic ip in",
					Optional:    false,
				},
				cli.Argument{
					Name:        "domain",
					Description: "The domain to create the elastic ip in (classic or vpc)",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateAddress(c.NamedArg("region"), c.NamedArg("domain"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createAutoScaleGroups",
			Usage: "Create an AWS AutoScaling Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of the autoscaling groups to create",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateAutoScaleGroups(c.NamedArg("class"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createIAMUser",
			Usage: "Create an IAM User",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "username",
					Description: "The username for this IAM user",
					Optional:    false,
				},
				cli.Argument{
					Name:        "path",
					Description: "The optional path for the user",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateIAMUser(c.NamedArg("username"), c.NamedArg("path"))
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createImage",
			Usage: "Create an AWS Machine Image from a running instance",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The AMI to create an image of",
					Optional:    false,
				},
				cli.Argument{
					Name:        "class",
					Description: "The class of the new image",
					Optional:    false,
				},
				cli.Argument{
					Name:        "name",
					Description: "The name of the new image",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateImage(c.NamedArg("search"), c.NamedArg("class"), c.NamedArg("name"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createLaunchConfigurations",
			Usage: "Create an AWS AutoScaling Launch Configurations",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of the launch configuration groups to create",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateLaunchConfigurations(c.NamedArg("class"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createKeyPair",
			Usage: "Create an AWS Key Pair in the specified region",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of the key pair",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to create the keypair in",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateKeyPair(c.NamedArg("class"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createSimpleDBDomain",
			Usage: "Create an AWS SimpleDB Domain",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "domain",
					Description: "The domain of the db",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the db",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateSimpleDBDomain(c.NamedArg("domain"), c.NamedArg("region"))
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createSnapshot",
			Usage: "Create an AWS EBS snapshot of a volume",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The volume to create a snapshot from",
					Optional:    false,
				},
				cli.Argument{
					Name:        "class",
					Description: "The class of the new snapshot",
					Optional:    false,
				},
				cli.Argument{
					Name:        "name",
					Description: "The name of the new snapshot",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateSnapshot(c.NamedArg("search"), c.NamedArg("class"), c.NamedArg("name"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createVolume",
			Usage: "Create an AWS EBS volume",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of the new volume",
					Optional:    false,
				},
				cli.Argument{
					Name:        "name",
					Description: "The name of the new volume",
					Optional:    false,
				},
				cli.Argument{
					Name:        "az",
					Description: "The Availability Zone to create the volume in",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateVolume(c.NamedArg("class"), c.NamedArg("name"), c.NamedArg("az"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createVpc",
			Usage: "Create an AWS VPC",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of VPC to create",
					Optional:    false,
				},
				cli.Argument{
					Name:        "name",
					Description: "The name of the VPC",
					Optional:    false,
				},
				cli.Argument{
					Name:        "ip",
					Description: "The IP address of this VPC (not including CIDR)",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to create the VPC in",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateVpc(c.NamedArg("class"), c.NamedArg("name"), c.NamedArg("ip"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "createSubnet",
			Usage: "Create an AWS VPC Subnet",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of Subnet to create",
					Optional:    false,
				},
				cli.Argument{
					Name:        "name",
					Description: "The name of the Subnet",
					Optional:    false,
				},
				cli.Argument{
					Name:        "vpc",
					Description: "The VPC to create the Subnet in",
					Optional:    false,
				},
				cli.Argument{
					Name:        "ip",
					Description: "The IP address of this Subnet (not including CIDR)",
					Optional:    false,
				},
				cli.Argument{
					Name:        "az",
					Description: "The Availability Zone to create the Subnet in",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.CreateSubnet(c.NamedArg("class"), c.NamedArg("name"), c.NamedArg("vpc"), c.NamedArg("ip"), c.NamedArg("az"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteAddresses",
			Usage: "Delete AWS Elastic IP Addresses",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for the elastic ip to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to delete the elastic ip from",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteAddresses(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteAutoScaleGroups",
			Usage: "Delete AWS AutoScaling Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for the autoscaling group to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to delete the autoscaling group from",
					Optional:    true,
				},
			},
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:        "force",
					Destination: &force,
					Usage:       "force (Force deletes all instances and lifecycle actions)",
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteAutoScaleGroups(c.NamedArg("search"), c.NamedArg("region"), force, dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteIAMUsers",
			Usage: "Delete AWS IAM Users",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for iam username",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteIAMUsers(c.NamedArg("search"))
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteImages",
			Usage: "Delete AWS Machine Images",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for images to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the images (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteImages(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteKeyPairs",
			Usage: "Delete AWS KeyPairs",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "name",
					Description: "The name of the AWS KeyPair to delete",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				errs := aws.DeleteKeyPairs(c.NamedArg("name"), dryRun)
				if errs != nil {
					return cli.NewExitError("Errors Deleting KeyPair!", 1)

				}
				return nil
			},
		},
		{
			Name:  "deleteLaunchConfigurations",
			Usage: "Delete AWS AutoScaling Launch Configurations",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for the launch configuration to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to delete the launch configuration from",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteLaunchConfigurations(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteSecurityGroups",
			Usage: "Delete AWS Security Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for the security group to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to delete the security group from",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteSecurityGroups(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteSnapshots",
			Usage: "Delete AWS EBS Snapshots",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for snapshots to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the snapshots (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteSnapshots(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteSimpleDBDomains",
			Usage: "Delete AWS SimpleDB Domains",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for simpleDB domain to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the DBs (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteSimpleDBDomains(c.NamedArg("search"), c.NamedArg("region"))
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteVolumes",
			Usage: "Delete AWS EBS Volumes",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "volume",
					Description: "The volume to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the volumes (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {

				err := aws.DeleteVolumes(c.NamedArg("volume"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteSubnets",
			Usage: "Delete AWS VPC Subnets",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for Subnets to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the subnets (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteSubnets(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "deleteVpcs",
			Usage: "Delete AWS VPCs",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for VPCs to delete",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the VPCs (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.DeleteVpcs(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "detachVolume",
			Usage: "Detach an AWS EBS Volume",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "volume",
					Description: "The volume to detach",
					Optional:    false,
				},
				cli.Argument{
					Name:        "instance",
					Description: "The instance to detach the volume from",
					Optional:    false,
				},
			},
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:        "force",
					Destination: &force,
					Usage:       "force detach",
				},
			},
			Action: func(c *cli.Context) error {

				err := aws.DetachVolume(c.NamedArg("volume"), c.NamedArg("instance"), force, dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "stopInstances",
			Usage: "Stop AWS instances",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for instance to stop",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the instance (optional)",
					Optional:    true,
				},
			},
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:        "force",
					Destination: &force,
					Usage:       "force (Force deletes all instances and lifecycle actions)",
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.StopInstances(c.NamedArg("search"), c.NamedArg("region"), force, dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "startInstances",
			Usage: "Start AWS instances",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for Instance to start",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the instance (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.StartInstances(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "rebootInstances",
			Usage: "Reboot AWS instances",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for instance to reboot",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the instance (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.RebootInstances(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "terminateInstances",
			Usage: "Terminate AWS instances",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "name",
					Description: "The search term for instance to terminate",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region of the instance (optional)",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.TerminateInstances(c.NamedArg("name"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "launchInstance",
			Usage: "Launch an EC2 instance",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "class",
					Description: "The class of the instance (dev, stage, etc)",
					Optional:    false,
				},
				cli.Argument{
					Name:        "sequence",
					Description: "The sequence of the instance (1...100)",
					Optional:    false,
				},
				cli.Argument{
					Name:        "az",
					Description: "The availability zone to launch the instance in (us-west-2a, us-east-1a, etc)",
					Optional:    false,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.LaunchInstance(c.NamedArg("class"), c.NamedArg("sequence"), c.NamedArg("az"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "listAddresses",
			Usage: "Lists AWS Elastic IP Addresses",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				addresses, errs := aws.GetAddresses(c.NamedArg("search"), false)
				if errs != nil {
					return cli.NewExitError("Error Listing Addresses!", 1)
				}
				addresses.PrintTable()
				return nil
			},
		},
		{
			Name:  "listAlarms",
			Usage: "Lists CloudWatch Alarms",
			Action: func(c *cli.Context) error {
				alarms, errs := aws.GetAlarms()
				if errs != nil {
					return cli.NewExitError("Error Listing Alarms!", 1)
				}
				alarms.PrintTable()

				return nil
			},
		},
		{
			Name:  "listAutoScaleGroups",
			Usage: "Lists AutoScale Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				groups, errs := aws.GetAutoScaleGroups(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing Auto Scale Groups!", 1)
				}
				groups.PrintTable()

				return nil
			},
		},
		{
			Name:  "listIAMUsers",
			Usage: "Lists IAM Users",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				iam, errs := aws.GetIAMUsers(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing IAM Users!", 1)
				}
				iam.PrintTable()

				return nil
			},
		},
		{
			Name:  "listImages",
			Usage: "Lists AWS Machine Images owned by us",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				images, errs := aws.GetImages(c.NamedArg("search"), false)
				if errs != nil {
					return cli.NewExitError("Error Listing Images!", 1)
				}
				images.PrintTable()

				return nil
			},
		},
		{
			Name:  "listInstances",
			Usage: "Lists AWS EC2 Instances",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				instances, errs := aws.GetInstances(c.NamedArg("search"), false)
				if errs != nil {
					return cli.NewExitError("Error Listing Instances!", 1)
				}
				instances.PrintTable()

				return nil
			},
		},
		{
			Name:  "listKeyPairs",
			Usage: "Lists AWS Key Pairs",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				keyPairs, errs := aws.GetKeyPairs(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing Key Pairs!", 1)
				}
				keyPairs.PrintTable()

				return nil
			},
		},
		{
			Name:  "listLaunchConfigurations",
			Usage: "Lists Launch Configurations",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				launchConfigs, errs := aws.GetLaunchConfigurations(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing Launch Configurations!", 1)
				}
				launchConfigs.PrintTable()

				return nil
			},
		},
		{
			Name:  "listLoadBalancers",
			Usage: "Lists Elastic Load Balancers",
			Action: func(c *cli.Context) error {
				loadBalancers, errs := aws.GetLoadBalancers()
				if errs != nil {
					return cli.NewExitError("Error Listing Load Balancers!", 1)
				}
				loadBalancers.PrintTable()

				return nil
			},
		},
		{
			Name:  "listScalingPolicies",
			Usage: "Lists Scaling Policies",
			Action: func(c *cli.Context) error {
				policies, errs := aws.GetScalingPolicies()
				if errs != nil {
					return cli.NewExitError("Error Listing Auto Scaling Policies!", 1)
				}
				policies.PrintTable()

				return nil
			},
		},
		{
			Name:  "listSecurityGroups",
			Usage: "Lists Security Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				groups, errs := aws.GetSecurityGroups(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing Security Groups!", 1)
				}
				groups.PrintTable()

				return nil
			},
		},
		{
			Name:  "listSnapshots",
			Usage: "Lists AWS EBS Snapshots",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				snapshots, errs := aws.GetSnapshots(c.NamedArg("search"), false)
				if errs != nil {
					return cli.NewExitError("Error Listing Snapshots!", 1)
				}
				snapshots.PrintTable()

				return nil
			},
		},
		{
			Name:  "listSubnets",
			Usage: "Lists AWS Subnets",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				subnets, errs := aws.GetSubnets(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing Subnets!", 1)
				}
				subnets.PrintTable()

				return nil
			},
		},
		{
			Name:  "listSimpleDBDomains",
			Usage: "Lists AWS SimpleDB Domains",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				domains, errs := aws.GetSimpleDBDomains(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing Simple DB Domains!", 1)
				}
				domains.PrintTable()

				return nil
			},
		},
		{
			Name:  "listVolumes",
			Usage: "Lists AWS EBS Volumes",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				volumes, errs := aws.GetVolumes(c.NamedArg("search"), false)
				if errs != nil {
					return cli.NewExitError("Error Listing Volumes!", 1)
				}
				volumes.PrintTable()

				return nil
			},
		},
		{
			Name:  "listVpcs",
			Usage: "Lists AWS Vpcs",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The keyword to search for",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				vpcs, errs := aws.GetVpcs(c.NamedArg("search"))
				if errs != nil {
					return cli.NewExitError("Error Listing VPCs!", 1)
				}
				vpcs.PrintTable()

				return nil
			},
		},
		{
			Name:  "resumeProcesses",
			Usage: "Resume scaling processes on autoscaling groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for the autoscaling group to resume",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to resume the processes in",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.ResumeProcesses(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "runCommand",
			Usage: "Run a command on a set of instances",
			Action: func(c *cli.Context) error {
				// TODO
				return nil
			},
		},
		{
			Name:  "suspendProcesses",
			Usage: "Suspend scaling processes on autoscaling groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term for the autoscaling group to suspend",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to suspend the processes in",
					Optional:    true,
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.SuspendProcesses(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "updateAutoScaleGroups",
			Usage: "Update AutoScaling Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term autoscaling group to update",
					Optional:    false,
				},
				cli.Argument{
					Name:        "version",
					Description: "The version of the launch configuration group to use (defaults to the most recent)",
					Optional:    true,
				},
			},
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:        "double",
					Destination: &double,
					Usage:       "double (Doubles the desired-capacity and max-capacity)",
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.UpdateAutoScaleGroups(c.NamedArg("search"), c.NamedArg("version"), double, dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
		{
			Name:  "updateSecurityGroups",
			Usage: "Update Security Groups",
			Arguments: []cli.Argument{
				cli.Argument{
					Name:        "search",
					Description: "The search term autoscaling group to update",
					Optional:    false,
				},
				cli.Argument{
					Name:        "region",
					Description: "The region to update the security groups in (optional)",
					Optional:    true,
				},
			},
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:        "double",
					Destination: &double,
					Usage:       "double (Doubles the desired-capacity and max-capacity)",
				},
			},
			Action: func(c *cli.Context) error {
				err := aws.UpdateSecurityGroups(c.NamedArg("search"), c.NamedArg("region"), dryRun)
				if err != nil {
					terminal.ErrorLine(err.Error())
				}
				return nil
			},
		},
	}

	app.Run(os.Args)
}
Example #6
0
// LaunchInstance Launches a new EC2 Instance
func LaunchInstance(class, sequence, az string, dryRun bool) error {

	// --dry-run flag
	if dryRun {
		terminal.Information("--dry-run flag is set, not making any actual changes!")
	}

	// Instance Class Config
	instanceCfg, err := config.LoadInstanceClass(class)
	if err != nil {
		return err
	}

	terminal.Information("Found Instance class configuration for [" + class + "]!")

	// AZ
	azs, _ := regions.GetAZs()
	if !azs.ValidAZ(az) {
		return cli.NewExitError("Availability Zone ["+az+"] is Invalid!", 1)
	}

	terminal.Information("Found Availability Zone [" + az + "]!")

	region := azs.GetRegion(az)

	// AMI
	ami, err := GetLatestImageByTag(region, "Class", instanceCfg.AMI)
	if err != nil {
		return err
	}

	terminal.Information("Found AMI [" + ami.ImageID + "] with class [" + ami.Class + "] created [" + ami.CreatedHuman + "]!")

	// EBS
	ebsVolumes := make([]*ec2.BlockDeviceMapping, len(instanceCfg.EBSVolumes))
	for i, ebsClass := range instanceCfg.EBSVolumes {
		volCfg, err := config.LoadVolumeClass(ebsClass)
		if err != nil {
			return err
		}

		terminal.Information("Found Volume Class Configuration for [" + ebsClass + "]!")

		latestSnapshot, err := GetLatestSnapshotByTag(region, "Class", volCfg.Snapshot)
		if err != nil {
			return err
		}

		terminal.Information("Found Snapshot [" + latestSnapshot.SnapshotID + "] with class [" + latestSnapshot.Class + "] created [" + latestSnapshot.CreatedHuman + "]!")

		ebsVolumes[i] = &ec2.BlockDeviceMapping{
			DeviceName: aws.String(volCfg.DeviceName),
			Ebs: &ec2.EbsBlockDevice{
				DeleteOnTermination: aws.Bool(volCfg.DeleteOnTermination),
				//Encrypted:           aws.Bool(volCfg.Encrypted),
				SnapshotId: aws.String(latestSnapshot.SnapshotID),
				VolumeSize: aws.Int64(int64(volCfg.VolumeSize)),
				VolumeType: aws.String(volCfg.VolumeType),
			},
			//NoDevice:    aws.String("String"),
			//VirtualName: aws.String("String"),
		}

		if volCfg.VolumeType == "io1" {
			ebsVolumes[i].Ebs.Iops = aws.Int64(int64(volCfg.Iops))
		}

	}

	// EBS Optimized
	if instanceCfg.EbsOptimized {
		terminal.Information("Launching as EBS Optimized")
	}

	// IAM Profile
	var iam IAMUser
	if len(instanceCfg.IAMUser) > 0 {
		iam, err := GetIAMUser(instanceCfg.IAMUser)
		if err != nil {
			return err
		}

		terminal.Information("Found IAM User [" + iam.UserName + "]!")

	}

	// KeyPair
	keyPair, err := GetKeyPairByName(region, instanceCfg.KeyName)
	if err != nil {
		return err
	}

	terminal.Information("Found KeyPair [" + keyPair.KeyName + "] in [" + keyPair.Region + "]!")

	// Network Interfaces

	// Placement ??

	// VPC / Subnet
	var vpc Vpc
	var subnet Subnet
	var subnetID string
	secGroupIds := make([]*string, len(instanceCfg.SecurityGroups))
	if instanceCfg.Vpc != "" && instanceCfg.Subnet != "" {
		// VPC
		vpc, err = GetVpcByTag(region, "Class", instanceCfg.Vpc)
		if err != nil {
			return err
		}

		terminal.Information("Found VPC [" + vpc.VpcID + "] in Region [" + region + "]!")

		// Subnet
		subnet, err = vpc.GetVpcSubnetByTag("Class", instanceCfg.Subnet)
		if err != nil {
			return err
		}

		subnetID = subnet.SubnetID
		terminal.Information("Found Subnet [" + subnet.SubnetID + "] in VPC [" + subnet.VpcID + "]!")

		// VPC Security Groups
		secGroups, err := vpc.GetVpcSecurityGroupByTagMulti("Class", instanceCfg.SecurityGroups)
		if err != nil {
			return err
		}

		for i, secGroup := range secGroups {
			terminal.Information("Found VPC Security Group [" + secGroup.GroupID + "] with name [" + secGroup.Name + "]!")
			secGroupIds[i] = aws.String(secGroup.GroupID)
		}

	} else {
		terminal.Information("No VPC and/or Subnet specified for instance Class [" + class + "]!")

		// EC2-Classic security groups
		secGroups, err := GetSecurityGroupByTagMulti(region, "Class", instanceCfg.SecurityGroups)
		if err != nil {
			return err
		}

		for i, secGroup := range secGroups {
			terminal.Information("Found Security Group [" + secGroup.GroupID + "] with name [" + secGroup.Name + "]!")
			secGroupIds[i] = aws.String(secGroup.GroupID)
		}

	}

	// User Data

	// ================================================================
	// ================================================================
	// ================================================================

	svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)}))

	params := &ec2.RunInstancesInput{
		ImageId:             aws.String(ami.ImageID),
		MaxCount:            aws.Int64(1),
		MinCount:            aws.Int64(1),
		BlockDeviceMappings: ebsVolumes,
		DryRun:              aws.Bool(dryRun),
		EbsOptimized:        aws.Bool(instanceCfg.EbsOptimized),
		IamInstanceProfile: &ec2.IamInstanceProfileSpecification{
			Arn:  aws.String(iam.Arn),
			Name: aws.String(iam.UserName),
		},
		InstanceInitiatedShutdownBehavior: aws.String(instanceCfg.ShutdownBehavior),
		InstanceType:                      aws.String(instanceCfg.InstanceType),
		KeyName:                           aws.String(keyPair.KeyName),
		Monitoring: &ec2.RunInstancesMonitoringEnabled{
			Enabled: aws.Bool(instanceCfg.Monitoring),
		},
		NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{ // only needed when we launch with a public ip. TODO
			{
			/*
				AssociatePublicIpAddress: aws.Bool(instanceCfg.PublicIpAddress),
				DeleteOnTermination:      aws.Bool(true),
				//Description:              aws.String("String"),
				DeviceIndex: aws.Int64(0),
				Groups: []*string{
					aws.String("String"), // Required
				},

					PrivateIpAddress:   aws.String("String"),
					PrivateIpAddresses: []*ec2.PrivateIpAddressSpecification{
						{ // Required
							PrivateIpAddress: aws.String("String"), // Required
							Primary:          aws.Bool(true),
						},
					},
					SecondaryPrivateIpAddressCount: aws.Int64(1),

					SubnetId:                       aws.String("String"),
			*/
			},
		},
		/*
			Placement: &ec2.Placement{ // havent played around with placements yet, TODO?
				Affinity:         aws.String("String"),
				AvailabilityZone: aws.String("String"),
				GroupName:        aws.String("String"),
				HostId:           aws.String("String"),
				Tenancy:          aws.String("Tenancy"),
			},
		*/
		// PrivateIpAddress: aws.String("String"),
		SecurityGroupIds: secGroupIds,
		SubnetId:         aws.String(subnetID),
		UserData:         aws.String(base64.StdEncoding.EncodeToString([]byte(instanceCfg.UserData))),

		//KernelId:         aws.String("String"),
		//RamdiskId:        aws.String("String"),
	}

	launchInstanceResp, err := svc.RunInstances(params)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			return errors.New(awsErr.Message())
		}
		return err
	}

	// Add Tags
	instanceTagsParams := &ec2.CreateTagsInput{
		Resources: []*string{
			launchInstanceResp.Instances[0].InstanceId,
		},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String("Name"),
				Value: aws.String(class + sequence),
			},
			{
				Key:   aws.String("Sequence"),
				Value: aws.String(sequence),
			},
			{
				Key:   aws.String("Class"),
				Value: aws.String(class),
			},
		},
		DryRun: aws.Bool(dryRun),
	}
	_, err = svc.CreateTags(instanceTagsParams)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			return errors.New(awsErr.Message())
		}
		return err
	}

	terminal.Information("Finished Launching Instance!")

	inst := make(Instances, 1)
	inst[1].Marshal(launchInstanceResp.Instances[0], region, &Subnets{subnet}, &Vpcs{vpc}, &Images{ami})

	inst.PrintTable()

	// ================================================================
	// ================================================================
	// ================================================================

	return nil
}