github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/agent/addons/addons_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package addons_test 5 6 import ( 7 "runtime" 8 "time" 9 10 "github.com/juju/clock" 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 "github.com/juju/names/v5" 14 "github.com/juju/testing" 15 jc "github.com/juju/testing/checkers" 16 "github.com/juju/worker/v3" 17 "github.com/juju/worker/v3/dependency" 18 "github.com/prometheus/client_golang/prometheus" 19 "go.uber.org/mock/gomock" 20 gc "gopkg.in/check.v1" 21 22 "github.com/juju/juju/agent/addons" 23 agenterrors "github.com/juju/juju/cmd/jujud/agent/errors" 24 coretesting "github.com/juju/juju/testing" 25 "github.com/juju/juju/worker/introspection" 26 ) 27 28 type introspectionSuite struct { 29 testing.IsolationSuite 30 } 31 32 var _ = gc.Suite(&introspectionSuite{}) 33 34 func (s *introspectionSuite) TestStartNonLinux(c *gc.C) { 35 if runtime.GOOS == "linux" { 36 c.Skip("testing for non-linux") 37 } 38 var started bool 39 40 cfg := addons.IntrospectionConfig{ 41 WorkerFunc: func(_ introspection.Config) (worker.Worker, error) { 42 started = true 43 return nil, errors.New("shouldn't call start") 44 }, 45 } 46 47 err := addons.StartIntrospection(cfg) 48 c.Assert(err, jc.ErrorIsNil) 49 c.Assert(started, jc.IsFalse) 50 } 51 52 func (s *introspectionSuite) TestStartError(c *gc.C) { 53 if runtime.GOOS != "linux" { 54 c.Skip("introspection worker not supported on non-linux") 55 } 56 57 cfg := addons.IntrospectionConfig{ 58 AgentTag: names.NewMachineTag("42"), 59 NewSocketName: addons.DefaultIntrospectionSocketName, 60 WorkerFunc: func(_ introspection.Config) (worker.Worker, error) { 61 return nil, errors.New("boom") 62 }, 63 } 64 65 err := addons.StartIntrospection(cfg) 66 c.Check(err, gc.ErrorMatches, "boom") 67 } 68 69 func (s *introspectionSuite) TestStartSuccess(c *gc.C) { 70 if runtime.GOOS != "linux" { 71 c.Skip("introspection worker not supported on non-linux") 72 } 73 fake := &dummyWorker{ 74 done: make(chan struct{}), 75 } 76 77 config := dependency.EngineConfig{ 78 IsFatal: agenterrors.IsFatal, 79 WorstError: agenterrors.MoreImportantError, 80 Clock: clock.WallClock, 81 Metrics: dependency.DefaultMetrics(), 82 Logger: loggo.GetLogger("juju.worker.dependency"), 83 } 84 engine, err := dependency.NewEngine(config) 85 c.Assert(err, jc.ErrorIsNil) 86 87 cfg := addons.IntrospectionConfig{ 88 AgentTag: names.NewMachineTag("42"), 89 Engine: engine, 90 NewSocketName: func(tag names.Tag) string { return "bananas" }, 91 WorkerFunc: func(cfg introspection.Config) (worker.Worker, error) { 92 fake.config = cfg 93 return fake, nil 94 }, 95 } 96 97 err = addons.StartIntrospection(cfg) 98 c.Assert(err, jc.ErrorIsNil) 99 100 c.Check(fake.config.DepEngine, gc.Equals, engine) 101 c.Check(fake.config.SocketName, gc.Equals, "bananas") 102 103 // Stopping the engine causes the introspection worker to stop. 104 engine.Kill() 105 106 select { 107 case <-fake.done: 108 case <-time.After(coretesting.LongWait): 109 c.Fatalf("worker did not get stopped") 110 } 111 } 112 113 func (s *introspectionSuite) TestDefaultIntrospectionSocketName(c *gc.C) { 114 name := addons.DefaultIntrospectionSocketName(names.NewMachineTag("42")) 115 c.Assert(name, gc.Equals, "jujud-machine-42") 116 } 117 118 type dummyWorker struct { 119 config introspection.Config 120 done chan struct{} 121 } 122 123 func (d *dummyWorker) Kill() { 124 close(d.done) 125 } 126 127 func (d *dummyWorker) Wait() error { 128 <-d.done 129 return nil 130 } 131 132 type registerSuite struct { 133 testing.IsolationSuite 134 } 135 136 var _ = gc.Suite(®isterSuite{}) 137 138 func (s *registerSuite) TestRegisterEngineMetrics(c *gc.C) { 139 ctrl := gomock.NewController(c) 140 defer ctrl.Finish() 141 142 done := make(chan struct{}, 1) 143 144 collector := dummyCollector{} 145 146 registry := NewMockRegisterer(ctrl) 147 registry.EXPECT().Register(collector) 148 registry.EXPECT().Unregister(collector).Do(func(_ prometheus.Collector) { 149 close(done) 150 }) 151 sink := NewMockMetricSink(ctrl) 152 sink.EXPECT().Unregister() 153 154 worker := &dummyWorker{ 155 done: make(chan struct{}, 1), 156 } 157 158 err := addons.RegisterEngineMetrics(registry, collector, worker, sink) 159 c.Assert(err, jc.ErrorIsNil) 160 161 worker.Kill() 162 163 select { 164 case <-done: 165 case <-time.After(testing.ShortWait): 166 } 167 } 168 169 type dummyCollector struct{} 170 171 // Describe is part of the prometheus.Collector interface. 172 func (dummyCollector) Describe(ch chan<- *prometheus.Desc) { 173 } 174 175 // Collect is part of the prometheus.Collector interface. 176 func (dummyCollector) Collect(ch chan<- prometheus.Metric) { 177 }