Skip to content

Commit f80a24c

Browse files
authored
Merge pull request #41240 from Giaco9NN/f-aws-lambda-invocation-import-support
aws_lambda_invocation: Add import support
2 parents 0632825 + c0e0d95 commit f80a24c

File tree

5 files changed

+170
-1
lines changed

5 files changed

+170
-1
lines changed

.changelog/41240.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/aws_lambda_invocation: Add import support
3+
```

internal/service/lambda/exports_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
LayerVersionParseResourceID = layerVersionParseResourceID
3636
LayerVersionPermissionParseResourceID = layerVersionPermissionParseResourceID
3737
SignerServiceIsAvailable = signerServiceIsAvailable
38+
InvocationParseResourceID = invocationParseResourceID
3839

3940
ValidFunctionName = validFunctionName
4041
ValidPermissionAction = validPermissionAction

internal/service/lambda/invocation.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"log"
1313
"strings"
1414

15+
"github.com/YakDriver/regexache"
1516
"github.com/aws/aws-sdk-go-v2/aws"
1617
"github.com/aws/aws-sdk-go-v2/service/lambda"
1718
awstypes "github.com/aws/aws-sdk-go-v2/service/lambda/types"
@@ -22,9 +23,14 @@ import (
2223
"github.com/hashicorp/terraform-provider-aws/internal/conns"
2324
"github.com/hashicorp/terraform-provider-aws/internal/enum"
2425
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
26+
"github.com/hashicorp/terraform-provider-aws/internal/flex"
2527
"github.com/hashicorp/terraform-provider-aws/names"
2628
)
2729

30+
const (
31+
invocationResourceIDPartCount = 3
32+
)
33+
2834
// @SDKResource("aws_lambda_invocation", name="Invocation")
2935
func resourceInvocation() *schema.Resource {
3036
return &schema.Resource{
@@ -41,6 +47,19 @@ func resourceInvocation() *schema.Resource {
4147
Version: 0,
4248
},
4349
},
50+
Importer: &schema.ResourceImporter{
51+
StateContext: func(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) {
52+
functionName, qualifier, _, err := invocationParseResourceID(d.Id())
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
d.Set("function_name", functionName)
58+
d.Set("qualifier", qualifier)
59+
60+
return []*schema.ResourceData{d}, nil
61+
},
62+
},
4463

4564
Schema: map[string]*schema.Schema{
4665
"function_name": {
@@ -205,7 +224,13 @@ func invoke(ctx context.Context, conn *lambda.Client, d *schema.ResourceData, ac
205224
return sdkdiag.AppendErrorf(diags, "invoking Lambda Function (%s): %s", functionName, string(output.Payload))
206225
}
207226

208-
d.SetId(fmt.Sprintf("%s_%s_%x", functionName, qualifier, md5.Sum(payload)))
227+
resultHash := fmt.Sprintf("%x", md5.Sum(payload))
228+
id, err := flex.FlattenResourceId([]string{functionName, qualifier, resultHash}, invocationResourceIDPartCount, false)
229+
if err != nil {
230+
return sdkdiag.AppendFromErr(diags, err)
231+
}
232+
233+
d.SetId(id)
209234
d.Set("result", string(output.Payload))
210235

211236
return diags
@@ -248,3 +273,26 @@ func customizeDiffInputChangeWithCRUDScope(_ context.Context, diff *schema.Resou
248273
}
249274
return nil
250275
}
276+
277+
func invocationParseResourceID(id string) (string, string, string, error) {
278+
parts, err := flex.ExpandResourceId(id, invocationResourceIDPartCount, false)
279+
if err != nil {
280+
return "", "", "", err
281+
}
282+
283+
functionName := parts[0]
284+
qualifier := parts[1]
285+
resultHash := parts[2]
286+
287+
// Validate qualifier format
288+
if qualifier != "$LATEST" && !regexache.MustCompile(`^[0-9]+$`).MatchString(qualifier) {
289+
return "", "", "", fmt.Errorf("invalid qualifier format: %s, expected $LATEST or numeric version", qualifier)
290+
}
291+
292+
// Validate hash format (should be MD5 - 32 hex chars)
293+
if !regexache.MustCompile(`^[a-f0-9]{32}$`).MatchString(resultHash) {
294+
return "", "", "", fmt.Errorf("invalid result hash format: %s, expected 32-character MD5 hash", resultHash)
295+
}
296+
297+
return functionName, qualifier, resultHash, nil
298+
}

internal/service/lambda/invocation_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,89 @@ import (
1616
"github.com/hashicorp/terraform-plugin-testing/terraform"
1717
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
1818
"github.com/hashicorp/terraform-provider-aws/internal/conns"
19+
tflambda "github.com/hashicorp/terraform-provider-aws/internal/service/lambda"
1920
"github.com/hashicorp/terraform-provider-aws/internal/verify"
2021
"github.com/hashicorp/terraform-provider-aws/names"
2122
)
2223

24+
func TestParseRecordID(t *testing.T) {
25+
t.Parallel()
26+
27+
cases := []struct {
28+
Input string
29+
FunctionName, Qualifier, ResultHash string
30+
ExpectError bool
31+
}{
32+
// Invalid cases
33+
{"ABCDEF", "", "", "", true},
34+
{"ABCDEF,42", "", "", "", true},
35+
{"ABCDEF,,", "", "", "", true},
36+
{"ABCDEF,invalid_qualifier,b326b5062b2f0e69046810717534cb09", "", "", "", true},
37+
{"ABCDEF,42,invalid_hash", "", "", "", true},
38+
// Valid cases
39+
{"ABCDEF,42,b326b5062b2f0e69046810717534cb09", "ABCDEF", "42", "b326b5062b2f0e69046810717534cb09", false},
40+
{"ABC_DEF,42,b326b5062b2f0e69046810717534cb09", "ABC_DEF", "42", "b326b5062b2f0e69046810717534cb09", false},
41+
{"ABCDEF,$LATEST,b326b5062b2f0e69046810717534cb09", "ABCDEF", "$LATEST", "b326b5062b2f0e69046810717534cb09", false},
42+
{"ABC_DEF,$LATEST,b326b5062b2f0e69046810717534cb09", "ABC_DEF", "$LATEST", "b326b5062b2f0e69046810717534cb09", false},
43+
{"ABC_DEF_1234,567,b326b5062b2f0e69046810717534cb09", "ABC_DEF_1234", "567", "b326b5062b2f0e69046810717534cb09", false},
44+
}
45+
46+
for _, tc := range cases {
47+
t.Run(tc.Input, func(t *testing.T) {
48+
t.Parallel()
49+
50+
functionName, qualifier, resultHash, err := tflambda.InvocationParseResourceID(tc.Input)
51+
52+
if tc.ExpectError {
53+
if err == nil {
54+
t.Fatalf("expected error for input: %s", tc.Input)
55+
}
56+
return
57+
}
58+
59+
if err != nil {
60+
t.Fatalf("unexpected error for input %s: %v", tc.Input, err)
61+
}
62+
63+
if functionName != tc.FunctionName {
64+
t.Fatalf("input: %s\nfunction_name: %s\nexpected:%s", tc.Input, functionName, tc.FunctionName)
65+
}
66+
if qualifier != tc.Qualifier {
67+
t.Fatalf("input: %s\nqualifier: %s\nexpected:%s", tc.Input, qualifier, tc.Qualifier)
68+
}
69+
if resultHash != tc.ResultHash {
70+
t.Fatalf("input: %s\nresult: %s\nexpected:%s", tc.Input, resultHash, tc.ResultHash)
71+
}
72+
})
73+
}
74+
}
75+
76+
func TestInvocationResourceIDCreation(t *testing.T) {
77+
t.Parallel()
78+
79+
functionName := "my_test_function"
80+
qualifier := "$LATEST"
81+
resultHash := "b326b5062b2f0e69046810717534cb09"
82+
83+
expectedID := "my_test_function,$LATEST,b326b5062b2f0e69046810717534cb09"
84+
85+
// Test parsing the expected ID format
86+
parsedFunctionName, parsedQualifier, parsedResultHash, err := tflambda.InvocationParseResourceID(expectedID)
87+
if err != nil {
88+
t.Fatalf("unexpected error parsing resource ID: %v", err)
89+
}
90+
91+
if parsedFunctionName != functionName {
92+
t.Fatalf("expected function name: %s, got: %s", functionName, parsedFunctionName)
93+
}
94+
if parsedQualifier != qualifier {
95+
t.Fatalf("expected qualifier: %s, got: %s", qualifier, parsedQualifier)
96+
}
97+
if parsedResultHash != resultHash {
98+
t.Fatalf("expected result hash: %s, got: %s", resultHash, parsedResultHash)
99+
}
100+
}
101+
23102
func TestAccLambdaInvocation_basic(t *testing.T) {
24103
ctx := acctest.Context(t)
25104
resourceName := "aws_lambda_invocation.test"
@@ -44,6 +123,12 @@ func TestAccLambdaInvocation_basic(t *testing.T) {
44123
testAccCheckInvocationResult(resourceName, resultJSON),
45124
),
46125
},
126+
{
127+
ResourceName: resourceName,
128+
ImportState: true,
129+
ImportStateVerify: true,
130+
ImportStateVerifyIgnore: []string{"input", "lifecycle_scope", "result", "terraform_key"},
131+
},
47132
},
48133
})
49134
}
@@ -66,6 +151,12 @@ func TestAccLambdaInvocation_qualifier(t *testing.T) {
66151
testAccCheckInvocationResult(resourceName, `{"key1":"value1","key2":"value2","key3":"`+testData+`"}`),
67152
),
68153
},
154+
{
155+
ResourceName: resourceName,
156+
ImportState: true,
157+
ImportStateVerify: true,
158+
ImportStateVerifyIgnore: []string{"input", "lifecycle_scope", "result", "terraform_key"},
159+
},
69160
},
70161
})
71162
}
@@ -153,6 +244,12 @@ func TestAccLambdaInvocation_lifecycle_scopeCRUDCreate(t *testing.T) {
153244
testAccCheckInvocationResult(resourceName, resultJSON),
154245
),
155246
},
247+
{
248+
ResourceName: resourceName,
249+
ImportState: true,
250+
ImportStateVerify: true,
251+
ImportStateVerifyIgnore: []string{"input", "lifecycle_scope", "result", "terraform_key"},
252+
},
156253
},
157254
})
158255
}

website/docs/r/lambda_invocation.html.markdown

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,23 @@ The following arguments are optional:
181181
This resource exports the following attributes in addition to the arguments above:
182182

183183
* `result` - String result of the Lambda function invocation.
184+
185+
## Import
186+
187+
In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Lambda Invocation using the `function_name,qualifier,result_hash`. For example:
188+
189+
```terraform
190+
import {
191+
to = aws_lambda_invocation.test_lambda
192+
id = "my_test_lambda_function,$LATEST,b326b5062b2f0e69046810717534cb09"
193+
}
194+
```
195+
196+
Using `terraform import`, import Lambda Invocation using the `function_name,qualifier,result_hash`. For example:
197+
198+
```console
199+
% terraform import aws_lambda_invocation.test_lambda my_test_lambda_function,$LATEST,b326b5062b2f0e69046810717534cb09
200+
```
201+
202+
Because it is not possible to retrieve previous invocations, during the next apply `terraform` will update the resource calling again the function.
203+
To compute the `result_hash`, it is necessary to hash it with the standard `md5` hash function.

0 commit comments

Comments
 (0)