Skip to content

feat(observability): add send_resolved field #935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/data-sources/observability_instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ Read-Only:
- `auth_password` (String) SMTP authentication password.
- `auth_username` (String) SMTP authentication username.
- `from` (String) The sender email address. Must be a valid email address
- `send_resolved` (Boolean) Whether to notify about resolved alerts.
- `smart_host` (String) The SMTP host through which emails are sent.
- `to` (String) The email address to send notifications to. Must be a valid email address

Expand All @@ -110,6 +111,7 @@ Read-Only:

- `api_key` (String) The API key for OpsGenie.
- `api_url` (String) The host to send OpsGenie API requests to. Must be a valid URL
- `send_resolved` (Boolean) Whether to notify about resolved alerts.
- `tags` (String) Comma separated list of tags attached to the notifications.


Expand All @@ -119,6 +121,7 @@ Read-Only:
Read-Only:

- `ms_teams` (Boolean) Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.
- `send_resolved` (Boolean) Whether to notify about resolved alerts.
- `url` (String) The endpoint to send HTTP POST requests to. Must be a valid URL


Expand Down
3 changes: 3 additions & 0 deletions docs/resources/observability_instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Optional:
- `auth_password` (String) SMTP authentication password.
- `auth_username` (String) SMTP authentication username.
- `from` (String) The sender email address. Must be a valid email address
- `send_resolved` (Boolean) Whether to notify about resolved alerts.
- `smart_host` (String) The SMTP host through which emails are sent.
- `to` (String) The email address to send notifications to. Must be a valid email address

Expand All @@ -109,6 +110,7 @@ Optional:

- `api_key` (String) The API key for OpsGenie.
- `api_url` (String) The host to send OpsGenie API requests to. Must be a valid URL
- `send_resolved` (Boolean) Whether to notify about resolved alerts.
- `tags` (String) Comma separated list of tags attached to the notifications.


Expand All @@ -118,6 +120,7 @@ Optional:
Optional:

- `ms_teams` (Boolean) Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.
- `send_resolved` (Boolean) Whether to notify about resolved alerts.
- `url` (String) The endpoint to send HTTP POST requests to. Must be a valid URL


Expand Down
12 changes: 12 additions & 0 deletions stackit/internal/services/observability/instance/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ func (d *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
Description: "The sender email address. Must be a valid email address",
Computed: true,
},
"send_resolved": schema.BoolAttribute{
Description: "Whether to notify about resolved alerts.",
Computed: true,
},
"smart_host": schema.StringAttribute{
Description: "The SMTP host through which emails are sent.",
Computed: true,
Expand Down Expand Up @@ -247,6 +251,10 @@ func (d *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
Description: "Comma separated list of tags attached to the notifications.",
Computed: true,
},
"send_resolved": schema.BoolAttribute{
Description: "Whether to notify about resolved alerts.",
Computed: true,
},
},
},
},
Expand All @@ -263,6 +271,10 @@ func (d *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
Description: "Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.",
Computed: true,
},
"send_resolved": schema.BoolAttribute{
Description: "Whether to notify about resolved alerts.",
Computed: true,
},
},
},
},
Expand Down
65 changes: 45 additions & 20 deletions stackit/internal/services/observability/instance/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ type emailConfigsModel struct {
AuthPassword types.String `tfsdk:"auth_password"`
AuthUsername types.String `tfsdk:"auth_username"`
From types.String `tfsdk:"from"`
SendResolved types.Bool `tfsdk:"send_resolved"`
Smarthost types.String `tfsdk:"smart_host"`
To types.String `tfsdk:"to"`
}
Expand All @@ -181,32 +182,37 @@ var emailConfigsTypes = map[string]attr.Type{
"auth_password": types.StringType,
"auth_username": types.StringType,
"from": types.StringType,
"send_resolved": types.BoolType,
"smart_host": types.StringType,
"to": types.StringType,
}

// Struct corresponding to Model.AlertConfig.receivers.opsGenieConfigs
type opsgenieConfigsModel struct {
ApiKey types.String `tfsdk:"api_key"`
ApiUrl types.String `tfsdk:"api_url"`
Tags types.String `tfsdk:"tags"`
ApiKey types.String `tfsdk:"api_key"`
ApiUrl types.String `tfsdk:"api_url"`
Tags types.String `tfsdk:"tags"`
SendResolved types.Bool `tfsdk:"send_resolved"`
}

