diff --git a/aws/provider.go b/aws/provider.go index a2d0c4d2db9..a72de75a74f 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -492,6 +492,7 @@ func Provider() *schema.Provider { "aws_codecommit_trigger": resourceAwsCodeCommitTrigger(), "aws_codeartifact_domain": resourceAwsCodeArtifactDomain(), "aws_codeartifact_domain_permissions_policy": resourceAwsCodeArtifactDomainPermissionsPolicy(), + "aws_codeartifact_repository": resourceAwsCodeArtifactRepository(), "aws_codebuild_project": resourceAwsCodeBuildProject(), "aws_codebuild_report_group": resourceAwsCodeBuildReportGroup(), "aws_codebuild_source_credential": resourceAwsCodeBuildSourceCredential(), diff --git a/aws/resource_aws_codeartifact_repository.go b/aws/resource_aws_codeartifact_repository.go new file mode 100644 index 00000000000..6479d83e98f --- /dev/null +++ b/aws/resource_aws_codeartifact_repository.go @@ -0,0 +1,288 @@ +package aws + +import ( + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/codeartifact" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceAwsCodeArtifactRepository() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCodeArtifactRepositoryCreate, + Read: resourceAwsCodeArtifactRepositoryRead, + Update: resourceAwsCodeArtifactRepositoryUpdate, + Delete: resourceAwsCodeArtifactRepositoryDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "repository": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "domain": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "domain_owner": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "upstream": { + Type: schema.TypeList, + MinItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repository_name": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "external_connections": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "external_connection_name": { + Type: schema.TypeString, + Computed: true, + }, + "package_format": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "administrator_account": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceAwsCodeArtifactRepositoryCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).codeartifactconn + log.Print("[DEBUG] Creating CodeArtifact Repository") + + params := &codeartifact.CreateRepositoryInput{ + Repository: aws.String(d.Get("repository").(string)), + Domain: aws.String(d.Get("domain").(string)), + } + + if v, ok := d.GetOk("description"); ok { + params.Description = aws.String(v.(string)) + } + + if v, ok := d.GetOk("domain_owner"); ok { + params.DomainOwner = aws.String(v.(string)) + } + + if v, ok := d.GetOk("upstream"); ok { + params.Upstreams = expandCodeArtifactUpstreams(v.([]interface{})) + } + + res, err := conn.CreateRepository(params) + if err != nil { + return fmt.Errorf("error creating CodeArtifact Repository: %w", err) + } + + repo := res.Repository + d.SetId(aws.StringValue(repo.Arn)) + + return resourceAwsCodeArtifactRepositoryRead(d, meta) +} + +func resourceAwsCodeArtifactRepositoryUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).codeartifactconn + log.Print("[DEBUG] Updating CodeArtifact Repository") + + params := &codeartifact.UpdateRepositoryInput{ + Repository: aws.String(d.Get("repository").(string)), + Domain: aws.String(d.Get("domain").(string)), + DomainOwner: aws.String(d.Get("domain_owner").(string)), + } + + if d.HasChange("description") { + if v, ok := d.GetOk("description"); ok { + params.Description = aws.String(v.(string)) + } + } + + if d.HasChange("upstream") { + if v, ok := d.GetOk("upstream"); ok { + params.Upstreams = expandCodeArtifactUpstreams(v.([]interface{})) + } + } + + _, err := conn.UpdateRepository(params) + if err != nil { + return fmt.Errorf("error updating CodeArtifact Repository: %w", err) + } + + return resourceAwsCodeArtifactRepositoryRead(d, meta) +} + +func resourceAwsCodeArtifactRepositoryRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).codeartifactconn + + log.Printf("[DEBUG] Reading CodeArtifact Repository: %s", d.Id()) + + owner, domain, repo, err := decodeCodeArtifactRepositoryID(d.Id()) + if err != nil { + return err + } + sm, err := conn.DescribeRepository(&codeartifact.DescribeRepositoryInput{ + Repository: aws.String(repo), + Domain: aws.String(domain), + DomainOwner: aws.String(owner), + }) + if err != nil { + if isAWSErr(err, codeartifact.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] CodeArtifact Repository %q not found, removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("error reading CodeArtifact Repository (%s): %w", d.Id(), err) + } + + d.Set("repository", sm.Repository.Name) + d.Set("arn", sm.Repository.Arn) + d.Set("domain_owner", sm.Repository.DomainOwner) + d.Set("domain", sm.Repository.DomainName) + d.Set("administrator_account", sm.Repository.AdministratorAccount) + d.Set("description", sm.Repository.Description) + + if sm.Repository.Upstreams != nil { + if err := d.Set("upstream", flattenCodeArtifactUpstreams(sm.Repository.Upstreams)); err != nil { + return fmt.Errorf("[WARN] Error setting upstream: %w", err) + } + } + + if sm.Repository.ExternalConnections != nil { + if err := d.Set("external_connections", flattenCodeArtifactExternalConnections(sm.Repository.ExternalConnections)); err != nil { + return fmt.Errorf("[WARN] Error setting external_connections: %w", err) + } + } + + return nil +} + +func resourceAwsCodeArtifactRepositoryDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).codeartifactconn + log.Printf("[DEBUG] Deleting CodeArtifact Repository: %s", d.Id()) + + owner, domain, repo, err := decodeCodeArtifactRepositoryID(d.Id()) + if err != nil { + return err + } + input := &codeartifact.DeleteRepositoryInput{ + Repository: aws.String(repo), + Domain: aws.String(domain), + DomainOwner: aws.String(owner), + } + + _, err = conn.DeleteRepository(input) + + if isAWSErr(err, codeartifact.ErrCodeResourceNotFoundException, "") { + return nil + } + + if err != nil { + return fmt.Errorf("error deleting CodeArtifact Repository (%s): %w", d.Id(), err) + } + + return nil +} + +func expandCodeArtifactUpstreams(l []interface{}) []*codeartifact.UpstreamRepository { + upstreams := []*codeartifact.UpstreamRepository{} + + for _, mRaw := range l { + m := mRaw.(map[string]interface{}) + upstream := &codeartifact.UpstreamRepository{ + RepositoryName: aws.String(m["repository_name"].(string)), + } + + upstreams = append(upstreams, upstream) + } + + return upstreams +} + +func flattenCodeArtifactUpstreams(upstreams []*codeartifact.UpstreamRepositoryInfo) []interface{} { + if len(upstreams) == 0 { + return nil + } + + var ls []interface{} + + for _, upstream := range upstreams { + m := map[string]interface{}{ + "repository_name": aws.StringValue(upstream.RepositoryName), + } + + ls = append(ls, m) + } + + return ls +} + +func flattenCodeArtifactExternalConnections(connections []*codeartifact.RepositoryExternalConnectionInfo) []interface{} { + if len(connections) == 0 { + return nil + } + + var ls []interface{} + + for _, connection := range connections { + m := map[string]interface{}{ + "external_connection_name": aws.StringValue(connection.ExternalConnectionName), + "package_format": aws.StringValue(connection.PackageFormat), + "status": aws.StringValue(connection.Status), + } + + ls = append(ls, m) + } + + return ls +} + +func decodeCodeArtifactRepositoryID(id string) (string, string, string, error) { + repoArn, err := arn.Parse(id) + if err != nil { + return "", "", "", err + } + + idParts := strings.Split(strings.TrimPrefix(repoArn.Resource, "repository/"), "/") + if len(idParts) != 2 { + return "", "", "", fmt.Errorf("expected resource part of arn in format DomainName/RepositoryName, received: %s", repoArn.Resource) + } + return repoArn.AccountID, idParts[0], idParts[1], nil +} diff --git a/aws/resource_aws_codeartifact_repository_test.go b/aws/resource_aws_codeartifact_repository_test.go new file mode 100644 index 00000000000..d99851ed283 --- /dev/null +++ b/aws/resource_aws_codeartifact_repository_test.go @@ -0,0 +1,414 @@ +package aws + +import ( + "fmt" + "log" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/codeartifact" + "github.com/hashicorp/go-multierror" + "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" +) + +func init() { + resource.AddTestSweepers("aws_codeartifact_repository", &resource.Sweeper{ + Name: "aws_codeartifact_repository", + F: testSweepCodeArtifactRepositories, + }) +} + +func testSweepCodeArtifactRepositories(region string) error { + client, err := sharedClientForRegion(region) + if err != nil { + return fmt.Errorf("error getting client: %w", err) + } + conn := client.(*AWSClient).codeartifactconn + input := &codeartifact.ListRepositoriesInput{} + var sweeperErrs *multierror.Error + + err = conn.ListRepositoriesPages(input, func(page *codeartifact.ListRepositoriesOutput, lastPage bool) bool { + for _, repositoryPtr := range page.Repositories { + if repositoryPtr == nil { + continue + } + + repository := aws.StringValue(repositoryPtr.Name) + input := &codeartifact.DeleteRepositoryInput{ + Repository: repositoryPtr.Name, + Domain: repositoryPtr.DomainName, + DomainOwner: repositoryPtr.DomainOwner, + } + + log.Printf("[INFO] Deleting CodeArtifact Repository: %s", repository) + + _, err := conn.DeleteRepository(input) + + if err != nil { + sweeperErr := fmt.Errorf("error deleting CodeArtifact Repository (%s): %w", repository, err) + log.Printf("[ERROR] %s", sweeperErr) + sweeperErrs = multierror.Append(sweeperErrs, sweeperErr) + } + } + + return !lastPage + }) + + if testSweepSkipSweepError(err) { + log.Printf("[WARN] Skipping CodeArtifact Repository sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing CodeArtifact Repositories: %w", err) + } + + return sweeperErrs.ErrorOrNil() +} + +func TestAccAWSCodeArtifactRepository_basic(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codeartifact_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeArtifactRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeArtifactRepositoryBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "codeartifact", fmt.Sprintf("repository/%s/%s", rName, rName)), + resource.TestCheckResourceAttr(resourceName, "repository", rName), + resource.TestCheckResourceAttr(resourceName, "domain", rName), + resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"), + resource.TestCheckResourceAttrPair(resourceName, "administrator_account", "aws_codeartifact_domain.test", "owner"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "upstream.#", "0"), + resource.TestCheckResourceAttr(resourceName, "external_connections.#", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSCodeArtifactRepository_owner(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codeartifact_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeArtifactRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeArtifactRepositoryOwnerConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "codeartifact", fmt.Sprintf("repository/%s/%s", rName, rName)), + resource.TestCheckResourceAttr(resourceName, "repository", rName), + resource.TestCheckResourceAttr(resourceName, "domain", rName), + resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"), + resource.TestCheckResourceAttrPair(resourceName, "administrator_account", "aws_codeartifact_domain.test", "owner"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "upstream.#", "0"), + resource.TestCheckResourceAttr(resourceName, "external_connections.#", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSCodeArtifactRepository_description(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codeartifact_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeArtifactRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeArtifactRepositoryDescConfig(rName, "desc"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", "desc"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSCodeArtifactRepositoryDescConfig(rName, "desc2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", "desc2"), + ), + }, + }, + }) +} + +func TestAccAWSCodeArtifactRepository_upstreams(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codeartifact_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeArtifactRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeArtifactRepositoryUpstreamsConfig1(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "upstream.#", "1"), + resource.TestCheckResourceAttr(resourceName, "upstream.0.repository_name", fmt.Sprintf("%s-upstream1", rName)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSCodeArtifactRepositoryUpstreamsConfig2(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "upstream.#", "2"), + resource.TestCheckResourceAttr(resourceName, "upstream.0.repository_name", fmt.Sprintf("%s-upstream1", rName)), + resource.TestCheckResourceAttr(resourceName, "upstream.1.repository_name", fmt.Sprintf("%s-upstream2", rName)), + ), + }, + { + Config: testAccAWSCodeArtifactRepositoryUpstreamsConfig1(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "upstream.#", "1"), + resource.TestCheckResourceAttr(resourceName, "upstream.0.repository_name", fmt.Sprintf("%s-upstream1", rName)), + ), + }, + }, + }) +} + +func TestAccAWSCodeArtifactRepository_disappears(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codeartifact_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeArtifactRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeArtifactRepositoryBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeArtifactRepositoryExists(resourceName), + testAccCheckResourceDisappears(testAccProvider, resourceAwsCodeArtifactRepository(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSCodeArtifactRepositoryExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no CodeArtifact repository set") + } + + conn := testAccProvider.Meta().(*AWSClient).codeartifactconn + owner, domain, repo, err := decodeCodeArtifactRepositoryID(rs.Primary.ID) + if err != nil { + return err + } + _, err = conn.DescribeRepository(&codeartifact.DescribeRepositoryInput{ + Repository: aws.String(repo), + Domain: aws.String(domain), + DomainOwner: aws.String(owner), + }) + + return err + } +} + +func testAccCheckAWSCodeArtifactRepositoryDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_codeartifact_repository" { + continue + } + + owner, domain, repo, err := decodeCodeArtifactRepositoryID(rs.Primary.ID) + if err != nil { + return err + } + conn := testAccProvider.Meta().(*AWSClient).codeartifactconn + resp, err := conn.DescribeRepository(&codeartifact.DescribeRepositoryInput{ + Repository: aws.String(repo), + Domain: aws.String(domain), + DomainOwner: aws.String(owner), + }) + + if err == nil { + if aws.StringValue(resp.Repository.Name) == repo && + aws.StringValue(resp.Repository.DomainName) == domain && + aws.StringValue(resp.Repository.DomainOwner) == owner { + return fmt.Errorf("CodeArtifact Repository %s in Domain %s still exists", repo, domain) + } + } + + if isAWSErr(err, codeartifact.ErrCodeResourceNotFoundException, "") { + return nil + } + + return err + } + + return nil +} + +func testAccAWSCodeArtifactRepositoryBasicConfig(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 +} + +resource "aws_codeartifact_repository" "test" { + repository = %[1]q + domain = aws_codeartifact_domain.test.domain +} +`, rName) +} + +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 +} + +resource "aws_codeartifact_repository" "test" { + repository = %[1]q + domain = aws_codeartifact_domain.test.domain + domain_owner = aws_codeartifact_domain.test.owner +} +`, rName) +} + +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 +} + +resource "aws_codeartifact_repository" "test" { + repository = %[1]q + domain = aws_codeartifact_domain.test.domain + description = %[2]q +} +`, rName, desc) +} + +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 +} + +resource "aws_codeartifact_repository" "upstream1" { + repository = "%[1]s-upstream1" + domain = aws_codeartifact_domain.test.domain +} + +resource "aws_codeartifact_repository" "test" { + repository = %[1]q + domain = aws_codeartifact_domain.test.domain + + upstream { + repository_name = aws_codeartifact_repository.upstream1.repository + } +} +`, rName) +} + +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 +} + +resource "aws_codeartifact_repository" "upstream1" { + repository = "%[1]s-upstream1" + domain = aws_codeartifact_domain.test.domain +} + +resource "aws_codeartifact_repository" "upstream2" { + repository = "%[1]s-upstream2" + domain = aws_codeartifact_domain.test.domain +} + +resource "aws_codeartifact_repository" "test" { + repository = %[1]q + domain = aws_codeartifact_domain.test.domain + + upstream { + repository_name = aws_codeartifact_repository.upstream1.repository + } + + upstream { + repository_name = aws_codeartifact_repository.upstream2.repository + } +} +`, rName) +} diff --git a/website/docs/r/codeartifact_repository.html.markdown b/website/docs/r/codeartifact_repository.html.markdown new file mode 100644 index 00000000000..8c8473a86cc --- /dev/null +++ b/website/docs/r/codeartifact_repository.html.markdown @@ -0,0 +1,84 @@ +--- +subcategory: "CodeArtifact" +layout: "aws" +page_title: "AWS: aws_codeartifact_repository" +description: |- + Provides a CodeArtifact Repository resource. +--- + +# Resource: aws_codeartifact_repository + +Provides a CodeArtifact Repository Resource. + +## Example Usage + +```hcl +resource "aws_kms_key" "example" { + description = "domain key" +} + +resource "aws_codeartifact_domain" "example" { + domain = "example" + encryption_key = aws_kms_key.example.arn +} + +resource "aws_codeartifact_repository" "test" { + repository = "example" + domain = aws_codeartifact_domain.example.domain +} +``` + +## Example Usage with upstream repository + +```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 + + upstream { + repository_name = aws_codeartifact_repository.upstream.repository + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `domain` - (Required) The domain that contains the created repository. +* `repository` - (Required) The name of the repository to create. +* `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) + +### Upstream + +* `repository_name` - (Required) The name of an upstream repository. + +## Attributes Reference + +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 + +CodeArtifact Repository can be imported using the CodeArtifact Repository ARN, e.g. + +``` +$ terraform import aws_codeartifact_repository.example arn:aws:codeartifact:us-west-2:012345678912:repository/tf-acc-test-6968272603913957763/tf-acc-test-6968272603913957763 +```