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

Add support for organizations and organizational units for EC2 image builder distribution configuration #22104

7 changes: 7 additions & 0 deletions .changelog/22104.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_imagebuilder_distribution_configuration: Add `organization_arns` and `organizational_unit_arns` arguments to the `distribution.ami_distribution_configuration.launch_permission` configuration block
```

```release-note:enhancement
data-source/aws_imagebuilder_distribution_configuration: Add `organization_arns` and `organizational_unit_arns` attributes to the `distribution.ami_distribution_configuration.launch_permission` configuration block
```
32 changes: 32 additions & 0 deletions internal/service/imagebuilder/distribution_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ func ResourceDistributionConfiguration() *schema.Resource {
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"organization_arns": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: verify.ValidARN,
},
},
"organizational_unit_arns": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: verify.ValidARN,
},
},
"user_groups": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -495,6 +511,14 @@ func expandLaunchPermissionConfiguration(tfMap map[string]interface{}) *imagebui

apiObject := &imagebuilder.LaunchPermissionConfiguration{}

if v, ok := tfMap["organization_arns"].(*schema.Set); ok && v.Len() > 0 {
apiObject.OrganizationArns = flex.ExpandStringSet(v)
}

if v, ok := tfMap["organizational_unit_arns"].(*schema.Set); ok && v.Len() > 0 {
apiObject.OrganizationalUnitArns = flex.ExpandStringSet(v)
}

if v, ok := tfMap["user_ids"].(*schema.Set); ok && v.Len() > 0 {
apiObject.UserIds = flex.ExpandStringSet(v)
}
Expand Down Expand Up @@ -671,6 +695,14 @@ func flattenLaunchPermissionConfiguration(apiObject *imagebuilder.LaunchPermissi

tfMap := map[string]interface{}{}

if v := apiObject.OrganizationArns; v != nil {
tfMap["organization_arns"] = aws.StringValueSlice(v)
}

if v := apiObject.OrganizationalUnitArns; v != nil {
tfMap["organizational_unit_arns"] = aws.StringValueSlice(v)
}

if v := apiObject.UserGroups; v != nil {
tfMap["user_groups"] = aws.StringValueSlice(v)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ func DataSourceDistributionConfiguration() *schema.Resource {
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"organization_arns": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"organizational_unit_arns": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"user_groups": {
Type: schema.TypeSet,
Computed: true,
Expand Down
125 changes: 124 additions & 1 deletion internal/service/imagebuilder/distribution_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ import (
tfimagebuilder "github.com/hashicorp/terraform-provider-aws/internal/service/imagebuilder"
)

func init() {
acctest.RegisterServiceErrorCheckFunc(imagebuilder.EndpointsID, testAccErrorCheckSkip)
}

func testAccErrorCheckSkip(t *testing.T) resource.ErrorCheckFunc {
return acctest.ErrorCheckSkipMessagesContaining(t,
"You have reached the maximum allowed number of license configurations created in one day",
)
}

func TestAccImageBuilderDistributionConfiguration_basic(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_distribution_configuration.test"
Expand Down Expand Up @@ -318,6 +328,69 @@ func TestAccImageBuilderDistributionConfiguration_DistributionAMIDistributionLau
})
}

func TestAccImageBuilderDistributionConfiguration_DistributionAMIDistributionLaunchPermission_organizationArns(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
organizationResourceName := "aws_organizations_organization.test"
resourceName := "aws_imagebuilder_distribution_configuration.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(t)
acctest.PreCheckOrganizationsAccount(t)
},
ErrorCheck: acctest.ErrorCheck(t, imagebuilder.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckDistributionConfigurationDestroy,
Steps: []resource.TestStep{
{
Config: testAccDistributionConfigurationDistributionAMIDistributionConfigurationLaunchPermissionOrganizationArnsConfig(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDistributionConfigurationExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "distribution.#", "1"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "distribution.*.ami_distribution_configuration.0.launch_permission.0.organization_arns.*", organizationResourceName, "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccImageBuilderDistributionConfiguration_DistributionAMIDistributionLaunchPermission_organizationalUnitArns(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
organizationalUnitResourceName := "aws_organizations_organizational_unit.test"

resourceName := "aws_imagebuilder_distribution_configuration.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(t)
acctest.PreCheckOrganizationsAccount(t)
},
ErrorCheck: acctest.ErrorCheck(t, imagebuilder.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckDistributionConfigurationDestroy,
Steps: []resource.TestStep{
{
Config: testAccDistributionConfigurationDistributionAMIDistributionConfigurationLaunchPermissionOrganizationalUnitArnsConfig(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDistributionConfigurationExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "distribution.#", "1"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "distribution.*.ami_distribution_configuration.0.launch_permission.0.organizational_unit_arns.*", organizationalUnitResourceName, "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccImageBuilderDistributionConfiguration_DistributionAMIDistribution_name(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_distribution_configuration.test"
Expand Down Expand Up @@ -562,7 +635,10 @@ func TestAccImageBuilderDistributionConfiguration_Distribution_licenseARNs(t *te
resourceName := "aws_imagebuilder_distribution_configuration.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
PreCheck: func() {
acctest.PreCheck(t)
acctest.PreCheckIAMServiceLinkedRole(t, "/aws-service-role/license-manager.amazonaws.com")
},
ErrorCheck: acctest.ErrorCheck(t, imagebuilder.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckDistributionConfigurationDestroy,
Expand Down Expand Up @@ -863,6 +939,53 @@ resource "aws_imagebuilder_distribution_configuration" "test" {
`, rName, userId)
}

