github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/builtin/providers/aws/resource_aws_lambda_function.go (about) 1 package aws 2 3 import ( 4 "crypto/sha256" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "time" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/lambda" 13 "github.com/mitchellh/go-homedir" 14 15 "errors" 16 17 "github.com/hashicorp/terraform/helper/resource" 18 "github.com/hashicorp/terraform/helper/schema" 19 ) 20 21 func resourceAwsLambdaFunction() *schema.Resource { 22 return &schema.Resource{ 23 Create: resourceAwsLambdaFunctionCreate, 24 Read: resourceAwsLambdaFunctionRead, 25 Update: resourceAwsLambdaFunctionUpdate, 26 Delete: resourceAwsLambdaFunctionDelete, 27 28 Schema: map[string]*schema.Schema{ 29 "filename": &schema.Schema{ 30 Type: schema.TypeString, 31 Optional: true, 32 ConflictsWith: []string{"s3_bucket", "s3_key", "s3_object_version"}, 33 }, 34 "s3_bucket": &schema.Schema{ 35 Type: schema.TypeString, 36 Optional: true, 37 ConflictsWith: []string{"filename"}, 38 }, 39 "s3_key": &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 ConflictsWith: []string{"filename"}, 43 }, 44 "s3_object_version": &schema.Schema{ 45 Type: schema.TypeString, 46 Optional: true, 47 ConflictsWith: []string{"filename"}, 48 }, 49 "description": &schema.Schema{ 50 Type: schema.TypeString, 51 Optional: true, 52 }, 53 "function_name": &schema.Schema{ 54 Type: schema.TypeString, 55 Required: true, 56 ForceNew: true, 57 }, 58 "handler": &schema.Schema{ 59 Type: schema.TypeString, 60 Required: true, 61 ForceNew: true, // TODO make this editable 62 }, 63 "memory_size": &schema.Schema{ 64 Type: schema.TypeInt, 65 Optional: true, 66 Default: 128, 67 ForceNew: true, // TODO make this editable 68 }, 69 "role": &schema.Schema{ 70 Type: schema.TypeString, 71 Required: true, 72 ForceNew: true, // TODO make this editable 73 }, 74 "runtime": &schema.Schema{ 75 Type: schema.TypeString, 76 Optional: true, 77 ForceNew: true, 78 Default: "nodejs", 79 }, 80 "timeout": &schema.Schema{ 81 Type: schema.TypeInt, 82 Optional: true, 83 Default: 3, 84 ForceNew: true, // TODO make this editable 85 }, 86 "arn": &schema.Schema{ 87 Type: schema.TypeString, 88 Computed: true, 89 }, 90 "last_modified": &schema.Schema{ 91 Type: schema.TypeString, 92 Computed: true, 93 }, 94 "source_code_hash": &schema.Schema{ 95 Type: schema.TypeString, 96 Computed: true, 97 ForceNew: true, 98 }, 99 }, 100 } 101 } 102 103 // resourceAwsLambdaFunction maps to: 104 // CreateFunction in the API / SDK 105 func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) error { 106 conn := meta.(*AWSClient).lambdaconn 107 108 functionName := d.Get("function_name").(string) 109 iamRole := d.Get("role").(string) 110 111 log.Printf("[DEBUG] Creating Lambda Function %s with role %s", functionName, iamRole) 112 113 var functionCode *lambda.FunctionCode 114 if v, ok := d.GetOk("filename"); ok { 115 filename, err := homedir.Expand(v.(string)) 116 if err != nil { 117 return err 118 } 119 zipfile, err := ioutil.ReadFile(filename) 120 if err != nil { 121 return err 122 } 123 d.Set("source_code_hash", sha256.Sum256(zipfile)) 124 functionCode = &lambda.FunctionCode{ 125 ZipFile: zipfile, 126 } 127 } else { 128 s3Bucket, bucketOk := d.GetOk("s3_bucket") 129 s3Key, keyOk := d.GetOk("s3_key") 130 s3ObjectVersion, versionOk := d.GetOk("s3_object_version") 131 if !bucketOk || !keyOk || !versionOk { 132 return errors.New("s3_bucket, s3_key and s3_object_version must all be set while using S3 code source") 133 } 134 functionCode = &lambda.FunctionCode{ 135 S3Bucket: aws.String(s3Bucket.(string)), 136 S3Key: aws.String(s3Key.(string)), 137 S3ObjectVersion: aws.String(s3ObjectVersion.(string)), 138 } 139 } 140 141 params := &lambda.CreateFunctionInput{ 142 Code: functionCode, 143 Description: aws.String(d.Get("description").(string)), 144 FunctionName: aws.String(functionName), 145 Handler: aws.String(d.Get("handler").(string)), 146 MemorySize: aws.Int64(int64(d.Get("memory_size").(int))), 147 Role: aws.String(iamRole), 148 Runtime: aws.String(d.Get("runtime").(string)), 149 Timeout: aws.Int64(int64(d.Get("timeout").(int))), 150 } 151 152 // IAM profiles can take ~10 seconds to propagate in AWS: 153 // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console 154 // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. 155 err := resource.Retry(1*time.Minute, func() error { 156 _, err := conn.CreateFunction(params) 157 if err != nil { 158 if awserr, ok := err.(awserr.Error); ok { 159 if awserr.Code() == "InvalidParameterValueException" { 160 // Retryable 161 return awserr 162 } 163 } 164 // Not retryable 165 return resource.RetryError{Err: err} 166 } 167 // No error 168 return nil 169 }) 170 if err != nil { 171 return fmt.Errorf("Error creating Lambda function: %s", err) 172 } 173 174 d.SetId(d.Get("function_name").(string)) 175 176 return resourceAwsLambdaFunctionRead(d, meta) 177 } 178 179 // resourceAwsLambdaFunctionRead maps to: 180 // GetFunction in the API / SDK 181 func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) error { 182 conn := meta.(*AWSClient).lambdaconn 183 184 log.Printf("[DEBUG] Fetching Lambda Function: %s", d.Id()) 185 186 params := &lambda.GetFunctionInput{ 187 FunctionName: aws.String(d.Get("function_name").(string)), 188 } 189 190 getFunctionOutput, err := conn.GetFunction(params) 191 if err != nil { 192 return err 193 } 194 195 // getFunctionOutput.Code.Location is a pre-signed URL pointing at the zip 196 // file that we uploaded when we created the resource. You can use it to 197 // download the code from AWS. The other part is 198 // getFunctionOutput.Configuration which holds metadata. 199 200 function := getFunctionOutput.Configuration 201 // TODO error checking / handling on the Set() calls. 202 d.Set("arn", function.FunctionArn) 203 d.Set("description", function.Description) 204 d.Set("handler", function.Handler) 205 d.Set("memory_size", function.MemorySize) 206 d.Set("last_modified", function.LastModified) 207 d.Set("role", function.Role) 208 d.Set("runtime", function.Runtime) 209 d.Set("timeout", function.Timeout) 210 211 return nil 212 } 213 214 // resourceAwsLambdaFunction maps to: 215 // DeleteFunction in the API / SDK 216 func resourceAwsLambdaFunctionDelete(d *schema.ResourceData, meta interface{}) error { 217 conn := meta.(*AWSClient).lambdaconn 218 219 log.Printf("[INFO] Deleting Lambda Function: %s", d.Id()) 220 221 params := &lambda.DeleteFunctionInput{ 222 FunctionName: aws.String(d.Get("function_name").(string)), 223 } 224 225 _, err := conn.DeleteFunction(params) 226 if err != nil { 227 return fmt.Errorf("Error deleting Lambda Function: %s", err) 228 } 229 230 d.SetId("") 231 232 return nil 233 } 234 235 // resourceAwsLambdaFunctionUpdate maps to: 236 // UpdateFunctionCode in the API / SDK 237 func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) error { 238 // conn := meta.(*AWSClient).lambdaconn 239 240 return nil 241 }