github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/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 "strings" 9 "time" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/aws/awserr" 13 "github.com/aws/aws-sdk-go/service/lambda" 14 "github.com/mitchellh/go-homedir" 15 16 "errors" 17 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 var err error 153 for i := 0; i < 5; i++ { 154 _, err = conn.CreateFunction(params) 155 if awsErr, ok := err.(awserr.Error); ok { 156 157 // IAM profiles can take ~10 seconds to propagate in AWS: 158 // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console 159 // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. 160 if awsErr.Code() == "InvalidParameterValueException" && strings.Contains(awsErr.Message(), "The role defined for the task cannot be assumed by Lambda.") { 161 log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") 162 time.Sleep(2 * time.Second) 163 continue 164 } 165 } 166 break 167 } 168 if err != nil { 169 return fmt.Errorf("Error creating Lambda function: %s", err) 170 } 171 172 d.SetId(d.Get("function_name").(string)) 173 174 return resourceAwsLambdaFunctionRead(d, meta) 175 } 176 177 // resourceAwsLambdaFunctionRead maps to: 178 // GetFunction in the API / SDK 179 func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) error { 180 conn := meta.(*AWSClient).lambdaconn 181 182 log.Printf("[DEBUG] Fetching Lambda Function: %s", d.Id()) 183 184 params := &lambda.GetFunctionInput{ 185 FunctionName: aws.String(d.Get("function_name").(string)), 186 } 187 188 getFunctionOutput, err := conn.GetFunction(params) 189 if err != nil { 190 return err 191 } 192 193 // getFunctionOutput.Code.Location is a pre-signed URL pointing at the zip 194 // file that we uploaded when we created the resource. You can use it to 195 // download the code from AWS. The other part is 196 // getFunctionOutput.Configuration which holds metadata. 197 198 function := getFunctionOutput.Configuration 199 // TODO error checking / handling on the Set() calls. 200 d.Set("arn", function.FunctionArn) 201 d.Set("description", function.Description) 202 d.Set("handler", function.Handler) 203 d.Set("memory_size", function.MemorySize) 204 d.Set("last_modified", function.LastModified) 205 d.Set("role", function.Role) 206 d.Set("runtime", function.Runtime) 207 d.Set("timeout", function.Timeout) 208 209 return nil 210 } 211 212 // resourceAwsLambdaFunction maps to: 213 // DeleteFunction in the API / SDK 214 func resourceAwsLambdaFunctionDelete(d *schema.ResourceData, meta interface{}) error { 215 conn := meta.(*AWSClient).lambdaconn 216 217 log.Printf("[INFO] Deleting Lambda Function: %s", d.Id()) 218 219 params := &lambda.DeleteFunctionInput{ 220 FunctionName: aws.String(d.Get("function_name").(string)), 221 } 222 223 _, err := conn.DeleteFunction(params) 224 if err != nil { 225 return fmt.Errorf("Error deleting Lambda Function: %s", err) 226 } 227 228 d.SetId("") 229 230 return nil 231 } 232 233 // resourceAwsLambdaFunctionUpdate maps to: 234 // UpdateFunctionCode in the API / SDK 235 func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) error { 236 // conn := meta.(*AWSClient).lambdaconn 237 238 return nil 239 }