github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/instancemutater/manifold_test.go (about)

     1  // Copyright 2019 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package instancemutater_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  	"github.com/juju/testing"
    10  	worker "github.com/juju/worker/v3"
    11  	"github.com/juju/worker/v3/dependency"
    12  	"go.uber.org/mock/gomock"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/agent"
    16  	"github.com/juju/juju/api/base"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/worker/instancemutater"
    19  	"github.com/juju/juju/worker/instancemutater/mocks"
    20  )
    21  
    22  type modelManifoldConfigSuite struct {
    23  	testing.IsolationSuite
    24  }
    25  
    26  var _ = gc.Suite(&modelManifoldConfigSuite{})
    27  
    28  func (s *modelManifoldConfigSuite) TestInvalidConfigValidate(c *gc.C) {
    29  	ctrl := gomock.NewController(c)
    30  	defer ctrl.Finish()
    31  
    32  	testcases := []struct {
    33  		description string
    34  		config      instancemutater.ModelManifoldConfig
    35  		err         string
    36  	}{
    37  		{
    38  			description: "Test empty configuration",
    39  			config:      instancemutater.ModelManifoldConfig{},
    40  			err:         "nil Logger not valid",
    41  		},
    42  		{
    43  			description: "Test no Logger",
    44  			config:      instancemutater.ModelManifoldConfig{},
    45  			err:         "nil Logger not valid",
    46  		},
    47  		{
    48  			description: "Test no new worker constructor",
    49  			config: instancemutater.ModelManifoldConfig{
    50  				Logger: mocks.NewMockLogger(ctrl),
    51  			},
    52  			err: "nil NewWorker not valid",
    53  		},
    54  		{
    55  			description: "Test no new client constructor",
    56  			config: instancemutater.ModelManifoldConfig{
    57  				Logger: mocks.NewMockLogger(ctrl),
    58  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
    59  					return mocks.NewMockWorker(ctrl), nil
    60  				},
    61  			},
    62  			err: "nil NewClient not valid",
    63  		},
    64  		{
    65  			description: "Test no agent name",
    66  			config: instancemutater.ModelManifoldConfig{
    67  				Logger: mocks.NewMockLogger(ctrl),
    68  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
    69  					return mocks.NewMockWorker(ctrl), nil
    70  				},
    71  				NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
    72  					return mocks.NewMockInstanceMutaterAPI(ctrl)
    73  				},
    74  			},
    75  			err: "empty AgentName not valid",
    76  		},
    77  		{
    78  			description: "Test no environ name",
    79  			config: instancemutater.ModelManifoldConfig{
    80  				Logger: mocks.NewMockLogger(ctrl),
    81  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
    82  					return mocks.NewMockWorker(ctrl), nil
    83  				},
    84  				NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
    85  					return mocks.NewMockInstanceMutaterAPI(ctrl)
    86  				},
    87  				AgentName: "agent",
    88  			},
    89  			err: "empty EnvironName not valid",
    90  		},
    91  		{
    92  			description: "Test no api caller name",
    93  			config: instancemutater.ModelManifoldConfig{
    94  				Logger: mocks.NewMockLogger(ctrl),
    95  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
    96  					return mocks.NewMockWorker(ctrl), nil
    97  				},
    98  				NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
    99  					return mocks.NewMockInstanceMutaterAPI(ctrl)
   100  				},
   101  				AgentName:   "agent",
   102  				EnvironName: "environ",
   103  			},
   104  			err: "empty APICallerName not valid",
   105  		},
   106  	}
   107  	for i, test := range testcases {
   108  		c.Logf("%d %s", i, test.description)
   109  		err := test.config.Validate()
   110  		c.Assert(err, gc.ErrorMatches, test.err)
   111  	}
   112  }
   113  
   114  func (s *modelManifoldConfigSuite) TestValidConfigValidate(c *gc.C) {
   115  	ctrl := gomock.NewController(c)
   116  	defer ctrl.Finish()
   117  
   118  	config := instancemutater.ModelManifoldConfig{
   119  		Logger: mocks.NewMockLogger(ctrl),
   120  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   121  			return mocks.NewMockWorker(ctrl), nil
   122  		},
   123  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   124  			return mocks.NewMockInstanceMutaterAPI(ctrl)
   125  		},
   126  		AgentName:     "agent",
   127  		EnvironName:   "environ",
   128  		APICallerName: "api-caller",
   129  	}
   130  	err := config.Validate()
   131  	c.Assert(err, gc.IsNil)
   132  }
   133  
   134  type environAPIManifoldSuite struct {
   135  	testing.IsolationSuite
   136  
   137  	logger    *mocks.MockLogger
   138  	context   *mocks.MockContext
   139  	agent     *mocks.MockAgent
   140  	environ   *mocks.MockEnviron
   141  	apiCaller *mocks.MockAPICaller
   142  	worker    *mocks.MockWorker
   143  }
   144  
   145  var _ = gc.Suite(&environAPIManifoldSuite{})
   146  
   147  func (s *environAPIManifoldSuite) setup(c *gc.C) *gomock.Controller {
   148  	ctrl := gomock.NewController(c)
   149  
   150  	s.logger = mocks.NewMockLogger(ctrl)
   151  	s.context = mocks.NewMockContext(ctrl)
   152  	s.agent = mocks.NewMockAgent(ctrl)
   153  	s.environ = mocks.NewMockEnviron(ctrl)
   154  	s.apiCaller = mocks.NewMockAPICaller(ctrl)
   155  	s.worker = mocks.NewMockWorker(ctrl)
   156  
   157  	return ctrl
   158  }
   159  
   160  func (s *environAPIManifoldSuite) TestStartReturnsWorker(c *gc.C) {
   161  	defer s.setup(c).Finish()
   162  
   163  	cExp := s.context.EXPECT()
   164  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   165  	cExp.Get("foobar", gomock.Any()).SetArg(1, s.environ).Return(nil)
   166  	cExp.Get("baz", gomock.Any()).SetArg(1, s.apiCaller).Return(nil)
   167  
   168  	config := instancemutater.EnvironAPIConfig{
   169  		EnvironName:   "foobar",
   170  		APICallerName: "baz",
   171  		AgentName:     "moon",
   172  	}
   173  	manifold := instancemutater.EnvironAPIManifold(config, func(environ environs.Environ, apiCaller base.APICaller, agent agent.Agent) (worker.Worker, error) {
   174  		c.Assert(environ, gc.Equals, s.environ)
   175  		c.Assert(apiCaller, gc.Equals, s.apiCaller)
   176  		c.Assert(agent, gc.Equals, s.agent)
   177  
   178  		return s.worker, nil
   179  	})
   180  	result, err := manifold.Start(s.context)
   181  	c.Assert(err, gc.IsNil)
   182  	c.Assert(result, gc.Equals, s.worker)
   183  }
   184  
   185  func (s *environAPIManifoldSuite) TestMissingEnvironFromContext(c *gc.C) {
   186  	defer s.setup(c).Finish()
   187  
   188  	cExp := s.context.EXPECT()
   189  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   190  	cExp.Get("foobar", gomock.Any()).Return(errors.New("missing"))
   191  
   192  	config := instancemutater.EnvironAPIConfig{
   193  		EnvironName:   "foobar",
   194  		APICallerName: "baz",
   195  		AgentName:     "moon",
   196  	}
   197  	manifold := instancemutater.EnvironAPIManifold(config, func(environs.Environ, base.APICaller, agent.Agent) (worker.Worker, error) {
   198  		c.Fail()
   199  		return nil, nil
   200  	})
   201  	_, err := manifold.Start(s.context)
   202  	c.Assert(err, gc.ErrorMatches, "missing")
   203  }
   204  
   205  func (s *environAPIManifoldSuite) TestMissingAPICallerFromContext(c *gc.C) {
   206  	defer s.setup(c).Finish()
   207  
   208  	cExp := s.context.EXPECT()
   209  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   210  	cExp.Get("foobar", gomock.Any()).SetArg(1, s.environ).Return(nil)
   211  	cExp.Get("baz", gomock.Any()).Return(errors.New("missing"))
   212  
   213  	config := instancemutater.EnvironAPIConfig{
   214  		EnvironName:   "foobar",
   215  		APICallerName: "baz",
   216  		AgentName:     "moon",
   217  	}
   218  	manifold := instancemutater.EnvironAPIManifold(config, func(environs.Environ, base.APICaller, agent.Agent) (worker.Worker, error) {
   219  		c.Fail()
   220  		return nil, nil
   221  	})
   222  	_, err := manifold.Start(s.context)
   223  	c.Assert(err, gc.ErrorMatches, "missing")
   224  }
   225  
   226  type modelManifoldSuite struct {
   227  	testing.IsolationSuite
   228  
   229  	logger      *mocks.MockLogger
   230  	context     *mocks.MockContext
   231  	agent       *mocks.MockAgent
   232  	agentConfig *mocks.MockConfig
   233  	environ     environShim
   234  	apiCaller   *mocks.MockAPICaller
   235  	worker      *mocks.MockWorker
   236  	api         *mocks.MockInstanceMutaterAPI
   237  }
   238  
   239  var _ = gc.Suite(&modelManifoldSuite{})
   240  
   241  func (s *modelManifoldSuite) setup(c *gc.C) *gomock.Controller {
   242  	ctrl := gomock.NewController(c)
   243  
   244  	s.logger = mocks.NewMockLogger(ctrl)
   245  	s.context = mocks.NewMockContext(ctrl)
   246  	s.agent = mocks.NewMockAgent(ctrl)
   247  	s.agentConfig = mocks.NewMockConfig(ctrl)
   248  	s.environ = environShim{
   249  		MockEnviron:     mocks.NewMockEnviron(ctrl),
   250  		MockLXDProfiler: mocks.NewMockLXDProfiler(ctrl),
   251  	}
   252  	s.apiCaller = mocks.NewMockAPICaller(ctrl)
   253  	s.worker = mocks.NewMockWorker(ctrl)
   254  	s.api = mocks.NewMockInstanceMutaterAPI(ctrl)
   255  
   256  	return ctrl
   257  }
   258  
   259  func (s *modelManifoldSuite) TestNewWorkerIsCalled(c *gc.C) {
   260  	defer s.setup(c).Finish()
   261  
   262  	s.behaviourContext()
   263  	s.behaviourAgent()
   264  
   265  	config := instancemutater.ModelManifoldConfig{
   266  		EnvironName:   "foobar",
   267  		APICallerName: "baz",
   268  		AgentName:     "moon",
   269  		Logger:        s.logger,
   270  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   271  			return s.worker, nil
   272  		},
   273  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   274  			return s.api
   275  		},
   276  	}
   277  	manifold := instancemutater.ModelManifold(config)
   278  	result, err := manifold.Start(s.context)
   279  	c.Assert(err, gc.IsNil)
   280  	c.Assert(result, gc.Equals, s.worker)
   281  }
   282  
   283  func (s *modelManifoldSuite) TestNewWorkerFromK8sController(c *gc.C) {
   284  	defer s.setup(c).Finish()
   285  
   286  	s.behaviourContext()
   287  	s.behaviorK8sController()
   288  
   289  	config := instancemutater.ModelManifoldConfig{
   290  		EnvironName:   "foobar",
   291  		APICallerName: "baz",
   292  		AgentName:     "moon",
   293  		Logger:        s.logger,
   294  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   295  			return s.worker, nil
   296  		},
   297  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   298  			return s.api
   299  		},
   300  	}
   301  	manifold := instancemutater.ModelManifold(config)
   302  	result, err := manifold.Start(s.context)
   303  	c.Assert(err, gc.IsNil)
   304  	c.Assert(result, gc.Equals, s.worker)
   305  }
   306  
   307  func (s *modelManifoldSuite) TestNewWorkerReturnsError(c *gc.C) {
   308  	defer s.setup(c).Finish()
   309  
   310  	s.behaviourContext()
   311  	s.behaviourAgent()
   312  
   313  	config := instancemutater.ModelManifoldConfig{
   314  		EnvironName:   "foobar",
   315  		APICallerName: "baz",
   316  		AgentName:     "moon",
   317  		Logger:        s.logger,
   318  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   319  			return nil, errors.New("errored")
   320  		},
   321  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   322  			return s.api
   323  		},
   324  	}
   325  	manifold := instancemutater.ModelManifold(config)
   326  	_, err := manifold.Start(s.context)
   327  	c.Assert(err, gc.ErrorMatches, "cannot start model instance-mutater worker: errored")
   328  }
   329  
   330  func (s *modelManifoldSuite) TestConfigValidatesForMissingWorker(c *gc.C) {
   331  	defer s.setup(c).Finish()
   332  
   333  	s.behaviourContext()
   334  
   335  	config := instancemutater.ModelManifoldConfig{
   336  		EnvironName:   "foobar",
   337  		APICallerName: "baz",
   338  		AgentName:     "moon",
   339  		Logger:        s.logger,
   340  	}
   341  	manifold := instancemutater.ModelManifold(config)
   342  	_, err := manifold.Start(s.context)
   343  	c.Assert(err, gc.ErrorMatches, "nil NewWorker not valid")
   344  }
   345  
   346  func (s *modelManifoldSuite) TestConfigValidatesForMissingClient(c *gc.C) {
   347  	defer s.setup(c).Finish()
   348  
   349  	s.behaviourContext()
   350  
   351  	config := instancemutater.ModelManifoldConfig{
   352  		EnvironName:   "foobar",
   353  		APICallerName: "baz",
   354  		AgentName:     "moon",
   355  		Logger:        s.logger,
   356  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   357  			return s.worker, nil
   358  		},
   359  	}
   360  	manifold := instancemutater.ModelManifold(config)
   361  	_, err := manifold.Start(s.context)
   362  	c.Assert(err, gc.ErrorMatches, "nil NewClient not valid")
   363  }
   364  
   365  func (s *modelManifoldSuite) behaviourContext() {
   366  	cExp := s.context.EXPECT()
   367  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   368  	cExp.Get("foobar", gomock.Any()).SetArg(1, s.environ).Return(nil)
   369  	cExp.Get("baz", gomock.Any()).SetArg(1, s.apiCaller).Return(nil)
   370  }
   371  
   372  func (s *modelManifoldSuite) behaviourAgent() {
   373  	aExp := s.agent.EXPECT()
   374  	aExp.CurrentConfig().Return(s.agentConfig)
   375  
   376  	cExp := s.agentConfig.EXPECT()
   377  	cExp.Tag().Return(names.MachineTag{})
   378  }
   379  
   380  func (s *modelManifoldSuite) behaviorK8sController() {
   381  	aExp := s.agent.EXPECT()
   382  	aExp.CurrentConfig().Return(s.agentConfig)
   383  
   384  	cExp := s.agentConfig.EXPECT()
   385  	cExp.Tag().Return(names.ControllerAgentTag{})
   386  }
   387  
   388  type environShim struct {
   389  	*mocks.MockEnviron
   390  	*mocks.MockLXDProfiler
   391  }
   392  
   393  type machineManifoldConfigSuite struct {
   394  	testing.IsolationSuite
   395  }
   396  
   397  var _ = gc.Suite(&machineManifoldConfigSuite{})
   398  
   399  func (s *machineManifoldConfigSuite) TestInvalidConfigValidate(c *gc.C) {
   400  	ctrl := gomock.NewController(c)
   401  	defer ctrl.Finish()
   402  
   403  	testcases := []struct {
   404  		description string
   405  		config      instancemutater.MachineManifoldConfig
   406  		err         string
   407  	}{
   408  		{
   409  			description: "Test empty configuration",
   410  			config:      instancemutater.MachineManifoldConfig{},
   411  			err:         "nil Logger not valid",
   412  		},
   413  		{
   414  			description: "Test no Logger",
   415  			config:      instancemutater.MachineManifoldConfig{},
   416  			err:         "nil Logger not valid",
   417  		},
   418  		{
   419  			description: "Test no new worker constructor",
   420  			config: instancemutater.MachineManifoldConfig{
   421  				Logger: mocks.NewMockLogger(ctrl),
   422  			},
   423  			err: "nil NewWorker not valid",
   424  		},
   425  		{
   426  			description: "Test no new client constructor",
   427  			config: instancemutater.MachineManifoldConfig{
   428  				Logger: mocks.NewMockLogger(ctrl),
   429  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   430  					return mocks.NewMockWorker(ctrl), nil
   431  				},
   432  			},
   433  			err: "nil NewClient not valid",
   434  		},
   435  		{
   436  			description: "Test no agent name",
   437  			config: instancemutater.MachineManifoldConfig{
   438  				Logger: mocks.NewMockLogger(ctrl),
   439  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   440  					return mocks.NewMockWorker(ctrl), nil
   441  				},
   442  				NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   443  					return mocks.NewMockInstanceMutaterAPI(ctrl)
   444  				},
   445  			},
   446  			err: "empty AgentName not valid",
   447  		},
   448  		{
   449  			description: "Test no environ name",
   450  			config: instancemutater.MachineManifoldConfig{
   451  				Logger: mocks.NewMockLogger(ctrl),
   452  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   453  					return mocks.NewMockWorker(ctrl), nil
   454  				},
   455  				NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   456  					return mocks.NewMockInstanceMutaterAPI(ctrl)
   457  				},
   458  				AgentName: "agent",
   459  			},
   460  			err: "empty BrokerName not valid",
   461  		},
   462  		{
   463  			description: "Test no api caller name",
   464  			config: instancemutater.MachineManifoldConfig{
   465  				Logger: mocks.NewMockLogger(ctrl),
   466  				NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   467  					return mocks.NewMockWorker(ctrl), nil
   468  				},
   469  				NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   470  					return mocks.NewMockInstanceMutaterAPI(ctrl)
   471  				},
   472  				AgentName:  "agent",
   473  				BrokerName: "broker",
   474  			},
   475  			err: "empty APICallerName not valid",
   476  		},
   477  	}
   478  	for i, test := range testcases {
   479  		c.Logf("%d %s", i, test.description)
   480  		err := test.config.Validate()
   481  		c.Assert(err, gc.ErrorMatches, test.err)
   482  	}
   483  }
   484  
   485  func (s *machineManifoldConfigSuite) TestValidConfigValidate(c *gc.C) {
   486  	ctrl := gomock.NewController(c)
   487  	defer ctrl.Finish()
   488  
   489  	config := instancemutater.MachineManifoldConfig{
   490  		Logger: mocks.NewMockLogger(ctrl),
   491  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   492  			return mocks.NewMockWorker(ctrl), nil
   493  		},
   494  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   495  			return mocks.NewMockInstanceMutaterAPI(ctrl)
   496  		},
   497  		AgentName:     "agent",
   498  		BrokerName:    "broker",
   499  		APICallerName: "api-caller",
   500  	}
   501  	err := config.Validate()
   502  	c.Assert(err, gc.IsNil)
   503  }
   504  
   505  type brokerAPIManifoldSuite struct {
   506  	testing.IsolationSuite
   507  
   508  	logger    *mocks.MockLogger
   509  	context   *mocks.MockContext
   510  	agent     *mocks.MockAgent
   511  	broker    *mocks.MockInstanceBroker
   512  	apiCaller *mocks.MockAPICaller
   513  	worker    *mocks.MockWorker
   514  }
   515  
   516  var _ = gc.Suite(&brokerAPIManifoldSuite{})
   517  
   518  func (s *brokerAPIManifoldSuite) setup(c *gc.C) *gomock.Controller {
   519  	ctrl := gomock.NewController(c)
   520  
   521  	s.logger = mocks.NewMockLogger(ctrl)
   522  	s.context = mocks.NewMockContext(ctrl)
   523  	s.agent = mocks.NewMockAgent(ctrl)
   524  	s.broker = mocks.NewMockInstanceBroker(ctrl)
   525  	s.apiCaller = mocks.NewMockAPICaller(ctrl)
   526  	s.worker = mocks.NewMockWorker(ctrl)
   527  
   528  	return ctrl
   529  }
   530  
   531  func (s *brokerAPIManifoldSuite) TestStartReturnsWorker(c *gc.C) {
   532  	defer s.setup(c).Finish()
   533  
   534  	cExp := s.context.EXPECT()
   535  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   536  	cExp.Get("foobar", gomock.Any()).SetArg(1, s.broker).Return(nil)
   537  	cExp.Get("baz", gomock.Any()).SetArg(1, s.apiCaller).Return(nil)
   538  
   539  	config := instancemutater.BrokerAPIConfig{
   540  		BrokerName:    "foobar",
   541  		APICallerName: "baz",
   542  		AgentName:     "moon",
   543  	}
   544  	manifold := instancemutater.BrokerAPIManifold(config, func(broker environs.InstanceBroker, apiCaller base.APICaller, agent agent.Agent) (worker.Worker, error) {
   545  		c.Assert(broker, gc.Equals, s.broker)
   546  		c.Assert(apiCaller, gc.Equals, s.apiCaller)
   547  		c.Assert(agent, gc.Equals, s.agent)
   548  
   549  		return s.worker, nil
   550  	})
   551  	result, err := manifold.Start(s.context)
   552  	c.Assert(err, gc.IsNil)
   553  	c.Assert(result, gc.Equals, s.worker)
   554  }
   555  
   556  func (s *brokerAPIManifoldSuite) TestMissingBrokerFromContext(c *gc.C) {
   557  	defer s.setup(c).Finish()
   558  
   559  	cExp := s.context.EXPECT()
   560  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   561  	cExp.Get("foobar", gomock.Any()).Return(errors.New("missing"))
   562  
   563  	config := instancemutater.BrokerAPIConfig{
   564  		BrokerName:    "foobar",
   565  		APICallerName: "baz",
   566  		AgentName:     "moon",
   567  	}
   568  	manifold := instancemutater.BrokerAPIManifold(config, func(environs.InstanceBroker, base.APICaller, agent.Agent) (worker.Worker, error) {
   569  		c.Fail()
   570  		return nil, nil
   571  	})
   572  	_, err := manifold.Start(s.context)
   573  	c.Assert(err, gc.ErrorMatches, "missing")
   574  }
   575  
   576  func (s *brokerAPIManifoldSuite) TestMissingAPICallerFromContext(c *gc.C) {
   577  	defer s.setup(c).Finish()
   578  
   579  	cExp := s.context.EXPECT()
   580  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   581  	cExp.Get("foobar", gomock.Any()).SetArg(1, s.broker).Return(nil)
   582  	cExp.Get("baz", gomock.Any()).Return(errors.New("missing"))
   583  
   584  	config := instancemutater.BrokerAPIConfig{
   585  		BrokerName:    "foobar",
   586  		APICallerName: "baz",
   587  		AgentName:     "moon",
   588  	}
   589  	manifold := instancemutater.BrokerAPIManifold(config, func(environs.InstanceBroker, base.APICaller, agent.Agent) (worker.Worker, error) {
   590  		c.Fail()
   591  		return nil, nil
   592  	})
   593  	_, err := manifold.Start(s.context)
   594  	c.Assert(err, gc.ErrorMatches, "missing")
   595  }
   596  
   597  type machineManifoldSuite struct {
   598  	testing.IsolationSuite
   599  
   600  	logger      *mocks.MockLogger
   601  	context     *mocks.MockContext
   602  	agent       *mocks.MockAgent
   603  	agentConfig *mocks.MockConfig
   604  	broker      brokerShim
   605  	apiCaller   *mocks.MockAPICaller
   606  	worker      *mocks.MockWorker
   607  	api         *mocks.MockInstanceMutaterAPI
   608  }
   609  
   610  var _ = gc.Suite(&machineManifoldSuite{})
   611  
   612  func (s *machineManifoldSuite) setup(c *gc.C) *gomock.Controller {
   613  	ctrl := gomock.NewController(c)
   614  
   615  	s.logger = mocks.NewMockLogger(ctrl)
   616  	s.context = mocks.NewMockContext(ctrl)
   617  	s.agent = mocks.NewMockAgent(ctrl)
   618  	s.agentConfig = mocks.NewMockConfig(ctrl)
   619  	s.broker = brokerShim{
   620  		MockInstanceBroker: mocks.NewMockInstanceBroker(ctrl),
   621  		MockLXDProfiler:    mocks.NewMockLXDProfiler(ctrl),
   622  	}
   623  	s.apiCaller = mocks.NewMockAPICaller(ctrl)
   624  	s.worker = mocks.NewMockWorker(ctrl)
   625  	s.api = mocks.NewMockInstanceMutaterAPI(ctrl)
   626  
   627  	return ctrl
   628  }
   629  
   630  func (s *machineManifoldSuite) TestNewWorkerIsCalled(c *gc.C) {
   631  	defer s.setup(c).Finish()
   632  
   633  	s.behaviourContext()
   634  	s.behaviourAgent()
   635  
   636  	config := instancemutater.MachineManifoldConfig{
   637  		BrokerName:    "foobar",
   638  		APICallerName: "baz",
   639  		AgentName:     "moon",
   640  		Logger:        s.logger,
   641  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   642  			return s.worker, nil
   643  		},
   644  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   645  			return s.api
   646  		},
   647  	}
   648  	manifold := instancemutater.MachineManifold(config)
   649  	result, err := manifold.Start(s.context)
   650  	c.Assert(err, gc.IsNil)
   651  	c.Assert(result, gc.Equals, s.worker)
   652  }
   653  
   654  func (s *machineManifoldSuite) TestNewWorkerIsRejectedForK8sController(c *gc.C) {
   655  	defer s.setup(c).Finish()
   656  
   657  	s.behaviourContext()
   658  	s.behaviorK8sController()
   659  
   660  	config := instancemutater.MachineManifoldConfig{
   661  		BrokerName:    "foobar",
   662  		APICallerName: "baz",
   663  		AgentName:     "moon",
   664  		Logger:        s.logger,
   665  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   666  			return s.worker, nil
   667  		},
   668  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   669  			return s.api
   670  		},
   671  	}
   672  	manifold := instancemutater.MachineManifold(config)
   673  	result, err := manifold.Start(s.context)
   674  	c.Assert(err, gc.Equals, dependency.ErrUninstall)
   675  	c.Assert(result, gc.IsNil)
   676  }
   677  
   678  func (s *machineManifoldSuite) TestNewWorkerReturnsError(c *gc.C) {
   679  	defer s.setup(c).Finish()
   680  
   681  	s.behaviourContext()
   682  	s.behaviourAgent()
   683  
   684  	config := instancemutater.MachineManifoldConfig{
   685  		BrokerName:    "foobar",
   686  		APICallerName: "baz",
   687  		AgentName:     "moon",
   688  		Logger:        s.logger,
   689  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   690  			return nil, errors.New("errored")
   691  		},
   692  		NewClient: func(base.APICaller) instancemutater.InstanceMutaterAPI {
   693  			return s.api
   694  		},
   695  	}
   696  	manifold := instancemutater.MachineManifold(config)
   697  	_, err := manifold.Start(s.context)
   698  	c.Assert(err, gc.ErrorMatches, "cannot start machine instancemutater worker: errored")
   699  }
   700  
   701  func (s *machineManifoldSuite) TestConfigValidatesForMissingWorker(c *gc.C) {
   702  	defer s.setup(c).Finish()
   703  
   704  	s.behaviourContext()
   705  
   706  	config := instancemutater.MachineManifoldConfig{
   707  		BrokerName:    "foobar",
   708  		APICallerName: "baz",
   709  		AgentName:     "moon",
   710  		Logger:        s.logger,
   711  	}
   712  	manifold := instancemutater.MachineManifold(config)
   713  	_, err := manifold.Start(s.context)
   714  	c.Assert(err, gc.ErrorMatches, "nil NewWorker not valid")
   715  }
   716  
   717  func (s *machineManifoldSuite) TestConfigValidatesForMissingClient(c *gc.C) {
   718  	defer s.setup(c).Finish()
   719  
   720  	s.behaviourContext()
   721  
   722  	config := instancemutater.MachineManifoldConfig{
   723  		BrokerName:    "foobar",
   724  		APICallerName: "baz",
   725  		AgentName:     "moon",
   726  		Logger:        s.logger,
   727  		NewWorker: func(cfg instancemutater.Config) (worker.Worker, error) {
   728  			return s.worker, nil
   729  		},
   730  	}
   731  	manifold := instancemutater.MachineManifold(config)
   732  	_, err := manifold.Start(s.context)
   733  	c.Assert(err, gc.ErrorMatches, "nil NewClient not valid")
   734  }
   735  
   736  func (s *machineManifoldSuite) behaviourContext() {
   737  	cExp := s.context.EXPECT()
   738  	cExp.Get("moon", gomock.Any()).SetArg(1, s.agent).Return(nil)
   739  	cExp.Get("foobar", gomock.Any()).SetArg(1, s.broker).Return(nil)
   740  	cExp.Get("baz", gomock.Any()).SetArg(1, s.apiCaller).Return(nil)
   741  }
   742  
   743  func (s *machineManifoldSuite) behaviourAgent() {
   744  	aExp := s.agent.EXPECT()
   745  	aExp.CurrentConfig().Return(s.agentConfig)
   746  
   747  	cExp := s.agentConfig.EXPECT()
   748  	cExp.Tag().Return(names.MachineTag{})
   749  }
   750  
   751  func (s *machineManifoldSuite) behaviorK8sController() {
   752  	aExp := s.agent.EXPECT()
   753  	aExp.CurrentConfig().Return(s.agentConfig)
   754  
   755  	cExp := s.agentConfig.EXPECT()
   756  	cExp.Tag().Return(names.ControllerAgentTag{})
   757  
   758  	lExp := s.logger.EXPECT()
   759  	lExp.Warningf(gomock.Any(), "controller")
   760  }
   761  
   762  type brokerShim struct {
   763  	*mocks.MockInstanceBroker
   764  	*mocks.MockLXDProfiler
   765  }