diff --git a/component/mimir/rules/debug.go b/component/mimir/rules/debug.go index 29cfcddc7c28..59b5103858dc 100644 --- a/component/mimir/rules/debug.go +++ b/component/mimir/rules/debug.go @@ -4,20 +4,20 @@ import "fmt" type DebugInfo struct { Error string `river:"error,attr,optional"` - PrometheusRules []DebugK8sPrometheusRule `river:"prometheusRules,attr,optional"` - MimirRuleNamespaces []DebugMimirNamespace `river:"mimirRuleNamespaces,attr,optional"` + PrometheusRules []DebugK8sPrometheusRule `river:"prometheus_rule,block,optional"` + MimirRuleNamespaces []DebugMimirNamespace `river:"mimir_rule_namespace,block,optional"` } type DebugK8sPrometheusRule struct { Namespace string `river:"namespace,attr"` Name string `river:"name,attr"` UID string `river:"uid,attr"` - NumRuleGroups int `river:"numRuleGroups,attr"` + NumRuleGroups int `river:"num_rule_groups,attr"` } type DebugMimirNamespace struct { Name string `river:"name,attr"` - NumRuleGroups int `river:"numRuleGroups,attr"` + NumRuleGroups int `river:"num_rule_groups,attr"` } func (c *Component) DebugInfo() interface{} { diff --git a/component/mimir/rules/diff.go b/component/mimir/rules/diff.go index 9739b582ce73..1a29233f221e 100644 --- a/component/mimir/rules/diff.go +++ b/component/mimir/rules/diff.go @@ -8,24 +8,24 @@ import ( "gopkg.in/yaml.v3" ) -type RuleGroupDiffKind string +type ruleGroupDiffKind string const ( - RuleGroupDiffKindAdd RuleGroupDiffKind = "add" - RuleGroupDiffKindRemove RuleGroupDiffKind = "remove" - RuleGroupDiffKindUpdate RuleGroupDiffKind = "update" + ruleGroupDiffKindAdd ruleGroupDiffKind = "add" + ruleGroupDiffKindRemove ruleGroupDiffKind = "remove" + ruleGroupDiffKindUpdate ruleGroupDiffKind = "update" ) -type RuleGroupDiff struct { - Kind RuleGroupDiffKind +type ruleGroupDiff struct { + Kind ruleGroupDiffKind Actual mimirClient.RuleGroup Desired mimirClient.RuleGroup } -func diffRuleState(desired map[string][]mimirClient.RuleGroup, actual map[string][]mimirClient.RuleGroup) (map[string][]RuleGroupDiff, error) { +func diffRuleState(desired map[string][]mimirClient.RuleGroup, actual map[string][]mimirClient.RuleGroup) (map[string][]ruleGroupDiff, error) { seen := map[string]bool{} - diff := make(map[string][]RuleGroupDiff) + diff := make(map[string][]ruleGroupDiff) for namespace, desiredRuleGroups := range desired { seen[namespace] = true @@ -59,8 +59,8 @@ func diffRuleState(desired map[string][]mimirClient.RuleGroup, actual map[string return diff, nil } -func diffRuleNamespaceState(desired []mimirClient.RuleGroup, actual []mimirClient.RuleGroup) ([]RuleGroupDiff, error) { - var diff []RuleGroupDiff +func diffRuleNamespaceState(desired []mimirClient.RuleGroup, actual []mimirClient.RuleGroup) ([]ruleGroupDiff, error) { + var diff []ruleGroupDiff seenGroups := map[string]bool{} @@ -74,8 +74,8 @@ desiredGroups: continue desiredGroups } - diff = append(diff, RuleGroupDiff{ - Kind: RuleGroupDiffKindUpdate, + diff = append(diff, ruleGroupDiff{ + Kind: ruleGroupDiffKindUpdate, Actual: actualRuleGroup, Desired: desiredRuleGroup, }) @@ -83,8 +83,8 @@ desiredGroups: } } - diff = append(diff, RuleGroupDiff{ - Kind: RuleGroupDiffKindAdd, + diff = append(diff, ruleGroupDiff{ + Kind: ruleGroupDiffKindAdd, Desired: desiredRuleGroup, }) } @@ -94,8 +94,8 @@ desiredGroups: continue } - diff = append(diff, RuleGroupDiff{ - Kind: RuleGroupDiffKindRemove, + diff = append(diff, ruleGroupDiff{ + Kind: ruleGroupDiffKindRemove, Actual: actualRuleGroup, }) } diff --git a/component/mimir/rules/diff_test.go b/component/mimir/rules/diff_test.go index 9cab0daac863..54da1a4bd8a0 100644 --- a/component/mimir/rules/diff_test.go +++ b/component/mimir/rules/diff_test.go @@ -47,7 +47,7 @@ groups: name string desired map[string][]mimirClient.RuleGroup actual map[string][]mimirClient.RuleGroup - expected map[string][]RuleGroupDiff + expected map[string][]ruleGroupDiff } testCases := []testCase{ @@ -55,7 +55,7 @@ groups: name: "empty sets", desired: map[string][]mimirClient.RuleGroup{}, actual: map[string][]mimirClient.RuleGroup{}, - expected: map[string][]RuleGroupDiff{}, + expected: map[string][]ruleGroupDiff{}, }, { name: "add rule group", @@ -63,10 +63,10 @@ groups: managedNamespace: ruleGroupsA, }, actual: map[string][]mimirClient.RuleGroup{}, - expected: map[string][]RuleGroupDiff{ + expected: map[string][]ruleGroupDiff{ managedNamespace: { { - Kind: RuleGroupDiffKindAdd, + Kind: ruleGroupDiffKindAdd, Desired: ruleGroupsA[0], }, }, @@ -78,10 +78,10 @@ groups: actual: map[string][]mimirClient.RuleGroup{ managedNamespace: ruleGroupsA, }, - expected: map[string][]RuleGroupDiff{ + expected: map[string][]ruleGroupDiff{ managedNamespace: { { - Kind: RuleGroupDiffKindRemove, + Kind: ruleGroupDiffKindRemove, Actual: ruleGroupsA[0], }, }, @@ -95,10 +95,10 @@ groups: actual: map[string][]mimirClient.RuleGroup{ managedNamespace: ruleGroupsAModified, }, - expected: map[string][]RuleGroupDiff{ + expected: map[string][]ruleGroupDiff{ managedNamespace: { { - Kind: RuleGroupDiffKindUpdate, + Kind: ruleGroupDiffKindUpdate, Desired: ruleGroupsA[0], Actual: ruleGroupsAModified[0], }, @@ -113,7 +113,7 @@ groups: actual: map[string][]mimirClient.RuleGroup{ managedNamespace: ruleGroupsA, }, - expected: map[string][]RuleGroupDiff{}, + expected: map[string][]ruleGroupDiff{}, }, } @@ -126,16 +126,16 @@ groups: } } -func requireEqualRuleDiffs(t *testing.T, expected, actual map[string][]RuleGroupDiff) { +func requireEqualRuleDiffs(t *testing.T, expected, actual map[string][]ruleGroupDiff) { require.Equal(t, len(expected), len(actual)) - var summarizeDiff = func(diff RuleGroupDiff) string { + var summarizeDiff = func(diff ruleGroupDiff) string { switch diff.Kind { - case RuleGroupDiffKindAdd: + case ruleGroupDiffKindAdd: return fmt.Sprintf("add: %s", diff.Desired.Name) - case RuleGroupDiffKindRemove: + case ruleGroupDiffKindRemove: return fmt.Sprintf("remove: %s", diff.Actual.Name) - case RuleGroupDiffKindUpdate: + case ruleGroupDiffKindUpdate: return fmt.Sprintf("update: %s", diff.Desired.Name) } panic("unreachable") diff --git a/component/mimir/rules/events.go b/component/mimir/rules/events.go index 876f4acefaa8..20ad767577b5 100644 --- a/component/mimir/rules/events.go +++ b/component/mimir/rules/events.go @@ -17,26 +17,29 @@ import ( // This type must be hashable, so it is kept simple. The indexer will maintain a // cache of current state, so this is mostly used for logging. -type Event struct { - Type EventType - ObjectKey string +type event struct { + typ eventType + objectKey string } -type EventType string +type eventType string const ( - EventTypeResourceChanged EventType = "resource-changed" - EventTypeSyncMimir EventType = "sync-mimir" + eventTypeResourceChanged eventType = "resource-changed" + eventTypeSyncMimir eventType = "sync-mimir" ) +// OnAdd implements the cache.ResourceEventHandler interface. func (c *Component) OnAdd(obj interface{}) { c.publishEvent(obj) } +// OnUpdate implements the cache.ResourceEventHandler interface. func (c *Component) OnUpdate(oldObj, newObj interface{}) { c.publishEvent(newObj) } +// OnDelete implements the cache.ResourceEventHandler interface. func (c *Component) OnDelete(obj interface{}) { c.publishEvent(obj) } @@ -48,29 +51,29 @@ func (c *Component) publishEvent(obj interface{}) { return } - c.queue.AddRateLimited(Event{ - Type: EventTypeResourceChanged, - ObjectKey: key, + c.queue.AddRateLimited(event{ + typ: eventTypeResourceChanged, + objectKey: key, }) } func (c *Component) eventLoop(ctx context.Context) { for { - event, shutdown := c.queue.Get() + eventInterface, shutdown := c.queue.Get() if shutdown { level.Info(c.log).Log("msg", "shutting down event loop") return } - evt := event.(Event) - c.metrics.eventsTotal.WithLabelValues(string(evt.Type)).Inc() + evt := eventInterface.(event) + c.metrics.eventsTotal.WithLabelValues(string(evt.typ)).Inc() err := c.processEvent(ctx, evt) if err != nil { - retries := c.queue.NumRequeues(event) + retries := c.queue.NumRequeues(evt) if retries < 5 { - c.metrics.eventsRetried.WithLabelValues(string(evt.Type)).Inc() - c.queue.AddRateLimited(event) + c.metrics.eventsRetried.WithLabelValues(string(evt.typ)).Inc() + c.queue.AddRateLimited(evt) level.Error(c.log).Log( "msg", "failed to process event, will retry", "retries", fmt.Sprintf("%d/5", retries), @@ -78,40 +81,46 @@ func (c *Component) eventLoop(ctx context.Context) { ) continue } else { - c.metrics.eventsFailed.WithLabelValues(string(evt.Type)).Inc() + c.metrics.eventsFailed.WithLabelValues(string(evt.typ)).Inc() level.Error(c.log).Log( "msg", "failed to process event, max retries exceeded", "retries", fmt.Sprintf("%d/5", retries), "err", err, ) + c.reportUnhealthy(err) } + } else { + c.reportHealthy() } - c.queue.Forget(event) + c.queue.Forget(evt) } } -func (c *Component) processEvent(ctx context.Context, e Event) error { +func (c *Component) processEvent(ctx context.Context, e event) error { defer c.queue.Done(e) - switch e.Type { - case EventTypeResourceChanged: - level.Info(c.log).Log("msg", "processing event", "type", e.Type, "key", e.ObjectKey) - case EventTypeSyncMimir: + switch e.typ { + case eventTypeResourceChanged: + level.Info(c.log).Log("msg", "processing event", "type", e.typ, "key", e.objectKey) + case eventTypeSyncMimir: level.Debug(c.log).Log("msg", "syncing current state from ruler") - c.syncMimir(ctx) + err := c.syncMimir(ctx) + if err != nil { + return err + } default: - return fmt.Errorf("unknown event type: %s", e.Type) + return fmt.Errorf("unknown event type: %s", e.typ) } return c.reconcileState(ctx) } -func (c *Component) syncMimir(ctx context.Context) { +func (c *Component) syncMimir(ctx context.Context) error { rulesByNamespace, err := c.mimirClient.ListRules(ctx, "") if err != nil { level.Error(c.log).Log("msg", "failed to list rules from mimir", "err", err) - return + return err } for ns := range rulesByNamespace { @@ -122,7 +131,7 @@ func (c *Component) syncMimir(ctx context.Context) { c.currentState = rulesByNamespace - return + return nil } func (c *Component) reconcileState(ctx context.Context) error { @@ -198,26 +207,26 @@ func convertCRDRuleGroupToRuleGroup(crd promv1.PrometheusRuleSpec) ([]mimirClien return mimirGroups, nil } -func (c *Component) applyChanges(ctx context.Context, namespace string, diffs []RuleGroupDiff) error { +func (c *Component) applyChanges(ctx context.Context, namespace string, diffs []ruleGroupDiff) error { if len(diffs) == 0 { return nil } for _, diff := range diffs { switch diff.Kind { - case RuleGroupDiffKindAdd: + case ruleGroupDiffKindAdd: err := c.mimirClient.CreateRuleGroup(ctx, namespace, diff.Desired) if err != nil { return err } level.Info(c.log).Log("msg", "added rule group", "namespace", namespace, "group", diff.Desired.Name) - case RuleGroupDiffKindRemove: + case ruleGroupDiffKindRemove: err := c.mimirClient.DeleteRuleGroup(ctx, namespace, diff.Actual.Name) if err != nil { return err } level.Info(c.log).Log("msg", "removed rule group", "namespace", namespace, "group", diff.Actual.Name) - case RuleGroupDiffKindUpdate: + case ruleGroupDiffKindUpdate: err := c.mimirClient.CreateRuleGroup(ctx, namespace, diff.Desired) if err != nil { return err diff --git a/component/mimir/rules/events_test.go b/component/mimir/rules/events_test.go index cb7bef7d0318..40857cd5ecef 100644 --- a/component/mimir/rules/events_test.go +++ b/component/mimir/rules/events_test.go @@ -117,6 +117,7 @@ func TestEventLoop(t *testing.T) { ruleSelector: labels.Everything(), mimirClient: newFakeMimirClient(), args: Arguments{MimirNameSpacePrefix: "agent"}, + metrics: newMetrics(), } ctx, cancel := context.WithCancel(context.Background()) @@ -133,7 +134,7 @@ func TestEventLoop(t *testing.T) { require.Eventually(t, func() bool { return len(handler.currentState) == 1 }, time.Second, 10*time.Millisecond) - handler.queue.AddRateLimited(Event{Type: EventTypeSyncMimir}) + handler.queue.AddRateLimited(event{typ: eventTypeSyncMimir}) // Update the rule in kubernetes rule.Spec.Groups[0].Rules = append(rule.Spec.Groups[0].Rules, v1.Rule{ @@ -148,7 +149,7 @@ func TestEventLoop(t *testing.T) { rules := handler.currentState[mimirNamespaceForRuleCRD("agent", rule)][0].Rules return len(rules) == 2 }, time.Second, 10*time.Millisecond) - handler.queue.AddRateLimited(Event{Type: EventTypeSyncMimir}) + handler.queue.AddRateLimited(event{typ: eventTypeSyncMimir}) // Remove the rule from kubernetes ruleIndexer.Delete(rule) diff --git a/component/mimir/rules/health.go b/component/mimir/rules/health.go new file mode 100644 index 000000000000..b48ffb4a547f --- /dev/null +++ b/component/mimir/rules/health.go @@ -0,0 +1,32 @@ +package rules + +import ( + "time" + + "github.com/grafana/agent/component" +) + +func (c *Component) reportUnhealthy(err error) { + c.healthMut.Lock() + defer c.healthMut.Unlock() + c.health = component.Health{ + Health: component.HealthTypeUnhealthy, + Message: err.Error(), + UpdateTime: time.Now(), + } +} + +func (c *Component) reportHealthy() { + c.healthMut.Lock() + defer c.healthMut.Unlock() + c.health = component.Health{ + Health: component.HealthTypeHealthy, + UpdateTime: time.Now(), + } +} + +func (c *Component) CurrentHealth() component.Health { + c.healthMut.RLock() + defer c.healthMut.RUnlock() + return c.health +} diff --git a/component/mimir/rules/rules.go b/component/mimir/rules/rules.go index 9ce68867ed5f..4df1a5dcd361 100644 --- a/component/mimir/rules/rules.go +++ b/component/mimir/rules/rules.go @@ -3,13 +3,14 @@ package rules import ( "context" "fmt" + "sync" "time" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/grafana/agent/component" mimirClient "github.com/grafana/agent/pkg/mimir/client" - "github.com/grafana/dskit/crypto/tls" + "github.com/pkg/errors" promListers "github.com/prometheus-operator/prometheus-operator/pkg/client/listers/monitoring/v1" "github.com/prometheus/client_golang/prometheus" "github.com/weaveworks/common/instrument" @@ -29,9 +30,9 @@ import ( func init() { component.Register(component.Registration{ - Name: "mimir.rules", + Name: "mimir.rules.kubernetes", Args: Arguments{}, - Exports: Exports{}, + Exports: nil, Build: func(o component.Options, c component.Arguments) (component.Component, error) { return NewComponent(o, c.(Arguments)) }, @@ -62,7 +63,9 @@ type Component struct { currentState map[string][]mimirClient.RuleGroup - metrics *metrics + metrics *metrics + healthMut sync.RWMutex + health component.Health } type metrics struct { @@ -124,29 +127,32 @@ type ConfigUpdate struct { var _ component.Component = (*Component)(nil) var _ component.DebugComponent = (*Component)(nil) +var _ component.HealthComponent = (*Component)(nil) -func NewComponent(o component.Options, c Arguments) (*Component, error) { - setDefaultArguments(&c) - +func NewComponent(o component.Options, args Arguments) (*Component, error) { metrics := newMetrics() metrics.Register(o.Registerer) - return &Component{ + c := &Component{ log: o.Logger, opts: o, - args: c, + args: args, configUpdates: make(chan ConfigUpdate), - ticker: time.NewTicker(c.SyncInterval), + ticker: time.NewTicker(args.SyncInterval), metrics: metrics, - }, nil -} + } -func (c *Component) Run(ctx context.Context) error { - err := c.startup(ctx) + err := c.init() if err != nil { - return err + return nil, errors.Wrap(err, "initializing component") } + return c, nil +} + +func (c *Component) Run(ctx context.Context) error { + c.startup(ctx) + for { select { case update := <-c.configUpdates: @@ -154,36 +160,34 @@ func (c *Component) Run(ctx context.Context) error { c.shutdown() c.args = update.args - err := c.startup(ctx) + err := c.init() update.err <- err if err != nil { - return err + level.Error(c.log).Log("msg", "updating configuration failed", "err", err) + c.reportUnhealthy(err) } + + c.startup(ctx) case <-ctx.Done(): c.shutdown() return nil case <-c.ticker.C: - c.queue.Add(Event{ - Type: EventTypeSyncMimir, + c.queue.Add(event{ + typ: eventTypeSyncMimir, }) } } } -func (c *Component) startup(ctx context.Context) error { - err := c.init() - if err != nil { - return err - } - - c.queue = workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "mimir.rules") +// startup launches the informers and starts the event loop. +func (c *Component) startup(ctx context.Context) { + c.queue = workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "mimir.rules.kubernetes") c.informerStopChan = make(chan struct{}) c.startNamespaceInformer() c.startRuleInformer() c.syncMimir(ctx) go c.eventLoop(ctx) - return nil } func (c *Component) shutdown() { @@ -203,12 +207,12 @@ func (c *Component) Update(newConfig component.Arguments) error { func (c *Component) init() error { level.Info(c.log).Log("msg", "initializing with new configuration") - setDefaultArguments(&c.args) - // TODO: allow overriding some stuff in RestConfig and k8s client options? - restConfig := controller.GetConfigOrDie() + restConfig, err := controller.GetConfig() + if err != nil { + return fmt.Errorf("failed to get k8s config: %w", err) + } - var err error c.k8sClient, err = kubernetes.NewForConfig(restConfig) if err != nil { return fmt.Errorf("failed to create k8s client: %w", err) @@ -219,22 +223,13 @@ func (c *Component) init() error { return fmt.Errorf("failed to create prometheus operator client: %w", err) } + httpClient := c.args.HTTPClientConfig.Convert() + c.mimirClient, err = mimirClient.New(c.log, mimirClient.Config{ - User: c.args.ClientParams.User, - Key: string(c.args.ClientParams.Key), - Address: c.args.ClientParams.Address, - ID: c.args.ClientParams.ID, - TLS: tls.ClientConfig{ - CertPath: c.args.ClientParams.TLS.CertPath, - KeyPath: c.args.ClientParams.TLS.KeyPath, - CAPath: c.args.ClientParams.TLS.CAPath, - ServerName: c.args.ClientParams.TLS.ServerName, - InsecureSkipVerify: c.args.ClientParams.TLS.InsecureSkipVerify, - CipherSuites: c.args.ClientParams.TLS.CipherSuites, - MinVersion: c.args.ClientParams.TLS.MinVersion, - }, - UseLegacyRoutes: c.args.ClientParams.UseLegacyRoutes, - AuthToken: string(c.args.ClientParams.AuthToken), + ID: c.args.TenantID, + Address: c.args.Address, + UseLegacyRoutes: c.args.UseLegacyRoutes, + HTTPClientConfig: *httpClient, }, c.metrics.mimirClientTiming) if err != nil { return err diff --git a/component/mimir/rules/rules_test.go b/component/mimir/rules/rules_test.go index f2e41821942e..6193228ccbc1 100644 --- a/component/mimir/rules/rules_test.go +++ b/component/mimir/rules/rules_test.go @@ -9,5 +9,5 @@ import ( func TestEventTypeIsHashable(t *testing.T) { // This test is here to ensure that the EventType type is hashable according to the workqueue implementation queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) - queue.AddRateLimited(Event{}) + queue.AddRateLimited(event{}) } diff --git a/component/mimir/rules/types.go b/component/mimir/rules/types.go index b2d30149dbce..8ea8adae4d87 100644 --- a/component/mimir/rules/types.go +++ b/component/mimir/rules/types.go @@ -1,33 +1,50 @@ package rules import ( + "fmt" "time" - "github.com/grafana/agent/pkg/flow/rivertypes" + "github.com/grafana/agent/component/common/config" ) type Arguments struct { - ClientParams ClientArguments `river:"client,block"` - SyncInterval time.Duration `river:"sync_interval,attr,optional"` - MimirNameSpacePrefix string `river:"mimir_namespace_prefix,attr,optional"` + Address string `river:"address,attr"` + TenantID string `river:"tenant_id,attr"` + UseLegacyRoutes bool `river:"use_legacy_routes,attr,optional"` + HTTPClientConfig config.HTTPClientConfig `river:"client,block,optional"` + SyncInterval time.Duration `river:"sync_interval,attr,optional"` + MimirNameSpacePrefix string `river:"mimir_namespace_prefix,attr,optional"` RuleSelector LabelSelector `river:"rule_selector,block,optional"` RuleNamespaceSelector LabelSelector `river:"rule_namespace_selector,block,optional"` } -func setDefaultArguments(args *Arguments) { - if args.SyncInterval == 0 { - args.SyncInterval = 30 * time.Second +var DefaultArguments = Arguments{ + SyncInterval: 30 * time.Second, + MimirNameSpacePrefix: "agent", +} + +func (args *Arguments) UnmarshalRiver(f func(interface{}) error) error { + *args = DefaultArguments + + type arguments Arguments + if err := f((*arguments)(args)); err != nil { + return err } + if args.SyncInterval <= 0 { + return fmt.Errorf("sync_interval must be greater than 0") + } if args.MimirNameSpacePrefix == "" { - args.MimirNameSpacePrefix = "agent" + return fmt.Errorf("mimir_namespace_prefix must not be empty") } + + return nil } type LabelSelector struct { MatchLabels map[string]string `river:"match_labels,attr,optional"` - MatchExpressions []MatchExpression `river:"match_expressions,attr,optional"` + MatchExpressions []MatchExpression `river:"match_expression,block,optional"` } type MatchExpression struct { @@ -35,26 +52,3 @@ type MatchExpression struct { Operator string `river:"operator,attr"` Values []string `river:"values,attr"` } - -type ClientArguments struct { - User string `river:"user,attr,optional"` - Key rivertypes.Secret `river:"key,attr,optional"` - Address string `river:"address,attr"` - ID string `river:"id,attr,optional"` - TLS TLSArguments `river:"tls,block,optional"` - UseLegacyRoutes bool `river:"use_legacy_routes,attr,optional"` - AuthToken rivertypes.Secret `river:"auth_token,attr,optional"` -} - -type TLSArguments struct { - CertPath string `river:"tls_cert_path,attr,optional"` - KeyPath string `river:"tls_key_path,attr,optional"` - CAPath string `river:"tls_ca_path,attr,optional"` - ServerName string `river:"tls_server_name,attr,optional"` - InsecureSkipVerify bool `river:"tls_insecure_skip_verify,attr,optional"` - CipherSuites string `river:"tls_cipher_suites,attr,optional"` - MinVersion string `river:"tls_min_version,attr,optional"` -} - -type Exports struct { -} diff --git a/pkg/mimir/client/client.go b/pkg/mimir/client/client.go index 89fdece2474a..6e430004cc37 100644 --- a/pkg/mimir/client/client.go +++ b/pkg/mimir/client/client.go @@ -11,12 +11,12 @@ import ( "strings" log "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/grafana/dskit/crypto/tls" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/config" weaveworksClient "github.com/weaveworks/common/http/client" "github.com/weaveworks/common/instrument" + "github.com/weaveworks/common/user" ) const ( @@ -31,13 +31,10 @@ var ( // Config is used to configure a MimirClient. type Config struct { - User string `yaml:"user"` - Key string `yaml:"key"` - Address string `yaml:"address"` - ID string `yaml:"id"` - TLS tls.ClientConfig - UseLegacyRoutes bool `yaml:"use_legacy_routes"` - AuthToken string `yaml:"auth_token"` + ID string + Address string + UseLegacyRoutes bool + HTTPClientConfig config.HTTPClientConfig } type Interface interface { @@ -48,14 +45,12 @@ type Interface interface { // MimirClient is a client to the Mimir API. type MimirClient struct { - user string - key string - id string - endpoint *url.URL - Client weaveworksClient.Requester - apiPath string - authToken string - logger log.Logger + id string + + endpoint *url.URL + client weaveworksClient.Requester + apiPath string + logger log.Logger } // New returns a new MimirClient. @@ -64,30 +59,9 @@ func New(logger log.Logger, cfg Config, timingHistogram *prometheus.HistogramVec if err != nil { return nil, err } - - level.Debug(logger).Log("msg", "New Mimir client created", "address", cfg.Address, "id", cfg.ID) - - client := &http.Client{} - - // Setup TLS client - tlsConfig, err := cfg.TLS.GetTLSConfig() + client, err := config.NewClientFromConfig(cfg.HTTPClientConfig, "GrafanaAgent", config.WithHTTP2Disabled()) if err != nil { - level.Error(logger).Log( - "msg", "error loading TLS files", - "tls-ca", cfg.TLS.CAPath, - "tls-cert", cfg.TLS.CertPath, - "tls-key", cfg.TLS.KeyPath, - "err", err, - ) - return nil, fmt.Errorf("Mimir client initialization unsuccessful") - } - - if tlsConfig != nil { - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: tlsConfig, - } - client = &http.Client{Transport: transport} + return nil, err } path := rulerAPIPath @@ -99,14 +73,11 @@ func New(logger log.Logger, cfg Config, timingHistogram *prometheus.HistogramVec timedClient := weaveworksClient.NewTimedClient(client, collector) return &MimirClient{ - user: cfg.User, - key: cfg.Key, - id: cfg.ID, - endpoint: endpoint, - Client: timedClient, - apiPath: path, - authToken: cfg.AuthToken, - logger: logger, + id: cfg.ID, + endpoint: endpoint, + client: timedClient, + apiPath: path, + logger: logger, }, nil } @@ -116,24 +87,11 @@ func (r *MimirClient) doRequest(operation, path, method string, payload []byte) return nil, err } - if (r.user != "" || r.key != "") && r.authToken != "" { - err := errors.New("atmost one of basic auth or auth token should be configured") - return nil, err - } - - if r.user != "" { - req.SetBasicAuth(r.user, r.key) - } else if r.key != "" { - req.SetBasicAuth(r.id, r.key) + if r.id != "" { + req.Header.Add(user.OrgIDHeaderName, r.id) } - if r.authToken != "" { - req.Header.Add("Authorization", "Bearer "+r.authToken) - } - - req.Header.Add("X-Scope-OrgID", r.id) - - resp, err := r.Client.Do(req) + resp, err := r.client.Do(req) if err != nil { return nil, err } diff --git a/pkg/mimir/client/rules_test.go b/pkg/mimir/client/rules_test.go index e8ff4677999c..fb22b15a7f84 100644 --- a/pkg/mimir/client/rules_test.go +++ b/pkg/mimir/client/rules_test.go @@ -24,8 +24,6 @@ func TestMimirClient_X(t *testing.T) { client, err := New(log.NewNopLogger(), Config{ Address: ts.URL, - ID: "my-id", - Key: "my-key", }, prometheus.NewHistogramVec(prometheus.HistogramOpts{}, instrument.HistogramCollectorBuckets)) require.NoError(t, err)