Skip to content

Commit

Permalink
Merge pull request #13467 from carthewd/master
Browse files Browse the repository at this point in the history
CodeCommit approval rule template association
  • Loading branch information
anGie44 authored Dec 2, 2021
2 parents 39277c0 + a65968c commit 27d7b22
Show file tree
Hide file tree
Showing 6 changed files with 412 additions and 3 deletions.
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
Expand Up @@ -913,9 +913,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(),
Expand Down
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
}
180 changes: 180 additions & 0 deletions internal/service/codecommit/approval_rule_template_association_test.go
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
}
Loading

0 comments on commit 27d7b22

Please sign in to comment.