Skip to content

Commit

Permalink
Add raw result to aws_lambda_invocation data source
Browse files Browse the repository at this point in the history
  • Loading branch information
spirius committed May 14, 2018
1 parent c79c7a0 commit 7c73567
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 18 deletions.
14 changes: 12 additions & 2 deletions aws/data_source_aws_lambda_invocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/md5"
"encoding/json"
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/lambda"
Expand Down Expand Up @@ -36,6 +37,11 @@ func dataSourceAwsLambdaInvocation() *schema.Resource {
},

"result": {
Type: schema.TypeString,
Computed: true,
},

"result_map": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Expand Down Expand Up @@ -68,14 +74,18 @@ func dataSourceAwsLambdaInvocationRead(d *schema.ResourceData, meta interface{})
return fmt.Errorf("Lambda function (%s) returned error: (%s)", functionName, string(res.Payload))
}

if err = d.Set("result", string(res.Payload)); err != nil {
return err
}

var result map[string]interface{}

if err = json.Unmarshal(res.Payload, &result); err != nil {
return err
}

if err = d.Set("result", result); err != nil {
return fmt.Errorf("Lambda function (%s) returned invalid JSON: %s", functionName, err)
if err = d.Set("result_map", result); err != nil {
log.Printf("[WARN] Cannot use the result invocation as a string map: %s", err)
}

d.SetId(fmt.Sprintf("%s_%s_%x", functionName, qualifier, md5.Sum(input)))
Expand Down
93 changes: 85 additions & 8 deletions aws/data_source_aws_lambda_invocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,34 @@ import (
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func testAccCheckLambdaInvocationResult(name, expectedResult string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

result, ok := rs.Primary.Attributes["result"]

if !ok {
return fmt.Errorf("No result is set")
}

if !suppressEquivalentJsonDiffs("", result, expectedResult, nil) {
return fmt.Errorf("%s: Attribute 'result' expected %s, got %s", name, expectedResult, result)
}

return nil
}
}

func TestAccDataSourceAwsLambdaInvocation_basic(t *testing.T) {
testData := "value3"

Expand All @@ -17,10 +43,11 @@ func TestAccDataSourceAwsLambdaInvocation_basic(t *testing.T) {
{
Config: testAccDataSourceAwsLambdaInvocation_basic_config("tf-test-lambda-role", "tf-test-lambda-invocation", testData),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.%", "3"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.key1", "value1"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.key2", "value2"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.key3", testData),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.%", "3"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.key1", "value1"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.key2", "value2"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.key3", testData),
testAccCheckLambdaInvocationResult("data.aws_lambda_invocation.invocation_test", `{"key1":"value1","key2":"value2","key3":"`+testData+`"}`),
),
},
},
Expand All @@ -37,10 +64,28 @@ func TestAccDataSourceAwsLambdaInvocation_qualifier(t *testing.T) {
{
Config: testAccDataSourceAwsLambdaInvocation_qualifier_config("tf-test-lambda-role-qualifier", "tf-test-lambda-invocation-qualifier", testData),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.%", "3"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.key1", "value1"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.key2", "value2"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result.key3", testData),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.%", "3"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.key1", "value1"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.key2", "value2"),
resource.TestCheckResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map.key3", testData),
),
},
},
})
}

func TestAccDataSourceAwsLambdaInvocation_complex(t *testing.T) {
testData := "value3"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsLambdaInvocation_complex_config("tf-test-lambda-role-complex", "tf-test-lambda-invocation-complex", testData),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckNoResourceAttr("data.aws_lambda_invocation.invocation_test", "result_map"),
testAccCheckLambdaInvocationResult("data.aws_lambda_invocation.invocation_test", `{"key1":{"subkey1":"subvalue1"},"key2":{"subkey2":"subvalue2","subkey3":{"a": "b"}},"key3":"`+testData+`"}`),
),
},
},
Expand Down Expand Up @@ -136,3 +181,35 @@ JSON
}
`, lambdaName, testData)
}

func testAccDataSourceAwsLambdaInvocation_complex_config(roleName, lambdaName, testData string) string {
return fmt.Sprintf(testAccDataSourceAwsLambdaInvocation_base_config(roleName)+`
resource "aws_lambda_function" "lambda" {
depends_on = ["aws_iam_role_policy_attachment.lambda_role_policy"]
filename = "test-fixtures/lambda_invocation.zip"
function_name = "%s"
role = "${aws_iam_role.lambda_role.arn}"
handler = "lambda_invocation.handler"
runtime = "nodejs8.10"
publish = true
environment {
variables = {
TEST_DATA = "%s"
}
}
}
data "aws_lambda_invocation" "invocation_test" {
function_name = "${aws_lambda_function.lambda.function_name}"
input = <<JSON
{
"key1": {"subkey1": "subvalue1"},
"key2": {"subkey2": "subvalue2", "subkey3": {"a": "b"}}
}
JSON
}
`, lambdaName, testData)
}
17 changes: 9 additions & 8 deletions website/docs/d/lambda_invocation.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ description: |-
# Data Source: aws_lambda_invocation

Use this data source to invoke custom lambda functions as data source.

~> **NOTE**: The `input` argument is JSON encoded and passed as payload to the
lambda function. All values in `input` map are converted to strings.
The lambda function is invoked with
[RequestResponse](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax)
invocation type. Response of lambda must be map of primitive types (string, bool or float).
The lambda function is invoked with [RequestResponse](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax)
invocation type.

## Example Usage

Expand All @@ -31,8 +27,12 @@ JSON
}
output "result_entry" {
value = "${data.aws_lambda_invocation.result_map["key1"]}"
}
output "result" {
value = "${data.aws_lambda_invocation.result["key1"]}"
value = "${data.aws_lambda_invocation.result}"
}
```

Expand All @@ -45,4 +45,5 @@ output "result" {

## Attributes Reference

* `result` - A map of string values returned from the lambda invocation.
* `result` - A result of the lambda function invocation.
* `result_map` - This field is set only if result is a map of primitive types.

0 comments on commit 7c73567

Please sign in to comment.