Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: enable copy_grants flag in view resource.
Browse files Browse the repository at this point in the history
sfc-gh-ngaberel committed Mar 28, 2023
1 parent fe4e4db commit 60128e9
Showing 4 changed files with 100 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/resources/view.md
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ SQL
### Optional

- `comment` (String) Specifies a comment for the view.
- `copy_grants` (Boolean) Retains the access permissions from the original view when a new view is created using the OR REPLACE clause.
- `is_secure` (Boolean) Specifies that the view is secure.
- `or_replace` (Boolean) Overwrites the View if it exists.
- `tag` (Block List, Deprecated) Definitions of a tag to associate with the resource. (see [below for nested schema](#nestedblock--tag))
14 changes: 14 additions & 0 deletions pkg/resources/view.go
Original file line number Diff line number Diff line change
@@ -40,6 +40,13 @@ var viewSchema = map[string]*schema.Schema{
Default: false,
Description: "Overwrites the View if it exists.",
},
"copy_grants": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Retains the access permissions from the original view when a new view is created using the OR REPLACE clause.",
ForceNew: true,
},
"is_secure": {
Type: schema.TypeBool,
Optional: true,
@@ -163,6 +170,10 @@ func CreateView(d *schema.ResourceData, meta interface{}) error {
builder.WithSecure()
}

if v, ok := d.GetOk("copy_grants"); ok && v.(bool) {
builder.WithCopyGrants()
}

if v, ok := d.GetOk("comment"); ok {
builder.WithComment(v.(string))
}
@@ -224,6 +235,9 @@ func ReadView(d *schema.ResourceData, meta interface{}) error {
if err = d.Set("is_secure", v.IsSecure); err != nil {
return err
}
if err = d.Set("copy_grants", v.CopyGrants()); err != nil {
return err
}
if err = d.Set("comment", v.Comment.String); err != nil {
return err
}
46 changes: 35 additions & 11 deletions pkg/resources/view_acceptance_test.go
Original file line number Diff line number Diff line change
@@ -17,11 +17,12 @@ func TestAcc_View(t *testing.T) {
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: viewConfig(accName, "SELECT ROLE_NAME, ROLE_OWNER FROM INFORMATION_SCHEMA.APPLICABLE_ROLES"),
Config: viewConfig(accName, false, "SELECT ROLE_NAME, ROLE_OWNER FROM INFORMATION_SCHEMA.APPLICABLE_ROLES"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("snowflake_view.test", "name", accName),
resource.TestCheckResourceAttr("snowflake_view.test", "database", accName),
resource.TestCheckResourceAttr("snowflake_view.test", "comment", "Terraform test resource"),
resource.TestCheckResourceAttr("snowflake_view.test", "copy_grants", "false"),
checkBool("snowflake_view.test", "is_secure", true), // this is from user_acceptance_test.go
),
},
@@ -37,32 +38,55 @@ func TestAcc_View2(t *testing.T) {
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: viewConfig(accName, "SELECT ROLE_NAME, ROLE_OWNER FROM INFORMATION_SCHEMA.APPLICABLE_ROLES where ROLE_OWNER like 'foo%%';"),
Config: viewConfig(accName, false, "SELECT ROLE_NAME, ROLE_OWNER FROM INFORMATION_SCHEMA.APPLICABLE_ROLES where ROLE_OWNER like 'foo%%';"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("snowflake_view.test", "name", accName),
resource.TestCheckResourceAttr("snowflake_view.test", "database", accName),
resource.TestCheckResourceAttr("snowflake_view.test", "comment", "Terraform test resource"),
resource.TestCheckResourceAttr("snowflake_view.test", "copy_grants", "false"),
checkBool("snowflake_view.test", "is_secure", true), // this is from user_acceptance_test.go
),
},
},
})
}

func viewConfig(n string, q string) string {
func TestAcc_ViewWithCopyGrants(t *testing.T) {
accName := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))

resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: viewConfig(accName, true, "SELECT ROLE_NAME, ROLE_OWNER FROM INFORMATION_SCHEMA.APPLICABLE_ROLES"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("snowflake_view.test", "name", accName),
resource.TestCheckResourceAttr("snowflake_view.test", "database", accName),
resource.TestCheckResourceAttr("snowflake_view.test", "comment", "Terraform test resource"),
resource.TestCheckResourceAttr("snowflake_view.test", "copy_grants", "true"),
checkBool("snowflake_view.test", "is_secure", true), // this is from user_acceptance_test.go
),
},
},
})
}

func viewConfig(n string, copyGrants bool, q string) string {
return fmt.Sprintf(`
resource "snowflake_database" "test" {
name = "%v"
}
resource "snowflake_view" "test" {
name = "%v"
comment = "Terraform test resource"
database = snowflake_database.test.name
schema = "PUBLIC"
is_secure = true
or_replace = false
statement = "%s"
name = "%v"
comment = "Terraform test resource"
database = snowflake_database.test.name
schema = "PUBLIC"
is_secure = true
or_replace = false
copy_grants = %t
statement = "%s"
}
`, n, n, q)
`, n, n, copyGrants, q)
}
50 changes: 50 additions & 0 deletions pkg/resources/view_test.go
Original file line number Diff line number Diff line change
@@ -71,6 +71,30 @@ func TestViewCreateOrReplace(t *testing.T) {
})
}

func TestViewCreateWithCopyGrants(t *testing.T) {
r := require.New(t)

in := map[string]interface{}{
"name": "good_name",
"database": "test_db",
"schema": "test_schema",
"copy_grants": true,
"statement": "SELECT * FROM test_db.PUBLIC.GREAT_TABLE WHERE account_id = 'bobs-account-id'",
}
d := schema.TestResourceDataRaw(t, resources.View().Schema, in)
r.NotNil(d)

testhelpers.WithMockDb(t, func(db *sql.DB, mock sqlmock.Sqlmock) {
mock.ExpectExec(
`^CREATE VIEW "test_db"."test_schema"."good_name" COPY GRANTS AS SELECT \* FROM test_db.PUBLIC.GREAT_TABLE WHERE account_id = 'bobs-account-id'$`,
).WillReturnResult(sqlmock.NewResult(1, 1))

expectReadView(mock)
err := resources.CreateView(d, db)
r.NoError(err)
})
}

func TestViewCreateAmpersand(t *testing.T) {
r := require.New(t)

@@ -152,3 +176,29 @@ func TestViewRead(t *testing.T) {
r.Nil(err)
})
}

func TestViewReadWithCopyGrants(t *testing.T) {
r := require.New(t)

in := map[string]interface{}{
"name": "good_name",
"database": "test_db",
"schema": "test_schema",
}

d := view(t, "test_db|test_schema|good_name", in)

testhelpers.WithMockDb(t, func(db *sql.DB, mock sqlmock.Sqlmock) {
// Test when resource is not found, checking if state will be empty
r.NotEmpty(d.State())
q := snowflake.NewViewBuilder("good_name").WithDB("test_db").WithSchema("test_schema").Show()
rows := sqlmock.NewRows([]string{
"created_on", "name", "reserved", "database_name", "schema_name", "owner", "comment", "text", "is_secure", "is_materialized",
},
).AddRow("2019-05-19 16:55:36.530 -0700", "good_name", "", "test_db", "test_schema", "admin", "great comment", "CREATE OR REPLACE VIEW test_db.test_schema.good_name COPY GRANTS AS SELECT * FROM test_db.GREAT_SCHEMA.GREAT_TABLE WHERE account_id = 'bobs-account-id'", true, false)
mock.ExpectQuery(q).WillReturnRows(rows)
err := resources.ReadView(d, db)
r.Equal("true", d.State().Attributes["copy_grants"])
r.Nil(err)
})
}

0 comments on commit 60128e9

Please sign in to comment.