feat(observability): add google chat to webhooks (#961)
This commit is contained in:
parent
971cd27e4b
commit
0f8362ca74
9 changed files with 112 additions and 23 deletions
|
|
@ -96,7 +96,7 @@ Read-Only:
|
|||
Read-Only:
|
||||
|
||||
- `auth_identity` (String) SMTP authentication information. Must be a valid email address
|
||||
- `auth_password` (String) SMTP authentication password.
|
||||
- `auth_password` (String, Sensitive) SMTP authentication password.
|
||||
- `auth_username` (String) SMTP authentication username.
|
||||
- `from` (String) The sender email address. Must be a valid email address
|
||||
- `smart_host` (String) The SMTP host through which emails are sent.
|
||||
|
|
@ -119,8 +119,9 @@ Read-Only:
|
|||
|
||||
Read-Only:
|
||||
|
||||
- `google_chat` (Boolean) Google Chat webhooks require special handling, set this to true if the webhook is for Google Chat.
|
||||
- `ms_teams` (Boolean) Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.
|
||||
- `url` (String) The endpoint to send HTTP POST requests to. Must be a valid URL
|
||||
- `url` (String, Sensitive) The endpoint to send HTTP POST requests to. Must be a valid URL
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ Optional:
|
|||
Optional:
|
||||
|
||||
- `auth_identity` (String) SMTP authentication information. Must be a valid email address
|
||||
- `auth_password` (String) SMTP authentication password.
|
||||
- `auth_password` (String, Sensitive) SMTP authentication password.
|
||||
- `auth_username` (String) SMTP authentication username.
|
||||
- `from` (String) The sender email address. Must be a valid email address
|
||||
- `smart_host` (String) The SMTP host through which emails are sent.
|
||||
|
|
@ -124,8 +124,9 @@ Optional:
|
|||
|
||||
Optional:
|
||||
|
||||
- `google_chat` (Boolean) Google Chat webhooks require special handling, set this to true if the webhook is for Google Chat.
|
||||
- `ms_teams` (Boolean) Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.
|
||||
- `url` (String) The endpoint to send HTTP POST requests to. Must be a valid URL
|
||||
- `url` (String, Sensitive) The endpoint to send HTTP POST requests to. Must be a valid URL
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/stackitcloud/stackit-sdk-go/services/modelserving v0.5.1
|
||||
github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2
|
||||
github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1
|
||||
github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0
|
||||
github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.0
|
||||
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1
|
||||
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1
|
||||
github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -176,8 +176,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a
|
|||
github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0 h1:SIctDqGprEoZArWaTds7hzQyh8Pqaz95Nmuj/1QuDEQ=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.0 h1:5BhZ/Ry3KWmhjBTVFBdLfVjPxxUOvVJuhGY0bnGRS7I=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc=
|
||||
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI=
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ func (d *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
|
|||
"auth_password": schema.StringAttribute{
|
||||
Description: "SMTP authentication password.",
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"auth_username": schema.StringAttribute{
|
||||
Description: "SMTP authentication username.",
|
||||
|
|
@ -262,11 +263,16 @@ func (d *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
|
|||
"url": schema.StringAttribute{
|
||||
Description: "The endpoint to send HTTP POST requests to. Must be a valid URL",
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"ms_teams": schema.BoolAttribute{
|
||||
Description: "Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.",
|
||||
Computed: true,
|
||||
},
|
||||
"google_chat": schema.BoolAttribute{
|
||||
Description: "Google Chat webhooks require special handling, set this to true if the webhook is for Google Chat.",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
|
|
@ -202,13 +203,15 @@ var opsgenieConfigsTypes = map[string]attr.Type{
|
|||
|
||||
// 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"`
|
||||
GoogleChat types.Bool `tfsdk:"google_chat"`
|
||||
}
|
||||
|
||||
var webHooksConfigsTypes = map[string]attr.Type{
|
||||
"url": types.StringType,
|
||||
"ms_teams": types.BoolType,
|
||||
"url": types.StringType,
|
||||
"ms_teams": types.BoolType,
|
||||
"google_chat": types.BoolType,
|
||||
}
|
||||
|
||||
var routeDescriptions = map[string]string{
|
||||
|
|
@ -591,6 +594,7 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
|
|||
"auth_password": schema.StringAttribute{
|
||||
Description: "SMTP authentication password.",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"auth_username": schema.StringAttribute{
|
||||
Description: "SMTP authentication username.",
|
||||
|
|
@ -645,14 +649,26 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
|
|||
listvalidator.SizeAtLeast(1),
|
||||
},
|
||||
NestedObject: schema.NestedAttributeObject{
|
||||
Validators: []validator.Object{
|
||||
WebhookConfigMutuallyExclusive(),
|
||||
},
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"url": schema.StringAttribute{
|
||||
Description: "The endpoint to send HTTP POST requests to. Must be a valid URL",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"ms_teams": schema.BoolAttribute{
|
||||
Description: "Microsoft Teams webhooks require special handling, set this to true if the webhook is for Microsoft Teams.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(false),
|
||||
},
|
||||
"google_chat": schema.BoolAttribute{
|
||||
Description: "Google Chat webhooks require special handling, set this to true if the webhook is for Google Chat.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -1687,9 +1703,13 @@ func mapReceiversToAttributes(ctx context.Context, respReceivers *[]observabilit
|
|||
webhooksConfigList := []attr.Value{}
|
||||
if receiver.WebHookConfigs != nil {
|
||||
for _, webhookConfig := range *receiver.WebHookConfigs {
|
||||
msTeamsValue := types.BoolPointerValue(webhookConfig.MsTeams)
|
||||
googleChatValue := types.BoolPointerValue(webhookConfig.GoogleChat)
|
||||
|
||||
webHookConfigsMap := map[string]attr.Value{
|
||||
"url": types.StringPointerValue(webhookConfig.Url),
|
||||
"ms_teams": types.BoolPointerValue(webhookConfig.MsTeams),
|
||||
"url": types.StringPointerValue(webhookConfig.Url),
|
||||
"ms_teams": msTeamsValue,
|
||||
"google_chat": googleChatValue,
|
||||
}
|
||||
webHookConfigsModel, diags := types.ObjectValue(webHooksConfigsTypes, webHookConfigsMap)
|
||||
if diags.HasError() {
|
||||
|
|
@ -2040,8 +2060,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),
|
||||
GoogleChat: conversion.BoolValueToPointer(webHooksConfig.GoogleChat),
|
||||
})
|
||||
}
|
||||
receiverPayload.WebHookConfigs = &payloadWebHooksConfigs
|
||||
|
|
@ -2214,3 +2235,51 @@ func setMetricsRetentions(ctx context.Context, state *tfsdk.State, model *Model)
|
|||
func setAlertConfig(ctx context.Context, state *tfsdk.State, model *Model) diag.Diagnostics {
|
||||
return state.SetAttribute(ctx, path.Root("alert_config"), model.AlertConfig)
|
||||
}
|
||||
|
||||
type webhookConfigMutuallyExclusive struct{}
|
||||
|
||||
func (v webhookConfigMutuallyExclusive) Description(_ context.Context) string {
|
||||
return "ms_teams and google_chat cannot both be true"
|
||||
}
|
||||
|
||||
func (v webhookConfigMutuallyExclusive) MarkdownDescription(ctx context.Context) string {
|
||||
return v.Description(ctx)
|
||||
}
|
||||
|
||||
func (v webhookConfigMutuallyExclusive) ValidateObject(_ context.Context, req validator.ObjectRequest, resp *validator.ObjectResponse) { //nolint:gocritic // req parameter signature required by validator.Object interface
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
attributes := req.ConfigValue.Attributes()
|
||||
|
||||
msTeamsAttr, msTeamsExists := attributes["ms_teams"]
|
||||
googleChatAttr, googleChatExists := attributes["google_chat"]
|
||||
|
||||
if !msTeamsExists || !googleChatExists {
|
||||
return
|
||||
}
|
||||
|
||||
if msTeamsAttr.IsNull() || msTeamsAttr.IsUnknown() || googleChatAttr.IsNull() || googleChatAttr.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
msTeamsValue, ok1 := msTeamsAttr.(types.Bool)
|
||||
googleChatValue, ok2 := googleChatAttr.(types.Bool)
|
||||
|
||||
if !ok1 || !ok2 {
|
||||
return
|
||||
}
|
||||
|
||||
if msTeamsValue.ValueBool() && googleChatValue.ValueBool() {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
req.Path,
|
||||
"Invalid Webhook Configuration",
|
||||
"Both ms_teams and google_chat cannot be set to true at the same time. Only one can be true.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func WebhookConfigMutuallyExclusive() validator.Object {
|
||||
return webhookConfigMutuallyExclusive{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,9 @@ func fixtureOpsGenieConfigsModel() basetypes.ListValue {
|
|||
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),
|
||||
"google_chat": types.BoolValue(true),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
|
@ -150,8 +151,9 @@ func fixtureOpsGenieConfigsPayload() observability.CreateAlertConfigReceiverPayl
|
|||
|
||||
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),
|
||||
GoogleChat: utils.Ptr(true),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,8 +233,9 @@ func fixtureOpsGenieConfigsResponse() observability.OpsgenieConfig {
|
|||
|
||||
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),
|
||||
GoogleChat: utils.Ptr(true),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ var testConfigVarsMax = config.Variables{
|
|||
"opsgenie_priority": config.StringVariable("P3"),
|
||||
"webhook_configs_url": config.StringVariable("https://example.com"),
|
||||
"ms_teams": config.StringVariable("true"),
|
||||
"google_chat": config.StringVariable("false"),
|
||||
"group_by": config.StringVariable("alertname"),
|
||||
"group_interval": config.StringVariable("10m"),
|
||||
"group_wait": config.StringVariable("1m"),
|
||||
|
|
@ -130,6 +131,9 @@ func configVarsMaxUpdated() config.Variables {
|
|||
tempConfig["alert_rule_expression"] = config.StringVariable(alert_rule_expression_updated)
|
||||
tempConfig["logalertgroup_interval"] = config.StringVariable("1h")
|
||||
tempConfig["logalertgroup_expression"] = config.StringVariable(logalertgroup_expression_updated)
|
||||
tempConfig["webhook_configs_url"] = config.StringVariable("https://chat.googleapis.com/api")
|
||||
tempConfig["ms_teams"] = config.StringVariable("false")
|
||||
tempConfig["google_chat"] = config.StringVariable("true")
|
||||
return tempConfig
|
||||
}
|
||||
|
||||
|
|
@ -510,6 +514,7 @@ func TestAccResourceMax(t *testing.T) {
|
|||
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.url", testutil.ConvertConfigVariable(testConfigVarsMax["webhook_configs_url"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.ms_teams", testutil.ConvertConfigVariable(testConfigVarsMax["ms_teams"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.google_chat", testutil.ConvertConfigVariable(testConfigVarsMax["google_chat"])),
|
||||
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.route.group_by.0", testutil.ConvertConfigVariable(testConfigVarsMax["group_by"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.route.group_interval", testutil.ConvertConfigVariable(testConfigVarsMax["group_interval"])),
|
||||
|
|
@ -672,6 +677,7 @@ func TestAccResourceMax(t *testing.T) {
|
|||
|
||||
resource.TestCheckResourceAttr("data.stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.url", testutil.ConvertConfigVariable(testConfigVarsMax["webhook_configs_url"])),
|
||||
resource.TestCheckResourceAttr("data.stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.ms_teams", testutil.ConvertConfigVariable(testConfigVarsMax["ms_teams"])),
|
||||
resource.TestCheckResourceAttr("data.stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.google_chat", testutil.ConvertConfigVariable(testConfigVarsMax["google_chat"])),
|
||||
|
||||
resource.TestCheckResourceAttr("data.stackit_observability_instance.instance", "alert_config.route.group_by.0", testutil.ConvertConfigVariable(testConfigVarsMax["group_by"])),
|
||||
resource.TestCheckResourceAttr("data.stackit_observability_instance.instance", "alert_config.route.group_interval", testutil.ConvertConfigVariable(testConfigVarsMax["group_interval"])),
|
||||
|
|
@ -893,8 +899,9 @@ func TestAccResourceMax(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.opsgenie_configs.0.api_url", testutil.ConvertConfigVariable(testConfigVarsMax["opsgenie_api_url"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.opsgenie_configs.0.priority", testutil.ConvertConfigVariable(testConfigVarsMax["opsgenie_priority"])),
|
||||
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.url", testutil.ConvertConfigVariable(testConfigVarsMax["webhook_configs_url"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.ms_teams", testutil.ConvertConfigVariable(testConfigVarsMax["ms_teams"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.url", testutil.ConvertConfigVariable(configVarsMaxUpdated()["webhook_configs_url"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.ms_teams", testutil.ConvertConfigVariable(configVarsMaxUpdated()["ms_teams"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.receivers.0.webhooks_configs.0.google_chat", testutil.ConvertConfigVariable(configVarsMaxUpdated()["google_chat"])),
|
||||
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.route.group_by.0", testutil.ConvertConfigVariable(testConfigVarsMax["group_by"])),
|
||||
resource.TestCheckResourceAttr("stackit_observability_instance.instance", "alert_config.route.group_interval", testutil.ConvertConfigVariable(testConfigVarsMax["group_interval"])),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ variable "opsgenie_api_url" {}
|
|||
variable "opsgenie_priority" {}
|
||||
variable "webhook_configs_url" {}
|
||||
variable "ms_teams" {}
|
||||
variable "google_chat" {}
|
||||
variable "group_by" {}
|
||||
variable "group_interval" {}
|
||||
variable "group_wait" {}
|
||||
|
|
@ -125,6 +126,7 @@ resource "stackit_observability_instance" "instance" {
|
|||
{
|
||||
url = var.webhook_configs_url
|
||||
ms_teams = var.ms_teams
|
||||
google_chat = var.google_chat
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue