Skip to content

Commit ab65789

Browse files
authored
Add plural data source for retrieving Artifact Registry packages (#14674)
1 parent 8e1c96b commit ab65789

File tree

4 files changed

+272
-0
lines changed

4 files changed

+272
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
3434
"google_artifact_registry_npm_package": artifactregistry.DataSourceArtifactRegistryNpmPackage(),
3535
"google_artifact_registry_npm_packages": artifactregistry.DataSourceArtifactRegistryNpmPackages(),
3636
"google_artifact_registry_package": artifactregistry.DataSourceArtifactRegistryPackage(),
37+
"google_artifact_registry_packages": artifactregistry.DataSourceArtifactRegistryPackages(),
3738
"google_artifact_registry_python_package": artifactregistry.DataSourceArtifactRegistryPythonPackage(),
3839
"google_artifact_registry_repositories": artifactregistry.DataSourceArtifactRegistryRepositories(),
3940
"google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(),
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
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 DataSourceArtifactRegistryPackages() *schema.Resource {
14+
return &schema.Resource{
15+
Read: dataSourceArtifactRegistryPackagesRead,
16+
Schema: map[string]*schema.Schema{
17+
"location": {
18+
Type: schema.TypeString,
19+
Required: true,
20+
},
21+
"repository_id": {
22+
Type: schema.TypeString,
23+
Required: true,
24+
},
25+
"filter": {
26+
Type: schema.TypeString,
27+
Optional: true,
28+
},
29+
"project": {
30+
Type: schema.TypeString,
31+
Optional: true,
32+
},
33+
"packages": {
34+
Type: schema.TypeList,
35+
Computed: true,
36+
Elem: &schema.Resource{
37+
Schema: map[string]*schema.Schema{
38+
"name": {
39+
Type: schema.TypeString,
40+
Computed: true,
41+
},
42+
"display_name": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
},
46+
"create_time": {
47+
Type: schema.TypeString,
48+
Computed: true,
49+
},
50+
"update_time": {
51+
Type: schema.TypeString,
52+
Computed: true,
53+
},
54+
"annotations": {
55+
Type: schema.TypeMap,
56+
Computed: true,
57+
Elem: &schema.Schema{Type: schema.TypeString},
58+
},
59+
},
60+
},
61+
},
62+
},
63+
}
64+
}
65+
66+
func dataSourceArtifactRegistryPackagesRead(d *schema.ResourceData, meta interface{}) error {
67+
config := meta.(*transport_tpg.Config)
68+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
69+
if err != nil {
70+
return err
71+
}
72+
73+
project, err := tpgresource.GetProject(d, config)
74+
if err != nil {
75+
return err
76+
}
77+
78+
basePath, err := tpgresource.ReplaceVars(d, config, "{{ArtifactRegistryBasePath}}")
79+
if err != nil {
80+
return fmt.Errorf("Error setting Artifact Registry base path: %s", err)
81+
}
82+
83+
resourcePath, err := tpgresource.ReplaceVars(d, config, fmt.Sprintf("projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}/packages"))
84+
if err != nil {
85+
return fmt.Errorf("Error setting resource path: %s", err)
86+
}
87+
88+
urlRequest := basePath + resourcePath
89+
90+
filter := ""
91+
if v, ok := d.GetOk("filter"); ok {
92+
filter = v.(string)
93+
94+
u, err := url.Parse(urlRequest)
95+
if err != nil {
96+
return fmt.Errorf("Error parsing URL: %s", err)
97+
}
98+
99+
q := u.Query()
100+
q.Set("filter", filter)
101+
u.RawQuery = q.Encode()
102+
urlRequest = u.String()
103+
}
104+
105+
headers := make(http.Header)
106+
packages := make([]map[string]interface{}, 0)
107+
pageToken := ""
108+
109+
for {
110+
u, err := url.Parse(urlRequest)
111+
if err != nil {
112+
return fmt.Errorf("Error parsing URL: %s", err)
113+
}
114+
115+
q := u.Query()
116+
if pageToken != "" {
117+
q.Set("pageToken", pageToken)
118+
}
119+
u.RawQuery = q.Encode()
120+
121+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
122+
Config: config,
123+
Method: "GET",
124+
RawURL: u.String(),
125+
UserAgent: userAgent,
126+
Headers: headers,
127+
})
128+
129+
if err != nil {
130+
return fmt.Errorf("Error listing Artifact Registry packages: %s", err)
131+
}
132+
133+
if items, ok := res["packages"].([]interface{}); ok {
134+
for _, item := range items {
135+
pkg := item.(map[string]interface{})
136+
137+
annotations := make(map[string]string)
138+
if anno, ok := pkg["annotations"].(map[string]interface{}); ok {
139+
for k, v := range anno {
140+
if val, ok := v.(string); ok {
141+
annotations[k] = val
142+
}
143+
}
144+
}
145+
146+
getString := func(m map[string]interface{}, key string) string {
147+
if v, ok := m[key].(string); ok {
148+
return v
149+
}
150+
return ""
151+
}
152+
153+
packages = append(packages, map[string]interface{}{
154+
"name": getString(pkg, "name"),
155+
"display_name": getString(pkg, "displayName"),
156+
"create_time": getString(pkg, "createTime"),
157+
"update_time": getString(pkg, "updateTime"),
158+
"annotations": annotations,
159+
})
160+
}
161+
}
162+
163+
if nextToken, ok := res["nextPageToken"].(string); ok && nextToken != "" {
164+
pageToken = nextToken
165+
} else {
166+
break
167+
}
168+
}
169+
170+
if err := d.Set("project", project); err != nil {
171+
return fmt.Errorf("Error setting project: %s", err)
172+
}
173+
174+
if err := d.Set("packages", packages); err != nil {
175+
return fmt.Errorf("Error setting Artifact Registry packages: %s", err)
176+
}
177+
178+
d.SetId(resourcePath)
179+
180+
return nil
181+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
)
9+
10+
func TestAccDataSourceArtifactRegistryPackages_basic(t *testing.T) {
11+
t.Parallel()
12+
13+
acctest.VcrTest(t, resource.TestCase{
14+
PreCheck: func() { acctest.AccTestPreCheck(t) },
15+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
16+
Steps: []resource.TestStep{
17+
{
18+
Config: testAccDataSourceArtifactRegistryPackagesConfig,
19+
Check: resource.ComposeTestCheckFunc(
20+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_packages.this", "project"),
21+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_packages.this", "location"),
22+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_packages.this", "repository_id"),
23+
resource.TestCheckResourceAttrSet("data.google_artifact_registry_packages.this", "packages.0.name"),
24+
),
25+
},
26+
},
27+
})
28+
}
29+
30+
// Test the data source against the public AR repos
31+
// https://console.cloud.google.com/artifacts/docker/cloudrun/us/container
32+
// https://console.cloud.google.com/artifacts/docker/go-containerregistry/us/gcr.io
33+
const testAccDataSourceArtifactRegistryPackagesConfig = `
34+
data "google_artifact_registry_packages" "this" {
35+
project = "go-containerregistry"
36+
location = "us"
37+
repository_id = "gcr.io"
38+
filter = "name=\"projects/go-containerregistry/locations/us/repositories/gcr.io/packages/gcrane\""
39+
}
40+
`
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
subcategory: "Artifact Registry"
3+
description: |-
4+
Get information about packages within a Google Artifact Registry repository.
5+
---
6+
7+
# google_artifact_registry_packages
8+
9+
Get information about Artifact Registry packages.
10+
See [the official documentation](https://cloud.google.com/artifact-registry/docs/overview)
11+
and [API](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories.packages/list).
12+
13+
## Example Usage
14+
15+
```hcl
16+
data "google_artifact_registry_packages" "my_images" {
17+
location = "us-central1"
18+
repository_id = "example-repo"
19+
}
20+
```
21+
22+
## Argument Reference
23+
24+
The following arguments are supported:
25+
26+
* `location` - (Required) The location of the Artifact Registry repository.
27+
28+
* `repository_id` - (Required) The last part of the repository name to fetch from.
29+
30+
* `filter` - (Optional) An expression for filtering the results of the request. Filter rules are case insensitive. The fields eligible for filtering are `name` and `annotations`. Further information can be found in the [REST API](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories.packages/list#query-parameters).
31+
32+
* `project` - (Optional) The project ID in which the resource belongs. If it is not provided, the provider project is used.
33+
34+
## Attributes Reference
35+
36+
The following attributes are exported:
37+
38+
* `packages` - A list of all retrieved Artifact Registry packages. Structure is [defined below](#nested_packages).
39+
40+
<a name="nested_packages"></a>The `packages` block supports:
41+
42+
* `name` - The name of the package, for example: `projects/p1/locations/us-central1/repositories/repo1/packages/pkg1`. If the package ID part contains slashes, the slashes are escaped.
43+
44+
* `display_name` - The display name of the package.
45+
46+
* `create_time` - The time, as a RFC 3339 string, this package was created.
47+
48+
* `update_time` - The time, as a RFC 3339 string, this package was last updated. This includes publishing a new version of the package.
49+
50+
* `annotations` - Client specified annotations.

0 commit comments

Comments
 (0)