feat(pkger): add support for notification endpoints to parser
parent
34c0a69abf
commit
4a888cc706
208
pkger/models.go
208
pkger/models.go
|
@ -3,32 +3,40 @@ package pkger
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/notification/endpoint"
|
||||
)
|
||||
|
||||
// Package kinds.
|
||||
const (
|
||||
KindUnknown Kind = ""
|
||||
KindBucket Kind = "bucket"
|
||||
KindDashboard Kind = "dashboard"
|
||||
KindLabel Kind = "label"
|
||||
KindPackage Kind = "package"
|
||||
KindTelegraf Kind = "telegraf"
|
||||
KindVariable Kind = "variable"
|
||||
KindUnknown Kind = ""
|
||||
KindBucket Kind = "bucket"
|
||||
KindDashboard Kind = "dashboard"
|
||||
KindLabel Kind = "label"
|
||||
KindNotificationEndpointPagerDuty Kind = "notificationendpointpagerduty"
|
||||
KindNotificationEndpointHTTP Kind = "notificationendpointhttp"
|
||||
KindNotificationEndpointSlack Kind = "notificationendpointslack"
|
||||
KindPackage Kind = "package"
|
||||
KindTelegraf Kind = "telegraf"
|
||||
KindVariable Kind = "variable"
|
||||
)
|
||||
|
||||
var kinds = map[Kind]bool{
|
||||
KindBucket: true,
|
||||
KindDashboard: true,
|
||||
KindLabel: true,
|
||||
KindPackage: true,
|
||||
KindTelegraf: true,
|
||||
KindVariable: true,
|
||||
KindBucket: true,
|
||||
KindDashboard: true,
|
||||
KindLabel: true,
|
||||
KindNotificationEndpointHTTP: true,
|
||||
KindNotificationEndpointPagerDuty: true,
|
||||
KindNotificationEndpointSlack: true,
|
||||
KindPackage: true,
|
||||
KindTelegraf: true,
|
||||
KindVariable: true,
|
||||
}
|
||||
|
||||
// Kind is a resource kind.
|
||||
|
@ -71,6 +79,10 @@ func (k Kind) ResourceType() influxdb.ResourceType {
|
|||
return influxdb.DashboardsResourceType
|
||||
case KindLabel:
|
||||
return influxdb.LabelsResourceType
|
||||
case KindNotificationEndpointHTTP,
|
||||
KindNotificationEndpointPagerDuty,
|
||||
KindNotificationEndpointSlack:
|
||||
return influxdb.NotificationEndpointResourceType
|
||||
case KindTelegraf:
|
||||
return influxdb.TelegrafsResourceType
|
||||
case KindVariable:
|
||||
|
@ -335,12 +347,13 @@ func (d DiffVariable) hasConflict() bool {
|
|||
// Summary is a definition of all the resources that have or
|
||||
// will be created from a pkg.
|
||||
type Summary struct {
|
||||
Buckets []SummaryBucket `json:"buckets"`
|
||||
Dashboards []SummaryDashboard `json:"dashboards"`
|
||||
Labels []SummaryLabel `json:"labels"`
|
||||
LabelMappings []SummaryLabelMapping `json:"labelMappings"`
|
||||
TelegrafConfigs []SummaryTelegraf `json:"telegrafConfigs"`
|
||||
Variables []SummaryVariable `json:"variables"`
|
||||
Buckets []SummaryBucket `json:"buckets"`
|
||||
Dashboards []SummaryDashboard `json:"dashboards"`
|
||||
NotificationEndpoints []SummaryNotificationEndpoint `json:"notificationEndpoints"`
|
||||
Labels []SummaryLabel `json:"labels"`
|
||||
LabelMappings []SummaryLabelMapping `json:"labelMappings"`
|
||||
TelegrafConfigs []SummaryTelegraf `json:"telegrafConfigs"`
|
||||
Variables []SummaryVariable `json:"variables"`
|
||||
}
|
||||
|
||||
// SummaryBucket provides a summary of a pkg bucket.
|
||||
|
@ -404,6 +417,12 @@ type SummaryChart struct {
|
|||
Width int `json:"width"`
|
||||
}
|
||||
|
||||
// SummaryNotificationEndpoint provides a summary of a pkg endpoint rule.
|
||||
type SummaryNotificationEndpoint struct {
|
||||
influxdb.NotificationEndpoint
|
||||
LabelAssociations []influxdb.Label `json:"labelAssociations"`
|
||||
}
|
||||
|
||||
// SummaryLabel provides a summary of a pkg label.
|
||||
type SummaryLabel struct {
|
||||
influxdb.Label
|
||||
|
@ -438,6 +457,7 @@ const (
|
|||
fieldPrefix = "prefix"
|
||||
fieldQuery = "query"
|
||||
fieldSuffix = "suffix"
|
||||
fieldStatus = "status"
|
||||
fieldType = "type"
|
||||
fieldValue = "value"
|
||||
fieldValues = "values"
|
||||
|
@ -721,6 +741,156 @@ func (s sortedLabels) Swap(i, j int) {
|
|||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
type notificationKind int
|
||||
|
||||
const (
|
||||
notificationKindHTTP notificationKind = iota + 1
|
||||
notificationKindPagerDuty
|
||||
notificationKindSlack
|
||||
)
|
||||
|
||||
const (
|
||||
notificationHTTPAuthTypeBasic = "basic"
|
||||
notificationHTTPAuthTypeBearer = "bearer"
|
||||
notificationHTTPAuthTypeNone = "none"
|
||||
)
|
||||
|
||||
const (
|
||||
fieldNotificationEndpointPassword = "password"
|
||||
fieldNotificationEndpointRoutingKey = "routingKey"
|
||||
fieldNotificationEndpointToken = "token"
|
||||
fieldNotificationEndpointURL = "url"
|
||||
fieldNotificationEndpointUsername = "username"
|
||||
)
|
||||
|
||||
type notificationEndpoint struct {
|
||||
kind notificationKind
|
||||
name string
|
||||
description string
|
||||
password string
|
||||
routingKey string
|
||||
status string
|
||||
token string
|
||||
httpType string
|
||||
url string
|
||||
username string
|
||||
|
||||
labels sortedLabels
|
||||
}
|
||||
|
||||
func (n *notificationEndpoint) Name() string {
|
||||
return n.name
|
||||
}
|
||||
|
||||
func (n *notificationEndpoint) ResourceType() influxdb.ResourceType {
|
||||
return KindNotificationEndpointSlack.ResourceType()
|
||||
}
|
||||
|
||||
func (n *notificationEndpoint) summarize() SummaryNotificationEndpoint {
|
||||
base := endpoint.Base{
|
||||
Name: n.Name(),
|
||||
Description: n.description,
|
||||
Status: influxdb.TaskStatusActive,
|
||||
}
|
||||
if n.status != "" {
|
||||
base.Status = influxdb.Status(n.status)
|
||||
}
|
||||
sum := SummaryNotificationEndpoint{
|
||||
LabelAssociations: toInfluxLabels(n.labels...),
|
||||
}
|
||||
switch n.kind {
|
||||
case notificationKindHTTP:
|
||||
e := &endpoint.HTTP{
|
||||
Base: base,
|
||||
URL: n.url,
|
||||
Method: "POST",
|
||||
}
|
||||
switch {
|
||||
case n.password == "" && n.username == "" && n.token == "":
|
||||
e.AuthMethod = notificationHTTPAuthTypeNone
|
||||
case n.token != "":
|
||||
e.AuthMethod = notificationHTTPAuthTypeBearer
|
||||
default:
|
||||
e.AuthMethod = notificationHTTPAuthTypeBasic
|
||||
}
|
||||
sum.NotificationEndpoint = e
|
||||
case notificationKindPagerDuty:
|
||||
sum.NotificationEndpoint = &endpoint.PagerDuty{
|
||||
Base: base,
|
||||
ClientURL: n.url,
|
||||
}
|
||||
case notificationKindSlack:
|
||||
sum.NotificationEndpoint = &endpoint.Slack{
|
||||
Base: base,
|
||||
URL: n.url,
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func (n *notificationEndpoint) valid() []validationErr {
|
||||
var failures []validationErr
|
||||
if _, err := url.Parse(n.url); err != nil || n.url == "" {
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldNotificationEndpointURL,
|
||||
Msg: "must be valid url",
|
||||
})
|
||||
}
|
||||
|
||||
if n.status != "" && influxdb.TaskStatusInactive != n.status && influxdb.TaskStatusActive != n.status {
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldStatus,
|
||||
Msg: "not a valid status; valid statues are one of [active, inactive]",
|
||||
})
|
||||
}
|
||||
|
||||
switch n.kind {
|
||||
case notificationKindPagerDuty:
|
||||
if n.routingKey == "" {
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldNotificationEndpointRoutingKey,
|
||||
Msg: "must provide non empty string",
|
||||
})
|
||||
}
|
||||
case notificationKindHTTP:
|
||||
switch n.httpType {
|
||||
case notificationHTTPAuthTypeBasic:
|
||||
if n.password == "" {
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldNotificationEndpointPassword,
|
||||
Msg: "must provide non empty string",
|
||||
})
|
||||
}
|
||||
if n.username == "" {
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldNotificationEndpointUsername,
|
||||
Msg: "must provide non empty string",
|
||||
})
|
||||
}
|
||||
case notificationHTTPAuthTypeBearer:
|
||||
if n.token == "" {
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldNotificationEndpointToken,
|
||||
Msg: "must provide non empty string",
|
||||
})
|
||||
}
|
||||
case notificationHTTPAuthTypeNone:
|
||||
default:
|
||||
failures = append(failures, validationErr{
|
||||
Field: fieldType,
|
||||
Msg: fmt.Sprintf(
|
||||
"invalid type provided %q; valid type is 1 in [%s, %s, %s]",
|
||||
n.httpType,
|
||||
notificationHTTPAuthTypeBasic,
|
||||
notificationHTTPAuthTypeBearer,
|
||||
notificationHTTPAuthTypeNone,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
return failures
|
||||
}
|
||||
|
||||
const (
|
||||
fieldTelegrafConfig = "config"
|
||||
)
|
||||
|
|
116
pkger/parser.go
116
pkger/parser.go
|
@ -133,11 +133,12 @@ type Pkg struct {
|
|||
Resources []Resource `yaml:"resources" json:"resources"`
|
||||
} `yaml:"spec" json:"spec"`
|
||||
|
||||
mLabels map[string]*label
|
||||
mBuckets map[string]*bucket
|
||||
mDashboards []*dashboard
|
||||
mVariables map[string]*variable
|
||||
mTelegrafs []*telegraf
|
||||
mLabels map[string]*label
|
||||
mBuckets map[string]*bucket
|
||||
mDashboards []*dashboard
|
||||
mNotificationEndpoints map[string]*notificationEndpoint
|
||||
mTelegrafs []*telegraf
|
||||
mVariables map[string]*variable
|
||||
|
||||
isVerified bool // dry run has verified pkg resources with existing resources
|
||||
isParsed bool // indicates the pkg has been parsed and all resources graphed accordingly
|
||||
|
@ -169,6 +170,10 @@ func (p *Pkg) Summary() Summary {
|
|||
})
|
||||
}
|
||||
|
||||
for _, n := range p.notificationEndpoints() {
|
||||
sum.NotificationEndpoints = append(sum.NotificationEndpoints, n.summarize())
|
||||
}
|
||||
|
||||
for _, t := range p.telegrafs() {
|
||||
sum.TelegrafConfigs = append(sum.TelegrafConfigs, t.summarize())
|
||||
}
|
||||
|
@ -259,6 +264,21 @@ func (p *Pkg) dashboards() []*dashboard {
|
|||
return dashes
|
||||
}
|
||||
|
||||
func (p *Pkg) notificationEndpoints() []*notificationEndpoint {
|
||||
endpoints := make([]*notificationEndpoint, 0, len(p.mNotificationEndpoints))
|
||||
for _, e := range p.mNotificationEndpoints {
|
||||
endpoints = append(endpoints, e)
|
||||
}
|
||||
sort.Slice(endpoints, func(i, j int) bool {
|
||||
ei, ej := endpoints[i], endpoints[j]
|
||||
if ei.kind == ej.kind {
|
||||
return ei.Name() < ej.Name()
|
||||
}
|
||||
return ei.kind < ej.kind
|
||||
})
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func (p *Pkg) telegrafs() []*telegraf {
|
||||
teles := p.mTelegrafs[:]
|
||||
sort.Slice(teles, func(i, j int) bool { return teles[i].Name() < teles[j].Name() })
|
||||
|
@ -375,23 +395,20 @@ func (p *Pkg) validResources() error {
|
|||
}
|
||||
|
||||
func (p *Pkg) graphResources() error {
|
||||
graphFns := []func() error{
|
||||
// labels are first to validate associations with other resources
|
||||
graphFns := []func() *parseErr{
|
||||
// labels are first, this is to validate associations with other resources
|
||||
p.graphLabels,
|
||||
p.graphVariables,
|
||||
p.graphBuckets,
|
||||
p.graphDashboards,
|
||||
p.graphNotificationEndpoints,
|
||||
p.graphTelegrafs,
|
||||
}
|
||||
|
||||
var pErr parseErr
|
||||
for _, fn := range graphFns {
|
||||
if err := fn(); err != nil {
|
||||
if IsParseErr(err) {
|
||||
pErr.append(err.(*parseErr).Resources...)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
pErr.append(err.Resources...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,7 +423,7 @@ func (p *Pkg) graphResources() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Pkg) graphBuckets() error {
|
||||
func (p *Pkg) graphBuckets() *parseErr {
|
||||
p.mBuckets = make(map[string]*bucket)
|
||||
return p.eachResource(KindBucket, 2, func(r Resource) []validationErr {
|
||||
if _, ok := p.mBuckets[r.Name()]; ok {
|
||||
|
@ -444,7 +461,7 @@ func (p *Pkg) graphBuckets() error {
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Pkg) graphLabels() error {
|
||||
func (p *Pkg) graphLabels() *parseErr {
|
||||
p.mLabels = make(map[string]*label)
|
||||
return p.eachResource(KindLabel, 2, func(r Resource) []validationErr {
|
||||
if _, ok := p.mLabels[r.Name()]; ok {
|
||||
|
@ -463,7 +480,7 @@ func (p *Pkg) graphLabels() error {
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Pkg) graphDashboards() error {
|
||||
func (p *Pkg) graphDashboards() *parseErr {
|
||||
p.mDashboards = make([]*dashboard, 0)
|
||||
return p.eachResource(KindDashboard, 2, func(r Resource) []validationErr {
|
||||
dash := &dashboard{
|
||||
|
@ -497,7 +514,70 @@ func (p *Pkg) graphDashboards() error {
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Pkg) graphVariables() error {
|
||||
func (p *Pkg) graphNotificationEndpoints() *parseErr {
|
||||
p.mNotificationEndpoints = make(map[string]*notificationEndpoint)
|
||||
|
||||
notificationKinds := []struct {
|
||||
kind Kind
|
||||
notificationKind notificationKind
|
||||
}{
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
notificationKind: notificationKindHTTP,
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointPagerDuty,
|
||||
notificationKind: notificationKindPagerDuty,
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointSlack,
|
||||
notificationKind: notificationKindSlack,
|
||||
},
|
||||
}
|
||||
|
||||
var pErr parseErr
|
||||
for _, nk := range notificationKinds {
|
||||
err := p.eachResource(nk.kind, 1, func(r Resource) []validationErr {
|
||||
if _, ok := p.mNotificationEndpoints[r.Name()]; ok {
|
||||
return []validationErr{{
|
||||
Field: "name",
|
||||
Msg: "duplicate name: " + r.Name(),
|
||||
}}
|
||||
}
|
||||
|
||||
endpoint := ¬ificationEndpoint{
|
||||
kind: nk.notificationKind,
|
||||
name: r.Name(),
|
||||
description: r.stringShort(fieldDescription),
|
||||
httpType: strings.ToLower(r.stringShort(fieldType)),
|
||||
password: r.stringShort(fieldNotificationEndpointPassword),
|
||||
routingKey: r.stringShort(fieldNotificationEndpointRoutingKey),
|
||||
status: strings.ToLower(r.stringShort(fieldStatus)),
|
||||
token: r.stringShort(fieldNotificationEndpointToken),
|
||||
url: r.stringShort(fieldNotificationEndpointURL),
|
||||
username: r.stringShort(fieldNotificationEndpointUsername),
|
||||
}
|
||||
failures := p.parseNestedLabels(r, func(l *label) error {
|
||||
endpoint.labels = append(endpoint.labels, l)
|
||||
p.mLabels[l.Name()].setMapping(endpoint, false)
|
||||
return nil
|
||||
})
|
||||
sort.Sort(endpoint.labels)
|
||||
|
||||
p.mNotificationEndpoints[endpoint.Name()] = endpoint
|
||||
return append(failures, endpoint.valid()...)
|
||||
})
|
||||
if err != nil {
|
||||
pErr.append(err.Resources...)
|
||||
}
|
||||
}
|
||||
if len(pErr.Resources) > 0 {
|
||||
return &pErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pkg) graphVariables() *parseErr {
|
||||
p.mVariables = make(map[string]*variable)
|
||||
return p.eachResource(KindVariable, 1, func(r Resource) []validationErr {
|
||||
if _, ok := p.mVariables[r.Name()]; ok {
|
||||
|
@ -531,7 +611,7 @@ func (p *Pkg) graphVariables() error {
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Pkg) graphTelegrafs() error {
|
||||
func (p *Pkg) graphTelegrafs() *parseErr {
|
||||
p.mTelegrafs = make([]*telegraf, 0)
|
||||
return p.eachResource(KindTelegraf, 0, func(r Resource) []validationErr {
|
||||
tele := new(telegraf)
|
||||
|
@ -559,7 +639,7 @@ func (p *Pkg) graphTelegrafs() error {
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Pkg) eachResource(resourceKind Kind, minNameLen int, fn func(r Resource) []validationErr) error {
|
||||
func (p *Pkg) eachResource(resourceKind Kind, minNameLen int, fn func(r Resource) []validationErr) *parseErr {
|
||||
var pErr parseErr
|
||||
for i, r := range p.Spec.Resources {
|
||||
k, err := r.kind()
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/notification/endpoint"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -132,7 +133,7 @@ spec:
|
|||
{
|
||||
name: "missing name",
|
||||
validationErrs: 1,
|
||||
valFields: []string{"name"},
|
||||
valFields: []string{fieldName},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
|
@ -147,7 +148,7 @@ spec:
|
|||
{
|
||||
name: "mixed valid and missing name",
|
||||
validationErrs: 1,
|
||||
valFields: []string{"name"},
|
||||
valFields: []string{fieldName},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
|
@ -166,7 +167,7 @@ spec:
|
|||
name: "mixed valid and multiple bad names",
|
||||
resourceErrs: 2,
|
||||
validationErrs: 1,
|
||||
valFields: []string{"name"},
|
||||
valFields: []string{fieldName},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
|
@ -187,7 +188,7 @@ spec:
|
|||
name: "duplicate bucket names",
|
||||
resourceErrs: 1,
|
||||
validationErrs: 1,
|
||||
valFields: []string{"name"},
|
||||
valFields: []string{fieldName},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
|
@ -2703,6 +2704,373 @@ spec:
|
|||
})
|
||||
})
|
||||
|
||||
t.Run("pkg with notification endpoints and labels associated", func(t *testing.T) {
|
||||
testfileRunner(t, "testdata/notification_endpoint", func(t *testing.T, pkg *Pkg) {
|
||||
expectedEndpoints := []SummaryNotificationEndpoint{
|
||||
{
|
||||
NotificationEndpoint: &endpoint.HTTP{
|
||||
Base: endpoint.Base{
|
||||
Name: "http_basic_auth_notification_endpoint",
|
||||
Description: "http basic auth desc",
|
||||
Status: influxdb.TaskStatusInactive,
|
||||
},
|
||||
URL: "https://www.example.com/endpoint/basicauth",
|
||||
AuthMethod: "basic",
|
||||
Method: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
NotificationEndpoint: &endpoint.HTTP{
|
||||
Base: endpoint.Base{
|
||||
Name: "http_bearer_auth_notification_endpoint",
|
||||
Description: "http bearer auth desc",
|
||||
Status: influxdb.TaskStatusActive,
|
||||
},
|
||||
URL: "https://www.example.com/endpoint/bearerauth",
|
||||
AuthMethod: "bearer",
|
||||
Method: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
NotificationEndpoint: &endpoint.HTTP{
|
||||
Base: endpoint.Base{
|
||||
Name: "http_none_auth_notification_endpoint",
|
||||
Description: "http none auth desc",
|
||||
Status: influxdb.TaskStatusActive,
|
||||
},
|
||||
URL: "https://www.example.com/endpoint/noneauth",
|
||||
AuthMethod: "none",
|
||||
Method: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
NotificationEndpoint: &endpoint.PagerDuty{
|
||||
Base: endpoint.Base{
|
||||
Name: "pager_duty_notification_endpoint",
|
||||
Description: "pager duty desc",
|
||||
Status: influxdb.TaskStatusActive,
|
||||
},
|
||||
ClientURL: "http://localhost:8080/orgs/7167eb6719fa34e5/alert-history",
|
||||
},
|
||||
},
|
||||
{
|
||||
NotificationEndpoint: &endpoint.Slack{
|
||||
Base: endpoint.Base{
|
||||
Name: "slack_notification_endpoint",
|
||||
Description: "slack desc",
|
||||
Status: influxdb.TaskStatusActive,
|
||||
},
|
||||
URL: "https://hooks.slack.com/services/bip/piddy/boppidy",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
sum := pkg.Summary()
|
||||
endpoints := sum.NotificationEndpoints
|
||||
require.Len(t, endpoints, len(expectedEndpoints))
|
||||
|
||||
for i := range expectedEndpoints {
|
||||
expected, actual := expectedEndpoints[i], endpoints[i]
|
||||
assert.Equalf(t, expected.NotificationEndpoint, actual.NotificationEndpoint, "index=%d", i)
|
||||
require.Len(t, actual.LabelAssociations, 1)
|
||||
assert.Equal(t, "label_1", actual.LabelAssociations[0].Name)
|
||||
|
||||
require.Len(t, sum.LabelMappings, len(expectedEndpoints))
|
||||
expectedMapping := SummaryLabelMapping{
|
||||
ResourceName: expected.GetName(),
|
||||
LabelName: "label_1",
|
||||
LabelMapping: influxdb.LabelMapping{
|
||||
ResourceType: influxdb.NotificationEndpointResourceType,
|
||||
},
|
||||
}
|
||||
assert.Contains(t, sum.LabelMappings, expectedMapping)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("handles bad config", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
kind Kind
|
||||
resErr testPkgResourceError
|
||||
}{
|
||||
{
|
||||
kind: KindNotificationEndpointSlack,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing slack url",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointURL},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointSlack
|
||||
name: name1
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointPagerDuty,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing pager duty url",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointURL},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointPagerDuty
|
||||
name: name1
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing http url",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointURL},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "bad url",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointURL},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: none
|
||||
url: d_____-_8**(*https://www.examples.coms
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "bad url",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointURL},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: none
|
||||
url: d_____-_8**(*https://www.examples.coms
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing basic username",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointUsername},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: basic
|
||||
url: example.com
|
||||
password: password
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing basic password",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointPassword},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: basic
|
||||
url: example.com
|
||||
username: user
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing basic password and username",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointPassword, fieldNotificationEndpointUsername},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: basic
|
||||
url: example.com
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "missing bearer token",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldNotificationEndpointToken},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: bearer
|
||||
url: example.com
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "invalid http type",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldType},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: threeve
|
||||
url: example.com
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointHTTP,
|
||||
resErr: testPkgResourceError{
|
||||
name: "invalid http type",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldType},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: name1
|
||||
type: threeve
|
||||
url: example.com
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointSlack,
|
||||
resErr: testPkgResourceError{
|
||||
name: "duplicate ",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldName},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointSlack
|
||||
name: dupe
|
||||
url: example.com
|
||||
- kind: NotificationEndpointSlack
|
||||
name: dupe
|
||||
url: example.com
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: KindNotificationEndpointSlack,
|
||||
resErr: testPkgResourceError{
|
||||
name: "invalid status",
|
||||
validationErrs: 1,
|
||||
valFields: []string{fieldStatus},
|
||||
pkgStr: `apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: NotificationEndpointSlack
|
||||
name: dupe
|
||||
url: example.com
|
||||
status: rando bad status
|
||||
`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
testPkgErrors(t, tt.kind, tt.resErr)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("pkg with telegraf and label associations", func(t *testing.T) {
|
||||
t.Run("with valid fields", func(t *testing.T) {
|
||||
testfileRunner(t, "testdata/telegraf", func(t *testing.T, pkg *Pkg) {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"apiVersion": "0.1.0",
|
||||
"kind": "Package",
|
||||
"meta": {
|
||||
"pkgName": "pkg_name",
|
||||
"pkgVersion": "1",
|
||||
"description": "pack description"
|
||||
},
|
||||
"spec": {
|
||||
"resources": [
|
||||
{
|
||||
"kind": "Label",
|
||||
"name": "label_1"
|
||||
},
|
||||
{
|
||||
"kind": "NotificationEndpointSlack",
|
||||
"name": "slack_notification_endpoint",
|
||||
"description": "slack desc",
|
||||
"url": "https://hooks.slack.com/services/bip/piddy/boppidy",
|
||||
"token": "tokenval",
|
||||
"status": "active",
|
||||
"associations": [
|
||||
{
|
||||
"kind": "Label",
|
||||
"name": "label_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "NotificationEndpointHTTP",
|
||||
"name": "http_none_auth_notification_endpoint",
|
||||
"description": "http none auth desc",
|
||||
"type": "none",
|
||||
"url": "https://www.example.com/endpoint/noneauth",
|
||||
"status": "active",
|
||||
"associations": [
|
||||
{
|
||||
"kind": "Label",
|
||||
"name": "label_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "NotificationEndpointHTTP",
|
||||
"name": "http_basic_auth_notification_endpoint",
|
||||
"description": "http basic auth desc",
|
||||
"type": "basic",
|
||||
"url": "https://www.example.com/endpoint/basicauth",
|
||||
"username": "secret username",
|
||||
"password": "secret password",
|
||||
"status": "inactive",
|
||||
"associations": [
|
||||
{
|
||||
"kind": "Label",
|
||||
"name": "label_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "NotificationEndpointHTTP",
|
||||
"name": "http_bearer_auth_notification_endpoint",
|
||||
"description": "http bearer auth desc",
|
||||
"type": "bearer",
|
||||
"url": "https://www.example.com/endpoint/bearerauth",
|
||||
"token": "secret token",
|
||||
"associations": [
|
||||
{
|
||||
"kind": "Label",
|
||||
"name": "label_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "NotificationEndpointPagerDuty",
|
||||
"name": "pager_duty_notification_endpoint",
|
||||
"description": "pager duty desc",
|
||||
"url": "http://localhost:8080/orgs/7167eb6719fa34e5/alert-history",
|
||||
"routingKey": "secret routing-key",
|
||||
"status": "active",
|
||||
"associations": [
|
||||
{
|
||||
"kind": "Label",
|
||||
"name": "label_1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
apiVersion: 0.1.0
|
||||
kind: Package
|
||||
meta:
|
||||
pkgName: pkg_name
|
||||
pkgVersion: 1
|
||||
description: pack description
|
||||
spec:
|
||||
resources:
|
||||
- kind: Label
|
||||
name: label_1
|
||||
- kind: NotificationEndpointSlack
|
||||
name: slack_notification_endpoint
|
||||
description: slack desc
|
||||
url: https://hooks.slack.com/services/bip/piddy/boppidy
|
||||
status: active
|
||||
token: tokenval
|
||||
associations:
|
||||
- kind: Label
|
||||
name: label_1
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: http_none_auth_notification_endpoint
|
||||
type: none
|
||||
description: http none auth desc
|
||||
url: https://www.example.com/endpoint/noneauth
|
||||
status: active
|
||||
associations:
|
||||
- kind: Label
|
||||
name: label_1
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: http_basic_auth_notification_endpoint
|
||||
description: http basic auth desc
|
||||
type: basic
|
||||
url: https://www.example.com/endpoint/basicauth
|
||||
username: "secret username"
|
||||
password: "secret password"
|
||||
status: inactive
|
||||
associations:
|
||||
- kind: Label
|
||||
name: label_1
|
||||
- kind: NotificationEndpointHTTP
|
||||
name: http_bearer_auth_notification_endpoint
|
||||
description: http bearer auth desc
|
||||
type: bearer
|
||||
url: https://www.example.com/endpoint/bearerauth
|
||||
token: "secret token"
|
||||
associations:
|
||||
- kind: Label
|
||||
name: label_1
|
||||
- kind: NotificationEndpointPagerDuty
|
||||
name: pager_duty_notification_endpoint
|
||||
description: pager duty desc
|
||||
url: http://localhost:8080/orgs/7167eb6719fa34e5/alert-history
|
||||
routingKey: "secret routing-key"
|
||||
status: active
|
||||
associations:
|
||||
- kind: Label
|
||||
name: label_1
|
||||
|
Loading…
Reference in New Issue