Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implemented Schemas, Tables and Views Datasources #618

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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