github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/upgrader/upgrader_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgrader_test 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils/arch" 13 "github.com/juju/utils/series" 14 "github.com/juju/version" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/apiserver/common" 18 "github.com/juju/juju/apiserver/params" 19 apiservertesting "github.com/juju/juju/apiserver/testing" 20 "github.com/juju/juju/apiserver/upgrader" 21 jujutesting "github.com/juju/juju/juju/testing" 22 "github.com/juju/juju/state" 23 statetesting "github.com/juju/juju/state/testing" 24 coretesting "github.com/juju/juju/testing" 25 jujuversion "github.com/juju/juju/version" 26 ) 27 28 type upgraderSuite struct { 29 jujutesting.JujuConnSuite 30 31 // These are raw State objects. Use them for setup and assertions, but 32 // should never be touched by the API calls themselves 33 rawMachine *state.Machine 34 apiMachine *state.Machine 35 upgrader *upgrader.UpgraderAPI 36 resources *common.Resources 37 authorizer apiservertesting.FakeAuthorizer 38 } 39 40 var _ = gc.Suite(&upgraderSuite{}) 41 42 func (s *upgraderSuite) SetUpTest(c *gc.C) { 43 s.JujuConnSuite.SetUpTest(c) 44 s.resources = common.NewResources() 45 s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) 46 47 // Create a machine to work with 48 var err error 49 // The first machine created is the only one allowed to 50 // JobManageModel 51 s.apiMachine, err = s.State.AddMachine("quantal", state.JobHostUnits, 52 state.JobManageModel) 53 c.Assert(err, jc.ErrorIsNil) 54 s.rawMachine, err = s.State.AddMachine("quantal", state.JobHostUnits) 55 c.Assert(err, jc.ErrorIsNil) 56 57 // The default auth is as the machine agent 58 s.authorizer = apiservertesting.FakeAuthorizer{ 59 Tag: s.rawMachine.Tag(), 60 } 61 s.upgrader, err = upgrader.NewUpgraderAPI(s.State, s.resources, s.authorizer) 62 c.Assert(err, jc.ErrorIsNil) 63 } 64 65 func (s *upgraderSuite) TearDownTest(c *gc.C) { 66 if s.resources != nil { 67 s.resources.StopAll() 68 } 69 s.JujuConnSuite.TearDownTest(c) 70 } 71 72 func (s *upgraderSuite) TestWatchAPIVersionNothing(c *gc.C) { 73 // Not an error to watch nothing 74 results, err := s.upgrader.WatchAPIVersion(params.Entities{}) 75 c.Assert(err, jc.ErrorIsNil) 76 c.Check(results.Results, gc.HasLen, 0) 77 } 78 79 func (s *upgraderSuite) TestWatchAPIVersion(c *gc.C) { 80 args := params.Entities{ 81 Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}, 82 } 83 results, err := s.upgrader.WatchAPIVersion(args) 84 c.Assert(err, jc.ErrorIsNil) 85 c.Check(results.Results, gc.HasLen, 1) 86 c.Check(results.Results[0].NotifyWatcherId, gc.Not(gc.Equals), "") 87 c.Check(results.Results[0].Error, gc.IsNil) 88 resource := s.resources.Get(results.Results[0].NotifyWatcherId) 89 c.Check(resource, gc.NotNil) 90 91 w := resource.(state.NotifyWatcher) 92 wc := statetesting.NewNotifyWatcherC(c, s.State, w) 93 wc.AssertNoChange() 94 95 err = statetesting.SetAgentVersion(s.State, version.MustParse("3.4.567.8")) 96 c.Assert(err, jc.ErrorIsNil) 97 wc.AssertOneChange() 98 statetesting.AssertStop(c, w) 99 wc.AssertClosed() 100 } 101 102 func (s *upgraderSuite) TestUpgraderAPIRefusesNonMachineAgent(c *gc.C) { 103 anAuthorizer := s.authorizer 104 anAuthorizer.Tag = names.NewUnitTag("ubuntu/1") 105 anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer) 106 c.Check(err, gc.NotNil) 107 c.Check(anUpgrader, gc.IsNil) 108 c.Assert(err, gc.ErrorMatches, "permission denied") 109 } 110 111 func (s *upgraderSuite) TestWatchAPIVersionRefusesWrongAgent(c *gc.C) { 112 // We are a machine agent, but not the one we are trying to track 113 anAuthorizer := s.authorizer 114 anAuthorizer.Tag = names.NewMachineTag("12354") 115 anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer) 116 c.Check(err, jc.ErrorIsNil) 117 args := params.Entities{ 118 Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}, 119 } 120 results, err := anUpgrader.WatchAPIVersion(args) 121 // It is not an error to make the request, but the specific item is rejected 122 c.Assert(err, jc.ErrorIsNil) 123 c.Check(results.Results, gc.HasLen, 1) 124 c.Check(results.Results[0].NotifyWatcherId, gc.Equals, "") 125 c.Assert(results.Results[0].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 126 } 127 128 func (s *upgraderSuite) TestToolsNothing(c *gc.C) { 129 // Not an error to watch nothing 130 results, err := s.upgrader.Tools(params.Entities{}) 131 c.Assert(err, jc.ErrorIsNil) 132 c.Check(results.Results, gc.HasLen, 0) 133 } 134 135 func (s *upgraderSuite) TestToolsRefusesWrongAgent(c *gc.C) { 136 anAuthorizer := s.authorizer 137 anAuthorizer.Tag = names.NewMachineTag("12354") 138 anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer) 139 c.Check(err, jc.ErrorIsNil) 140 args := params.Entities{ 141 Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}, 142 } 143 results, err := anUpgrader.Tools(args) 144 // It is not an error to make the request, but the specific item is rejected 145 c.Assert(err, jc.ErrorIsNil) 146 c.Check(results.Results, gc.HasLen, 1) 147 toolResult := results.Results[0] 148 c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 149 } 150 151 func (s *upgraderSuite) TestToolsForAgent(c *gc.C) { 152 current := version.Binary{ 153 Number: jujuversion.Current, 154 Arch: arch.HostArch(), 155 Series: series.HostSeries(), 156 } 157 agent := params.Entity{Tag: s.rawMachine.Tag().String()} 158 159 // The machine must have its existing tools set before we query for the 160 // next tools. This is so that we can grab Arch and Series without 161 // having to pass it in again 162 err := s.rawMachine.SetAgentVersion(current) 163 c.Assert(err, jc.ErrorIsNil) 164 165 args := params.Entities{Entities: []params.Entity{agent}} 166 results, err := s.upgrader.Tools(args) 167 c.Assert(err, jc.ErrorIsNil) 168 assertTools := func() { 169 c.Check(results.Results, gc.HasLen, 1) 170 c.Assert(results.Results[0].Error, gc.IsNil) 171 agentTools := results.Results[0].ToolsList[0] 172 url := fmt.Sprintf("https://%s/model/%s/tools/%s", 173 s.APIState.Addr(), coretesting.ModelTag.Id(), current) 174 c.Check(agentTools.URL, gc.Equals, url) 175 c.Check(agentTools.Version, gc.DeepEquals, current) 176 } 177 assertTools() 178 } 179 180 func (s *upgraderSuite) TestSetToolsNothing(c *gc.C) { 181 // Not an error to watch nothing 182 results, err := s.upgrader.SetTools(params.EntitiesVersion{}) 183 c.Assert(err, jc.ErrorIsNil) 184 c.Check(results.Results, gc.HasLen, 0) 185 } 186 187 func (s *upgraderSuite) TestSetToolsRefusesWrongAgent(c *gc.C) { 188 anAuthorizer := s.authorizer 189 anAuthorizer.Tag = names.NewMachineTag("12354") 190 anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer) 191 c.Check(err, jc.ErrorIsNil) 192 args := params.EntitiesVersion{ 193 AgentTools: []params.EntityVersion{{ 194 Tag: s.rawMachine.Tag().String(), 195 Tools: ¶ms.Version{ 196 Version: version.Binary{ 197 Number: jujuversion.Current, 198 Arch: arch.HostArch(), 199 Series: series.HostSeries(), 200 }, 201 }, 202 }}, 203 } 204 205 results, err := anUpgrader.SetTools(args) 206 c.Assert(results.Results, gc.HasLen, 1) 207 c.Assert(results.Results[0].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 208 } 209 210 func (s *upgraderSuite) TestSetTools(c *gc.C) { 211 current := version.Binary{ 212 Number: jujuversion.Current, 213 Arch: arch.HostArch(), 214 Series: series.HostSeries(), 215 } 216 _, err := s.rawMachine.AgentTools() 217 c.Assert(err, jc.Satisfies, errors.IsNotFound) 218 args := params.EntitiesVersion{ 219 AgentTools: []params.EntityVersion{{ 220 Tag: s.rawMachine.Tag().String(), 221 Tools: ¶ms.Version{ 222 Version: current, 223 }}, 224 }, 225 } 226 results, err := s.upgrader.SetTools(args) 227 c.Assert(err, jc.ErrorIsNil) 228 c.Assert(results.Results, gc.HasLen, 1) 229 c.Assert(results.Results[0].Error, gc.IsNil) 230 // Check that the new value actually got set, we must Refresh because 231 // it was set on a different Machine object 232 err = s.rawMachine.Refresh() 233 c.Assert(err, jc.ErrorIsNil) 234 realTools, err := s.rawMachine.AgentTools() 235 c.Assert(err, jc.ErrorIsNil) 236 c.Check(realTools.Version, gc.Equals, current) 237 c.Check(realTools.URL, gc.Equals, "") 238 } 239 240 func (s *upgraderSuite) TestDesiredVersionNothing(c *gc.C) { 241 // Not an error to watch nothing 242 results, err := s.upgrader.DesiredVersion(params.Entities{}) 243 c.Assert(err, jc.ErrorIsNil) 244 c.Check(results.Results, gc.HasLen, 0) 245 } 246 247 func (s *upgraderSuite) TestDesiredVersionRefusesWrongAgent(c *gc.C) { 248 anAuthorizer := s.authorizer 249 anAuthorizer.Tag = names.NewMachineTag("12354") 250 anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer) 251 c.Check(err, jc.ErrorIsNil) 252 args := params.Entities{ 253 Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}, 254 } 255 results, err := anUpgrader.DesiredVersion(args) 256 // It is not an error to make the request, but the specific item is rejected 257 c.Assert(err, jc.ErrorIsNil) 258 c.Check(results.Results, gc.HasLen, 1) 259 toolResult := results.Results[0] 260 c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 261 } 262 263 func (s *upgraderSuite) TestDesiredVersionNoticesMixedAgents(c *gc.C) { 264 args := params.Entities{Entities: []params.Entity{ 265 {Tag: s.rawMachine.Tag().String()}, 266 {Tag: "machine-12345"}, 267 }} 268 results, err := s.upgrader.DesiredVersion(args) 269 c.Assert(err, jc.ErrorIsNil) 270 c.Check(results.Results, gc.HasLen, 2) 271 c.Assert(results.Results[0].Error, gc.IsNil) 272 agentVersion := results.Results[0].Version 273 c.Assert(agentVersion, gc.NotNil) 274 c.Check(*agentVersion, gc.DeepEquals, jujuversion.Current) 275 276 c.Assert(results.Results[1].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 277 c.Assert(results.Results[1].Version, gc.IsNil) 278 279 } 280 281 func (s *upgraderSuite) TestDesiredVersionForAgent(c *gc.C) { 282 args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}} 283 results, err := s.upgrader.DesiredVersion(args) 284 c.Assert(err, jc.ErrorIsNil) 285 c.Check(results.Results, gc.HasLen, 1) 286 c.Assert(results.Results[0].Error, gc.IsNil) 287 agentVersion := results.Results[0].Version 288 c.Assert(agentVersion, gc.NotNil) 289 c.Check(*agentVersion, gc.DeepEquals, jujuversion.Current) 290 } 291 292 func (s *upgraderSuite) bumpDesiredAgentVersion(c *gc.C) version.Number { 293 // In order to call SetModelAgentVersion we have to first SetTools on 294 // all the existing machines 295 current := version.Binary{ 296 Number: jujuversion.Current, 297 Arch: arch.HostArch(), 298 Series: series.HostSeries(), 299 } 300 s.apiMachine.SetAgentVersion(current) 301 s.rawMachine.SetAgentVersion(current) 302 newer := current 303 newer.Patch++ 304 err := s.State.SetModelAgentVersion(newer.Number) 305 c.Assert(err, jc.ErrorIsNil) 306 cfg, err := s.State.ModelConfig() 307 c.Assert(err, jc.ErrorIsNil) 308 vers, ok := cfg.AgentVersion() 309 c.Assert(ok, jc.IsTrue) 310 c.Check(vers, gc.Equals, newer.Number) 311 return newer.Number 312 } 313 314 func (s *upgraderSuite) TestDesiredVersionUnrestrictedForAPIAgents(c *gc.C) { 315 newVersion := s.bumpDesiredAgentVersion(c) 316 // Grab a different Upgrader for the apiMachine 317 authorizer := apiservertesting.FakeAuthorizer{ 318 Tag: s.apiMachine.Tag(), 319 } 320 upgraderAPI, err := upgrader.NewUpgraderAPI(s.State, s.resources, authorizer) 321 c.Assert(err, jc.ErrorIsNil) 322 args := params.Entities{Entities: []params.Entity{{Tag: s.apiMachine.Tag().String()}}} 323 results, err := upgraderAPI.DesiredVersion(args) 324 c.Assert(err, jc.ErrorIsNil) 325 c.Check(results.Results, gc.HasLen, 1) 326 c.Assert(results.Results[0].Error, gc.IsNil) 327 agentVersion := results.Results[0].Version 328 c.Assert(agentVersion, gc.NotNil) 329 c.Check(*agentVersion, gc.DeepEquals, newVersion) 330 } 331 332 func (s *upgraderSuite) TestDesiredVersionRestrictedForNonAPIAgents(c *gc.C) { 333 newVersion := s.bumpDesiredAgentVersion(c) 334 c.Assert(newVersion, gc.Not(gc.Equals), jujuversion.Current) 335 args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}} 336 results, err := s.upgrader.DesiredVersion(args) 337 c.Assert(err, jc.ErrorIsNil) 338 c.Check(results.Results, gc.HasLen, 1) 339 c.Assert(results.Results[0].Error, gc.IsNil) 340 agentVersion := results.Results[0].Version 341 c.Assert(agentVersion, gc.NotNil) 342 c.Check(*agentVersion, gc.DeepEquals, jujuversion.Current) 343 }