Skip to content
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

Threshold alerts #49

Merged
merged 5 commits into from
Jul 3, 2019
Merged
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
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ Once you have the plugin you should remove the `_os_arch` from the end of the fi

Valid provider filenames are `terraform-provider-NAME_X.X.X` or `terraform-provider-NAME_vX.X.X`

## Known Issues

To ensure that applies of large batches of Alerts are successful you can use the `-parallelism` flag to prevent parallel resource creations
`terraform apply -parallelism=1`

## Building and Testing

### Build the plugin.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ module github.com/spaceapegames/terraform-provider-wavefront
require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/terraform v0.12.0
github.com/spaceapegames/go-wavefront v0.0.0-20190424105721-72e8eb185145
github.com/spaceapegames/go-wavefront v1.6.2
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,12 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaceapegames/go-wavefront v0.0.0-20190424105721-72e8eb185145 h1:iN5Rc2gJLJFZ3Io4n5qxwe6uVKyHRfTGWc0yTauAH60=
github.com/spaceapegames/go-wavefront v0.0.0-20190424105721-72e8eb185145/go.mod h1:Q9wbY/SM99cOM4NvoJ2SN1bzcJUJOEzta5C7dhnT5IM=
github.com/spaceapegames/go-wavefront v0.0.0-20190627103934-9f0b48af3f8f h1:EG1F9wt5cMZ9az8TDMlMRD08HP8zdjn8f3fmsVBBhf4=
github.com/spaceapegames/go-wavefront v0.0.0-20190627103934-9f0b48af3f8f/go.mod h1:Q9wbY/SM99cOM4NvoJ2SN1bzcJUJOEzta5C7dhnT5IM=
github.com/spaceapegames/go-wavefront v1.6.1 h1:5ZezLy0NiiOFDhrgJA01c5/vZZbFcj2IL2ymdRXJzT8=
github.com/spaceapegames/go-wavefront v1.6.1/go.mod h1:Q9wbY/SM99cOM4NvoJ2SN1bzcJUJOEzta5C7dhnT5IM=
github.com/spaceapegames/go-wavefront v1.6.2 h1:5AHElze/Y6oi4DdpkYfksS4F0ItsBpV7WwuB3r159cY=
github.com/spaceapegames/go-wavefront v1.6.2/go.mod h1:Q9wbY/SM99cOM4NvoJ2SN1bzcJUJOEzta5C7dhnT5IM=
github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M=
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
Expand Down
34 changes: 31 additions & 3 deletions vendor/github.com/spaceapegames/go-wavefront/alert.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/github.com/spaceapegames/go-wavefront/event.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/github.com/spaceapegames/go-wavefront/target.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/github.com/spaceapegames/go-wavefront/version

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ github.com/posener/complete
github.com/posener/complete/cmd/install
github.com/posener/complete/cmd
github.com/posener/complete/match
# github.com/spaceapegames/go-wavefront v0.0.0-20190424105721-72e8eb185145
# github.com/spaceapegames/go-wavefront v1.6.2
github.com/spaceapegames/go-wavefront
# github.com/spf13/afero v1.2.1
github.com/spf13/afero
Expand Down
104 changes: 93 additions & 11 deletions wavefront/resource_alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,28 @@ func resourceAlert() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"alert_type": {
Type: schema.TypeString,
Optional: true,
Default: wavefront.AlertTypeClassic,
},
"target": {
Type: schema.TypeString,
Required: true,
Optional: true,
},
"condition": {
Type: schema.TypeString,
Required: true,
Optional: true,
StateFunc: trimSpaces,
},
"threshold_conditions": {
Type: schema.TypeMap,
Optional: true,
},
"threshold_targets": {
Type: schema.TypeMap,
Optional: true,
},
"additional_information": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -56,7 +69,7 @@ func resourceAlert() *schema.Resource {
},
"severity": {
Type: schema.TypeString,
Required: true,
Optional: true,
},
"tags": {
Type: schema.TypeSet,
Expand All @@ -71,6 +84,14 @@ func trimSpaces(d interface{}) string {
return strings.TrimSpace(d.(string))
}

func trimSpacesMap(m map[string]interface{}) map[string]string {
trimmed := map[string]string{}
for key, v := range m {
trimmed[key] = trimSpaces(v)
}
return trimmed
}

func resourceAlertCreate(d *schema.ResourceData, m interface{}) error {
alerts := m.(*wavefrontClient).client.Alerts()

Expand All @@ -81,19 +102,21 @@ func resourceAlertCreate(d *schema.ResourceData, m interface{}) error {

a := &wavefront.Alert{
Name: d.Get("name").(string),
Target: d.Get("target").(string),
Condition: trimSpaces(d.Get("condition").(string)),
AdditionalInfo: trimSpaces(d.Get("additional_information").(string)),
DisplayExpression: trimSpaces(d.Get("display_expression").(string)),
Minutes: d.Get("minutes").(int),
ResolveAfterMinutes: d.Get("resolve_after_minutes").(int),
NotificationResendFrequencyMinutes: d.Get("notification_resend_frequency_minutes").(int),
Severity: d.Get("severity").(string),
Tags: tags,
Tags: tags,
}

err := validateAlertConditions(a, d)
if err != nil {
return err
}

// Create the alert on Wavefront
err := alerts.Create(a)
err = alerts.Create(a)
if err != nil {
return fmt.Errorf("error creating Alert %s. %s", d.Get("name"), err)
}
Expand Down Expand Up @@ -129,6 +152,9 @@ func resourceAlertRead(d *schema.ResourceData, m interface{}) error {
d.Set("notification_resend_frequency_minutes", tmpAlert.NotificationResendFrequencyMinutes)
d.Set("severity", tmpAlert.Severity)
d.Set("tags", tmpAlert.Tags)
d.Set("alert_type", tmpAlert.AlertType)
d.Set("threshold_conditions", tmpAlert.Conditions)
d.Set("threshold_targets", tmpAlert.Targets)

return nil
}
Expand All @@ -151,16 +177,18 @@ func resourceAlertUpdate(d *schema.ResourceData, m interface{}) error {

a := tmpAlert
a.Name = d.Get("name").(string)
a.Target = d.Get("target").(string)
a.Condition = trimSpaces(d.Get("condition").(string))
a.AdditionalInfo = trimSpaces(d.Get("additional_information").(string))
a.DisplayExpression = trimSpaces(d.Get("display_expression").(string))
a.Minutes = d.Get("minutes").(int)
a.ResolveAfterMinutes = d.Get("resolve_after_minutes").(int)
a.NotificationResendFrequencyMinutes = d.Get("notification_resend_frequency_minutes").(int)
a.Severity = d.Get("severity").(string)
a.Tags = tags

err = validateAlertConditions(&a, d)
if err != nil {
return err
}

// Update the alert on Wavefront
err = alerts.Update(&a)
if err != nil {
Expand Down Expand Up @@ -188,3 +216,57 @@ func resourceAlertDelete(d *schema.ResourceData, m interface{}) error {
d.SetId("")
return nil
}

func validateAlertConditions(a *wavefront.Alert, d *schema.ResourceData) error {
if d.Get("alert_type") == wavefront.AlertTypeThreshold {
a.AlertType = wavefront.AlertTypeThreshold
if conditions, ok := d.GetOk("threshold_conditions"); ok {
a.Conditions = trimSpacesMap(conditions.(map[string]interface{}))
err := validateThresholdLevels(a.Conditions)
if err != nil {
return err
}
} else {
return fmt.Errorf("threshold_conditions must be supplied for threshold alerts")
}

if targets, ok := d.GetOk("threshold_targets"); ok {
a.Targets = trimSpacesMap(targets.(map[string]interface{}))
return validateThresholdLevels(a.Targets)
}

} else if d.Get("alert_type") == wavefront.AlertTypeClassic {
a.AlertType = wavefront.AlertTypeClassic

if d.Get("condition") == "" {
return fmt.Errorf("condition must be supplied for classic alerts")
}
a.Condition = trimSpaces(d.Get("condition").(string))

if d.Get("severity") == "" {
return fmt.Errorf("severity must be supplied for classic alerts")
}
a.Severity = d.Get("severity").(string)
a.Target = d.Get("target").(string)
} else {
return fmt.Errorf("alert_type must be CLASSIC or THRESHOLD")
}

return nil
}

func validateThresholdLevels(m map[string]string) error {
for key := range m {
ok := false
for _, level := range []string{"severe", "warn", "info", "smoke"} {
if key == level {
ok = true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should break here when setting ok to true

break
}
}
if !ok {
return fmt.Errorf("invalid severity: %s", key)
}
}
return nil
}
Loading