1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
"github.com/juju/errors"
10
jc "github.com/juju/testing/checkers"
11
"github.com/juju/utils/arch"
12
"github.com/juju/utils/series"
13
"github.com/juju/version"
14
gc "gopkg.in/check.v1"
15
"gopkg.in/juju/names.v2"
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"
28
type upgraderSuite struct {
29
jujutesting.JujuConnSuite
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
40
var _ = gc.Suite(&upgraderSuite{})
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() })
47
// Create a machine to work with
49
// The first machine created is the only one allowed to
51
s.apiMachine, err = s.State.AddMachine("quantal", state.JobHostUnits,
53
c.Assert(err, jc.ErrorIsNil)
54
s.rawMachine, err = s.State.AddMachine("quantal", state.JobHostUnits)
55
c.Assert(err, jc.ErrorIsNil)
57
// The default auth is as the machine agent
58
s.authorizer = apiservertesting.FakeAuthorizer{
59
Tag: s.rawMachine.Tag(),
61
s.upgrader, err = upgrader.NewUpgraderAPI(s.State, s.resources, s.authorizer)
62
c.Assert(err, jc.ErrorIsNil)
65
func (s *upgraderSuite) TearDownTest(c *gc.C) {
66
if s.resources != nil {
69
s.JujuConnSuite.TearDownTest(c)
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)
79
func (s *upgraderSuite) TestWatchAPIVersion(c *gc.C) {
80
args := params.Entities{
81
Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}},
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)
91
w := resource.(state.NotifyWatcher)
92
wc := statetesting.NewNotifyWatcherC(c, s.State, w)
95
err = statetesting.SetAgentVersion(s.State, version.MustParse("3.4.567.8"))
96
c.Assert(err, jc.ErrorIsNil)
98
statetesting.AssertStop(c, w)
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")
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()}},
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)
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)
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()}},
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)
151
func (s *upgraderSuite) TestToolsForAgent(c *gc.C) {
152
current := version.Binary{
153
Number: jujuversion.Current,
154
Arch: arch.HostArch(),
155
Series: series.HostSeries(),
157
agent := params.Entity{Tag: s.rawMachine.Tag().String()}
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)
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)
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)
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(),
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)
210
func (s *upgraderSuite) TestSetTools(c *gc.C) {
211
current := version.Binary{
212
Number: jujuversion.Current,
213
Arch: arch.HostArch(),
214
Series: series.HostSeries(),
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{
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, "")
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)
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()}},
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)
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"},
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)
276
c.Assert(results.Results[1].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
277
c.Assert(results.Results[1].Version, gc.IsNil)
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)
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(),
300
s.apiMachine.SetAgentVersion(current)
301
s.rawMachine.SetAgentVersion(current)
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)
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(),
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)
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)