Skip to content

Commit

Permalink
Merge pull request #19470 from hashicorp/f-servicecat-principal-portf…
Browse files Browse the repository at this point in the history
…olio-association

r/servicecatalog_principal_portfolio_association: New resource
  • Loading branch information
YakDriver authored Jun 2, 2021
2 parents 3725755 + 3fdc4b7 commit fa84016
Show file tree
Hide file tree
Showing 24 changed files with 610 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .changelog/19470.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_servicecatalog_principal_portfolio_association
```
2 changes: 1 addition & 1 deletion aws/data_source_aws_servicecatalog_constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func dataSourceAwsServiceCatalogConstraint() *schema.Resource {
"accept_language": {
Type: schema.TypeString,
Optional: true,
Default: "en",
Default: tfservicecatalog.AcceptLanguageEnglish,
ValidateFunc: validation.StringInSlice(tfservicecatalog.AcceptLanguage_Values(), false),
},
"description": {
Expand Down
12 changes: 6 additions & 6 deletions aws/internal/service/servicecatalog/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package servicecatalog
const (
// If AWS adds these to the API, we should use those and remove these.

ServiceCatalogAcceptLanguageEnglish = "en"
ServiceCatalogAcceptLanguageJapanese = "jp"
ServiceCatalogAcceptLanguageChinese = "zh"
AcceptLanguageEnglish = "en"
AcceptLanguageJapanese = "jp"
AcceptLanguageChinese = "zh"

ConstraintTypeLaunch = "LAUNCH"
ConstraintTypeNotification = "NOTIFICATION"
Expand All @@ -16,9 +16,9 @@ const (

func AcceptLanguage_Values() []string {
return []string{
ServiceCatalogAcceptLanguageEnglish,
ServiceCatalogAcceptLanguageJapanese,
ServiceCatalogAcceptLanguageChinese,
AcceptLanguageEnglish,
AcceptLanguageJapanese,
AcceptLanguageChinese,
}
}

Expand Down
33 changes: 33 additions & 0 deletions aws/internal/service/servicecatalog/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,36 @@ func TagOptionResourceAssociation(conn *servicecatalog.ServiceCatalog, tagOption

return result, err
}

func PrincipalPortfolioAssociation(conn *servicecatalog.ServiceCatalog, acceptLanguage, principalARN, portfolioID string) (*servicecatalog.Principal, error) {
input := &servicecatalog.ListPrincipalsForPortfolioInput{
PortfolioId: aws.String(portfolioID),
}

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

var result *servicecatalog.Principal

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

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

if aws.StringValue(deet.PrincipalARN) == principalARN {
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 @@ -73,3 +73,17 @@ func ProvisioningArtifactParseID(id string) (string, string, error) {
}
return parts[0], parts[1], nil
}

func PrincipalPortfolioAssociationParseID(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,principalARN,portfolioID", id)
}

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

func PrincipalPortfolioAssociationID(acceptLanguage, principalARN, portfolioID string) string {
return strings.Join([]string{acceptLanguage, principalARN, portfolioID}, ",")
}
20 changes: 20 additions & 0 deletions aws/internal/service/servicecatalog/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,23 @@ func ProvisioningArtifactStatus(conn *servicecatalog.ServiceCatalog, id, product
return output, aws.StringValue(output.Status), err
}
}

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

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

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

if output == nil {
return nil, StatusNotFound, err
}

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

PrincipalPortfolioAssociationReadyTimeout = 3 * time.Minute
PrincipalPortfolioAssociationDeleteTimeout = 3 * time.Minute

StatusNotFound = "NOT_FOUND"
StatusUnavailable = "UNAVAILABLE"

Expand Down Expand Up @@ -407,3 +410,36 @@ func ProvisioningArtifactDeleted(conn *servicecatalog.ServiceCatalog, id, produc

return nil
}

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,
}

outputRaw, err := stateConf.WaitForState()

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

return nil, err
}

func PrincipalPortfolioAssociationDeleted(conn *servicecatalog.ServiceCatalog, acceptLanguage, principalARN, portfolioID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{servicecatalog.StatusAvailable},
Target: []string{StatusNotFound, StatusUnavailable},
Refresh: PrincipalPortfolioAssociationStatus(conn, acceptLanguage, principalARN, portfolioID),
Timeout: PrincipalPortfolioAssociationDeleteTimeout,
NotFoundChecks: 1,
}

_, err := stateConf.WaitForState()

return err
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,7 @@ func Provider() *schema.Provider {
"aws_servicecatalog_service_action": resourceAwsServiceCatalogServiceAction(),
"aws_servicecatalog_tag_option": resourceAwsServiceCatalogTagOption(),
"aws_servicecatalog_tag_option_resource_association": resourceAwsServiceCatalogTagOptionResourceAssociation(),
"aws_servicecatalog_principal_portfolio_association": resourceAwsServiceCatalogPrincipalPortfolioAssociation(),
"aws_servicecatalog_product_portfolio_association": resourceAwsServiceCatalogProductPortfolioAssociation(),
"aws_servicecatalog_provisioning_artifact": resourceAwsServiceCatalogProvisioningArtifact(),
"aws_service_discovery_http_namespace": resourceAwsServiceDiscoveryHttpNamespace(),
Expand Down
4 changes: 2 additions & 2 deletions aws/resource_aws_servicecatalog_constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func resourceAwsServiceCatalogConstraint() *schema.Resource {
"accept_language": {
Type: schema.TypeString,
Optional: true,
Default: "en",
Default: tfservicecatalog.AcceptLanguageEnglish,
ValidateFunc: validation.StringInSlice(tfservicecatalog.AcceptLanguage_Values(), false),
},
"description": {
Expand Down Expand Up @@ -151,7 +151,7 @@ func resourceAwsServiceCatalogConstraintRead(d *schema.ResourceData, meta interf
acceptLanguage := d.Get("accept_language").(string)

if acceptLanguage == "" {
acceptLanguage = "en"
acceptLanguage = tfservicecatalog.AcceptLanguageEnglish
}

d.Set("accept_language", acceptLanguage)
Expand Down
3 changes: 2 additions & 1 deletion aws/resource_aws_servicecatalog_constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
tfservicecatalog "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/servicecatalog"
)

// add sweeper to delete known test servicecat constraints
Expand Down Expand Up @@ -106,7 +107,7 @@ func TestAccAWSServiceCatalogConstraint_basic(t *testing.T) {
Config: testAccAWSServiceCatalogConstraintConfig_basic(rName, rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsServiceCatalogConstraintExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "accept_language", "en"),
resource.TestCheckResourceAttr(resourceName, "accept_language", tfservicecatalog.AcceptLanguageEnglish),
resource.TestCheckResourceAttr(resourceName, "description", rName),
resource.TestCheckResourceAttr(resourceName, "type", "NOTIFICATION"),
resource.TestCheckResourceAttrPair(resourceName, "portfolio_id", "aws_servicecatalog_portfolio.test", "id"),
Expand Down
7 changes: 4 additions & 3 deletions aws/resource_aws_servicecatalog_portfolio.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
tfservicecatalog "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/servicecatalog"
)

func resourceAwsServiceCatalogPortfolio() *schema.Resource {
Expand Down Expand Up @@ -68,7 +69,7 @@ func resourceAwsServiceCatalogPortfolioCreate(d *schema.ResourceData, meta inter
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{})))
input := servicecatalog.CreatePortfolioInput{
AcceptLanguage: aws.String("en"),
AcceptLanguage: aws.String(tfservicecatalog.AcceptLanguageEnglish),
DisplayName: aws.String(d.Get("name").(string)),
IdempotencyToken: aws.String(resource.UniqueId()),
Tags: tags.IgnoreAws().ServicecatalogTags(),
Expand Down Expand Up @@ -98,7 +99,7 @@ func resourceAwsServiceCatalogPortfolioRead(d *schema.ResourceData, meta interfa
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

input := servicecatalog.DescribePortfolioInput{
AcceptLanguage: aws.String("en"),
AcceptLanguage: aws.String(tfservicecatalog.AcceptLanguageEnglish),
}
input.Id = aws.String(d.Id())

Expand Down Expand Up @@ -138,7 +139,7 @@ func resourceAwsServiceCatalogPortfolioRead(d *schema.ResourceData, meta interfa
func resourceAwsServiceCatalogPortfolioUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).scconn
input := servicecatalog.UpdatePortfolioInput{
AcceptLanguage: aws.String("en"),
AcceptLanguage: aws.String(tfservicecatalog.AcceptLanguageEnglish),
Id: aws.String(d.Id()),
}

Expand Down
2 changes: 1 addition & 1 deletion aws/resource_aws_servicecatalog_portfolio_share.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func resourceAwsServiceCatalogPortfolioShare() *schema.Resource {
"accept_language": {
Type: schema.TypeString,
Optional: true,
Default: "en",
Default: tfservicecatalog.AcceptLanguageEnglish,
ValidateFunc: validation.StringInSlice(tfservicecatalog.AcceptLanguage_Values(), false),
},
"accepted": {
Expand Down
5 changes: 3 additions & 2 deletions aws/resource_aws_servicecatalog_portfolio_share_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
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 All @@ -34,7 +35,7 @@ func TestAccAWSServiceCatalogPortfolioShare_basic(t *testing.T) {
Config: testAccAWSServiceCatalogPortfolioShareConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsServiceCatalogPortfolioShareExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "accept_language", "en"),
resource.TestCheckResourceAttr(resourceName, "accept_language", tfservicecatalog.AcceptLanguageEnglish),
resource.TestCheckResourceAttr(resourceName, "accepted", "false"),
resource.TestCheckResourceAttrPair(resourceName, "principal_id", dataSourceName, "account_id"),
resource.TestCheckResourceAttrPair(resourceName, "portfolio_id", compareName, "id"),
Expand Down Expand Up @@ -74,7 +75,7 @@ func TestAccAWSServiceCatalogPortfolioShare_organizationalUnit(t *testing.T) {
Config: testAccAWSServiceCatalogPortfolioShareConfig_organizationalUnit(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsServiceCatalogPortfolioShareExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "accept_language", "en"),
resource.TestCheckResourceAttr(resourceName, "accept_language", tfservicecatalog.AcceptLanguageEnglish),
resource.TestCheckResourceAttr(resourceName, "accepted", "true"),
resource.TestCheckResourceAttrPair(resourceName, "principal_id", "aws_organizations_organizational_unit.test", "id"),
resource.TestCheckResourceAttrPair(resourceName, "portfolio_id", compareName, "id"),
Expand Down
Loading

0 comments on commit fa84016

Please sign in to comment.