LEFT | RIGHT |
1 package main | 1 package main |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 "io/ioutil" | 5 "io/ioutil" |
6 . "launchpad.net/gocheck" | 6 . "launchpad.net/gocheck" |
7 "launchpad.net/juju-core/environs/agent" | 7 "launchpad.net/juju-core/environs/agent" |
8 "launchpad.net/juju-core/environs/dummy" | 8 "launchpad.net/juju-core/environs/dummy" |
| 9 envtesting "launchpad.net/juju-core/environs/testing" |
9 "launchpad.net/juju-core/environs/tools" | 10 "launchpad.net/juju-core/environs/tools" |
10 "launchpad.net/juju-core/state" | 11 "launchpad.net/juju-core/state" |
11 "launchpad.net/juju-core/version" | 12 "launchpad.net/juju-core/version" |
12 "net/http" | |
13 "path/filepath" | 13 "path/filepath" |
14 "time" | 14 "time" |
15 ) | 15 ) |
16 | 16 |
17 var _ = Suite(&UpgraderSuite{}) | 17 var _ = Suite(&UpgraderSuite{}) |
18 | 18 |
19 type UpgraderSuite struct { | 19 type UpgraderSuite struct { |
20 oldVersion version.Binary | 20 oldVersion version.Binary |
21 agentSuite | 21 agentSuite |
22 } | 22 } |
23 | 23 |
24 func (s *UpgraderSuite) SetUpTest(c *C) { | 24 func (s *UpgraderSuite) SetUpTest(c *C) { |
25 s.JujuConnSuite.SetUpTest(c) | 25 s.JujuConnSuite.SetUpTest(c) |
26 s.oldVersion = version.Current | 26 s.oldVersion = version.Current |
27 } | 27 } |
28 | 28 |
29 func (s *UpgraderSuite) TearDownTest(c *C) { | 29 func (s *UpgraderSuite) TearDownTest(c *C) { |
30 version.Current = s.oldVersion | 30 version.Current = s.oldVersion |
31 s.JujuConnSuite.TearDownTest(c) | 31 s.JujuConnSuite.TearDownTest(c) |
32 } | 32 } |
33 | 33 |
34 func (s *UpgraderSuite) TestUpgraderStop(c *C) { | 34 func (s *UpgraderSuite) TestUpgraderStop(c *C) { |
35 u := s.startUpgrader(c, &state.Tools{Binary: version.Current}) | 35 u := s.startUpgrader(c, &state.Tools{Binary: version.Current}) |
36 err := u.Stop() | 36 err := u.Stop() |
37 c.Assert(err, IsNil) | 37 c.Assert(err, IsNil) |
38 } | 38 } |
39 | 39 |
40 type proposal struct { | 40 var ( |
41 » version string | 41 » v200 = version.MustParse("2.0.0") |
42 » devVersion bool | 42 » t200p64 = version.MustParseBinary("2.0.0-precise-amd64") |
43 } | 43 » t200p32 = version.MustParseBinary("2.0.0-precise-i386") |
44 | 44 » t200q64 = version.MustParseBinary("2.0.0-quantal-amd64") |
45 // Here be dragons. | 45 » t2007p64 = version.MustParseBinary("2.0.0.7-precise-amd64") |
| 46 » t200all = []version.Binary{t200p64, t200p32, t200q64, t2007p64} |
| 47 |
| 48 » v214 = version.MustParse("2.1.4") |
| 49 » t214p64 = version.MustParseBinary("2.1.4-precise-amd64") |
| 50 » v2144 = version.MustParse("2.1.4.4") |
| 51 » t2144p64 = version.MustParseBinary("2.1.4.4-precise-amd64") |
| 52 » t2144p32 = version.MustParseBinary("2.1.4.4-precise-i386") |
| 53 » t2144q64 = version.MustParseBinary("2.1.4.4-quantal-amd64") |
| 54 » t214all = []version.Binary{t214p64, t2144p64, t2144p32, t2144q64} |
| 55 » t2all = append(t200all, t214all...) |
| 56 |
| 57 » v300 = version.MustParse("3.0.0") |
| 58 » t300p64 = version.MustParseBinary("3.0.0-precise-amd64") |
| 59 » tAll = append(t2all, t300p64) |
| 60 ) |
| 61 |
46 var upgraderTests = []struct { | 62 var upgraderTests = []struct { |
47 » about string | 63 » about string |
48 » current string // current version. | 64 » current version.Binary |
49 » upload []string // Upload these tools versions. | 65 » available []version.Binary |
50 » propose string // Propose this version... | 66 » propose version.Number |
51 » devVersion bool // ... with devVersion set to this. | 67 » upgrade version.Binary |
52 | |
53 » // upgradeTo is blank if nothing should happen. | |
54 » upgradeTo string | |
55 }{{ | 68 }{{ |
56 » about: "propose with no possible candidates", | 69 » about: "same version, no tools available", |
57 » current: "2.0.0", | 70 » current: t200p64, |
58 » propose: "2.2.0", | 71 » propose: v200, |
59 }, { | 72 }, { |
60 » about: "propose with same candidate as current", | 73 » about: "same version, bad tools available", |
61 » current: "2.0.0", | 74 » current: t200p64, |
62 » upload: []string{"2.0.0"}, | 75 » available: []version.Binary{t200p32, t200q64, t214p64, t300p64}, |
63 » propose: "2.4.0", | 76 » propose: v200, |
64 }, { | 77 }, { |
65 » about: "dev available, dev proposed, dev chosen despite !devVersion"
, | 78 » about: "same version, all tools available", |
66 » current: "2.0.0", | 79 » current: t200p64, |
67 » upload: []string{"2.1.0"}, | 80 » available: tAll, |
68 » propose: "2.3.0", | 81 » propose: v200, |
69 » upgradeTo: "2.1.0", | 82 }, { |
70 }, { | 83 » about: "newer version, no tools available", |
71 » about: "dev available, release proposed, dev ignored because !devVersi
on", | 84 » current: t200p64, |
72 » current: "2.0.0", | 85 » propose: v2144, |
73 » upload: []string{"2.1.0"}, | 86 }, { |
74 » propose: "2.4.0", | 87 » about: "newer version, bad tools available", |
75 }, { | 88 » current: t200p64, |
76 » about: "dev available, release proposed, dev chosen because devVers
ion", | 89 » available: []version.Binary{t200p64, t214p64, t2144p32, t2144q64, t300p6
4}, |
77 » current: "2.0.0", | 90 » propose: v2144, |
78 » upload: []string{"2.2.0", "2.3.0"}, | 91 }, { |
79 » propose: "2.4.0", | 92 » about: "newer version, all tools available", |
80 » devVersion: true, | 93 » current: t200p64, |
81 » upgradeTo: "2.3.0", | 94 » available: tAll, |
82 }, { | 95 » propose: v2144, |
83 » about: "release available, release proposed, dev ignored because !de
vVersion", | 96 » upgrade: t2144p64, |
84 » current: "2.2.0", | 97 }, { |
85 » upload: []string{"2.0.0", "2.3.0"}, | 98 » about: "older version, no tools available", |
86 » propose: "2.4.0", | 99 » current: t2144p64, |
87 » upgradeTo: "2.0.0", | 100 » propose: v200, |
88 }, { | 101 }, { |
89 » about: "propose with higher available candidates", | 102 » about: "older version, bad tools available", |
90 » current: "2.0.0", | 103 » current: t2144p64, |
91 » upload: []string{"2.4.0", "2.5.0", "2.6.0"}, | 104 » available: []version.Binary{t200p32, t200q64, t214p64, t2144p64, t300p64
}, |
92 » propose: "2.4.0", | 105 » propose: v200, |
93 » upgradeTo: "2.4.0", | 106 }, { |
94 }, { | 107 » about: "older version, all tools available", |
95 » about: "propose exact available version", | 108 » current: t2144p64, |
96 » current: "2.4.0", | 109 » available: tAll, |
97 » upload: []string{"2.6.0"}, | 110 » propose: v200, |
98 » propose: "2.6.0", | 111 » upgrade: t200p64, |
99 » upgradeTo: "2.6.0", | 112 }, { |
100 }, { | 113 » about: "newer major version, all tools available", |
101 » about: "propose downgrade", | 114 » current: t200p64, |
102 » current: "2.6.0", | 115 » available: tAll, |
103 » upload: []string{"2.5.0"}, | 116 » propose: v300, |
104 » propose: "2.5.0", | 117 }, { |
105 » upgradeTo: "2.5.0", | 118 » about: "older major version, all tools available", |
106 }, | 119 » current: t300p64, |
107 } | 120 » available: tAll, |
| 121 » propose: v200, |
| 122 }} |
108 | 123 |
109 func (s *UpgraderSuite) TestUpgrader(c *C) { | 124 func (s *UpgraderSuite) TestUpgrader(c *C) { |
110 for i, test := range upgraderTests { | 125 for i, test := range upgraderTests { |
111 c.Logf("\ntest %d: %s", i, test.about) | 126 c.Logf("\ntest %d: %s", i, test.about) |
112 » » if test.current == "" { | 127 » » // Note: primeTools sets version.Current... |
113 » » » panic("incomplete test setup: starting current version i
s mandatory") | 128 » » currentTools := s.primeTools(c, test.current) |
| 129 » » // ...but it also puts tools in storage we don't need, which is
why we |
| 130 » » // don't clean up garbage from earlier runs first. |
| 131 » » envtesting.RemoveAllTools(c, s.Conn.Environ) |
| 132 » » uploaded := make(map[version.Binary]*state.Tools) |
| 133 » » for _, vers := range test.available { |
| 134 » » » tools := s.uploadTools(c, vers) |
| 135 » » » uploaded[vers] = tools |
114 } | 136 } |
115 » » currentTools := s.primeTools(c, version.MustParseBinary(test.cur
rent+"-foo-bar")) | 137 |
116 » » resp, err := http.Get(currentTools.URL) | |
117 » » c.Assert(err, IsNil) | |
118 » » err = agent.UnpackTools(s.DataDir(), currentTools, resp.Body) | |
119 » » resp.Body.Close() | |
120 » » c.Assert(err, IsNil) | |
121 » » s.removeTools(c) | |
122 | |
123 » » uploaded := make(map[version.Number]*state.Tools) | |
124 » » for _, v := range test.upload { | |
125 » » » vers := version.Current | |
126 » » » vers.Number = version.MustParse(v) | |
127 » » » tools := s.uploadTools(c, vers) | |
128 » » » uploaded[vers.Number] = tools | |
129 » » } | |
130 | |
131 » » s.proposeVersion(c, version.MustParse(test.current), test.devVer
sion) | |
132 » » version.Current.Number = version.MustParse(test.current) | |
133 » » currentTools, err = agent.ReadTools(s.DataDir(), version.Current
) | |
134 » » c.Assert(err, IsNil) | |
135 | |
136 » » u := s.startUpgrader(c, currentTools) | |
137 func() { | 138 func() { |
| 139 u := s.startUpgrader(c, currentTools) |
138 defer u.Stop() | 140 defer u.Stop() |
139 » » » if test.propose != "" { | 141 » » » s.proposeVersion(c, test.propose) |
140 » » » » s.proposeVersion(c, version.MustParse(test.propo
se), test.devVersion) | 142 » » » s.State.StartSync() |
141 » » » » s.State.StartSync() | 143 » » » if test.upgrade.Number == version.Zero { |
142 » » » } | |
143 » » » if test.upgradeTo == "" { | |
144 » » » » s.State.StartSync() | |
145 assertNothingHappens(c, u) | 144 assertNothingHappens(c, u) |
146 c.Assert(u.Stop(), IsNil) | 145 c.Assert(u.Stop(), IsNil) |
147 return | 146 return |
148 } | 147 } |
| 148 |
149 ug := waitDeath(c, u) | 149 ug := waitDeath(c, u) |
150 » » » tools := uploaded[version.MustParse(test.upgradeTo)] | 150 » » » tools := uploaded[test.upgrade] |
151 c.Check(ug.NewTools, DeepEquals, tools) | 151 c.Check(ug.NewTools, DeepEquals, tools) |
152 c.Check(ug.OldTools.Binary, Equals, version.Current) | 152 c.Check(ug.OldTools.Binary, Equals, version.Current) |
153 c.Check(ug.DataDir, Equals, s.DataDir()) | 153 c.Check(ug.DataDir, Equals, s.DataDir()) |
154 c.Check(ug.AgentName, Equals, "testagent") | 154 c.Check(ug.AgentName, Equals, "testagent") |
155 | 155 |
156 // Check that the upgraded version was really downloaded
. | 156 // Check that the upgraded version was really downloaded
. |
157 path := agent.SharedToolsDir(s.DataDir(), tools.Binary) | 157 path := agent.SharedToolsDir(s.DataDir(), tools.Binary) |
158 data, err := ioutil.ReadFile(filepath.Join(path, "jujud"
)) | 158 data, err := ioutil.ReadFile(filepath.Join(path, "jujud"
)) |
159 c.Check(err, IsNil) | 159 c.Check(err, IsNil) |
160 c.Check(string(data), Equals, "jujud contents "+tools.Bi
nary.String()) | 160 c.Check(string(data), Equals, "jujud contents "+tools.Bi
nary.String()) |
161 }() | 161 }() |
162 } | 162 } |
| 163 } |
| 164 |
| 165 func (s *UpgraderSuite) TestStillWorksAfterBadVersions(c *C) { |
| 166 currentTools := s.primeTools(c, t200p64) |
| 167 envtesting.RemoveAllTools(c, s.Conn.Environ) |
| 168 u := s.startUpgrader(c, currentTools) |
| 169 defer u.Stop() |
| 170 |
| 171 // Propose a missing version |
| 172 s.proposeVersion(c, v2144) |
| 173 s.State.StartSync() |
| 174 assertNothingHappens(c, u) |
| 175 |
| 176 // Propose an incompatible version |
| 177 s.proposeVersion(c, v300) |
| 178 s.State.StartSync() |
| 179 assertNothingHappens(c, u) |
| 180 |
| 181 // Propose a working version |
| 182 newTools := s.uploadTools(c, t2144p64) |
| 183 s.proposeVersion(c, v2144) |
| 184 s.State.StartSync() |
| 185 ug := waitDeath(c, u) |
| 186 c.Assert(ug.NewTools, DeepEquals, newTools) |
163 } | 187 } |
164 | 188 |
165 var delayedStopTests = []struct { | 189 var delayedStopTests = []struct { |
166 about string | 190 about string |
167 upgraderKillDelay time.Duration | 191 upgraderKillDelay time.Duration |
168 storageDelay time.Duration | 192 storageDelay time.Duration |
169 propose string | 193 propose string |
170 err string | 194 err string |
171 }{{ | 195 }{{ |
172 about: "same version", | 196 about: "same version", |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 s.uploadTools(c, version.MustParseBinary("2.0.6-foo-bar")) | 233 s.uploadTools(c, version.MustParseBinary("2.0.6-foo-bar")) |
210 s.uploadTools(c, version.MustParseBinary("2.0.6-foo-bar")) | 234 s.uploadTools(c, version.MustParseBinary("2.0.6-foo-bar")) |
211 s.uploadTools(c, version.MustParseBinary("2.0.7-foo-bar")) | 235 s.uploadTools(c, version.MustParseBinary("2.0.7-foo-bar")) |
212 s.poisonVersion(version.MustParseBinary("2.0.7-foo-bar")) | 236 s.poisonVersion(version.MustParseBinary("2.0.7-foo-bar")) |
213 | 237 |
214 for i, test := range delayedStopTests { | 238 for i, test := range delayedStopTests { |
215 c.Logf("%d. %v", i, test.about) | 239 c.Logf("%d. %v", i, test.about) |
216 upgraderKillDelay = test.upgraderKillDelay | 240 upgraderKillDelay = test.upgraderKillDelay |
217 dummy.SetStorageDelay(test.storageDelay) | 241 dummy.SetStorageDelay(test.storageDelay) |
218 proposed := version.MustParse(test.propose) | 242 proposed := version.MustParse(test.propose) |
219 » » s.proposeVersion(c, proposed, true) | 243 » » s.proposeVersion(c, proposed) |
220 u := s.startUpgrader(c, tools) | 244 u := s.startUpgrader(c, tools) |
221 t0 := time.Now() | 245 t0 := time.Now() |
222 err := u.Stop() | 246 err := u.Stop() |
223 d := time.Now().Sub(t0) | 247 d := time.Now().Sub(t0) |
224 if d > 100*time.Millisecond { | 248 if d > 100*time.Millisecond { |
225 c.Errorf("upgrader took took too long: %v", d) | 249 c.Errorf("upgrader took took too long: %v", d) |
226 } | 250 } |
227 if test.err == "" { | 251 if test.err == "" { |
228 c.Check(err, IsNil) | 252 c.Check(err, IsNil) |
229 } else { | 253 } else { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 return "testagent" | 344 return "testagent" |
321 } | 345 } |
322 | 346 |
323 func (as testAgentState) Life() state.Life { | 347 func (as testAgentState) Life() state.Life { |
324 panic("unimplemented") | 348 panic("unimplemented") |
325 } | 349 } |
326 | 350 |
327 func (as testAgentState) SetMongoPassword(string) error { | 351 func (as testAgentState) SetMongoPassword(string) error { |
328 panic("unimplemented") | 352 panic("unimplemented") |
329 } | 353 } |
LEFT | RIGHT |