github.com/bendemaree/terraform@v0.5.4-0.20150613200311-f50d97d6eee6/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 "github.com/hashicorp/terraform/helper/schema" 17 ) 18 19 func resourceAwsLambdaFunction() *schema.Resource { 20 return &schema.Resource{ 21 Create: resourceAwsLambdaFunctionCreate, 22 Read: resourceAwsLambdaFunctionRead, 23 Update: resourceAwsLambdaFunctionUpdate, 24 Delete: resourceAwsLambdaFunctionDelete, 25 26 Schema: map[string]*schema.Schema{ 27 "filename": &schema.Schema{ 28 Type: schema.TypeString, 29 Required: true, 30 }, 31 "description": &schema.Schema{ 32 Type: schema.TypeString, 33 Optional: true, 34 ForceNew: true, // TODO make this editable 35 }, 36 "function_name": &schema.Schema{ 37 Type: schema.TypeString, 38 Required: true, 39 ForceNew: true, 40 }, 41 "handler": &schema.Schema{ 42 Type: schema.TypeString, 43 Required: true, 44 ForceNew: true, // TODO make this editable 45 }, 46 "memory_size": &schema.Schema{ 47 Type: schema.TypeInt, 48 Optional: true, 49 Default: 128, 50 ForceNew: true, // TODO make this editable 51 }, 52 "role": &schema.Schema{ 53 Type: schema.TypeString, 54 Required: true, 55 ForceNew: true, // TODO make this editable 56 }, 57 "runtime": &schema.Schema{ 58 Type: schema.TypeString, 59 Optional: true, 60 ForceNew: true, 61 Default: "nodejs", 62 }, 63 "timeout": &schema.Schema{ 64 Type: schema.TypeInt, 65 Optional: true, 66 Default: 3, 67 ForceNew: true, // TODO make this editable 68 }, 69 "arn": &schema.Schema{ 70 Type: schema.TypeString, 71 Computed: true, 72 }, 73 "last_modified": &schema.Schema{ 74 Type: schema.TypeString, 75 Computed: true, 76 }, 77 "source_code_hash": &schema.Schema{ 78 Type: schema.TypeString, 79 Computed: true, 80 ForceNew: true, 81 }, 82 }, 83 } 84 } 85 86 // resourceAwsLambdaFunction maps to: 87 // CreateFunction in the API / SDK 88 func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) error { 89 conn := meta.(*AWSClient).lambdaconn 90 91 functionName := d.Get("function_name").(string) 92 iamRole := d.Get("role").(string) 93 94 log.Printf("[DEBUG] Creating Lambda Function %s with role %s", functionName, iamRole) 95 96 filename, err := homedir.Expand(d.Get("filename").(string)) 97 if err != nil { 98 return err 99 } 100 zipfile, err := ioutil.ReadFile(filename) 101 if err != nil { 102 return err 103 } 104 d.Set("source_code_hash", sha256.Sum256(zipfile)) 105 106 log.Printf("[DEBUG] ") 107 108 params := &lambda.CreateFunctionInput{ 109 Code: &lambda.FunctionCode{ 110 ZipFile: zipfile, 111 }, 112 Description: aws.String(d.Get("description").(string)), 113 FunctionName: aws.String(functionName), 114 Handler: aws.String(d.Get("handler").(string)), 115 MemorySize: aws.Long(int64(d.Get("memory_size").(int))), 116 Role: aws.String(iamRole), 117 Runtime: aws.String(d.Get("runtime").(string)), 118 Timeout: aws.Long(int64(d.Get("timeout").(int))), 119 } 120 121 for i := 0; i < 5; i++ { 122 _, err = conn.CreateFunction(params) 123 if awsErr, ok := err.(awserr.Error); ok { 124 125 // IAM profiles can take ~10 seconds to propagate in AWS: 126 // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console 127 // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. 128 if awsErr.Code() == "InvalidParameterValueException" && strings.Contains(awsErr.Message(), "The role defined for the task cannot be assumed by Lambda.") { 129 log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") 130 time.Sleep(2 * time.Second) 131 continue 132 } 133 } 134 break 135 } 136 if err != nil { 137 return fmt.Errorf("Error creating Lambda function: %s", err) 138 } 139 140 d.SetId(d.Get("function_name").(string)) 141 142 return resourceAwsLambdaFunctionRead(d, meta) 143 } 144 145 // resourceAwsLambdaFunctionRead maps to: 146 // GetFunction in the API / SDK 147 func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) error { 148 conn := meta.(*AWSClient).lambdaconn 149 150 log.Printf("[DEBUG] Fetching Lambda Function: %s", d.Id()) 151 152 params := &lambda.GetFunctionInput{ 153 FunctionName: aws.String(d.Get("function_name").(string)), 154 } 155 156 getFunctionOutput, err := conn.GetFunction(params) 157 if err != nil { 158 return err 159 } 160 161 // getFunctionOutput.Code.Location is a pre-signed URL pointing at the zip 162 // file that we uploaded when we created the resource. You can use it to 163 // download the code from AWS. The other part is 164 // getFunctionOutput.Configuration which holds metadata. 165 166 function := getFunctionOutput.Configuration 167 // TODO error checking / handling on the Set() calls. 168 d.Set("arn", function.FunctionARN) 169 d.Set("description", function.Description) 170 d.Set("handler", function.Handler) 171 d.Set("memory_size", function.MemorySize) 172 d.Set("last_modified", function.LastModified) 173 d.Set("role", function.Role) 174 d.Set("runtime", function.Runtime) 175 d.Set("timeout", function.Timeout) 176 177 return nil 178 } 179 180 // resourceAwsLambdaFunction maps to: 181 // DeleteFunction in the API / SDK 182 func resourceAwsLambdaFunctionDelete(d *schema.ResourceData, meta interface{}) error { 183 conn := meta.(*AWSClient).lambdaconn 184 185 log.Printf("[INFO] Deleting Lambda Function: %s", d.Id()) 186 187 params := &lambda.DeleteFunctionInput{ 188 FunctionName: aws.String(d.Get("function_name").(string)), 189 } 190 191 _, err := conn.DeleteFunction(params) 192 if err != nil { 193 return fmt.Errorf("Error deleting Lambda Function: %s", err) 194 } 195 196 d.SetId("") 197 198 return nil 199 } 200 201 // resourceAwsLambdaFunctionUpdate maps to: 202 // UpdateFunctionCode in the API / SDK 203 func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) error { 204 // conn := meta.(*AWSClient).lambdaconn 205 206 return nil 207 }