Skip to content

Commit

Permalink
Add resource tags to BigQuery Table (GoogleCloudPlatform#10455)
Browse files Browse the repository at this point in the history
  • Loading branch information
wj-chen authored and balanaguharsha committed Apr 19, 2024
1 parent cde6f3e commit 8dff4da
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 1 deletion.
8 changes: 8 additions & 0 deletions mmv1/products/bigquery/Table.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -508,3 +508,11 @@ properties:
- :INTEGER
- :FLOAT
- :BOOLEAN
- !ruby/object:Api::Type::KeyValuePairs
name: 'resourceTags'
min_version: beta
description: |
The tags attached to this table. Tag keys are globally unique. Tag key is expected to be
in the namespaced format, for example "123456789012/environment" where 123456789012 is the
ID of the parent organization or project resource for this tag key. Tag value is expected
to be the short name, for example "Production".
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package bigquery

import (
Expand Down Expand Up @@ -1305,6 +1306,14 @@ func ResourceBigQueryTable() *schema.Resource {
},
},
},
<% unless version == 'ga' -%>
"resource_tags": {
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: `The tags attached to this table. Tag keys are globally unique. Tag key is expected to be in the namespaced format, for example "123456789012/environment" where 123456789012 is the ID of the parent organization or project resource for this tag key. Tag value is expected to be the short name, for example "Production".`,
},
<% end -%>
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -1419,6 +1428,10 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e
table.TableConstraints = tableConstraints
}

<% unless version == 'ga' -%>
table.ResourceTags = tpgresource.ExpandStringMap(d, "resource_tags")

<% end -%>
return table, nil
}

Expand Down Expand Up @@ -1692,6 +1705,12 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error {
}
}

<% unless version == 'ga' -%>
if err := d.Set("resource_tags", res.ResourceTags); err != nil {
return fmt.Errorf("Error setting resource tags: %s", err)
}

<% end -%>
// TODO: Update when the Get API fields for TableReplicationInfo are available in the client library.
url, err := tpgresource.ReplaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}/tables/{{table_id}}")
if err != nil {
Expand Down Expand Up @@ -1772,6 +1791,10 @@ func resourceBigQueryTableColumnDrop(config *transport_tpg.Config, userAgent str
return err
}

if table.Schema == nil {
return nil
}

newTableFields := map[string]bool{}
for _, field := range table.Schema.Fields {
newTableFields[field.Name] = true
Expand Down Expand Up @@ -1807,8 +1830,20 @@ func resourceBigQueryTableColumnDrop(config *transport_tpg.Config, userAgent str

func resourceBigQueryTableDelete(d *schema.ResourceData, meta interface{}) error {
if d.Get("deletion_protection").(bool) {
return fmt.Errorf("cannot destroy instance without setting deletion_protection=false and running `terraform apply`")
return fmt.Errorf("cannot destroy table %v without setting deletion_protection=false and running `terraform apply`", d.Id())
}
<% unless version == 'ga' -%>
if v, ok := d.GetOk("resource_tags"); ok {
var resourceTags []string

for k, v := range v.(map[string]interface{}) {
resourceTags = append(resourceTags, fmt.Sprintf("%s:%s", k, v.(string)))
}

return fmt.Errorf("cannot destroy table %v without clearing the following resource tags: %v", d.Id(), resourceTags)
}

<% end -%>
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% autogen_exception -%>
package bigquery_test

import (
Expand Down Expand Up @@ -1552,6 +1553,58 @@ func TestAccBigQueryTable_TableReplicationInfo_WithReplicationInterval(t *testin
})
}

<% unless version == 'ga' -%>
func TestAccBigQueryTable_ResourceTags(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"project_id": envvar.GetTestProjectFromEnv(),
"dataset_id": fmt.Sprintf("tf_test_dataset_%s", acctest.RandString(t, 10)),
"table_id" : fmt.Sprintf("tf_test_table_%s", acctest.RandString(t, 10)),
"tag_key_name1": fmt.Sprintf("tf_test_tag_key1_%s", acctest.RandString(t, 10)),
"tag_value_name1": fmt.Sprintf("tf_test_tag_value1_%s", acctest.RandString(t, 10)),
"tag_key_name2": fmt.Sprintf("tf_test_tag_key2_%s", acctest.RandString(t, 10)),
"tag_value_name2": fmt.Sprintf("tf_test_tag_value2_%s", acctest.RandString(t, 10)),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccBigQueryTableWithResourceTags(context),
},
{
ResourceName: "google_bigquery_table.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection"},
},
{
Config: testAccBigQueryTableWithResourceTagsUpdate(context),
},
{
ResourceName: "google_bigquery_table.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection"},
},
// testAccBigQueryTableWithResourceTagsDestroy must be called at the end of this test to clear the resource tag bindings of the table before deletion.
{
Config: testAccBigQueryTableWithResourceTagsDestroy(context),
},
{
ResourceName: "google_bigquery_table.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection"},
},
},
})
}

