Skip to content

Commit

Permalink
Merge pull request #16853 from DrFaust92/r/ecr_replication_configuration
Browse files Browse the repository at this point in the history
r/ecr_replication_configuration - new resource
  • Loading branch information
gdavison committed Apr 5, 2021
2 parents c891864 + ab582cf commit c25b788
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/16853.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_ecr_replication_configuration
```
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ func Provider() *schema.Provider {
"aws_ec2_transit_gateway_vpc_attachment_accepter": resourceAwsEc2TransitGatewayVpcAttachmentAccepter(),
"aws_ecr_lifecycle_policy": resourceAwsEcrLifecyclePolicy(),
"aws_ecrpublic_repository": resourceAwsEcrPublicRepository(),
"aws_ecr_replication_configuration": resourceAwsEcrReplicationConfiguration(),
"aws_ecr_repository": resourceAwsEcrRepository(),
"aws_ecr_repository_policy": resourceAwsEcrRepositoryPolicy(),
"aws_ecs_capacity_provider": resourceAwsEcsCapacityProvider(),
Expand Down
200 changes: 200 additions & 0 deletions aws/resource_aws_ecr_replication_configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package aws

import (
"fmt"
"log"

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

func resourceAwsEcrReplicationConfiguration() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEcrReplicationConfigurationPut,
Read: resourceAwsEcrReplicationConfigurationRead,
Update: resourceAwsEcrReplicationConfigurationPut,
Delete: schema.Noop,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"registry_id": {
Type: schema.TypeString,
Computed: true,
},
"replication_configuration": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"rule": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"destination": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Required: true,
},
"registry_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateAwsAccountId,
},
},
},
},
},
},
},
},
},
},
},
}
}

func resourceAwsEcrReplicationConfigurationPut(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecrconn

input := ecr.PutReplicationConfigurationInput{
ReplicationConfiguration: expandEcrReplicationConfigurationReplicationConfiguration(d.Get("replication_configuration").([]interface{})),
}

_, err := conn.PutReplicationConfiguration(&input)
if err != nil {
return fmt.Errorf("error creating ECR Replication Configuration: %w", err)
}

d.SetId(meta.(*AWSClient).accountid)

return resourceAwsEcrReplicationConfigurationRead(d, meta)
}

func resourceAwsEcrReplicationConfigurationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecrconn

log.Printf("[DEBUG] Reading ECR Replication Configuration %s", d.Id())
out, err := conn.DescribeRegistry(&ecr.DescribeRegistryInput{})
if err != nil {
return fmt.Errorf("error reading ECR Replication Configuration: %w", err)
}

d.Set("registry_id", out.RegistryId)

if err := d.Set("replication_configuration", flattenEcrReplicationConfigurationReplicationConfiguration(out.ReplicationConfiguration)); err != nil {
return fmt.Errorf("error setting replication_configuration for ECR Replication Configuration: %w", err)
}

return nil
}

func expandEcrReplicationConfigurationReplicationConfiguration(data []interface{}) *ecr.ReplicationConfiguration {
if len(data) == 0 || data[0] == nil {
return nil
}

ec := data[0].(map[string]interface{})
config := &ecr.ReplicationConfiguration{
Rules: expandEcrReplicationConfigurationReplicationConfigurationRules(ec["rule"].([]interface{})),
}
return config
}

func flattenEcrReplicationConfigurationReplicationConfiguration(ec *ecr.ReplicationConfiguration) []map[string]interface{} {
if ec == nil {
return nil
}

config := map[string]interface{}{
"rule": flattenEcrReplicationConfigurationReplicationConfigurationRules(ec.Rules),
}

return []map[string]interface{}{
config,
}
}

func expandEcrReplicationConfigurationReplicationConfigurationRules(data []interface{}) []*ecr.ReplicationRule {
if len(data) == 0 || data[0] == nil {
return nil
}

var rules []*ecr.ReplicationRule

for _, rule := range data {
ec := rule.(map[string]interface{})
config := &ecr.ReplicationRule{
Destinations: expandEcrReplicationConfigurationReplicationConfigurationRulesDestinations(ec["destination"].([]interface{})),
}

rules = append(rules, config)

}
return rules
}

func flattenEcrReplicationConfigurationReplicationConfigurationRules(ec []*ecr.ReplicationRule) []interface{} {
if len(ec) == 0 {
return nil
}

var tfList []interface{}

for _, apiObject := range ec {
tfMap := map[string]interface{}{
"destination": flattenEcrReplicationConfigurationReplicationConfigurationRulesDestinations(apiObject.Destinations),
}

tfList = append(tfList, tfMap)
}

return tfList
}

func expandEcrReplicationConfigurationReplicationConfigurationRulesDestinations(data []interface{}) []*ecr.ReplicationDestination {
if len(data) == 0 || data[0] == nil {
return nil
}

var dests []*ecr.ReplicationDestination

for _, dest := range data {
ec := dest.(map[string]interface{})
config := &ecr.ReplicationDestination{
Region: aws.String(ec["region"].(string)),
RegistryId: aws.String(ec["registry_id"].(string)),
}

dests = append(dests, config)
}
return dests
}

func flattenEcrReplicationConfigurationReplicationConfigurationRulesDestinations(ec []*ecr.ReplicationDestination) []interface{} {
if len(ec) == 0 {
return nil
}

var tfList []interface{}

for _, apiObject := range ec {
tfMap := map[string]interface{}{
"region": aws.StringValue(apiObject.Region),
"registry_id": aws.StringValue(apiObject.RegistryId),
}

tfList = append(tfList, tfMap)
}

return tfList
}
68 changes: 68 additions & 0 deletions aws/resource_aws_ecr_replication_configuration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package aws

import (
"fmt"
"testing"

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

func TestAccAWSEcrReplicationConfiguration_basic(t *testing.T) {
resourceName := "aws_ecr_replication_configuration.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, ecr.EndpointsID),
Providers: testAccProviders,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccAWSEcrReplicationConfiguration(testAccGetAlternateRegion()),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcrReplicationConfigurationExists(resourceName),
testAccCheckResourceAttrAccountID(resourceName, "registry_id"),
resource.TestCheckResourceAttr(resourceName, "replication_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "replication_configuration.0.rule.#", "1"),
resource.TestCheckResourceAttr(resourceName, "replication_configuration.0.rule.0.destination.#", "1"),
resource.TestCheckResourceAttr(resourceName, "replication_configuration.0.rule.0.destination.0.region", testAccGetAlternateRegion()),
testAccCheckResourceAttrAccountID(resourceName, "replication_configuration.0.rule.0.destination.0.registry_id"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckAWSEcrReplicationConfigurationExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}

return nil
}
}

func testAccAWSEcrReplicationConfiguration(region string) string {
return fmt.Sprintf(`
data "aws_caller_identity" "current" {}
resource "aws_ecr_replication_configuration" "test" {
replication_configuration {
rule {
destination {
region = %[1]q
registry_id = data.aws_caller_identity.current.account_id
}
}
}
}
`, region)
}
63 changes: 63 additions & 0 deletions website/docs/r/ecr_replication_configuration.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
subcategory: "ECR"
layout: "aws"
page_title: "AWS: aws_ecr_replication_configuration"
description: |-
Provides an Elastic Container Registry Replication Configuration.
---

# Resource: aws_ecr_replication_configuration

Provides an Elastic Container Registry Replication Configuration.

## Example Usage

```terraform
data "aws_caller_identity" "current" {}
data "aws_regions" "example" {}
resource "aws_ecr_replication_configuration" "example" {
replication_configuration {
rule {
destination {
region = data.aws_regions.example.names[0]
registry_id = data.aws_caller_identity.current.account_id
}
}
}
}
```

## Argument Reference

The following arguments are supported:

* `replication_configuration` - (Required) Replication configuration for a registry. See [Replication Configuration](#encryption-configuration).

### Replication Configuration

* `rule` - (Required) The replication rules for a replication configuration. See [Rule](#rule).

### Rule

* `destination` - (Required) the details of a replication destination. See [Destination](#destination).

### Destination

* `region` - (Required) A Region to replicate to.
* `registry_id` - (Required) The account ID of the destination registry to replicate to.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

* `registry_id` - The registry ID where the replication configuration was created.

## Import

ECR Replication Configuration can be imported using the `registry_id`, e.g.

```
$ terraform import aws_ecr_replication_configuration.service 012345678912
```

0 comments on commit c25b788

Please sign in to comment.