mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-01 16:21:06 +00:00
Support Bigquery Views (#230)
* Support views in Terraform.BigQuery * Add tests for Table with view, and fix existing Table test * Remove dead code * run gofmt * Address comments * Address review comments and add support for use_legacy_sql * Force transmission/storage of UseLegacySQL * Trying to fix tests * add tests for useLegacySQL
This commit is contained in:
parent
6715d0d363
commit
d23e9c668f
@ -229,7 +229,6 @@ func resourceBigQueryDatasetRead(d *schema.ResourceData, meta interface{}) error
|
|||||||
|
|
||||||
d.Set("etag", res.Etag)
|
d.Set("etag", res.Etag)
|
||||||
d.Set("labels", res.Labels)
|
d.Set("labels", res.Labels)
|
||||||
d.Set("location", res.Location)
|
|
||||||
d.Set("self_link", res.SelfLink)
|
d.Set("self_link", res.SelfLink)
|
||||||
d.Set("description", res.Description)
|
d.Set("description", res.Description)
|
||||||
d.Set("friendly_name", res.FriendlyName)
|
d.Set("friendly_name", res.FriendlyName)
|
||||||
@ -238,6 +237,15 @@ func resourceBigQueryDatasetRead(d *schema.ResourceData, meta interface{}) error
|
|||||||
d.Set("dataset_id", res.DatasetReference.DatasetId)
|
d.Set("dataset_id", res.DatasetReference.DatasetId)
|
||||||
d.Set("default_table_expiration_ms", res.DefaultTableExpirationMs)
|
d.Set("default_table_expiration_ms", res.DefaultTableExpirationMs)
|
||||||
|
|
||||||
|
// Older Tables in BigQuery have no Location set in the API response. This may be an issue when importing
|
||||||
|
// tables created before BigQuery was available in multiple zones. We can safely assume that these tables
|
||||||
|
// are in the US, as this was the default at the time.
|
||||||
|
if res.Location == "" {
|
||||||
|
d.Set("location", "US")
|
||||||
|
} else {
|
||||||
|
d.Set("location", res.Location)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +92,31 @@ func resourceBigQueryTable() *schema.Resource {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// View: [Optional] If specified, configures this table as a view.
|
||||||
|
"view": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
// Query: [Required] A query that BigQuery executes when the view is
|
||||||
|
// referenced.
|
||||||
|
"query": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// UseLegacySQL: [Optional] Specifies whether to use BigQuery's
|
||||||
|
// legacy SQL for this view. The default value is true. If set to
|
||||||
|
// false, the view will use BigQuery's standard SQL:
|
||||||
|
"use_legacy_sql": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// TimePartitioning: [Experimental] If specified, configures time-based
|
// TimePartitioning: [Experimental] If specified, configures time-based
|
||||||
// partitioning for this table.
|
// partitioning for this table.
|
||||||
"time_partitioning": &schema.Schema{
|
"time_partitioning": &schema.Schema{
|
||||||
@ -202,6 +227,10 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("view"); ok {
|
||||||
|
table.View = expandView(v)
|
||||||
|
}
|
||||||
|
|
||||||
if v, ok := d.GetOk("description"); ok {
|
if v, ok := d.GetOk("description"); ok {
|
||||||
table.Description = v.(string)
|
table.Description = v.(string)
|
||||||
}
|
}
|
||||||
@ -317,6 +346,11 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error {
|
|||||||
d.Set("schema", schema)
|
d.Set("schema", schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if res.View != nil {
|
||||||
|
view := flattenView(res.View)
|
||||||
|
d.Set("view", view)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,3 +428,22 @@ func flattenTimePartitioning(tp *bigquery.TimePartitioning) []map[string]interfa
|
|||||||
|
|
||||||
return []map[string]interface{}{result}
|
return []map[string]interface{}{result}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func expandView(configured interface{}) *bigquery.ViewDefinition {
|
||||||
|
raw := configured.([]interface{})[0].(map[string]interface{})
|
||||||
|
vd := &bigquery.ViewDefinition{Query: raw["query"].(string)}
|
||||||
|
|
||||||
|
if v, ok := raw["use_legacy_sql"]; ok {
|
||||||
|
vd.UseLegacySql = v.(bool)
|
||||||
|
vd.ForceSendFields = append(vd.ForceSendFields, "UseLegacySql")
|
||||||
|
}
|
||||||
|
|
||||||
|
return vd
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenView(vd *bigquery.ViewDefinition) []map[string]interface{} {
|
||||||
|
result := map[string]interface{}{"query": vd.Query}
|
||||||
|
result["use_legacy_sql"] = vd.UseLegacySql
|
||||||
|
|
||||||
|
return []map[string]interface{}{result}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package google
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/acctest"
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
@ -37,6 +38,53 @@ func TestAccBigQueryTable_Basic(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccBigQueryTable_View(t *testing.T) {
|
||||||
|
datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(10))
|
||||||
|
tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckBigQueryTableDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccBigQueryTableWithView(datasetID, tableID),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccBigQueryTableExistsWithView(
|
||||||
|
"google_bigquery_table.test"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccBigQueryTable_ViewWithLegacySQL(t *testing.T) {
|
||||||
|
datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(10))
|
||||||
|
tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckBigQueryTableDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccBigQueryTableWithView(datasetID, tableID),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccBigQueryTableExistsWithLegacySql(
|
||||||
|
"google_bigquery_table.test", true),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccBigQueryTableWithNewSqlView(datasetID, tableID),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccBigQueryTableExistsWithLegacySql(
|
||||||
|
"google_bigquery_table.test", false),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckBigQueryTableDestroy(s *terraform.State) error {
|
func testAccCheckBigQueryTableDestroy(s *terraform.State) error {
|
||||||
for _, rs := range s.RootModule().Resources {
|
for _, rs := range s.RootModule().Resources {
|
||||||
if rs.Type != "google_bigquery_table" {
|
if rs.Type != "google_bigquery_table" {
|
||||||
@ -44,7 +92,7 @@ func testAccCheckBigQueryTableDestroy(s *terraform.State) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := testAccProvider.Meta().(*Config)
|
config := testAccProvider.Meta().(*Config)
|
||||||
_, err := config.clientBigQuery.Tables.Get(config.Project, rs.Primary.Attributes["dataset_id"], rs.Primary.Attributes["name"]).Do()
|
_, err := config.clientBigQuery.Tables.Get(config.Project, rs.Primary.Attributes["dataset_id"], rs.Primary.Attributes["table_id"]).Do()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return fmt.Errorf("Table still present")
|
return fmt.Errorf("Table still present")
|
||||||
}
|
}
|
||||||
@ -64,11 +112,69 @@ func testAccBigQueryTableExists(n string) resource.TestCheckFunc {
|
|||||||
return fmt.Errorf("No ID is set")
|
return fmt.Errorf("No ID is set")
|
||||||
}
|
}
|
||||||
config := testAccProvider.Meta().(*Config)
|
config := testAccProvider.Meta().(*Config)
|
||||||
_, err := config.clientBigQuery.Tables.Get(config.Project, rs.Primary.Attributes["dataset_id"], rs.Primary.Attributes["name"]).Do()
|
table, err := config.clientBigQuery.Tables.Get(config.Project, rs.Primary.Attributes["dataset_id"], rs.Primary.Attributes["table_id"]).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("BigQuery Table not present")
|
return fmt.Errorf("BigQuery Table not present")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !strings.HasSuffix(table.Id, rs.Primary.Attributes["table_id"]) {
|
||||||
|
return fmt.Errorf("BigQuery Table ID does not match expected value")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigQueryTableExistsWithView(n string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
table, err := config.clientBigQuery.Tables.Get(config.Project, rs.Primary.Attributes["dataset_id"], rs.Primary.Attributes["table_id"]).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("BigQuery Table not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
if table.View == nil {
|
||||||
|
return fmt.Errorf("View object missing on table")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigQueryTableExistsWithLegacySql(n string, useLegacySql bool) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
table, err := config.clientBigQuery.Tables.Get(config.Project, rs.Primary.Attributes["dataset_id"], rs.Primary.Attributes["table_id"]).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("BigQuery Table not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
if table.View == nil {
|
||||||
|
return fmt.Errorf("View object missing on table")
|
||||||
|
}
|
||||||
|
|
||||||
|
if table.View.UseLegacySql != useLegacySql {
|
||||||
|
return fmt.Errorf("Value of UseLegacySQL does not match expected value")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,6 +220,48 @@ EOH
|
|||||||
}`, datasetID, tableID)
|
}`, datasetID, tableID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccBigQueryTableWithView(datasetID, tableID string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_bigquery_dataset" "test" {
|
||||||
|
dataset_id = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_bigquery_table" "test" {
|
||||||
|
table_id = "%s"
|
||||||
|
dataset_id = "${google_bigquery_dataset.test.dataset_id}"
|
||||||
|
|
||||||
|
time_partitioning {
|
||||||
|
type = "DAY"
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
query = "SELECT state FROM [lookerdata:cdc.project_tycho_reports]"
|
||||||
|
use_legacy_sql = true
|
||||||
|
}
|
||||||
|
}`, datasetID, tableID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigQueryTableWithNewSqlView(datasetID, tableID string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_bigquery_dataset" "test" {
|
||||||
|
dataset_id = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_bigquery_table" "test" {
|
||||||
|
table_id = "%s"
|
||||||
|
dataset_id = "${google_bigquery_dataset.test.dataset_id}"
|
||||||
|
|
||||||
|
time_partitioning {
|
||||||
|
type = "DAY"
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
query = "%s"
|
||||||
|
use_legacy_sql = false
|
||||||
|
}
|
||||||
|
}`, datasetID, tableID, "SELECT state FROM `lookerdata:cdc.project_tycho_reports`")
|
||||||
|
}
|
||||||
|
|
||||||
func testAccBigQueryTableUpdated(datasetID, tableID string) string {
|
func testAccBigQueryTableUpdated(datasetID, tableID string) string {
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
resource "google_bigquery_dataset" "test" {
|
resource "google_bigquery_dataset" "test" {
|
||||||
|
Loading…
Reference in New Issue
Block a user