github.com/adrian-bl/terraform@v0.7.0-rc2.0.20160705220747-de0a34fc3517/builtin/providers/aws/resource_aws_efs_mount_target.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/aws/awserr" 10 "github.com/aws/aws-sdk-go/service/ec2" 11 "github.com/aws/aws-sdk-go/service/efs" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func resourceAwsEfsMountTarget() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAwsEfsMountTargetCreate, 19 Read: resourceAwsEfsMountTargetRead, 20 Update: resourceAwsEfsMountTargetUpdate, 21 Delete: resourceAwsEfsMountTargetDelete, 22 23 Schema: map[string]*schema.Schema{ 24 "file_system_id": &schema.Schema{ 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 30 "ip_address": &schema.Schema{ 31 Type: schema.TypeString, 32 Computed: true, 33 Optional: true, 34 ForceNew: true, 35 }, 36 37 "security_groups": &schema.Schema{ 38 Type: schema.TypeSet, 39 Elem: &schema.Schema{Type: schema.TypeString}, 40 Set: schema.HashString, 41 Computed: true, 42 Optional: true, 43 }, 44 45 "subnet_id": &schema.Schema{ 46 Type: schema.TypeString, 47 Required: true, 48 ForceNew: true, 49 }, 50 51 "network_interface_id": &schema.Schema{ 52 Type: schema.TypeString, 53 Computed: true, 54 }, 55 "dns_name": &schema.Schema{ 56 Type: schema.TypeString, 57 Computed: true, 58 }, 59 }, 60 } 61 } 62 63 func resourceAwsEfsMountTargetCreate(d *schema.ResourceData, meta interface{}) error { 64 conn := meta.(*AWSClient).efsconn 65 66 input := efs.CreateMountTargetInput{ 67 FileSystemId: aws.String(d.Get("file_system_id").(string)), 68 SubnetId: aws.String(d.Get("subnet_id").(string)), 69 } 70 71 if v, ok := d.GetOk("ip_address"); ok { 72 input.IpAddress = aws.String(v.(string)) 73 } 74 if v, ok := d.GetOk("security_groups"); ok { 75 input.SecurityGroups = expandStringList(v.(*schema.Set).List()) 76 } 77 78 log.Printf("[DEBUG] Creating EFS mount target: %#v", input) 79 80 mt, err := conn.CreateMountTarget(&input) 81 if err != nil { 82 return err 83 } 84 85 d.SetId(*mt.MountTargetId) 86 87 stateConf := &resource.StateChangeConf{ 88 Pending: []string{"creating"}, 89 Target: []string{"available"}, 90 Refresh: func() (interface{}, string, error) { 91 resp, err := conn.DescribeMountTargets(&efs.DescribeMountTargetsInput{ 92 MountTargetId: aws.String(d.Id()), 93 }) 94 if err != nil { 95 return nil, "error", err 96 } 97 98 if len(resp.MountTargets) < 1 { 99 return nil, "error", fmt.Errorf("EFS mount target %q not found", d.Id()) 100 } 101 102 mt := resp.MountTargets[0] 103 104 log.Printf("[DEBUG] Current status of %q: %q", *mt.MountTargetId, *mt.LifeCycleState) 105 return mt, *mt.LifeCycleState, nil 106 }, 107 Timeout: 10 * time.Minute, 108 Delay: 2 * time.Second, 109 MinTimeout: 3 * time.Second, 110 } 111 112 _, err = stateConf.WaitForState() 113 if err != nil { 114 return fmt.Errorf("Error waiting for EFS mount target (%s) to create: %s", d.Id(), err) 115 } 116 117 log.Printf("[DEBUG] EFS mount target created: %s", *mt.MountTargetId) 118 119 return resourceAwsEfsMountTargetRead(d, meta) 120 } 121 122 func resourceAwsEfsMountTargetUpdate(d *schema.ResourceData, meta interface{}) error { 123 conn := meta.(*AWSClient).efsconn 124 125 if d.HasChange("security_groups") { 126 input := efs.ModifyMountTargetSecurityGroupsInput{ 127 MountTargetId: aws.String(d.Id()), 128 SecurityGroups: expandStringList(d.Get("security_groups").(*schema.Set).List()), 129 } 130 _, err := conn.ModifyMountTargetSecurityGroups(&input) 131 if err != nil { 132 return err 133 } 134 } 135 136 return resourceAwsEfsMountTargetRead(d, meta) 137 } 138 139 func resourceAwsEfsMountTargetRead(d *schema.ResourceData, meta interface{}) error { 140 conn := meta.(*AWSClient).efsconn 141 resp, err := conn.DescribeMountTargets(&efs.DescribeMountTargetsInput{ 142 MountTargetId: aws.String(d.Id()), 143 }) 144 if err != nil { 145 return err 146 } 147 148 if len(resp.MountTargets) < 1 { 149 return fmt.Errorf("EFS mount target %q not found", d.Id()) 150 } 151 152 mt := resp.MountTargets[0] 153 154 log.Printf("[DEBUG] Found EFS mount target: %#v", mt) 155 156 d.SetId(*mt.MountTargetId) 157 d.Set("file_system_id", *mt.FileSystemId) 158 d.Set("ip_address", *mt.IpAddress) 159 d.Set("subnet_id", *mt.SubnetId) 160 d.Set("network_interface_id", *mt.NetworkInterfaceId) 161 162 sgResp, err := conn.DescribeMountTargetSecurityGroups(&efs.DescribeMountTargetSecurityGroupsInput{ 163 MountTargetId: aws.String(d.Id()), 164 }) 165 if err != nil { 166 return err 167 } 168 169 d.Set("security_groups", schema.NewSet(schema.HashString, flattenStringList(sgResp.SecurityGroups))) 170 171 // DNS name per http://docs.aws.amazon.com/efs/latest/ug/mounting-fs-mount-cmd-dns-name.html 172 az, err := getAzFromSubnetId(*mt.SubnetId, meta.(*AWSClient).ec2conn) 173 if err != nil { 174 return fmt.Errorf("Failed getting AZ from subnet ID (%s): %s", *mt.SubnetId, err) 175 } 176 region := meta.(*AWSClient).region 177 d.Set("dns_name", fmt.Sprintf("%s.%s.efs.%s.amazonaws.com", az, *mt.FileSystemId, region)) 178 179 return nil 180 } 181 182 func getAzFromSubnetId(subnetId string, conn *ec2.EC2) (string, error) { 183 input := ec2.DescribeSubnetsInput{ 184 SubnetIds: []*string{aws.String(subnetId)}, 185 } 186 out, err := conn.DescribeSubnets(&input) 187 if err != nil { 188 return "", err 189 } 190 191 if len(out.Subnets) != 1 { 192 return "", fmt.Errorf("Expected exactly 1 subnet returned for %q", subnetId) 193 } 194 195 return *out.Subnets[0].AvailabilityZone, nil 196 } 197 198 func resourceAwsEfsMountTargetDelete(d *schema.ResourceData, meta interface{}) error { 199 conn := meta.(*AWSClient).efsconn 200 201 log.Printf("[DEBUG] Deleting EFS mount target %q", d.Id()) 202 _, err := conn.DeleteMountTarget(&efs.DeleteMountTargetInput{ 203 MountTargetId: aws.String(d.Id()), 204 }) 205 if err != nil { 206 return err 207 } 208 209 stateConf := &resource.StateChangeConf{ 210 Pending: []string{"available", "deleting", "deleted"}, 211 Target: []string{}, 212 Refresh: func() (interface{}, string, error) { 213 resp, err := conn.DescribeMountTargets(&efs.DescribeMountTargetsInput{ 214 MountTargetId: aws.String(d.Id()), 215 }) 216 if err != nil { 217 awsErr, ok := err.(awserr.Error) 218 if !ok { 219 return nil, "error", err 220 } 221 222 if awsErr.Code() == "MountTargetNotFound" { 223 return nil, "", nil 224 } 225 226 return nil, "error", awsErr 227 } 228 229 if len(resp.MountTargets) < 1 { 230 return nil, "", nil 231 } 232 233 mt := resp.MountTargets[0] 234 235 log.Printf("[DEBUG] Current status of %q: %q", *mt.MountTargetId, *mt.LifeCycleState) 236 return mt, *mt.LifeCycleState, nil 237 }, 238 Timeout: 10 * time.Minute, 239 Delay: 2 * time.Second, 240 MinTimeout: 3 * time.Second, 241 } 242 243 _, err = stateConf.WaitForState() 244 if err != nil { 245 return fmt.Errorf("Error waiting for EFS mount target (%q) to delete: %q", 246 d.Id(), err.Error()) 247 } 248 249 log.Printf("[DEBUG] EFS mount target %q deleted.", d.Id()) 250 251 return nil 252 }