github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 }