diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index de1dd32ef..3e835c106 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -17,6 +17,7 @@ import ( "github.com/aws/aws-sdk-go/service/cloudtrail" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/aws/aws-sdk-go/service/codecommit" "github.com/aws/aws-sdk-go/service/codedeploy" "github.com/aws/aws-sdk-go/service/directoryservice" "github.com/aws/aws-sdk-go/service/dynamodb" @@ -78,6 +79,7 @@ type AWSClient struct { opsworksconn *opsworks.OpsWorks glacierconn *glacier.Glacier codedeployconn *codedeploy.CodeDeploy + codecommitconn *codecommit.CodeCommit } // Client configures and returns a fully initialized AWSClient @@ -213,6 +215,9 @@ func (c *Config) Client() (interface{}, error) { log.Println("[INFO] Initializing CodeDeploy Connection") client.codedeployconn = codedeploy.New(sess) + + log.Println("[INFO] Initializing CodeCommit SDK connection") + client.codecommitconn = codecommit.New(usEast1Sess) } if len(errs) > 0 { diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 5ed49de86..b5392429a 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -177,6 +177,7 @@ func Provider() terraform.ResourceProvider { "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), "aws_codedeploy_app": resourceAwsCodeDeployApp(), "aws_codedeploy_deployment_group": resourceAwsCodeDeployDeploymentGroup(), + "aws_codecommit_repository": resourceAwsCodeCommitRepository(), "aws_customer_gateway": resourceAwsCustomerGateway(), "aws_db_instance": resourceAwsDbInstance(), "aws_db_parameter_group": resourceAwsDbParameterGroup(), diff --git a/builtin/providers/aws/resource_aws_codecommit_repository.go b/builtin/providers/aws/resource_aws_codecommit_repository.go new file mode 100644 index 000000000..ac2e1b1b3 --- /dev/null +++ b/builtin/providers/aws/resource_aws_codecommit_repository.go @@ -0,0 +1,185 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/codecommit" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsCodeCommitRepository() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCodeCommitRepositoryCreate, + Update: resourceAwsCodeCommitRepositoryUpdate, + Read: resourceAwsCodeCommitRepositoryRead, + Delete: resourceAwsCodeCommitRepositoryDelete, + + Schema: map[string]*schema.Schema{ + "repository_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) > 100 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 100 characters", k)) + } + return + }, + }, + + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) > 1000 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 1000 characters", k)) + } + return + }, + }, + + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "repository_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "clone_url_http": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "clone_url_ssh": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "default_branch": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceAwsCodeCommitRepositoryCreate(d *schema.ResourceData, meta interface{}) error { + codecommitconn := meta.(*AWSClient).codecommitconn + region := meta.(*AWSClient).region + + // This is a temporary thing - we need to ensure that CodeCommit is only being run against us-east-1 + // As this is the only place that AWS currently supports it + if region != "us-east-1" { + return fmt.Errorf("CodeCommit can only be used with us-east-1. You are trying to use it on %s", region) + } + + input := &codecommit.CreateRepositoryInput{ + RepositoryName: aws.String(d.Get("repository_name").(string)), + RepositoryDescription: aws.String(d.Get("description").(string)), + } + + out, err := codecommitconn.CreateRepository(input) + if err != nil { + return fmt.Errorf("Error creating CodeCommit Repository: %s", err) + } + + d.SetId(d.Get("repository_name").(string)) + d.Set("repository_id", *out.RepositoryMetadata.RepositoryId) + d.Set("arn", *out.RepositoryMetadata.Arn) + d.Set("clone_url_http", *out.RepositoryMetadata.CloneUrlHttp) + d.Set("clone_url_ssh", *out.RepositoryMetadata.CloneUrlSsh) + + return resourceAwsCodeCommitRepositoryUpdate(d, meta) +} + +func resourceAwsCodeCommitRepositoryUpdate(d *schema.ResourceData, meta interface{}) error { + codecommitconn := meta.(*AWSClient).codecommitconn + + if d.HasChange("default_branch") { + if err := resourceAwsCodeCommitUpdateDefaultBranch(codecommitconn, d); err != nil { + return err + } + } + + if d.HasChange("description") { + if err := resourceAwsCodeCommitUpdateDescription(codecommitconn, d); err != nil { + return err + } + } + + return resourceAwsCodeCommitRepositoryRead(d, meta) +} + +func resourceAwsCodeCommitRepositoryRead(d *schema.ResourceData, meta interface{}) error { + codecommitconn := meta.(*AWSClient).codecommitconn + + input := &codecommit.GetRepositoryInput{ + RepositoryName: aws.String(d.Id()), + } + + out, err := codecommitconn.GetRepository(input) + if err != nil { + return fmt.Errorf("Error reading CodeCommit Repository: %s", err.Error()) + } + + d.Set("repository_id", *out.RepositoryMetadata.RepositoryId) + d.Set("arn", *out.RepositoryMetadata.Arn) + d.Set("clone_url_http", *out.RepositoryMetadata.CloneUrlHttp) + d.Set("clone_url_ssh", *out.RepositoryMetadata.CloneUrlSsh) + if out.RepositoryMetadata.DefaultBranch != nil { + d.Set("default_branch", *out.RepositoryMetadata.DefaultBranch) + } + + return nil +} + +func resourceAwsCodeCommitRepositoryDelete(d *schema.ResourceData, meta interface{}) error { + codecommitconn := meta.(*AWSClient).codecommitconn + + log.Printf("[DEBUG] CodeCommit Delete Repository: %s", d.Id()) + _, err := codecommitconn.DeleteRepository(&codecommit.DeleteRepositoryInput{ + RepositoryName: aws.String(d.Id()), + }) + if err != nil { + return fmt.Errorf("Error deleting CodeCommit Repository: %s", err.Error()) + } + + return nil +} + +func resourceAwsCodeCommitUpdateDescription(codecommitconn *codecommit.CodeCommit, d *schema.ResourceData) error { + branchInput := &codecommit.UpdateRepositoryDescriptionInput{ + RepositoryName: aws.String(d.Id()), + RepositoryDescription: aws.String(d.Get("description").(string)), + } + + _, err := codecommitconn.UpdateRepositoryDescription(branchInput) + if err != nil { + return fmt.Errorf("Error Updating Repository Description for CodeCommit Repository: %s", err.Error()) + } + + return nil +} + +func resourceAwsCodeCommitUpdateDefaultBranch(codecommitconn *codecommit.CodeCommit, d *schema.ResourceData) error { + branchInput := &codecommit.UpdateDefaultBranchInput{ + RepositoryName: aws.String(d.Id()), + DefaultBranchName: aws.String(d.Get("default_branch").(string)), + } + + _, err := codecommitconn.UpdateDefaultBranch(branchInput) + if err != nil { + return fmt.Errorf("Error Updating Default Branch for CodeCommit Repository: %s", err.Error()) + } + + return nil +} diff --git a/builtin/providers/aws/resource_aws_codecommit_repository_test.go b/builtin/providers/aws/resource_aws_codecommit_repository_test.go new file mode 100644 index 000000000..14fcdf321 --- /dev/null +++ b/builtin/providers/aws/resource_aws_codecommit_repository_test.go @@ -0,0 +1,109 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/codecommit" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSCodeCommitRepository_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCodeCommitRepositoryDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCodeCommitRepository_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckCodeCommitRepositoryExists("aws_codecommit_repository.test"), + ), + }, + }, + }) +} + +func TestAccAWSCodeCommitRepository_withChanges(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCodeCommitRepositoryDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCodeCommitRepository_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckCodeCommitRepositoryExists("aws_codecommit_repository.test"), + resource.TestCheckResourceAttr( + "aws_codecommit_repository.test", "description", "This is a test description"), + ), + }, + resource.TestStep{ + Config: testAccCodeCommitRepository_withChanges, + Check: resource.ComposeTestCheckFunc( + testAccCheckCodeCommitRepositoryExists("aws_codecommit_repository.test"), + resource.TestCheckResourceAttr( + "aws_codecommit_repository.test", "description", "This is a test description - with changes"), + ), + }, + }, + }) +} + +func testAccCheckCodeCommitRepositoryExists(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") + } + + codecommitconn := testAccProvider.Meta().(*AWSClient).codecommitconn + out, err := codecommitconn.GetRepository(&codecommit.GetRepositoryInput{ + RepositoryName: aws.String(rs.Primary.ID), + }) + + if err != nil { + return err + } + + if out.RepositoryMetadata.Arn == nil { + return fmt.Errorf("No CodeCommit Repository Vault Found") + } + + if *out.RepositoryMetadata.RepositoryName != rs.Primary.ID { + return fmt.Errorf("CodeCommit Repository Mismatch - existing: %q, state: %q", + *out.RepositoryMetadata.RepositoryName, rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckCodeCommitRepositoryDestroy(s *terraform.State) error { + if len(s.RootModule().Resources) > 0 { + return fmt.Errorf("Expected all resources to be gone, but found: %#v", + s.RootModule().Resources) + } + + return nil +} + +const testAccCodeCommitRepository_basic = ` +resource "aws_codecommit_repository" "test" { + repository_name = "my_test_repository" + description = "This is a test description" +} +` + +const testAccCodeCommitRepository_withChanges = ` +resource "aws_codecommit_repository" "test" { + repository_name = "my_test_repository" + description = "This is a test description - with changes" +} +` diff --git a/terraform/eval_ignore_changes.go b/terraform/eval_ignore_changes.go index 2eb2d9bb1..cc2261313 100644 --- a/terraform/eval_ignore_changes.go +++ b/terraform/eval_ignore_changes.go @@ -1,8 +1,9 @@ package terraform import ( - "github.com/hashicorp/terraform/config" "strings" + + "github.com/hashicorp/terraform/config" ) // EvalIgnoreChanges is an EvalNode implementation that removes diff diff --git a/website/source/docs/providers/aws/r/code_commit_repository.html.markdown b/website/source/docs/providers/aws/r/code_commit_repository.html.markdown new file mode 100644 index 000000000..84a161f5d --- /dev/null +++ b/website/source/docs/providers/aws/r/code_commit_repository.html.markdown @@ -0,0 +1,37 @@ +--- +layout: "aws" +page_title: "AWS: aws_codecommit_repository" +sidebar_current: "docs-aws-resource-codecommit-repository" +description: |- + Provides a CodeCommit Repository Resource. +--- + +# aws\_codecommit\_repository + +Provides a CodeCommit Repository Resource. + +## Example Usage + +``` +resource "aws_codecommit_repository" "test" { + repository_name = "MyTestRepository" + description = "This is the Sample App Repository" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `repository_name` - (Required) The name for the repository. This needs to be less than 100 characters. +* `description` - (Optional) The description of the repository. This needs to be less than 1000 characters +* `default_branch` - (Optional) The default branch of the repository. The branch specified here needs to exist. + +## Attributes Reference + +The following attributes are exported: + +* `repository_id` - The ID of the repository +* `arn` - The ARN of the repository +* `clone_url_http` - The URL to use for cloning the repository over HTTPS. +* `clone_url_ssh` - The URL to use for cloning the repository over SSH. \ No newline at end of file diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index a12f55972..e9f773c29 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -43,6 +43,16 @@ + > + CodeCommit Resources + + + > CodeDeploy Resources + > DynamoDB Resources