Skip to content

Commit 438776b

Browse files
author
Marcin Belczewski
committed
feat: implement email contact
1 parent 9c4f788 commit 438776b

16 files changed

+1542
-115
lines changed

internal/service/notifications/channel_association.go

Lines changed: 493 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package notifications_test
5+
// **PLEASE DELETE THIS AND ALL TIP COMMENTS BEFORE SUBMITTING A PR FOR REVIEW!**
6+
//
7+
// TIP: ==== INTRODUCTION ====
8+
// Thank you for trying the skaff tool!
9+
//
10+
// You have opted to include these helpful comments. They all include "TIP:"
11+
// to help you find and remove them when you're done with them.
12+
//
13+
// While some aspects of this file are customized to your input, the
14+
// scaffold tool does *not* look at the AWS API and ensure it has correct
15+
// function, structure, and variable names. It makes guesses based on
16+
// commonalities. You will need to make significant adjustments.
17+
//
18+
// In other words, as generated, this is a rough outline of the work you will
19+
// need to do. If something doesn't make sense for your situation, get rid of
20+
// it.
21+
22+
import (
23+
// TIP: ==== IMPORTS ====
24+
// This is a common set of imports but not customized to your code since
25+
// your code hasn't been written yet. Make sure you, your IDE, or
26+
// goimports -w <file> fixes these imports.
27+
//
28+
// The provider linter wants your imports to be in two groups: first,
29+
// standard library (i.e., "fmt" or "strings"), second, everything else.
30+
//
31+
// Also, AWS Go SDK v2 may handle nested structures differently than v1,
32+
// using the services/notifications/types package. If so, you'll
33+
// need to import types and reference the nested types, e.g., as
34+
// types.<Type Name>.
35+
"context"
36+
"errors"
37+
"fmt"
38+
"testing"
39+
40+
"github.com/YakDriver/regexache"
41+
"github.com/aws/aws-sdk-go-v2/aws"
42+
"github.com/aws/aws-sdk-go-v2/service/notifications"
43+
"github.com/aws/aws-sdk-go-v2/service/notifications/types"
44+
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
45+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
46+
"github.com/hashicorp/terraform-plugin-testing/plancheck"
47+
"github.com/hashicorp/terraform-plugin-testing/terraform"
48+
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
49+
"github.com/hashicorp/terraform-provider-aws/internal/conns"
50+
"github.com/hashicorp/terraform-provider-aws/internal/create"
51+
"github.com/hashicorp/terraform-provider-aws/internal/errs"
52+
"github.com/hashicorp/terraform-provider-aws/names"
53+
54+
// TIP: You will often need to import the package that this test file lives
55+
// in. Since it is in the "test" context, it must import the package to use
56+
// any normal context constants, variables, or functions.
57+
tfnotifications "github.com/hashicorp/terraform-provider-aws/internal/service/notifications"
58+
)
59+
60+
// TIP: File Structure. The basic outline for all test files should be as
61+
// follows. Improve this resource's maintainability by following this
62+
// outline.
63+
//
64+
// 1. Package declaration (add "_test" since this is a test file)
65+
// 2. Imports
66+
// 3. Unit tests
67+
// 4. Basic test
68+
// 5. Disappears test
69+
// 6. All the other tests
70+
// 7. Helper functions (exists, destroy, check, etc.)
71+
// 8. Functions that return Terraform configurations
72+
73+
// TIP: ==== UNIT TESTS ====
74+
// This is an example of a unit test. Its name is not prefixed with
75+
// "TestAcc" like an acceptance test.
76+
//
77+
// Unlike acceptance tests, unit tests do not access AWS and are focused on a
78+
// function (or method). Because of this, they are quick and cheap to run.
79+
//
80+
// In designing a resource's implementation, isolate complex bits from AWS bits
81+
// so that they can be tested through a unit test. We encourage more unit tests
82+
// in the provider.
83+
//
84+
// Cut and dry functions using well-used patterns, like typical flatteners and
85+
// expanders, don't need unit testing. However, if they are complex or
86+
// intricate, they should be unit tested.
87+
func TestChannelAssociationExampleUnitTest(t *testing.T) {
88+
t.Parallel()
89+
90+
testCases := []struct {
91+
TestName string
92+
Input string
93+
Expected string
94+
Error bool
95+
}{
96+
{
97+
TestName: "empty",
98+
Input: "",
99+
Expected: "",
100+
Error: true,
101+
},
102+
{
103+
TestName: "descriptive name",
104+
Input: "some input",
105+
Expected: "some output",
106+
Error: false,
107+
},
108+
{
109+
TestName: "another descriptive name",
110+
Input: "more input",
111+
Expected: "more output",
112+
Error: false,
113+
},
114+
}
115+
116+
for _, testCase := range testCases {
117+
t.Run(testCase.TestName, func(t *testing.T) {
118+
t.Parallel()
119+
got, err := tfnotifications.FunctionFromResource(testCase.Input)
120+
121+
if err != nil && !testCase.Error {
122+
t.Errorf("got error (%s), expected no error", err)
123+
}
124+
125+
if err == nil && testCase.Error {
126+
t.Errorf("got (%s) and no error, expected error", got)
127+
}
128+
129+
if got != testCase.Expected {
130+
t.Errorf("got %s, expected %s", got, testCase.Expected)
131+
}
132+
})
133+
}
134+
}
135+
136+
// TIP: ==== ACCEPTANCE TESTS ====
137+
// This is an example of a basic acceptance test. This should test as much of
138+
// standard functionality of the resource as possible, and test importing, if
139+
// applicable. We prefix its name with "TestAcc", the service, and the
140+
// resource name.
141+
//
142+
// Acceptance test access AWS and cost money to run.
143+
func TestAccNotificationsChannelAssociation_basic(t *testing.T) {
144+
ctx := acctest.Context(t)
145+
// TIP: This is a long-running test guard for tests that run longer than
146+
// 300s (5 min) generally.
147+
if testing.Short() {
148+
t.Skip("skipping long-running test in short mode")
149+
}
150+
151+
var channelassociation notifications.DescribeChannelAssociationResponse
152+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
153+
resourceName := "aws_notifications_channel_association.test"
154+
155+
resource.ParallelTest(t, resource.TestCase{
156+
PreCheck: func() {
157+
acctest.PreCheck(ctx, t)
158+
acctest.PreCheckPartitionHasService(t, names.NotificationsEndpointID)
159+
testAccPreCheck(ctx, t)
160+
},
161+
ErrorCheck: acctest.ErrorCheck(t, names.NotificationsServiceID),
162+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
163+
CheckDestroy: testAccCheckChannelAssociationDestroy(ctx),
164+
Steps: []resource.TestStep{
165+
{
166+
Config: testAccChannelAssociationConfig_basic(rName),
167+
Check: resource.ComposeAggregateTestCheckFunc(
168+
testAccCheckChannelAssociationExists(ctx, resourceName, &channelassociation),
169+
resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"),
170+
resource.TestCheckResourceAttrSet(resourceName, "maintenance_window_start_time.0.day_of_week"),
171+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "user.*", map[string]string{
172+
"console_access": "false",
173+
"groups.#": "0",
174+
"username": "Test",
175+
"password": "TestTest1234",
176+
}),
177+
// TIP: If the ARN can be partially or completely determined by the parameters passed, e.g. it contains the
178+
// value of `rName`, either include the values in the regex or check for an exact match using `acctest.CheckResourceAttrRegionalARN`
179+
acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "notifications", regexache.MustCompile(`channelassociation:.+$`)),
180+
),
181+
},
182+
{
183+
ResourceName: resourceName,
184+
ImportState: true,
185+
ImportStateVerify: true,
186+
ImportStateVerifyIgnore: []string{"apply_immediately", "user"},
187+
},
188+
},
189+
})
190+
}
191+
192+
func TestAccNotificationsChannelAssociation_disappears(t *testing.T) {
193+
ctx := acctest.Context(t)
194+
if testing.Short() {
195+
t.Skip("skipping long-running test in short mode")
196+
}
197+
198+
var channelassociation notifications.DescribeChannelAssociationResponse
199+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
200+
resourceName := "aws_notifications_channel_association.test"
201+
202+
resource.ParallelTest(t, resource.TestCase{
203+
PreCheck: func() {
204+
acctest.PreCheck(ctx, t)
205+
acctest.PreCheckPartitionHasService(t, names.NotificationsEndpointID)
206+
testAccPreCheck(ctx, t)
207+
},
208+
ErrorCheck: acctest.ErrorCheck(t, names.NotificationsServiceID),
209+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
210+
CheckDestroy: testAccCheckChannelAssociationDestroy(ctx),
211+
Steps: []resource.TestStep{
212+
{
213+
Config: testAccChannelAssociationConfig_basic(rName, testAccChannelAssociationVersionNewer),
214+
Check: resource.ComposeAggregateTestCheckFunc(
215+
testAccCheckChannelAssociationExists(ctx, resourceName, &channelassociation),
216+
// TIP: The Plugin-Framework disappears helper is similar to the Plugin-SDK version,
217+
// but expects a new resource factory function as the third argument. To expose this
218+
// private function to the testing package, you may need to add a line like the following
219+
// to exports_test.go:
220+
//
221+
// var ResourceChannelAssociation = newResourceChannelAssociation
222+
acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfnotifications.ResourceChannelAssociation, resourceName),
223+
),
224+
ExpectNonEmptyPlan: true,
225+
ConfigPlanChecks: resource.ConfigPlanChecks{
226+
PostApplyPostRefresh: []plancheck.PlanCheck{
227+
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
228+
},
229+
},
230+
},
231+
},
232+
})
233+
}
234+
235+
func testAccCheckChannelAssociationDestroy(ctx context.Context) resource.TestCheckFunc {
236+
return func(s *terraform.State) error {
237+
conn := acctest.Provider.Meta().(*conns.AWSClient).NotificationsClient(ctx)
238+
239+
for _, rs := range s.RootModule().Resources {
240+
if rs.Type != "aws_notifications_channel_association" {
241+
continue
242+
}
243+
244+
245+
// TIP: ==== FINDERS ====
246+
// The find function should be exported. Since it won't be used outside of the package, it can be exported
247+
// in the `exports_test.go` file.
248+
_, err := tfnotifications.FindChannelAssociationByID(ctx, conn, rs.Primary.ID)
249+
if tfresource.NotFound(err) {
250+
return nil
251+
}
252+
if err != nil {
253+
return create.Error(names.Notifications, create.ErrActionCheckingDestroyed, tfnotifications.ResNameChannelAssociation, rs.Primary.ID, err)
254+
}
255+
256+
return create.Error(names.Notifications, create.ErrActionCheckingDestroyed, tfnotifications.ResNameChannelAssociation, rs.Primary.ID, errors.New("not destroyed"))
257+
}
258+
259+
return nil
260+
}
261+
}
262+
263+
func testAccCheckChannelAssociationExists(ctx context.Context, name string, channelassociation *notifications.DescribeChannelAssociationResponse) resource.TestCheckFunc {
264+
return func(s *terraform.State) error {
265+
rs, ok := s.RootModule().Resources[name]
266+
if !ok {
267+
return create.Error(names.Notifications, create.ErrActionCheckingExistence, tfnotifications.ResNameChannelAssociation, name, errors.New("not found"))
268+
}
269+
270+
if rs.Primary.ID == "" {
271+
return create.Error(names.Notifications, create.ErrActionCheckingExistence, tfnotifications.ResNameChannelAssociation, name, errors.New("not set"))
272+
}
273+
274+
conn := acctest.Provider.Meta().(*conns.AWSClient).NotificationsClient(ctx)
275+
276+
resp, err := tfnotifications.FindChannelAssociationByID(ctx, conn, rs.Primary.ID)
277+
if err != nil {
278+
return create.Error(names.Notifications, create.ErrActionCheckingExistence, tfnotifications.ResNameChannelAssociation, rs.Primary.ID, err)
279+
}
280+
281+
*channelassociation = *resp
282+
283+
return nil
284+
}
285+
}
286+
287+
func testAccPreCheck(ctx context.Context, t *testing.T) {
288+
conn := acctest.Provider.Meta().(*conns.AWSClient).NotificationsClient(ctx)
289+
290+
input := &notifications.ListChannelAssociationsInput{}
291+
292+
_, err := conn.ListChannelAssociations(ctx, input)
293+
294+
if acctest.PreCheckSkipError(err) {
295+
t.Skipf("skipping acceptance testing: %s", err)
296+
}
297+
if err != nil {
298+
t.Fatalf("unexpected PreCheck error: %s", err)
299+
}
300+
}
301+
302+
func testAccCheckChannelAssociationNotRecreated(before, after *notifications.DescribeChannelAssociationResponse) resource.TestCheckFunc {
303+
return func(s *terraform.State) error {
304+
if before, after := aws.ToString(before.ChannelAssociationId), aws.ToString(after.ChannelAssociationId); before != after {
305+
return create.Error(names.Notifications, create.ErrActionCheckingNotRecreated, tfnotifications.ResNameChannelAssociation, aws.ToString(before.ChannelAssociationId), errors.New("recreated"))
306+
}
307+
308+
return nil
309+
}
310+
}
311+
312+
func testAccChannelAssociationConfig_basic(rName, version string) string {
313+
return fmt.Sprintf(`
314+
resource "aws_security_group" "test" {
315+
name = %[1]q
316+
}
317+
318+
resource "aws_notifications_channel_association" "test" {
319+
channel_association_name = %[1]q
320+
engine_type = "ActiveNotifications"
321+
engine_version = %[2]q
322+
host_instance_type = "notifications.t2.micro"
323+
security_groups = [aws_security_group.test.id]
324+
authentication_strategy = "simple"
325+
storage_type = "efs"
326+
327+
logs {
328+
general = true
329+
}
330+
331+
user {
332+
username = "Test"
333+
password = "TestTest1234"
334+
}
335+
}
336+
`, rName, version)
337+
}

