Skip to content

Commit bec04cb

Browse files
committed
Add tests for new action
1 parent 129a728 commit bec04cb

File tree

1 file changed

+370
-0
lines changed

1 file changed

+370
-0
lines changed
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package sfn_test
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"testing"
10+
11+
"github.com/aws/aws-sdk-go-v2/service/sfn"
12+
awstypes "github.com/aws/aws-sdk-go-v2/service/sfn/types"
13+
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
14+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
15+
"github.com/hashicorp/terraform-plugin-testing/terraform"
16+
"github.com/hashicorp/terraform-plugin-testing/tfversion"
17+
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
18+
"github.com/hashicorp/terraform-provider-aws/internal/conns"
19+
"github.com/hashicorp/terraform-provider-aws/names"
20+
)
21+
22+
func TestAccSFNStartExecutionAction_basic(t *testing.T) {
23+
ctx := acctest.Context(t)
24+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
25+
inputJSON := `{"key1":"value1","key2":"value2"}`
26+
27+
resource.ParallelTest(t, resource.TestCase{
28+
PreCheck: func() { acctest.PreCheck(ctx, t) },
29+
ErrorCheck: acctest.ErrorCheck(t, names.SFNServiceID),
30+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
31+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
32+
tfversion.SkipBelow(tfversion.Version1_14_0),
33+
},
34+
CheckDestroy: acctest.CheckDestroyNoop,
35+
Steps: []resource.TestStep{
36+
{
37+
Config: testAccStartExecutionActionConfig_basic(rName, inputJSON),
38+
Check: resource.ComposeTestCheckFunc(
39+
testAccCheckStartExecutionAction(ctx, rName, inputJSON),
40+
),
41+
},
42+
},
43+
})
44+
}
45+
46+
func TestAccSFNStartExecutionAction_withName(t *testing.T) {
47+
ctx := acctest.Context(t)
48+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
49+
executionName := sdkacctest.RandomWithPrefix("execution")
50+
inputJSON := `{"test":"data"}`
51+
52+
resource.ParallelTest(t, resource.TestCase{
53+
PreCheck: func() { acctest.PreCheck(ctx, t) },
54+
ErrorCheck: acctest.ErrorCheck(t, names.SFNServiceID),
55+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
56+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
57+
tfversion.SkipBelow(tfversion.Version1_14_0),
58+
},
59+
CheckDestroy: acctest.CheckDestroyNoop,
60+
Steps: []resource.TestStep{
61+
{
62+
Config: testAccStartExecutionActionConfig_withName(rName, executionName, inputJSON),
63+
Check: resource.ComposeTestCheckFunc(
64+
testAccCheckStartExecutionActionWithName(ctx, rName, executionName, inputJSON),
65+
),
66+
},
67+
},
68+
})
69+
}
70+
71+
func TestAccSFNStartExecutionAction_emptyInput(t *testing.T) {
72+
ctx := acctest.Context(t)
73+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
74+
75+
resource.ParallelTest(t, resource.TestCase{
76+
PreCheck: func() { acctest.PreCheck(ctx, t) },
77+
ErrorCheck: acctest.ErrorCheck(t, names.SFNServiceID),
78+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
79+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
80+
tfversion.SkipBelow(tfversion.Version1_14_0),
81+
},
82+
CheckDestroy: acctest.CheckDestroyNoop,
83+
Steps: []resource.TestStep{
84+
{
85+
Config: testAccStartExecutionActionConfig_emptyInput(rName),
86+
Check: resource.ComposeTestCheckFunc(
87+
testAccCheckStartExecutionAction(ctx, rName, "{}"),
88+
),
89+
},
90+
},
91+
})
92+
}
93+
94+
// Test helper functions
95+
96+
func testAccCheckStartExecutionAction(ctx context.Context, stateMachineName, expectedInput string) resource.TestCheckFunc {
97+
return func(s *terraform.State) error {
98+
conn := acctest.Provider.Meta().(*conns.AWSClient).SFNClient(ctx)
99+
100+
// Get the state machine ARN
101+
stateMachines, err := conn.ListStateMachines(ctx, &sfn.ListStateMachinesInput{})
102+
if err != nil {
103+
return fmt.Errorf("failed to list state machines: %w", err)
104+
}
105+
106+
var stateMachineArn string
107+
for _, sm := range stateMachines.StateMachines {
108+
if *sm.Name == stateMachineName {
109+
stateMachineArn = *sm.StateMachineArn
110+
break
111+
}
112+
}
113+
114+
if stateMachineArn == "" {
115+
return fmt.Errorf("state machine %s not found", stateMachineName)
116+
}
117+
118+
// List executions to verify one was created (check all statuses)
119+
executions, err := conn.ListExecutions(ctx, &sfn.ListExecutionsInput{
120+
StateMachineArn: &stateMachineArn,
121+
})
122+
if err != nil {
123+
return fmt.Errorf("failed to list executions for state machine %s: %w", stateMachineName, err)
124+
}
125+
126+
if len(executions.Executions) == 0 {
127+
return fmt.Errorf("no executions found for state machine %s", stateMachineName)
128+
}
129+
130+
// Verify the execution input matches expected
131+
execution := executions.Executions[0]
132+
executionDetails, err := conn.DescribeExecution(ctx, &sfn.DescribeExecutionInput{
133+
ExecutionArn: execution.ExecutionArn,
134+
})
135+
if err != nil {
136+
return fmt.Errorf("failed to describe execution %s: %w", *execution.ExecutionArn, err)
137+
}
138+
139+
if *executionDetails.Input != expectedInput {
140+
return fmt.Errorf("execution input mismatch. Expected: %s, Got: %s", expectedInput, *executionDetails.Input)
141+
}
142+
143+
return nil
144+
}
145+
}
146+
147+
func testAccCheckStartExecutionActionWithName(ctx context.Context, stateMachineName, executionName, expectedInput string) resource.TestCheckFunc {
148+
return func(s *terraform.State) error {
149+
conn := acctest.Provider.Meta().(*conns.AWSClient).SFNClient(ctx)
150+
151+
// Get the state machine ARN
152+
stateMachines, err := conn.ListStateMachines(ctx, &sfn.ListStateMachinesInput{})
153+
if err != nil {
154+
return fmt.Errorf("failed to list state machines: %w", err)
155+
}
156+
157+
var stateMachineArn string
158+
for _, sm := range stateMachines.StateMachines {
159+
if *sm.Name == stateMachineName {
160+
stateMachineArn = *sm.StateMachineArn
161+
break
162+
}
163+
}
164+
165+
if stateMachineArn == "" {
166+
return fmt.Errorf("state machine %s not found", stateMachineName)
167+
}
168+
169+
// Find execution by name (check all statuses)
170+
executions, err := conn.ListExecutions(ctx, &sfn.ListExecutionsInput{
171+
StateMachineArn: &stateMachineArn,
172+
})
173+
if err != nil {
174+
return fmt.Errorf("failed to list executions for state machine %s: %w", stateMachineName, err)
175+
}
176+
177+
var foundExecution *awstypes.ExecutionListItem
178+
for _, execution := range executions.Executions {
179+
if *execution.Name == executionName {
180+
foundExecution = &execution
181+
break
182+
}
183+
}
184+
185+
if foundExecution == nil {
186+
return fmt.Errorf("execution with name %s not found for state machine %s", executionName, stateMachineName)
187+
}
188+
189+
// Verify the execution input
190+
executionDetails, err := conn.DescribeExecution(ctx, &sfn.DescribeExecutionInput{
191+
ExecutionArn: foundExecution.ExecutionArn,
192+
})
193+
if err != nil {
194+
return fmt.Errorf("failed to describe execution %s: %w", *foundExecution.ExecutionArn, err)
195+
}
196+
197+
if *executionDetails.Input != expectedInput {
198+
return fmt.Errorf("execution input mismatch. Expected: %s, Got: %s", expectedInput, *executionDetails.Input)
199+
}
200+
201+
return nil
202+
}
203+
}
204+
205+
// Configuration functions
206+
207+
func testAccStartExecutionActionConfig_basic(rName, inputJSON string) string {
208+
return acctest.ConfigCompose(
209+
testAccStartExecutionActionConfig_base(rName),
210+
fmt.Sprintf(`
211+
action "aws_sfn_start_execution" "test" {
212+
config {
213+
state_machine_arn = aws_sfn_state_machine.test.arn
214+
input = %[1]q
215+
}
216+
}
217+
218+
resource "terraform_data" "trigger" {
219+
input = "trigger"
220+
lifecycle {
221+
action_trigger {
222+
events = [before_create, before_update]
223+
actions = [action.aws_sfn_start_execution.test]
224+
}
225+
}
226+
}
227+
`, inputJSON))
228+
}
229+
230+
func testAccStartExecutionActionConfig_withName(rName, executionName, inputJSON string) string {
231+
return acctest.ConfigCompose(
232+
testAccStartExecutionActionConfig_base(rName),
233+
fmt.Sprintf(`
234+
action "aws_sfn_start_execution" "test" {
235+
config {
236+
state_machine_arn = aws_sfn_state_machine.test.arn
237+
name = %[1]q
238+
input = %[2]q
239+
}
240+
}
241+
242+
resource "terraform_data" "trigger" {
243+
input = "trigger"
244+
lifecycle {
245+
action_trigger {
246+
events = [before_create, before_update]
247+
actions = [action.aws_sfn_start_execution.test]
248+
}
249+
}
250+
}
251+
`, executionName, inputJSON))
252+
}
253+
254+
func testAccStartExecutionActionConfig_emptyInput(rName string) string {
255+
return acctest.ConfigCompose(
256+
testAccStartExecutionActionConfig_base(rName),
257+
`
258+
action "aws_sfn_start_execution" "test" {
259+
config {
260+
state_machine_arn = aws_sfn_state_machine.test.arn
261+
}
262+
}
263+
264+
resource "terraform_data" "trigger" {
265+
input = "trigger"
266+
lifecycle {
267+
action_trigger {
268+
events = [before_create, before_update]
269+
actions = [action.aws_sfn_start_execution.test]
270+
}
271+
}
272+
}
273+
`)
274+
}
275+
276+
func testAccStartExecutionActionConfig_base(rName string) string {
277+
return fmt.Sprintf(`
278+
resource "aws_iam_role" "for_lambda" {
279+
name = "%[1]s-lambda"
280+
281+
assume_role_policy = jsonencode({
282+
Version = "2012-10-17"
283+
Statement = [{
284+
Action = "sts:AssumeRole"
285+
Principal = {
286+
Service = "lambda.amazonaws.com"
287+
}
288+
Effect = "Allow"
289+
}]
290+
})
291+
}
292+
293+
resource "aws_iam_role_policy" "for_lambda" {
294+
name = "%[1]s-lambda"
295+
role = aws_iam_role.for_lambda.id
296+
297+
policy = jsonencode({
298+
Version = "2012-10-17"
299+
Statement = [{
300+
Effect = "Allow"
301+
Action = [
302+
"logs:CreateLogGroup",
303+
"logs:CreateLogStream",
304+
"logs:PutLogEvents"
305+
]
306+
Resource = "arn:${data.aws_partition.current.partition}:logs:*:*:*"
307+
}]
308+
})
309+
}
310+
311+
resource "aws_lambda_function" "test" {
312+
filename = "test-fixtures/lambdatest.zip"
313+
function_name = %[1]q
314+
role = aws_iam_role.for_lambda.arn
315+
handler = "exports.example"
316+
runtime = "nodejs20.x"
317+
}
318+
319+
resource "aws_iam_role" "for_sfn" {
320+
name = "%[1]s-sfn"
321+
322+
assume_role_policy = jsonencode({
323+
Version = "2012-10-17"
324+
Statement = [{
325+
Effect = "Allow"
326+
Principal = {
327+
Service = "states.${data.aws_region.current.region}.amazonaws.com"
328+
}
329+
Action = "sts:AssumeRole"
330+
}]
331+
})
332+
}
333+
334+
resource "aws_iam_role_policy" "for_sfn" {
335+
name = "%[1]s-sfn"
336+
role = aws_iam_role.for_sfn.id
337+
338+
policy = jsonencode({
339+
Version = "2012-10-17"
340+
Statement = [{
341+
Effect = "Allow"
342+
Action = [
343+
"lambda:InvokeFunction"
344+
]
345+
Resource = "*"
346+
}]
347+
})
348+
}
349+
350+
resource "aws_sfn_state_machine" "test" {
351+
name = %[1]q
352+
role_arn = aws_iam_role.for_sfn.arn
353+
354+
definition = jsonencode({
355+
Comment = "A simple minimal example"
356+
StartAt = "Hello"
357+
States = {
358+
Hello = {
359+
Type = "Task"
360+
Resource = aws_lambda_function.test.arn
361+
End = true
362+
}
363+
}
364+
})
365+
}
366+
367+
data "aws_region" "current" {}
368+
data "aws_partition" "current" {}
369+
`, rName)
370+
}

0 commit comments

Comments
 (0)