github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/resumer/manifold_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package resumer_test 5 6 import ( 7 "errors" 8 "time" 9 10 "github.com/juju/clock" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/juju/names.v2" 15 "gopkg.in/juju/worker.v1" 16 "gopkg.in/juju/worker.v1/dependency" 17 dt "gopkg.in/juju/worker.v1/dependency/testing" 18 "gopkg.in/juju/worker.v1/workertest" 19 20 "github.com/juju/juju/agent" 21 "github.com/juju/juju/api/base" 22 "github.com/juju/juju/apiserver/params" 23 "github.com/juju/juju/state/multiwatcher" 24 coretesting "github.com/juju/juju/testing" 25 resumer "github.com/juju/juju/worker/resumer" 26 ) 27 28 type ManifoldSuite struct { 29 testing.IsolationSuite 30 } 31 32 var _ = gc.Suite(&ManifoldSuite{}) 33 34 func (*ManifoldSuite) TestInputs(c *gc.C) { 35 manifold := resumer.Manifold(resumer.ManifoldConfig{ 36 AgentName: "bill", 37 APICallerName: "ben", 38 }) 39 expect := []string{"bill", "ben"} 40 c.Check(manifold.Inputs, jc.DeepEquals, expect) 41 } 42 43 func (*ManifoldSuite) TestOutput(c *gc.C) { 44 manifold := resumer.Manifold(resumer.ManifoldConfig{}) 45 c.Check(manifold.Output, gc.IsNil) 46 } 47 48 func (*ManifoldSuite) TestMissingAgent(c *gc.C) { 49 manifold := resumer.Manifold(resumer.ManifoldConfig{ 50 AgentName: "agent", 51 APICallerName: "api-caller", 52 }) 53 54 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 55 "agent": dependency.ErrMissing, 56 "api-caller": &fakeAPICaller{}, 57 })) 58 workertest.CheckNilOrKill(c, worker) 59 c.Check(err, gc.Equals, dependency.ErrMissing) 60 } 61 62 func (*ManifoldSuite) TestMissingAPICaller(c *gc.C) { 63 manifold := resumer.Manifold(resumer.ManifoldConfig{ 64 AgentName: "agent", 65 APICallerName: "api-caller", 66 }) 67 68 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 69 "agent": &fakeAgent{}, 70 "api-caller": dependency.ErrMissing, 71 })) 72 workertest.CheckNilOrKill(c, worker) 73 c.Check(err, gc.Equals, dependency.ErrMissing) 74 } 75 76 func (*ManifoldSuite) TestAgentEntity_Error(c *gc.C) { 77 manifold := resumer.Manifold(resumer.ManifoldConfig{ 78 AgentName: "agent", 79 APICallerName: "api-caller", 80 }) 81 82 stub := &testing.Stub{} 83 stub.SetErrors(errors.New("zap")) 84 apiCaller := &fakeAPICaller{stub: stub} 85 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 86 "agent": &fakeAgent{}, 87 "api-caller": apiCaller, 88 })) 89 workertest.CheckNilOrKill(c, worker) 90 c.Check(err, gc.ErrorMatches, "zap") 91 92 stub.CheckCalls(c, []testing.StubCall{{ 93 FuncName: "Agent.GetEntities", 94 Args: []interface{}{params.Entities{ 95 Entities: []params.Entity{{ 96 Tag: "machine-123", 97 }}, 98 }}, 99 }}) 100 } 101 102 func (s *ManifoldSuite) TestAgentEntity_NoJob(c *gc.C) { 103 manifold := resumer.Manifold(resumer.ManifoldConfig{ 104 AgentName: "agent", 105 APICallerName: "api-caller", 106 }) 107 108 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 109 "agent": &fakeAgent{}, 110 "api-caller": &fakeAPICaller{}, 111 })) 112 workertest.CheckNilOrKill(c, worker) 113 c.Check(err, gc.Equals, dependency.ErrMissing) 114 } 115 116 func (s *ManifoldSuite) TestAgentEntity_NotModelManager(c *gc.C) { 117 manifold := resumer.Manifold(resumer.ManifoldConfig{ 118 AgentName: "agent", 119 APICallerName: "api-caller", 120 }) 121 122 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 123 "agent": &fakeAgent{}, 124 "api-caller": newFakeAPICaller(multiwatcher.JobHostUnits), 125 })) 126 workertest.CheckNilOrKill(c, worker) 127 c.Check(err, gc.Equals, dependency.ErrMissing) 128 } 129 130 func (s *ManifoldSuite) TestNewFacade_Missing(c *gc.C) { 131 manifold := resumer.Manifold(resumer.ManifoldConfig{ 132 AgentName: "agent", 133 APICallerName: "api-caller", 134 }) 135 136 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 137 "agent": &fakeAgent{}, 138 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 139 })) 140 workertest.CheckNilOrKill(c, worker) 141 c.Check(err, gc.Equals, dependency.ErrUninstall) 142 } 143 144 func (s *ManifoldSuite) TestNewFacade_Error(c *gc.C) { 145 apiCaller := newFakeAPICaller(multiwatcher.JobManageModel) 146 manifold := resumer.Manifold(resumer.ManifoldConfig{ 147 AgentName: "agent", 148 APICallerName: "api-caller", 149 NewFacade: func(actual base.APICaller) (resumer.Facade, error) { 150 c.Check(actual, gc.Equals, apiCaller) 151 return nil, errors.New("pow") 152 }, 153 }) 154 155 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 156 "agent": &fakeAgent{}, 157 "api-caller": apiCaller, 158 })) 159 workertest.CheckNilOrKill(c, worker) 160 c.Check(err, gc.ErrorMatches, "pow") 161 } 162 163 func (s *ManifoldSuite) TestNewWorker_Missing(c *gc.C) { 164 manifold := resumer.Manifold(resumer.ManifoldConfig{ 165 AgentName: "agent", 166 APICallerName: "api-caller", 167 NewFacade: func(base.APICaller) (resumer.Facade, error) { 168 return &fakeFacade{}, nil 169 }, 170 }) 171 172 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 173 "agent": &fakeAgent{}, 174 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 175 })) 176 workertest.CheckNilOrKill(c, worker) 177 c.Check(err, gc.Equals, dependency.ErrUninstall) 178 } 179 180 func (s *ManifoldSuite) TestNewWorker_Error(c *gc.C) { 181 clock := &fakeClock{} 182 facade := &fakeFacade{} 183 manifold := resumer.Manifold(resumer.ManifoldConfig{ 184 AgentName: "agent", 185 APICallerName: "api-caller", 186 Clock: clock, 187 Interval: time.Hour, 188 NewFacade: func(base.APICaller) (resumer.Facade, error) { 189 return facade, nil 190 }, 191 NewWorker: func(actual resumer.Config) (worker.Worker, error) { 192 c.Check(actual, jc.DeepEquals, resumer.Config{ 193 Facade: facade, 194 Clock: clock, 195 Interval: time.Hour, 196 }) 197 return nil, errors.New("blam") 198 }, 199 }) 200 201 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 202 "agent": &fakeAgent{}, 203 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 204 })) 205 workertest.CheckNilOrKill(c, worker) 206 c.Check(err, gc.ErrorMatches, "blam") 207 } 208 209 func (s *ManifoldSuite) TestNewWorker_Success(c *gc.C) { 210 expect := &fakeWorker{} 211 manifold := resumer.Manifold(resumer.ManifoldConfig{ 212 AgentName: "agent", 213 APICallerName: "api-caller", 214 NewFacade: func(base.APICaller) (resumer.Facade, error) { 215 return &fakeFacade{}, nil 216 }, 217 NewWorker: func(actual resumer.Config) (worker.Worker, error) { 218 return expect, nil 219 }, 220 }) 221 222 actual, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 223 "agent": &fakeAgent{}, 224 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 225 })) 226 c.Check(err, jc.ErrorIsNil) 227 c.Check(actual, gc.Equals, expect) 228 } 229 230 // fakeFacade should not be called. 231 type fakeFacade struct { 232 resumer.Facade 233 } 234 235 // fakeClock should not be called. 236 type fakeClock struct { 237 clock.Clock 238 } 239 240 // fakeWorker should not be called. 241 type fakeWorker struct { 242 worker.Worker 243 } 244 245 // fakeAgent exists to expose a tag via CurrentConfig().Tag(). 246 type fakeAgent struct { 247 agent.Agent 248 } 249 250 // CurrentConfig returns an agent.Config with a working Tag() method. 251 func (a *fakeAgent) CurrentConfig() agent.Config { 252 return &fakeConfig{} 253 } 254 255 // fakeConfig exists to expose Tag. 256 type fakeConfig struct { 257 agent.Config 258 } 259 260 // Tag returns a Tag. 261 func (c *fakeConfig) Tag() names.Tag { 262 return names.NewMachineTag("123") 263 } 264 265 func newFakeAPICaller(jobs ...multiwatcher.MachineJob) *fakeAPICaller { 266 return &fakeAPICaller{jobs: jobs} 267 } 268 269 // fakeAPICaller exists to handle the hackish checkModelManager's api 270 // call directly, because it shouldn't happen in this context at all 271 // and we don't want it leaking into the config. 272 type fakeAPICaller struct { 273 base.APICaller 274 stub *testing.Stub 275 jobs []multiwatcher.MachineJob 276 } 277 278 // APICall is part of the base.APICaller interface. 279 func (f *fakeAPICaller) APICall(objType string, version int, id, request string, args interface{}, response interface{}) error { 280 if f.stub != nil { 281 // We don't usually set the stub here, most of the time 282 // the APICall hack is just an unwanted distraction from 283 // the NewFacade/NewWorker bits that *should* exist long- 284 // term. This makes it easier to just delete the broken 285 // tests, and most of this type, including all of the 286 // methods, when we drop the job check. 287 f.stub.AddCall(objType+"."+request, args) 288 if err := f.stub.NextErr(); err != nil { 289 return err 290 } 291 } 292 293 if res, ok := response.(*params.AgentGetEntitiesResults); ok { 294 jobs := make([]multiwatcher.MachineJob, 0, len(f.jobs)) 295 jobs = append(jobs, f.jobs...) 296 res.Entities = []params.AgentGetEntitiesResult{ 297 {Jobs: jobs}, 298 } 299 } 300 return nil 301 } 302 303 // BestFacadeVersion is part of the base.APICaller interface. 304 func (*fakeAPICaller) BestFacadeVersion(facade string) int { 305 return 42 306 } 307 308 // ModelTag is part of the base.APICaller interface. 309 func (*fakeAPICaller) ModelTag() (names.ModelTag, bool) { 310 return coretesting.ModelTag, true 311 }