func testAccDistributionConfigurationDistributionAMIDistributionConfigurationLaunchPermissionOrganizationArnsConfig(rName string) string {
return fmt.Sprintf(`
data "aws_region" "current" {}
data "aws_partition" "current" {}

resource "aws_organizations_organization" "test" {}

resource "aws_imagebuilder_distribution_configuration" "test" {
name = %[1]q
distribution {
ami_distribution_configuration {
launch_permission {
organization_arns = [aws_organizations_organization.test.arn]
}
}
region = data.aws_region.current.name
}
}
`, rName)
}

func testAccDistributionConfigurationDistributionAMIDistributionConfigurationLaunchPermissionOrganizationalUnitArnsConfig(rName string) string {
return fmt.Sprintf(`
data "aws_region" "current" {}
data "aws_partition" "current" {}

resource "aws_organizations_organization" "test" {}

resource "aws_organizations_organizational_unit" "test" {
name = %[1]q
parent_id = aws_organizations_organization.test.roots[0].id
}

resource "aws_imagebuilder_distribution_configuration" "test" {
name = %[1]q
distribution {
ami_distribution_configuration {
launch_permission {
organizational_unit_arns = [aws_organizations_organizational_unit.test.arn]
}
}
region = data.aws_region.current.name
}
}
`, rName)
}

func testAccDistributionConfigurationDistributionAMIDistributionConfigurationNameConfig(rName string, name string) string {
return fmt.Sprintf(`
data "aws_region" "current" {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ In addition to all arguments above, the following attributes are exported:
* `description` - Description to apply to distributed AMI.
* `kms_key_id` - Amazon Resource Name (ARN) of Key Management Service (KMS) Key to encrypt AMI.
* `launch_permission` - Nested list of EC2 launch permissions.
* `organization_arns` - Set of AWS Organization ARNs.
* `organizational_unit_arns` - Set of AWS Organizational Unit ARNs.
* `user_groups` - Set of EC2 launch permission user groups.
* `user_ids` - Set of AWS Account identifiers.
* `target_account_ids` - Set of target AWS Account identifiers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ The following arguments are optional:

The following arguments are optional:

* `organization_arns` - (Optional) Set of AWS Organization ARNs to assign.
* `organizational_unit_arns` - (Optional) Set of AWS Organizational Unit ARNs to assign.
* `user_groups` - (Optional) Set of EC2 launch permission user groups to assign. Use `all` to distribute a public AMI.
* `user_ids` - (Optional) Set of AWS Account identifiers to assign.

Expand Down