github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cmd/jujud/agent/machine/servinginfo_setter_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package machine_test
     5  
     6  import (
     7  	jc "github.com/juju/testing/checkers"
     8  	gc "gopkg.in/check.v1"
     9  	"gopkg.in/juju/names.v2"
    10  
    11  	coreagent "github.com/juju/juju/agent"
    12  	basetesting "github.com/juju/juju/api/base/testing"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/cmd/jujud/agent/machine"
    15  	"github.com/juju/juju/state/multiwatcher"
    16  	"github.com/juju/juju/testing"
    17  	"github.com/juju/juju/worker/dependency"
    18  	dt "github.com/juju/juju/worker/dependency/testing"
    19  )
    20  
    21  type ServingInfoSetterSuite struct {
    22  	testing.BaseSuite
    23  	manifold dependency.Manifold
    24  }
    25  
    26  var _ = gc.Suite(&ServingInfoSetterSuite{})
    27  
    28  func (s *ServingInfoSetterSuite) SetUpTest(c *gc.C) {
    29  	s.manifold = machine.ServingInfoSetterManifold(machine.ServingInfoSetterConfig{
    30  		AgentName:     "agent",
    31  		APICallerName: "api-caller",
    32  	})
    33  }
    34  
    35  func (s *ServingInfoSetterSuite) TestInputs(c *gc.C) {
    36  	c.Assert(s.manifold.Inputs, jc.SameContents, []string{
    37  		"agent",
    38  		"api-caller",
    39  	})
    40  }
    41  
    42  func (s *ServingInfoSetterSuite) TestStartAgentMissing(c *gc.C) {
    43  	context := dt.StubContext(nil, map[string]interface{}{
    44  		"agent": dependency.ErrMissing,
    45  	})
    46  	worker, err := s.manifold.Start(context)
    47  	c.Check(worker, gc.IsNil)
    48  	c.Check(err, gc.Equals, dependency.ErrMissing)
    49  }
    50  
    51  func (s *ServingInfoSetterSuite) TestStartAPICallerMissing(c *gc.C) {
    52  	context := dt.StubContext(nil, map[string]interface{}{
    53  		"agent":      &mockAgent{},
    54  		"api-caller": dependency.ErrMissing,
    55  	})
    56  	worker, err := s.manifold.Start(context)
    57  	c.Check(worker, gc.IsNil)
    58  	c.Check(err, gc.Equals, dependency.ErrMissing)
    59  }
    60  
    61  func (s *ServingInfoSetterSuite) TestNotMachine(c *gc.C) {
    62  	a := &mockAgent{
    63  		conf: mockConfig{tag: names.NewUnitTag("foo/0")},
    64  	}
    65  	context := dt.StubContext(nil, map[string]interface{}{
    66  		"agent": a,
    67  	})
    68  	worker, err := s.manifold.Start(context)
    69  	c.Check(worker, gc.IsNil)
    70  	c.Check(err, gc.ErrorMatches, "agent's tag is not a machine tag")
    71  }
    72  
    73  func (s *ServingInfoSetterSuite) TestEntityLookupFailure(c *gc.C) {
    74  	// Set up a fake Agent and APICaller
    75  	a := &mockAgent{}
    76  	apiCaller := basetesting.APICallerFunc(
    77  		func(objType string, version int, id, request string, args, response interface{}) error {
    78  			c.Assert(objType, gc.Equals, "Agent")
    79  			switch request {
    80  			case "GetEntities":
    81  				c.Assert(args.(params.Entities).Entities, gc.HasLen, 1)
    82  				result := response.(*params.AgentGetEntitiesResults)
    83  				result.Entities = []params.AgentGetEntitiesResult{{
    84  					Error: &params.Error{Message: "boom"},
    85  				}}
    86  			default:
    87  				c.Fatalf("not sure how to handle: %q", request)
    88  			}
    89  			return nil
    90  		},
    91  	)
    92  	// Call the manifold's start func with a fake resource getter that
    93  	// returns the fake Agent and APICaller
    94  	context := dt.StubContext(nil, map[string]interface{}{
    95  		"agent":      a,
    96  		"api-caller": apiCaller,
    97  	})
    98  	w, err := s.manifold.Start(context)
    99  	c.Assert(w, gc.IsNil)
   100  	c.Assert(err, gc.ErrorMatches, "checking controller status: boom")
   101  }
   102  
   103  func (s *ServingInfoSetterSuite) startManifold(c *gc.C, a coreagent.Agent, mockAPIPort int) {
   104  	apiCaller := basetesting.APICallerFunc(
   105  		func(objType string, version int, id, request string, args, response interface{}) error {
   106  			c.Assert(objType, gc.Equals, "Agent")
   107  			switch request {
   108  			case "GetEntities":
   109  				c.Assert(args.(params.Entities).Entities, gc.HasLen, 1)
   110  				result := response.(*params.AgentGetEntitiesResults)
   111  				result.Entities = []params.AgentGetEntitiesResult{{
   112  					Jobs: []multiwatcher.MachineJob{multiwatcher.JobManageModel},
   113  				}}
   114  			case "StateServingInfo":
   115  				result := response.(*params.StateServingInfo)
   116  				*result = params.StateServingInfo{
   117  					Cert:       "cert",
   118  					PrivateKey: "key",
   119  					APIPort:    mockAPIPort,
   120  				}
   121  			default:
   122  				c.Fatalf("not sure how to handle: %q", request)
   123  			}
   124  			return nil
   125  		},
   126  	)
   127  	context := dt.StubContext(nil, map[string]interface{}{
   128  		"agent":      a,
   129  		"api-caller": apiCaller,
   130  	})
   131  	w, err := s.manifold.Start(context)
   132  	c.Assert(w, gc.IsNil)
   133  	c.Assert(err, gc.Equals, dependency.ErrUninstall)
   134  }
   135  
   136  func (s *ServingInfoSetterSuite) TestJobManageEnviron(c *gc.C) {
   137  	// State serving info should be set for machines with JobManageEnviron.
   138  	const mockAPIPort = 1234
   139  
   140  	a := &mockAgent{}
   141  	s.startManifold(c, a, mockAPIPort)
   142  
   143  	// Verify that the state serving info was actually set.
   144  	c.Assert(a.conf.ssiSet, jc.IsTrue)
   145  	c.Assert(a.conf.ssi.APIPort, gc.Equals, mockAPIPort)
   146  	c.Assert(a.conf.ssi.Cert, gc.Equals, "cert")
   147  	c.Assert(a.conf.ssi.PrivateKey, gc.Equals, "key")
   148  }
   149  
   150  func (s *ServingInfoSetterSuite) TestJobManageEnvironNotOverwriteCert(c *gc.C) {
   151  	// State serving info should be set for machines with JobManageEnviron.
   152  	const mockAPIPort = 1234
   153  
   154  	a := &mockAgent{}
   155  	existingCert := "some cert set by certupdater"
   156  	existingKey := "some key set by certupdater"
   157  	a.conf.SetStateServingInfo(params.StateServingInfo{
   158  		Cert:       existingCert,
   159  		PrivateKey: existingKey,
   160  	})
   161  
   162  	s.startManifold(c, a, mockAPIPort)
   163  
   164  	// Verify that the state serving info was actually set.
   165  	c.Assert(a.conf.ssiSet, jc.IsTrue)
   166  	c.Assert(a.conf.ssi.APIPort, gc.Equals, mockAPIPort)
   167  	c.Assert(a.conf.ssi.Cert, gc.Equals, existingCert)
   168  	c.Assert(a.conf.ssi.PrivateKey, gc.Equals, existingKey)
   169  }
   170  
   171  func (s *ServingInfoSetterSuite) TestJobHostUnits(c *gc.C) {
   172  	// State serving info should not be set for JobHostUnits.
   173  	s.checkNotController(c, multiwatcher.JobHostUnits)
   174  }
   175  
   176  func (s *ServingInfoSetterSuite) checkNotController(c *gc.C, job multiwatcher.MachineJob) {
   177  	a := &mockAgent{}
   178  	apiCaller := basetesting.APICallerFunc(
   179  		func(objType string, version int, id, request string, args, response interface{}) error {
   180  			c.Assert(objType, gc.Equals, "Agent")
   181  			switch request {
   182  			case "GetEntities":
   183  				c.Assert(args.(params.Entities).Entities, gc.HasLen, 1)
   184  				result := response.(*params.AgentGetEntitiesResults)
   185  				result.Entities = []params.AgentGetEntitiesResult{{
   186  					Jobs: []multiwatcher.MachineJob{job},
   187  				}}
   188  			default:
   189  				c.Fatalf("not sure how to handle: %q", request)
   190  			}
   191  			return nil
   192  		},
   193  	)
   194  	w, err := s.manifold.Start(dt.StubContext(nil, map[string]interface{}{
   195  		"agent":      a,
   196  		"api-caller": apiCaller,
   197  	}))
   198  	c.Assert(w, gc.IsNil)
   199  	c.Assert(err, gc.Equals, dependency.ErrUninstall)
   200  
   201  	// State serving info shouldn't have been set for this job type.
   202  	c.Assert(a.conf.ssiSet, jc.IsFalse)
   203  }
   204  
   205  type mockAgent struct {
   206  	coreagent.Agent
   207  	conf mockConfig
   208  }
   209  
   210  func (ma *mockAgent) CurrentConfig() coreagent.Config {
   211  	return &ma.conf
   212  }
   213  
   214  func (ma *mockAgent) ChangeConfig(f coreagent.ConfigMutator) error {
   215  	return f(&ma.conf)
   216  }
   217  
   218  type mockConfig struct {
   219  	coreagent.ConfigSetter
   220  	tag    names.Tag
   221  	ssiSet bool
   222  	ssi    params.StateServingInfo
   223  }
   224  
   225  func (mc *mockConfig) Tag() names.Tag {
   226  	if mc.tag == nil {
   227  		return names.NewMachineTag("99")
   228  	}
   229  	return mc.tag
   230  }
   231  
   232  func (mc *mockConfig) StateServingInfo() (params.StateServingInfo, bool) {
   233  	return mc.ssi, mc.ssiSet
   234  }
   235  
   236  func (mc *mockConfig) SetStateServingInfo(info params.StateServingInfo) {
   237  	mc.ssiSet = true
   238  	mc.ssi = info
   239  }