Skip to content

Commit 4002178

Browse files
authored
Add plural data source for retrieving Artifact Registry repositories (#14633)
1 parent 0692e14 commit 4002178

4 files changed

Lines changed: 349 additions & 0 deletions

File tree

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
2929
"google_artifact_registry_docker_image": artifactregistry.DataSourceArtifactRegistryDockerImage(),
3030
"google_artifact_registry_docker_images": artifactregistry.DataSourceArtifactRegistryDockerImages(),
3131
"google_artifact_registry_locations": artifactregistry.DataSourceGoogleArtifactRegistryLocations(),
32+
"google_artifact_registry_repositories": artifactregistry.DataSourceArtifactRegistryRepositories(),
3233
"google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(),
3334
"google_artifact_registry_package": artifactregistry.DataSourceArtifactRegistryPackage(),
3435
"google_artifact_registry_version": artifactregistry.DataSourceArtifactRegistryVersion(),
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package artifactregistry
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
)
12+
13+
func DataSourceArtifactRegistryRepositories() *schema.Resource {
14+
return &schema.Resource{
15+
Read: dataSourceArtifactRegistryRepositoriesRead,
16+
Schema: map[string]*schema.Schema{
17+
"location": {
18+
Type: schema.TypeString,
19+
Required: true,
20+
},
21+
"name_filter": {
22+
Type: schema.TypeString,
23+
Optional: true,
24+
},
25+
"project": {
26+
Type: schema.TypeString,
27+
Optional: true,
28+
},
29+
"repositories": {
30+
Type: schema.TypeList,
31+
Computed: true,
32+
Elem: &schema.Resource{
33+
Schema: map[string]*schema.Schema{
34+
"id": {
35+
Type: schema.TypeString,
36+
Computed: true,
37+
},
38+
"repository_id": {
39+
Type: schema.TypeString,
40+
Computed: true,
41+
},
42+
"format": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
},
46+
"description": {
47+
Type: schema.TypeString,
48+
Computed: true,
49+
},
50+
"create_time": {
51+
Type: schema.TypeString,
52+
Computed: true,
53+
},
54+
"update_time": {
55+
Type: schema.TypeString,
56+
Computed: true,
57+
},
58+
},
59+
},
60+
},
61+
},
62+
}
63+
}
64+
65+
func dataSourceArtifactRegistryRepositoriesRead(d *schema.ResourceData, meta interface{}) error {
66+
config := meta.(*transport_tpg.Config)
67+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
68+
if err != nil {
69+
return err
70+
}
71+
72+
project, err := tpgresource.GetProject(d, config)
73+
if err != nil {
74+
return err
75+
}
76+
77+
basePath, err := tpgresource.ReplaceVars(d, config, "{{ArtifactRegistryBasePath}}")
78+
if err != nil {
79+
return fmt.Errorf("Error setting Artifact Registry base path: %s", err)
80+
}
81+
82+
resourcePath, err := tpgresource.ReplaceVars(d, config, fmt.Sprintf("projects/{{project}}/locations/{{location}}/repositories"))
83+
if err != nil {
84+
return fmt.Errorf("Error setting resource path: %s", err)
85+
}
86+
87+
urlRequest := basePath + resourcePath
88+
89+
nameFilter := ""
90+
if v, ok := d.GetOk("name_filter"); ok {
91+
nameFilter = fmt.Sprintf("name=\"%s/%s\"", resourcePath, v.(string))
92+
93+
u, err := url.Parse(urlRequest)
94+
if err != nil {
95+
return fmt.Errorf("Error parsing URL: %s", err)
96+
}
97+
98+
q := u.Query()
99+
q.Set("filter", nameFilter)
100+
u.RawQuery = q.Encode()
101+
urlRequest = u.String()
102+
}
103+
104+
headers := make(http.Header)
105+
repos := make([]map[string]interface{}, 0)
106+
pageToken := ""
107+
108+
for {
109+
u, err := url.Parse(urlRequest)
110+
if err != nil {
111+
return fmt.Errorf("Error parsing URL: %s", err)
112+
}
113+
114+
q := u.Query()
115+
if nameFilter != "" {
116+
q.Set("filter", nameFilter)
117+
}
118+
if pageToken != "" {
119+
q.Set("pageToken", pageToken)
120+
}
121+
u.RawQuery = q.Encode()
122+
123+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
124+
Config: config,
125+
Method: "GET",
126+
RawURL: u.String(),
127+
UserAgent: userAgent,
128+
Headers: headers,
129+
})
130+
131+
if err != nil {
132+
return fmt.Errorf("Error listing Artifact Registry repositories: %s", err)
133+
}
134+
135+
if items, ok := res["repositories"].([]interface{}); ok {
136+
for _, item := range items {
137+
repo := item.(map[string]interface{})
138+
repos = append(repos, map[string]interface{}{
139+
"id": repo["name"],
140+
"repository_id": tpgresource.GetResourceNameFromSelfLink(repo["name"].(string)),
141+
"format": repo["format"],
142+
"description": repo["description"],
143+
"create_time": repo["createTime"],
144+
"update_time": repo["updateTime"],
145+
})
146+
}
147+
}
148+
149+
if nextToken, ok := res["nextPageToken"].(string); ok && nextToken != "" {
150+
pageToken = nextToken
151+
} else {
152+
break
153+
}
154+
}
155+
156+
if err := d.Set("project", project); err != nil {
157+
return fmt.Errorf("Error setting project: %s", err)
158+
}
159+
160+
if err := d.Set("repositories", repos); err != nil {
161+
return fmt.Errorf("Error setting Artifact Registry repositories: %s", err)
162+
}
163+
164+
setId := resourcePath
165+
166+
if nameFilter != "" {
167+
setId += "/" + nameFilter
168+
}
169+
170+
d.SetId(setId)
171+
172+
return nil
173+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package artifactregistry_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
7+
"github.com/hashicorp/terraform-provider-google/google/acctest"
8+
"github.com/hashicorp/terraform-provider-google/google/envvar"
9+
)
10+
11+
func TestAccDataSourceArtifactRegistryRepositories_basic(t *testing.T) {
12+
t.Parallel()
13+
14+
context := map[string]interface{}{
15+
"location": envvar.GetTestRegionFromEnv(),
16+
"random_suffix": acctest.RandString(t, 8),
17+
}
18+
19+
acctest.VcrTest(t, resource.TestCase{
20+
PreCheck: func() { acctest.AccTestPreCheck(t) },
21+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccDataSourceArtifactRegistryRepositoriesConfig(context),
25+
Check: resource.ComposeTestCheckFunc(
26+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "project"),
27+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.0.id"),
28+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.1.id"),
29+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.2.id"),
30+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.0.repository_id"),
31+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.0.format"),
32+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.0.create_time"),
33+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.all", "repositories.0.update_time"),
34+
),
35+
},
36+
{
37+
Config: testAccDataSourceArtifactRegistryRepositoriesConfigWithFilter(context),
38+
Check: resource.ComposeTestCheckFunc(
39+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.filtered", "repositories.0.id"),
40+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.filtered", "repositories.0.repository_id"),
41+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.filtered", "repositories.0.format"),
42+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.filtered", "repositories.0.create_time"),
43+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_repositories.filtered", "repositories.0.update_time"),
44+
),
45+
},
46+
},
47+
})
48+
}
49+
50+
func testAccDataSourceArtifactRegistryRepositoriesConfig(context map[string]interface{}) string {
51+
return acctest.Nprintf(`
52+
resource "google_artifact_registry_repository" "repo1" {
53+
location = "%{location}"
54+
repository_id = "tf-test-repo1%{random_suffix}"
55+
format = "DOCKER"
56+
description = "repo1 desc"
57+
}
58+
59+
resource "google_artifact_registry_repository" "repo2" {
60+
location = "%{location}"
61+
repository_id = "tf-test-repo2%{random_suffix}"
62+
format = "DOCKER"
63+
description = "repo2 desc"
64+
}
65+
66+
resource "google_artifact_registry_repository" "repo3" {
67+
location = "%{location}"
68+
repository_id = "tf-test-repo3%{random_suffix}"
69+
format = "DOCKER"
70+
description = "repo3 desc"
71+
}
72+
73+
data "google_artifact_registry_repositories" "all" {
74+
location = "%{location}"
75+
76+
depends_on = [
77+
google_artifact_registry_repository.repo1,
78+
google_artifact_registry_repository.repo2,
79+
google_artifact_registry_repository.repo3,
80+
]
81+
}
82+
`, context)
83+
}
84+
85+
func testAccDataSourceArtifactRegistryRepositoriesConfigWithFilter(context map[string]interface{}) string {
86+
return acctest.Nprintf(`
87+
resource "google_artifact_registry_repository" "repo1" {
88+
location = "%{location}"
89+
repository_id = "tf-test-repo1%{random_suffix}"
90+
format = "DOCKER"
91+
description = "repo1 desc"
92+
}
93+
94+
resource "google_artifact_registry_repository" "repo2" {
95+
location = "%{location}"
96+
repository_id = "tf-test-repo2%{random_suffix}"
97+
format = "DOCKER"
98+
description = "repo2 desc"
99+
}
100+
101+
resource "google_artifact_registry_repository" "repo3" {
102+
location = "%{location}"
103+
repository_id = "tf-test-repo3%{random_suffix}"
104+
format = "DOCKER"
105+
description = "repo3 desc"
106+
}
107+
108+
resource "google_artifact_registry_repository" "repo4" {
109+
location = "%{location}"
110+
repository_id = "tf-acc-repo4%{random_suffix}"
111+
format = "DOCKER"
112+
description = "acc desc"
113+
}
114+
115+
data "google_artifact_registry_repositories" "filtered" {
116+
location = "%{location}"
117+
name_filter = "*acc*"
118+
119+
depends_on = [
120+
google_artifact_registry_repository.repo1,
121+
google_artifact_registry_repository.repo2,
122+
google_artifact_registry_repository.repo3,
123+
google_artifact_registry_repository.repo4,
124+
]
125+
}
126+
`, context)
127+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
subcategory: "Artifact Registry"
3+
description: |-
4+
Get information about Artifact Registry repositories.
5+
---
6+
7+
# google_artifact_registry_repositories
8+
9+
Get information about Artifact Registry repositories.
10+
See [the official documentation](https://cloud.google.com/artifact-registry/docs)
11+
and [API](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories/list).
12+
13+
```hcl
14+
data "google_artifact_registry_repositories" "example" {
15+
location = "us-central1"
16+
project = "my-project"
17+
}
18+
```
19+
20+
## Argument Reference
21+
22+
The following arguments are supported:
23+
24+
* `location` - (Optional) The location of the artifact registry repositories. eg `us-central1`.
25+
26+
* `name_filter` - (Optional) Optional. An expression for filtering the results by name. You can also use wildcards `*`. I.e. `my-repo`, `*-repo`, `my-*`, `*-re*`. For further information reach out to the [API docs](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories/list).
27+
28+
* `project` - (Optional) The ID of the project. If it is not provided, the provider project is used.
29+
30+
## Attributes Reference
31+
32+
The following attributes are exported:
33+
34+
* `repositories` - A list of all retrieved Artifact Registry repositories. Structure is [defined below](#nested_repositories).
35+
36+
<a name="nested_repositories"></a>The `repositories` block supports:
37+
38+
* `id` - An identifier for the resource with format `projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}`
39+
40+
* `repository_id` - The last part of the repository name, for example: `"repo1"`
41+
42+
* `format` - The format of packages that are stored in the repository. Supported formats can be found [here](https://cloud.google.com/artifact-registry/docs/supported-formats).
43+
44+
* `description` - The user-provided description of the repository.
45+
46+
* `create_time` - The time when the repository was created.
47+
48+
* `update_time` - The time when the repository was last updated.

0 commit comments

Comments
 (0)