diff --git a/aws/data_source_aws_lambda_function.go b/aws/data_source_aws_lambda_function.go index 0f5e47750df..dbd49a854fc 100644 --- a/aws/data_source_aws_lambda_function.go +++ b/aws/data_source_aws_lambda_function.go @@ -1,6 +1,12 @@ package aws import ( + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/lambda" "github.com/hashicorp/terraform/helper/schema" ) @@ -16,7 +22,6 @@ func dataSourceAwsLambdaFunction() *schema.Resource { "qualifier": { Type: schema.TypeString, Optional: true, - Default: "$LATEST", }, "description": { Type: schema.TypeString, @@ -152,11 +157,114 @@ func dataSourceAwsLambdaFunction() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "tags": tagsSchemaComputed(), }, } } func dataSourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) error { - d.SetId(d.Get("function_name").(string)) - return resourceAwsLambdaFunctionRead(d, meta) + conn := meta.(*AWSClient).lambdaconn + functionName := d.Get("function_name").(string) + + input := &lambda.GetFunctionInput{ + FunctionName: aws.String(functionName), + } + + if v, ok := d.GetOk("qualifier"); ok { + input.Qualifier = aws.String(v.(string)) + } + + log.Printf("[DEBUG] Getting Lambda Function: %s", input) + output, err := conn.GetFunction(input) + + if err != nil { + return fmt.Errorf("error getting Lambda Function (%s): %s", functionName, err) + } + + if output == nil { + return fmt.Errorf("error getting Lambda Function (%s): empty response", functionName) + } + + function := output.Configuration + + functionARN := aws.StringValue(function.FunctionArn) + qualifierSuffix := fmt.Sprintf(":%s", d.Get("qualifier").(string)) + versionSuffix := fmt.Sprintf(":%s", aws.StringValue(function.Version)) + + qualifiedARN := functionARN + if !strings.HasSuffix(functionARN, qualifierSuffix) && !strings.HasSuffix(functionARN, versionSuffix) { + qualifiedARN = functionARN + versionSuffix + } + + unqualifiedARN := strings.TrimSuffix(functionARN, qualifierSuffix) + + d.Set("arn", unqualifiedARN) + + deadLetterConfig := []interface{}{} + if function.DeadLetterConfig != nil { + deadLetterConfig = []interface{}{ + map[string]interface{}{ + "target_arn": aws.StringValue(function.DeadLetterConfig.TargetArn), + }, + } + } + if err := d.Set("dead_letter_config", deadLetterConfig); err != nil { + return fmt.Errorf("error setting dead_letter_config: %s", err) + } + + d.Set("description", function.Description) + + if err := d.Set("environment", flattenLambdaEnvironment(function.Environment)); err != nil { + return fmt.Errorf("error setting environment: %s", err) + } + + d.Set("handler", function.Handler) + d.Set("invoke_arn", lambdaFunctionInvokeArn(aws.StringValue(function.FunctionArn), meta)) + d.Set("kms_key_arn", function.KMSKeyArn) + d.Set("last_modified", function.LastModified) + + if err := d.Set("layers", flattenLambdaLayers(function.Layers)); err != nil { + return fmt.Errorf("Error setting layers for Lambda Function (%s): %s", d.Id(), err) + } + + d.Set("memory_size", function.MemorySize) + d.Set("qualified_arn", qualifiedARN) + + reservedConcurrentExecutions := int64(-1) + if output.Concurrency != nil { + reservedConcurrentExecutions = aws.Int64Value(output.Concurrency.ReservedConcurrentExecutions) + } + d.Set("reserved_concurrent_executions", reservedConcurrentExecutions) + + d.Set("role", function.Role) + d.Set("runtime", function.Runtime) + d.Set("source_code_hash", function.CodeSha256) + d.Set("source_code_size", function.CodeSize) + + if err := d.Set("tags", tagsToMapGeneric(output.Tags)); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + + tracingConfig := []map[string]interface{}{ + { + "mode": lambda.TracingModePassThrough, + }, + } + if function.TracingConfig != nil { + tracingConfig[0]["mode"] = aws.StringValue(function.TracingConfig.Mode) + } + if err := d.Set("tracing_config", tracingConfig); err != nil { + return fmt.Errorf("error setting tracing_config: %s", tracingConfig) + } + + d.Set("timeout", function.Timeout) + d.Set("version", function.Version) + + if err := d.Set("vpc_config", flattenLambdaVpcConfigResponse(function.VpcConfig)); err != nil { + return fmt.Errorf("error setting vpc_config: %s", err) + } + + d.SetId(aws.StringValue(function.FunctionName)) + + return nil } diff --git a/aws/data_source_aws_lambda_function_test.go b/aws/data_source_aws_lambda_function_test.go index 76d9e6b7729..cad19dd3be3 100644 --- a/aws/data_source_aws_lambda_function_test.go +++ b/aws/data_source_aws_lambda_function_test.go @@ -9,38 +9,36 @@ import ( ) func TestAccDataSourceAWSLambdaFunction_basic(t *testing.T) { - rString := acctest.RandString(7) - roleName := fmt.Sprintf("tf-acctest-d-lambda-function-basic-role-%s", rString) - policyName := fmt.Sprintf("tf-acctest-d-lambda-function-basic-policy-%s", rString) - sgName := fmt.Sprintf("tf-acctest-d-lambda-function-basic-sg-%s", rString) - funcName := fmt.Sprintf("tf-acctest-d-lambda-function-basic-func-%s", rString) + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_lambda_function.test" + resourceName := "aws_lambda_function.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAWSLambdaFunctionConfigBasic(roleName, policyName, sgName, funcName), + Config: testAccDataSourceAWSLambdaFunctionConfigBasic(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "arn"), - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "role"), - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "source_code_hash"), - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "source_code_size"), - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "last_modified"), - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "qualified_arn"), - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "invoke_arn"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "function_name", funcName), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "description", funcName), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "qualifier", "$LATEST"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "handler", "exports.example"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "memory_size", "128"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "runtime", "nodejs8.10"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "timeout", "3"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "version", "$LATEST"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "reserved_concurrent_executions", "0"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "dead_letter_config.#", "0"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "tracing_config.#", "1"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "tracing_config.0.mode", "PassThrough"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "dead_letter_config.#", resourceName, "dead_letter_config.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"), + resource.TestCheckResourceAttrPair(dataSourceName, "function_name", resourceName, "function_name"), + resource.TestCheckResourceAttrPair(dataSourceName, "handler", resourceName, "handler"), + resource.TestCheckResourceAttrPair(dataSourceName, "invoke_arn", resourceName, "invoke_arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "last_modified", resourceName, "last_modified"), + resource.TestCheckResourceAttrPair(dataSourceName, "memory_size", resourceName, "memory_size"), + resource.TestCheckResourceAttrPair(dataSourceName, "qualified_arn", resourceName, "qualified_arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "reserved_concurrent_executions", resourceName, "reserved_concurrent_executions"), + resource.TestCheckResourceAttrPair(dataSourceName, "role", resourceName, "role"), + resource.TestCheckResourceAttrPair(dataSourceName, "runtime", resourceName, "runtime"), + resource.TestCheckResourceAttrPair(dataSourceName, "source_code_hash", resourceName, "source_code_hash"), + resource.TestCheckResourceAttrPair(dataSourceName, "source_code_size", resourceName, "source_code_size"), + resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"), + resource.TestCheckResourceAttrPair(dataSourceName, "timeout", resourceName, "timeout"), + resource.TestCheckResourceAttrPair(dataSourceName, "tracing_config.#", resourceName, "tracing_config.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "tracing_config.0.mode", resourceName, "tracing_config.0.mode"), + resource.TestCheckResourceAttrPair(dataSourceName, "version", resourceName, "version"), ), }, }, @@ -48,23 +46,21 @@ func TestAccDataSourceAWSLambdaFunction_basic(t *testing.T) { } func TestAccDataSourceAWSLambdaFunction_version(t *testing.T) { - rString := acctest.RandString(7) - roleName := fmt.Sprintf("tf-acctest-d-lambda-function-version-role-%s", rString) - policyName := fmt.Sprintf("tf-acctest-d-lambda-function-version-policy-%s", rString) - sgName := fmt.Sprintf("tf-acctest-d-lambda-function-version-sg-%s", rString) - funcName := fmt.Sprintf("tf-acctest-d-lambda-function-version-func-%s", rString) + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_lambda_function.test" + resourceName := "aws_lambda_function.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAWSLambdaFunctionConfigVersion(roleName, policyName, sgName, funcName), + Config: testAccDataSourceAWSLambdaFunctionConfigVersion(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "arn"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "function_name", funcName), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "qualifier", "1"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "version", "1"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "qualified_arn", resourceName, "qualified_arn"), + resource.TestCheckResourceAttr(dataSourceName, "qualifier", "1"), + resource.TestCheckResourceAttr(dataSourceName, "version", "1"), ), }, }, @@ -72,23 +68,22 @@ func TestAccDataSourceAWSLambdaFunction_version(t *testing.T) { } func TestAccDataSourceAWSLambdaFunction_alias(t *testing.T) { - rString := acctest.RandString(7) - roleName := fmt.Sprintf("tf-acctest-d-lambda-function-alias-role-%s", rString) - policyName := fmt.Sprintf("tf-acctest-d-lambda-function-alias-policy-%s", rString) - sgName := fmt.Sprintf("tf-acctest-d-lambda-function-alias-sg-%s", rString) - funcName := fmt.Sprintf("tf-acctest-d-lambda-function-alias-func-%s", rString) + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_lambda_function.test" + lambdaAliasResourceName := "aws_lambda_alias.test" + resourceName := "aws_lambda_function.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAWSLambdaFunctionConfigAlias(roleName, policyName, sgName, funcName), + Config: testAccDataSourceAWSLambdaFunctionConfigAlias(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "arn"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "function_name", funcName), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "qualifier", "alias-name"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "version", "1"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "qualified_arn", lambdaAliasResourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "qualifier", lambdaAliasResourceName, "name"), + resource.TestCheckResourceAttrPair(dataSourceName, "version", lambdaAliasResourceName, "function_version"), ), }, }, @@ -96,22 +91,19 @@ func TestAccDataSourceAWSLambdaFunction_alias(t *testing.T) { } func TestAccDataSourceAWSLambdaFunction_layers(t *testing.T) { - rString := acctest.RandString(7) - roleName := fmt.Sprintf("tf-acctest-d-lambda-function-layer-role-%s", rString) - policyName := fmt.Sprintf("tf-acctest-d-lambda-function-layer-policy-%s", rString) - sgName := fmt.Sprintf("tf-acctest-d-lambda-function-layer-sg-%s", rString) - funcName := fmt.Sprintf("tf-acctest-d-lambda-function-layer-func-%s", rString) - layerName := fmt.Sprintf("tf-acctest-d-lambda-function-layer-layer-%s", rString) + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_lambda_function.test" + resourceName := "aws_lambda_function.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAWSLambdaFunctionConfigLayers(roleName, policyName, sgName, funcName, layerName), + Config: testAccDataSourceAWSLambdaFunctionConfigLayers(rName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "arn"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "layers.#", "1"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "layers.#", resourceName, "layers.#"), ), }, }, @@ -119,23 +111,21 @@ func TestAccDataSourceAWSLambdaFunction_layers(t *testing.T) { } func TestAccDataSourceAWSLambdaFunction_vpc(t *testing.T) { - rString := acctest.RandString(7) - roleName := fmt.Sprintf("tf-acctest-d-lambda-function-vpc-role-%s", rString) - policyName := fmt.Sprintf("tf-acctest-d-lambda-function-vpc-policy-%s", rString) - sgName := fmt.Sprintf("tf-acctest-d-lambda-function-vpc-sg-%s", rString) - funcName := fmt.Sprintf("tf-acctest-d-lambda-function-vpc-func-%s", rString) + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_lambda_function.test" + resourceName := "aws_lambda_function.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAWSLambdaFunctionConfigVPC(roleName, policyName, sgName, funcName), + Config: testAccDataSourceAWSLambdaFunctionConfigVPC(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "arn"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "vpc_config.#", "1"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "vpc_config.0.security_group_ids.#", "1"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "vpc_config.0.subnet_ids.#", "1"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "vpc_config.#", resourceName, "vpc_config.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "vpc_config.0.security_group_ids.#", resourceName, "vpc_config.0.security_group_ids.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "vpc_config.0.subnet_ids.#", resourceName, "vpc_config.0.subnet_ids.#"), ), }, }, @@ -143,34 +133,32 @@ func TestAccDataSourceAWSLambdaFunction_vpc(t *testing.T) { } func TestAccDataSourceAWSLambdaFunction_environment(t *testing.T) { - rString := acctest.RandString(7) - roleName := fmt.Sprintf("tf-acctest-d-lambda-function-environment-role-%s", rString) - policyName := fmt.Sprintf("tf-acctest-d-lambda-function-environment-policy-%s", rString) - sgName := fmt.Sprintf("tf-acctest-d-lambda-function-environment-sg-%s", rString) - funcName := fmt.Sprintf("tf-acctest-d-lambda-function-environment-func-%s", rString) + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_lambda_function.test" + resourceName := "aws_lambda_function.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAWSLambdaFunctionConfigEnvironment(roleName, policyName, sgName, funcName), + Config: testAccDataSourceAWSLambdaFunctionConfigEnvironment(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.aws_lambda_function.acctest", "arn"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "environment.#", "1"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "environment.0.variables.%", "2"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "environment.0.variables.key1", "value1"), - resource.TestCheckResourceAttr("data.aws_lambda_function.acctest", "environment.0.variables.key2", "value2"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "environment.#", resourceName, "environment.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "environment.0.variables.%", resourceName, "environment.0.variables.%"), + resource.TestCheckResourceAttrPair(dataSourceName, "environment.0.variables.key1", resourceName, "environment.0.variables.key1"), + resource.TestCheckResourceAttrPair(dataSourceName, "environment.0.variables.key2", resourceName, "environment.0.variables.key2"), ), }, }, }) } -func testAccDataSourceAWSLambdaFunctionConfigBase(roleName, policyName, sgName string) string { +func testAccDataSourceAWSLambdaFunctionConfigBase(rName string) string { return fmt.Sprintf(` resource "aws_iam_role" "lambda" { - name = "%s" + name = %[1]q assume_role_policy = <