From c5f788ec5807b1060cb94ea6e2c223cd4e6d198b Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Tue, 24 May 2016 23:39:35 +0200 Subject: [PATCH 1/4] Attempt to fix #6794 - update only non empty fields on aws_lambda_function s3 --- .../aws/resource_aws_lambda_function.go | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index 4d74ca3f0..33a7e387d 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -306,20 +306,32 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e } codeUpdate := false - if d.HasChange("filename") || d.HasChange("source_code_hash") { - name := d.Get("filename").(string) - file, err := loadFileContent(name) - if err != nil { - return fmt.Errorf("Unable to load %q: %s", name, err) + if v, ok := d.GetOk("filename"); ok { + if d.HasChange("source_code_hash") { + file, err := loadFileContent(v.(string)) + if err != nil { + return fmt.Errorf("Unable to load %q: %s", v.(string), err) + } + codeReq.ZipFile = file + codeUpdate = true + } + } else { + s3Bucket, bucketOk := d.GetOk("s3_bucket") + s3Key, keyOk := d.GetOk("s3_key") + s3ObjectVersion, versionOk := d.GetOk("s3_object_version") + + if bucketOk && d.HasChange("s3_bucket") { + codeReq.S3Bucket = aws.String(s3Bucket.(string)) + codeUpdate = true + } + if keyOk && d.HasChange("s3_key") { + codeReq.S3Key = aws.String(s3Key.(string)) + codeUpdate = true + } + if versionOk && d.HasChange("s3_object_version") { + codeReq.S3ObjectVersion = aws.String(s3ObjectVersion.(string)) + codeUpdate = true } - codeReq.ZipFile = file - codeUpdate = true - } - if d.HasChange("s3_bucket") || d.HasChange("s3_key") || d.HasChange("s3_object_version") { - codeReq.S3Bucket = aws.String(d.Get("s3_bucket").(string)) - codeReq.S3Key = aws.String(d.Get("s3_key").(string)) - codeReq.S3ObjectVersion = aws.String(d.Get("s3_object_version").(string)) - codeUpdate = true } if codeUpdate { From c9bd7d680f0763ac7a85b22db95d3af1f3af7dfe Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Tue, 24 May 2016 23:46:18 +0200 Subject: [PATCH 2/4] Add a test to check the unversioned lambda function update - copy and adapt genAWSLambdaFunctionConfig_s3 --- .../aws/resource_aws_lambda_function_test.go | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/builtin/providers/aws/resource_aws_lambda_function_test.go b/builtin/providers/aws/resource_aws_lambda_function_test.go index d7ad80143..2ae453c20 100644 --- a/builtin/providers/aws/resource_aws_lambda_function_test.go +++ b/builtin/providers/aws/resource_aws_lambda_function_test.go @@ -230,6 +230,60 @@ func TestAccAWSLambdaFunction_s3Update(t *testing.T) { }) } +func TestAccAWSLambdaFunction_s3Update_unversioned(t *testing.T) { + var conf lambda.GetFunctionOutput + + path, zipFile, err := createTempFile("lambda_s3Update") + if err != nil { + t.Fatal(err) + } + defer os.Remove(path) + + bucketName := fmt.Sprintf("tf-acc-lambda-s3-deployments-%d", randomInteger) + key := "lambda-func.zip" + key2 := "lambda-func-modified.zip" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLambdaFunctionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + PreConfig: func() { + // Upload 1st version + testAccCreateZipFromFiles(map[string]string{"test-fixtures/lambda_func.js": "lambda.js"}, zipFile) + }, + Config: genAWSLambdaFunctionConfig_s3_unversioned(bucketName, key, path), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_s3", "tf_acc_lambda_name_s3_unversioned", &conf), + testAccCheckAwsLambdaFunctionName(&conf, "tf_acc_lambda_name_s3_unversioned"), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, "tf_acc_lambda_name_s3_unversioned"), + testAccCheckAwsLambdaSourceCodeHash(&conf, "un6qF9S9hKvXbWwJ6m2EYaVCWjcr0PCZWiTV3h4zB0I="), + ), + }, + resource.TestStep{ + ExpectNonEmptyPlan: true, + PreConfig: func() { + // Upload 2nd version + testAccCreateZipFromFiles(map[string]string{"test-fixtures/lambda_func_modified.js": "lambda.js"}, zipFile) + }, + Config: genAWSLambdaFunctionConfig_s3_unversioned(bucketName, key2, path), + }, + // Extra step because of missing ComputedWhen + // See https://github.com/hashicorp/terraform/pull/4846 & https://github.com/hashicorp/terraform/pull/5330 + resource.TestStep{ + Config: genAWSLambdaFunctionConfig_s3_unversioned(bucketName, key2, path), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_s3", "tf_acc_lambda_name_s3_unversioned", &conf), + testAccCheckAwsLambdaFunctionName(&conf, "tf_acc_lambda_name_s3_unversioned"), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, "tf_acc_lambda_name_s3_unversioned"), + testAccCheckAwsLambdaSourceCodeHash(&conf, "Y5Jf4Si63UDy1wKNfPs+U56ZL0NxsieKPt9EwRl4GQM="), + ), + }, + }, + }) +} + func testAccCheckLambdaFunctionDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).lambdaconn @@ -632,3 +686,47 @@ func genAWSLambdaFunctionConfig_s3(bucket, key, path string) string { return fmt.Sprintf(testAccAWSLambdaFunctionConfig_s3_tpl, bucket, key, path, path) } + +const testAccAWSLambdaFunctionConfig_s3_unversioned_tpl = ` +resource "aws_s3_bucket" "artifacts" { + bucket = "%s" + acl = "private" + force_destroy = true +} +resource "aws_s3_bucket_object" "o" { + bucket = "${aws_s3_bucket.artifacts.bucket}" + key = "%s" + source = "%s" + etag = "${md5(file("%s"))}" +} +resource "aws_iam_role" "iam_for_lambda" { + name = "iam_for_lambda" + assume_role_policy = < Date: Wed, 25 May 2016 10:02:20 +0200 Subject: [PATCH 3/4] S3Bucket and S3Key are always required --- .../aws/resource_aws_lambda_function.go | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index 33a7e387d..9a680e74d 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -320,17 +320,19 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e s3Key, keyOk := d.GetOk("s3_key") s3ObjectVersion, versionOk := d.GetOk("s3_object_version") - if bucketOk && d.HasChange("s3_bucket") { - codeReq.S3Bucket = aws.String(s3Bucket.(string)) - codeUpdate = true - } - if keyOk && d.HasChange("s3_key") { - codeReq.S3Key = aws.String(s3Key.(string)) - codeUpdate = true - } - if versionOk && d.HasChange("s3_object_version") { - codeReq.S3ObjectVersion = aws.String(s3ObjectVersion.(string)) - codeUpdate = true + if bucketOk && keyOk { + if d.HasChange("s3_bucket") || d.HasChange("s3_key") { + codeReq.S3Bucket = aws.String(s3Bucket.(string)) + codeReq.S3Key = aws.String(s3Key.(string)) + codeUpdate = true + } + + if versionOk && d.HasChange("s3_object_version") { + codeReq.S3Bucket = aws.String(s3Bucket.(string)) + codeReq.S3Key = aws.String(s3Key.(string)) + codeReq.S3ObjectVersion = aws.String(s3ObjectVersion.(string)) + codeUpdate = true + } } } From 3a97971e41db1a3cdb1501d6e4657bf38d206850 Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Fri, 27 May 2016 07:38:12 +0200 Subject: [PATCH 4/4] Refactor for code simplicity. --- .../aws/resource_aws_lambda_function.go | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index 9a680e74d..84e667ecc 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -301,43 +301,31 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e d.Partial(true) - codeReq := &lambda.UpdateFunctionCodeInput{ - FunctionName: aws.String(d.Id()), - } + if d.HasChange("filename") || d.HasChange("source_code_hash") || d.HasChange("s3_bucket") || d.HasChange("s3_key") || d.HasChange("s3_object_version") { + codeReq := &lambda.UpdateFunctionCodeInput{ + FunctionName: aws.String(d.Id()), + } - codeUpdate := false - if v, ok := d.GetOk("filename"); ok { - if d.HasChange("source_code_hash") { + if v, ok := d.GetOk("filename"); ok { file, err := loadFileContent(v.(string)) if err != nil { return fmt.Errorf("Unable to load %q: %s", v.(string), err) } codeReq.ZipFile = file - codeUpdate = true - } - } else { - s3Bucket, bucketOk := d.GetOk("s3_bucket") - s3Key, keyOk := d.GetOk("s3_key") - s3ObjectVersion, versionOk := d.GetOk("s3_object_version") + } else { + s3Bucket, _ := d.GetOk("s3_bucket") + s3Key, _ := d.GetOk("s3_key") + s3ObjectVersion, versionOk := d.GetOk("s3_object_version") - if bucketOk && keyOk { - if d.HasChange("s3_bucket") || d.HasChange("s3_key") { - codeReq.S3Bucket = aws.String(s3Bucket.(string)) - codeReq.S3Key = aws.String(s3Key.(string)) - codeUpdate = true - } - - if versionOk && d.HasChange("s3_object_version") { - codeReq.S3Bucket = aws.String(s3Bucket.(string)) - codeReq.S3Key = aws.String(s3Key.(string)) + codeReq.S3Bucket = aws.String(s3Bucket.(string)) + codeReq.S3Key = aws.String(s3Key.(string)) + if versionOk { codeReq.S3ObjectVersion = aws.String(s3ObjectVersion.(string)) - codeUpdate = true } } - } - if codeUpdate { log.Printf("[DEBUG] Send Update Lambda Function Code request: %#v", codeReq) + _, err := conn.UpdateFunctionCode(codeReq) if err != nil { return fmt.Errorf("Error modifying Lambda Function Code %s: %s", d.Id(), err)