diff --git a/aws/resource_aws_codeartifact_repository.go b/aws/resource_aws_codeartifact_repository.go index 6479d83e98f..74ca27d175e 100644 --- a/aws/resource_aws_codeartifact_repository.go +++ b/aws/resource_aws_codeartifact_repository.go @@ -37,10 +37,11 @@ func resourceAwsCodeArtifactRepository() *schema.Resource { ForceNew: true, }, "domain_owner": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ValidateFunc: validateAwsAccountId, }, "description": { Type: schema.TypeString, @@ -61,12 +62,13 @@ func resourceAwsCodeArtifactRepository() *schema.Resource { }, "external_connections": { Type: schema.TypeList, - Computed: true, + Optional: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "external_connection_name": { Type: schema.TypeString, - Computed: true, + Required: true, }, "package_format": { Type: schema.TypeString, @@ -116,6 +118,21 @@ func resourceAwsCodeArtifactRepositoryCreate(d *schema.ResourceData, meta interf repo := res.Repository d.SetId(aws.StringValue(repo.Arn)) + if v, ok := d.GetOk("external_connections"); ok { + externalConnection := v.([]interface{})[0].(map[string]interface{}) + input := &codeartifact.AssociateExternalConnectionInput{ + Domain: repo.DomainName, + Repository: repo.Name, + DomainOwner: repo.DomainOwner, + ExternalConnection: aws.String(externalConnection["external_connection_name"].(string)), + } + + _, err := conn.AssociateExternalConnection(input) + if err != nil { + return fmt.Errorf("error associating external connection to CodeArtifact repository: %w", err) + } + } + return resourceAwsCodeArtifactRepositoryRead(d, meta) } @@ -146,6 +163,37 @@ func resourceAwsCodeArtifactRepositoryUpdate(d *schema.ResourceData, meta interf return fmt.Errorf("error updating CodeArtifact Repository: %w", err) } + if d.HasChange("external_connections") { + if v, ok := d.GetOk("external_connections"); ok { + externalConnection := v.([]interface{})[0].(map[string]interface{}) + input := &codeartifact.AssociateExternalConnectionInput{ + Repository: aws.String(d.Get("repository").(string)), + Domain: aws.String(d.Get("domain").(string)), + DomainOwner: aws.String(d.Get("domain_owner").(string)), + ExternalConnection: aws.String(externalConnection["external_connection_name"].(string)), + } + + _, err := conn.AssociateExternalConnection(input) + if err != nil { + return fmt.Errorf("error associating external connection to CodeArtifact repository: %w", err) + } + } else { + oldConn, _ := d.GetChange("external_connections") + externalConnection := oldConn.([]interface{})[0].(map[string]interface{}) + input := &codeartifact.DisassociateExternalConnectionInput{ + Repository: aws.String(d.Get("repository").(string)), + Domain: aws.String(d.Get("domain").(string)), + DomainOwner: aws.String(d.Get("domain_owner").(string)), + ExternalConnection: aws.String(externalConnection["external_connection_name"].(string)), + } + + _, err := conn.DisassociateExternalConnection(input) + if err != nil { + return fmt.Errorf("error disassociating external connection to CodeArtifact repository: %w", err) + } + } + } + return resourceAwsCodeArtifactRepositoryRead(d, meta) } diff --git a/aws/resource_aws_codeartifact_repository_test.go b/aws/resource_aws_codeartifact_repository_test.go index f40cf27cadd..76e1f1e3860 100644 --- a/aws/resource_aws_codeartifact_repository_test.go +++ b/aws/resource_aws_codeartifact_repository_test.go @@ -207,6 +207,50 @@ func TestAccAWSCodeArtifactRepository_upstreams(t *testing.T) { }) } +func TestAccAWSCodeArtifactRepository_externalConnection(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codeartifact_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck("codeartifact", t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeArtifactRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeArtifactRepositoryExternalConnectionConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "external_connections.#", "1"), + resource.TestCheckResourceAttr(resourceName, "external_connections.0.external_connection_name", "public:npmjs"), + resource.TestCheckResourceAttr(resourceName, "external_connections.0.package_format", "npm"), + resource.TestCheckResourceAttr(resourceName, "external_connections.0.status", "AVAILABLE"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSCodeArtifactRepositoryBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "external_connections.#", "0"), + ), + }, + { + Config: testAccAWSCodeArtifactRepositoryExternalConnectionConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "external_connections.#", "1"), + resource.TestCheckResourceAttr(resourceName, "external_connections.0.external_connection_name", "public:npmjs"), + resource.TestCheckResourceAttr(resourceName, "external_connections.0.package_format", "npm"), + resource.TestCheckResourceAttr(resourceName, "external_connections.0.status", "AVAILABLE"), + ), + }, + }, + }) +} func TestAccAWSCodeArtifactRepository_disappears(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_codeartifact_repository.test" @@ -289,7 +333,7 @@ func testAccCheckAWSCodeArtifactRepositoryDestroy(s *terraform.State) error { return nil } -func testAccAWSCodeArtifactRepositoryBasicConfig(rName string) string { +func testAccAWSCodeArtifactRepositoryBaseConfig(rName string) string { return fmt.Sprintf(` resource "aws_kms_key" "test" { description = %[1]q @@ -300,7 +344,11 @@ resource "aws_codeartifact_domain" "test" { domain = %[1]q encryption_key = aws_kms_key.test.arn } +`, rName) +} +func testAccAWSCodeArtifactRepositoryBasicConfig(rName string) string { + return testAccAWSCodeArtifactRepositoryBaseConfig(rName) + fmt.Sprintf(` resource "aws_codeartifact_repository" "test" { repository = %[1]q domain = aws_codeartifact_domain.test.domain @@ -309,17 +357,7 @@ resource "aws_codeartifact_repository" "test" { } func testAccAWSCodeArtifactRepositoryOwnerConfig(rName string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_codeartifact_domain" "test" { - domain = %[1]q - encryption_key = aws_kms_key.test.arn -} - + return testAccAWSCodeArtifactRepositoryBaseConfig(rName) + fmt.Sprintf(` resource "aws_codeartifact_repository" "test" { repository = %[1]q domain = aws_codeartifact_domain.test.domain @@ -329,17 +367,7 @@ resource "aws_codeartifact_repository" "test" { } func testAccAWSCodeArtifactRepositoryDescConfig(rName, desc string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_codeartifact_domain" "test" { - domain = %[1]q - encryption_key = aws_kms_key.test.arn -} - + return testAccAWSCodeArtifactRepositoryBaseConfig(rName) + fmt.Sprintf(` resource "aws_codeartifact_repository" "test" { repository = %[1]q domain = aws_codeartifact_domain.test.domain @@ -349,17 +377,7 @@ resource "aws_codeartifact_repository" "test" { } func testAccAWSCodeArtifactRepositoryUpstreamsConfig1(rName string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_codeartifact_domain" "test" { - domain = %[1]q - encryption_key = aws_kms_key.test.arn -} - + return testAccAWSCodeArtifactRepositoryBaseConfig(rName) + fmt.Sprintf(` resource "aws_codeartifact_repository" "upstream1" { repository = "%[1]s-upstream1" domain = aws_codeartifact_domain.test.domain @@ -377,17 +395,7 @@ resource "aws_codeartifact_repository" "test" { } func testAccAWSCodeArtifactRepositoryUpstreamsConfig2(rName string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_codeartifact_domain" "test" { - domain = %[1]q - encryption_key = aws_kms_key.test.arn -} - + return testAccAWSCodeArtifactRepositoryBaseConfig(rName) + fmt.Sprintf(` resource "aws_codeartifact_repository" "upstream1" { repository = "%[1]s-upstream1" domain = aws_codeartifact_domain.test.domain @@ -412,3 +420,16 @@ resource "aws_codeartifact_repository" "test" { } `, rName) } + +func testAccAWSCodeArtifactRepositoryExternalConnectionConfig(rName string) string { + return testAccAWSCodeArtifactRepositoryBaseConfig(rName) + fmt.Sprintf(` +resource "aws_codeartifact_repository" "test" { + repository = %[1]q + domain = aws_codeartifact_domain.test.domain + + external_connections { + external_connection_name = "public:npmjs" + } +} +`, rName) +} diff --git a/website/docs/r/codeartifact_repository.html.markdown b/website/docs/r/codeartifact_repository.html.markdown index 8c8473a86cc..cdcbcd9f95c 100644 --- a/website/docs/r/codeartifact_repository.html.markdown +++ b/website/docs/r/codeartifact_repository.html.markdown @@ -46,6 +46,24 @@ resource "aws_codeartifact_repository" "test" { } ``` +## Example Usage with external connection + +```hcl +resource "aws_codeartifact_repository" "upstream" { + repository = "upstream" + domain = aws_codeartifact_domain.test.domain +} + +resource "aws_codeartifact_repository" "test" { + repository = "example" + domain = aws_codeartifact_domain.example.domain + + external_connections { + external_connection_name = "public:npmjs" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -55,11 +73,16 @@ The following arguments are supported: * `domain_owner` - (Optional) The account number of the AWS account that owns the domain. * `description` - (Optional) The description of the repository. * `upstream` - (Optional) A list of upstream repositories to associate with the repository. The order of the upstream repositories in the list determines their priority order when AWS CodeArtifact looks for a requested package version. see [Upstream](#upstream) +* `external_connections` - An array of external connections associated with the repository. Only one external connection can be set per repository. see [External Connections](#external-connections). ### Upstream * `repository_name` - (Required) The name of an upstream repository. +### External Connections + +* `external_connection_name` - (Required) The name of the external connection associated with a repository. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -67,13 +90,6 @@ In addition to all arguments above, the following attributes are exported: * `id` - The Name of the repository. * `arn` - The ARN of the repository. * `administrator_account` - The account number of the AWS account that manages the repository. -* `external_connections` - An array of external connections associated with the repository. see [External Connections](#external-connections) - -### External Connections - -* `external_connection_name` - The name of the external connection associated with a repository. -* `package_format` - The package format associated with a repository's external connection. -* `status` - The status of the external connection of a repository. ## Import