Skip to content

Commit 201865b

Browse files
authored
Merge pull request #37066 from hashicorp/td-generate-tagtests-servicecatalog
Service Catalog Provisioned Product tagging issues
2 parents efcc2da + b51a14f commit 201865b

19 files changed

+2739
-253
lines changed

.changelog/37066.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:bug
2+
resource/aws_servicecatalog_provisioned_product: Fixes error where tag values are not applied to products when tag values don't change.
3+
```
4+
5+
```release-note:bug
6+
resource/aws_servicecatalog_portfolio: Fixes error where deletion fails if resource was deleted out of band.
7+
```

internal/acctest/s3.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package acctest
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-testing/terraform"
12+
"github.com/hashicorp/terraform-provider-aws/internal/conns"
13+
tfs3 "github.com/hashicorp/terraform-provider-aws/internal/service/s3"
14+
)
15+
16+
func S3BucketHasTag(ctx context.Context, bucketName, key, value string) resource.TestCheckFunc {
17+
return func(s *terraform.State) error {
18+
conn := Provider.Meta().(*conns.AWSClient).S3Client(ctx)
19+
20+
tags, err := tfs3.BucketListTags(ctx, conn, bucketName)
21+
if err != nil {
22+
return err
23+
}
24+
25+
for k, v := range tags {
26+
if k == key {
27+
if v.ValueString() == value {
28+
return nil
29+
} else {
30+
return fmt.Errorf("expected tag %q value to be %s, got %s", key, value, v.ValueString())
31+
}
32+
}
33+
}
34+
35+
return fmt.Errorf("expected tag %q not found", key)
36+
}
37+
}

internal/generate/tagstests/file.tmpl

+15
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ import (
5151
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
5252
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
5353
"github.com/hashicorp/terraform-provider-aws/names"
54+
{{ range .GoImports -}}
55+
{{ if .Alias }}{{ .Alias }} {{ end }}"{{ .Path }}"
56+
{{ end }}
5457
)
5558

5659
{{ if .Serialize }}
@@ -173,6 +176,9 @@ func {{ template "testname" . }}_tags_AddOnUpdate(t *testing.T) {
173176
}
174177

175178
func {{ template "testname" . }}_tags_EmptyTag_OnCreate(t *testing.T) {
179+
{{- if .SkipEmptyTags }}
180+
t.Skip("Resource {{ .Name }} does not support empty tags")
181+
{{ end }}
176182
{{- template "Init" . }}
177183

178184
resource.{{ if .Serialize }}Test{{ else }}ParallelTest{{ end }}(t, resource.TestCase{
@@ -200,6 +206,9 @@ func {{ template "testname" . }}_tags_EmptyTag_OnCreate(t *testing.T) {
200206
}
201207

202208
func {{ template "testname" . }}_tags_EmptyTag_OnUpdate_Add(t *testing.T) {
209+
{{- if .SkipEmptyTags }}
210+
t.Skip("Resource {{ .Name }} does not support empty tags")
211+
{{ end }}
203212
{{- template "Init" . }}
204213

205214
resource.{{ if .Serialize }}Test{{ else }}ParallelTest{{ end }}(t, resource.TestCase{
@@ -237,6 +246,9 @@ func {{ template "testname" . }}_tags_EmptyTag_OnUpdate_Add(t *testing.T) {
237246
}
238247

239248
func {{ template "testname" . }}_tags_EmptyTag_OnUpdate_Replace(t *testing.T) {
249+
{{- if .SkipEmptyTags }}
250+
t.Skip("Resource {{ .Name }} does not support empty tags")
251+
{{ end }}
240252
{{- template "Init" . }}
241253

242254
resource.{{ if .Serialize }}Test{{ else }}ParallelTest{{ end }}(t, resource.TestCase{
@@ -500,6 +512,9 @@ func {{ template "testname" . }}_tags_DefaultTags_updateToResourceOnly(t *testin
500512
}
501513

502514
func {{ template "testname" . }}_tags_DefaultTags_emptyResourceTag(t *testing.T) {
515+
{{- if .SkipEmptyTags }}
516+
t.Skip("Resource {{ .Name }} does not support empty tags")
517+
{{ end }}
503518
{{- template "Init" . }}
504519

505520
resource.{{ if .Serialize }}Test{{ else }}ParallelTest{{ end }}(t, resource.TestCase{

internal/generate/tagstests/main.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ type ResourceDatum struct {
111111
Implementation implementation
112112
Serialize bool
113113
PreCheck bool
114+
SkipEmptyTags bool // TODO: Remove when we have a strategy for resources that have a minimum tag value length of 1
115+
GoImports []goImport
116+
}
117+
118+
type goImport struct {
119+
Path string
120+
Alias string
114121
}
115122

116123
//go:embed file.tmpl
@@ -221,7 +228,28 @@ func (v *visitor) processFuncDecl(funcDecl *ast.FuncDecl) {
221228
d.ExistsTypeName = typeName
222229
}
223230
if attr, ok := args.Keyword["generator"]; ok {
224-
d.Generator = attr
231+
parts := strings.Split(attr, ";")
232+
switch len(parts) {
233+
case 1:
234+
d.Generator = parts[0]
235+
236+
case 2:
237+
d.Generator = parts[1]
238+
d.GoImports = append(d.GoImports, goImport{
239+
Path: parts[0],
240+
})
241+
242+
case 3:
243+
d.Generator = parts[2]
244+
d.GoImports = append(d.GoImports, goImport{
245+
Path: parts[0],
246+
Alias: parts[1],
247+
})
248+
249+
default:
250+
v.errs = append(v.errs, fmt.Errorf("invalid generator value: %q at %s.", attr, fmt.Sprintf("%s.%s", v.packageName, v.functionName)))
251+
continue
252+
}
225253
}
226254
if attr, ok := args.Keyword["importIgnore"]; ok {
227255
d.ImportIgnore = strings.Split(attr, ";")
@@ -254,6 +282,14 @@ func (v *visitor) processFuncDecl(funcDecl *ast.FuncDecl) {
254282
skip = true
255283
}
256284
}
285+
if attr, ok := args.Keyword["skipEmptyTags"]; ok {
286+
if b, err := strconv.ParseBool(attr); err != nil {
287+
v.errs = append(v.errs, fmt.Errorf("invalid skipEmptyTags value: %q at %s. Should be boolean value.", attr, fmt.Sprintf("%s.%s", v.packageName, v.functionName)))
288+
continue
289+
} else {
290+
d.SkipEmptyTags = b
291+
}
292+
}
257293
}
258294
}
259295
}

internal/service/s3/exports.go

+2
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ package s3
77
var (
88
ResourceBucket = resourceBucket
99
ResourceObject = resourceObject
10+
11+
BucketListTags = bucketListTags
1012
)

internal/service/s3/exports_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ var (
2828
ResourceDirectoryBucket = newDirectoryBucketResource
2929
ResourceObjectCopy = resourceObjectCopy
3030

31-
BucketListTags = bucketListTags
3231
BucketUpdateTags = bucketUpdateTags
3332
BucketRegionalDomainName = bucketRegionalDomainName
3433
BucketWebsiteEndpointAndDomain = bucketWebsiteEndpointAndDomain

internal/service/servicecatalog/generate.go

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
//go:generate go run ../../generate/tags/main.go -ServiceTagsSlice
55
//go:generate go run ../../generate/servicepackage/main.go
6+
//go:generate go run ../../generate/tagstests/main.go
67
// ONLY generate directives and package declaration! Do not add anything else to this file.
78

89
package servicecatalog

internal/service/servicecatalog/portfolio.go

+5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
// @SDKResource("aws_servicecatalog_portfolio", name="Portfolio")
2828
// @Tags
29+
// @Testing(existsType="github.com/aws/aws-sdk-go/service/servicecatalog.DescribePortfolioOutput", generator="github.com/hashicorp/terraform-plugin-testing/helper/acctest;sdkacctest;sdkacctest.RandString(5)", skipEmptyTags=true)
2930
func ResourcePortfolio() *schema.Resource {
3031
return &schema.Resource{
3132
CreateWithoutTimeout: resourcePortfolioCreate,
@@ -185,6 +186,10 @@ func resourcePortfolioDelete(ctx context.Context, d *schema.ResourceData, meta i
185186
Id: aws.String(d.Id()),
186187
})
187188

189+
if tfawserr.ErrCodeEquals(err, servicecatalog.ErrCodeResourceNotFoundException) {
190+
return diags
191+
}
192+
188193
if err != nil {
189194
return sdkdiag.AppendErrorf(diags, "deleting Service Catalog Portfolio (%s): %s", d.Id(), err)
190195
}

internal/service/servicecatalog/portfolio_data_source_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestAccServiceCatalogPortfolioDataSource_basic(t *testing.T) {
2222
PreCheck: func() { acctest.PreCheck(ctx, t) },
2323
ErrorCheck: acctest.ErrorCheck(t, names.ServiceCatalogServiceID),
2424
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
25-
CheckDestroy: testAccCheckServiceCatlaogPortfolioDestroy(ctx),
25+
CheckDestroy: testAccCheckPortfolioDestroy(ctx),
2626
Steps: []resource.TestStep{
2727
{
2828
Config: testAccPortfolioDataSourceConfig_basic(rName),

0 commit comments

Comments
 (0)