-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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 aws_codebuild_webhook resource for creating GitHub webhooks for CodeBuild projects #4473
Changes from all commits
19e6763
f6aa617
b7f1069
b40dc8e
8522c88
22e8140
9abbc82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package aws | ||
|
||
import ( | ||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/codebuild" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsCodeBuildWebhook() *schema.Resource { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can easily add import support for this resource as the ID is already handled properly in the read function. Will add the passthrough importer to this resource and document how to import on merge. |
||
return &schema.Resource{ | ||
Create: resourceAwsCodeBuildWebhookCreate, | ||
Read: resourceAwsCodeBuildWebhookRead, | ||
Delete: resourceAwsCodeBuildWebhookDelete, | ||
Update: resourceAwsCodeBuildWebhookUpdate, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might seem pedantic for now, but on merge will rename this attribute to |
||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"branch_filter": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"url": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsCodeBuildWebhookCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).codebuildconn | ||
|
||
resp, err := conn.CreateWebhook(&codebuild.CreateWebhookInput{ | ||
ProjectName: aws.String(d.Get("name").(string)), | ||
BranchFilter: aws.String(d.Get("branch_filter").(string)), | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId(d.Get("name").(string)) | ||
d.Set("branch_filter", d.Get("branch_filter").(string)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
d.Set("url", resp.Webhook.Url) | ||
return nil | ||
} | ||
|
||
func resourceAwsCodeBuildWebhookRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).codebuildconn | ||
|
||
resp, err := conn.BatchGetProjects(&codebuild.BatchGetProjectsInput{ | ||
Names: []*string{ | ||
aws.String(d.Id()), | ||
}, | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should check for "resource not found" type errors and |
||
} | ||
|
||
if len(resp.Projects) == 0 { | ||
d.SetId("") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When we're removing a resource from the state, we should log an appropriate warning message in the logs, e.g. log.Printf("[WARN] CodeBuild Project %q not found, removing from state", d.Id()) |
||
return nil | ||
} | ||
|
||
project := resp.Projects[0] | ||
d.Set("branch_filter", project.Webhook.BranchFilter) | ||
d.Set("url", project.Webhook.Url) | ||
return nil | ||
} | ||
|
||
func resourceAwsCodeBuildWebhookUpdate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).codebuildconn | ||
|
||
if !d.HasChange("branch_filter") { | ||
return nil | ||
} | ||
|
||
_, err := conn.UpdateWebhook(&codebuild.UpdateWebhookInput{ | ||
ProjectName: aws.String(d.Id()), | ||
BranchFilter: aws.String(d.Get("branch_filter").(string)), | ||
RotateSecret: aws.Bool(false), | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsCodeBuildWebhookDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).codebuildconn | ||
|
||
_, err := conn.DeleteWebhook(&codebuild.DeleteWebhookInput{ | ||
ProjectName: aws.String(d.Id()), | ||
}) | ||
|
||
if err != nil { | ||
if isAWSErr(err, codebuild.ErrCodeResourceNotFoundException, "") { | ||
d.SetId("") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return nil | ||
} | ||
return err | ||
} | ||
|
||
d.SetId("") | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/codebuild" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAwsCodeBuildWebhook_basic(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAwsCodeBuildWebhookDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCodeBuildWebhookConfig_basic(acctest.RandString(5)), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAwsCodeBuildWebhookExists("aws_codebuild_webhook.test"), | ||
resource.TestCheckResourceAttrSet("aws_codebuild_webhook.test", "url"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably be a little more cautious and at least partially validate the value as e.g. resource.TestMatchResourceAttr("aws_codebuild_webhook.test", "url", regexp.MustCompile(`^https://`)) |
||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAwsCodeBuildWebhookDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).codebuildconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_codebuild_webhook" { | ||
continue | ||
} | ||
|
||
resp, err := conn.BatchGetProjects(&codebuild.BatchGetProjectsInput{ | ||
Names: []*string{ | ||
aws.String(rs.Primary.ID), | ||
}, | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A resource not found exception here would be a good thing and should |
||
} | ||
|
||
if len(resp.Projects) == 0 { | ||
return nil | ||
} | ||
|
||
project := resp.Projects[0] | ||
if project.Webhook != nil && project.Webhook.Url != nil { | ||
return fmt.Errorf("Found CodeBuild Webhook: %s", rs.Primary.ID) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func testAccCheckAwsCodeBuildWebhookExists(name string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
_, ok := s.RootModule().Resources[name] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", name) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to how the destroy acceptance test function above is checking against the API, we should do the same thing here to ensure the "physical" webhook actually exists. |
||
return nil | ||
} | ||
} | ||
|
||
func testAccCodeBuildWebhookConfig_basic(rName string) string { | ||
return fmt.Sprintf(testAccAWSCodeBuildProjectConfig_basic(rName, "", "") + ` | ||
resource "aws_codebuild_webhook" "test" { | ||
name = "${aws_codebuild_project.foo.name}" | ||
} | ||
`) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_codebuild_webhook" | ||
sidebar_current: "docs-aws-resource-codebuild-webhook" | ||
description: |- | ||
Provides a CodeBuild Webhook resource. | ||
--- | ||
|
||
# aws_codebuild_webhook | ||
|
||
Provides a CodeBuild Webhook resource. | ||
|
||
~> **Note:** The AWS account that Terraform uses to create this resource *must* have authorized CodeBuild to access GitHub's OAuth API. This is a manual step that must be done *before* creating webhooks with this resource. If OAuth is not configured, AWS will return an error similar to `ResourceNotFoundException: Could not find access token for server type github`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This manual step must also be done in every applicable region where the resource will be used. We should probably also point to the AWS documentation surrounding project webhooks here. Will update on merge. |
||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "aws_codebuild_webhook" "github" { | ||
name = "${aws_codebuild_project.my_project.name}" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `name` - (Required) The name of the build project. | ||
* `branch_filter` - (Optional) A regular expression used to determine which branches get built. Default is all branches are built. | ||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `id` - The name of the build project. | ||
* `url` - The URL to the webhook. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great idea -- I'll make sure this gets ported over in some fashion when I rebase this PR.