Skip to content

Commit

Permalink
refactor: add new label package (#18078)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlirieGray authored May 21, 2020
1 parent 5ac45cc commit 7f4ddab
Show file tree
Hide file tree
Showing 36 changed files with 3,774 additions and 157 deletions.
41 changes: 3 additions & 38 deletions authorization/middleware_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package authorization

import (
"context"
"fmt"

"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/metric"
Expand All @@ -18,10 +17,10 @@ type AuthMetrics struct {

var _ influxdb.AuthorizationService = (*AuthMetrics)(nil)

func NewAuthMetrics(reg prometheus.Registerer, s influxdb.AuthorizationService, opts ...MetricsOption) *AuthMetrics {
o := applyOpts(opts...)
func NewAuthMetrics(reg prometheus.Registerer, s influxdb.AuthorizationService, opts ...metric.MetricsOption) *AuthMetrics {
o := metric.ApplyMetricOpts(opts...)
return &AuthMetrics{
rec: metric.New(reg, o.applySuffix("token")),
rec: metric.New(reg, o.ApplySuffix("token")),
authService: s,
}
}
Expand Down Expand Up @@ -59,37 +58,3 @@ func (m *AuthMetrics) DeleteAuthorization(ctx context.Context, id influxdb.ID) e
err := m.authService.DeleteAuthorization(ctx, id)
return rec(err)
}

// Metrics options
type metricOpts struct {
serviceSuffix string
}

func defaultOpts() *metricOpts {
return &metricOpts{}
}

func (o *metricOpts) applySuffix(prefix string) string {
if o.serviceSuffix != "" {
return fmt.Sprintf("%s_%s", prefix, o.serviceSuffix)
}
return prefix
}

// MetricsOption is an option used by a metric middleware.
type MetricsOption func(*metricOpts)

// WithSuffix returns a metric option that applies a suffix to the service name of the metric.
func WithSuffix(suffix string) MetricsOption {
return func(opts *metricOpts) {
opts.serviceSuffix = suffix
}
}

func applyOpts(opts ...MetricsOption) *metricOpts {
o := defaultOpts()
for _, opt := range opts {
opt(o)
}
return o
}
2 changes: 1 addition & 1 deletion authorization/storage_authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"encoding/json"

"github.com/buger/jsonparser"
influxdb "github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kv"
jsonp "github.com/influxdata/influxdb/v2/pkg/jsonparser"
)
Expand Down
13 changes: 7 additions & 6 deletions cmd/influxd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/influxdata/influxdb/v2/kit/cli"
"github.com/influxdata/influxdb/v2/kit/feature"
overrideflagger "github.com/influxdata/influxdb/v2/kit/feature/override"
"github.com/influxdata/influxdb/v2/kit/metric"
"github.com/influxdata/influxdb/v2/kit/prom"
"github.com/influxdata/influxdb/v2/kit/signals"
"github.com/influxdata/influxdb/v2/kit/tracing"
Expand Down Expand Up @@ -617,11 +618,11 @@ func (m *Launcher) run(ctx context.Context) (err error) {

if m.enableNewMetaStore {
ts := tenant.NewService(store)
userSvc = tenant.NewUserLogger(m.log.With(zap.String("store", "new")), tenant.NewUserMetrics(m.reg, ts, tenant.WithSuffix("new")))
orgSvc = tenant.NewOrgLogger(m.log.With(zap.String("store", "new")), tenant.NewOrgMetrics(m.reg, ts, tenant.WithSuffix("new")))
userResourceSvc = tenant.NewURMLogger(m.log.With(zap.String("store", "new")), tenant.NewUrmMetrics(m.reg, ts, tenant.WithSuffix("new")))
bucketSvc = tenant.NewBucketLogger(m.log.With(zap.String("store", "new")), tenant.NewBucketMetrics(m.reg, ts, tenant.WithSuffix("new")))
passwdsSvc = tenant.NewPasswordLogger(m.log.With(zap.String("store", "new")), tenant.NewPasswordMetrics(m.reg, ts, tenant.WithSuffix("new")))
userSvc = tenant.NewUserLogger(m.log.With(zap.String("store", "new")), tenant.NewUserMetrics(m.reg, ts, metric.WithSuffix("new")))
orgSvc = tenant.NewOrgLogger(m.log.With(zap.String("store", "new")), tenant.NewOrgMetrics(m.reg, ts, metric.WithSuffix("new")))
userResourceSvc = tenant.NewURMLogger(m.log.With(zap.String("store", "new")), tenant.NewUrmMetrics(m.reg, ts, metric.WithSuffix("new")))
bucketSvc = tenant.NewBucketLogger(m.log.With(zap.String("store", "new")), tenant.NewBucketMetrics(m.reg, ts, metric.WithSuffix("new")))
passwdsSvc = tenant.NewPasswordLogger(m.log.With(zap.String("store", "new")), tenant.NewPasswordMetrics(m.reg, ts, metric.WithSuffix("new")))
}

switch m.secretStore {
Expand Down Expand Up @@ -969,7 +970,7 @@ func (m *Launcher) run(ctx context.Context) (err error) {
{
onboardSvc := tenant.NewOnboardService(store, authSvc) // basic service
onboardSvc = tenant.NewAuthedOnboardSvc(onboardSvc) // with auth
onboardSvc = tenant.NewOnboardingMetrics(m.reg, onboardSvc, tenant.WithSuffix("new")) // with metrics
onboardSvc = tenant.NewOnboardingMetrics(m.reg, onboardSvc, metric.WithSuffix("new")) // with metrics
onboardSvc = tenant.NewOnboardingLogger(m.log.With(zap.String("handler", "onboard")), onboardSvc) // with logging

onboardHTTPServer = tenant.NewHTTPOnboardHandler(m.log, onboardSvc)
Expand Down
9 changes: 9 additions & 0 deletions id.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ var (
}
)

// ErrCorruptID means the ID stored in the Store is corrupt.
func ErrCorruptID(err error) *Error {
return &Error{
Code: EInvalid,
Msg: "corrupt ID provided",
Err: err,
}
}

// ID is a unique identifier.
//
// Its zero value is not a valid ID.
Expand Down
6 changes: 3 additions & 3 deletions tenant/metrics_options.go → kit/metric/metrics_options.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tenant
package metric

import "fmt"

Expand All @@ -10,7 +10,7 @@ func defaultOpts() *metricOpts {
return &metricOpts{}
}

func (o *metricOpts) applySuffix(prefix string) string {
func (o *metricOpts) ApplySuffix(prefix string) string {
if o.serviceSuffix != "" {
return fmt.Sprintf("%s_%s", prefix, o.serviceSuffix)
}
Expand All @@ -27,7 +27,7 @@ func WithSuffix(suffix string) MetricsOption {
}
}

func applyOpts(opts ...MetricsOption) *metricOpts {
func ApplyMetricOpts(opts ...MetricsOption) *metricOpts {
o := defaultOpts()
for _, opt := range opts {
opt(o)
Expand Down
42 changes: 42 additions & 0 deletions kit/transport/http/middleware.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package http

import (
"context"
"net/http"
"path"
"strings"
"time"

"github.com/go-chi/chi"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/tracing"
ua "github.com/mileusna/useragent"
Expand Down Expand Up @@ -130,3 +132,43 @@ func shiftPath(p string) (head, tail string) {
}
return p[1:i], p[i:]
}

type OrgContext string

const CtxOrgKey OrgContext = "orgID"

// ValidResource make sure a resource exists when a sub system needs to be mounted to an api
func ValidResource(api *API, lookupOrgByResourceID func(context.Context, influxdb.ID) (influxdb.ID, error)) Middleware {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
statusW := NewStatusResponseWriter(w)
id, err := influxdb.IDFromString(chi.URLParam(r, "id"))
if err != nil {
api.Err(w, r, influxdb.ErrCorruptID(err))
return
}

ctx := r.Context()

orgID, err := lookupOrgByResourceID(ctx, *id)
if err != nil {
api.Err(w, r, err)
return
}

// embed OrgID into context
next.ServeHTTP(statusW, r.WithContext(context.WithValue(ctx, CtxOrgKey, orgID)))
}
return http.HandlerFunc(fn)
}
}

// OrgIDFromContext ....
func OrgIDFromContext(ctx context.Context) *influxdb.ID {
v := ctx.Value(CtxOrgKey)
if v == nil {
return nil
}
id := v.(influxdb.ID)
return &id
}
8 changes: 8 additions & 0 deletions kv/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,14 @@ func (s *Service) PutLabel(ctx context.Context, l *influxdb.Label) error {
})
}

// CreateUserResourceMappingForOrg is a public function that calls createUserResourceMappingForOrg used only for the label service
// it can be removed when URMs are removed from the label service
func (s *Service) CreateUserResourceMappingForOrg(ctx context.Context, tx Tx, orgID influxdb.ID, resID influxdb.ID, resType influxdb.ResourceType) error {
err := s.createUserResourceMappingForOrg(ctx, tx, orgID, resID, resType)

return err
}

func (s *Service) createUserResourceMappingForOrg(ctx context.Context, tx Tx, orgID influxdb.ID, resID influxdb.ID, resType influxdb.ResourceType) error {
span, ctx := tracing.StartSpanFromContext(ctx)
defer span.Finish()
Expand Down
34 changes: 34 additions & 0 deletions label/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package label

import (
"github.com/influxdata/influxdb/v2"
)

var (
// NotUniqueIDError occurs when attempting to create a Label with an ID that already belongs to another one
NotUniqueIDError = &influxdb.Error{
Code: influxdb.EConflict,
Msg: "ID already exists",
}

// ErrFailureGeneratingID occurs ony when the random number generator
// cannot generate an ID in MaxIDGenerationN times.
ErrFailureGeneratingID = &influxdb.Error{
Code: influxdb.EInternal,
Msg: "unable to generate valid id",
}

// ErrLabelNotFound occurs when a label cannot be found by its ID
ErrLabelNotFound = &influxdb.Error{
Code: influxdb.ENotFound,
Msg: "label not found",
}
)

// ErrInternalServiceError is used when the error comes from an internal system.
func ErrInternalServiceError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Err: err,
}
}
135 changes: 135 additions & 0 deletions label/http_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package label

import (
"context"
"path"

"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/pkg/httpc"
)

var _ influxdb.LabelService = (*LabelClientService)(nil)

type LabelClientService struct {
Client *httpc.Client
}

func labelIDPath(id influxdb.ID) string {
return path.Join(prefixLabels, id.String())
}

func resourceIDPath(resourceType influxdb.ResourceType, resourceID influxdb.ID, p string) string {
return path.Join("/api/v2/", string(resourceType), resourceID.String(), p)
}

// CreateLabel creates a new label.
func (s *LabelClientService) CreateLabel(ctx context.Context, l *influxdb.Label) error {
var lr labelResponse
err := s.Client.
PostJSON(l, prefixLabels).
DecodeJSON(&lr).
Do(ctx)
if err != nil {
return err
}

*l = lr.Label
return nil
}

// FindLabelByID returns a single label by ID.
func (s *LabelClientService) FindLabelByID(ctx context.Context, id influxdb.ID) (*influxdb.Label, error) {
var lr labelResponse
err := s.Client.
Get(labelIDPath(id)).
DecodeJSON(&lr).
Do(ctx)
if err != nil {
return nil, err
}
return &lr.Label, nil
}

// FindLabels is a client for the find labels response from the server.
func (s *LabelClientService) FindLabels(ctx context.Context, filter influxdb.LabelFilter, opt ...influxdb.FindOptions) ([]*influxdb.Label, error) {
params := influxdb.FindOptionParams(opt...)
if filter.OrgID != nil {
params = append(params, [2]string{"orgID", filter.OrgID.String()})
}
if filter.Name != "" {
params = append(params, [2]string{"name", filter.Name})
}

var lr labelsResponse
err := s.Client.
Get(prefixLabels).
QueryParams(params...).
DecodeJSON(&lr).
Do(ctx)
if err != nil {
return nil, err
}
return lr.Labels, nil
}

// FindResourceLabels returns a list of labels, derived from a label mapping filter.
func (s *LabelClientService) FindResourceLabels(ctx context.Context, filter influxdb.LabelMappingFilter) ([]*influxdb.Label, error) {
if err := filter.Valid(); err != nil {
return nil, err
}

var r labelsResponse
err := s.Client.
Get(resourceIDPath(filter.ResourceType, filter.ResourceID, "labels")).
DecodeJSON(&r).
Do(ctx)
if err != nil {
return nil, err
}
return r.Labels, nil
}

// UpdateLabel updates a label and returns the updated label.
func (s *LabelClientService) UpdateLabel(ctx context.Context, id influxdb.ID, upd influxdb.LabelUpdate) (*influxdb.Label, error) {
var lr labelResponse
err := s.Client.
PatchJSON(upd, labelIDPath(id)).
DecodeJSON(&lr).
Do(ctx)
if err != nil {
return nil, err
}
return &lr.Label, nil
}

// DeleteLabel removes a label by ID.
func (s *LabelClientService) DeleteLabel(ctx context.Context, id influxdb.ID) error {
return s.Client.
Delete(labelIDPath(id)).
Do(ctx)
}

// ******* Label Mappings ******* //

// CreateLabelMapping will create a labbel mapping
func (s *LabelClientService) CreateLabelMapping(ctx context.Context, m *influxdb.LabelMapping) error {
if err := m.Validate(); err != nil {
return err
}

urlPath := resourceIDPath(m.ResourceType, m.ResourceID, "labels")
return s.Client.
PostJSON(m, urlPath).
DecodeJSON(m).
Do(ctx)
}

func (s *LabelClientService) DeleteLabelMapping(ctx context.Context, m *influxdb.LabelMapping) error {
if err := m.Validate(); err != nil {
return err
}

return s.Client.
Delete(resourceIDPath(m.ResourceType, m.ResourceID, "labels")).
Do(ctx)
}
Loading

0 comments on commit 7f4ddab

Please sign in to comment.