Skip to content

Commit

Permalink
chore: refactor notication endpoints to make a service out of notific…
Browse files Browse the repository at this point in the history
…ation endpoints

this is a blocker for anyone who hits the endpoint services internally. They
had to know that they need to also know of hte secret service then do all that
put/delete alongside the operation. This makes that unified inside the store tx.

one other thing this does is make obvious the dependencies that
notification services has. In this case it is the secrets service it
depends on.
  • Loading branch information
jsteenb2 committed Dec 17, 2019
1 parent 09f2f40 commit a6e768d
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 361 deletions.
45 changes: 23 additions & 22 deletions cmd/influxd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/influxdata/influxdb/bolt"
"github.com/influxdata/influxdb/chronograf/server"
"github.com/influxdata/influxdb/cmd/influxd/inspect"
"github.com/influxdata/influxdb/endpoints"
"github.com/influxdata/influxdb/gather"
"github.com/influxdata/influxdb/http"
"github.com/influxdata/influxdb/inmem"
Expand Down Expand Up @@ -524,27 +525,27 @@ func (m *Launcher) run(ctx context.Context) (err error) {
m.reg.MustRegister(m.boltClient)

var (
orgSvc platform.OrganizationService = m.kvService
authSvc platform.AuthorizationService = m.kvService
userSvc platform.UserService = m.kvService
variableSvc platform.VariableService = m.kvService
bucketSvc platform.BucketService = m.kvService
sourceSvc platform.SourceService = m.kvService
sessionSvc platform.SessionService = m.kvService
passwdsSvc platform.PasswordsService = m.kvService
dashboardSvc platform.DashboardService = m.kvService
dashboardLogSvc platform.DashboardOperationLogService = m.kvService
userLogSvc platform.UserOperationLogService = m.kvService
bucketLogSvc platform.BucketOperationLogService = m.kvService
orgLogSvc platform.OrganizationOperationLogService = m.kvService
onboardingSvc platform.OnboardingService = m.kvService
scraperTargetSvc platform.ScraperTargetStoreService = m.kvService
telegrafSvc platform.TelegrafConfigStore = m.kvService
userResourceSvc platform.UserResourceMappingService = m.kvService
labelSvc platform.LabelService = m.kvService
secretSvc platform.SecretService = m.kvService
lookupSvc platform.LookupService = m.kvService
notificationEndpointSvc platform.NotificationEndpointService = m.kvService
orgSvc platform.OrganizationService = m.kvService
authSvc platform.AuthorizationService = m.kvService
userSvc platform.UserService = m.kvService
variableSvc platform.VariableService = m.kvService
bucketSvc platform.BucketService = m.kvService
sourceSvc platform.SourceService = m.kvService
sessionSvc platform.SessionService = m.kvService
passwdsSvc platform.PasswordsService = m.kvService
dashboardSvc platform.DashboardService = m.kvService
dashboardLogSvc platform.DashboardOperationLogService = m.kvService
userLogSvc platform.UserOperationLogService = m.kvService
bucketLogSvc platform.BucketOperationLogService = m.kvService
orgLogSvc platform.OrganizationOperationLogService = m.kvService
onboardingSvc platform.OnboardingService = m.kvService
scraperTargetSvc platform.ScraperTargetStoreService = m.kvService
telegrafSvc platform.TelegrafConfigStore = m.kvService
userResourceSvc platform.UserResourceMappingService = m.kvService
labelSvc platform.LabelService = m.kvService
secretSvc platform.SecretService = m.kvService
lookupSvc platform.LookupService = m.kvService
notificationEndpointStore platform.NotificationEndpointService = m.kvService
)

switch m.secretStore {
Expand Down Expand Up @@ -818,7 +819,7 @@ func (m *Launcher) run(ctx context.Context) (err error) {
TaskService: taskSvc,
TelegrafService: telegrafSvc,
NotificationRuleStore: notificationRuleSvc,
NotificationEndpointService: notificationEndpointSvc,
NotificationEndpointService: endpoints.NewService(notificationEndpointStore, secretSvc, userResourceSvc, orgSvc),
CheckService: checkSvc,
ScraperTargetStoreService: scraperTargetSvc,
ChronografService: chronografSvc,
Expand Down
98 changes: 98 additions & 0 deletions endpoints/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package endpoints

import (
"context"

"github.com/influxdata/influxdb"
)

// Service provides all the notification endpoint service behavior.
type Service struct {
endpointStore influxdb.NotificationEndpointService
secretSVC influxdb.SecretService

// TODO(jsteenb2): NUKE THESE 2 embedded services after fixing up the domain!
influxdb.UserResourceMappingService
influxdb.OrganizationService
}

// NewService constructs a new Service.
func NewService(store influxdb.NotificationEndpointService, secretSVC influxdb.SecretService, urmSVC influxdb.UserResourceMappingService, orgSVC influxdb.OrganizationService) *Service {
return &Service{
endpointStore: store,
secretSVC: secretSVC,
UserResourceMappingService: urmSVC,
OrganizationService: orgSVC,
}
}

var _ influxdb.NotificationEndpointService = (*Service)(nil)

// FindNotificationEndpointByID returns a single notification endpoint by ID.
func (s *Service) FindNotificationEndpointByID(ctx context.Context, id influxdb.ID) (influxdb.NotificationEndpoint, error) {
return s.endpointStore.FindNotificationEndpointByID(ctx, id)
}

// FindNotificationEndpoints returns a list of notification endpoints that match filter and the total count of matching notification endpoints.
// Additional options provide pagination & sorting.
func (s *Service) FindNotificationEndpoints(ctx context.Context, filter influxdb.NotificationEndpointFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationEndpoint, int, error) {
return s.endpointStore.FindNotificationEndpoints(ctx, filter, opt...)
}

// CreateNotificationEndpoint creates a new notification endpoint and sets b.ID with the new identifier.
func (s *Service) CreateNotificationEndpoint(ctx context.Context, edp influxdb.NotificationEndpoint, userID influxdb.ID) error {
err := s.endpointStore.CreateNotificationEndpoint(ctx, edp, userID)
if err != nil {
return err
}

secrets := make(map[string]string)
for _, fld := range edp.SecretFields() {
if fld.Value != nil {
secrets[fld.Key] = *fld.Value
}
}
if len(secrets) == 0 {
return nil
}

return s.secretSVC.PutSecrets(ctx, edp.GetOrgID(), secrets)
}

// UpdateNotificationEndpoint updates a single notification endpoint.
// Returns the new notification endpoint after update.
func (s *Service) UpdateNotificationEndpoint(ctx context.Context, id influxdb.ID, nr influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) {
nr.BackfillSecretKeys() // :sadpanda:
updatedEndpoint, err := s.endpointStore.UpdateNotificationEndpoint(ctx, id, nr, userID)
if err != nil {
return nil, err
}

secrets := make(map[string]string)
for _, fld := range updatedEndpoint.SecretFields() {
if fld.Value != nil {
secrets[fld.Key] = *fld.Value
}
}

if len(secrets) == 0 {
return updatedEndpoint, nil
}

if err := s.secretSVC.PutSecrets(ctx, updatedEndpoint.GetOrgID(), secrets); err != nil {
return nil, err
}

return updatedEndpoint, nil
}

// PatchNotificationEndpoint updates a single notification endpoint with changeset.
// Returns the new notification endpoint state after update.
func (s *Service) PatchNotificationEndpoint(ctx context.Context, id influxdb.ID, upd influxdb.NotificationEndpointUpdate) (influxdb.NotificationEndpoint, error) {
return s.endpointStore.PatchNotificationEndpoint(ctx, id, upd)
}

// DeleteNotificationEndpoint removes a notification endpoint by ID, returns secret fields, orgID for further deletion.
func (s *Service) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
return s.endpointStore.DeleteNotificationEndpoint(ctx, id)
}
3 changes: 2 additions & 1 deletion http/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1882,7 +1882,6 @@ func TestService_handlePostDashboardLabel(t *testing.T) {
}

func jsonEqual(s1, s2 string) (eq bool, diff string, err error) {
var o1, o2 interface{}
if s1 == s2 {
return true, "", nil
}
Expand All @@ -1895,10 +1894,12 @@ func jsonEqual(s1, s2 string) (eq bool, diff string, err error) {
return false, s1, fmt.Errorf("s2 is empty")
}

var o1 interface{}
if err = json.Unmarshal([]byte(s1), &o1); err != nil {
return
}

var o2 interface{}
if err = json.Unmarshal([]byte(s2), &o2); err != nil {
return
}
Expand Down
61 changes: 12 additions & 49 deletions http/notification_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

"github.com/influxdata/httprouter"
Expand All @@ -26,7 +27,6 @@ type NotificationEndpointBackend struct {
LabelService influxdb.LabelService
UserService influxdb.UserService
OrganizationService influxdb.OrganizationService
SecretService influxdb.SecretService
}

// NewNotificationEndpointBackend returns a new instance of NotificationEndpointBackend.
Expand All @@ -40,7 +40,6 @@ func NewNotificationEndpointBackend(log *zap.Logger, b *APIBackend) *Notificatio
LabelService: b.LabelService,
UserService: b.UserService,
OrganizationService: b.OrganizationService,
SecretService: b.SecretService,
}
}

Expand All @@ -59,7 +58,6 @@ type NotificationEndpointHandler struct {
LabelService influxdb.LabelService
UserService influxdb.UserService
OrganizationService influxdb.OrganizationService
SecretService influxdb.SecretService
}

const (
Expand All @@ -85,7 +83,6 @@ func NewNotificationEndpointHandler(log *zap.Logger, b *NotificationEndpointBack
LabelService: b.LabelService,
UserService: b.UserService,
OrganizationService: b.OrganizationService,
SecretService: b.SecretService,
}
h.HandlerFunc("POST", prefixNotificationEndpoints, h.handlePostNotificationEndpoint)
h.HandlerFunc("GET", prefixNotificationEndpoints, h.handleGetNotificationEndpoints)
Expand Down Expand Up @@ -307,36 +304,34 @@ func decodeNotificationEndpointFilter(ctx context.Context, r *http.Request) (inf
}

func decodePostNotificationEndpointRequest(r *http.Request) (postNotificationEndpointRequest, error) {
var req postNotificationEndpointRequest
buf := new(bytes.Buffer)
_, err := buf.ReadFrom(r.Body)
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return req, &influxdb.Error{
return postNotificationEndpointRequest{}, &influxdb.Error{
Code: influxdb.EInvalid,
Err: err,
}
}
defer r.Body.Close()
edp, err := endpoint.UnmarshalJSON(buf.Bytes())
edp, err := endpoint.UnmarshalJSON(b)
if err != nil {
return req, &influxdb.Error{
return postNotificationEndpointRequest{}, &influxdb.Error{
Code: influxdb.EInvalid,
Err: err,
}
}

var dl decodeLabels
if err := json.Unmarshal(buf.Bytes(), &dl); err != nil {
return req, &influxdb.Error{
if err := json.Unmarshal(b, &dl); err != nil {
return postNotificationEndpointRequest{}, &influxdb.Error{
Code: influxdb.EInvalid,
Err: err,
}
}

req.NotificationEndpoint = edp
req.Labels = dl.Labels

return req, nil
return postNotificationEndpointRequest{
NotificationEndpoint: edp,
Labels: dl.Labels,
}, nil
}

func decodePutNotificationEndpointRequest(ctx context.Context, r *http.Request) (influxdb.NotificationEndpoint, error) {
Expand Down Expand Up @@ -419,18 +414,6 @@ func (h *NotificationEndpointHandler) handlePostNotificationEndpoint(w http.Resp
h.HandleHTTPError(ctx, err, w)
return
}
for _, fld := range edp.SecretFields() {
if fld.Value != nil {
if err := h.SecretService.PutSecret(ctx, edp.GetOrgID(),
fld.Key, *fld.Value); err != nil {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handlePostNotificationEndpoint",
Err: err,
}, w)
return
}
}
}

labels := h.mapNewNotificationEndpointLabels(ctx, edp.NotificationEndpoint, edp.Labels)

Expand Down Expand Up @@ -494,19 +477,6 @@ func (h *NotificationEndpointHandler) handlePutNotificationEndpoint(w http.Respo
return
}

for _, fld := range edp.SecretFields() {
if fld.Value != nil {
if err := h.SecretService.PutSecret(ctx, edp.GetOrgID(),
fld.Key, *fld.Value); err != nil {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handlePutNotificationEndpoint",
Err: err,
}, w)
return
}
}
}

labels, err := h.LabelService.FindResourceLabels(ctx, influxdb.LabelMappingFilter{ResourceID: edp.GetID()})
if err != nil {
h.HandleHTTPError(ctx, err, w)
Expand Down Expand Up @@ -557,7 +527,7 @@ func (h *NotificationEndpointHandler) handleDeleteNotificationEndpoint(w http.Re
return
}

flds, orgID, err := h.NotificationEndpointService.DeleteNotificationEndpoint(ctx, i)
flds, _, err := h.NotificationEndpointService.DeleteNotificationEndpoint(ctx, i)
if err != nil {
h.HandleHTTPError(ctx, err, w)
return
Expand All @@ -573,13 +543,6 @@ func (h *NotificationEndpointHandler) handleDeleteNotificationEndpoint(w http.Re
}
keys[k] = fld.Key
}
if err := h.SecretService.DeleteSecret(ctx, orgID, keys...); err != nil {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handleDeleteNotificationEndpoint",
Err: err,
}, w)
return
}
h.log.Debug("NotificationEndpoint deleted", zap.String("notificationEndpointID", fmt.Sprint(i)))

w.WriteHeader(http.StatusNoContent)
Expand Down
Loading

0 comments on commit a6e768d

Please sign in to comment.