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: ¶ms.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 }