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

CodeCommit approval rule template association #13467

Merged
merged 11 commits into from
Dec 2, 2021
3 changes: 3 additions & 0 deletions .changelog/13467.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_codecommit_approval_rule_template_association
```
7 changes: 4 additions & 3 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
@@ -912,9 +912,10 @@ func Provider() *schema.Provider {
"aws_codebuild_source_credential": codebuild.ResourceSourceCredential(),
"aws_codebuild_webhook": codebuild.ResourceWebhook(),

"aws_codecommit_approval_rule_template": codecommit.ResourceApprovalRuleTemplate(),
"aws_codecommit_repository": codecommit.ResourceRepository(),
"aws_codecommit_trigger": codecommit.ResourceTrigger(),
"aws_codecommit_approval_rule_template": codecommit.ResourceApprovalRuleTemplate(),
"aws_codecommit_approval_rule_template_association": codecommit.ResourceApprovalRuleTemplateAssociation(),
"aws_codecommit_repository": codecommit.ResourceRepository(),
"aws_codecommit_trigger": codecommit.ResourceTrigger(),

"aws_codedeploy_app": codedeploy.ResourceApp(),
"aws_codedeploy_deployment_config": codedeploy.ResourceDeploymentConfig(),
130 changes: 130 additions & 0 deletions internal/service/codecommit/approval_rule_template_association.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package codecommit

import (
"fmt"
"log"
"regexp"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/codecommit"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func ResourceApprovalRuleTemplateAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceApprovalRuleTemplateAssociationCreate,
Read: resourceApprovalRuleTemplateAssociationRead,
Delete: resourceApprovalRuleTemplateAssociationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"approval_rule_template_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 100),
},
"repository_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 100),
validation.StringMatch(regexp.MustCompile(`[\w\.-]+`), ""),
),
},
},
}
}

func resourceApprovalRuleTemplateAssociationCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).CodeCommitConn

approvalRuleTemplateName := d.Get("approval_rule_template_name").(string)
repositoryName := d.Get("repository_name").(string)

input := &codecommit.AssociateApprovalRuleTemplateWithRepositoryInput{
ApprovalRuleTemplateName: aws.String(approvalRuleTemplateName),
RepositoryName: aws.String(repositoryName),
}

_, err := conn.AssociateApprovalRuleTemplateWithRepository(input)

if err != nil {
return fmt.Errorf("error associating CodeCommit Approval Rule Template (%s) with repository (%s): %w", approvalRuleTemplateName, repositoryName, err)
}

d.SetId(fmt.Sprintf("%s,%s", approvalRuleTemplateName, repositoryName))

return resourceApprovalRuleTemplateAssociationRead(d, meta)
}

func resourceApprovalRuleTemplateAssociationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).CodeCommitConn

approvalRuleTemplateName, repositoryName, err := ApprovalRuleTemplateAssociationParseID(d.Id())

if err != nil {
return err
}

err = FindApprovalRuleTemplateAssociation(conn, approvalRuleTemplateName, repositoryName)

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] CodeCommit Approval Rule Template Association (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading CodeCommit Approval Rule Template Association (%s): %w", d.Id(), err)
}

d.Set("approval_rule_template_name", approvalRuleTemplateName)
d.Set("repository_name", repositoryName)

return nil
}

func resourceApprovalRuleTemplateAssociationDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).CodeCommitConn

approvalRuleTemplateName, repositoryName, err := ApprovalRuleTemplateAssociationParseID(d.Id())

if err != nil {
return err
}

input := &codecommit.DisassociateApprovalRuleTemplateFromRepositoryInput{
ApprovalRuleTemplateName: aws.String(approvalRuleTemplateName),
RepositoryName: aws.String(repositoryName),
}

_, err = conn.DisassociateApprovalRuleTemplateFromRepository(input)

if tfawserr.ErrCodeEquals(err, codecommit.ErrCodeApprovalRuleTemplateDoesNotExistException, codecommit.ErrCodeRepositoryDoesNotExistException) {
return nil
}

if err != nil {
return fmt.Errorf("error disassociating CodeCommit Approval Rule Template (%s) from repository (%s): %w", approvalRuleTemplateName, repositoryName, err)
}

return nil
}

func ApprovalRuleTemplateAssociationParseID(id string) (string, string, error) {
parts := strings.SplitN(id, ",", 2)
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return "", "", fmt.Errorf("unexpected format of ID (%s), expected APPROVAL_RULE_TEMPLATE_NAME,REPOSITORY_NAME", id)
}

return parts[0], parts[1], nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package codecommit_test

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/service/codecommit"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfcodecommit "github.com/hashicorp/terraform-provider-aws/internal/service/codecommit"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func TestAccCodeCommitApprovalRuleTemplateAssociation_basic(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_codecommit_approval_rule_template_association.test"
repoResourceName := "aws_codecommit_repository.test"
templateResourceName := "aws_codecommit_approval_rule_template.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, codecommit.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckCodeCommitApprovalRuleTemplateAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCodeCommitApprovalRuleTemplateAssociation_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckCodeCommitApprovalRuleTemplateAssociationExists(resourceName),
resource.TestCheckResourceAttrPair(resourceName, "approval_rule_template_name", templateResourceName, "name"),
resource.TestCheckResourceAttrPair(resourceName, "repository_name", repoResourceName, "repository_name"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccCodeCommitApprovalRuleTemplateAssociation_disappears(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_codecommit_approval_rule_template_association.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, codecommit.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckCodeCommitApprovalRuleTemplateAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCodeCommitApprovalRuleTemplateAssociation_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckCodeCommitApprovalRuleTemplateAssociationExists(resourceName),
acctest.CheckResourceDisappears(acctest.Provider, tfcodecommit.ResourceApprovalRuleTemplateAssociation(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func TestAccCodeCommitApprovalRuleTemplateAssociation_Disappears_repository(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
repoResourceName := "aws_codecommit_repository.test"
resourceName := "aws_codecommit_approval_rule_template_association.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, codecommit.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckCodeCommitApprovalRuleTemplateAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCodeCommitApprovalRuleTemplateAssociation_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckCodeCommitApprovalRuleTemplateAssociationExists(resourceName),
acctest.CheckResourceDisappears(acctest.Provider, tfcodecommit.ResourceRepository(), repoResourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

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

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

conn := acctest.Provider.Meta().(*conns.AWSClient).CodeCommitConn

approvalTemplateName, repositoryName, err := tfcodecommit.ApprovalRuleTemplateAssociationParseID(rs.Primary.ID)

if err != nil {
return err
}

err = tfcodecommit.FindApprovalRuleTemplateAssociation(conn, approvalTemplateName, repositoryName)

if err != nil {
return err
}

return nil
}
}

func testAccCheckCodeCommitApprovalRuleTemplateAssociationDestroy(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).CodeCommitConn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_codecommit_approval_rule_template_association" {
continue
}

approvalTemplateName, repositoryName, err := tfcodecommit.ApprovalRuleTemplateAssociationParseID(rs.Primary.ID)

if err != nil {
return err
}

err = tfcodecommit.FindApprovalRuleTemplateAssociation(conn, approvalTemplateName, repositoryName)

if tfresource.NotFound(err) {
continue
}

if err != nil {
return err
}

return fmt.Errorf("CodeCommit Approval Rule Template Association %s still exists", rs.Primary.ID)
}

return nil
}

func testAccCodeCommitApprovalRuleTemplateAssociation_basic(rName string) string {
return fmt.Sprintf(`
data "aws_caller_identity" "current" {}
data "aws_partition" "current" {}
resource "aws_codecommit_approval_rule_template" "test" {
name = %[1]q
content = <<EOF
{
"Version": "2018-11-08",
"DestinationReferences": ["refs/heads/master"],
"Statements": [{
"Type": "Approvers",
"NumberOfApprovalsNeeded": 2,
"ApprovalPoolMembers": ["arn:${data.aws_partition.current.partition}:sts::${data.aws_caller_identity.current.account_id}:assumed-role/CodeCommitReview/*"]}]
}
EOF
}
resource "aws_codecommit_repository" "test" {
repository_name = %[1]q
}
resource "aws_codecommit_approval_rule_template_association" "test" {
approval_rule_template_name = aws_codecommit_approval_rule_template.test.name
repository_name = aws_codecommit_repository.test.repository_name
}
`, rName)
}
54 changes: 54 additions & 0 deletions internal/service/codecommit/find.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package codecommit

import (
"fmt"

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

// FindApprovalRuleTemplateAssociation validates that an approval rule template has the named associated repository
func FindApprovalRuleTemplateAssociation(conn *codecommit.CodeCommit, approvalRuleTemplateName, repositoryName string) error {
input := &codecommit.ListRepositoriesForApprovalRuleTemplateInput{
ApprovalRuleTemplateName: aws.String(approvalRuleTemplateName),
}

found := false

err := conn.ListRepositoriesForApprovalRuleTemplatePages(input, func(page *codecommit.ListRepositoriesForApprovalRuleTemplateOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, repoName := range page.RepositoryNames {
if aws.StringValue(repoName) == repositoryName {
found = true
return false
}
}

return !lastPage
})

if tfawserr.ErrCodeEquals(err, codecommit.ErrCodeApprovalRuleTemplateDoesNotExistException) {
return &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return err
}

if !found {
return &resource.NotFoundError{
Message: fmt.Sprintf("No approval rule template (%q) associated with repository (%q)", approvalRuleTemplateName, repositoryName),
LastRequest: input,
}
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
subcategory: "CodeCommit"
layout: "aws"
page_title: "AWS: aws_codecommit_approval_rule_template_association"
description: |-
Associates a CodeCommit Approval Rule Template with a Repository.
---

# Resource: aws_codecommit_approval_rule_template_association

Associates a CodeCommit Approval Rule Template with a Repository.

## Example Usage

```terraform
resource "aws_codecommit_approval_rule_template_association" "example" {
approval_rule_template_name = aws_codecommit_approval_rule_template.example.name
repository_name = aws_codecommit_repository.example.repository_name
}
```

## Argument Reference

The following arguments are supported:

* `approval_rule_template_name` - (Required) The name for the approval rule template.
* `repository_name` - (Required) The name of the repository that you want to associate with the template.

## Attributes Reference

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

* `id` - The name of the approval rule template and name of the repository, separated by a comma (`,`).

## Import

CodeCommit approval rule template associations can be imported using the `approval_rule_template_name` and `repository_name` separated by a comma (`,`), e.g.

```
$ terraform import aws_codecommit_approval_rule_template_association.example approver-rule-for-example,MyExampleRepo
```