1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
"github.com/juju/testing"
11
jc "github.com/juju/testing/checkers"
12
"github.com/juju/utils/clock"
13
gc "gopkg.in/check.v1"
14
"gopkg.in/juju/names.v2"
16
"github.com/juju/juju/agent"
17
"github.com/juju/juju/api/base"
18
"github.com/juju/juju/apiserver/params"
19
"github.com/juju/juju/state/multiwatcher"
20
"github.com/juju/juju/worker"
21
"github.com/juju/juju/worker/dependency"
22
dt "github.com/juju/juju/worker/dependency/testing"
23
resumer "github.com/juju/juju/worker/resumer"
24
"github.com/juju/juju/worker/workertest"
27
type ManifoldSuite struct {
28
testing.IsolationSuite
31
var _ = gc.Suite(&ManifoldSuite{})
33
func (*ManifoldSuite) TestInputs(c *gc.C) {
34
manifold := resumer.Manifold(resumer.ManifoldConfig{
38
expect := []string{"bill", "ben"}
39
c.Check(manifold.Inputs, jc.DeepEquals, expect)
42
func (*ManifoldSuite) TestOutput(c *gc.C) {
43
manifold := resumer.Manifold(resumer.ManifoldConfig{})
44
c.Check(manifold.Output, gc.IsNil)
47
func (*ManifoldSuite) TestMissingAgent(c *gc.C) {
48
manifold := resumer.Manifold(resumer.ManifoldConfig{
50
APICallerName: "api-caller",
53
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
54
"agent": dependency.ErrMissing,
55
"api-caller": &fakeAPICaller{},
57
workertest.CheckNilOrKill(c, worker)
58
c.Check(err, gc.Equals, dependency.ErrMissing)
61
func (*ManifoldSuite) TestMissingAPICaller(c *gc.C) {
62
manifold := resumer.Manifold(resumer.ManifoldConfig{
64
APICallerName: "api-caller",
67
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
68
"agent": &fakeAgent{},
69
"api-caller": dependency.ErrMissing,
71
workertest.CheckNilOrKill(c, worker)
72
c.Check(err, gc.Equals, dependency.ErrMissing)
75
func (*ManifoldSuite) TestAgentEntity_Error(c *gc.C) {
76
manifold := resumer.Manifold(resumer.ManifoldConfig{
78
APICallerName: "api-caller",
81
stub := &testing.Stub{}
82
stub.SetErrors(errors.New("zap"))
83
apiCaller := &fakeAPICaller{stub: stub}
84
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
85
"agent": &fakeAgent{},
86
"api-caller": apiCaller,
88
workertest.CheckNilOrKill(c, worker)
89
c.Check(err, gc.ErrorMatches, "zap")
91
stub.CheckCalls(c, []testing.StubCall{{
92
FuncName: "Agent.GetEntities",
93
Args: []interface{}{params.Entities{
94
Entities: []params.Entity{{
101
func (s *ManifoldSuite) TestAgentEntity_NoJob(c *gc.C) {
102
manifold := resumer.Manifold(resumer.ManifoldConfig{
104
APICallerName: "api-caller",
107
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
108
"agent": &fakeAgent{},
109
"api-caller": &fakeAPICaller{},
111
workertest.CheckNilOrKill(c, worker)
112
c.Check(err, gc.Equals, dependency.ErrMissing)
115
func (s *ManifoldSuite) TestAgentEntity_NotModelManager(c *gc.C) {
116
manifold := resumer.Manifold(resumer.ManifoldConfig{
118
APICallerName: "api-caller",
121
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
122
"agent": &fakeAgent{},
123
"api-caller": newFakeAPICaller(multiwatcher.JobHostUnits),
125
workertest.CheckNilOrKill(c, worker)
126
c.Check(err, gc.Equals, dependency.ErrMissing)
129
func (s *ManifoldSuite) TestNewFacade_Missing(c *gc.C) {
130
manifold := resumer.Manifold(resumer.ManifoldConfig{
132
APICallerName: "api-caller",
135
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
136
"agent": &fakeAgent{},
137
"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
139
workertest.CheckNilOrKill(c, worker)
140
c.Check(err, gc.Equals, dependency.ErrUninstall)
143
func (s *ManifoldSuite) TestNewFacade_Error(c *gc.C) {
144
apiCaller := newFakeAPICaller(multiwatcher.JobManageModel)
145
manifold := resumer.Manifold(resumer.ManifoldConfig{
147
APICallerName: "api-caller",
148
NewFacade: func(actual base.APICaller) (resumer.Facade, error) {
149
c.Check(actual, gc.Equals, apiCaller)
150
return nil, errors.New("pow")
154
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
155
"agent": &fakeAgent{},
156
"api-caller": apiCaller,
158
workertest.CheckNilOrKill(c, worker)
159
c.Check(err, gc.ErrorMatches, "pow")
162
func (s *ManifoldSuite) TestNewWorker_Missing(c *gc.C) {
163
manifold := resumer.Manifold(resumer.ManifoldConfig{
165
APICallerName: "api-caller",
166
NewFacade: func(base.APICaller) (resumer.Facade, error) {
167
return &fakeFacade{}, nil
171
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
172
"agent": &fakeAgent{},
173
"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
175
workertest.CheckNilOrKill(c, worker)
176
c.Check(err, gc.Equals, dependency.ErrUninstall)
179
func (s *ManifoldSuite) TestNewWorker_Error(c *gc.C) {
180
clock := &fakeClock{}
181
facade := &fakeFacade{}
182
manifold := resumer.Manifold(resumer.ManifoldConfig{
184
APICallerName: "api-caller",
187
NewFacade: func(base.APICaller) (resumer.Facade, error) {
190
NewWorker: func(actual resumer.Config) (worker.Worker, error) {
191
c.Check(actual, jc.DeepEquals, resumer.Config{
196
return nil, errors.New("blam")
200
worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
201
"agent": &fakeAgent{},
202
"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
204
workertest.CheckNilOrKill(c, worker)
205
c.Check(err, gc.ErrorMatches, "blam")
208
func (s *ManifoldSuite) TestNewWorker_Success(c *gc.C) {
209
expect := &fakeWorker{}
210
manifold := resumer.Manifold(resumer.ManifoldConfig{
212
APICallerName: "api-caller",
213
NewFacade: func(base.APICaller) (resumer.Facade, error) {
214
return &fakeFacade{}, nil
216
NewWorker: func(actual resumer.Config) (worker.Worker, error) {
221
actual, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
222
"agent": &fakeAgent{},
223
"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
225
c.Check(err, jc.ErrorIsNil)
226
c.Check(actual, gc.Equals, expect)
229
// fakeFacade should not be called.
230
type fakeFacade struct {
234
// fakeClock should not be called.
235
type fakeClock struct {
239
// fakeWorker should not be called.
240
type fakeWorker struct {
244
// fakeAgent exists to expose a tag via CurrentConfig().Tag().
245
type fakeAgent struct {
249
// CurrentConfig returns an agent.Config with a working Tag() method.
250
func (a *fakeAgent) CurrentConfig() agent.Config {
254
// fakeConfig exists to expose Tag.
255
type fakeConfig struct {
259
// Tag returns a Tag.
260
func (c *fakeConfig) Tag() names.Tag {
261
return names.NewMachineTag("123")
264
func newFakeAPICaller(jobs ...multiwatcher.MachineJob) *fakeAPICaller {
265
return &fakeAPICaller{jobs: jobs}
268
// fakeAPICaller exists to handle the hackish checkModelManager's api
269
// call directly, because it shouldn't happen in this context at all
270
// and we don't want it leaking into the config.
271
type fakeAPICaller struct {
274
jobs []multiwatcher.MachineJob
277
// APICall is part of the base.APICaller interface.
278
func (f *fakeAPICaller) APICall(objType string, version int, id, request string, args interface{}, response interface{}) error {
280
// We don't usually set the stub here, most of the time
281
// the APICall hack is just an unwanted distraction from
282
// the NewFacade/NewWorker bits that *should* exist long-
283
// term. This makes it easier to just delete the broken
284
// tests, and most of this type, including all of the
285
// methods, when we drop the job check.
286
f.stub.AddCall(objType+"."+request, args)
287
if err := f.stub.NextErr(); err != nil {
292
if res, ok := response.(*params.AgentGetEntitiesResults); ok {
293
jobs := make([]multiwatcher.MachineJob, 0, len(f.jobs))
294
jobs = append(jobs, f.jobs...)
295
res.Entities = []params.AgentGetEntitiesResult{
302
// BestFacadeVersion is part of the base.APICaller interface.
303
func (*fakeAPICaller) BestFacadeVersion(facade string) int {