<% end -%>
func testAccCheckBigQueryExtData(t *testing.T, expectedQuoteChar string) resource.TestCheckFunc {
return func(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
Expand Down Expand Up @@ -3921,6 +3974,140 @@ resource "time_sleep" "wait_10_seconds_last" {
`, sourceDatasetID, sourceTableID, sourceMVJobID, sourceDatasetID, sourceMVID, sourceDatasetID, sourceTableID, projectID, sourceMVID, replicaDatasetID, replicaMVID, projectID, sourceMVID, replicationIntervalExpr, dropMVJobID, sourceDatasetID, sourceMVID)
}

<% unless version == 'ga' -%>
func testAccBigQueryTableWithResourceTags(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_tags_tag_key" "key1" {
provider = google-beta

parent = "projects/%{project_id}"
short_name = "%{tag_key_name1}"
}

resource "google_tags_tag_value" "value1" {
provider = google-beta

parent = "tagKeys/${google_tags_tag_key.key1.name}"
short_name = "%{tag_value_name1}"
}

resource "google_bigquery_dataset" "test" {
provider = google-beta

dataset_id = "%{dataset_id}"
}

resource "google_bigquery_table" "test" {
provider = google-beta

deletion_protection = false
dataset_id = "${google_bigquery_dataset.test.dataset_id}"
table_id = "%{table_id}"
resource_tags = {
"%{project_id}/${google_tags_tag_key.key1.short_name}" = "${google_tags_tag_value.value1.short_name}"
}
}
`, context)
}

func testAccBigQueryTableWithResourceTagsUpdate(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_tags_tag_key" "key1" {
provider = google-beta

parent = "projects/%{project_id}"
short_name = "%{tag_key_name1}"
}

resource "google_tags_tag_value" "value1" {
provider = google-beta

parent = "tagKeys/${google_tags_tag_key.key1.name}"
short_name = "%{tag_value_name1}"
}

resource "google_tags_tag_key" "key2" {
provider = google-beta

parent = "projects/%{project_id}"
short_name = "%{tag_key_name2}"
}

resource "google_tags_tag_value" "value2" {
provider = google-beta

parent = "tagKeys/${google_tags_tag_key.key2.name}"
short_name = "%{tag_value_name2}"
}

resource "google_bigquery_dataset" "test" {
provider = google-beta

dataset_id = "%{dataset_id}"
}

resource "google_bigquery_table" "test" {
provider = google-beta

deletion_protection = false
dataset_id = "${google_bigquery_dataset.test.dataset_id}"
table_id = "%{table_id}"
resource_tags = {
"%{project_id}/${google_tags_tag_key.key1.short_name}" = "${google_tags_tag_value.value1.short_name}"
"%{project_id}/${google_tags_tag_key.key2.short_name}" = "${google_tags_tag_value.value2.short_name}"
}
}
`, context)
}

func testAccBigQueryTableWithResourceTagsDestroy(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_tags_tag_key" "key1" {
provider = google-beta

parent = "projects/%{project_id}"
short_name = "%{tag_key_name1}"
}

resource "google_tags_tag_value" "value1" {
provider = google-beta

parent = "tagKeys/${google_tags_tag_key.key1.name}"
short_name = "%{tag_value_name1}"
}

resource "google_tags_tag_key" "key2" {
provider = google-beta

parent = "projects/%{project_id}"
short_name = "%{tag_key_name2}"
}

resource "google_tags_tag_value" "value2" {
provider = google-beta

parent = "tagKeys/${google_tags_tag_key.key2.name}"
short_name = "%{tag_value_name2}"
}

resource "google_bigquery_dataset" "test" {
provider = google-beta

dataset_id = "%{dataset_id}"
}

resource "google_bigquery_table" "test" {
provider = google-beta

deletion_protection = false
dataset_id = "${google_bigquery_dataset.test.dataset_id}"
table_id = "%{table_id}"
resource_tags = {}
}
`, context)
}

<% end -%>
var TEST_CSV = `lifelock,LifeLock,,web,Tempe,AZ,1-May-07,6850000,USD,b
lifelock,LifeLock,,web,Tempe,AZ,1-Oct-06,6000000,USD,a
lifelock,LifeLock,,web,Tempe,AZ,1-Jan-08,25000000,USD,c
Expand Down

0 comments on commit 8dff4da

Please sign in to comment.