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

Service Catalog PortfolioPrincipalAssociation resource added #13837

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
f6321f3
refactoring artifact definition
bw-intuit Oct 25, 2017
8915edc
wip adding artifact block
bw-intuit Oct 26, 2017
f365893
refactoring to support new format
bw-intuit Nov 13, 2017
bfa2bc2
minor code cleanup
bw-intuit Nov 13, 2017
9227706
update based on code review
bw-intuit Apr 9, 2018
9370c2d
updates based on code review
bw-intuit Apr 10, 2018
0e57346
refactoring to updated template structure
bw-intuit May 3, 2018
07107de
fix test
bw-intuit May 3, 2018
ea45424
minor code / test cleanup
bw-intuit May 3, 2018
051a1a0
adding comment
bw-intuit May 3, 2018
5179004
reading template url, fix import
bw-intuit May 3, 2018
88f81f0
refactored, added acceptance tests and documentation
trung Jun 21, 2018
22148da
minor fixes
trung Jun 25, 2018
8870e42
initial testing
May 23, 2020
e887f5f
hope and prayer
May 23, 2020
b261bbd
found the work of @trung and getting it up and running
May 23, 2020
c01782c
intial creation working
May 25, 2020
bea44a7
updates
May 26, 2020
383dbfd
Merge remote-tracking branch 'trung/f-service-catalog' into sc-produc…
ahgittin Jun 12, 2020
975fd2d
Merge remote-tracking branch 'frc9/master' into sc-product-and-pp
ahgittin Jun 12, 2020
848689c
Merge branch 'master' into sc-product-and-pp
ahgittin Jun 12, 2020
413cd8a
update servicecatalog_product helper imports
kemitix Jun 11, 2020
dee8315
revert go.mod and go.sum
ahgittin Jun 12, 2020
56493a6
fix error handling on PP
ahgittin Jun 12, 2020
1d8c7a6
fix syntax errors in servicecatalog product tests
ahgittin Jun 12, 2020
bfaadb1
include TODO items for things not supported on product
ahgittin Jun 12, 2020
243dc9a
provisioned product - create, read, and delete minimally working
ahgittin Jun 12, 2020
440ef4b
Merge branch 'master' into sc-product-and-pp
kemitix Jun 15, 2020
676b9d0
sc-product: define timeouts for update and delete operations
kemitix Jun 15, 2020
eb1a397
sc-product: generate idempotencyToken as resource id
kemitix Jun 15, 2020
258271d
sc-product: extract waitFor…Status method
kemitix Jun 15, 2020
93fbd22
sc-provisioned-product: add wait for resource to create
kemitix Jun 15, 2020
24f04a2
Merge remote-tracking branch 'origin/master' into sc-product-and-pp
ahgittin Jun 15, 2020
1818eac
minor corrections to product doc, and add a useful "complete" example
ahgittin Jun 15, 2020
3b98f38
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 15, 2020
63763ef
sc-product-portfolio-assoc: crud
kemitix Jun 15, 2020
7a15c8c
add docs for service catalog provisioned product and portfolio-produc…
ahgittin Jun 16, 2020
222fea6
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 16, 2020
971ac5b
sc-product-portfolio-assoc: cast ids to string early
kemitix Jun 16, 2020
edc5efd
sc-product-portfolio-assoc: fetch all pages ListPortfoliosForProduct
kemitix Jun 16, 2020
b24619a
sc-product-portfolio-assoc: rename methods to fit existing pattern
kemitix Jun 16, 2020
25ab24a
update PP and add'l fields
ahgittin Jun 16, 2020
07c104a
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 16, 2020
610384d
SC PP - support params, tags; better wait logic
ahgittin Jun 16, 2020
4e025ed
SC - Product - wait for completion of tasks, not just submission
ahgittin Jun 16, 2020
3c661c6
sc-product-portfolio-assoc: register in provider.go
kemitix Jun 16, 2020
1b8d9f3
sc-product-portfolio-assoc: first pass at basic test
kemitix Jun 16, 2020
e1327f5
wait for, and test, deletion of SC Product and SC ProvisionedProduct
ahgittin Jun 16, 2020
515b1cd
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 16, 2020
0b7e87e
sc-product-portfolio-assoc: minor updates to docs
kemitix Jun 16, 2020
7377257
fix ID syntax for portfolio-product-association -- all tests passing,…
ahgittin Jun 16, 2020
c94fab4
sc-product-portfolio-assoc: revert to standard format for arguments
kemitix Jun 16, 2020
035dfac
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 16, 2020
59fa151
sc-provisioned-product: fix typo in docs
kemitix Jun 16, 2020
c34bb97
add portfolio-principal association, and use it for product provision…
ahgittin Jun 16, 2020
d22fcd8
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 17, 2020
888aa0b
sc-portfolio-assocs: Add todo notes to reduce api calls
kemitix Jun 17, 2020
06af8fb
sc-portfolio-assocs: only fetch pages when assoc not yet found
kemitix Jun 17, 2020
9294fb1
fix the product provisioning test, ensure use of separate providers a…
ahgittin Jun 17, 2020
80ff8af
Merge branch 'sc-product-and-pp' of github.com:cloudsoft/terraform-pr…
ahgittin Jun 17, 2020
f096f5d
Merge branch 'master' into sc-product-and-pp
ahgittin Jun 17, 2020
f5ca63e
SC provisioned-product test passing!
ahgittin Jun 17, 2020
ae3e74d
tidy up - merge util class with the (only) place it is used
ahgittin Jun 17, 2020
bc84989
apply gofmt
ahgittin Jun 17, 2020
9793677
SC - more miny tidies and explanations
ahgittin Jun 17, 2020
b8b8b4b
shorten prefixes to fit within 20 char limit
ahgittin Jun 17, 2020
866f047
fix most linter-flagged issues
ahgittin Jun 17, 2020
19fca67
address go lint issues
ahgittin Jun 17, 2020
603d288
address linter issues in docs page (deprecated frontmatter)
ahgittin Jun 17, 2020
eee00a1
SC - address first round of PR review comments
ahgittin Jun 18, 2020
08716d3
revert the index files - not to have any SC items (to avoid merge con…
ahgittin Jun 18, 2020
70ac64a
remove provisioned product additions for now, focus on incremental PRs
ahgittin Jun 18, 2020
625c9b7
remove portfolio-principal-association additions for now, focus on in…
ahgittin Jun 18, 2020
2dcb083
remove portfolio-product-association additions for now, focus on incr…
ahgittin Jun 18, 2020
85d33e4
remove product additions and portfolio changes for now, focus on incr…
ahgittin Jun 18, 2020
8cfecab
restore portfolio-principal-association additions for now, focus on i…
ahgittin Jun 18, 2020
46303a4
add portfolio-principal association to index files
ahgittin Jun 18, 2020
a7f6049
add and update all tests, all passing
ahgittin Jun 19, 2020
ccba736
Fix two linter problems
ahgittin Jun 19, 2020
11d3c81
update portfolio_principal_association_test method names to match pre…
ahgittin Jun 22, 2020
40a91d1
SC Portfolio Principal Association - tests updated
ahgittin Jul 21, 2020
87e6ab0
SC Portfolio Principal Association - conform markdown examples to ter…
ahgittin Jul 21, 2020
fd79364
Merge branch 'master' into f-servicecatalog-portfolio-principal-assoc…
ahgittin Jul 21, 2020
f1b3c20
SC Portfolio Principal Association - test for principal existence
ahgittin Jul 21, 2020
be3065b
SC Portfolio Principal Association - format tidy
ahgittin Jul 21, 2020
1294114
SC Portfolio Principal Association - fix principal check
ahgittin Jul 21, 2020
33be215
Merge branch 'master' into f-servicecatalog-portfolio-principal-assoc…
ahgittin Sep 26, 2020
c8bae8b
Update imports to use v2/ of plugin SDK
ahgittin Sep 26, 2020
08e3b91
fix trailing spaces in markdown
ahgittin Sep 26, 2020
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
1 change: 1 addition & 0 deletions aws/provider.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,7 @@ func Provider() *schema.Provider {
"aws_securityhub_product_subscription": resourceAwsSecurityHubProductSubscription(),
"aws_securityhub_standards_subscription": resourceAwsSecurityHubStandardsSubscription(),
"aws_servicecatalog_portfolio": resourceAwsServiceCatalogPortfolio(),
"aws_servicecatalog_portfolio_principal_association": resourceAwsServiceCatalogPortfolioPrincipalAssociation(),
"aws_service_discovery_http_namespace": resourceAwsServiceDiscoveryHttpNamespace(),
"aws_service_discovery_private_dns_namespace": resourceAwsServiceDiscoveryPrivateDnsNamespace(),
"aws_service_discovery_public_dns_namespace": resourceAwsServiceDiscoveryPublicDnsNamespace(),
Expand Down
14 changes: 12 additions & 2 deletions aws/resource_aws_servicecatalog_portfolio.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,19 @@ func resourceAwsServiceCatalogPortfolioDelete(d *schema.ResourceData, meta inter
input.Id = aws.String(d.Id())

log.Printf("[DEBUG] Delete Service Catalog Portfolio: %#v", input)
_, err := conn.DeletePortfolio(&input)
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
_, err := conn.DeletePortfolio(&input)
if err != nil {
if isAWSErr(err, servicecatalog.ErrCodeResourceInUseException, "") {
// delay and retry, other things eg associations might still be getting deleted
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
if err != nil {
return fmt.Errorf("Deleting Service Catalog Portfolio '%s' failed: %s", *input.Id, err.Error())
return fmt.Errorf("Deleting Service Catalog Portfolio '%s' failed: %s", *input.Id, err)
}
return nil
}
174 changes: 174 additions & 0 deletions aws/resource_aws_servicecatalog_portfolio_principal_association.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package aws

import (
"fmt"
"log"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/servicecatalog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceAwsServiceCatalogPortfolioPrincipalAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceAwsServiceCatalogPortfolioPrincipalAssociationCreate,
Read: resourceAwsServiceCatalogPortfolioPrincipalAssociationRead,
Delete: resourceAwsServiceCatalogPortfolioPrincipalAssociationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},
Schema: map[string]*schema.Schema{
"portfolio_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"principal_arn": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateArn,
ForceNew: true,
},
},
}
}

func resourceAwsServiceCatalogPortfolioPrincipalAssociationCreate(d *schema.ResourceData, meta interface{}) error {
_, portfolioId, principalArn, err := resourceAwsServiceCatalogPortfolioPrincipalAssociationRequiredParameters(d)
if err != nil {
return err
}
input := servicecatalog.AssociatePrincipalWithPortfolioInput{
PortfolioId: aws.String(portfolioId),
PrincipalARN: aws.String(principalArn),
PrincipalType: aws.String(servicecatalog.PrincipalTypeIam),
}
conn := meta.(*AWSClient).scconn
_, err = conn.AssociatePrincipalWithPortfolio(&input)
if err != nil {
return fmt.Errorf("creating Service Catalog Principal(%s)/Portfolio(%s) Association failed: %s",
principalArn, portfolioId, err.Error())
}

return resourceAwsServiceCatalogPortfolioPrincipalAssociationRead(d, meta)
}

func resourceAwsServiceCatalogPortfolioPrincipalAssociationRead(d *schema.ResourceData, meta interface{}) error {
id, portfolioId, principalArn, err := resourceAwsServiceCatalogPortfolioPrincipalAssociationRequiredParameters(d)
if err != nil {
return err
}
input := servicecatalog.ListPrincipalsForPortfolioInput{
PortfolioId: aws.String(portfolioId),
}
conn := meta.(*AWSClient).scconn
isFound := false

// listing principals for portfolio is a paginated operation
// and if a principal has recently been added, it can contain the ID while it is stabilising,
// so we retry for up to 1 minute if it is stabilising and the ARN we are looking for is not found
err = resource.Retry(1*time.Minute, func() *resource.RetryError {
var pageToken = ""
for {
nonArnFound := false
pageOfDetails, nextPageToken, err := resourceAwsServiceCatalogPortfolioPrincipalAssociationListPrincipalsForPortfolioPage(conn, input, &pageToken)
if err != nil {
return resource.NonRetryableError(err)
}
for _, principal := range pageOfDetails {
if aws.StringValue(principal.PrincipalARN) == principalArn {
isFound = true
return nil
}
if !strings.HasPrefix(aws.StringValue(principal.PrincipalARN), "arn:") {
nonArnFound = true
}
}
if nextPageToken == nil {
if nonArnFound {
log.Printf("[DEBUG] Service Catalog Principal(%s)/Portfolio(%s) Association not found, but principals detected as stabilizing",
principalArn, portfolioId)
return resource.RetryableError(fmt.Errorf("Principals stabilizing"))
} else {
return nil
}
}
pageToken = aws.StringValue(nextPageToken)
}
})
if err != nil {
return err
}
if isFound {
d.SetId(id)
} else {
log.Printf("[WARN] Service Catalog Principal(%s)/Portfolio(%s) Association not found, removing from state",
principalArn, portfolioId)
d.SetId("")
}
d.Set("principal_arn", principalArn)
d.Set("portfolio_id", portfolioId)
return nil
}

func resourceAwsServiceCatalogPortfolioPrincipalAssociationListPrincipalsForPortfolioPage(conn *servicecatalog.ServiceCatalog, input servicecatalog.ListPrincipalsForPortfolioInput, nextPageToken *string) ([]*servicecatalog.Principal, *string, error) {
input.PageToken = nextPageToken
var page, err = conn.ListPrincipalsForPortfolio(&input)
if err != nil {
return nil, nil, fmt.Errorf("retrieving Service Catalog Associations for Principal/Portfolios: %s", err.Error())
}
principalDetails := page.Principals
return principalDetails, page.NextPageToken, nil
}

func resourceAwsServiceCatalogPortfolioPrincipalAssociationDelete(d *schema.ResourceData, meta interface{}) error {
_, portfolioId, principalArn, err := resourceAwsServiceCatalogPortfolioPrincipalAssociationRequiredParameters(d)
if err != nil {
return err
}
input := servicecatalog.DisassociatePrincipalFromPortfolioInput{
PortfolioId: aws.String(portfolioId),
PrincipalARN: aws.String(principalArn),
}
conn := meta.(*AWSClient).scconn
_, err = conn.DisassociatePrincipalFromPortfolio(&input)
if err != nil {
return fmt.Errorf("deleting Service Catalog Principal(%s)/Portfolio(%s) Association failed: %s",
principalArn, portfolioId, err.Error())
}
return nil
}

func resourceAwsServiceCatalogPortfolioPrincipalAssociationRequiredParameters(d *schema.ResourceData) (string, string, string, error) {
// ":" recommended as separator where multiple fields needed to uniquely identify and import, based on https://www.terraform.io/docs/extend/resources/import.html#importer-state-function
// (as in this case where AWS doesn't treat this association as a first class resource; it has no AWS identifier)
// this is not a valid "identifier" character according to https://www.terraform.io/docs/configuration/syntax.html#identifiers
// but that does not seem to apply to this internal "id"
principalArn, ok := d.GetOk("principal_arn")
portfolioId, ok2 := d.GetOk("portfolio_id")
if ok && ok2 {
id := portfolioId.(string) + ":" + principalArn.(string)
return id, portfolioId.(string), principalArn.(string), nil
} else if ok || ok2 {
return "", "", "", fmt.Errorf("Invalid state - principal_arn and portfolio_id must both be set or neither set to infer from ID")
} else if d.Id() != "" {
return parseServiceCatalogPortfolioPrincipalAssociationResourceId(d.Id())
} else {
return "", "", "", fmt.Errorf("Invalid state - principal_arn and portfolio_id must be set, or ID set to import")
}
}

func parseServiceCatalogPortfolioPrincipalAssociationResourceId(id string) (string, string, string, error) {
s := strings.SplitN(id, ":", 2)
if len(s) != 2 {
return "", "", "", fmt.Errorf("Invalid ID '%s' - should be of format <portfolio_id>:<principal-arn>", id)
}
return id, s[0], s[1], nil
}
Loading