Skip to content

Commit

Permalink
add default tags support
Browse files Browse the repository at this point in the history
  • Loading branch information
anGie44 committed Apr 22, 2021
1 parent f3e53a1 commit fa8f776
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 34 deletions.
78 changes: 45 additions & 33 deletions aws/resource_aws_organizations_organizational_unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

func resourceAwsOrganizationsOrganizationalUnit() *schema.Resource {
Expand Down Expand Up @@ -65,57 +66,58 @@ func resourceAwsOrganizationsOrganizationalUnit() *schema.Resource {
Required: true,
ValidateFunc: validation.StringMatch(regexp.MustCompile("^(r-[0-9a-z]{4,32})|(ou-[0-9a-z]{4,32}-[a-z0-9]{8,32})$"), "see https://docs.aws.amazon.com/organizations/latest/APIReference/API_CreateOrganizationalUnit.html#organizations-CreateOrganizationalUnit-request-ParentId"),
},
"tags": tagsSchema(),
"tags": tagsSchema(),
"tags_all": tagsSchemaComputed(),
},

CustomizeDiff: SetTagsDiff,
}
}

func resourceAwsOrganizationsOrganizationalUnitCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).organizationsconn
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{})))

// Create the organizational unit
createOpts := &organizations.CreateOrganizationalUnitInput{
Name: aws.String(d.Get("name").(string)),
ParentId: aws.String(d.Get("parent_id").(string)),
Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().OrganizationsTags(),
Tags: tags.IgnoreAws().OrganizationsTags(),
}

log.Printf("[DEBUG] Organizational Unit create config: %#v", createOpts)

var err error
var resp *organizations.CreateOrganizationalUnitOutput
err = resource.Retry(4*time.Minute, func() *resource.RetryError {
resp, err = conn.CreateOrganizationalUnit(createOpts)

if err != nil {
if isAWSErr(err, organizations.ErrCodeFinalizingOrganizationException, "") {
log.Printf("[DEBUG] Trying to create Organizational Unit again: %q", err.Error())
return resource.RetryableError(err)
}
if tfawserr.ErrCodeEquals(err, organizations.ErrCodeFinalizingOrganizationException) {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})
if isResourceTimeoutError(err) {
if tfresource.TimedOut(err) {
resp, err = conn.CreateOrganizationalUnit(createOpts)
}

if err != nil {
return fmt.Errorf("Error creating Organizational Unit: %s", err)
return fmt.Errorf("error creating Organizations Organizational Unit: %w", err)
}
log.Printf("[DEBUG] Organizational Unit create response: %#v", resp)

// Store the ID
ouId := resp.OrganizationalUnit.Id
d.SetId(aws.StringValue(ouId))
d.SetId(aws.StringValue(resp.OrganizationalUnit.Id))

return resourceAwsOrganizationsOrganizationalUnitRead(d, meta)
}

func resourceAwsOrganizationsOrganizationalUnitRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).organizationsconn
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

describeOpts := &organizations.DescribeOrganizationalUnitInput{
Expand Down Expand Up @@ -154,8 +156,6 @@ func resourceAwsOrganizationsOrganizationalUnitRead(d *schema.ResourceData, meta
return fmt.Errorf("error listing Organizations Organizational Unit (%s) parents: %w", d.Id(), err)
}

log.Printf("[INFO] Listing Accounts for Organizational Unit: %s", d.Id())

var accounts []*organizations.Account
input := &organizations.ListAccountsForParentInput{
ParentId: aws.String(d.Id()),
Expand All @@ -168,11 +168,11 @@ func resourceAwsOrganizationsOrganizationalUnitRead(d *schema.ResourceData, meta
})

if err != nil {
return fmt.Errorf("error listing AWS Organizations Organizational Unit (%s) accounts: %s", d.Id(), err)
return fmt.Errorf("error listing Organizations Organizational Unit (%s) accounts: %w", d.Id(), err)
}

if err := d.Set("accounts", flattenOrganizationsOrganizationalUnitAccounts(accounts)); err != nil {
return fmt.Errorf("error setting accounts: %s", err)
return fmt.Errorf("error setting accounts: %w", err)
}

d.Set("arn", ou.Arn)
Expand All @@ -182,11 +182,18 @@ func resourceAwsOrganizationsOrganizationalUnitRead(d *schema.ResourceData, meta
tags, err := keyvaluetags.OrganizationsListTags(conn, d.Id())

if err != nil {
return fmt.Errorf("error listing tags for AWS Organizational Unit (%s): %s", d.Id(), err)
return fmt.Errorf("error listing tags for Organizations Organizational Unit (%s): %w", d.Id(), err)
}

tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
}

if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
if err := d.Set("tags_all", tags.Map()); err != nil {
return fmt.Errorf("error setting tags_all: %w", err)
}

return nil
Expand All @@ -201,19 +208,17 @@ func resourceAwsOrganizationsOrganizationalUnitUpdate(d *schema.ResourceData, me
OrganizationalUnitId: aws.String(d.Id()),
}

log.Printf("[DEBUG] Organizational Unit update config: %#v", updateOpts)
resp, err := conn.UpdateOrganizationalUnit(updateOpts)
_, err := conn.UpdateOrganizationalUnit(updateOpts)
if err != nil {
return fmt.Errorf("Error updating Organizational Unit: %s", err)
return fmt.Errorf("error updating Organizations Organizational Unit (%s): %w", d.Id(), err)
}
log.Printf("[DEBUG] Organizational Unit update response: %#v", resp)
}

if d.HasChange("tags") {
o, n := d.GetChange("tags")
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := keyvaluetags.OrganizationsUpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating Organizational Unit (%s) tags: %s", d.Id(), err)
return fmt.Errorf("error updating Organizations Organizational Unit (%s) tags: %w", d.Id(), err)
}
}

Expand All @@ -226,14 +231,17 @@ func resourceAwsOrganizationsOrganizationalUnitDelete(d *schema.ResourceData, me
input := &organizations.DeleteOrganizationalUnitInput{
OrganizationalUnitId: aws.String(d.Id()),
}
log.Printf("[DEBUG] Removing AWS Organizational Unit from organization: %s", input)

_, err := conn.DeleteOrganizationalUnit(input)

if tfawserr.ErrCodeEquals(err, organizations.ErrCodeOrganizationalUnitNotFoundException) {
return nil
}

if err != nil {
if isAWSErr(err, organizations.ErrCodeOrganizationalUnitNotFoundException, "") {
return nil
}
return err
return fmt.Errorf("error deleting Organizations Organizational Unit (%s): %w", d.Id(), err)
}

return nil
}

Expand All @@ -244,6 +252,10 @@ func resourceAwsOrganizationsOrganizationalUnitGetParentId(conn *organizations.O
var parents []*organizations.Parent

err := conn.ListParentsPages(input, func(page *organizations.ListParentsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

parents = append(parents, page.Parents...)

return !lastPage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The following arguments are supported:

* `name` - The name for the organizational unit
* `parent_id` - ID of the parent organizational unit, which may be the root
* `tags` - (Optional) Key-value map of resource tags.
* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

## Attributes Reference

Expand All @@ -38,6 +38,7 @@ In addition to all arguments above, the following attributes are exported:
* `name` - Name of the account
* `arn` - ARN of the organizational unit
* `id` - Identifier of the organization unit
* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block).

## Import

Expand Down

0 comments on commit fa8f776

Please sign in to comment.