Skip to content

Commit

Permalink
Implemented Schemas, Tables and Views Datasources (Snowflake-Labs#618)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisIsidora authored and anton-chekanov committed Jan 25, 2022
1 parent 5c83ecc commit b4c5397
Show file tree
Hide file tree
Showing 17 changed files with 685 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
data "snowflake_materialized_views" "current" {
database = "MYDB"
schema = "MYSCHEMA"
}
3 changes: 3 additions & 0 deletions examples/data-sources/snowflake_schemas/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "snowflake_schemas" "current" {
database = "MYDB"
}
4 changes: 4 additions & 0 deletions examples/data-sources/snowflake_tables/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
data "snowflake_tables" "current" {
database = "MYDB"
schema = "MYSCHEMA"
}
4 changes: 4 additions & 0 deletions examples/data-sources/snowflake_views/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
data "snowflake_views" "current" {
database = "MYDB"
schema = "MYSCHEMA"
}
90 changes: 90 additions & 0 deletions pkg/datasources/materialized_views.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package datasources

import (
"database/sql"
"fmt"
"log"

"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var materializedViewsSchema = map[string]*schema.Schema{
"database": {
Type: schema.TypeString,
Required: true,
Description: "The database from which to return the schemas from.",
},
"schema": {
Type: schema.TypeString,
Required: true,
Description: "The schema from which to return the views from.",
},
"materialized_views": {
Type: schema.TypeList,
Computed: true,
Description: "The views in the schema",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
"database": {
Type: schema.TypeString,
Computed: true,
},
"schema": {
Type: schema.TypeString,
Computed: true,
},
"comment": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
},
},
}

func MaterializedViews() *schema.Resource {
return &schema.Resource{
Read: ReadMaterializedViews,
Schema: materializedViewsSchema,
}
}

func ReadMaterializedViews(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
databaseName := d.Get("database").(string)
schemaName := d.Get("schema").(string)

currentViews, err := snowflake.ListMaterializedViews(databaseName, schemaName, db)
if err == sql.ErrNoRows {
// If not found, mark resource to be removed from statefile during apply or refresh
log.Printf("[DEBUG] materialized views in schema (%s) not found", d.Id())
d.SetId("")
return nil
} else if err != nil {
log.Printf("[DEBUG] materialized unable to parse views in schema (%s)", d.Id())
d.SetId("")
return nil
}

views := []map[string]interface{}{}

for _, view := range currentViews {
viewMap := map[string]interface{}{}

viewMap["name"] = view.Name.String
viewMap["database"] = view.DatabaseName.String
viewMap["schema"] = view.SchemaName.String
viewMap["comment"] = view.Comment.String

views = append(views, viewMap)
}

d.SetId(fmt.Sprintf(`%v|%v`, databaseName, schemaName))
return d.Set("materialized_views", views)
}
77 changes: 77 additions & 0 deletions pkg/datasources/materialized_views_acceptance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package datasources_test

import (
"fmt"
"strings"
"testing"

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

func TestAccMaterializedViews(t *testing.T) {
warehouseName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
databaseName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
schemaName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
tableName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
viewName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
Steps: []resource.TestStep{
{
Config: materializedViews(warehouseName, databaseName, schemaName, tableName, viewName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.snowflake_materialized_views.v", "database", databaseName),
resource.TestCheckResourceAttr("data.snowflake_materialized_views.v", "schema", schemaName),
resource.TestCheckResourceAttrSet("data.snowflake_materialized_views.v", "materialized_views.#"),
resource.TestCheckResourceAttr("data.snowflake_materialized_views.v", "materialized_views.#", "1"),
resource.TestCheckResourceAttr("data.snowflake_materialized_views.v", "materialized_views.0.name", viewName),
),
},
},
})
}

func materializedViews(warehouseName string, databaseName string, schemaName string, tableName string, viewName string) string {
return fmt.Sprintf(`
resource "snowflake_warehouse" "w" {
name = "%v"
initially_suspended = false
}
resource snowflake_database "d" {
name = "%v"
}
resource snowflake_schema "s"{
name = "%v"
database = snowflake_database.d.name
}
resource snowflake_table "t"{
name = "%v"
database = snowflake_schema.s.database
schema = snowflake_schema.s.name
column {
name = "column2"
type = "VARCHAR(16)"
}
}
resource snowflake_materialized_view "v"{
name = "%v"
comment = "Terraform test resource"
database = snowflake_schema.s.database
schema = snowflake_schema.s.name
is_secure = true
or_replace = false
statement = "SELECT * FROM ${snowflake_table.t.name}"
warehouse = snowflake_warehouse.w.name
}
data snowflake_materialized_views "v" {
database = snowflake_materialized_view.v.database
schema = snowflake_materialized_view.v.schema
}
`, warehouseName, databaseName, schemaName, tableName, viewName)
}
80 changes: 80 additions & 0 deletions pkg/datasources/schemas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package datasources

import (
"database/sql"
"log"

"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var schemasSchema = map[string]*schema.Schema{
"database": {
Type: schema.TypeString,
Required: true,
Description: "The database from which to return the schemas from.",
},
"schemas": {
Type: schema.TypeList,
Computed: true,
Description: "The schemas in the database",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
"database": {
Type: schema.TypeString,
Computed: true,
},
"comment": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
},
},
}

func Schemas() *schema.Resource {
return &schema.Resource{
Read: ReadSchemas,
Schema: schemasSchema,
}
}

func ReadSchemas(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
databaseName := d.Get("database").(string)

log.Printf("[DEBUG] database name %s", databaseName)

currentSchemas, err := snowflake.ListSchemas(databaseName, db)
if err == sql.ErrNoRows {
// If not found, mark resource to be removed from statefile during apply or refresh
log.Printf("[DEBUG] schemas in database (%s) not found", d.Id())
d.SetId("")
return nil
} else if err != nil {
log.Printf("[DEBUG] unable to parse schemas in database (%s)", d.Id())
d.SetId("")
return nil
}

schemas := []map[string]interface{}{}

for _, schema := range currentSchemas {
schemaMap := map[string]interface{}{}

schemaMap["name"] = schema.Name.String
schemaMap["database"] = schema.DatabaseName.String
schemaMap["comment"] = schema.Comment.String

schemas = append(schemas, schemaMap)
}

d.SetId(databaseName)
return d.Set("schemas", schemas)
}
46 changes: 46 additions & 0 deletions pkg/datasources/schemas_acceptance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package datasources_test

import (
"fmt"
"strings"
"testing"

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

func TestAccSchemas(t *testing.T) {
databaseName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
schemaName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
Steps: []resource.TestStep{
{
Config: schemas(databaseName, schemaName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.snowflake_schemas.s", "database", databaseName),
resource.TestCheckResourceAttrSet("data.snowflake_schemas.s", "schemas.#"),
resource.TestCheckResourceAttr("data.snowflake_schemas.s", "schemas.#", "3"),
),
},
},
})
}

func schemas(databaseName string, schemaName string) string {
return fmt.Sprintf(`
resource snowflake_database "d" {
name = "%v"
}
resource snowflake_schema "s"{
name = "%v"
database = snowflake_database.d.name
}
data snowflake_schemas "s" {
database = snowflake_schema.s.database
}
`, databaseName, schemaName)
}
Loading

0 comments on commit b4c5397

Please sign in to comment.