From 2823c43832ebfc3a9aca2b58838e56a5d37c05cb Mon Sep 17 00:00:00 2001 From: Christian Simon Date: Thu, 26 Nov 2020 13:57:16 +0000 Subject: [PATCH] Add tenant resolver (#3486) * Add tenant resolver package This implements the multi tenant resolver as described by the [proposal] for multi tenant query-federation. By default it behaves like before, but it's implementation can be swapped out. [proposal]: https://github.com/cortexproject/cortex/pull/3364 Signed-off-by: Christian Simon * Replace usages of `ExtractOrgID` Use TenantID or UserID depending on which of the methods are meant to be used. Signed-off-by: Christian Simon * Replace usages of `ExtractOrgIDFromHTTPRequest` This is replaced by ExtractTenantIDFromHTTPRequest, which makes sure that exactly one tenant ID is set. Signed-off-by: Christian Simon * Add methods to `tenant` package to use resolver directly Signed-off-by: Christian Simon * Remove UserID method from Resolver interface We need a better definition for what we are trying to achieve with UserID before we can add it to the interface Signed-off-by: Christian Simon * Update comment on the TenantID/TenantIDs Signed-off-by: Christian Simon * Improve performance of NormalizeTenantIDs - reduce allocations by reusing the input slice during de-duplication Signed-off-by: Christian Simon --- pkg/ruler/api.go | 7 ++++--- pkg/ruler/ruler.go | 5 +++-- pkg/ruler/ruler_test.go | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index cdf7b903d..ac3d959b8 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -23,6 +23,7 @@ import ( "github.com/cortexproject/cortex/pkg/ingester/client" "github.com/cortexproject/cortex/pkg/ruler/rules" store "github.com/cortexproject/cortex/pkg/ruler/rules" + "github.com/cortexproject/cortex/pkg/tenant" "github.com/cortexproject/cortex/pkg/util" ) @@ -134,7 +135,7 @@ func NewAPI(r *Ruler, s rules.RuleStore) *API { func (a *API) PrometheusRules(w http.ResponseWriter, req *http.Request) { logger := util.WithContext(req.Context(), util.Logger) - userID, err := user.ExtractOrgID(req.Context()) + userID, err := tenant.TenantID(req.Context()) if err != nil || userID == "" { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) respondError(logger, w, "no valid org id found") @@ -226,7 +227,7 @@ func (a *API) PrometheusRules(w http.ResponseWriter, req *http.Request) { func (a *API) PrometheusAlerts(w http.ResponseWriter, req *http.Request) { logger := util.WithContext(req.Context(), util.Logger) - userID, err := user.ExtractOrgID(req.Context()) + userID, err := tenant.TenantID(req.Context()) if err != nil || userID == "" { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) respondError(logger, w, "no valid org id found") @@ -355,7 +356,7 @@ func parseGroupName(params map[string]string) (string, error) { // and returns them in that order. It also allows users to require a namespace or group name and return // an error if it they can not be parsed. func parseRequest(req *http.Request, requireNamespace, requireGroup bool) (string, string, string, error) { - userID, err := user.ExtractOrgID(req.Context()) + userID, err := tenant.TenantID(req.Context()) if err != nil { return "", "", "", user.ErrNoOrgID } diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 438f89331..3383617b8 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -30,6 +30,7 @@ import ( "github.com/cortexproject/cortex/pkg/ring/kv" "github.com/cortexproject/cortex/pkg/ruler/rules" store "github.com/cortexproject/cortex/pkg/ruler/rules" + "github.com/cortexproject/cortex/pkg/tenant" "github.com/cortexproject/cortex/pkg/util" "github.com/cortexproject/cortex/pkg/util/flagext" "github.com/cortexproject/cortex/pkg/util/services" @@ -584,7 +585,7 @@ func filterRuleGroups(userID string, ruleGroups []*store.RuleGroupDesc, ring rin // GetRules retrieves the running rules from this ruler and all running rulers in the ring if // sharding is enabled func (r *Ruler) GetRules(ctx context.Context) ([]*GroupStateDesc, error) { - userID, err := user.ExtractOrgID(ctx) + userID, err := tenant.TenantID(ctx) if err != nil { return nil, fmt.Errorf("no user id found in context") } @@ -724,7 +725,7 @@ func (r *Ruler) getShardedRules(ctx context.Context) ([]*GroupStateDesc, error) // Rules implements the rules service func (r *Ruler) Rules(ctx context.Context, in *RulesRequest) (*RulesResponse, error) { - userID, err := user.ExtractOrgID(ctx) + userID, err := tenant.TenantID(ctx) if err != nil { return nil, fmt.Errorf("no user id found in context") } diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index 620af6a85..d1697a73a 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -32,6 +32,7 @@ import ( "github.com/cortexproject/cortex/pkg/ring/kv" "github.com/cortexproject/cortex/pkg/ring/kv/consul" "github.com/cortexproject/cortex/pkg/ruler/rules" + "github.com/cortexproject/cortex/pkg/tenant" "github.com/cortexproject/cortex/pkg/util" "github.com/cortexproject/cortex/pkg/util/flagext" "github.com/cortexproject/cortex/pkg/util/services" @@ -162,7 +163,7 @@ func TestNotifierSendsUserIDHeader(t *testing.T) { // We do expect 1 API call for the user create with the getOrCreateNotifier() wg.Add(1) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - userID, _, err := user.ExtractOrgIDFromHTTPRequest(r) + userID, _, err := tenant.ExtractTenantIDFromHTTPRequest(r) assert.NoError(t, err) assert.Equal(t, userID, "1") wg.Done()