From 1a3af922d198a3da489dc35ab144388f05f33fed Mon Sep 17 00:00:00 2001 From: Mike Gouline <1960272+gouline@users.noreply.github.com> Date: Wed, 1 Dec 2021 06:11:56 +1100 Subject: [PATCH] feat: Allow setting resource monitor on account (#768) --- docs/resources/resource_monitor.md | 1 + pkg/resources/resource_monitor.go | 22 ++++++++++++++++++- .../resource_monitor_acceptance_test.go | 6 +++-- pkg/resources/resource_monitor_test.go | 4 +++- pkg/snowflake/resource_monitor.go | 5 +++++ pkg/snowflake/resource_monitor_test.go | 9 ++++++++ 6 files changed, 43 insertions(+), 4 deletions(-) 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..626a2c3b72 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 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 } // ReadResourceMonitor implements schema.ReadFunc @@ -198,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 3281f58000..bd3db91fb7 100644 --- a/pkg/resources/resource_monitor_acceptance_test.go +++ b/pkg/resources/resource_monitor_acceptance_test.go @@ -21,6 +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"), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "set_for_account", "false"), ), }, // IMPORT @@ -36,8 +37,9 @@ func TestAcc_ResourceMonitor(t *testing.T) { func resourceMonitorConfig(accName string) string { return fmt.Sprintf(` resource "snowflake_resource_monitor" "test" { - name = "%v" - credit_quota = 100 + name = "%v" + credit_quota = 100 + set_for_account = false } `, accName) } diff --git a/pkg/resources/resource_monitor_test.go b/pkg/resources/resource_monitor_test.go index bfceeb9b4a..58d6f0c3a5 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) @@ -51,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) } 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) +}