var opsgenieConfigsTypes = map[string]attr.Type{
"api_key": types.StringType,
"api_url": types.StringType,
"tags": types.StringType,
"api_key": types.StringType,
"api_url": types.StringType,
"tags": types.StringType,
"send_resolved": types.BoolType,
}

// Struct corresponding to Model.AlertConfig.receivers.webHooksConfigs
type webHooksConfigsModel struct {
Url types.String `tfsdk:"url"`
MsTeams types.Bool `tfsdk:"ms_teams"`
Url types.String `tfsdk:"url"`
MsTeams types.Bool `tfsdk:"ms_teams"`
SendResolved types.Bool `tfsdk:"send_resolved"`
}

var webHooksConfigsTypes = map[string]attr.Type{
"url": types.StringType,
"ms_teams": types.BoolType,
"url": types.StringType,
"ms_teams": types.BoolType,
"send_resolved": types.BoolType,
}

var routeDescriptions = map[string]string{
Expand Down Expand Up @@ -598,6 +604,10 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
Description: "The sender email address. Must be a valid email address",
Optional: true,
},
"send_resolved": schema.BoolAttribute{
Description: "Whether to notify about resolved alerts.",
Optional: true,
},
"smart_host": schema.StringAttribute{
Description: "The SMTP host through which emails are sent.",
Optional: true,
Expand Down Expand Up @@ -629,6 +639,10 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
Description: "Comma separated list of tags attached to the notifications.",
Optional: true,
},
"send_resolved": schema.BoolAttribute{
Description: "Whether to notify about resolved alerts.",
Optional: true,
},
},
},
},
Expand All @@ -648,6 +662,10 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
Description: "Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.",
Optional: true,
},
"send_resolved": schema.BoolAttribute{
Description: "Whether to notify about resolved alerts.",
Optional: true,
},
},
},
},
Expand Down Expand Up @@ -1503,6 +1521,7 @@ func getMockAlertConfig(ctx context.Context) (alertConfigModel, error) {
mockEmailConfig, diags := types.ObjectValue(emailConfigsTypes, map[string]attr.Value{
"to": types.StringValue("[email protected]"),
"smart_host": types.StringValue("smtp.gmail.com:587"),
"send_resolved": types.BoolValue(false),
"from": types.StringValue("[email protected]"),
"auth_username": types.StringValue("[email protected]"),
"auth_password": types.StringValue("xxxxxxxxx"),
Expand Down Expand Up @@ -1650,6 +1669,7 @@ func mapReceiversToAttributes(ctx context.Context, respReceivers *[]observabilit
"auth_password": types.StringPointerValue(emailConfig.AuthPassword),
"auth_username": types.StringPointerValue(emailConfig.AuthUsername),
"from": types.StringPointerValue(emailConfig.From),
"send_resolved": types.BoolPointerValue(emailConfig.SendResolved),
"smart_host": types.StringPointerValue(emailConfig.Smarthost),
"to": types.StringPointerValue(emailConfig.To),
}
Expand All @@ -1665,9 +1685,10 @@ func mapReceiversToAttributes(ctx context.Context, respReceivers *[]observabilit
if receiver.OpsgenieConfigs != nil {
for _, opsgenieConfig := range *receiver.OpsgenieConfigs {
opsGenieConfigMap := map[string]attr.Value{
"api_key": types.StringPointerValue(opsgenieConfig.ApiKey),
"api_url": types.StringPointerValue(opsgenieConfig.ApiUrl),
"tags": types.StringPointerValue(opsgenieConfig.Tags),
"api_key": types.StringPointerValue(opsgenieConfig.ApiKey),
"api_url": types.StringPointerValue(opsgenieConfig.ApiUrl),
"tags": types.StringPointerValue(opsgenieConfig.Tags),
"send_resolved": types.BoolPointerValue(opsgenieConfig.SendResolved),
}
opsGenieConfigModel, diags := types.ObjectValue(opsgenieConfigsTypes, opsGenieConfigMap)
if diags.HasError() {
Expand All @@ -1681,8 +1702,9 @@ func mapReceiversToAttributes(ctx context.Context, respReceivers *[]observabilit
if receiver.WebHookConfigs != nil {
for _, webhookConfig := range *receiver.WebHookConfigs {
webHookConfigsMap := map[string]attr.Value{
"url": types.StringPointerValue(webhookConfig.Url),
"ms_teams": types.BoolPointerValue(webhookConfig.MsTeams),
"url": types.StringPointerValue(webhookConfig.Url),
"ms_teams": types.BoolPointerValue(webhookConfig.MsTeams),
"send_resolved": types.BoolPointerValue(webhookConfig.SendResolved),
}
webHookConfigsModel, diags := types.ObjectValue(webHooksConfigsTypes, webHookConfigsMap)
if diags.HasError() {
Expand Down Expand Up @@ -1997,6 +2019,7 @@ func toReceiverPayload(ctx context.Context, model *alertConfigModel) (*[]observa
AuthPassword: conversion.StringValueToPointer(emailConfig.AuthPassword),
AuthUsername: conversion.StringValueToPointer(emailConfig.AuthUsername),
From: conversion.StringValueToPointer(emailConfig.From),
SendResolved: conversion.BoolValueToPointer(emailConfig.SendResolved),
Smarthost: conversion.StringValueToPointer(emailConfig.Smarthost),
To: conversion.StringValueToPointer(emailConfig.To),
})
Expand All @@ -2014,9 +2037,10 @@ func toReceiverPayload(ctx context.Context, model *alertConfigModel) (*[]observa
for i := range opsgenieConfigs {
opsgenieConfig := opsgenieConfigs[i]
payloadOpsGenieConfigs = append(payloadOpsGenieConfigs, observability.CreateAlertConfigReceiverPayloadOpsgenieConfigsInner{
ApiKey: conversion.StringValueToPointer(opsgenieConfig.ApiKey),
ApiUrl: conversion.StringValueToPointer(opsgenieConfig.ApiUrl),
Tags: conversion.StringValueToPointer(opsgenieConfig.Tags),
ApiKey: conversion.StringValueToPointer(opsgenieConfig.ApiKey),
ApiUrl: conversion.StringValueToPointer(opsgenieConfig.ApiUrl),
Tags: conversion.StringValueToPointer(opsgenieConfig.Tags),
SendResolved: conversion.BoolValueToPointer(opsgenieConfig.SendResolved),
})
}
receiverPayload.OpsgenieConfigs = &payloadOpsGenieConfigs
Expand All @@ -2032,8 +2056,9 @@ func toReceiverPayload(ctx context.Context, model *alertConfigModel) (*[]observa
for i := range receiverWebHooksConfigs {
webHooksConfig := receiverWebHooksConfigs[i]
payloadWebHooksConfigs = append(payloadWebHooksConfigs, observability.CreateAlertConfigReceiverPayloadWebHookConfigsInner{
Url: conversion.StringValueToPointer(webHooksConfig.Url),
MsTeams: conversion.BoolValueToPointer(webHooksConfig.MsTeams),
Url: conversion.StringValueToPointer(webHooksConfig.Url),
MsTeams: conversion.BoolValueToPointer(webHooksConfig.MsTeams),
SendResolved: conversion.BoolValueToPointer(webHooksConfig.SendResolved),
})
}
receiverPayload.WebHookConfigs = &payloadWebHooksConfigs
Expand Down
39 changes: 24 additions & 15 deletions stackit/internal/services/observability/instance/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func fixtureEmailConfigsModel() basetypes.ListValue {
"auth_password": types.StringValue("password"),
"auth_username": types.StringValue("username"),
"from": types.StringValue("[email protected]"),
"send_resolved": types.BoolValue(true),
"smart_host": types.StringValue("smtp.example.com"),
"to": types.StringValue("[email protected]"),
}),
Expand All @@ -33,18 +34,20 @@ func fixtureEmailConfigsModel() basetypes.ListValue {
func fixtureOpsGenieConfigsModel() basetypes.ListValue {
return types.ListValueMust(types.ObjectType{AttrTypes: opsgenieConfigsTypes}, []attr.Value{
types.ObjectValueMust(opsgenieConfigsTypes, map[string]attr.Value{
"api_key": types.StringValue("key"),
"tags": types.StringValue("tag"),
"api_url": types.StringValue("ops.example.com"),
"api_key": types.StringValue("key"),
"tags": types.StringValue("tag"),
"api_url": types.StringValue("ops.example.com"),
"send_resolved": types.BoolValue(true),
}),
})
}

func fixtureWebHooksConfigsModel() basetypes.ListValue {
return types.ListValueMust(types.ObjectType{AttrTypes: webHooksConfigsTypes}, []attr.Value{
types.ObjectValueMust(webHooksConfigsTypes, map[string]attr.Value{
"url": types.StringValue("http://example.com"),
"ms_teams": types.BoolValue(true),
"url": types.StringValue("http://example.com"),
"ms_teams": types.BoolValue(true),
"send_resolved": types.BoolValue(true),
}),
})
}
Expand Down Expand Up @@ -133,23 +136,26 @@ func fixtureEmailConfigsPayload() observability.CreateAlertConfigReceiverPayload
AuthPassword: utils.Ptr("password"),
AuthUsername: utils.Ptr("username"),
From: utils.Ptr("[email protected]"),
SendResolved: utils.Ptr(true),
Smarthost: utils.Ptr("smtp.example.com"),
To: utils.Ptr("[email protected]"),
}
}

func fixtureOpsGenieConfigsPayload() observability.CreateAlertConfigReceiverPayloadOpsgenieConfigsInner {
return observability.CreateAlertConfigReceiverPayloadOpsgenieConfigsInner{
ApiKey: utils.Ptr("key"),
Tags: utils.Ptr("tag"),
ApiUrl: utils.Ptr("ops.example.com"),
ApiKey: utils.Ptr("key"),
Tags: utils.Ptr("tag"),
ApiUrl: utils.Ptr("ops.example.com"),
SendResolved: utils.Ptr(true),
}
}

func fixtureWebHooksConfigsPayload() observability.CreateAlertConfigReceiverPayloadWebHookConfigsInner {
return observability.CreateAlertConfigReceiverPayloadWebHookConfigsInner{
Url: utils.Ptr("http://example.com"),
MsTeams: utils.Ptr(true),
Url: utils.Ptr("http://example.com"),
MsTeams: utils.Ptr(true),
SendResolved: utils.Ptr(true),
}
}

Expand Down Expand Up @@ -213,23 +219,26 @@ func fixtureEmailConfigsResponse() observability.EmailConfig {
AuthPassword: utils.Ptr("password"),
AuthUsername: utils.Ptr("username"),
From: utils.Ptr("[email protected]"),
SendResolved: utils.Ptr(true),
Smarthost: utils.Ptr("smtp.example.com"),
To: utils.Ptr("[email protected]"),
}
}

func fixtureOpsGenieConfigsResponse() observability.OpsgenieConfig {
return observability.OpsgenieConfig{
ApiKey: utils.Ptr("key"),
Tags: utils.Ptr("tag"),
ApiUrl: utils.Ptr("ops.example.com"),
ApiKey: utils.Ptr("key"),
Tags: utils.Ptr("tag"),
ApiUrl: utils.Ptr("ops.example.com"),
SendResolved: utils.Ptr(true),
}
}

func fixtureWebHooksConfigsResponse() observability.WebHook {
return observability.WebHook{
Url: utils.Ptr("http://example.com"),
MsTeams: utils.Ptr(true),
Url: utils.Ptr("http://example.com"),
MsTeams: utils.Ptr(true),
SendResolved: utils.Ptr(true),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,16 @@ var testConfigVarsMax = config.Variables{
"auth_password": config.StringVariable("password"),
"auth_username": config.StringVariable("username"),
"email_from": config.StringVariable("[email protected]"),
"email_send_resolved": config.StringVariable("true"),
"smart_host": config.StringVariable("smtp.gmail.com:587"),
"email_to": config.StringVariable("[email protected]"),
"opsgenie_api_key": config.StringVariable("example-api-key"),
"opsgenie_api_tags": config.StringVariable("observability-alert"),
"opsgenie_api_url": config.StringVariable("https://api.eu.opsgenie.com"),
"opsgenie_send_resolved": config.StringVariable("false"),
"webhook_configs_url": config.StringVariable("https://example.com"),
"ms_teams": config.StringVariable("true"),
"webhook_configs_send_resolved": config.StringVariable("false"),
"group_by": config.StringVariable("alertname"),
"group_interval": config.StringVariable("10m"),
"group_wait": config.StringVariable("1m"),
Expand Down
Loading
Loading