From 55d3909907099993120f5bcf5bf25c691a92b4d6 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Fri, 28 Jul 2023 21:11:08 +0000 Subject: [PATCH] Enhance BigQuery table schema input validation (#8460) * Enhance BigQuery table schema input validation * skip TestAccBigQueryTable_invalidSchemas in VCR test Signed-off-by: Modular Magician --- .changelog/8460.txt | 3 + google/resource_bigquery_table_test.go | 134 ++++++++++++++++++ .../bigquery/resource_bigquery_table.go | 30 +++- 3 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 .changelog/8460.txt diff --git a/.changelog/8460.txt b/.changelog/8460.txt new file mode 100644 index 00000000000..2bbf6efe62a --- /dev/null +++ b/.changelog/8460.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +added more input validations for BigQuery table schema +``` diff --git a/google/resource_bigquery_table_test.go b/google/resource_bigquery_table_test.go index 70694b5b1c9..60c698df8ec 100644 --- a/google/resource_bigquery_table_test.go +++ b/google/resource_bigquery_table_test.go @@ -588,6 +588,36 @@ func TestAccBigQueryExternalDataTable_CSV(t *testing.T) { }) } +func TestAccBigQueryExternalDataTable_CSV_WithSchema_InvalidSchemas(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + objectName := fmt.Sprintf("tf_test_%s.csv", RandString(t, 10)) + + datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_NOT_JSON), + ExpectError: regexp.MustCompile("contains an invalid JSON"), + }, + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_NOT_JSON_LIST), + ExpectError: regexp.MustCompile("\"schema\" is not a JSON array"), + }, + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_JSON_LIST_WITH_NULL_ELEMENT), + ExpectError: regexp.MustCompile("\"schema\" contains a nil element"), + }, + }, + }) +} + func TestAccBigQueryExternalDataTable_CSV_WithSchemaAndConnectionID_UpdateNoConnectionID(t *testing.T) { t.Parallel() @@ -919,6 +949,35 @@ func TestAccBigQueryTable_emptySchema(t *testing.T) { }) } +func TestAccBigQueryTable_invalidSchemas(t *testing.T) { + t.Parallel() + // Not an acceptance test. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_NOT_JSON), + ExpectError: regexp.MustCompile("contains an invalid JSON"), + }, + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_NOT_JSON_LIST), + ExpectError: regexp.MustCompile("\"schema\" is not a JSON array"), + }, + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_JSON_LIST_WITH_NULL_ELEMENT), + ExpectError: regexp.MustCompile("\"schema\" contains a nil element"), + }, + }, + }) +} + func testAccCheckBigQueryExtData(t *testing.T, expectedQuoteChar string) resource.TestCheckFunc { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { @@ -1986,6 +2045,45 @@ resource "google_bigquery_table" "test" { `, datasetID, bucketName, objectName, content, tableID, schema) } +func testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, content, schema string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} +resource "google_storage_bucket" "test" { + name = "%s" + location = "US" + force_destroy = true +} +resource "google_storage_bucket_object" "test" { + name = "%s" + content = <