internal/service/notifications/notification_configuration.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ import (
1616
"github.com/hashicorp/terraform-plugin-framework/path"
1717
"github.com/hashicorp/terraform-plugin-framework/resource"
1818
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
19-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
2019
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
21-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
2220
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
2321
"github.com/hashicorp/terraform-plugin-framework/types"
2422
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
@@ -81,10 +79,8 @@ func (r *resourceNotificationConfiguration) Schema(ctx context.Context, req reso
8179
names.AttrStatus: schema.StringAttribute{
8280
CustomType: fwtypes.StringEnumType[awstypes.NotificationConfigurationStatus](),
8381
Computed: true,
84-
PlanModifiers: []planmodifier.String{
85-
stringplanmodifier.UseStateForUnknown(),
86-
},
87-
}, names.AttrTags: tftags.TagsAttribute(),
82+
},
83+
names.AttrTags: tftags.TagsAttribute(),
8884
names.AttrTagsAll: tftags.TagsAttributeComputedOnly(),
8985
},
9086
}

internal/service/notifications/notification_configuration_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ import (
2727

2828
func TestAccNotificationsNotificationConfiguration_basic(t *testing.T) {
2929
ctx := acctest.Context(t)
30-
if testing.Short() {
31-
t.Skip("skipping long-running test in short mode")
32-
}
3330

3431
var notificationconfiguration notifications.GetNotificationConfigurationOutput
3532
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
@@ -72,9 +69,6 @@ func TestAccNotificationsNotificationConfiguration_basic(t *testing.T) {
7269

7370
func TestAccNotificationsNotificationConfiguration_disappears(t *testing.T) {
7471
ctx := acctest.Context(t)
75-
if testing.Short() {
76-
t.Skip("skipping long-running test in short mode")
77-
}
7872

7973
var notificationconfiguration notifications.GetNotificationConfigurationOutput
8074
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
@@ -263,7 +257,6 @@ resource "aws_notifications_notification_configuration" "test" {
263257
name = %[1]q
264258
description = %[2]q
265259
aggregation_duration = %[3]q
266-
267260
tags = {
268261
%[4]q = %[5]q
269262
}

0 commit comments

Comments
 (0)