github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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/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"
    15  
    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"
    25  )
    26  
    27  type ManifoldSuite struct {
    28  	testing.IsolationSuite
    29  }
    30  
    31  var _ = gc.Suite(&ManifoldSuite{})
    32  
    33  func (*ManifoldSuite) TestInputs(c *gc.C) {
    34  	manifold := resumer.Manifold(resumer.ManifoldConfig{
    35  		AgentName:     "bill",
    36  		APICallerName: "ben",
    37  	})
    38  	expect := []string{"bill", "ben"}
    39  	c.Check(manifold.Inputs, jc.DeepEquals, expect)
    40  }
    41  
    42  func (*ManifoldSuite) TestOutput(c *gc.C) {
    43  	manifold := resumer.Manifold(resumer.ManifoldConfig{})
    44  	c.Check(manifold.Output, gc.IsNil)
    45  }
    46  
    47  func (*ManifoldSuite) TestMissingAgent(c *gc.C) {
    48  	manifold := resumer.Manifold(resumer.ManifoldConfig{
    49  		AgentName:     "agent",
    50  		APICallerName: "api-caller",
    51  	})
    52  
    53  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
    54  		"agent":      dependency.ErrMissing,
    55  		"api-caller": &fakeAPICaller{},
    56  	}))
    57  	workertest.CheckNilOrKill(c, worker)
    58  	c.Check(err, gc.Equals, dependency.ErrMissing)
    59  }
    60  
    61  func (*ManifoldSuite) TestMissingAPICaller(c *gc.C) {
    62  	manifold := resumer.Manifold(resumer.ManifoldConfig{
    63  		AgentName:     "agent",
    64  		APICallerName: "api-caller",
    65  	})
    66  
    67  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
    68  		"agent":      &fakeAgent{},
    69  		"api-caller": dependency.ErrMissing,
    70  	}))
    71  	workertest.CheckNilOrKill(c, worker)
    72  	c.Check(err, gc.Equals, dependency.ErrMissing)
    73  }
    74  
    75  func (*ManifoldSuite) TestAgentEntity_Error(c *gc.C) {
    76  	manifold := resumer.Manifold(resumer.ManifoldConfig{
    77  		AgentName:     "agent",
    78  		APICallerName: "api-caller",
    79  	})
    80  
    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,
    87  	}))
    88  	workertest.CheckNilOrKill(c, worker)
    89  	c.Check(err, gc.ErrorMatches, "zap")
    90  
    91  	stub.CheckCalls(c, []testing.StubCall{{
    92  		FuncName: "Agent.GetEntities",
    93  		Args: []interface{}{params.Entities{
    94  			Entities: []params.Entity{{
    95  				Tag: "machine-123",
    96  			}},
    97  		}},
    98  	}})
    99  }
   100  
   101  func (s *ManifoldSuite) TestAgentEntity_NoJob(c *gc.C) {
   102  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   103  		AgentName:     "agent",
   104  		APICallerName: "api-caller",
   105  	})
   106  
   107  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   108  		"agent":      &fakeAgent{},
   109  		"api-caller": &fakeAPICaller{},
   110  	}))
   111  	workertest.CheckNilOrKill(c, worker)
   112  	c.Check(err, gc.Equals, dependency.ErrMissing)
   113  }
   114  
   115  func (s *ManifoldSuite) TestAgentEntity_NotModelManager(c *gc.C) {
   116  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   117  		AgentName:     "agent",
   118  		APICallerName: "api-caller",
   119  	})
   120  
   121  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   122  		"agent":      &fakeAgent{},
   123  		"api-caller": newFakeAPICaller(multiwatcher.JobHostUnits),
   124  	}))
   125  	workertest.CheckNilOrKill(c, worker)
   126  	c.Check(err, gc.Equals, dependency.ErrMissing)
   127  }
   128  
   129  func (s *ManifoldSuite) TestNewFacade_Missing(c *gc.C) {
   130  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   131  		AgentName:     "agent",
   132  		APICallerName: "api-caller",
   133  	})
   134  
   135  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   136  		"agent":      &fakeAgent{},
   137  		"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
   138  	}))
   139  	workertest.CheckNilOrKill(c, worker)
   140  	c.Check(err, gc.Equals, dependency.ErrUninstall)
   141  }
   142  
   143  func (s *ManifoldSuite) TestNewFacade_Error(c *gc.C) {
   144  	apiCaller := newFakeAPICaller(multiwatcher.JobManageModel)
   145  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   146  		AgentName:     "agent",
   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")
   151  		},
   152  	})
   153  
   154  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   155  		"agent":      &fakeAgent{},
   156  		"api-caller": apiCaller,
   157  	}))
   158  	workertest.CheckNilOrKill(c, worker)
   159  	c.Check(err, gc.ErrorMatches, "pow")
   160  }
   161  
   162  func (s *ManifoldSuite) TestNewWorker_Missing(c *gc.C) {
   163  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   164  		AgentName:     "agent",
   165  		APICallerName: "api-caller",
   166  		NewFacade: func(base.APICaller) (resumer.Facade, error) {
   167  			return &fakeFacade{}, nil
   168  		},
   169  	})
   170  
   171  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   172  		"agent":      &fakeAgent{},
   173  		"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
   174  	}))
   175  	workertest.CheckNilOrKill(c, worker)
   176  	c.Check(err, gc.Equals, dependency.ErrUninstall)
   177  }
   178  
   179  func (s *ManifoldSuite) TestNewWorker_Error(c *gc.C) {
   180  	clock := &fakeClock{}
   181  	facade := &fakeFacade{}
   182  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   183  		AgentName:     "agent",
   184  		APICallerName: "api-caller",
   185  		Clock:         clock,
   186  		Interval:      time.Hour,
   187  		NewFacade: func(base.APICaller) (resumer.Facade, error) {
   188  			return facade, nil
   189  		},
   190  		NewWorker: func(actual resumer.Config) (worker.Worker, error) {
   191  			c.Check(actual, jc.DeepEquals, resumer.Config{
   192  				Facade:   facade,
   193  				Clock:    clock,
   194  				Interval: time.Hour,
   195  			})
   196  			return nil, errors.New("blam")
   197  		},
   198  	})
   199  
   200  	worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   201  		"agent":      &fakeAgent{},
   202  		"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
   203  	}))
   204  	workertest.CheckNilOrKill(c, worker)
   205  	c.Check(err, gc.ErrorMatches, "blam")
   206  }
   207  
   208  func (s *ManifoldSuite) TestNewWorker_Success(c *gc.C) {
   209  	expect := &fakeWorker{}
   210  	manifold := resumer.Manifold(resumer.ManifoldConfig{
   211  		AgentName:     "agent",
   212  		APICallerName: "api-caller",
   213  		NewFacade: func(base.APICaller) (resumer.Facade, error) {
   214  			return &fakeFacade{}, nil
   215  		},
   216  		NewWorker: func(actual resumer.Config) (worker.Worker, error) {
   217  			return expect, nil
   218  		},
   219  	})
   220  
   221  	actual, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{
   222  		"agent":      &fakeAgent{},
   223  		"api-caller": newFakeAPICaller(multiwatcher.JobManageModel),
   224  	}))
   225  	c.Check(err, jc.ErrorIsNil)
   226  	c.Check(actual, gc.Equals, expect)
   227  }
   228  
   229  // fakeFacade should not be called.
   230  type fakeFacade struct {
   231  	resumer.Facade
   232  }
   233  
   234  // fakeClock should not be called.
   235  type fakeClock struct {
   236  	clock.Clock
   237  }
   238  
   239  // fakeWorker should not be called.
   240  type fakeWorker struct {
   241  	worker.Worker
   242  }
   243  
   244  // fakeAgent exists to expose a tag via CurrentConfig().Tag().
   245  type fakeAgent struct {
   246  	agent.Agent
   247  }
   248  
   249  // CurrentConfig returns an agent.Config with a working Tag() method.
   250  func (a *fakeAgent) CurrentConfig() agent.Config {
   251  	return &fakeConfig{}
   252  }
   253  
   254  // fakeConfig exists to expose Tag.
   255  type fakeConfig struct {
   256  	agent.Config
   257  }
   258  
   259  // Tag returns a Tag.
   260  func (c *fakeConfig) Tag() names.Tag {
   261  	return names.NewMachineTag("123")
   262  }
   263  
   264  func newFakeAPICaller(jobs ...multiwatcher.MachineJob) *fakeAPICaller {
   265  	return &fakeAPICaller{jobs: jobs}
   266  }
   267  
   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 {
   272  	base.APICaller
   273  	stub *testing.Stub
   274  	jobs []multiwatcher.MachineJob
   275  }
   276  
   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 {
   279  	if f.stub != nil {
   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 {
   288  			return err
   289  		}
   290  	}
   291  
   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{
   296  			{Jobs: jobs},
   297  		}
   298  	}
   299  	return nil
   300  }
   301  
   302  // BestFacadeVersion is part of the base.APICaller interface.
   303  func (*fakeAPICaller) BestFacadeVersion(facade string) int {
   304  	return 42
   305  }