Skip to content

Commit

Permalink
fix: handling not exist gracefully (#1031)
Browse files Browse the repository at this point in the history
* handling not exist gracefully

* moved generic error to common file

* moved generic error to common file, api_integration as well

* Generic 'No Rows in RS' error was not compared correctly

Co-authored-by: Scott Winkler <scott.winkler@snowflake.com>
  • Loading branch information
israel and sfc-gh-swinkler authored Jun 16, 2022
1 parent b65d692 commit 101267d
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 12 deletions.
8 changes: 7 additions & 1 deletion pkg/resources/api_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,13 @@ func ReadAPIIntegration(d *schema.ResourceData, meta interface{}) error {

s, err := snowflake.ScanApiIntegration(row)
if err != nil {
return fmt.Errorf("Could not show api integration: %w", err)
// If no such resource exists, it is not an error but rather not exist
if err.Error() == snowflake.ErrNoRowInRS {
d.SetId("")
return nil
} else {
return fmt.Errorf("Could not show api integration: %w", err)
}
}

// Note: category must be API or something is broken
Expand Down
7 changes: 6 additions & 1 deletion pkg/resources/external_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,12 @@ func ReadExternalFunction(d *schema.ResourceData, meta interface{}) error {
row := snowflake.QueryRow(db, stmt)
externalFunction, err := snowflake.ScanExternalFunction(row)
if err != nil {
return err
if err.Error() == snowflake.ErrNoRowInRS {
d.SetId("")
return nil
} else {
return err
}
}

// Note: 'language' must be EXTERNAL and 'is_external_function' set to Y
Expand Down
8 changes: 7 additions & 1 deletion pkg/resources/external_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,13 @@ func ReadExternalTable(d *schema.ResourceData, meta interface{}) error {
row := snowflake.QueryRow(db, stmt)
externalTable, err := snowflake.ScanExternalTable(row)
if err != nil {
return err
if err.Error() == snowflake.ErrNoRowInRS {
fmt.Println("Good !!")
d.SetId("")
return nil
} else {
return err
}
}

err = d.Set("name", externalTable.ExternalTableName.String)
Expand Down
12 changes: 6 additions & 6 deletions pkg/resources/procedure.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ var procedureSchema = map[string]*schema.Schema{
DiffSuppressFunc: DiffSuppressStatement,
},
"language": {
Type: schema.TypeString,
Optional: true,
Default: "SQL",
Type: schema.TypeString,
Optional: true,
Default: "SQL",
// Suppress the diff shown if the values are equal when both compared in lower case.
DiffSuppressFunc: DiffTypes,
ValidateFunc: validation.StringInSlice(procedureLanguages, true),
Description: "Specifies the language of the stored procedure code.",
ValidateFunc: validation.StringInSlice(procedureLanguages, true),
Description: "Specifies the language of the stored procedure code.",
},
"execute_as": {
Type: schema.TypeString,
Expand Down Expand Up @@ -278,7 +278,7 @@ func ReadProcedure(d *schema.ResourceData, meta interface{}) error {
if err = d.Set("language", desc.Value.String); err != nil {
return err
}

default:
log.Printf("[WARN] unexpected procedure property %v returned from Snowflake", desc.Property.String)
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/resources/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package resources
import (
"database/sql"
"log"
"regexp"
"strings"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake"
Expand Down Expand Up @@ -132,6 +133,11 @@ var userSchema = map[string]*schema.Schema{
// MINS_TO_BYPASS_NETWORK POLICY = <integer>
}

func isUserNotExistOrNotAuthorized(errorString string) bool {
var userNotExistOrNotAuthorizedRegEx, _ = regexp.Compile("SQL compilation error:User '.*' does not exist or not authorized.")
return userNotExistOrNotAuthorizedRegEx.MatchString(strings.ReplaceAll(errorString, "\n", ""))
}

func User() *schema.Resource {
return &schema.Resource{
Create: CreateUser,
Expand Down Expand Up @@ -160,9 +166,10 @@ func ReadUser(d *schema.ResourceData, meta interface{}) error {
// requires the "MANAGE GRANTS" global privilege
stmt := snowflake.User(id).Describe()
rows, err := snowflake.Query(db, stmt)
if err == sql.ErrNoRows {

if err != nil && isUserNotExistOrNotAuthorized(err.Error()) {
// If not found, mark resource to be removed from statefile during apply or refresh
log.Printf("[DEBUG] user (%s) not found", d.Id())
log.Printf("[DEBUG] user (%s) not found or we are not authorized.Err:\n%s", d.Id(), err.Error())
d.SetId("")
return nil
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/resources/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"testing"

"github.com/pkg/errors"

sqlmock "github.com/DATA-DOG/go-sqlmock"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/resources"
Expand Down Expand Up @@ -110,7 +112,7 @@ func TestUserRead(t *testing.T) {
// Test when resource is not found, checking if state will be empty
r.NotEmpty(d.State())
q := snowflake.User(d.Id()).Describe()
mock.ExpectQuery(q).WillReturnError(sql.ErrNoRows)
mock.ExpectQuery(q).WillReturnError(errors.New(fmt.Sprintf("SQL compilation error:User '%s' does not exist or not authorized.", name)))
err2 := resources.ReadUser(d, db)
r.Empty(d.State())
r.Nil(err2)
Expand Down
6 changes: 6 additions & 0 deletions pkg/snowflake/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package snowflake

// Generic Errors
var (
ErrNoRowInRS = "sql: no rows in result set"
)

0 comments on commit 101267d

Please sign in to comment.