github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_efs_file_system.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/efs"
    11  	"github.com/hashicorp/terraform/helper/resource"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  )
    14  
    15  func resourceAwsEfsFileSystem() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceAwsEfsFileSystemCreate,
    18  		Read:   resourceAwsEfsFileSystemRead,
    19  		Update: resourceAwsEfsFileSystemUpdate,
    20  		Delete: resourceAwsEfsFileSystemDelete,
    21  
    22  		Importer: &schema.ResourceImporter{
    23  			State: schema.ImportStatePassthrough,
    24  		},
    25  
    26  		Schema: map[string]*schema.Schema{
    27  			"creation_token": {
    28  				Type:         schema.TypeString,
    29  				Optional:     true,
    30  				Computed:     true,
    31  				ForceNew:     true,
    32  				ValidateFunc: validateMaxLength(64),
    33  			},
    34  
    35  			"reference_name": {
    36  				Type:         schema.TypeString,
    37  				Optional:     true,
    38  				Computed:     true,
    39  				Deprecated:   "Please use attribute `creation_token' instead. This attribute might be removed in future releases.",
    40  				ValidateFunc: validateReferenceName,
    41  			},
    42  
    43  			"performance_mode": {
    44  				Type:         schema.TypeString,
    45  				Optional:     true,
    46  				Computed:     true,
    47  				ForceNew:     true,
    48  				ValidateFunc: validatePerformanceModeType,
    49  			},
    50  
    51  			"tags": tagsSchema(),
    52  		},
    53  	}
    54  }
    55  
    56  func resourceAwsEfsFileSystemCreate(d *schema.ResourceData, meta interface{}) error {
    57  	conn := meta.(*AWSClient).efsconn
    58  
    59  	creationToken := ""
    60  	if v, ok := d.GetOk("creation_token"); ok {
    61  		creationToken = v.(string)
    62  	} else {
    63  		if v, ok := d.GetOk("reference_name"); ok {
    64  			creationToken = resource.PrefixedUniqueId(fmt.Sprintf("%s-", v.(string)))
    65  			log.Printf("[WARN] Using deprecated `reference_name' attribute.")
    66  		} else {
    67  			creationToken = resource.UniqueId()
    68  		}
    69  	}
    70  
    71  	createOpts := &efs.CreateFileSystemInput{
    72  		CreationToken: aws.String(creationToken),
    73  	}
    74  
    75  	if v, ok := d.GetOk("performance_mode"); ok {
    76  		createOpts.PerformanceMode = aws.String(v.(string))
    77  	}
    78  
    79  	log.Printf("[DEBUG] EFS file system create options: %#v", *createOpts)
    80  	fs, err := conn.CreateFileSystem(createOpts)
    81  	if err != nil {
    82  		return fmt.Errorf("Error creating EFS file system: %s", err)
    83  	}
    84  
    85  	d.SetId(*fs.FileSystemId)
    86  	log.Printf("[INFO] EFS file system ID: %s", d.Id())
    87  
    88  	stateConf := &resource.StateChangeConf{
    89  		Pending: []string{"creating"},
    90  		Target:  []string{"available"},
    91  		Refresh: func() (interface{}, string, error) {
    92  			resp, err := conn.DescribeFileSystems(&efs.DescribeFileSystemsInput{
    93  				FileSystemId: aws.String(d.Id()),
    94  			})
    95  			if err != nil {
    96  				return nil, "error", err
    97  			}
    98  
    99  			if hasEmptyFileSystems(resp) {
   100  				return nil, "not-found", fmt.Errorf("EFS file system %q could not be found.", d.Id())
   101  			}
   102  
   103  			fs := resp.FileSystems[0]
   104  			log.Printf("[DEBUG] current status of %q: %q", *fs.FileSystemId, *fs.LifeCycleState)
   105  			return fs, *fs.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 file system (%q) to create: %s",
   115  			d.Id(), err.Error())
   116  	}
   117  	log.Printf("[DEBUG] EFS file system %q created.", d.Id())
   118  
   119  	return resourceAwsEfsFileSystemUpdate(d, meta)
   120  }
   121  
   122  func resourceAwsEfsFileSystemUpdate(d *schema.ResourceData, meta interface{}) error {
   123  	conn := meta.(*AWSClient).efsconn
   124  	err := setTagsEFS(conn, d)
   125  	if err != nil {
   126  		return fmt.Errorf("Error setting EC2 tags for EFS file system (%q): %s",
   127  			d.Id(), err.Error())
   128  	}
   129  
   130  	return resourceAwsEfsFileSystemRead(d, meta)
   131  }
   132  
   133  func resourceAwsEfsFileSystemRead(d *schema.ResourceData, meta interface{}) error {
   134  	conn := meta.(*AWSClient).efsconn
   135  
   136  	resp, err := conn.DescribeFileSystems(&efs.DescribeFileSystemsInput{
   137  		FileSystemId: aws.String(d.Id()),
   138  	})
   139  	if err != nil {
   140  		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "FileSystemNotFound" {
   141  			log.Printf("[WARN] EFS file system (%s) could not be found.", d.Id())
   142  			d.SetId("")
   143  			return nil
   144  		}
   145  		return err
   146  	}
   147  
   148  	if hasEmptyFileSystems(resp) {
   149  		return fmt.Errorf("EFS file system %q could not be found.", d.Id())
   150  	}
   151  
   152  	tags := make([]*efs.Tag, 0)
   153  	var marker string
   154  	for {
   155  		params := &efs.DescribeTagsInput{
   156  			FileSystemId: aws.String(d.Id()),
   157  		}
   158  		if marker != "" {
   159  			params.Marker = aws.String(marker)
   160  		}
   161  
   162  		tagsResp, err := conn.DescribeTags(params)
   163  		if err != nil {
   164  			return fmt.Errorf("Error retrieving EC2 tags for EFS file system (%q): %s",
   165  				d.Id(), err.Error())
   166  		}
   167  
   168  		for _, tag := range tagsResp.Tags {
   169  			tags = append(tags, tag)
   170  		}
   171  
   172  		if tagsResp.NextMarker != nil {
   173  			marker = *tagsResp.NextMarker
   174  		} else {
   175  			break
   176  		}
   177  	}
   178  
   179  	err = d.Set("tags", tagsToMapEFS(tags))
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	var fs *efs.FileSystemDescription
   185  	for _, f := range resp.FileSystems {
   186  		if d.Id() == *f.FileSystemId {
   187  			fs = f
   188  			break
   189  		}
   190  	}
   191  	if fs == nil {
   192  		log.Printf("[WARN] EFS (%s) not found, removing from state", d.Id())
   193  		d.SetId("")
   194  		return nil
   195  	}
   196  
   197  	d.Set("creation_token", fs.CreationToken)
   198  	d.Set("performance_mode", fs.PerformanceMode)
   199  
   200  	return nil
   201  }
   202  
   203  func resourceAwsEfsFileSystemDelete(d *schema.ResourceData, meta interface{}) error {
   204  	conn := meta.(*AWSClient).efsconn
   205  
   206  	log.Printf("[DEBUG] Deleting EFS file system: %s", d.Id())
   207  	_, err := conn.DeleteFileSystem(&efs.DeleteFileSystemInput{
   208  		FileSystemId: aws.String(d.Id()),
   209  	})
   210  	stateConf := &resource.StateChangeConf{
   211  		Pending: []string{"available", "deleting"},
   212  		Target:  []string{},
   213  		Refresh: func() (interface{}, string, error) {
   214  			resp, err := conn.DescribeFileSystems(&efs.DescribeFileSystemsInput{
   215  				FileSystemId: aws.String(d.Id()),
   216  			})
   217  			if err != nil {
   218  				efsErr, ok := err.(awserr.Error)
   219  				if ok && efsErr.Code() == "FileSystemNotFound" {
   220  					return nil, "", nil
   221  				}
   222  				return nil, "error", err
   223  			}
   224  
   225  			if hasEmptyFileSystems(resp) {
   226  				return nil, "", nil
   227  			}
   228  
   229  			fs := resp.FileSystems[0]
   230  			log.Printf("[DEBUG] current status of %q: %q", *fs.FileSystemId, *fs.LifeCycleState)
   231  			return fs, *fs.LifeCycleState, nil
   232  		},
   233  		Timeout:    10 * time.Minute,
   234  		Delay:      2 * time.Second,
   235  		MinTimeout: 3 * time.Second,
   236  	}
   237  
   238  	_, err = stateConf.WaitForState()
   239  	if err != nil {
   240  		return fmt.Errorf("Error waiting for EFS file system (%q) to delete: %s",
   241  			d.Id(), err.Error())
   242  	}
   243  
   244  	log.Printf("[DEBUG] EFS file system %q deleted.", d.Id())
   245  
   246  	return nil
   247  }
   248  
   249  func validateReferenceName(v interface{}, k string) (ws []string, errors []error) {
   250  	value := v.(string)
   251  	creationToken := resource.PrefixedUniqueId(fmt.Sprintf("%s-", value))
   252  	if len(creationToken) > 64 {
   253  		errors = append(errors, fmt.Errorf(
   254  			"%q cannot take the Creation Token over the limit of 64 characters: %q", k, value))
   255  	}
   256  	return
   257  }
   258  
   259  func validatePerformanceModeType(v interface{}, k string) (ws []string, errors []error) {
   260  	value := v.(string)
   261  	if value != efs.PerformanceModeGeneralPurpose && value != efs.PerformanceModeMaxIo {
   262  		errors = append(errors, fmt.Errorf(
   263  			"%q contains an invalid Performance Mode %q. Valid modes are either %q or %q.",
   264  			k, value, efs.PerformanceModeGeneralPurpose, efs.PerformanceModeMaxIo))
   265  	}
   266  	return
   267  }
   268  
   269  func hasEmptyFileSystems(fs *efs.DescribeFileSystemsOutput) bool {
   270  	if fs != nil && len(fs.FileSystems) > 0 {
   271  		return false
   272  	}
   273  	return true
   274  }