Skip to content

Commit

Permalink
Merge pull request #39120 from jordanst3wart/feature-new-data-source-…
Browse files Browse the repository at this point in the history
…30992

feature: [New Data Source]: AWS Organizations descendant OUs
  • Loading branch information
ewbankkit authored Sep 3, 2024
2 parents 6e6321a + 18419fa commit 1046c82
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/39120.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_organizations_organizational_unit_descendant_organizational_units
```
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func dataSourceOrganizationalUnitsRead(ctx context.Context, d *schema.ResourceDa
children, err := findOrganizationalUnitsForParentByID(ctx, conn, parentID)

if err != nil {
return sdkdiag.AppendErrorf(diags, "listing Organizations Organization Units for parent (%s): %s", parentID, err)
return sdkdiag.AppendErrorf(diags, "listing Organizations Organizational Units for parent (%s): %s", parentID, err)
}

d.SetId(parentID)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package organizations

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/organizations"
awstypes "github.com/aws/aws-sdk-go-v2/service/organizations/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @SDKDataSource("aws_organizations_organizational_unit_descendant_organizational_units", name="Organizational Unit Descendant Organization Units")
func dataSourceOrganizationalUnitDescendantOrganizationalUnits() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceOrganizationalUnitDescendantOrganizationalUnitsRead,

Schema: map[string]*schema.Schema{
"children": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
names.AttrARN: {
Type: schema.TypeString,
Computed: true,
},
names.AttrID: {
Type: schema.TypeString,
Computed: true,
},
names.AttrName: {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"parent_id": {
Type: schema.TypeString,
Required: true,
},
},
}
}

func dataSourceOrganizationalUnitDescendantOrganizationalUnitsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).OrganizationsClient(ctx)

parentID := d.Get("parent_id").(string)
organizationUnits, err := findAllOrganizationalUnitsForParentAndBelow(ctx, conn, parentID)

if err != nil {
return sdkdiag.AppendErrorf(diags, "listing Organizations Organizational Units for parent (%s) and descendants: %s", parentID, err)
}

d.SetId(parentID)

if err := d.Set("children", flattenOrganizationalUnits(organizationUnits)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting children: %s", err)
}

return diags
}

// findAllOrganizationalUnitsForParentAndBelow recurses down an OU tree, returning all organizational units at the specified parent and below.
func findAllOrganizationalUnitsForParentAndBelow(ctx context.Context, conn *organizations.Client, id string) ([]awstypes.OrganizationalUnit, error) {
var output []awstypes.OrganizationalUnit

ous, err := findOrganizationalUnitsForParentByID(ctx, conn, id)

if err != nil {
return nil, err
}

output = append(output, ous...)

for _, ou := range ous {
organizationUnits, err := findAllOrganizationalUnitsForParentAndBelow(ctx, conn, aws.ToString(ou.Id))

if err != nil {
return nil, err
}

output = append(output, organizationUnits...)
}

return output, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package organizations_test

import (
"fmt"
"testing"

sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/names"
)

func testOrganizationalUnitDescendantOUsDataSource_basic(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
topOUDataSourceName := "data.aws_organizations_organizational_unit_descendant_organizational_units.current"
newOU1DataSourceName := "data.aws_organizations_organizational_unit_descendant_organizational_units.test0"
newOU2DataSourceName := "data.aws_organizations_organizational_unit_descendant_organizational_units.test1"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckOrganizationManagementAccount(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.OrganizationsServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: testOrganizationalUnitDescendantOusDataSourceConfig_basic(rName),
Check: resource.ComposeAggregateTestCheckFunc(
acctest.CheckResourceAttrGreaterThanOrEqualValue(topOUDataSourceName, "children.#", 2),
resource.TestCheckResourceAttr(newOU1DataSourceName, "children.#", acctest.Ct1),
resource.TestCheckResourceAttr(newOU2DataSourceName, "children.#", acctest.Ct0),
),
},
},
})
}

func testOrganizationalUnitDescendantOusDataSourceConfig_basic(rName string) string {
return fmt.Sprintf(`
data "aws_organizations_organization" "current" {}
resource "aws_organizations_organizational_unit" "test0" {
name = "%[1]s-0"
parent_id = data.aws_organizations_organization.current.roots[0].id
}
resource "aws_organizations_organizational_unit" "test1" {
name = "%[1]s-1"
parent_id = aws_organizations_organizational_unit.test0.id
}
data "aws_organizations_organizational_unit_descendant_organizational_units" "current" {
parent_id = data.aws_organizations_organization.current.roots[0].id
depends_on = [aws_organizations_organizational_unit.test0, aws_organizations_organizational_unit.test1]
}
data "aws_organizations_organizational_unit_descendant_organizational_units" "test0" {
parent_id = aws_organizations_organizational_unit.test0.id
depends_on = [aws_organizations_organizational_unit.test1]
}
data "aws_organizations_organizational_unit_descendant_organizational_units" "test1" {
parent_id = aws_organizations_organizational_unit.test1.id
}
`, rName)
}
1 change: 1 addition & 0 deletions internal/service/organizations/organizations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func TestAccOrganizations_serial(t *testing.T) {
"update": testAccOrganizationalUnit_update,
"tags": testAccOrganizationalUnit_tags,
"DataSource_basic": testAccOrganizationalUnitDataSource_basic,
"DescendantOUsDataSource_basic": testOrganizationalUnitDescendantOUsDataSource_basic,
"ChildAccountsDataSource_basic": testAccOrganizationalUnitChildAccountsDataSource_basic,
"DescendantAccountsDataSource_basic": testAccOrganizationalUnitDescendantAccountsDataSource_basic,
"PluralDataSource_basic": testAccOrganizationalUnitsDataSource_basic,
Expand Down
5 changes: 5 additions & 0 deletions internal/service/organizations/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
subcategory: "Organizations"
layout: "aws"
page_title: "AWS: aws_organizations_organizational_unit_descendant_organizational_units"
description: |-
Get all direct child organizational units under a parent organizational unit. This provides all children.
---

# Data Source: aws_organizations_organizational_unit_descendant_organizational_units

Get all direct child organizational units under a parent organizational unit. This provides all children.

## Example Usage

```terraform
data "aws_organizations_organization" "org" {}
data "aws_organizations_organizational_unit_descendant_organizational_units" "ous" {
parent_id = data.aws_organizations_organization.org.roots[0].id
}
```

## Argument Reference

* `parent_id` - (Required) Parent ID of the organizational unit.

## Attribute Reference

This data source exports the following attributes in addition to the arguments above:

* `children` - List of child organizational units, which have the following attributes:
* `arn` - ARN of the organizational unit
* `name` - Name of the organizational unit
* `id` - ID of the organizational unit
* `id` - Parent identifier of the organizational units.

0 comments on commit 1046c82

Please sign in to comment.