diff --git a/cmd/influx/pkg.go b/cmd/influx/pkg.go index b7fe2d06822..b1f28a8184c 100644 --- a/cmd/influx/pkg.go +++ b/cmd/influx/pkg.go @@ -832,20 +832,45 @@ func (b *cmdPkgBuilder) printPkgDiff(diff pkger.Diff) error { } if rules := diff.NotificationRules; len(rules) > 0 { - headers := []string{"New", "Name", "Description", "Every", "Offset", "Endpoint Name", "Endpoint ID", "Endpoint Type"} - tablePrintFn("NOTIFICATION RULES", headers, len(rules), func(i int) []string { - v := rules[i] + printer := diffPrinterGen("Notification Rules", []string{ + "Description", + "Every", + "Offset", + "Endpoint Name", + "Endpoint ID", + "Endpoint Type", + }) + + appendValues := func(id pkger.SafeID, pkgName string, v pkger.DiffNotificationRuleValues) []string { return []string{ - green(true), + pkgName, + id.String(), v.Name, - v.Description, v.Every, v.Offset, v.EndpointName, v.EndpointID.String(), v.EndpointType, } - }) + } + + for _, e := range rules { + var oldRow []string + if e.Old != nil { + oldRow = appendValues(e.ID, e.PkgName, *e.Old) + } + + newRow := appendValues(e.ID, e.PkgName, e.New) + switch { + case e.IsNew(): + printer.AppendDiff(nil, newRow) + case e.Remove: + printer.AppendDiff(oldRow, nil) + default: + printer.AppendDiff(oldRow, newRow) + } + } + printer.Render() } if teles := diff.Telegrafs; len(teles) > 0 { diff --git a/cmd/influxd/launcher/launcher_helpers.go b/cmd/influxd/launcher/launcher_helpers.go index 1ac5907dabb..0abf1747fc0 100644 --- a/cmd/influxd/launcher/launcher_helpers.go +++ b/cmd/influxd/launcher/launcher_helpers.go @@ -104,7 +104,7 @@ func (tl *TestLauncher) ShutdownOrFail(tb testing.TB, ctx context.Context) { } } -// SetupOrFail creates a new user, bucket, org, and auth token. +// Setup creates a new user, bucket, org, and auth token. func (tl *TestLauncher) Setup() error { results, err := tl.OnBoard(&platform.OnboardingRequest{ User: "USER", @@ -117,7 +117,6 @@ func (tl *TestLauncher) Setup() error { } tl.User = results.User - fmt.Println(tl.User) tl.Org = results.Org tl.Bucket = results.Bucket tl.Auth = results.Auth diff --git a/cmd/influxd/launcher/pkger_test.go b/cmd/influxd/launcher/pkger_test.go index 2a2691167c5..c1e0d6fd24d 100644 --- a/cmd/influxd/launcher/pkger_test.go +++ b/cmd/influxd/launcher/pkger_test.go @@ -535,7 +535,7 @@ func TestLauncher_Pkger(t *testing.T) { require.Len(t, diff.NotificationRules, 1) // the pkg being run here has a relationship with the rule and the endpoint within the pkg. - assert.Equal(t, "http", diff.NotificationRules[0].EndpointType) + assert.Equal(t, "http", diff.NotificationRules[0].New.EndpointType) require.Len(t, diff.Dashboards, 1) require.Len(t, diff.NotificationEndpoints, 1) @@ -1089,6 +1089,7 @@ spec: pkger.WithDashboardSVC(l.DashboardService(t)), pkger.WithLabelSVC(l.LabelService(t)), pkger.WithNotificationEndpointSVC(l.NotificationEndpointService(t)), + pkger.WithNotificationRuleSVC(l.NotificationRuleService()), pkger.WithTaskSVC(l.TaskServiceKV()), pkger.WithTelegrafSVC(l.TelegrafService(t)), pkger.WithVariableSVC(l.VariableService(t)), diff --git a/pkger/clone_resource.go b/pkger/clone_resource.go index 951a834f029..c71de115c17 100644 --- a/pkger/clone_resource.go +++ b/pkger/clone_resource.go @@ -247,7 +247,7 @@ func (ex *resourceExporter) resourceCloneToKind(ctx context.Context, r ResourceT } endpointObjectName := object.Name() - mapResource(rule.GetOrgID(), rule.GetID(), KindNotificationRule, ruleToObject(rule, endpointObjectName, r.Name)) + mapResource(rule.GetOrgID(), rule.GetID(), KindNotificationRule, NotificationRuleToObject(r.Name, endpointObjectName, rule)) case r.Kind.is(KindTask): t, err := ex.taskSVC.FindTaskByID(ctx, r.ID) if err != nil { @@ -806,6 +806,7 @@ func LabelToObject(name string, l influxdb.Label) Object { return o } +// NotificationEndpointToObject converts an notification endpoint into a pkger Object. func NotificationEndpointToObject(name string, e influxdb.NotificationEndpoint) Object { if name == "" { name = e.GetName() @@ -845,13 +846,14 @@ func NotificationEndpointToObject(name string, e influxdb.NotificationEndpoint) return o } -func ruleToObject(iRule influxdb.NotificationRule, endpointName, name string) Object { +// NotificationRuleToObject converts an notification rule into a pkger Object. +func NotificationRuleToObject(name, endpointPkgName string, iRule influxdb.NotificationRule) Object { if name == "" { name = iRule.GetName() } o := newObject(KindNotificationRule, name) - o.Spec[fieldNotificationRuleEndpointName] = endpointName + o.Spec[fieldNotificationRuleEndpointName] = endpointPkgName assignNonZeroStrings(o.Spec, map[string]string{ fieldDescription: iRule.GetDescription(), }) diff --git a/pkger/http_remote_service.go b/pkger/http_remote_service.go index b224fa5685e..8c272584f78 100644 --- a/pkger/http_remote_service.go +++ b/pkger/http_remote_service.go @@ -2,7 +2,6 @@ package pkger import ( "context" - "fmt" "net/http" "github.com/influxdata/influxdb/v2" @@ -43,14 +42,12 @@ func (s *HTTPRemoteService) InitStack(ctx context.Context, userID influxdb.ID, s id, err := influxdb.IDFromString(respBody.ID) if err != nil { - fmt.Println("IN HERE with id: ", respBody.ID) return Stack{}, err } newStack.ID = *id orgID, err := influxdb.IDFromString(respBody.OrgID) if err != nil { - fmt.Println("IN HERE with orgID: ", respBody.OrgID) return Stack{}, err } newStack.OrgID = *orgID diff --git a/pkger/models.go b/pkger/models.go index 14e077c811d..b9ea96e4a9a 100644 --- a/pkger/models.go +++ b/pkger/models.go @@ -417,8 +417,7 @@ func (d DiffNotificationEndpoint) IsNew() bool { return d.Old == nil } -// DiffNotificationRule is a diff of an individual notification rule. This resource is always new. -type DiffNotificationRule struct { +type DiffNotificationRuleValues struct { Name string `json:"name"` Description string `json:"description"` @@ -430,31 +429,96 @@ type DiffNotificationRule struct { Every string `json:"every"` Offset string `json:"offset"` MessageTemplate string `json:"messageTemplate"` - Status influxdb.Status `json:"status"` StatusRules []SummaryStatusRule `json:"statusRules"` TagRules []SummaryTagRule `json:"tagRules"` } +// DiffNotificationRule is a diff of an individual notification rule. This resource is always new. +type DiffNotificationRule struct { + ID SafeID `json:"id"` + Remove bool `json:"bool"` + PkgName string `json:"pkgName"` + + New DiffNotificationRuleValues `json:"new"` + Old *DiffNotificationRuleValues `json:"old"` +} + func newDiffNotificationRule(r *notificationRule, iEndpoint influxdb.NotificationEndpoint) DiffNotificationRule { sum := DiffNotificationRule{ - Name: r.Name(), - Description: r.description, - EndpointName: r.endpointName.String(), - Every: r.every.String(), - Offset: r.offset.String(), - MessageTemplate: r.msgTemplate, - Status: r.Status(), - StatusRules: toSummaryStatusRules(r.statusRules), - TagRules: toSummaryTagRules(r.tagRules), + ID: SafeID(r.ID()), + Remove: r.shouldRemove, + PkgName: r.PkgName(), + New: DiffNotificationRuleValues{ + Name: r.Name(), + Description: r.description, + EndpointName: r.endpointName.String(), + Every: r.every.String(), + Offset: r.offset.String(), + MessageTemplate: r.msgTemplate, + StatusRules: toSummaryStatusRules(r.statusRules), + TagRules: toSummaryTagRules(r.tagRules), + }, } if iEndpoint != nil { - sum.EndpointID = SafeID(iEndpoint.GetID()) - sum.EndpointType = iEndpoint.Type() + sum.New.EndpointID = SafeID(iEndpoint.GetID()) + sum.New.EndpointType = iEndpoint.Type() + } + + if r.existing == nil { + return sum + } + + sum.Old = &DiffNotificationRuleValues{ + Name: r.existing.rule.GetName(), + Description: r.existing.rule.GetDescription(), + EndpointName: r.existing.endpointName, + EndpointID: SafeID(r.existing.rule.GetEndpointID()), + EndpointType: r.existing.endpointType, + } + + assignBase := func(b rule.Base) { + if b.Every != nil { + sum.Old.Every = b.Every.TimeDuration().String() + } + if b.Offset != nil { + sum.Old.Offset = b.Offset.TimeDuration().String() + } + for _, tr := range b.TagRules { + sum.Old.TagRules = append(sum.Old.TagRules, SummaryTagRule{ + Key: tr.Key, + Value: tr.Value, + Operator: tr.Operator.String(), + }) + } + for _, sr := range b.StatusRules { + sRule := SummaryStatusRule{CurrentLevel: sr.CurrentLevel.String()} + if sr.PreviousLevel != nil { + sRule.PreviousLevel = sr.PreviousLevel.String() + } + sum.Old.StatusRules = append(sum.Old.StatusRules, sRule) + } + } + + switch p := r.existing.rule.(type) { + case *rule.HTTP: + assignBase(p.Base) + case *rule.Slack: + assignBase(p.Base) + sum.Old.MessageTemplate = p.MessageTemplate + case *rule.PagerDuty: + assignBase(p.Base) + sum.Old.MessageTemplate = p.MessageTemplate } return sum } +// IsNew indicates if the resource will be new to the platform or if it edits +// an existing resource. +func (d DiffNotificationRule) IsNew() bool { + return d.Old != nil +} + // DiffTask is a diff of an individual task. This resource is always new. type DiffTask struct { Name string `json:"name"` @@ -1667,14 +1731,25 @@ type notificationRule struct { endpointName *references endpointType string + existing *existingRule + labels sortedLabels } +type existingRule struct { + rule influxdb.NotificationRule + endpointName string + endpointType string +} + func (r *notificationRule) Exists() bool { - return false + return r.existing != nil } func (r *notificationRule) ID() influxdb.ID { + if r.existing != nil { + return r.existing.rule.GetID() + } return r.id } diff --git a/pkger/service.go b/pkger/service.go index 6c1d46b1a31..ebc66a86620 100644 --- a/pkger/service.go +++ b/pkger/service.go @@ -831,9 +831,24 @@ func (s *Service) dryRunNotificationRules(ctx context.Context, orgID influxdb.ID if err != nil { return nil, internalErr(err) } - mExisting := make(map[string]influxdb.NotificationEndpoint) + + mExistingEndpointsByName := make(map[string]influxdb.NotificationEndpoint) + mExistingEndpointsByID := make(map[influxdb.ID]influxdb.NotificationEndpoint) for _, e := range iEndpoints { - mExisting[e.GetName()] = e + mExistingEndpointsByName[e.GetName()] = e + mExistingEndpointsByID[e.GetID()] = e + } + + iRules, _, err := s.ruleSVC.FindNotificationRules(ctx, influxdb.NotificationRuleFilter{ + OrgID: &orgID, + }, influxdb.FindOptions{Limit: 100}) + if err != nil { + return nil, internalErr(err) + } + + mExistingRulesByID := make(map[influxdb.ID]influxdb.NotificationRule) + for _, r := range iRules { + mExistingRulesByID[r.GetID()] = r } mPkgEndpoints := make(map[string]influxdb.NotificationEndpoint) @@ -842,9 +857,9 @@ func (s *Service) dryRunNotificationRules(ctx context.Context, orgID influxdb.ID mPkgEndpoints[e.PkgName()] = influxEndpoint } - diffs := make([]DiffNotificationRule, 0, len(mExisting)) + diffs := make([]DiffNotificationRule, 0) for _, r := range pkg.notificationRules() { - e, ok := mExisting[r.endpointName.String()] + e, ok := mExistingEndpointsByName[r.endpointName.String()] if !ok { influxEndpoint, ok := mPkgEndpoints[r.endpointName.String()] if !ok { @@ -853,6 +868,20 @@ func (s *Service) dryRunNotificationRules(ctx context.Context, orgID influxdb.ID } e = influxEndpoint } + + if iRule, ok := mExistingRulesByID[r.ID()]; ok { + var endpointName, endpointType string + if e, ok := mExistingRulesByID[iRule.GetEndpointID()]; ok { + endpointName = e.GetName() + endpointType = e.Type() + } + r.existing = &existingRule{ + rule: iRule, + endpointName: endpointName, + endpointType: endpointType, + } + } + diffs = append(diffs, newDiffNotificationRule(r, e)) } @@ -1680,20 +1709,16 @@ func (s *Service) applyNotificationEndpoint(ctx context.Context, e notificationE return e.existing, nil } - if e.existing != nil { + if e.Exists() { // stub out userID since we're always using hte http client which will fill it in for us with the token // feels a bit broken that is required. // TODO: look into this userID requirement - updatedEndpoint, err := s.endpointSVC.UpdateNotificationEndpoint( + return s.endpointSVC.UpdateNotificationEndpoint( ctx, e.ID(), e.summarize().NotificationEndpoint, userID, ) - if err != nil { - return nil, err - } - return updatedEndpoint, nil } actual := e.summarize().NotificationEndpoint @@ -1745,9 +1770,9 @@ func (s *Service) applyNotificationRulesGenerator(ctx context.Context, orgID inf id influxdb.ID eType string } - mEndpoints := make(map[string]mVal) + mEndpointsByPkgName := make(map[string]mVal) for _, e := range endpoints { - mEndpoints[e.GetName()] = mVal{ + mEndpointsByPkgName[e.GetName()] = mVal{ id: e.GetID(), eType: e.Type(), } @@ -1757,10 +1782,10 @@ func (s *Service) applyNotificationRulesGenerator(ctx context.Context, orgID inf continue } - if _, ok := mEndpoints[e.PkgName()]; ok { + if _, ok := mEndpointsByPkgName[e.PkgName()]; ok { continue } - mEndpoints[e.PkgName()] = mVal{ + mEndpointsByPkgName[e.PkgName()] = mVal{ id: e.ID(), eType: e.summarize().NotificationEndpoint.Type(), } @@ -1770,11 +1795,11 @@ func (s *Service) applyNotificationRulesGenerator(ctx context.Context, orgID inf var errs applyErrs for _, r := range rules { - v, ok := mEndpoints[r.endpointName.String()] + v, ok := mEndpointsByPkgName[r.endpointName.String()] if !ok { errs = append(errs, &applyErrBody{ name: r.Name(), - msg: fmt.Sprintf("endpoint dependency does not exist; endpointName=%q", r.endpointName), + msg: fmt.Sprintf("notification rule endpoint dependency does not exist; endpointName=%q", r.endpointName), }) continue } diff --git a/pkger/service_test.go b/pkger/service_test.go index fb266c4e65f..a96888983f7 100644 --- a/pkger/service_test.go +++ b/pkger/service_test.go @@ -337,13 +337,12 @@ func TestService(t *testing.T) { require.Len(t, diff.NotificationRules, 1) - actual := diff.NotificationRules[0] + actual := diff.NotificationRules[0].New assert.Equal(t, "rule_0", actual.Name) assert.Equal(t, "desc_0", actual.Description) assert.Equal(t, "http", actual.EndpointType) assert.Equal(t, existing.Name, actual.EndpointName) assert.Equal(t, SafeID(*existing.ID), actual.EndpointID) - assert.Equal(t, influxdb.Active, actual.Status) assert.Equal(t, (10 * time.Minute).String(), actual.Every) assert.Equal(t, (30 * time.Second).String(), actual.Offset)