Skip to content

Commit

Permalink
Merge pull request #19459 from hashicorp/f-servicecat-provisioned-pro…
Browse files Browse the repository at this point in the history
…duct

r/servicecatalog_provisioned_product: New resource
  • Loading branch information
YakDriver authored Jun 30, 2021
2 parents f2da30d + c410a9d commit 72b2317
Show file tree
Hide file tree
Showing 9 changed files with 1,349 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .changelog/19459.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_servicecatalog_provisioned_product
```
10 changes: 10 additions & 0 deletions aws/internal/keyvaluetags/servicecatalog_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,13 @@ func ServiceCatalogProductUpdateTags(conn *servicecatalog.ServiceCatalog, identi

return nil
}

func ServicecatalogRecordKeyValueTags(tags []*servicecatalog.RecordTag) KeyValueTags {
m := make(map[string]*string, len(tags))

for _, tag := range tags {
m[aws.StringValue(tag.Key)] = tag.Value
}

return New(m)
}
61 changes: 61 additions & 0 deletions aws/internal/service/servicecatalog/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,3 +356,64 @@ func LaunchPathsStatus(conn *servicecatalog.ServiceCatalog, acceptLanguage, prod
return summaries, servicecatalog.StatusAvailable, err
}
}

func ProvisionedProductStatus(conn *servicecatalog.ServiceCatalog, acceptLanguage, id, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &servicecatalog.DescribeProvisionedProductInput{}

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

// one or the other but not both
if id != "" {
input.Id = aws.String(id)
} else if name != "" {
input.Name = aws.String(name)
}

output, err := conn.DescribeProvisionedProduct(input)

if tfawserr.ErrCodeEquals(err, servicecatalog.ErrCodeResourceNotFoundException) {
return nil, StatusNotFound, err
}

if err != nil {
return nil, servicecatalog.StatusFailed, err
}

if output == nil || output.ProvisionedProductDetail == nil {
return nil, StatusNotFound, err
}

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

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

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

output, err := conn.DescribeRecord(input)

if tfawserr.ErrCodeEquals(err, servicecatalog.ErrCodeResourceNotFoundException) {
return nil, StatusNotFound, err
}

if err != nil {
return nil, servicecatalog.StatusFailed, err
}

if output == nil || output.RecordDetail == nil {
return nil, StatusNotFound, err
}

return output, aws.StringValue(output.RecordDetail.Status), err
}
}
130 changes: 104 additions & 26 deletions aws/internal/service/servicecatalog/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ const (

LaunchPathsReadyTimeout = 3 * time.Minute

ProvisionedProductReadyTimeout = 3 * time.Minute
ProvisionedProductDeleteTimeout = 3 * time.Minute

RecordReadyTimeout = 3 * time.Minute

MinTimeout = 2 * time.Second
NotFoundChecks = 5
ContinuousTargetOccurrence = 2

StatusNotFound = "NOT_FOUND"
StatusUnavailable = "UNAVAILABLE"

Expand All @@ -54,10 +63,13 @@ const (

func ProductReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, productID string) (*servicecatalog.DescribeProductAsAdminOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{servicecatalog.StatusCreating, StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable, StatusCreated},
Refresh: ProductStatus(conn, acceptLanguage, productID),
Timeout: ProductReadyTimeout,
Pending: []string{servicecatalog.StatusCreating, StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable, StatusCreated},
Refresh: ProductStatus(conn, acceptLanguage, productID),
Timeout: ProductReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand Down Expand Up @@ -223,10 +235,13 @@ func OrganizationsAccessStable(conn *servicecatalog.ServiceCatalog) (string, 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,
Pending: []string{StatusNotFound, servicecatalog.StatusCreating, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable},
Refresh: ConstraintStatus(conn, acceptLanguage, id),
Timeout: ConstraintReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand All @@ -253,10 +268,13 @@ func ConstraintDeleted(conn *servicecatalog.ServiceCatalog, acceptLanguage, id s

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,
Pending: []string{StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable},
Refresh: ProductPortfolioAssociationStatus(conn, acceptLanguage, portfolioID, productID),
Timeout: ProductPortfolioAssociationReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand Down Expand Up @@ -377,10 +395,13 @@ func TagOptionResourceAssociationDeleted(conn *servicecatalog.ServiceCatalog, ta

func ProvisioningArtifactReady(conn *servicecatalog.ServiceCatalog, id, productID string) (*servicecatalog.DescribeProvisioningArtifactOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{servicecatalog.StatusCreating, StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable, StatusCreated},
Refresh: ProvisioningArtifactStatus(conn, id, productID),
Timeout: ProvisioningArtifactReadyTimeout,
Pending: []string{servicecatalog.StatusCreating, StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable, StatusCreated},
Refresh: ProvisioningArtifactStatus(conn, id, productID),
Timeout: ProvisioningArtifactReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand Down Expand Up @@ -415,12 +436,13 @@ func ProvisioningArtifactDeleted(conn *servicecatalog.ServiceCatalog, id, produc

func PrincipalPortfolioAssociationReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, principalARN, portfolioID string) (*servicecatalog.Principal, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable},
Refresh: PrincipalPortfolioAssociationStatus(conn, acceptLanguage, principalARN, portfolioID),
Timeout: PrincipalPortfolioAssociationReadyTimeout,
NotFoundChecks: 5,
MinTimeout: 10 * time.Second,
Pending: []string{StatusNotFound, StatusUnavailable},
Target: []string{servicecatalog.StatusAvailable},
Refresh: PrincipalPortfolioAssociationStatus(conn, acceptLanguage, principalARN, portfolioID),
Timeout: PrincipalPortfolioAssociationReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand Down Expand Up @@ -448,10 +470,13 @@ func PrincipalPortfolioAssociationDeleted(conn *servicecatalog.ServiceCatalog, a

func LaunchPathsReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, productID string) ([]*servicecatalog.LaunchPathSummary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{StatusNotFound},
Target: []string{servicecatalog.StatusAvailable},
Refresh: LaunchPathsStatus(conn, acceptLanguage, productID),
Timeout: LaunchPathsReadyTimeout,
Pending: []string{StatusNotFound},
Target: []string{servicecatalog.StatusAvailable},
Refresh: LaunchPathsStatus(conn, acceptLanguage, productID),
Timeout: LaunchPathsReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand All @@ -462,3 +487,56 @@ func LaunchPathsReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, produ

return nil, err
}

func ProvisionedProductReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, id, name string) (*servicecatalog.DescribeProvisionedProductOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{StatusNotFound, StatusUnavailable, servicecatalog.ProvisionedProductStatusUnderChange, servicecatalog.ProvisionedProductStatusPlanInProgress},
Target: []string{servicecatalog.StatusAvailable},
Refresh: ProvisionedProductStatus(conn, acceptLanguage, id, name),
Timeout: ProvisionedProductReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()

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

return nil, err
}

func ProvisionedProductTerminated(conn *servicecatalog.ServiceCatalog, acceptLanguage, id, name string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{servicecatalog.StatusAvailable, servicecatalog.ProvisionedProductStatusUnderChange},
Target: []string{StatusNotFound, StatusUnavailable},
Refresh: ProvisionedProductStatus(conn, acceptLanguage, id, name),
Timeout: ProvisionedProductDeleteTimeout,
}

_, err := stateConf.WaitForState()

return err
}

func RecordReady(conn *servicecatalog.ServiceCatalog, acceptLanguage, id string) (*servicecatalog.DescribeRecordOutput, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{StatusNotFound, StatusUnavailable, servicecatalog.ProvisionedProductStatusUnderChange, servicecatalog.ProvisionedProductStatusPlanInProgress},
Target: []string{servicecatalog.RecordStatusSucceeded, servicecatalog.StatusAvailable},
Refresh: RecordStatus(conn, acceptLanguage, id),
Timeout: RecordReadyTimeout,
ContinuousTargetOccurence: ContinuousTargetOccurrence,
NotFoundChecks: NotFoundChecks,
MinTimeout: MinTimeout,
}

outputRaw, err := stateConf.WaitForState()

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

return nil, err
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,7 @@ func Provider() *schema.Provider {
"aws_servicecatalog_portfolio": resourceAwsServiceCatalogPortfolio(),
"aws_servicecatalog_portfolio_share": resourceAwsServiceCatalogPortfolioShare(),
"aws_servicecatalog_product": resourceAwsServiceCatalogProduct(),
"aws_servicecatalog_provisioned_product": resourceAwsServiceCatalogProvisionedProduct(),
"aws_servicecatalog_service_action": resourceAwsServiceCatalogServiceAction(),
"aws_servicecatalog_tag_option": resourceAwsServiceCatalogTagOption(),
"aws_servicecatalog_tag_option_resource_association": resourceAwsServiceCatalogTagOptionResourceAssociation(),
Expand Down
Loading

0 comments on commit 72b2317

Please sign in to comment.