diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 7f59b75310..9c6d1d077b 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -5,6 +5,7 @@ import ( "crypto/sha1" "encoding/base64" "encoding/hex" + "errors" "fmt" "log" "strings" @@ -32,67 +33,67 @@ func resourceAwsInstance() *schema.Resource { MigrateState: resourceAwsInstanceMigrateState, Schema: map[string]*schema.Schema{ - "ami": &schema.Schema{ + "ami": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "associate_public_ip_address": &schema.Schema{ + "associate_public_ip_address": { Type: schema.TypeBool, ForceNew: true, Computed: true, Optional: true, }, - "availability_zone": &schema.Schema{ + "availability_zone": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - "placement_group": &schema.Schema{ + "placement_group": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - "instance_type": &schema.Schema{ + "instance_type": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "key_name": &schema.Schema{ + "key_name": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: true, }, - "subnet_id": &schema.Schema{ + "subnet_id": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - "private_ip": &schema.Schema{ + "private_ip": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: true, }, - "source_dest_check": &schema.Schema{ + "source_dest_check": { Type: schema.TypeBool, Optional: true, Default: true, }, - "user_data": &schema.Schema{ + "user_data": { Type: schema.TypeString, Optional: true, ForceNew: true, @@ -106,7 +107,7 @@ func resourceAwsInstance() *schema.Resource { }, }, - "security_groups": &schema.Schema{ + "security_groups": { Type: schema.TypeSet, Optional: true, Computed: true, @@ -115,7 +116,7 @@ func resourceAwsInstance() *schema.Resource { Set: schema.HashString, }, - "vpc_security_group_ids": &schema.Schema{ + "vpc_security_group_ids": { Type: schema.TypeSet, Optional: true, Computed: true, @@ -123,59 +124,59 @@ func resourceAwsInstance() *schema.Resource { Set: schema.HashString, }, - "public_dns": &schema.Schema{ + "public_dns": { Type: schema.TypeString, Computed: true, }, - "network_interface_id": &schema.Schema{ + "network_interface_id": { Type: schema.TypeString, Computed: true, }, - "public_ip": &schema.Schema{ + "public_ip": { Type: schema.TypeString, Computed: true, }, - "instance_state": &schema.Schema{ + "instance_state": { Type: schema.TypeString, Computed: true, }, - "private_dns": &schema.Schema{ + "private_dns": { Type: schema.TypeString, Computed: true, }, - "ebs_optimized": &schema.Schema{ + "ebs_optimized": { Type: schema.TypeBool, Optional: true, ForceNew: true, }, - "disable_api_termination": &schema.Schema{ + "disable_api_termination": { Type: schema.TypeBool, Optional: true, }, - "instance_initiated_shutdown_behavior": &schema.Schema{ + "instance_initiated_shutdown_behavior": { Type: schema.TypeString, Optional: true, }, - "monitoring": &schema.Schema{ + "monitoring": { Type: schema.TypeBool, Optional: true, }, - "iam_instance_profile": &schema.Schema{ + "iam_instance_profile": { Type: schema.TypeString, ForceNew: true, Optional: true, }, - "tenancy": &schema.Schema{ + "tenancy": { Type: schema.TypeString, Optional: true, Computed: true, @@ -184,60 +185,60 @@ func resourceAwsInstance() *schema.Resource { "tags": tagsSchema(), - "block_device": &schema.Schema{ + "block_device": { Type: schema.TypeMap, Optional: true, Removed: "Split out into three sub-types; see Changelog and Docs", }, - "ebs_block_device": &schema.Schema{ + "ebs_block_device": { Type: schema.TypeSet, Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "delete_on_termination": &schema.Schema{ + "delete_on_termination": { Type: schema.TypeBool, Optional: true, Default: true, ForceNew: true, }, - "device_name": &schema.Schema{ + "device_name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "encrypted": &schema.Schema{ + "encrypted": { Type: schema.TypeBool, Optional: true, Computed: true, ForceNew: true, }, - "iops": &schema.Schema{ + "iops": { Type: schema.TypeInt, Optional: true, Computed: true, ForceNew: true, }, - "snapshot_id": &schema.Schema{ + "snapshot_id": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - "volume_size": &schema.Schema{ + "volume_size": { Type: schema.TypeInt, Optional: true, Computed: true, ForceNew: true, }, - "volume_type": &schema.Schema{ + "volume_type": { Type: schema.TypeString, Optional: true, Computed: true, @@ -254,24 +255,24 @@ func resourceAwsInstance() *schema.Resource { }, }, - "ephemeral_block_device": &schema.Schema{ + "ephemeral_block_device": { Type: schema.TypeSet, Optional: true, Computed: true, ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "device_name": &schema.Schema{ + "device_name": { Type: schema.TypeString, Required: true, }, - "virtual_name": &schema.Schema{ + "virtual_name": { Type: schema.TypeString, Optional: true, }, - "no_device": &schema.Schema{ + "no_device": { Type: schema.TypeBool, Optional: true, }, @@ -289,41 +290,38 @@ func resourceAwsInstance() *schema.Resource { }, }, - "root_block_device": &schema.Schema{ - // TODO: This is a set because we don't support singleton - // sub-resources today. We'll enforce that the set only ever has - // length zero or one below. When TF gains support for - // sub-resources this can be converted. - Type: schema.TypeSet, + "root_block_device": { + Type: schema.TypeList, Optional: true, Computed: true, + MaxItems: 1, Elem: &schema.Resource{ // "You can only modify the volume size, volume type, and Delete on // Termination flag on the block device mapping entry for the root // device volume." - bit.ly/ec2bdmap Schema: map[string]*schema.Schema{ - "delete_on_termination": &schema.Schema{ + "delete_on_termination": { Type: schema.TypeBool, Optional: true, Default: true, ForceNew: true, }, - "iops": &schema.Schema{ + "iops": { Type: schema.TypeInt, Optional: true, Computed: true, ForceNew: true, }, - "volume_size": &schema.Schema{ + "volume_size": { Type: schema.TypeInt, Optional: true, Computed: true, ForceNew: true, }, - "volume_type": &schema.Schema{ + "volume_type": { Type: schema.TypeString, Optional: true, Computed: true, @@ -331,10 +329,6 @@ func resourceAwsInstance() *schema.Resource { }, }, }, - Set: func(v interface{}) int { - // there can be only one root device; no need to hash anything - return 0 - }, }, }, } @@ -380,12 +374,12 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { // IAM instance profiles can take ~10 seconds to propagate in AWS: // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console if isAWSErr(err, "InvalidParameterValue", "Invalid IAM Instance Profile") { - log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") + log.Print("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") return resource.RetryableError(err) } // IAM roles can also take time to propagate in AWS: if isAWSErr(err, "InvalidParameterValue", " has no associated IAM Roles") { - log.Printf("[DEBUG] IAM Instance Profile appears to have no IAM roles, retrying...") + log.Print("[DEBUG] IAM Instance Profile appears to have no IAM roles, retrying...") return resource.RetryableError(err) } return resource.NonRetryableError(err) @@ -400,7 +394,7 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error launching source instance: %s", err) } if runResp == nil || len(runResp.Instances) == 0 { - return fmt.Errorf("Error launching source instance: no instances returned in response") + return errors.New("Error launching source instance: no instances returned in response") } instance := runResp.Instances[0] @@ -804,7 +798,7 @@ func blockDeviceIsRoot(bd *ec2.InstanceBlockDeviceMapping, instance *ec2.Instanc func fetchRootDeviceName(ami string, conn *ec2.EC2) (*string, error) { if ami == "" { - return nil, fmt.Errorf("Cannot fetch root device name for blank AMI ID.") + return nil, errors.New("Cannot fetch root device name for blank AMI ID.") } log.Printf("[DEBUG] Describing AMI %q to get root block device name", ami) @@ -911,7 +905,7 @@ func readBlockDeviceMappingsFromConfig( } if bdm.NoDevice == nil && aws.StringValue(bdm.VirtualName) == "" { - return nil, fmt.Errorf("virtual_name cannot be empty when no_device is false or undefined.") + return nil, errors.New("virtual_name cannot be empty when no_device is false or undefined.") } blockDevices = append(blockDevices, bdm) @@ -919,9 +913,9 @@ func readBlockDeviceMappingsFromConfig( } if v, ok := d.GetOk("root_block_device"); ok { - vL := v.(*schema.Set).List() + vL := v.([]interface{}) if len(vL) > 1 { - return nil, fmt.Errorf("Cannot specify more than one root_block_device.") + return nil, errors.New("Cannot specify more than one root_block_device.") } for _, v := range vL { bd := v.(map[string]interface{}) @@ -946,7 +940,7 @@ func readBlockDeviceMappingsFromConfig( ebs.Iops = aws.Int64(int64(v)) } else if v, ok := bd["iops"].(int); ok && v > 0 && *ebs.VolumeType != "io1" { // Message user about incompatibility - log.Printf("[WARN] IOPs is only valid for storate type io1 for EBS Volumes") + log.Print("[WARN] IOPs is only valid for storate type io1 for EBS Volumes") } if dn, err := fetchRootDeviceName(d.Get("ami").(string), conn); err == nil { @@ -1096,7 +1090,7 @@ func buildAwsInstanceOpts( // See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html sgs := v.(*schema.Set).List() if len(sgs) > 0 && hasSubnet { - log.Printf("[WARN] Deprecated. Attempting to use 'security_groups' within a VPC instance. Use 'vpc_security_group_ids' instead.") + log.Print("[WARN] Deprecated. Attempting to use 'security_groups' within a VPC instance. Use 'vpc_security_group_ids' instead.") } for _, v := range sgs { str := v.(string)