Skip to content

Commit d91b54e

Browse files
committed
Add tests
1 parent b9b4893 commit d91b54e

File tree

1 file changed

+384
-0
lines changed

1 file changed

+384
-0
lines changed
Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package events_test
5+
6+
import (
7+
"context"
8+
"encoding/json"
9+
"fmt"
10+
"strings"
11+
"testing"
12+
"time"
13+
14+
"github.com/aws/aws-sdk-go-v2/service/eventbridge"
15+
"github.com/aws/aws-sdk-go-v2/service/sqs"
16+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
17+
"github.com/hashicorp/terraform-plugin-testing/terraform"
18+
"github.com/hashicorp/terraform-plugin-testing/tfversion"
19+
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
20+
"github.com/hashicorp/terraform-provider-aws/internal/conns"
21+
"github.com/hashicorp/terraform-provider-aws/names"
22+
)
23+
24+
func TestAccEventsPutEventsAction_basic(t *testing.T) {
25+
ctx := acctest.Context(t)
26+
rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix)
27+
28+
resource.ParallelTest(t, resource.TestCase{
29+
PreCheck: func() { acctest.PreCheck(ctx, t) },
30+
ErrorCheck: acctest.ErrorCheck(t, names.EventsServiceID),
31+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
32+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
33+
tfversion.SkipBelow(tfversion.Version1_14_0),
34+
},
35+
CheckDestroy: testAccCheckBusDestroy(ctx),
36+
Steps: []resource.TestStep{
37+
{
38+
Config: testAccPutEventsActionConfig_basic(rName),
39+
Check: resource.ComposeTestCheckFunc(
40+
testAccCheckPutEventsDelivered(ctx, rName, 1),
41+
),
42+
},
43+
},
44+
})
45+
}
46+
47+
func TestAccEventsPutEventsAction_multipleEntries(t *testing.T) {
48+
ctx := acctest.Context(t)
49+
rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix)
50+
51+
resource.ParallelTest(t, resource.TestCase{
52+
PreCheck: func() { acctest.PreCheck(ctx, t) },
53+
ErrorCheck: acctest.ErrorCheck(t, names.EventsServiceID),
54+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
55+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
56+
tfversion.SkipBelow(tfversion.Version1_14_0),
57+
},
58+
CheckDestroy: testAccCheckBusDestroy(ctx),
59+
Steps: []resource.TestStep{
60+
{
61+
Config: testAccPutEventsActionConfig_multipleEntries(rName),
62+
Check: resource.ComposeTestCheckFunc(
63+
testAccCheckPutEventsDelivered(ctx, rName, 2),
64+
),
65+
},
66+
},
67+
})
68+
}
69+
70+
func TestAccEventsPutEventsAction_customBus(t *testing.T) {
71+
ctx := acctest.Context(t)
72+
rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix)
73+
74+
resource.ParallelTest(t, resource.TestCase{
75+
PreCheck: func() { acctest.PreCheck(ctx, t) },
76+
ErrorCheck: acctest.ErrorCheck(t, names.EventsServiceID),
77+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
78+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
79+
tfversion.SkipBelow(tfversion.Version1_14_0),
80+
},
81+
CheckDestroy: testAccCheckBusDestroy(ctx),
82+
Steps: []resource.TestStep{
83+
{
84+
Config: testAccPutEventsActionConfig_customBus(rName),
85+
Check: resource.ComposeTestCheckFunc(
86+
testAccCheckPutEventsDelivered(ctx, rName, 1),
87+
),
88+
},
89+
},
90+
})
91+
}
92+
93+
// nosemgrep: ci.events-in-func-name -- Verification helper for PutEvents delivery
94+
func testAccCheckPutEventsDelivered(ctx context.Context, rName string, expected int) resource.TestCheckFunc {
95+
return func(s *terraform.State) error {
96+
meta := acctest.Provider.Meta().(*conns.AWSClient)
97+
evConn := meta.EventsClient(ctx)
98+
sqsConn := meta.SQSClient(ctx)
99+
100+
// Ensure bus exists (sanity)
101+
if _, err := evConn.DescribeEventBus(ctx, &eventbridge.DescribeEventBusInput{Name: &rName}); err != nil {
102+
return fmt.Errorf("event bus %s not found: %w", rName, err)
103+
}
104+
105+
// Discover queue URL via name convention
106+
queueName := rName + "-events-test"
107+
getOut, err := sqsConn.GetQueueUrl(ctx, &sqs.GetQueueUrlInput{QueueName: &queueName})
108+
if err != nil {
109+
return fmt.Errorf("getting queue url: %w", err)
110+
}
111+
112+
deadline := time.Now().Add(2 * time.Minute)
113+
received := 0
114+
marker := rName
115+
for time.Now().Before(deadline) && received < expected {
116+
// Long poll
117+
msgOut, err := sqsConn.ReceiveMessage(ctx, &sqs.ReceiveMessageInput{
118+
QueueUrl: getOut.QueueUrl,
119+
MaxNumberOfMessages: 10,
120+
WaitTimeSeconds: 10,
121+
})
122+
if err != nil {
123+
// transient network errors: retry
124+
continue
125+
}
126+
for _, m := range msgOut.Messages {
127+
if m.Body == nil {
128+
continue
129+
}
130+
// EventBridge SQS target wraps the event as JSON; look for marker inside detail
131+
if strings.Contains(*m.Body, marker) {
132+
// Optionally parse to verify structure
133+
var parsed map[string]any
134+
_ = json.Unmarshal([]byte(*m.Body), &parsed)
135+
received++
136+
}
137+
}
138+
}
139+
140+
if received < expected {
141+
return fmt.Errorf("expected %d events delivered to SQS, received %d", expected, received)
142+
}
143+
return nil
144+
}
145+
}
146+
147+
// nosemgrep: ci.events-in-func-name -- Function reflects PutEvents operation naming for consistency.
148+
func testAccPutEventsActionConfig_basic(rName string) string {
149+
return fmt.Sprintf(`
150+
resource "aws_cloudwatch_event_bus" "test" {
151+
name = %[1]q
152+
}
153+
154+
resource "aws_cloudwatch_event_rule" "test" {
155+
name = %[1]q
156+
event_bus_name = aws_cloudwatch_event_bus.test.name
157+
event_pattern = jsonencode({
158+
source = ["test.application"]
159+
})
160+
}
161+
162+
resource "aws_sqs_queue" "events_target" {
163+
name = "%[1]s-events-test"
164+
}
165+
166+
resource "aws_sqs_queue_policy" "events_target" {
167+
queue_url = aws_sqs_queue.events_target.id
168+
policy = jsonencode({
169+
Version = "2012-10-17"
170+
Statement = [
171+
{
172+
Sid = "AllowEventBridgeSendMessage"
173+
Effect = "Allow"
174+
Principal = { Service = "events.amazonaws.com" }
175+
Action = "sqs:SendMessage"
176+
Resource = aws_sqs_queue.events_target.arn
177+
Condition = {
178+
ArnEquals = { "aws:SourceArn" = aws_cloudwatch_event_rule.test.arn }
179+
}
180+
}
181+
]
182+
})
183+
}
184+
185+
resource "aws_cloudwatch_event_target" "test" {
186+
rule = aws_cloudwatch_event_rule.test.name
187+
event_bus_name = aws_cloudwatch_event_bus.test.name
188+
target_id = "sqs"
189+
arn = aws_sqs_queue.events_target.arn
190+
}
191+
192+
action "aws_events_put_events" "test" {
193+
config {
194+
entry {
195+
source = "test.application"
196+
detail_type = "Test Event"
197+
event_bus_name = aws_cloudwatch_event_bus.test.name
198+
detail = jsonencode({
199+
marker = %[1]q
200+
action = "test"
201+
})
202+
}
203+
}
204+
}
205+
206+
resource "terraform_data" "trigger" {
207+
input = "trigger"
208+
lifecycle {
209+
action_trigger {
210+
events = [after_create, before_update]
211+
actions = [action.aws_events_put_events.test]
212+
}
213+
}
214+
depends_on = [
215+
aws_cloudwatch_event_target.test,
216+
aws_sqs_queue_policy.events_target
217+
]
218+
}
219+
`, rName)
220+
}
221+
222+
// nosemgrep: ci.events-in-func-name -- Function reflects PutEvents operation naming for consistency.
223+
func testAccPutEventsActionConfig_multipleEntries(rName string) string {
224+
return fmt.Sprintf(`
225+
resource "aws_cloudwatch_event_bus" "test" {
226+
name = %[1]q
227+
}
228+
229+
resource "aws_cloudwatch_event_rule" "test" {
230+
name = %[1]q
231+
event_bus_name = aws_cloudwatch_event_bus.test.name
232+
event_pattern = jsonencode({
233+
source = ["test.application", "test.orders"]
234+
})
235+
}
236+
237+
resource "aws_sqs_queue" "events_target" {
238+
name = "%[1]s-events-test"
239+
}
240+
241+
resource "aws_sqs_queue_policy" "events_target" {
242+
queue_url = aws_sqs_queue.events_target.id
243+
policy = jsonencode({
244+
Version = "2012-10-17"
245+
Statement = [
246+
{
247+
Sid = "AllowEventBridgeSendMessage"
248+
Effect = "Allow"
249+
Principal = { Service = "events.amazonaws.com" }
250+
Action = "sqs:SendMessage"
251+
Resource = aws_sqs_queue.events_target.arn
252+
Condition = {
253+
ArnEquals = { "aws:SourceArn" = aws_cloudwatch_event_rule.test.arn }
254+
}
255+
}
256+
]
257+
})
258+
}
259+
260+
resource "aws_cloudwatch_event_target" "test" {
261+
rule = aws_cloudwatch_event_rule.test.name
262+
event_bus_name = aws_cloudwatch_event_bus.test.name
263+
target_id = "sqs"
264+
arn = aws_sqs_queue.events_target.arn
265+
}
266+
267+
action "aws_events_put_events" "test" {
268+
config {
269+
entry {
270+
source = "test.application"
271+
detail_type = "User Action"
272+
event_bus_name = aws_cloudwatch_event_bus.test.name
273+
detail = jsonencode({
274+
marker = %[1]q
275+
action = "login"
276+
})
277+
}
278+
279+
entry {
280+
source = "test.orders"
281+
detail_type = "Order Created"
282+
event_bus_name = aws_cloudwatch_event_bus.test.name
283+
detail = jsonencode({
284+
marker = %[1]q
285+
amount = 99.99
286+
})
287+
}
288+
}
289+
}
290+
291+
resource "terraform_data" "trigger" {
292+
input = "trigger"
293+
lifecycle {
294+
action_trigger {
295+
events = [after_create, before_update]
296+
actions = [action.aws_events_put_events.test]
297+
}
298+
}
299+
depends_on = [
300+
aws_cloudwatch_event_target.test,
301+
aws_sqs_queue_policy.events_target
302+
]
303+
}
304+
`, rName)
305+
}
306+
307+
// nosemgrep: ci.events-in-func-name -- Function reflects PutEvents operation naming for consistency.
308+
func testAccPutEventsActionConfig_customBus(rName string) string {
309+
return fmt.Sprintf(`
310+
resource "aws_cloudwatch_event_bus" "test" {
311+
name = %[1]q
312+
}
313+
314+
resource "aws_cloudwatch_event_rule" "test" {
315+
name = %[1]q
316+
event_bus_name = aws_cloudwatch_event_bus.test.name
317+
event_pattern = jsonencode({
318+
source = ["custom.source"]
319+
detail-type = ["Custom Event"]
320+
})
321+
}
322+
323+
resource "aws_sqs_queue" "events_target" {
324+
name = "%[1]s-events-test"
325+
}
326+
327+
resource "aws_sqs_queue_policy" "events_target" {
328+
queue_url = aws_sqs_queue.events_target.id
329+
policy = jsonencode({
330+
Version = "2012-10-17"
331+
Statement = [
332+
{
333+
Sid = "AllowEventBridgeSendMessage"
334+
Effect = "Allow"
335+
Principal = { Service = "events.amazonaws.com" }
336+
Action = "sqs:SendMessage"
337+
Resource = aws_sqs_queue.events_target.arn
338+
Condition = {
339+
ArnEquals = { "aws:SourceArn" = aws_cloudwatch_event_rule.test.arn }
340+
}
341+
}
342+
]
343+
})
344+
}
345+
346+
resource "aws_cloudwatch_event_target" "test" {
347+
rule = aws_cloudwatch_event_rule.test.name
348+
event_bus_name = aws_cloudwatch_event_bus.test.name
349+
target_id = "sqs"
350+
arn = aws_sqs_queue.events_target.arn
351+
}
352+
353+
action "aws_events_put_events" "test" {
354+
config {
355+
entry {
356+
source = "custom.source"
357+
detail_type = "Custom Event"
358+
event_bus_name = aws_cloudwatch_event_bus.test.name
359+
time = "2023-01-01T12:00:00Z"
360+
resources = ["arn:aws:s3:::example-bucket"]
361+
detail = jsonencode({
362+
custom_field = "custom_value"
363+
marker = %[1]q
364+
timestamp = "2023-01-01T12:00:00Z"
365+
})
366+
}
367+
}
368+
}
369+
370+
resource "terraform_data" "trigger" {
371+
input = "trigger"
372+
lifecycle {
373+
action_trigger {
374+
events = [after_create, before_update]
375+
actions = [action.aws_events_put_events.test]
376+
}
377+
}
378+
depends_on = [
379+
aws_cloudwatch_event_target.test,
380+
aws_sqs_queue_policy.events_target
381+
]
382+
}
383+
`, rName)
384+
}

0 commit comments

Comments
 (0)