Skip to content

Commit 04dbd08

Browse files
Add data source for retrieving multiple GCS buckets from a project (#10444) (#17960)
[upstream:0afb6b573d7554b6b232f7738de08945d5fc1f9b] Signed-off-by: Modular Magician <[email protected]>
1 parent 3b8109d commit 04dbd08

File tree

4 files changed

+323
-0
lines changed

4 files changed

+323
-0
lines changed

google/provider/provider_mmv1_resources.go

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
274274
"google_sql_database_instances": sql.DataSourceSqlDatabaseInstances(),
275275
"google_service_networking_peered_dns_domain": servicenetworking.DataSourceGoogleServiceNetworkingPeeredDNSDomain(),
276276
"google_storage_bucket": storage.DataSourceGoogleStorageBucket(),
277+
"google_storage_buckets": storage.DataSourceGoogleStorageBuckets(),
277278
"google_storage_bucket_object": storage.DataSourceGoogleStorageBucketObject(),
278279
"google_storage_bucket_objects": storage.DataSourceGoogleStorageBucketObjects(),
279280
"google_storage_bucket_object_content": storage.DataSourceGoogleStorageBucketObjectContent(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
// Copyright (c) HashiCorp, Inc.
4+
// SPDX-License-Identifier: MPL-2.0
5+
package storage
6+
7+
import (
8+
"fmt"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
12+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
13+
)
14+
15+
func DataSourceGoogleStorageBuckets() *schema.Resource {
16+
return &schema.Resource{
17+
Read: datasourceGoogleStorageBucketsRead,
18+
Schema: map[string]*schema.Schema{
19+
"prefix": {
20+
Type: schema.TypeString,
21+
Optional: true,
22+
},
23+
"project": {
24+
Type: schema.TypeString,
25+
Optional: true,
26+
},
27+
"buckets": {
28+
Type: schema.TypeList,
29+
Computed: true,
30+
Elem: &schema.Resource{
31+
Schema: map[string]*schema.Schema{
32+
"labels": {
33+
Type: schema.TypeMap,
34+
Computed: true,
35+
Elem: &schema.Schema{Type: schema.TypeString},
36+
},
37+
"location": {
38+
Type: schema.TypeString,
39+
Computed: true,
40+
},
41+
"name": {
42+
Type: schema.TypeString,
43+
Computed: true,
44+
},
45+
"self_link": {
46+
Type: schema.TypeString,
47+
Computed: true,
48+
},
49+
"storage_class": {
50+
Type: schema.TypeString,
51+
Computed: true,
52+
},
53+
},
54+
},
55+
},
56+
},
57+
}
58+
}
59+
60+
func datasourceGoogleStorageBucketsRead(d *schema.ResourceData, meta interface{}) error {
61+
config := meta.(*transport_tpg.Config)
62+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
63+
if err != nil {
64+
return err
65+
}
66+
67+
params := make(map[string]string)
68+
buckets := make([]map[string]interface{}, 0)
69+
70+
for {
71+
url := "https://storage.googleapis.com/storage/v1/b"
72+
73+
params["project"], err = tpgresource.GetProject(d, config)
74+
if err != nil {
75+
return fmt.Errorf("Error fetching project for bucket: %s", err)
76+
}
77+
78+
if v, ok := d.GetOk("prefix"); ok {
79+
params["prefix"] = v.(string)
80+
}
81+
82+
url, err = transport_tpg.AddQueryParams(url, params)
83+
if err != nil {
84+
return err
85+
}
86+
87+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
88+
Config: config,
89+
Method: "GET",
90+
RawURL: url,
91+
UserAgent: userAgent,
92+
})
93+
if err != nil {
94+
return fmt.Errorf("Error retrieving buckets: %s", err)
95+
}
96+
97+
pageBuckets := flattenDatasourceGoogleBucketsList(res["items"])
98+
buckets = append(buckets, pageBuckets...)
99+
100+
pToken, ok := res["nextPageToken"]
101+
if ok && pToken != nil && pToken.(string) != "" {
102+
params["pageToken"] = pToken.(string)
103+
} else {
104+
break
105+
}
106+
}
107+
108+
if err := d.Set("buckets", buckets); err != nil {
109+
return fmt.Errorf("Error retrieving buckets: %s", err)
110+
}
111+
112+
d.SetId(params["project"])
113+
114+
return nil
115+
}
116+
117+
func flattenDatasourceGoogleBucketsList(v interface{}) []map[string]interface{} {
118+
if v == nil {
119+
return make([]map[string]interface{}, 0)
120+
}
121+
122+
ls := v.([]interface{})
123+
buckets := make([]map[string]interface{}, 0, len(ls))
124+
for _, raw := range ls {
125+
o := raw.(map[string]interface{})
126+
127+
var mLabels, mLocation, mName, mSelfLink, mStorageClass interface{}
128+
if oLabels, ok := o["labels"]; ok {
129+
mLabels = oLabels
130+
}
131+
if oLocation, ok := o["location"]; ok {
132+
mLocation = oLocation
133+
}
134+
if oName, ok := o["name"]; ok {
135+
mName = oName
136+
}
137+
if oSelfLink, ok := o["selfLink"]; ok {
138+
mSelfLink = oSelfLink
139+
}
140+
if oStorageClass, ok := o["storageClass"]; ok {
141+
mStorageClass = oStorageClass
142+
}
143+
buckets = append(buckets, map[string]interface{}{
144+
"labels": mLabels,
145+
"location": mLocation,
146+
"name": mName,
147+
"self_link": mSelfLink,
148+
"storage_class": mStorageClass,
149+
})
150+
}
151+
152+
return buckets
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
// Copyright (c) HashiCorp, Inc.
4+
// SPDX-License-Identifier: MPL-2.0
5+
package storage_test
6+
7+
import (
8+
"fmt"
9+
"testing"
10+
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
12+
"github.com/hashicorp/terraform-provider-google/google/acctest"
13+
"github.com/hashicorp/terraform-provider-google/google/envvar"
14+
)
15+
16+
func TestAccDataSourceGoogleStorageBuckets_basic(t *testing.T) {
17+
t.Parallel()
18+
19+
static_prefix := "tf-bucket-test"
20+
random_suffix := acctest.RandString(t, 10)
21+
22+
context := map[string]interface{}{
23+
"billing_account": envvar.GetTestBillingAccountFromEnv(t),
24+
"bucket1": static_prefix + "-1-" + random_suffix,
25+
"bucket2": static_prefix + "-2-" + random_suffix,
26+
"project_id": static_prefix + "-" + random_suffix,
27+
"organization": envvar.GetTestOrgFromEnv(t),
28+
}
29+
30+
acctest.VcrTest(t, resource.TestCase{
31+
PreCheck: func() { acctest.AccTestPreCheck(t) },
32+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
33+
Steps: []resource.TestStep{
34+
{
35+
Config: testAccCheckGoogleStorageBucketsConfig(context),
36+
Check: resource.ComposeTestCheckFunc(
37+
// Test schema
38+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.0.location"),
39+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.0.name"),
40+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.0.self_link"),
41+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.0.storage_class"),
42+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.1.location"),
43+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.1.name"),
44+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.1.self_link"),
45+
resource.TestCheckResourceAttrSet("data.google_storage_buckets.all", "buckets.1.storage_class"),
46+
// Test content
47+
resource.TestCheckResourceAttr("data.google_storage_buckets.all", "project", context["project_id"].(string)),
48+
resource.TestCheckResourceAttr("data.google_storage_buckets.all", "buckets.0.name", context["bucket1"].(string)),
49+
resource.TestCheckResourceAttr("data.google_storage_buckets.all", "buckets.1.name", context["bucket2"].(string)),
50+
// Test with project
51+
resource.TestCheckResourceAttr("data.google_storage_buckets.one", "buckets.0.name", context["bucket1"].(string)),
52+
// Test prefix
53+
resource.TestCheckResourceAttr("data.google_storage_buckets.two", "buckets.0.name", context["bucket2"].(string)),
54+
),
55+
},
56+
},
57+
})
58+
}
59+
60+
func testAccCheckGoogleStorageBucketsConfig(context map[string]interface{}) string {
61+
return fmt.Sprintf(`
62+
locals {
63+
billing_account = "%s"
64+
bucket_one = "%s"
65+
bucket_two = "%s"
66+
organization = "%s"
67+
project_id = "%s"
68+
}
69+
70+
resource "google_project" "acceptance" {
71+
name = local.project_id
72+
project_id = local.project_id
73+
org_id = local.organization
74+
billing_account = local.billing_account
75+
}
76+
77+
resource "google_storage_bucket" "one" {
78+
force_destroy = true
79+
location = "EU"
80+
name = local.bucket_one
81+
project = google_project.acceptance.project_id
82+
uniform_bucket_level_access = true
83+
}
84+
85+
resource "google_storage_bucket" "two" {
86+
force_destroy = true
87+
location = "EU"
88+
name = local.bucket_two
89+
project = google_project.acceptance.project_id
90+
uniform_bucket_level_access = true
91+
}
92+
93+
data "google_storage_buckets" "all" {
94+
project = google_project.acceptance.project_id
95+
96+
depends_on = [
97+
google_storage_bucket.one,
98+
google_storage_bucket.two,
99+
]
100+
}
101+
102+
data "google_storage_buckets" "one" {
103+
prefix = "tf-bucket-test-1"
104+
project = google_project.acceptance.project_id
105+
106+
depends_on = [
107+
google_storage_bucket.one,
108+
]
109+
}
110+
111+
data "google_storage_buckets" "two" {
112+
prefix = "tf-bucket-test-2"
113+
project = google_project.acceptance.project_id
114+
115+
depends_on = [
116+
google_storage_bucket.two,
117+
]
118+
}`,
119+
context["billing_account"].(string),
120+
context["bucket1"].(string),
121+
context["bucket2"].(string),
122+
context["organization"].(string),
123+
context["project_id"].(string),
124+
)
125+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
subcategory: "Cloud Storage"
3+
description: |-
4+
Retrieve information about a set of GCS buckets in a project.
5+
---
6+
7+
8+
# google\_storage\_buckets
9+
10+
Gets a list of existing GCS buckets.
11+
See [the official documentation](https://cloud.google.com/storage/docs/introduction)
12+
and [API](https://cloud.google.com/storage/docs/json_api/v1/buckets/list).
13+
14+
## Example Usage
15+
16+
Example GCS buckets.
17+
18+
```hcl
19+
data "google_storage_buckets" "example" {
20+
project = "example-project"
21+
}
22+
```
23+
24+
## Argument Reference
25+
26+
The following arguments are supported:
27+
28+
* `prefix` - (Optional) Filter results to buckets whose names begin with this prefix.
29+
* `project` - (Optional) The ID of the project. If it is not provided, the provider project is used.
30+
31+
32+
## Attributes Reference
33+
34+
The following attributes are exported:
35+
36+
* `buckets` - A list of all retrieved GCS buckets. Structure is [defined below](#nested_buckets).
37+
38+
<a name="nested_buckets"></a>The `buckets` block supports:
39+
40+
* `labels` - User-provided bucket labels, in key/value pairs.
41+
* `location` - The location of the bucket.
42+
* `name` - The name of the bucket.
43+
* `self_link` - A url reference to the bucket.
44+
* `storage_class` - The [StorageClass](https://cloud.google.com/storage/docs/storage-classes) of the bucket.

0 commit comments

Comments
 (0)