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

feat(pkger): add export support for notification rules #16312

Merged
merged 1 commit into from
Dec 21, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
1. [16297](https://github.com/influxdata/influxdb/pull/16297): Add support for notification rule to pkger parser
1. [16298](https://github.com/influxdata/influxdb/pull/16298): Add support for notification rule pkger dry run functionality
1. [16305](https://github.com/influxdata/influxdb/pull/16305): Add support for notification rule pkger apply functionality
1. [16312](https://github.com/influxdata/influxdb/pull/16312): Add support for notification rule pkger export functionality

### Bug Fixes

Expand Down
5 changes: 4 additions & 1 deletion cmd/influx/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type cmdPkgBuilder struct {
dashboards string
endpoints string
labels string
rules string
telegrafs string
variables string
}
Expand Down Expand Up @@ -229,6 +230,7 @@ func (b *cmdPkgBuilder) cmdPkgExport() *cobra.Command {
cmd.Flags().StringVar(&b.exportOpts.dashboards, "dashboards", "", "List of dashboard ids comma separated")
cmd.Flags().StringVar(&b.exportOpts.endpoints, "endpoints", "", "List of notification endpoint ids comma separated")
cmd.Flags().StringVar(&b.exportOpts.labels, "labels", "", "List of label ids comma separated")
cmd.Flags().StringVar(&b.exportOpts.rules, "rules", "", "List of notification rule ids comma separated")
cmd.Flags().StringVar(&b.exportOpts.telegrafs, "telegraf-configs", "", "List of telegraf config ids comma separated")
cmd.Flags().StringVar(&b.exportOpts.variables, "variables", "", "List of variable ids comma separated")

Expand All @@ -253,8 +255,9 @@ func (b *cmdPkgBuilder) pkgExportRunEFn() func(*cobra.Command, []string) error {
{kind: pkger.KindBucket, idStrs: strings.Split(b.exportOpts.buckets, ",")},
{kind: pkger.KindCheck, idStrs: strings.Split(b.exportOpts.checks, ",")},
{kind: pkger.KindDashboard, idStrs: strings.Split(b.exportOpts.dashboards, ",")},
{kind: pkger.KindNotificationEndpoint, idStrs: strings.Split(b.exportOpts.endpoints, ",")},
{kind: pkger.KindLabel, idStrs: strings.Split(b.exportOpts.labels, ",")},
{kind: pkger.KindNotificationEndpoint, idStrs: strings.Split(b.exportOpts.endpoints, ",")},
{kind: pkger.KindNotificationRule, idStrs: strings.Split(b.exportOpts.rules, ",")},
{kind: pkger.KindTelegraf, idStrs: strings.Split(b.exportOpts.telegrafs, ",")},
{kind: pkger.KindVariable, idStrs: strings.Split(b.exportOpts.variables, ",")},
}
Expand Down
22 changes: 22 additions & 0 deletions cmd/influxd/launcher/pkger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,11 @@ spec:
}

resWithNewName := []pkger.ResourceToClone{
{
Kind: pkger.KindNotificationRule,
Name: "new rule name",
ID: influxdb.ID(rule.ID),
},
{
Kind: pkger.KindVariable,
Name: "new name",
Expand Down Expand Up @@ -457,6 +462,13 @@ spec:
assert.Equal(t, endpoints[0].NotificationEndpoint.GetDescription(), newEndpoints[0].NotificationEndpoint.GetDescription())
hasLabelAssociations(t, newEndpoints[0].LabelAssociations, 1, "label_1")

require.Len(t, newSum.NotificationRules, 1)
newRule := newSum.NotificationRules[0]
assert.Equal(t, "new rule name", newRule.Name)
assert.Zero(t, newRule.EndpointID)
assert.Equal(t, rule.EndpointName, newRule.EndpointName)
hasLabelAssociations(t, newRule.LabelAssociations, 1, "label_1")

require.Len(t, newSum.TelegrafConfigs, 1)
assert.Equal(t, teles[0].TelegrafConfig.Name, newSum.TelegrafConfigs[0].TelegrafConfig.Name)
assert.Equal(t, teles[0].TelegrafConfig.Description, newSum.TelegrafConfigs[0].TelegrafConfig.Description)
Expand Down Expand Up @@ -636,6 +648,16 @@ spec:
level: INfO
min: 30.0
max: 45.0
- type: outside_range
level: WARN
min: 60.0
max: 70.0
- type: greater
level: CRIT
val: 80
- type: lesser
level: OK
val: 30
associations:
- kind: Label
name: label_1
Expand Down
1 change: 1 addition & 0 deletions http/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7156,6 +7156,7 @@ components:
- dashboard
- label
- notification_endpoint
- notification_rule
- telegraf
- variable
name:
Expand Down
112 changes: 95 additions & 17 deletions pkger/clone_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/influxdata/influxdb/notification"
icheck "github.com/influxdata/influxdb/notification/check"
"github.com/influxdata/influxdb/notification/endpoint"
"github.com/influxdata/influxdb/notification/rule"
)

// ResourceToClone is a resource that will be cloned.
Expand Down Expand Up @@ -79,18 +80,14 @@ func checkToResource(ch influxdb.Check, name string) Resource {
}
assignNonZeroStrings(r, map[string]string{fieldDescription: ch.GetDescription()})

assignFluxDur := func(field string, dur *notification.Duration) {
if dur == nil {
return
}
r[field] = dur.TimeDuration().String()
}

assignBase := func(base icheck.Base) {
r[fieldQuery] = base.Query.Text
r[fieldCheckStatusMessageTemplate] = base.StatusMessageTemplate
assignFluxDur(fieldEvery, base.Every)
assignFluxDur(fieldOffset, base.Offset)
assignNonZeroFluxDurs(r, map[string]*notification.Duration{
fieldEvery: base.Every,
fieldOffset: base.Offset,
})

var tags []Resource
for _, t := range base.Tags {
if t.Valid() != nil {
Expand All @@ -110,8 +107,10 @@ func checkToResource(ch influxdb.Check, name string) Resource {
case *icheck.Deadman:
r[fieldKind] = KindCheckDeadman.title()
assignBase(cT.Base)
assignFluxDur(fieldCheckTimeSince, cT.TimeSince)
assignFluxDur(fieldCheckStaleTime, cT.StaleTime)
assignNonZeroFluxDurs(r, map[string]*notification.Duration{
fieldCheckTimeSince: cT.TimeSince,
fieldCheckStaleTime: cT.StaleTime,
})
r[fieldLevel] = cT.Level.String()
assignNonZeroBools(r, map[string]bool{fieldCheckReportZero: cT.ReportZero})
case *icheck.Threshold:
Expand All @@ -129,15 +128,21 @@ func checkToResource(ch influxdb.Check, name string) Resource {
func convertThreshold(th icheck.ThresholdConfig) Resource {
r := Resource{fieldLevel: th.GetLevel().String()}

assignLesser := func(threshType thresholdType, allValues bool, val float64) {
r[fieldType] = string(threshType)
assignNonZeroBools(r, map[string]bool{fieldCheckAllValues: allValues})
r[fieldValue] = val
}

switch realType := th.(type) {
case icheck.Lesser:
r[fieldType] = string(thresholdTypeLesser)
assignNonZeroBools(r, map[string]bool{fieldCheckAllValues: realType.AllValues})
r[fieldValue] = realType.Value
assignLesser(thresholdTypeLesser, realType.AllValues, realType.Value)
case *icheck.Lesser:
assignLesser(thresholdTypeLesser, realType.AllValues, realType.Value)
case icheck.Greater:
r[fieldType] = string(thresholdTypeGreater)
assignNonZeroBools(r, map[string]bool{fieldCheckAllValues: realType.AllValues})
r[fieldValue] = realType.Value
assignLesser(thresholdTypeGreater, realType.AllValues, realType.Value)
case *icheck.Greater:
assignLesser(thresholdTypeGreater, realType.AllValues, realType.Value)
case icheck.Range:
assignRangeThreshold(r, realType)
case *icheck.Range:
Expand Down Expand Up @@ -433,6 +438,67 @@ func endpointToResource(e influxdb.NotificationEndpoint, name string) Resource {
return r
}

func ruleToResource(iRule influxdb.NotificationRule, endpointName, name string) Resource {
if name == "" {
name = iRule.GetName()
}
r := Resource{
fieldKind: KindNotificationRule.title(),
fieldName: name,
fieldNotificationRuleEndpointName: endpointName,
}
assignNonZeroStrings(r, map[string]string{
fieldDescription: iRule.GetDescription(),
})

assignBase := func(base rule.Base) {
assignNonZeroFluxDurs(r, map[string]*notification.Duration{
fieldEvery: base.Every,
fieldOffset: base.Offset,
})

var tagRes []Resource
for _, tRule := range base.TagRules {
tagRes = append(tagRes, Resource{
fieldKey: tRule.Key,
fieldValue: tRule.Value,
fieldOperator: tRule.Operator.String(),
})
}
if len(tagRes) > 0 {
r[fieldNotificationRuleTagRules] = tagRes
}

var statusRuleRes []Resource
for _, sRule := range base.StatusRules {
sRes := Resource{
fieldNotificationRuleCurrentLevel: sRule.CurrentLevel.String(),
}
if sRule.PreviousLevel != nil {
sRes[fieldNotificationRulePreviousLevel] = sRule.PreviousLevel.String()
}
statusRuleRes = append(statusRuleRes, sRes)
}
if len(statusRuleRes) > 0 {
r[fieldNotificationRuleStatusRules] = statusRuleRes
}
}

switch t := iRule.(type) {
case *rule.HTTP:
assignBase(t.Base)
case *rule.PagerDuty:
assignBase(t.Base)
r[fieldNotificationRuleMessageTemplate] = t.MessageTemplate
case *rule.Slack:
assignBase(t.Base)
r[fieldNotificationRuleMessageTemplate] = t.MessageTemplate
assignNonZeroStrings(r, map[string]string{fieldNotificationRuleChannel: t.Channel})
}

return r
}

func telegrafToResource(t influxdb.TelegrafConfig, name string) Resource {
if name == "" {
name = t.Name
Expand Down Expand Up @@ -487,6 +553,18 @@ func variableToResource(v influxdb.Variable, name string) Resource {
return r
}

func assignNonZeroFluxDurs(r Resource, m map[string]*notification.Duration) {
for field, dur := range m {
if dur == nil {
continue
}
if dur.TimeDuration() == 0 {
continue
}
r[field] = dur.TimeDuration().String()
}
}

func assignNonZeroBools(r Resource, m map[string]bool) {
for k, v := range m {
if v {
Expand Down
13 changes: 13 additions & 0 deletions pkger/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ var kinds = map[Kind]bool{
KindVariable: true,
}

var kindsUniqByName = map[Kind]bool{
KindBucket: true,
KindCheck: true,
KindCheckDeadman: true,
KindCheckThreshold: true,
KindLabel: true,
KindNotificationEndpoint: true,
KindNotificationEndpointHTTP: true,
KindNotificationEndpointPagerDuty: true,
KindNotificationEndpointSlack: true,
KindVariable: true,
}

// Kind is a resource kind.
type Kind string

Expand Down
26 changes: 18 additions & 8 deletions pkger/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1274,7 +1274,13 @@ func uniqResources(resources []Resource) []Resource {
kind Kind
name string
}

// these 2 maps are used to eliminate duplicates that come
// from dependencies while keeping the Resource that has any
// associations. If there are no associations, then the resources
// are no different from one another.
m := make(map[key]bool)
res := make(map[key]Resource)

out := make([]Resource, 0, len(resources))
for _, r := range resources {
Expand All @@ -1285,18 +1291,22 @@ func uniqResources(resources []Resource) []Resource {
if err := k.OK(); err != nil {
continue
}
switch k {
// these 3 kinds are unique, have existing state identifiable by name
case KindBucket, KindLabel, KindVariable:

if kindsUniqByName[k] {
rKey := key{kind: k, name: r.Name()}
if m[rKey] {
if hasAssociations, ok := m[rKey]; ok && hasAssociations {
continue
}
m[rKey] = true
fallthrough
default:
out = append(out, r)
_, hasAssociations := r[fieldAssociations]
m[rKey] = hasAssociations
res[rKey] = r
continue
}
out = append(out, r)
}

for _, r := range res {
out = append(out, r)
}
return out
}
Expand Down
Loading