Skip to content

Commit

Permalink
Add project_number field to google_storage_bucket resource and data…
Browse files Browse the repository at this point in the history
…source, enable providing `project` argument to data source (GoogleCloudPlatform#10312)
  • Loading branch information
SarahFrench authored and Cheriit committed Jun 4, 2024
1 parent 848b1c3 commit 7fdace2
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func DataSourceGoogleStorageBucket() *schema.Resource {

dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceStorageBucket().Schema)

tpgresource.AddOptionalFieldsToSchema(dsSchema, "project")
tpgresource.AddRequiredFieldsToSchema(dsSchema, "name")

return &schema.Resource{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package storage_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
)

func TestAccDataSourceGoogleStorageBucket_basic(t *testing.T) {
t.Parallel()

bucket := "tf-bucket-" + acctest.RandString(t, 10)
context := map[string]interface{}{
"bucket_name": "tf-bucket-" + acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccStorageBucketDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleStorageBucketConfig(bucket),
Config: testAccDataSourceGoogleStorageBucketConfig(context),
Check: resource.ComposeTestCheckFunc(
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_storage_bucket.bar", "google_storage_bucket.foo", map[string]struct{}{"force_destroy": {}}),
),
Expand All @@ -28,18 +30,80 @@ func TestAccDataSourceGoogleStorageBucket_basic(t *testing.T) {
})
}

func testAccDataSourceGoogleStorageBucketConfig(bucketName string) string {
return fmt.Sprintf(`
// Test that the data source can take a project argument, which is used as a way to avoid using Compute API to
// get project id for the project number returned from the Storage API.
func TestAccDataSourceGoogleStorageBucket_avoidComputeAPI(t *testing.T) {
// Cannot use t.Parallel() if using t.Setenv

project := envvar.GetTestProjectFromEnv()

context := map[string]interface{}{
"bucket_name": "tf-bucket-" + acctest.RandString(t, 10),
"real_project_id": project,
"incorrect_project_id": "foobar",
}

// Unset ENV so no provider default is available to the data source
t.Setenv("GOOGLE_PROJECT", "")

acctest.VcrTest(t, resource.TestCase{
// Removed PreCheck because it wants to enforce GOOGLE_PROJECT being set
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccStorageBucketDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleStorageBucketConfig_setProjectInConfig(context),
Check: resource.ComposeTestCheckFunc(
// We ignore project to show that the project argument on the data source is retained and isn't impacted
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_storage_bucket.bar", "google_storage_bucket.foo", map[string]struct{}{"force_destroy": {}, "project": {}}),

resource.TestCheckResourceAttrSet(
"google_storage_bucket.foo", "project_number"),
resource.TestCheckResourceAttr(
"google_storage_bucket.foo", "project", context["real_project_id"].(string)),

resource.TestCheckResourceAttrSet(
"data.google_storage_bucket.bar", "project_number"),
resource.TestCheckResourceAttr(
"data.google_storage_bucket.bar", "project", context["incorrect_project_id"].(string)),
),
},
},
})
}

func testAccDataSourceGoogleStorageBucketConfig(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_storage_bucket" "foo" {
name = "%{bucket_name}"
location = "US"
}
data "google_storage_bucket" "bar" {
name = google_storage_bucket.foo.name
depends_on = [
google_storage_bucket.foo,
]
}
`, context)
}

func testAccDataSourceGoogleStorageBucketConfig_setProjectInConfig(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_storage_bucket" "foo" {
name = "%s"
project = "%{real_project_id}"
name = "%{bucket_name}"
location = "US"
}
// The project argument here doesn't help the provider retrieve data about the bucket
// It only serves to stop the data source using the compute API to convert the project number to an id
data "google_storage_bucket" "bar" {
project = "%{incorrect_project_id}"
name = google_storage_bucket.foo.name
depends_on = [
google_storage_bucket.foo,
]
}
`, bucketName)
`, context)
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ func ResourceStorageBucket() *schema.Resource {
Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`,
},

"project_number": {
Type: schema.TypeInt,
Computed: true,
Description: `The project number of the project in which the resource belongs.`,
},

"self_link": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -1718,6 +1724,9 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res
if err := d.Set("url", fmt.Sprintf("gs://%s", bucket)); err != nil {
return fmt.Errorf("Error setting url: %s", err)
}
if err := d.Set("project_number", res.ProjectNumber); err != nil {
return fmt.Errorf("Error setting project_number: %s", err)
}
if err := d.Set("storage_class", res.StorageClass); err != nil {
return fmt.Errorf("Error setting storage_class: %s", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ func TestAccStorageBucket_basic(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"google_storage_bucket.bucket", "force_destroy", "false"),
resource.TestCheckResourceAttr(
"google_storage_bucket.bucket", "project", envvar.GetTestProjectFromEnv()),
resource.TestCheckResourceAttrSet(
"google_storage_bucket.bucket", "project_number"),
),
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ The following arguments are supported:

* `name` - (Required) The name of the bucket.

* `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. If no value is supplied in the configuration or through provider defaults then the data source will use the Compute API to find the project id that corresponds to the project number returned from the Storage API. Supplying a value for `project` doesn't influence retrieving data about the bucket but it can be used to prevent use of the Compute API. If you do provide a `project` value ensure that it is the correct value for that bucket; the data source will not check that the project id and project number match.

## Attributes Reference

See [google_storage_bucket](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket#argument-reference) resource for details of the available attributes.

0 comments on commit 7fdace2

Please sign in to comment.