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