Skip to content

Commit

Permalink
feat(monitor): add resource to manage Inhibition rules (#535)
Browse files Browse the repository at this point in the history
* feat(monitor): add resource to manage inhibition rules

* feat(monitor): add labels attribute to alerts
  • Loading branch information
dbonf authored Aug 5, 2024
1 parent e5fa378 commit daf27af
Show file tree
Hide file tree
Showing 18 changed files with 747 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*monitor*providers* @jwsarna1
*monitor*groupmapping* @shadow649
*notification_channel* @michelevergnano @dkutsanov @antonio-cuomo @dbonf
*inhibition_rule* @michelevergnano @dkutsanov @antonio-cuomo @dbonf
*silence_rule* @michelevergnano @dkutsanov @antonio-cuomo @dbonf

# policies/rules
*secure*policy* @kmvachhani @rosenbloomb-sysdig @ombellare @miguelgordo @ivanlysiuk-sysdig @daniel-almeida @jbainbridgesysdig @IvanNik @hila1608 @yaminSapir @chen-shmilovich-sysdig @zohar-arad
Expand Down
3 changes: 2 additions & 1 deletion sysdig/internal/client/v2/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type MonitorCommon interface {
AlertV2Interface
DashboardInterface
SilenceRuleInterface
InhibitionRuleInterface
}

type SecureCommon interface {
Expand All @@ -75,7 +76,7 @@ func (client *Client) ErrorFromResponse(response *http.Response) error {
return errors.New(response.Status)
}

search, err := jmespath.Search("[message, error, errors[].[reason, message]][][] | join(', ', @)", data)
search, err := jmespath.Search("[message, error, details[], errors[].[reason, message]][][] | join(', ', @)", data)
if err != nil {
return errors.New(response.Status)
}
Expand Down
105 changes: 105 additions & 0 deletions sysdig/internal/client/v2/inhibition_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package v2

import (
"context"
"errors"
"fmt"
"net/http"
)

const (
inhibitionRulesPath = "%s/monitor/alerts/v1/inhibition-rules"
inhibitionRulePath = "%s/monitor/alerts/v1/inhibition-rules/%d"
)

var ErrInhibitionRuleNotFound = errors.New("inhibition rule not found")

type InhibitionRuleInterface interface {
Base
GetInhibitionRule(ctx context.Context, id int) (InhibitionRule, error)
CreateInhibitionRule(ctx context.Context, inhibitionRule InhibitionRule) (InhibitionRule, error)
UpdateInhibitionRule(ctx context.Context, inhibitionRule InhibitionRule) (InhibitionRule, error)
DeleteInhibitionRule(ctx context.Context, id int) error
}

func (client *Client) GetInhibitionRule(ctx context.Context, id int) (InhibitionRule, error) {
response, err := client.requester.Request(ctx, http.MethodGet, client.getInhibitionRuleURL(id), nil)
if err != nil {
return InhibitionRule{}, err
}
defer response.Body.Close()

if response.StatusCode == http.StatusNotFound {
return InhibitionRule{}, ErrInhibitionRuleNotFound
}
if response.StatusCode != http.StatusOK {
return InhibitionRule{}, client.ErrorFromResponse(response)
}

inhibitionRule, err := Unmarshal[InhibitionRule](response.Body)
if err != nil {
return InhibitionRule{}, err
}

return inhibitionRule, nil
}

func (client *Client) CreateInhibitionRule(ctx context.Context, inhibitionRule InhibitionRule) (InhibitionRule, error) {
payload, err := Marshal(inhibitionRule)
if err != nil {
return InhibitionRule{}, err
}

response, err := client.requester.Request(ctx, http.MethodPost, client.getInhibitionRulesURL(), payload)
if err != nil {
return InhibitionRule{}, err
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
return InhibitionRule{}, client.ErrorFromResponse(response)
}

return Unmarshal[InhibitionRule](response.Body)
}

func (client *Client) UpdateInhibitionRule(ctx context.Context, inhibitionRule InhibitionRule) (InhibitionRule, error) {
payload, err := Marshal(inhibitionRule)
if err != nil {
return InhibitionRule{}, err
}

response, err := client.requester.Request(ctx, http.MethodPut, client.getInhibitionRuleURL(inhibitionRule.ID), payload)
if err != nil {
return InhibitionRule{}, err
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return InhibitionRule{}, client.ErrorFromResponse(response)
}

return Unmarshal[InhibitionRule](response.Body)
}

func (client *Client) DeleteInhibitionRule(ctx context.Context, id int) error {
response, err := client.requester.Request(ctx, http.MethodDelete, client.getInhibitionRuleURL(id), nil)
if err != nil {
return err
}
defer response.Body.Close()

if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound {
return client.ErrorFromResponse(response)
}

return nil
}

func (client *Client) getInhibitionRulesURL() string {
return fmt.Sprintf(inhibitionRulesPath, client.config.url)
}

func (client *Client) getInhibitionRuleURL(id int) string {
return fmt.Sprintf(inhibitionRulePath, client.config.url, id)
}
19 changes: 19 additions & 0 deletions sysdig/internal/client/v2/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ type AlertV2Common struct {
CustomNotificationTemplate *CustomNotificationTemplateV2 `json:"customNotificationTemplate,omitempty"`
CaptureConfig *CaptureConfigV2 `json:"captureConfig,omitempty"`
Links []AlertLinkV2 `json:"links"`
Labels map[string]interface{} `json:"labels,omitempty"`
}

type AlertV2ConfigPrometheus struct {
Expand Down Expand Up @@ -1088,6 +1089,24 @@ type SilenceRule struct {
ID int `json:"id,omitempty"`
}

type InhibitionRule struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Enabled bool `json:"isEnabled"`
SourceMatchers []LabelMatchers `json:"sourceMatchers"`
TargetMatchers []LabelMatchers `json:"targetMatchers"`
Equal []string `json:"equal,omitempty"`

Version int `json:"version,omitempty"`
ID int `json:"id,omitempty"`
}

type LabelMatchers struct {
LabelName string `json:"labelName"`
Operator string `json:"operator"`
Value string `json:"value"`
}

type AgentAccessKey struct {
ID int `json:"id,omitempty"`
Reservation int `json:"agentReservation,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions sysdig/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func (p *SysdigProvider) Provider() *schema.Provider {
"sysdig_secure_cloud_auth_account_feature": resourceSysdigSecureCloudauthAccountFeature(),

"sysdig_monitor_silence_rule": resourceSysdigMonitorSilenceRule(),
"sysdig_monitor_inhibition_rule": resourceSysdigMonitorInhibitionRule(),
"sysdig_monitor_alert_downtime": resourceSysdigMonitorAlertDowntime(),
"sysdig_monitor_alert_metric": resourceSysdigMonitorAlertMetric(),
"sysdig_monitor_alert_event": resourceSysdigMonitorAlertEvent(),
Expand Down
8 changes: 8 additions & 0 deletions sysdig/resource_sysdig_monitor_alert_v2_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ func createAlertV2Schema(original map[string]*schema.Schema) map[string]*schema.
},
},
},
"labels": {
Type: schema.TypeMap,
Optional: true,
},
}

for k, v := range original {
Expand Down Expand Up @@ -307,6 +311,8 @@ func buildAlertV2CommonStruct(d *schema.ResourceData) *v2.AlertV2Common {
}
}

alert.Labels = d.Get("labels").(map[string]interface{})

return alert
}

Expand Down Expand Up @@ -395,6 +401,8 @@ func updateAlertV2CommonState(d *schema.ResourceData, alert *v2.AlertV2Common) (
_ = d.Set("link", links)
}

_ = d.Set("labels", alert.Labels)

return nil
}

Expand Down
23 changes: 23 additions & 0 deletions sysdig/resource_sysdig_monitor_alert_v2_metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ func TestAccAlertV2Metric(t *testing.T) {
{
Config: alertV2MetricWithUnreportedAlertNotificationsRetentionSec(rText()),
},
{
Config: alertV2MetricWithLabels(rText()),
},
{
Config: alertV2MetricWithWarningThreshold(rText()),
},
Expand Down Expand Up @@ -383,6 +386,26 @@ resource "sysdig_monitor_alert_v2_metric" "sample" {
`, name)
}

func alertV2MetricWithLabels(name string) string {
return fmt.Sprintf(`
resource "sysdig_monitor_alert_v2_metric" "sample" {
name = "TERRAFORM TEST - METRICV2 %s"
metric = "sysdig_container_cpu_used_percent"
group_aggregation = "avg"
time_aggregation = "avg"
operator = ">="
threshold = 50
trigger_after_minutes = 15
labels = {
application = "app1"
maturity = "high"
}
}
`, name)
}

func alertV2MetricWithWarningThreshold(name string) string {
return fmt.Sprintf(`
resource "sysdig_monitor_notification_channel_email" "nc_email1" {
Expand Down
Loading

0 comments on commit daf27af

Please sign in to comment.