Skip to content

Commit

Permalink
feat: use funcs from sdk (#2462)
Browse files Browse the repository at this point in the history
refactor funcs to use sdk
  • Loading branch information
sfc-gh-swinkler authored Feb 9, 2024
1 parent 0385650 commit a5f969c
Show file tree
Hide file tree
Showing 26 changed files with 1,005 additions and 1,293 deletions.
4 changes: 2 additions & 2 deletions docs/resources/function.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ resource "snowflake_function" "sql_test" {
- `name` (String) Specifies the identifier for the function; does not have to be unique for the schema in which the function is created. Don't use the | character.
- `return_type` (String) The return type of the function
- `schema` (String) The schema in which to create the function. Don't use the | character.
- `statement` (String) Specifies the javascript / java / sql / python code used to create the function.
- `statement` (String) Specifies the javascript / java / scala / sql / python code used to create the function.

### Optional

Expand All @@ -106,7 +106,7 @@ resource "snowflake_function" "sql_test" {
- `handler` (String) The handler method for Java / Python function.
- `imports` (List of String) Imports for Java / Python functions. For Java this a list of jar files, for Python this is a list of Python files.
- `is_secure` (Boolean) Specifies that the function is secure.
- `language` (String) The language of the statement
- `language` (String) Specifies the language of the stored function code.
- `null_input_behavior` (String) Specifies the behavior of the function when called with null inputs.
- `packages` (List of String) List of package imports to use for Java / Python functions. For Java, package imports should be of the form: package_name:version_number, where package_name is snowflake_domain:package. For Python use it should be: ('numpy','pandas','xgboost==1.5.0').
- `return_behavior` (String) Specifies the behavior of the function when returning results
Expand Down
66 changes: 39 additions & 27 deletions pkg/datasources/functions.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package datasources

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

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

Expand Down Expand Up @@ -60,43 +63,52 @@ var functionsSchema = map[string]*schema.Schema{

func Functions() *schema.Resource {
return &schema.Resource{
Read: ReadFunctions,
Schema: functionsSchema,
ReadContext: ReadContextFunctions,
Schema: functionsSchema,
}
}

// todo: fix this. ListUserFunctions isn't using the right struct right now and also the signature of this doesn't support all the features it could for example, database and schema should be optional, and you could also list by account.
func ReadFunctions(d *schema.ResourceData, meta interface{}) error {
func ReadContextFunctions(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
db := meta.(*sql.DB)
client := sdk.NewClientFromDB(db)
databaseName := d.Get("database").(string)
schemaName := d.Get("schema").(string)

d.SetId("functions")
currentFunctions, err := snowflake.ListUserFunctions(databaseName, schemaName, db)
request := sdk.NewShowFunctionRequest()
request.WithIn(&sdk.In{Schema: sdk.NewDatabaseObjectIdentifier(databaseName, schemaName)})
functions, err := client.Functions.Show(ctx, request)
if err != nil {
log.Printf("[DEBUG] error listing functions: %v", err)
return nil
}

functions := []map[string]interface{}{}
id := d.Id()

for _, function := range currentFunctions {
functionMap := map[string]interface{}{}
d.SetId("")
return diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("Unable to parse functions in schema (%s)", id),
Detail: "See our document on design decisions for functions: <LINK (coming soon)>",
},
}
}

functionSignatureMap, err := parseArguments(function.Arguments.String)
entities := []map[string]interface{}{}
for _, item := range functions {
signature, err := parseArguments(item.Arguments)
if err != nil {
return err
return diag.FromErr(err)
}
m := map[string]interface{}{}
m["name"] = item.Name
m["database"] = databaseName
m["schema"] = schemaName
m["comment"] = item.Description
m["argument_types"] = signature["argumentTypes"].([]string)
m["return_type"] = signature["returnType"].(string)

functionMap["name"] = function.Name.String
functionMap["database"] = databaseName
functionMap["schema"] = schemaName
functionMap["comment"] = function.Description.String
functionMap["argument_types"] = functionSignatureMap["argumentTypes"].([]string)
functionMap["return_type"] = functionSignatureMap["returnType"].(string)

functions = append(functions, functionMap)
entities = append(entities, m)
}

return d.Set("functions", functions)
d.SetId(helpers.EncodeSnowflakeID(databaseName, schemaName))
if err := d.Set("functions", entities); err != nil {
return diag.FromErr(err)
}
return nil
}
64 changes: 27 additions & 37 deletions pkg/datasources/functions_acceptance_test.go
Original file line number Diff line number Diff line change
@@ -1,57 +1,47 @@
package datasources_test

import (
"fmt"
"strings"
"testing"

acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

func TestAcc_Functions(t *testing.T) {
databaseName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
schemaName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
functionName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
functionNameOne := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
functionNameTwo := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
dataSourceName := "data.snowflake_functions.functions"

m := func() map[string]config.Variable {
return map[string]config.Variable{
"database": config.StringVariable(acc.TestDatabaseName),
"schema": config.StringVariable(acc.TestSchemaName),
"function_name_one": config.StringVariable(functionNameOne),
"function_name_two": config.StringVariable(functionNameTwo),
}
}
variableSet1 := m()
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
PreCheck: func() { acc.TestAccPreCheck(t) },
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.RequireAbove(tfversion.Version1_5_0),
},
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: functions(databaseName, schemaName, functionName),
ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Functions/complete"),
ConfigVariables: variableSet1,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.snowflake_functions.t", "database", databaseName),
resource.TestCheckResourceAttr("data.snowflake_functions.t", "schema", schemaName),
resource.TestCheckResourceAttr(dataSourceName, "database", acc.TestDatabaseName),
resource.TestCheckResourceAttr(dataSourceName, "schema", acc.TestSchemaName),
resource.TestCheckResourceAttrSet(dataSourceName, "functions.#"),
),
},
},
})
}

func functions(databaseName string, schemaName string, functionName string) string {
s := `
resource "snowflake_database" "test_database" {
name = "%v"
comment = "Terraform acceptance test"
}
resource "snowflake_schema" "test_schema" {
name = "%v"
database = snowflake_database.test_database.name
comment = "Terraform acceptance test"
}
resource "snowflake_function" "test_funct_simple" {
name = "%s"
database = snowflake_database.test_database.name
schema = snowflake_schema.test_schema.name
return_type = "float"
statement = "3.141592654::FLOAT"
}
data snowflake_functions "t" {
database = snowflake_database.test_database.name
schema = snowflake_schema.test_schema.name
depends_on = [snowflake_function.test_funct_simple]
}
`
return fmt.Sprintf(s, databaseName, schemaName, functionName)
}
33 changes: 33 additions & 0 deletions pkg/datasources/testdata/TestAcc_Functions/complete/test.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
resource "snowflake_function" "test_function_one" {
name = var.function_name_one
database = var.database
schema = var.schema
return_type = "VARCHAR"
language = "JAVASCRIPT"
statement = <<-EOF
return "Hi"
EOF
}

resource "snowflake_function" "test_function_two" {
name = var.function_name_two
database = var.database
schema = var.schema
arguments {
name = "arg1"
type = "varchar"
}
comment = "Terraform acceptance test"
return_type = "varchar"
language = "JAVASCRIPT"
statement = <<-EOF
var x = 1
return x
EOF
}

data "snowflake_functions" "functions" {
database = var.database
schema = var.schema
depends_on = [snowflake_function.test_function_one, snowflake_function.test_function_two]
}
15 changes: 15 additions & 0 deletions pkg/datasources/testdata/TestAcc_Functions/complete/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
variable "function_name_one" {
type = string
}

variable "function_name_two" {
type = string
}

variable "database" {
type = string
}

variable "schema" {
type = string
}
Loading

0 comments on commit a5f969c

Please sign in to comment.