From 2c407360af74fb6013a579b190f0c5ec73441083 Mon Sep 17 00:00:00 2001 From: Mike Gouline <1960272+gouline@users.noreply.github.com> Date: Fri, 26 Nov 2021 22:26:42 +1100 Subject: [PATCH 1/4] Allow setting resource monitor on account --- docs/resources/resource_monitor.md | 1 + pkg/resources/resource_monitor.go | 19 ++++++++++++++++++- .../resource_monitor_acceptance_test.go | 18 ++++++++++++++++++ pkg/resources/resource_monitor_test.go | 2 ++ pkg/snowflake/resource_monitor.go | 5 +++++ pkg/snowflake/resource_monitor_test.go | 9 +++++++++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/docs/resources/resource_monitor.md b/docs/resources/resource_monitor.md index 38d6338a37..989bc4dba7 100644 --- a/docs/resources/resource_monitor.md +++ b/docs/resources/resource_monitor.md @@ -41,6 +41,7 @@ resource snowflake_resource_monitor monitor { - **frequency** (String) The frequency interval at which the credit usage resets to 0. If you set a frequency for a resource monitor, you must also set START_TIMESTAMP. - **id** (String) The ID of this resource. - **notify_triggers** (Set of Number) A list of percentage thresholds at which to send an alert to subscribed users. +- **set_for_account** (Boolean) Specifies whether the resource monitor should be applied globally to your Snowflake account. - **start_timestamp** (String) The date and time when the resource monitor starts monitoring credit usage for the assigned warehouses. - **suspend_immediate_triggers** (Set of Number) A list of percentage thresholds at which to immediately suspend all warehouses. - **suspend_triggers** (Set of Number) A list of percentage thresholds at which to suspend all warehouses. diff --git a/pkg/resources/resource_monitor.go b/pkg/resources/resource_monitor.go index 8bcb002ad2..f391299963 100644 --- a/pkg/resources/resource_monitor.go +++ b/pkg/resources/resource_monitor.go @@ -70,6 +70,13 @@ var resourceMonitorSchema = map[string]*schema.Schema{ Description: "A list of percentage thresholds at which to send an alert to subscribed users.", ForceNew: true, }, + "set_for_account": { + Type: schema.TypeBool, + Optional: true, + Description: "Specifies whether the resource monitor should be applied globally to your Snowflake account.", + Default: false, + ForceNew: true, + }, } // ResourceMonitor returns a pointer to the resource representing a resource monitor @@ -129,7 +136,17 @@ func CreateResourceMonitor(d *schema.ResourceData, meta interface{}) error { d.SetId(name) - return ReadResourceMonitor(d, meta) + if err := ReadResourceMonitor(d, meta); err != nil { + return err + } + + if d.Get("set_for_account").(bool) { + if err := snowflake.Exec(db, cb.SetOnAccount()); err != nil { + return errors.Wrapf(err, "error setting resource monitor %v on account", name) + } + } + + return nil } // ReadResourceMonitor implements schema.ReadFunc diff --git a/pkg/resources/resource_monitor_acceptance_test.go b/pkg/resources/resource_monitor_acceptance_test.go index 3281f58000..5cd9ed7c93 100644 --- a/pkg/resources/resource_monitor_acceptance_test.go +++ b/pkg/resources/resource_monitor_acceptance_test.go @@ -23,6 +23,14 @@ func TestAcc_ResourceMonitor(t *testing.T) { resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "100"), ), }, + { + Config: resourceMonitorConfigSetForAccount(name, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", name), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "100"), + resource.TestCheckResourceAttrSet("snowflake_resource_monitor.test", "set_for_account"), + ), + }, // IMPORT { ResourceName: "snowflake_resource_monitor.test", @@ -41,3 +49,13 @@ resource "snowflake_resource_monitor" "test" { } `, accName) } + +func resourceMonitorConfigSetForAccount(accName string, setForAccount bool) string { + return fmt.Sprintf(` +resource "snowflake_resource_monitor" "test" { + name = "%v" + credit_quota = 100 + set_for_account = %t +} +`, accName, setForAccount) +} diff --git a/pkg/resources/resource_monitor_test.go b/pkg/resources/resource_monitor_test.go index bfceeb9b4a..132ca45c81 100644 --- a/pkg/resources/resource_monitor_test.go +++ b/pkg/resources/resource_monitor_test.go @@ -29,6 +29,7 @@ func TestResourceMonitorCreate(t *testing.T) { "notify_triggers": []interface{}{75, 88}, "suspend_triggers": []interface{}{99}, "suspend_immediate_triggers": []interface{}{105}, + "set_for_account": true, } d := schema.TestResourceDataRaw(t, resources.ResourceMonitor().Schema, in) @@ -38,6 +39,7 @@ func TestResourceMonitorCreate(t *testing.T) { mock.ExpectExec( `^CREATE RESOURCE MONITOR "good_name" CREDIT_QUOTA=100 TRIGGERS ON 99 PERCENT DO SUSPEND ON 105 PERCENT DO SUSPEND_IMMEDIATE ON 88 PERCENT DO NOTIFY ON 75 PERCENT DO NOTIFY$`, ).WillReturnResult(sqlmock.NewResult(1, 1)) + mock.ExpectExec(`^ALTER ACCOUNT SET RESOURCE_MONITOR = "good_name"$`).WillReturnResult(sqlmock.NewResult(1, 1)) expectReadResourceMonitor(mock) err := resources.CreateResourceMonitor(d, db) diff --git a/pkg/snowflake/resource_monitor.go b/pkg/snowflake/resource_monitor.go index 1e97a1754d..a40b1d18a2 100644 --- a/pkg/snowflake/resource_monitor.go +++ b/pkg/snowflake/resource_monitor.go @@ -119,6 +119,11 @@ func (rcb *ResourceMonitorCreateBuilder) Statement() string { return sb.String() } +// SetOnAccount returns the SQL query that will set the resource monitor globally on your Snowflake account +func (rcb *ResourceMonitorCreateBuilder) SetOnAccount() string { + return fmt.Sprintf(`ALTER ACCOUNT SET RESOURCE_MONITOR = "%v"`, rcb.name) +} + type resourceMonitor struct { Name sql.NullString `db:"name"` CreditQuota sql.NullString `db:"credit_quota"` diff --git a/pkg/snowflake/resource_monitor_test.go b/pkg/snowflake/resource_monitor_test.go index 04eb4c16ab..8be9c2b890 100644 --- a/pkg/snowflake/resource_monitor_test.go +++ b/pkg/snowflake/resource_monitor_test.go @@ -34,3 +34,12 @@ func TestResourceMonitor(t *testing.T) { q = cb.Statement() r.Equal(`CREATE RESOURCE MONITOR "resource_monitor" FREQUENCY='YEARLY' CREDIT_QUOTA=666 TRIGGERS ON 80 PERCENT DO NOTIFY ON 90 PERCENT DO NOTIFY ON 95 PERCENT DO SUSPEND ON 100 PERCENT DO SUSPEND_IMMEDIATE`, q) } + +func TestResourceMonitorSetOnAccount(t *testing.T) { + r := require.New(t) + s := snowflake.ResourceMonitor("test_resource_monitor") + r.NotNil(s) + + q := s.Create().SetOnAccount() + r.Equal(`ALTER ACCOUNT SET RESOURCE_MONITOR = "test_resource_monitor"`, q) +} From a8644ca1c403ec1b19619b20efaadbef15c34554 Mon Sep 17 00:00:00 2001 From: Mike Gouline <1960272+gouline@users.noreply.github.com> Date: Tue, 30 Nov 2021 13:47:49 +1100 Subject: [PATCH 2/4] Fix acceptance test --- .../resource_monitor_acceptance_test.go | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/pkg/resources/resource_monitor_acceptance_test.go b/pkg/resources/resource_monitor_acceptance_test.go index 5cd9ed7c93..bd3db91fb7 100644 --- a/pkg/resources/resource_monitor_acceptance_test.go +++ b/pkg/resources/resource_monitor_acceptance_test.go @@ -21,14 +21,7 @@ func TestAcc_ResourceMonitor(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", name), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "100"), - ), - }, - { - Config: resourceMonitorConfigSetForAccount(name, true), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", name), - resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "100"), - resource.TestCheckResourceAttrSet("snowflake_resource_monitor.test", "set_for_account"), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "set_for_account", "false"), ), }, // IMPORT @@ -43,19 +36,10 @@ func TestAcc_ResourceMonitor(t *testing.T) { func resourceMonitorConfig(accName string) string { return fmt.Sprintf(` -resource "snowflake_resource_monitor" "test" { - name = "%v" - credit_quota = 100 -} -`, accName) -} - -func resourceMonitorConfigSetForAccount(accName string, setForAccount bool) string { - return fmt.Sprintf(` resource "snowflake_resource_monitor" "test" { name = "%v" credit_quota = 100 - set_for_account = %t + set_for_account = false } -`, accName, setForAccount) +`, accName) } From 0fd208aacde036e3f79c9b4e2b86efa97f49907f Mon Sep 17 00:00:00 2001 From: Mike Gouline <1960272+gouline@users.noreply.github.com> Date: Tue, 30 Nov 2021 16:54:30 +1100 Subject: [PATCH 3/4] Disable ImportStateVerify to match network_policy_attachment --- pkg/resources/resource_monitor_acceptance_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/resources/resource_monitor_acceptance_test.go b/pkg/resources/resource_monitor_acceptance_test.go index bd3db91fb7..c2ae424c99 100644 --- a/pkg/resources/resource_monitor_acceptance_test.go +++ b/pkg/resources/resource_monitor_acceptance_test.go @@ -28,7 +28,7 @@ func TestAcc_ResourceMonitor(t *testing.T) { { ResourceName: "snowflake_resource_monitor.test", ImportState: true, - ImportStateVerify: true, + ImportStateVerify: false, }, }, }) From fe106496734c43f5788339681a2c4ed6d22f018c Mon Sep 17 00:00:00 2001 From: Mike Gouline <1960272+gouline@users.noreply.github.com> Date: Tue, 30 Nov 2021 17:34:21 +1100 Subject: [PATCH 4/4] Read set_for_account from resource monitor level --- pkg/resources/resource_monitor.go | 11 +++++++---- pkg/resources/resource_monitor_acceptance_test.go | 2 +- pkg/resources/resource_monitor_test.go | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/resources/resource_monitor.go b/pkg/resources/resource_monitor.go index f391299963..626a2c3b72 100644 --- a/pkg/resources/resource_monitor.go +++ b/pkg/resources/resource_monitor.go @@ -136,16 +136,16 @@ func CreateResourceMonitor(d *schema.ResourceData, meta interface{}) error { d.SetId(name) - if err := ReadResourceMonitor(d, meta); err != nil { - return err - } - if d.Get("set_for_account").(bool) { if err := snowflake.Exec(db, cb.SetOnAccount()); err != nil { return errors.Wrapf(err, "error setting resource monitor %v on account", name) } } + if err := ReadResourceMonitor(d, meta); err != nil { + return err + } + return nil } @@ -215,6 +215,9 @@ func ReadResourceMonitor(d *schema.ResourceData, meta interface{}) error { } err = d.Set("notify_triggers", nTrigs) + // Account level + d.Set("set_for_account", rm.Level.Valid && rm.Level.String == "ACCOUNT") + return err } diff --git a/pkg/resources/resource_monitor_acceptance_test.go b/pkg/resources/resource_monitor_acceptance_test.go index c2ae424c99..bd3db91fb7 100644 --- a/pkg/resources/resource_monitor_acceptance_test.go +++ b/pkg/resources/resource_monitor_acceptance_test.go @@ -28,7 +28,7 @@ func TestAcc_ResourceMonitor(t *testing.T) { { ResourceName: "snowflake_resource_monitor.test", ImportState: true, - ImportStateVerify: false, + ImportStateVerify: true, }, }, }) diff --git a/pkg/resources/resource_monitor_test.go b/pkg/resources/resource_monitor_test.go index 132ca45c81..58d6f0c3a5 100644 --- a/pkg/resources/resource_monitor_test.go +++ b/pkg/resources/resource_monitor_test.go @@ -53,7 +53,7 @@ func expectReadResourceMonitor(mock sqlmock.Sqlmock) { "frequency", "start_time", "end_time", "notify_at", "suspend_at", "suspend_immediately_at", "created_on", "owner", "comment", }).AddRow( - "good_name", 100.00, 0.00, 100.00, "", "MONTHLY", "2001-01-01 00:00:00.000 -0700", + "good_name", 100.00, 0.00, 100.00, "ACCOUNT", "MONTHLY", "2001-01-01 00:00:00.000 -0700", "", "75%,88%", "99%", "105%", "2001-01-01 00:00:00.000 -0700", "ACCOUNTADMIN", "") mock.ExpectQuery(`^SHOW RESOURCE MONITORS LIKE 'good_name'$`).WillReturnRows(rows) }