Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/servicecatalog: New resources (constraint, product_portfolio_association) #19385

Merged
merged 34 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a590c95
r/servicecat_constraint: Add constraint type enum
YakDriver May 14, 2021
cafda43
r/servicecat_constraint: Add statuser for constraints
YakDriver May 14, 2021
e269edc
r/servicecat_constraints: Add waiters for constraints
YakDriver May 14, 2021
e42aad1
r/servicecat_constraint: New resource
YakDriver May 14, 2021
2263d5d
tests/r/servicecat_constraint: Test new resource
YakDriver May 14, 2021
8dac191
docs/r/servicecat_constraint: Doc new resource
YakDriver May 14, 2021
7842593
provider: Add servicecat_constraint
YakDriver May 14, 2021
1eeefb9
r/servicecat_constraint: Add changelog
YakDriver May 14, 2021
bbe79d5
r/servicecatalog_constraint: Debug
YakDriver May 14, 2021
df2e045
tests/r/servicecatalog_constraint: Add role test
YakDriver May 14, 2021
76e267d
r/servicecatalog_portfolio: Make required
YakDriver May 14, 2021
3b73312
r/servicecat_product_portfolio_associ: New resource
YakDriver May 17, 2021
813f63c
tests/r/servicecat_product_portfolio_assoc: Test new resource
YakDriver May 17, 2021
2af4a19
docs/r/servicecat_product_portfolio_assoc: Doc new resource
YakDriver May 17, 2021
54a5a4b
r/servicecat: Add new resources
YakDriver May 17, 2021
93704c7
docs/r/servicecat_constraint: Add note
YakDriver May 17, 2021
fa60ac1
r/servicecat_constraint: Rework not found
YakDriver May 17, 2021
0d1674e
tests/r/servicecat_constraint: Rework tests not found
YakDriver May 17, 2021
0fe2e0e
internal/servicecat_constraint: Adjust not found use
YakDriver May 17, 2021
a84e54a
r/servicecat_product_portfolio_assoc: Add ID funcs
YakDriver May 17, 2021
5911248
r/servicecat: Adjust not found use constraint
YakDriver May 17, 2021
ff851a5
internal/r/servicecat: Use notfound errors
YakDriver May 17, 2021
595b240
r/servicecat_product_portfolio_association: Changelog
YakDriver May 17, 2021
d95c04f
docs/r/servicecat_constraint: Add realistic import ID
YakDriver May 17, 2021
0a015bb
docs/r/servicecat_constraint: Lints
YakDriver May 17, 2021
490853f
tests/r/servicecat_constraint: Lint
YakDriver May 17, 2021
3b2f313
docs/r/servicecat_constraint: Lints
YakDriver May 17, 2021
ced110b
tests/r/servicecat_constraint: Lints
YakDriver May 17, 2021
feffaab
docs/r/servicecat_constraint: Link doesn't exist, yet
YakDriver May 17, 2021
a739ff0
internal/servicecat: Right wrong error wrap
YakDriver May 17, 2021
e13b004
tests/r/servicecat_prod_port_assoc: Make assignment effectual
YakDriver May 17, 2021
196f765
i/r/servicecat_constraint: Minor fixes
YakDriver May 19, 2021
012802c
r/servicecat_constraint: Remove debug
YakDriver May 19, 2021
b188a11
r/servicecat_constraint: Wrappers paradise
YakDriver May 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/19385.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:new-resource
aws_servicecatalog_constraint
```

```release-note:new-resource
aws_servicecatalog_product_portfolio_association
```
18 changes: 18 additions & 0 deletions aws/internal/service/servicecatalog/enum.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package servicecatalog

const (
// If AWS adds these to the API, we should use those and remove these.

ServiceCatalogAcceptLanguageEnglish = "en"
ServiceCatalogAcceptLanguageJapanese = "jp"
ServiceCatalogAcceptLanguageChinese = "zh"

ConstraintTypeLaunch = "LAUNCH"
ConstraintTypeNotification = "NOTIFICATION"
ConstraintTypeResourceUpdate = "RESOURCE_UPDATE"
ConstraintTypeStackset = "STACKSET"
ConstraintTypeTemplate = "TEMPLATE"
)

func AcceptLanguage_Values() []string {
Expand All @@ -13,3 +21,13 @@ func AcceptLanguage_Values() []string {
ServiceCatalogAcceptLanguageChinese,
}
}

func ConstraintType_Values() []string {
return []string{
ConstraintTypeLaunch,
ConstraintTypeNotification,
ConstraintTypeResourceUpdate,
ConstraintTypeStackset,
ConstraintTypeTemplate,
}
}
34 changes: 34 additions & 0 deletions aws/internal/service/servicecatalog/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,37 @@ func PortfolioShare(conn *servicecatalog.ServiceCatalog, portfolioID, shareType,

return result, err
}

func ProductPortfolioAssociation(conn *servicecatalog.ServiceCatalog, acceptLanguage, portfolioID, productID string) (*servicecatalog.PortfolioDetail, error) {
// seems odd that the sourcePortfolioID is not returned or searchable...
input := &servicecatalog.ListPortfoliosForProductInput{
ProductId: aws.String(productID),
}

if acceptLanguage != "" {
input.AcceptLanguage = aws.String(acceptLanguage)
}

var result *servicecatalog.PortfolioDetail

err := conn.ListPortfoliosForProductPages(input, func(page *servicecatalog.ListPortfoliosForProductOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, deet := range page.PortfolioDetails {
if deet == nil {
continue
}

if aws.StringValue(deet.Id) == portfolioID {
result = deet
return false
}
}

return !lastPage
})

return result, err
}
14 changes: 14 additions & 0 deletions aws/internal/service/servicecatalog/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,17 @@ func PortfolioShareParseResourceID(id string) (string, string, string, error) {
func PortfolioShareCreateResourceID(portfolioID, shareType, principalID string) string {
return strings.Join([]string{portfolioID, shareType, principalID}, ":")
}

func ProductPortfolioAssociationParseID(id string) (string, string, string, error) {
parts := strings.SplitN(id, ":", 3)

if len(parts) != 3 || parts[0] == "" || parts[1] == "" || parts[2] == "" {
return "", "", "", fmt.Errorf("unexpected format of ID (%s), expected acceptLanguage:portfolioID:productID", id)
}

return parts[0], parts[1], parts[2], nil
}

func ProductPortfolioAssociationCreateID(acceptLanguage, portfolioID, productID string) string {
return strings.Join([]string{acceptLanguage, portfolioID, productID}, ":")
}
57 changes: 57 additions & 0 deletions aws/internal/service/servicecatalog/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/aws/aws-sdk-go/service/servicecatalog"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
tfservicecatalog "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/servicecatalog"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/servicecatalog/finder"
)

Expand Down Expand Up @@ -140,3 +141,59 @@ func OrganizationsAccessStatus(conn *servicecatalog.ServiceCatalog) resource.Sta
return output, aws.StringValue(output.AccessStatus), err
}
}

func ConstraintStatus(conn *servicecatalog.ServiceCatalog, acceptLanguage, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &servicecatalog.DescribeConstraintInput{
Id: aws.String(id),
}

if acceptLanguage != "" {
input.AcceptLanguage = aws.String(acceptLanguage)
}

output, err := conn.DescribeConstraint(input)

if tfawserr.ErrCodeEquals(err, servicecatalog.ErrCodeResourceNotFoundException) {
return nil, StatusNotFound, &resource.NotFoundError{
Message: fmt.Sprintf("constraint not found (accept language %s, ID: %s): %s", acceptLanguage, id, err),
YakDriver marked this conversation as resolved.
Show resolved Hide resolved
}
}

if err != nil {
return nil, servicecatalog.StatusFailed, fmt.Errorf("error describing constraint: %w", err)
}

if output == nil || output.ConstraintDetail == nil {
return nil, StatusNotFound, &resource.NotFoundError{
Message: fmt.Sprintf("describing constraint (accept language %s, ID: %s): empty response", acceptLanguage, id),
}
}

return output, aws.StringValue(output.Status), err
}
}

func ProductPortfolioAssociationStatus(conn *servicecatalog.ServiceCatalog, acceptLanguage, portfolioID, productID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := finder.ProductPortfolioAssociation(conn, acceptLanguage, portfolioID, productID)

if tfawserr.ErrCodeEquals(err, servicecatalog.ErrCodeResourceNotFoundException) {
return nil, StatusNotFound, &resource.NotFoundError{
Message: fmt.Sprintf("product portfolio association not found (%s): %s", tfservicecatalog.ProductPortfolioAssociationCreateID(acceptLanguage, portfolioID, productID), err),
}
}

if err != nil {
return nil, servicecatalog.StatusFailed, fmt.Errorf("error describing product portfolio association: %w", err)
}

if output == nil {
return nil, StatusNotFound, &resource.NotFoundError{
Message: fmt.Sprintf("finding product portfolio association (%s): empty response", tfservicecatalog.ProductPortfolioAssociationCreateID(acceptLanguage, portfolioID, productID)),
}
}

return output, servicecatalog.StatusAvailable, err
}
}
65 changes: 65 additions & 0 deletions aws/internal/service/servicecatalog/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ const (
PortfolioShareCreateTimeout = 3 * time.Minute

OrganizationsAccessStableTimeout = 3 * time.Minute
ConstraintReadyTimeout = 3 * time.Minute
ConstraintDeleteTimeout = 3 * time.Minute

ProductPortfolioAssociationReadyTimeout = 3 * time.Minute
ProductPortfolioAssociationDeleteTimeout = 3 * time.Minute

StatusNotFound = "NOT_FOUND"
StatusUnavailable = "UNAVAILABLE"
Expand Down Expand Up @@ -198,3 +203,63 @@ func OrganizationsAccessStable(conn *servicecatalog.ServiceCatalog) (string, err

return "", err
}

func ConstraintReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, id string) (*servicecatalog.DescribeConstraintOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{StatusNotFound, servicecatalog.StatusCreating, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable},
Refresh: ConstraintStatus(conn, acceptLanguage, id),
Timeout: ConstraintReadyTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*servicecatalog.DescribeConstraintOutput); ok {
return output, err
}

return nil, err
}

func ConstraintDeleted(conn *servicecatalog.ServiceCatalog, acceptLanguage, id string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{servicecatalog.StatusAvailable, servicecatalog.StatusCreating},
Target: []string{StatusNotFound},
Refresh: ConstraintStatus(conn, acceptLanguage, id),
Timeout: ConstraintDeleteTimeout,
}

_, err := stateConf.WaitForState()

return err
}

func ProductPortfolioAssociationReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, portfolioID, productID string) (*servicecatalog.PortfolioDetail, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable},
Refresh: ProductPortfolioAssociationStatus(conn, acceptLanguage, portfolioID, productID),
Timeout: ProductPortfolioAssociationReadyTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*servicecatalog.PortfolioDetail); ok {
return output, err
}

return nil, err
}

func ProductPortfolioAssociationDeleted(conn *servicecatalog.ServiceCatalog, acceptLanguage, portfolioID, productID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{servicecatalog.StatusAvailable},
Target: []string{StatusNotFound, StatusUnavailable},
Refresh: ProductPortfolioAssociationStatus(conn, acceptLanguage, portfolioID, productID),
Timeout: ProductPortfolioAssociationDeleteTimeout,
}

_, err := stateConf.WaitForState()

return err
}
2 changes: 2 additions & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1005,11 +1005,13 @@ func Provider() *schema.Provider {
"aws_securityhub_organization_admin_account": resourceAwsSecurityHubOrganizationAdminAccount(),
"aws_securityhub_product_subscription": resourceAwsSecurityHubProductSubscription(),
"aws_securityhub_standards_subscription": resourceAwsSecurityHubStandardsSubscription(),
"aws_servicecatalog_constraint": resourceAwsServiceCatalogConstraint(),
"aws_servicecatalog_organizations_access": resourceAwsServiceCatalogOrganizationsAccess(),
"aws_servicecatalog_portfolio": resourceAwsServiceCatalogPortfolio(),
"aws_servicecatalog_portfolio_share": resourceAwsServiceCatalogPortfolioShare(),
"aws_servicecatalog_product": resourceAwsServiceCatalogProduct(),
"aws_servicecatalog_tag_option": resourceAwsServiceCatalogTagOption(),
"aws_servicecatalog_product_portfolio_association": resourceAwsServiceCatalogProductPortfolioAssociation(),
"aws_service_discovery_http_namespace": resourceAwsServiceDiscoveryHttpNamespace(),
"aws_service_discovery_private_dns_namespace": resourceAwsServiceDiscoveryPrivateDnsNamespace(),
"aws_service_discovery_public_dns_namespace": resourceAwsServiceDiscoveryPublicDnsNamespace(),
Expand Down
Loading