Skip to content

Commit

Permalink
feat: Resource monitor v1 readiness (#3052)
Browse files Browse the repository at this point in the history
## Changes
- Add ValuePresent assert to our custom assertions
- Add ToConfigValues function for every model
- Update Resource Monitor SDK + unit and integration tests
- Update Resource Monitor Resource + acc tests
- Handle issues connected to the resource monitor (mostly timestamp
format difference causing infinite plan or only trigger updates causing
SQL compilation error):
  -  #1500 
  - #1624 
  - #1716 
  - #1754 
  - #1821 
  - #1832 
  - #1990

## Next pr
- Adjust examples and update migration notes
- Data source (impl, tests, examples, migration notes)

## References
* [CREATE RESOURCE
MONITOR](https://docs.snowflake.com/en/sql-reference/sql/create-resource-monitor)
  • Loading branch information
sfc-gh-jcieslak committed Sep 11, 2024
1 parent d5dac60 commit ac493f4
Show file tree
Hide file tree
Showing 29 changed files with 2,109 additions and 861 deletions.
40 changes: 28 additions & 12 deletions docs/resources/resource_monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,43 @@ resource "snowflake_resource_monitor" "monitor" {

### Required

- `name` (String) Identifier for the resource monitor; must be unique for your account.
- `name` (String) Identifier for the resource monitor; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`

### Optional

- `credit_quota` (Number) The number of credits allocated monthly to the resource monitor.
- `credit_quota` (Number) The number of credits allocated to the resource monitor per frequency interval. When total usage for all warehouses assigned to the monitor reaches this number for the current frequency interval, the resource monitor is considered to be at 100% of quota.
- `end_timestamp` (String) The date and time when the resource monitor suspends the assigned warehouses.
- `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.
- `notify_triggers` (Set of Number) A list of percentage thresholds at which to send an alert to subscribed users.
- `notify_users` (Set of String) Specifies the list of users to receive email notifications on resource monitors.
- `set_for_account` (Boolean) Specifies whether the resource monitor should be applied globally to your Snowflake account (defaults to false).
- `start_timestamp` (String) The date and time when the resource monitor starts monitoring credit usage for the assigned warehouses.
- `suspend_immediate_trigger` (Number) The number that represents the percentage threshold at which to immediately suspend all warehouses.
- `suspend_immediate_triggers` (Set of Number, Deprecated) A list of percentage thresholds at which to suspend all warehouses.
- `suspend_trigger` (Number) The number that represents the percentage threshold at which to suspend all warehouses.
- `suspend_triggers` (Set of Number, Deprecated) A list of percentage thresholds at which to suspend all warehouses.
- `warehouses` (Set of String) A list of warehouses to apply the resource monitor to.
- `frequency` (String) The frequency interval at which the credit usage resets to 0. Valid values are (case-insensitive): `MONTHLY` | `DAILY` | `WEEKLY` | `YEARLY` | `NEVER`. If you set a `frequency` for a resource monitor, you must also set `start_timestamp`. If you specify `NEVER` for the frequency, the credit usage for the warehouse does not reset. After removing this field from the config, the previously set value will be preserved on the Snowflake side, not the default value. That's due to Snowflake limitation and the lack of unset functionality for this parameter.
- `notify_triggers` (Set of Number) Specifies a list of percentages of the credit quota. After reaching any of the values the users passed in the notify_users field will be notified (to receive the notification they should have notifications enabled). Values over 100 are supported.
- `notify_users` (Set of String) Specifies the list of users (their identifiers) to receive email notifications on resource monitors.
- `start_timestamp` (String) The date and time when the resource monitor starts monitoring credit usage for the assigned warehouses. If you set a `start_timestamp` for a resource monitor, you must also set `frequency`. After removing this field from the config, the previously set value will be preserved on the Snowflake side, not the default value. That's due to Snowflake limitation and the lack of unset functionality for this parameter.
- `suspend_immediate_trigger` (Number) Represents a numeric value specified as a percentage of the credit quota. Values over 100 are supported. After reaching this value, all assigned warehouses immediately cancel any currently running queries or statements. In addition, this action sends a notification to all users who have enabled notifications for themselves.
- `suspend_trigger` (Number) Represents a numeric value specified as a percentage of the credit quota. Values over 100 are supported. After reaching this value, all assigned warehouses while allowing currently running queries to complete will be suspended. No new queries can be executed by the warehouses until the credit quota for the resource monitor is increased. In addition, this action sends a notification to all users who have enabled notifications for themselves.

### Read-Only

- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
- `show_output` (List of Object) Outputs the result of `SHOW RESOURCE MONITORS` for the given resource monitor. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedatt--show_output"></a>
### Nested Schema for `show_output`

Read-Only:

- `comment` (String)
- `created_on` (String)
- `credit_quota` (Number)
- `end_time` (String)
- `frequency` (String)
- `level` (String)
- `name` (String)
- `owner` (String)
- `remaining_credits` (Number)
- `start_time` (String)
- `suspend_at` (Number)
- `suspend_immediate_at` (Number)
- `used_credits` (Number)

## Import

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/warehouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ resource "snowflake_warehouse" "warehouse" {
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
- `parameters` (List of Object) Outputs the result of `SHOW PARAMETERS IN WAREHOUSE` for the given warehouse. (see [below for nested schema](#nestedatt--parameters))
- `show_output` (List of Object) Outputs the result of `SHOW WAREHOUSE` for the given warehouse. (see [below for nested schema](#nestedatt--show_output))
- `show_output` (List of Object) Outputs the result of `SHOW WAREHOUSES` for the given warehouse. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedatt--parameters"></a>
### Nested Schema for `parameters`
Expand Down
18 changes: 8 additions & 10 deletions framework/provider/resource_monitor_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ func (r *ResourceMonitorResource) create(ctx context.Context, data *resourceMoni
}
if !data.Frequency.IsNull() && data.Frequency.ValueString() != "" {
setWith = true
frequency, err := sdk.FrequencyFromString(data.Frequency.ValueString())
frequency, err := sdk.ToResourceMonitorFrequency(data.Frequency.ValueString())
if err != nil {
diags.AddError("Client Error", fmt.Sprintf("Unable to create resource monitor, got error: %s", err))
}
Expand All @@ -529,7 +529,7 @@ func (r *ResourceMonitorResource) create(ctx context.Context, data *resourceMoni
elements := make([]types.String, 0, len(data.NotifyUsers.Elements()))
var notifiedUsers []sdk.NotifiedUser
for _, e := range elements {
notifiedUsers = append(notifiedUsers, sdk.NotifiedUser{Name: e.ValueString()})
notifiedUsers = append(notifiedUsers, sdk.NotifiedUser{Name: sdk.NewAccountObjectIdentifier(e.ValueString())})
}
with.NotifyUsers = &sdk.NotifyUsers{
Users: notifiedUsers,
Expand Down Expand Up @@ -600,13 +600,11 @@ func (r *ResourceMonitorResource) read(ctx context.Context, data *resourceMonito

data.CreditQuota = types.Float64Value(resourceMonitor.CreditQuota)
data.Frequency = types.StringValue(string(resourceMonitor.Frequency))
switch resourceMonitor.Level {
switch *resourceMonitor.Level {
case sdk.ResourceMonitorLevelAccount:
data.Level = types.StringValue("ACCOUNT")
case sdk.ResourceMonitorLevelWarehouse:
data.Level = types.StringValue("WAREHOUSE")
case sdk.ResourceMonitorLevelNull:
data.Level = types.StringValue("NULL")
}
data.UsedCredits = types.Float64Value(resourceMonitor.UsedCredits)
data.RemainingCredits = types.Float64Value(resourceMonitor.RemainingCredits)
Expand Down Expand Up @@ -637,11 +635,11 @@ func (r *ResourceMonitorResource) read(ctx context.Context, data *resourceMonito
"threshold": types.Int64Type,
"trigger_action": types.StringType,
})
if len(resourceMonitor.NotifyTriggers) == 0 && resourceMonitor.SuspendAt == nil && resourceMonitor.SuspendImmediateAt == nil {
if len(resourceMonitor.NotifyAt) == 0 && resourceMonitor.SuspendAt == nil && resourceMonitor.SuspendImmediateAt == nil {
data.Triggers = types.SetNull(triggersObjectType)
} else {
var triggers []resourceMonitorTriggerModel
for _, e := range resourceMonitor.NotifyTriggers {
for _, e := range resourceMonitor.NotifyAt {
triggers = append(triggers, resourceMonitorTriggerModel{
Threshold: types.Int64Value(int64(e)),
TriggerAction: types.StringValue(string(sdk.TriggerActionNotify)),
Expand Down Expand Up @@ -700,7 +698,7 @@ func (r *ResourceMonitorResource) update(ctx context.Context, plan *resourceMoni
if opts.Set == nil {
opts.Set = &sdk.ResourceMonitorSet{}
}
frequency, err := sdk.FrequencyFromString(plan.Frequency.ValueString())
frequency, err := sdk.ToResourceMonitorFrequency(plan.Frequency.ValueString())
if err != nil {
diags.AddError("Client Error", fmt.Sprintf("Unable to update resource monitor, got error: %s", err))
return plan, nil, diags
Expand All @@ -713,7 +711,7 @@ func (r *ResourceMonitorResource) update(ctx context.Context, plan *resourceMoni
if opts.Set == nil {
opts.Set = &sdk.ResourceMonitorSet{}
}
frequency, err := sdk.FrequencyFromString(plan.Frequency.ValueString())
frequency, err := sdk.ToResourceMonitorFrequency(plan.Frequency.ValueString())
if err != nil {
diags.AddError("Client Error", fmt.Sprintf("Unable to update resource monitor, got error: %s", err))
return plan, nil, diags
Expand All @@ -734,7 +732,7 @@ func (r *ResourceMonitorResource) update(ctx context.Context, plan *resourceMoni
elements := make([]types.String, 0, len(plan.NotifyUsers.Elements()))
plan.NotifyUsers.ElementsAs(ctx, &elements, false)
for _, e := range elements {
notifiedUsers = append(notifiedUsers, sdk.NotifiedUser{Name: e.ValueString()})
notifiedUsers = append(notifiedUsers, sdk.NotifiedUser{Name: sdk.NewAccountObjectIdentifier(e.ValueString())})
}
opts.Set.NotifyUsers = &sdk.NotifyUsers{
Users: notifiedUsers,
Expand Down
4 changes: 2 additions & 2 deletions pkg/acceptance/bettertestspoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ func (w *WarehouseModel) WithWarehouseSizeEnum(warehouseSize sdk.WarehouseSize)
Each of the above assertion types/config models has its own generator and cleanup entry in our Makefile.
You can generate config models with:
```shell
make clean-resource-model-builder generate-resource-model-builder
make clean-resource-model-builders generate-resource-model-builders
```

You can use cli flags:
```shell
make clean-resource-model-builder generate-resource-model-builder SF_TF_GENERATOR_ARGS='--dry-run --verbose'
make clean-resource-model-builders generate-resource-model-builders SF_TF_GENERATOR_ARGS='--dry-run --verbose'
```

To clean/generate all from this package run
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ var allStructs = []SdkObjectDef{
ObjectType: sdk.ObjectTypeWarehouse,
ObjectStruct: sdk.Warehouse{},
},
{
IdType: "sdk.AccountObjectIdentifier",
ObjectType: sdk.ObjectTypeResourceMonitor,
ObjectStruct: sdk.ResourceMonitor{},
},
}

func GetSdkObjectDetails() []genhelpers.SdkObjectDetails {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package objectassert

import (
"fmt"
"testing"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
)

func (r *ResourceMonitorAssert) HasNonEmptyStartTime() *ResourceMonitorAssert {
r.AddAssertion(func(t *testing.T, o *sdk.ResourceMonitor) error {
t.Helper()
if o.StartTime == "" {
return fmt.Errorf("expected start time to be non empty")
}
return nil
})
return r
}

func (r *ResourceMonitorAssert) HasNonEmptyEndTime() *ResourceMonitorAssert {
r.AddAssertion(func(t *testing.T, o *sdk.ResourceMonitor) error {
t.Helper()
if o.StartTime == "" {
return fmt.Errorf("expected end time to be non empty")
}
return nil
})
return r
}
Loading

0 comments on commit ac493f4

Please sign in to comment.