From 89c0344ffd41f22d4c8d56c1bbd00b96f74db1de Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 13 Sep 2023 12:30:07 -0400 Subject: [PATCH 1/5] aws_servicecatalog_product: import provisioning_artifact_parameters --- internal/service/servicecatalog/find.go | 21 +++++++ internal/service/servicecatalog/product.go | 60 ++++++++++++++++++- .../service/servicecatalog/product_test.go | 4 +- 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/internal/service/servicecatalog/find.go b/internal/service/servicecatalog/find.go index 0862bcf97e43..1c7857993b76 100644 --- a/internal/service/servicecatalog/find.go +++ b/internal/service/servicecatalog/find.go @@ -149,3 +149,24 @@ func FindTagOptionResourceAssociation(ctx context.Context, conn *servicecatalog. return result, err } + +func findProductByID(ctx context.Context, conn *servicecatalog.ServiceCatalog, productID string) (*servicecatalog.DescribeProductAsAdminOutput, error) { + in := &servicecatalog.DescribeProductAsAdminInput{ + Id: aws.String(productID), + } + + out, err := conn.DescribeProductAsAdminWithContext(ctx, in) + + if tfawserr.ErrCodeEquals(err, servicecatalog.ErrCodeResourceNotFoundException) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + return out, nil +} diff --git a/internal/service/servicecatalog/product.go b/internal/service/servicecatalog/product.go index 01b6ba38df5b..e933618a9e90 100644 --- a/internal/service/servicecatalog/product.go +++ b/internal/service/servicecatalog/product.go @@ -6,6 +6,7 @@ package servicecatalog import ( "context" "log" + "sort" "time" "github.com/aws/aws-sdk-go/aws" @@ -34,7 +35,7 @@ func ResourceProduct() *schema.Resource { DeleteWithoutTimeout: resourceProductDelete, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: resourceProductImport, }, Timeouts: &schema.ResourceTimeout{ @@ -163,6 +164,38 @@ func ResourceProduct() *schema.Resource { } } +func resourceProductImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + conn := meta.(*conns.AWSClient).ServiceCatalogConn(ctx) + + productData, err := findProductByID(ctx, conn, d.Id()) + + if err != nil { + return []*schema.ResourceData{d}, err + } + + sort.Slice(productData.ProvisioningArtifactSummaries, func(i, j int) bool { + return aws.TimeValue(productData.ProvisioningArtifactSummaries[i].CreatedTime).Before(aws.TimeValue(productData.ProvisioningArtifactSummaries[j].CreatedTime)) + }) + + // import the last entry in the summary + provisioningArtifact := productData.ProvisioningArtifactSummaries[len(productData.ProvisioningArtifactSummaries)-1] + in := &servicecatalog.DescribeProvisioningArtifactInput{ + ProductId: aws.String(d.Id()), + ProvisioningArtifactId: provisioningArtifact.Id, + } + + // Find additional artifact details. + artifactData, err := conn.DescribeProvisioningArtifactWithContext(ctx, in) + + if err != nil { + return []*schema.ResourceData{d}, err + } + + d.Set("provisioning_artifact_parameters", flattenProvisioningArtifactParameters(artifactData)) + + return []*schema.ResourceData{d}, nil +} + func resourceProductCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).ServiceCatalogConn(ctx) @@ -433,3 +466,28 @@ func expandProvisioningArtifactParameters(tfMap map[string]interface{}) *service return apiObject } + +func flattenProvisioningArtifactParameters(apiObject *servicecatalog.DescribeProvisioningArtifactOutput) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{ + "description": aws.StringValue(apiObject.ProvisioningArtifactDetail.Description), + "disable_template_validation": false, + "name": aws.StringValue(apiObject.ProvisioningArtifactDetail.Name), + "type": aws.StringValue(apiObject.ProvisioningArtifactDetail.Type), + } + + if apiObject.Info != nil { + if v, ok := apiObject.Info["TemplateUrl"]; ok { + m["template_url"] = aws.StringValue(v) + } + + if v, ok := apiObject.Info["PhysicalId"]; ok { + m["template_physical_id"] = aws.StringValue(v) + } + } + + return []interface{}{m} +} diff --git a/internal/service/servicecatalog/product_test.go b/internal/service/servicecatalog/product_test.go index ce5592bb2e95..d4012712323c 100644 --- a/internal/service/servicecatalog/product_test.go +++ b/internal/service/servicecatalog/product_test.go @@ -68,7 +68,7 @@ func TestAccServiceCatalogProduct_basic(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{ "accept_language", - "provisioning_artifact_parameters", + "provisioning_artifact_parameters.0.disable_template_validation", }, }, }, @@ -208,7 +208,7 @@ func TestAccServiceCatalogProduct_physicalID(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{ "accept_language", - "provisioning_artifact_parameters", + "provisioning_artifact_parameters.0.disable_template_validation", }, }, }, From 5175f32a848a403a4f575a784c7793b3df2c0a06 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 13 Sep 2023 12:30:43 -0400 Subject: [PATCH 2/5] aws_servicecatalog_product: cleanup --- internal/service/servicecatalog/product.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/servicecatalog/product.go b/internal/service/servicecatalog/product.go index e933618a9e90..64dc8813a762 100644 --- a/internal/service/servicecatalog/product.go +++ b/internal/service/servicecatalog/product.go @@ -474,7 +474,7 @@ func flattenProvisioningArtifactParameters(apiObject *servicecatalog.DescribePro m := map[string]interface{}{ "description": aws.StringValue(apiObject.ProvisioningArtifactDetail.Description), - "disable_template_validation": false, + "disable_template_validation": false, // set default because it cannot be read "name": aws.StringValue(apiObject.ProvisioningArtifactDetail.Name), "type": aws.StringValue(apiObject.ProvisioningArtifactDetail.Type), } From 16b0b18db76e86d790266a728ca931fdb6bdd40a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 13 Sep 2023 12:42:23 -0400 Subject: [PATCH 3/5] add CHANGELOG entry --- .changelog/33448.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/33448.txt diff --git a/.changelog/33448.txt b/.changelog/33448.txt new file mode 100644 index 000000000000..c2891ab99d97 --- /dev/null +++ b/.changelog/33448.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_servicecatalog_product: Allow import on `provisioning_artifact_parameters` attribute +``` \ No newline at end of file From 71ec12f269c9d2fcad9b760ddac005fce8ef7940 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 13 Sep 2023 13:01:35 -0400 Subject: [PATCH 4/5] aws_servicecatalog_product: import only if artifact exist --- internal/service/servicecatalog/product.go | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/internal/service/servicecatalog/product.go b/internal/service/servicecatalog/product.go index 64dc8813a762..7de59cb261de 100644 --- a/internal/service/servicecatalog/product.go +++ b/internal/service/servicecatalog/product.go @@ -173,25 +173,27 @@ func resourceProductImport(ctx context.Context, d *schema.ResourceData, meta int return []*schema.ResourceData{d}, err } - sort.Slice(productData.ProvisioningArtifactSummaries, func(i, j int) bool { - return aws.TimeValue(productData.ProvisioningArtifactSummaries[i].CreatedTime).Before(aws.TimeValue(productData.ProvisioningArtifactSummaries[j].CreatedTime)) - }) - // import the last entry in the summary - provisioningArtifact := productData.ProvisioningArtifactSummaries[len(productData.ProvisioningArtifactSummaries)-1] - in := &servicecatalog.DescribeProvisioningArtifactInput{ - ProductId: aws.String(d.Id()), - ProvisioningArtifactId: provisioningArtifact.Id, - } + if len(productData.ProvisioningArtifactSummaries) > 0 { + sort.Slice(productData.ProvisioningArtifactSummaries, func(i, j int) bool { + return aws.TimeValue(productData.ProvisioningArtifactSummaries[i].CreatedTime).Before(aws.TimeValue(productData.ProvisioningArtifactSummaries[j].CreatedTime)) + }) + + provisioningArtifact := productData.ProvisioningArtifactSummaries[len(productData.ProvisioningArtifactSummaries)-1] + in := &servicecatalog.DescribeProvisioningArtifactInput{ + ProductId: aws.String(d.Id()), + ProvisioningArtifactId: provisioningArtifact.Id, + } - // Find additional artifact details. - artifactData, err := conn.DescribeProvisioningArtifactWithContext(ctx, in) + // Find additional artifact details. + artifactData, err := conn.DescribeProvisioningArtifactWithContext(ctx, in) - if err != nil { - return []*schema.ResourceData{d}, err - } + if err != nil { + return []*schema.ResourceData{d}, err + } - d.Set("provisioning_artifact_parameters", flattenProvisioningArtifactParameters(artifactData)) + d.Set("provisioning_artifact_parameters", flattenProvisioningArtifactParameters(artifactData)) + } return []*schema.ResourceData{d}, nil } From 1c9ef326f5a224aa7b2c19ae9c75462a3bc3b985 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 13 Sep 2023 13:09:54 -0400 Subject: [PATCH 5/5] fix lint errors --- internal/service/servicecatalog/product.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/servicecatalog/product.go b/internal/service/servicecatalog/product.go index 7de59cb261de..98064f6ac822 100644 --- a/internal/service/servicecatalog/product.go +++ b/internal/service/servicecatalog/product.go @@ -178,7 +178,7 @@ func resourceProductImport(ctx context.Context, d *schema.ResourceData, meta int sort.Slice(productData.ProvisioningArtifactSummaries, func(i, j int) bool { return aws.TimeValue(productData.ProvisioningArtifactSummaries[i].CreatedTime).Before(aws.TimeValue(productData.ProvisioningArtifactSummaries[j].CreatedTime)) }) - + provisioningArtifact := productData.ProvisioningArtifactSummaries[len(productData.ProvisioningArtifactSummaries)-1] in := &servicecatalog.DescribeProvisioningArtifactInput{ ProductId: aws.String(d.Id()),