diff --git a/sysdig/internal/client/v2/alerts_v2.go b/sysdig/internal/client/v2/alerts_v2.go index 37577462..5bc6900c 100644 --- a/sysdig/internal/client/v2/alerts_v2.go +++ b/sysdig/internal/client/v2/alerts_v2.go @@ -22,10 +22,11 @@ const ( labelsV3Path = "%s/api/v3/labels/?limit=6000" labelsV3DescriptorsPath = "%s/api/v3/labels/descriptors/%s" - AlertV2TypePrometheus AlertV2Type = "PROMETHEUS" - AlertV2TypeManual AlertV2Type = "MANUAL" - AlertV2TypeEvent AlertV2Type = "EVENT" - AlertV2TypeChange AlertV2Type = "PERCENTAGE_OF_CHANGE" + AlertV2TypePrometheus AlertV2Type = "PROMETHEUS" + AlertV2TypeManual AlertV2Type = "MANUAL" + AlertV2TypeEvent AlertV2Type = "EVENT" + AlertV2TypeChange AlertV2Type = "PERCENTAGE_OF_CHANGE" + AlertV2TypeFormBasedPrometheus AlertV2Type = "FORM_BASED_PROMETHEUS" AlertV2SeverityHigh AlertV2Severity = "high" AlertV2SeverityMedium AlertV2Severity = "medium" @@ -48,6 +49,7 @@ type AlertV2Interface interface { AlertV2MetricInterface AlertV2DowntimeInterface AlertV2ChangeInterface + AlertV2FormBasedPrometheusInterface } type AlertV2PrometheusInterface interface { @@ -82,6 +84,14 @@ type AlertV2ChangeInterface interface { DeleteAlertV2Change(ctx context.Context, alertID int) error } +type AlertV2FormBasedPrometheusInterface interface { + Base + CreateAlertV2FormBasedPrometheus(ctx context.Context, alert AlertV2FormBasedPrometheus) (AlertV2FormBasedPrometheus, error) + UpdateAlertV2FormBasedPrometheus(ctx context.Context, alert AlertV2FormBasedPrometheus) (AlertV2FormBasedPrometheus, error) + GetAlertV2FormBasedPrometheus(ctx context.Context, alertID int) (AlertV2FormBasedPrometheus, error) + DeleteAlertV2FormBasedPrometheus(ctx context.Context, alertID int) error +} + type AlertV2DowntimeInterface interface { Base CreateAlertV2Downtime(ctx context.Context, alert AlertV2Downtime) (AlertV2Downtime, error) @@ -459,6 +469,82 @@ func (client *Client) DeleteAlertV2Change(ctx context.Context, alertID int) erro return client.deleteAlertV2(ctx, alertID) } +func (client *Client) CreateAlertV2FormBasedPrometheus(ctx context.Context, alert AlertV2FormBasedPrometheus) (AlertV2FormBasedPrometheus, error) { + err := client.addNotificationChannelType(ctx, alert.NotificationChannelConfigList) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + err = client.translateScopeSegmentLabels(ctx, &alert.Config.ScopedSegmentedConfig) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + payload, err := Marshal(alertV2FormBasedPrometheusWrapper{Alert: alert}) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + body, err := client.createAlertV2(ctx, payload) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + wrapper, err := Unmarshal[alertV2FormBasedPrometheusWrapper](body) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + return wrapper.Alert, nil +} + +func (client *Client) UpdateAlertV2FormBasedPrometheus(ctx context.Context, alert AlertV2FormBasedPrometheus) (AlertV2FormBasedPrometheus, error) { + err := client.addNotificationChannelType(ctx, alert.NotificationChannelConfigList) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + err = client.translateScopeSegmentLabels(ctx, &alert.Config.ScopedSegmentedConfig) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + payload, err := Marshal(alertV2FormBasedPrometheusWrapper{Alert: alert}) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + body, err := client.updateAlertV2(ctx, alert.ID, payload) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + wrapper, err := Unmarshal[alertV2FormBasedPrometheusWrapper](body) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + return wrapper.Alert, nil +} + +func (client *Client) GetAlertV2FormBasedPrometheus(ctx context.Context, alertID int) (AlertV2FormBasedPrometheus, error) { + body, err := client.getAlertV2(ctx, alertID) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + wrapper, err := Unmarshal[alertV2FormBasedPrometheusWrapper](body) + if err != nil { + return AlertV2FormBasedPrometheus{}, err + } + + return wrapper.Alert, nil +} + +func (client *Client) DeleteAlertV2FormBasedPrometheus(ctx context.Context, alertID int) error { + return client.deleteAlertV2(ctx, alertID) +} + func (client *Client) createAlertV2(ctx context.Context, alertJson io.Reader) (io.ReadCloser, error) { response, err := client.requester.Request(ctx, http.MethodPost, client.alertsV2URL(), alertJson) if err != nil { diff --git a/sysdig/internal/client/v2/model.go b/sysdig/internal/client/v2/model.go index e959c030..0094d81a 100644 --- a/sysdig/internal/client/v2/model.go +++ b/sysdig/internal/client/v2/model.go @@ -643,6 +643,27 @@ type AlertV2ConfigChange struct { LongerRangeSec int `json:"longerRangeSec"` } +type AlertV2ConfigFormBasedPrometheus struct { + ScopedSegmentedConfig + + Query string `json:"query"` + ConditionOperator string `json:"conditionOperator"` + Threshold float64 `json:"threshold"` + WarningConditionOperator string `json:"warningConditionOperator,omitempty"` + WarningThreshold *float64 `json:"warningThreshold,omitempty"` + NoDataBehaviour string `json:"noDataBehaviour"` +} + +type AlertV2FormBasedPrometheus struct { + AlertV2Common + DurationSec int `json:"durationSec"` // not really used but the api wants it set to 0 in POST/PUT + Config AlertV2ConfigFormBasedPrometheus `json:"config"` +} + +type alertV2FormBasedPrometheusWrapper struct { + Alert AlertV2FormBasedPrometheus `json:"alert"` +} + type AlertV2Change struct { AlertV2Common DurationSec int `json:"durationSec"` // not really used but the api wants it set to 0 in POST/PUT diff --git a/sysdig/provider.go b/sysdig/provider.go index 50b6d543..92e1a64f 100644 --- a/sysdig/provider.go +++ b/sysdig/provider.go @@ -146,6 +146,7 @@ func Provider() *schema.Provider { "sysdig_monitor_alert_v2_downtime": resourceSysdigMonitorAlertV2Downtime(), "sysdig_monitor_alert_v2_prometheus": resourceSysdigMonitorAlertV2Prometheus(), "sysdig_monitor_alert_v2_change": resourceSysdigMonitorAlertV2Change(), + "sysdig_monitor_alert_v2_form_based_prometheus": resourceSysdigMonitorAlertV2FormBasedPrometheus(), "sysdig_monitor_dashboard": resourceSysdigMonitorDashboard(), "sysdig_monitor_notification_channel_email": resourceSysdigMonitorNotificationChannelEmail(), "sysdig_monitor_notification_channel_opsgenie": resourceSysdigMonitorNotificationChannelOpsGenie(), diff --git a/sysdig/resource_sysdig_monitor_alert_v2_change_test.go b/sysdig/resource_sysdig_monitor_alert_v2_change_test.go index 5986efab..b470d031 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_change_test.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_change_test.go @@ -269,7 +269,7 @@ resource "sysdig_monitor_alert_v2_change" "sample" { longer_time_range_seconds = 3600 link { type = "runbook" - href = "http://ciao2.com" + href = "http://example.com" } link { type = "dashboard" diff --git a/sysdig/resource_sysdig_monitor_alert_v2_form_based_prometheus.go b/sysdig/resource_sysdig_monitor_alert_v2_form_based_prometheus.go new file mode 100644 index 00000000..1997d825 --- /dev/null +++ b/sysdig/resource_sysdig_monitor_alert_v2_form_based_prometheus.go @@ -0,0 +1,229 @@ +package sysdig + +import ( + "context" + "fmt" + "strconv" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigMonitorAlertV2FormBasedPrometheus() *schema.Resource { + + timeout := 5 * time.Minute + + return &schema.Resource{ + CreateContext: resourceSysdigMonitorAlertV2FormBasedPrometheusCreate, + UpdateContext: resourceSysdigMonitorAlertV2FormBasedPrometheusUpdate, + ReadContext: resourceSysdigMonitorAlertV2FormBasedPrometheusRead, + DeleteContext: resourceSysdigMonitorAlertV2FormBasedPrometheusDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + }, + + Schema: createScopedSegmentedAlertV2Schema(createAlertV2Schema(map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{">", ">=", "<", "<=", "=", "!="}, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + "warning_threshold": { + Type: schema.TypeString, + Optional: true, + Default: "", + }, + "query": { + Type: schema.TypeString, + Required: true, + }, + "no_data_behaviour": { + Type: schema.TypeString, + Optional: true, + Default: "DO_NOTHING", + ValidateFunc: validation.StringInSlice([]string{"DO_NOTHING", "TRIGGER"}, false), + }, + })), + } +} + +func getAlertV2FormBasedPrometheusClient(c SysdigClients) (v2.AlertV2FormBasedPrometheusInterface, error) { + return getAlertV2Client(c) +} + +func resourceSysdigMonitorAlertV2FormBasedPrometheusCreate(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + client, err := getAlertV2FormBasedPrometheusClient(i.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + a, err := buildAlertV2FormBasedPrometheusStruct(d) + if err != nil { + return diag.FromErr(err) + } + + aCreated, err := client.CreateAlertV2FormBasedPrometheus(ctx, *a) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.Itoa(aCreated.ID)) + + err = updateAlertV2FormBasedPrometheusState(d, &aCreated) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigMonitorAlertV2FormBasedPrometheusRead(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + client, err := getAlertV2FormBasedPrometheusClient(i.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + a, err := client.GetAlertV2FormBasedPrometheus(ctx, id) + if err != nil { + if err == v2.AlertV2NotFound { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + + err = updateAlertV2FormBasedPrometheusState(d, &a) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigMonitorAlertV2FormBasedPrometheusUpdate(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + client, err := getAlertV2FormBasedPrometheusClient(i.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + a, err := buildAlertV2FormBasedPrometheusStruct(d) + if err != nil { + return diag.FromErr(err) + } + + a.ID, _ = strconv.Atoi(d.Id()) + + aUpdated, err := client.UpdateAlertV2FormBasedPrometheus(ctx, *a) + if err != nil { + return diag.FromErr(err) + } + + err = updateAlertV2FormBasedPrometheusState(d, &aUpdated) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigMonitorAlertV2FormBasedPrometheusDelete(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + client, err := getAlertV2FormBasedPrometheusClient(i.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + err = client.DeleteAlertV2FormBasedPrometheus(ctx, id) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func buildAlertV2FormBasedPrometheusStruct(d *schema.ResourceData) (*v2.AlertV2FormBasedPrometheus, error) { + alertV2Common := buildAlertV2CommonStruct(d) + alertV2Common.Type = string(v2.AlertV2TypeFormBasedPrometheus) + config := v2.AlertV2ConfigFormBasedPrometheus{} + + buildScopedSegmentedConfigStruct(d, &config.ScopedSegmentedConfig) + + //ConditionOperator + config.ConditionOperator = d.Get("operator").(string) + + //threshold + config.Threshold = d.Get("threshold").(float64) + + //WarningThreshold + if warningThreshold, ok := d.GetOk("warning_threshold"); ok { + wts := warningThreshold.(string) + wt, err := strconv.ParseFloat(wts, 64) + if err != nil { + return nil, fmt.Errorf("cannot convert warning_threshold to a number: %w", err) + } + config.WarningThreshold = &wt + config.WarningConditionOperator = config.ConditionOperator + } + + //Query + config.Query = d.Get("query").(string) + + config.NoDataBehaviour = d.Get("no_data_behaviour").(string) + + alert := &v2.AlertV2FormBasedPrometheus{ + AlertV2Common: *alertV2Common, + DurationSec: 0, + Config: config, + } + return alert, nil +} + +func updateAlertV2FormBasedPrometheusState(d *schema.ResourceData, alert *v2.AlertV2FormBasedPrometheus) error { + err := updateAlertV2CommonState(d, &alert.AlertV2Common) + if err != nil { + return err + } + + err = updateScopedSegmentedConfigState(d, &alert.Config.ScopedSegmentedConfig) + if err != nil { + return err + } + + _ = d.Set("operator", alert.Config.ConditionOperator) + + _ = d.Set("threshold", alert.Config.Threshold) + + if alert.Config.WarningThreshold != nil { + _ = d.Set("warning_threshold", fmt.Sprintf("%v", *alert.Config.WarningThreshold)) + } + + _ = d.Set("query", alert.Config.Query) + + _ = d.Set("no_data_behaviour", alert.Config.NoDataBehaviour) + + return nil +} diff --git a/sysdig/resource_sysdig_monitor_alert_v2_form_based_prometheus_test.go b/sysdig/resource_sysdig_monitor_alert_v2_form_based_prometheus_test.go new file mode 100644 index 00000000..c92b1c25 --- /dev/null +++ b/sysdig/resource_sysdig_monitor_alert_v2_form_based_prometheus_test.go @@ -0,0 +1,264 @@ +//go:build tf_acc_sysdig_monitor || tf_acc_ibm_monitor + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/draios/terraform-provider-sysdig/sysdig" +) + +func TestAccAlertV2FormBasedPrometheusTest(t *testing.T) { + rText := func() string { return acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) } + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigIBMMonitorAPIKeyEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: alertV2FormBasedPrometheusTest(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithNoData(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithNotificationChannels(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithDescription(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithSeverity(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithGroup(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithCustomNotifications(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithLink(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithEnabled(rText()), + }, + { + Config: alertV2FormBasedPrometheusTestWithWarningThreshold(rText()), + }, + { + ResourceName: "sysdig_monitor_alert_v2_form_based_prometheus.sample", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func alertV2FormBasedPrometheusTest(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithNoData(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + no_data_behaviour = "TRIGGER" +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithNotificationChannels(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_notification_channel_email" "nc_email_1" { + name = "%s1" + recipients = ["root@localhost.com"] +} + +resource "sysdig_monitor_notification_channel_email" "nc_email_2" { + name = "%s2" + recipients = ["root@localhost.com"] +} + +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + enabled = false + notification_channels { + id = sysdig_monitor_notification_channel_email.nc_email_1.id + notify_on_resolve = false + } + notification_channels { + id = sysdig_monitor_notification_channel_email.nc_email_2.id + renotify_every_minutes = 30 + } +} +`, name, name, name) +} + +func alertV2FormBasedPrometheusTestWithDescription(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + description = "description" +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithSeverity(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + severity = "high" +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithGroup(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + group = "customgroup" +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithCustomNotifications(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + custom_notification { + subject = "test" + prepend = "pre" + append = "post" + } +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithLink(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_dashboard" "dashboard_1" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + description = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + panel { + pos_x = 0 + pos_y = 0 + width = 12 # Maximum size: 24 + height = 6 + type = "timechart" + name = "example panel" + description = "description" + + legend { + show_current = true + position = "bottom" + layout = "inline" + } + + query { + promql = "avg(avg_over_time(sysdig_host_cpu_used_percent[$__interval]))" + unit = "percent" + + format { + display_format = "auto" + input_format = "0-100" + y_axis = "auto" + null_value_display_mode = "nullGap" + } + } + } +} + +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + link { + type = "runbook" + href = "http://example.com" + } + link { + type = "dashboard" + id = sysdig_monitor_dashboard.dashboard_1.id + } +} +`, name, name, name) +} + +func alertV2FormBasedPrometheusTestWithEnabled(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + enabled = false +} +`, name) +} + +func alertV2FormBasedPrometheusTestWithWarningThreshold(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_notification_channel_email" "nc_email_3" { + name = "%s3" + recipients = ["root@localhost.com"] +} + +resource "sysdig_monitor_notification_channel_email" "nc_email_4" { + name = "%s4" + recipients = ["root@localhost.com"] +} + +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + + name = "TERRAFORM TEST - FORM BASED PROMETHEUS %s" + query = "avg_over_time(sysdig_container_cpu_used_percent{}[59s])" + operator = ">=" + threshold = 50 + enabled = false + warning_threshold = 10 + notification_channels { + id = sysdig_monitor_notification_channel_email.nc_email_3.id + } + notification_channels { + id = sysdig_monitor_notification_channel_email.nc_email_4.id + warning_threshold = true + } +} +`, name, name, name) +} diff --git a/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go b/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go index 38074fd6..7471d7af 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go @@ -317,7 +317,7 @@ resource "sysdig_monitor_alert_v2_metric" "sample" { trigger_after_minutes = 15 link { type = "runbook" - href = "http://ciao2.com" + href = "http://example.com" } link { type = "dashboard" diff --git a/website/docs/index.md b/website/docs/index.md index 52a5250b..824b05ce 100644 --- a/website/docs/index.md +++ b/website/docs/index.md @@ -248,6 +248,7 @@ When IBM Workload Protection resources are to be created, this authentication mu > - `sysdig_monitor_alert_v2_metric` > - `sysdig_monitor_alert_v2_prometheus` > - `sysdig_monitor_alert_v2_change` +> - `sysdig_monitor_alert_v2_form_based_prometheus` > - `sysdig_monitor_dashboard` > - `sysdig_secure_posture_zone` > diff --git a/website/docs/r/monitor_alert_v2_change.md b/website/docs/r/monitor_alert_v2_change.md index 806704a7..5c40d243 100644 --- a/website/docs/r/monitor_alert_v2_change.md +++ b/website/docs/r/monitor_alert_v2_change.md @@ -101,7 +101,7 @@ By defining this field, the user can add link to notifications. * `group_aggregation` - (Required) group aggregation function for data. It can be `avg`, `sum`, `min`, `max`. * `operator` - (Required) Operator for the condition to alert on. It can be `>`, `>=`, `<`, `<=`, `=` or `!=`. * `threshold` - (Required) Threshold used together with `op` to trigger the alert if crossed. -* `warning_threshold` - (Optional) Warning threshold used together with `op` to trigger the alert if crossed. Must be a number lower than `threshold`. +* `warning_threshold` - (Optional) Warning threshold used together with `op` to trigger the alert if crossed. Must be a number that triggers the alert before reaching the main `threshold`. * `shorter_time_range_seconds` - (Required) Time range for which data is compared to a longer, previous period. Can be one of `300` (5 minutes), `600` (10 minutes), `3600` (1 hour), `14400` (4 hours), `86400` (1 day). * `longer_time_range_seconds` - (Required) Time range for which data will be used as baseline for comparisons with data in the time range defined in `shorter_time_range_seconds`. Possible values depend on `shorter_time_range_seconds`: for a shorter time range of 5 minutes, longer time range can be 1, 2 or 3 hours, for a shorter time range or 10 minutes, it can be from 1 to 8 hours, for a shorter time range or one hour, it can be from 4 to 24 hours, for a shorter time range of 4 hours, it can be from 1 to 7 days, for a shorter time range of one day, it can only be 7 days. diff --git a/website/docs/r/monitor_alert_v2_event.md b/website/docs/r/monitor_alert_v2_event.md index 1909b24f..848710fb 100644 --- a/website/docs/r/monitor_alert_v2_event.md +++ b/website/docs/r/monitor_alert_v2_event.md @@ -110,7 +110,7 @@ Enables the creation of a capture file of the syscalls during the event. * `group_by` - (Optional) List of segments to trigger a separate alert on. Example: `["kube_cluster_name", "kube_pod_name"]`. * `operator` - (Required) Condition operator of the event count. It can be `>`, `>=`, `<`, `<=`, `=` or `!=`. * `threshold` - (Required) Number of events to match with `op`. -* `warning_threshold` - (Optional) Number of events to match with `op` to trigger a warning alert. Must be a number lower than `threshold`. +* `warning_threshold` - (Optional) Warning threshold used together with `op` to trigger the alert if crossed. Must be a number that triggers the alert before reaching the main `threshold`. * `filter` - (Required) String that matches part of name, tag or the description of Sysdig Events. * `sources` - (Required) List of sources of the event. It can be `kubernetes`, `containerd`, `docker` or arbitrary custom sources. diff --git a/website/docs/r/monitor_alert_v2_form_based_prometheus.md b/website/docs/r/monitor_alert_v2_form_based_prometheus.md new file mode 100644 index 00000000..0ec783b0 --- /dev/null +++ b/website/docs/r/monitor_alert_v2_form_based_prometheus.md @@ -0,0 +1,100 @@ +--- +subcategory: "Sysdig Monitor" +layout: "sysdig" +page_title: "Sysdig: sysdig_monitor_alert_v2_form_based_prometheus" +description: |- + Creates a Sysdig Monitor Form Based Prometheus Alert with AlertV2 API. +--- + +# Resource: sysdig_monitor_alert_v2_form_based_prometheus + +Creates a Sysdig Monitor Form Based Prometheus Alert. The notification is triggered on the user-defined PromQL expression with a threshold and operator defined outside of the expression, as described in [here](https://docs.sysdig.com/en/docs/sysdig-monitor/alerts/alert-types/metric-alerts/#translate-to-promql). + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +```terraform +resource "sysdig_monitor_alert_v2_form_based_prometheus" "sample" { + name = "Elasticsearch JVM heap usage" + description = "Elasticsearch JVM heap used over attention threshold" + severity = "high" + query = "(elasticsearch_jvm_memory_used_bytes{area=\"heap\"} / elasticsearch_jvm_memory_max_bytes{area=\"heap\"}) * 100" + operator = ">" + threshold = 80 + notification_channels { + id = 1234 + renotify_every_minutes = 5 + } +} +``` + +## Argument Reference + +### Common alert arguments + +These arguments are common to all alerts in Sysdig Monitor. + +* `name` - (Required) The name of the Monitor alert. It must be unique. +* `description` - (Optional) The description of Monitor alert. +* `group` - (Optional) Lowercase string to group alerts in the UI. +* `severity` - (Optional) Severity of the Monitor alert. It must be `high`, `medium`, `low` or `info`. Default: `low`. +* `enabled` - (Optional) Boolean that defines if the alert is enabled or not. Default: `true`. +* `notification_channels` - (Optional) List of notification channel configurations. +* `custom_notification` - (Optional) Allows to define a custom notification title, prepend and append text. +* `link` - (Optional) List of links to add to notifications. + +### `notification_channels` + +By defining this field, the user can choose to which notification channels send the events when the alert fires. + +It is a list of objects with the following fields: +* `id` - (Required) The ID of the notification channel. +* `renotify_every_minutes` - (Optional) the amount of minutes to wait before re sending the notification to this channel. `0` means no renotification enabled. +* `notify_on_resolve` - (Optional) Wether to send a notification when the alert is resolved. Default: `true`. +* `main_threshold` - (Optional) Whether this notification channel is used for the main threshold of the alert. Default: `true`. +* `warning_threshold` - (Optional) Whether this notification channel is used for the warning threshold of the alert. Default: `false`. + +### `custom_notification` + +By defining this field, the user can modify the title and the body of the message sent when the alert is fired. + +* `subject` - (Optional) Sets the title of the alert. +* `prepend` - (Optional) Text to add before the alert template. +* `append` - (Optional) Text to add after the alert template. + +### `link` + +By defining this field, the user can add link to notifications. + +* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `href` - (Optional) When using `runbook` type, url of the external resource. +* `id` - (Optional) When using `dashboard` type, dashboard id. + +### Form Based Prometheus alert arguments + +* `query` - (Required) PromQL-based metric expression to alert on. Example: `sysdig_host_memory_available_bytes / sysdig_host_memory_total_bytes * 100` or `avg_over_time(sysdig_container_cpu_used_percent{}[59s])`. +* `operator` - (Required) Operator for the condition to alert on. It can be `>`, `>=`, `<`, `<=`, `=` or `!=`. +* `threshold` - (Required) Threshold used together with `op` to trigger the alert if crossed. +* `warning_threshold` - (Optional) Warning threshold used together with `op` to trigger the alert if crossed. Must be a number that triggers the alert before reaching the main `threshold`. +* `no_data_behaviour` - (Optional) behaviour in case of missing data. Can be `DO_NOTHING`, i.e. ignore, or `TRIGGER`, i.e. notify on main threshold. Default: `DO_NOTHING`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +### Common alert attributes + +In addition to all arguments above, the following attributes are exported, which are common to all the alerts in Sysdig Monitor: + +* `id` - ID of the alert created. +* `version` - Current version of the resource in Sysdig Monitor. +* `team` - Team ID that owns the alert. + +## Import + +Form Based Prometheus alerts can be imported using the alert ID, e.g. + +``` +$ terraform import sysdig_monitor_alert_v2_form_based_prometheus.example 12345 +``` diff --git a/website/docs/r/monitor_alert_v2_metric.md b/website/docs/r/monitor_alert_v2_metric.md index 7504332b..6bf1eea1 100644 --- a/website/docs/r/monitor_alert_v2_metric.md +++ b/website/docs/r/monitor_alert_v2_metric.md @@ -111,7 +111,7 @@ Enables the creation of a capture file of the syscalls during the event. * `group_aggregation` - (Required) group aggregation function for data. It can be `avg`, `sum`, `min`, `max`. * `operator` - (Required) Operator for the condition to alert on. It can be `>`, `>=`, `<`, `<=`, `=` or `!=`. * `threshold` - (Required) Threshold used together with `op` to trigger the alert if crossed. -* `warning_threshold` - (Optional) Warning threshold used together with `op` to trigger the alert if crossed. Must be a number lower than `threshold`. +* `warning_threshold` - (Optional) Warning threshold used together with `op` to trigger the alert if crossed. Must be a number that triggers the alert before reaching the main `threshold`. * `no_data_behaviour` - (Optional) behaviour in case of missing data. Can be `DO_NOTHING`, i.e. ignore, or `TRIGGER`, i.e. notify on main threshold. Default: `DO_NOTHING`. ### `scope` diff --git a/website/docs/r/monitor_alert_v2_prometheus.md b/website/docs/r/monitor_alert_v2_prometheus.md index b41e0115..63d5a535 100644 --- a/website/docs/r/monitor_alert_v2_prometheus.md +++ b/website/docs/r/monitor_alert_v2_prometheus.md @@ -44,7 +44,7 @@ These arguments are common to all alerts in Sysdig Monitor. * `custom_notification` - (Optional) Allows to define a custom notification title, prepend and append text. * `link` - (Optional) List of links to add to notifications. -### `notification_channels` - +### `notification_channels` By defining this field, the user can choose to which notification channels send the events when the alert fires.