Skip to content

Commit 63f0c0d

Browse files
committed
Adds sdkv2/importer.RegionalInherentRegion
1 parent e67deec commit 63f0c0d

File tree

2 files changed

+373
-0
lines changed

2 files changed

+373
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package importer
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
inttypes "github.com/hashicorp/terraform-provider-aws/internal/types"
12+
"github.com/hashicorp/terraform-provider-aws/names"
13+
)
14+
15+
func RegionalInherentRegion(_ context.Context, rd *schema.ResourceData, identitySpec inttypes.Identity) error {
16+
attr := identitySpec.Attributes[0]
17+
parser := identitySpec.CustomInherentRegionParser()
18+
19+
if rd.Id() != "" {
20+
baseIdentity, err := parser(rd.Id())
21+
if err != nil {
22+
return fmt.Errorf("parsing import ID %q: %w", rd.Id(), err)
23+
}
24+
25+
rd.Set(attr.ResourceAttributeName(), rd.Id())
26+
for _, attr := range identitySpec.IdentityDuplicateAttrs {
27+
setAttribute(rd, attr, rd.Id())
28+
}
29+
30+
if region, ok := rd.GetOk(names.AttrRegion); ok {
31+
if region != baseIdentity.Region {
32+
return fmt.Errorf("the region passed for import %q does not match the region %q in the import ID %q", region, baseIdentity.Region, rd.Id())
33+
}
34+
} else {
35+
rd.Set(names.AttrRegion, baseIdentity.Region)
36+
}
37+
38+
return nil
39+
}
40+
41+
identity, err := rd.Identity()
42+
if err != nil {
43+
return err
44+
}
45+
46+
valueRaw, ok := identity.GetOk(attr.Name())
47+
if !ok {
48+
return fmt.Errorf("identity attribute %q is required", attr.Name())
49+
}
50+
51+
value, ok := valueRaw.(string)
52+
if !ok {
53+
return fmt.Errorf("identity attribute %q: expected string, got %T", attr.Name(), valueRaw)
54+
}
55+
56+
foo, err := parser(value)
57+
if err != nil {
58+
return fmt.Errorf("identity attribute %q: parsing %q: %w", attr.Name(), value, err)
59+
}
60+
61+
rd.Set(names.AttrRegion, foo.Region)
62+
63+
rd.Set(attr.ResourceAttributeName(), value)
64+
for _, attr := range identitySpec.IdentityDuplicateAttrs {
65+
setAttribute(rd, attr, value)
66+
}
67+
68+
return nil
69+
}
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package importer_test
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
"testing"
11+
12+
"github.com/YakDriver/regexache"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
14+
"github.com/hashicorp/terraform-provider-aws/internal/provider/sdkv2/importer"
15+
"github.com/hashicorp/terraform-provider-aws/internal/provider/sdkv2/internal/attribute"
16+
inttypes "github.com/hashicorp/terraform-provider-aws/internal/types"
17+
)
18+
19+
var regionalInherentRegionSchema = map[string]*schema.Schema{
20+
"url": {
21+
Type: schema.TypeString,
22+
Computed: true,
23+
},
24+
"attr": {
25+
Type: schema.TypeString,
26+
Optional: true,
27+
},
28+
"region": attribute.Region(),
29+
}
30+
31+
// lintignore:S013 // Identity Schemas cannot specify Computed, Optional, or Required
32+
var regionalInherentRegionIdentitySchema = map[string]*schema.Schema{
33+
"url": {
34+
Type: schema.TypeString,
35+
RequiredForImport: true,
36+
},
37+
}
38+
39+
func parseID(value string) (inttypes.BaseIdentity, error) {
40+
re := regexache.MustCompile(`^https://a-service\.([a-z0-9-]+)\.[^/]+/([0-9]{12})/.+`)
41+
match := re.FindStringSubmatch(value)
42+
if match == nil {
43+
return inttypes.BaseIdentity{}, fmt.Errorf("could not parse import ID %q as SQS URL", value)
44+
}
45+
return inttypes.BaseIdentity{
46+
AccountID: match[2],
47+
Region: match[1],
48+
}, nil
49+
}
50+
51+
func createID(region, accountID, resource string) string {
52+
return fmt.Sprintf("https://a-service.%s.amazonaws.com/%s/%s", region, accountID, resource)
53+
}
54+
55+
func TestRegionalInherentRegion_ImportID_Invalid(t *testing.T) {
56+
t.Parallel()
57+
58+
rd := schema.TestResourceDataRaw(t, regionalInherentRegionSchema, map[string]any{})
59+
id := "invalid"
60+
rd.SetId(id)
61+
62+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
63+
inttypes.WithIdentityDuplicateAttrs("id"),
64+
)
65+
66+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
67+
if err != nil {
68+
if !strings.HasPrefix(err.Error(), fmt.Sprintf("parsing import ID %q", id)) {
69+
t.Fatalf("Unexpected error: %s", err)
70+
}
71+
} else {
72+
t.Fatal("Expected error, got none")
73+
}
74+
}
75+
76+
func TestRegionalInherentRegion_ImportID_Invalid_WrongRegion(t *testing.T) {
77+
t.Parallel()
78+
79+
rd := schema.TestResourceDataRaw(t, regionalInherentRegionSchema, map[string]any{
80+
"region": "another-region-1",
81+
})
82+
region := "a-region-1"
83+
accountID := "123456789012"
84+
id := createID(region, accountID, "res-abc123")
85+
rd.SetId(id)
86+
87+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
88+
inttypes.WithIdentityDuplicateAttrs("id"),
89+
)
90+
91+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
92+
if err != nil {
93+
if !strings.HasPrefix(err.Error(), "the region passed for import") {
94+
t.Fatalf("Unexpected error: %s", err)
95+
}
96+
} else {
97+
t.Fatal("Expected error, got none")
98+
}
99+
}
100+
101+
func TestRegionalInherentRegion_ImportID_Valid_DefaultRegion(t *testing.T) {
102+
t.Parallel()
103+
104+
rd := schema.TestResourceDataRaw(t, regionalInherentRegionSchema, map[string]any{})
105+
region := "a-region-1"
106+
accountID := "123456789012"
107+
id := createID(region, accountID, "res-abc123")
108+
rd.SetId(id)
109+
110+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
111+
inttypes.WithIdentityDuplicateAttrs("id"),
112+
)
113+
114+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
115+
if err != nil {
116+
t.Fatalf("Unexpected error: %s", err)
117+
}
118+
119+
if e, a := id, rd.Id(); e != a {
120+
t.Errorf("expected `id` to be %q, got %q", e, a)
121+
}
122+
if e, a := id, rd.Get("url"); e != a {
123+
t.Errorf("expected `url` to be %q, got %q", e, a)
124+
}
125+
if e, a := region, rd.Get("region"); e != a {
126+
t.Errorf("expected `region` to be %q, got %q", e, a)
127+
}
128+
if e, a := "", rd.Get("attr"); e != a {
129+
t.Errorf("expected `attr` to be %q, got %q", e, a)
130+
}
131+
}
132+
133+
func TestRegionalInherentRegion_ImportID_Valid_RegionOverride(t *testing.T) {
134+
t.Parallel()
135+
136+
region := "a-region-1"
137+
rd := schema.TestResourceDataRaw(t, regionalInherentRegionSchema, map[string]any{
138+
"region": region,
139+
})
140+
accountID := "123456789012"
141+
id := createID(region, accountID, "res-abc123")
142+
rd.SetId(id)
143+
144+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
145+
inttypes.WithIdentityDuplicateAttrs("id"),
146+
)
147+
148+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
149+
if err != nil {
150+
t.Fatalf("Unexpected error: %s", err)
151+
}
152+
153+
if e, a := id, rd.Id(); e != a {
154+
t.Errorf("expected `id` to be %q, got %q", e, a)
155+
}
156+
if e, a := id, rd.Get("url"); e != a {
157+
t.Errorf("expected `arn` to be %q, got %q", e, a)
158+
}
159+
if e, a := region, rd.Get("region"); e != a {
160+
t.Errorf("expected `region` to be %q, got %q", e, a)
161+
}
162+
if e, a := "", rd.Get("attr"); e != a {
163+
t.Errorf("expected `attr` to be %q, got %q", e, a)
164+
}
165+
}
166+
167+
func TestRegionalInherentRegion_Identity_Invalid_AttributeNotSet(t *testing.T) {
168+
t.Parallel()
169+
170+
rd := schema.TestResourceDataWithIdentityRaw(t, regionalInherentRegionSchema, regionalInherentRegionIdentitySchema, map[string]string{})
171+
172+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
173+
inttypes.WithIdentityDuplicateAttrs("id"),
174+
)
175+
176+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
177+
if err != nil {
178+
if err.Error() != fmt.Sprintf("identity attribute %q is required", "url") {
179+
t.Fatalf("Unexpected error: %s", err)
180+
}
181+
} else {
182+
t.Fatal("Expected error, got none")
183+
}
184+
}
185+
186+
func TestRegionalInherentRegion_Identity_Invalid(t *testing.T) {
187+
t.Parallel()
188+
189+
id := "invalid"
190+
rd := schema.TestResourceDataWithIdentityRaw(t, regionalInherentRegionSchema, regionalInherentRegionIdentitySchema, map[string]string{
191+
"url": id,
192+
})
193+
194+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
195+
inttypes.WithIdentityDuplicateAttrs("id"),
196+
)
197+
198+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
199+
if err != nil {
200+
if !strings.HasPrefix(err.Error(), fmt.Sprintf("identity attribute %q: parsing %q: ", "url", id)) {
201+
t.Fatalf("Unexpected error: %s", err)
202+
}
203+
} else {
204+
t.Fatal("Expected error, got none")
205+
}
206+
}
207+
208+
func TestRegionalInherentRegion_Identity_Valid(t *testing.T) {
209+
t.Parallel()
210+
211+
region := "a-region-1"
212+
accountID := "123456789012"
213+
id := createID(region, accountID, "res-abc123")
214+
rd := schema.TestResourceDataWithIdentityRaw(t, regionalInherentRegionSchema, regionalInherentRegionIdentitySchema, map[string]string{
215+
"url": id,
216+
})
217+
218+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
219+
inttypes.WithIdentityDuplicateAttrs("id"),
220+
)
221+
222+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
223+
if err != nil {
224+
t.Fatalf("Unexpected error: %s", err)
225+
}
226+
227+
if e, a := id, rd.Id(); e != a {
228+
t.Errorf("expected `id` to be %q, got %q", e, a)
229+
}
230+
if e, a := id, rd.Get("url"); e != a {
231+
t.Errorf("expected `arn` to be %q, got %q", e, a)
232+
}
233+
if e, a := region, rd.Get("region"); e != a {
234+
t.Errorf("expected `region` to be %q, got %q", e, a)
235+
}
236+
if e, a := "", rd.Get("attr"); e != a {
237+
t.Errorf("expected `attr` to be %q, got %q", e, a)
238+
}
239+
}
240+
241+
func TestRegionalInherentRegion_DuplicateAttrs_ImportID_Valid(t *testing.T) {
242+
t.Parallel()
243+
244+
rd := schema.TestResourceDataRaw(t, regionalInherentRegionSchema, map[string]any{})
245+
region := "a-region-1"
246+
accountID := "123456789012"
247+
id := createID(region, accountID, "res-abc123")
248+
rd.SetId(id)
249+
250+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
251+
inttypes.WithIdentityDuplicateAttrs("id", "attr"),
252+
)
253+
254+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
255+
if err != nil {
256+
t.Fatalf("Unexpected error: %s", err)
257+
}
258+
259+
if e, a := id, rd.Id(); e != a {
260+
t.Errorf("expected `id` to be %q, got %q", e, a)
261+
}
262+
if e, a := id, rd.Get("url"); e != a {
263+
t.Errorf("expected `arn` to be %q, got %q", e, a)
264+
}
265+
if e, a := region, rd.Get("region"); e != a {
266+
t.Errorf("expected `region` to be %q, got %q", e, a)
267+
}
268+
if e, a := id, rd.Get("attr"); e != a {
269+
t.Errorf("expected `attr` to be %q, got %q", e, a)
270+
}
271+
}
272+
273+
func TestRegionalInherentRegion_DuplicateAttrs_Identity_Valid(t *testing.T) {
274+
t.Parallel()
275+
276+
region := "a-region-1"
277+
accountID := "123456789012"
278+
id := createID(region, accountID, "res-abc123")
279+
rd := schema.TestResourceDataWithIdentityRaw(t, regionalInherentRegionSchema, regionalInherentRegionIdentitySchema, map[string]string{
280+
"url": id,
281+
})
282+
283+
identity := inttypes.RegionalCustomInherentRegionIdentity("url", parseID,
284+
inttypes.WithIdentityDuplicateAttrs("id", "attr"),
285+
)
286+
287+
err := importer.RegionalInherentRegion(context.Background(), rd, identity)
288+
if err != nil {
289+
t.Fatalf("Unexpected error: %s", err)
290+
}
291+
292+
if e, a := id, rd.Id(); e != a {
293+
t.Errorf("expected `id` to be %q, got %q", e, a)
294+
}
295+
if e, a := id, rd.Get("url"); e != a {
296+
t.Errorf("expected `arn` to be %q, got %q", e, a)
297+
}
298+
if e, a := region, rd.Get("region"); e != a {
299+
t.Errorf("expected `region` to be %q, got %q", e, a)
300+
}
301+
if e, a := id, rd.Get("attr"); e != a {
302+
t.Errorf("expected `attr` to be %q, got %q", e, a)
303+
}
304+
}

0 commit comments

Comments
 (0)