diff --git a/internal/component/prometheus/operator/common/component.go b/internal/component/prometheus/operator/common/component.go index e54f51237..11a8c014b 100644 --- a/internal/component/prometheus/operator/common/component.go +++ b/internal/component/prometheus/operator/common/component.go @@ -19,7 +19,7 @@ import ( type Component struct { mut sync.RWMutex config *operator.Arguments - manager *crdManager + manager crdManagerInterface ls labelstore.LabelStore onUpdate chan struct{} @@ -27,6 +27,8 @@ type Component struct { healthMut sync.RWMutex health component.Health + crdManagerFactory crdManagerFactory + kind string cluster cluster.Cluster } @@ -44,11 +46,12 @@ func New(o component.Options, args component.Arguments, kind string) (*Component } ls := service.(labelstore.LabelStore) c := &Component{ - opts: o, - onUpdate: make(chan struct{}, 1), - kind: kind, - cluster: clusterData, - ls: ls, + opts: o, + onUpdate: make(chan struct{}, 1), + kind: kind, + cluster: clusterData, + ls: ls, + crdManagerFactory: realCrdManagerFactory{}, } return c, c.Update(args) } @@ -87,7 +90,7 @@ func (c *Component) Run(ctx context.Context) error { c.reportHealth(err) case <-c.onUpdate: c.mut.Lock() - manager := newCrdManager(c.opts, c.cluster, c.opts.Logger, c.config, c.kind, c.ls) + manager := c.crdManagerFactory.New(c.opts, c.cluster, c.opts.Logger, c.config, c.kind, c.ls) c.manager = manager // Wait for the old manager to stop. @@ -180,7 +183,7 @@ func (c *Component) Handler() http.Handler { } ns := parts[1] name := parts[2] - scs := man.getScrapeConfig(ns, name) + scs := man.GetScrapeConfig(ns, name) if len(scs) == 0 { w.WriteHeader(404) return diff --git a/internal/component/prometheus/operator/common/crdmanager.go b/internal/component/prometheus/operator/common/crdmanager.go index baa72f498..f5c13da57 100644 --- a/internal/component/prometheus/operator/common/crdmanager.go +++ b/internal/component/prometheus/operator/common/crdmanager.go @@ -40,6 +40,23 @@ import ( // Generous timeout period for configuring all informers const informerSyncTimeout = 10 * time.Second +type crdManagerInterface interface { + Run(ctx context.Context) error + ClusteringUpdated() + DebugInfo() interface{} + GetScrapeConfig(ns, name string) []*config.ScrapeConfig +} + +type crdManagerFactory interface { + New(opts component.Options, cluster cluster.Cluster, logger log.Logger, args *operator.Arguments, kind string, ls labelstore.LabelStore) crdManagerInterface +} + +type realCrdManagerFactory struct{} + +func (realCrdManagerFactory) New(opts component.Options, cluster cluster.Cluster, logger log.Logger, args *operator.Arguments, kind string, ls labelstore.LabelStore) crdManagerInterface { + return newCrdManager(opts, cluster, logger, args, kind, ls) +} + // crdManager is all of the fields required to run a crd based component. // on update, this entire thing should be recreated and restarted type crdManager struct { @@ -237,7 +254,7 @@ func (c *crdManager) DebugInfo() interface{} { return info } -func (c *crdManager) getScrapeConfig(ns, name string) []*config.ScrapeConfig { +func (c *crdManager) GetScrapeConfig(ns, name string) []*config.ScrapeConfig { prefix := fmt.Sprintf("%s/%s/%s", c.kind, ns, name) matches := []*config.ScrapeConfig{} for k, v := range c.scrapeConfigs { diff --git a/internal/component/prometheus/operator/common/crdmanager_test.go b/internal/component/prometheus/operator/common/crdmanager_test.go index e1fb880bb..db8a05f9c 100644 --- a/internal/component/prometheus/operator/common/crdmanager_test.go +++ b/internal/component/prometheus/operator/common/crdmanager_test.go @@ -1,6 +1,7 @@ package common import ( + "context" "testing" "golang.org/x/exp/maps" @@ -167,3 +168,34 @@ func (m *mockScrapeManager) TargetsActive() map[string][]*scrape.Target { func (m *mockScrapeManager) ApplyConfig(cfg *config.Config) error { return nil } + +type crdManagerFactoryHungRun struct{} + +func (crdManagerFactoryHungRun) New(opts component.Options, cluster cluster.Cluster, logger log.Logger, args *operator.Arguments, kind string, ls labelstore.LabelStore) crdManagerInterface { + return &crdManagerHungRun{} +} + +type crdManagerHungRun struct{} + +func (c *crdManagerHungRun) Run(ctx context.Context) error { + +} + +func (c *crdManagerHungRun) ClusteringUpdated() {} + +func (c *crdManagerHungRun) DebugInfo() interface{} { + return nil +} + +func (c *crdManagerHungRun) GetScrapeConfig(ns, name string) []*config.ScrapeConfig { + return nil +} + +func TestRunExit(t *testing.T) { + // Create a Component + // Call component.Run + // Cancel the context. + // Make sure component.Run didn't exit for a few seconds + // Make crdManager.Run exit + // Make sure component.Run exits +}