Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(836)

Side by Side Diff: cmd/jujud/upgradevalidation_test.go

Issue 11137044: cmd/jujud: Ensure valid agent.conf after upgrade
Patch Set: cmd/jujud: Ensure valid agent.conf after upgrade Created 11 years, 9 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cmd/jujud/upgradevalidation.go ('k') | state/apiserver/common/remove_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2012, 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details.
3
4 package main
5
6 import (
7 "fmt"
8 "time"
9
10 gc "launchpad.net/gocheck"
11
12 "launchpad.net/juju-core/agent"
13 "launchpad.net/juju-core/constraints"
14 "launchpad.net/juju-core/container/lxc"
15 "launchpad.net/juju-core/state"
16 "launchpad.net/juju-core/state/api"
17 "launchpad.net/juju-core/testing"
18 )
19
20 var _ = gc.Suite(&UpgradeValidationMachineSuite{})
21
22 type UpgradeValidationMachineSuite struct {
23 agentSuite
24 lxc.TestSuite
25 }
26
27 func (s *UpgradeValidationMachineSuite) SetUpSuite(c *gc.C) {
28 s.agentSuite.SetUpSuite(c)
29 s.TestSuite.SetUpSuite(c)
30 }
31
32 func (s *UpgradeValidationMachineSuite) TearDownSuite(c *gc.C) {
33 s.TestSuite.TearDownSuite(c)
34 s.agentSuite.TearDownSuite(c)
35 }
36
37 func (s *UpgradeValidationMachineSuite) SetUpTest(c *gc.C) {
38 s.agentSuite.SetUpTest(c)
39 s.TestSuite.SetUpTest(c)
40 }
41
42 func (s *UpgradeValidationMachineSuite) TearDownTest(c *gc.C) {
43 s.TestSuite.TearDownTest(c)
44 s.agentSuite.TearDownTest(c)
45 }
46
47 func (s *UpgradeValidationMachineSuite) Create1_10Machine(c *gc.C) (*state.Machi ne, *agent.Conf) {
48 // Given the current connection to state, create a new machine, and 'res et'
49 // the configuration so that it looks like how juju 1.10 would have
50 // configured it
51 m, err := s.State.InjectMachine("series", constraints.Value{}, "ardbeg-0 ", state.JobHostUnits)
52 c.Assert(err, gc.IsNil)
53 err = m.SetMongoPassword("machine-password")
54 c.Assert(err, gc.IsNil)
55 // We intentionally do *not* call m.SetPassword here, as it was not
56 // done in 1.10, we also intentionally set the APIInfo.Password back to
57 // the empty string.
58 conf, _ := s.agentSuite.primeAgent(c, m.Tag(), "machine-password")
59 conf.MachineNonce = state.BootstrapNonce
60 conf.APIInfo.Password = ""
61 conf.Write()
62 c.Assert(conf.StateInfo.Tag, gc.Equals, m.Tag())
63 c.Assert(conf.StateInfo.Password, gc.Equals, "machine-password")
64 c.Assert(err, gc.IsNil)
65 return m, conf
66 }
67
68 func (s *UpgradeValidationMachineSuite) TestEnsureAPIInfo(c *gc.C) {
69 m, conf := s.Create1_10Machine(c)
70 // Opening the API should fail as is
71 apiState, newPassword, err := conf.OpenAPI(api.DialOpts{})
72 c.Assert(apiState, gc.IsNil)
73 c.Assert(newPassword, gc.Equals, "")
74 c.Assert(err, gc.NotNil)
75 c.Assert(err, gc.ErrorMatches, "invalid entity name or password")
76
77 err = EnsureAPIInfo(conf, s.State, m)
78 c.Assert(err, gc.IsNil)
79 // After EnsureAPIInfo we should be able to connect
80 apiState, newPassword, err = conf.OpenAPI(api.DialOpts{})
81 c.Assert(err, gc.IsNil)
82 c.Assert(apiState, gc.NotNil)
83 // We shouldn't need to set a new password
84 c.Assert(newPassword, gc.Equals, "")
85 }
86
87 func (s *UpgradeValidationMachineSuite) TestEnsureAPIInfoNoOp(c *gc.C) {
88 m, conf := s.Create1_10Machine(c)
89 // Set the API password to something, and record it, ensure that
90 // EnsureAPIInfo doesn't change it on us
91 m.SetPassword("frobnizzle")
92 conf.APIInfo.Password = "frobnizzle"
93 // We matched them, so we should be able to open the API
94 apiState, newPassword, err := conf.OpenAPI(api.DialOpts{})
95 c.Assert(apiState, gc.NotNil)
96 c.Assert(newPassword, gc.Equals, "")
97 c.Assert(err, gc.IsNil)
98 apiState.Close()
99
100 err = EnsureAPIInfo(conf, s.State, m)
101 c.Assert(err, gc.IsNil)
102 // After EnsureAPIInfo we should still be able to connect
103 apiState, newPassword, err = conf.OpenAPI(api.DialOpts{})
104 c.Assert(err, gc.IsNil)
105 c.Assert(apiState, gc.NotNil)
106 // We shouldn't need to set a new password
107 c.Assert(newPassword, gc.Equals, "")
108 // The password hasn't been changed
109 c.Assert(conf.APIInfo.Password, gc.Equals, "frobnizzle")
110 }
111
112 // Test that MachineAgent enforces the API password on startup
113 func (s *UpgradeValidationMachineSuite) TestAgentEnsuresAPIInfo(c *gc.C) {
114 m, _ := s.Create1_10Machine(c)
115 // This is similar to assertJobWithState, however we need to control
116 // how the machine is initialized, so it looks like a 1.10 upgrade
117 a := &MachineAgent{}
118 s.initAgent(c, a, "--machine-id", m.Id())
119
120 agentStates := make(chan *state.State, 1000)
121 undo := sendOpenedStates(agentStates)
122 defer undo()
123
124 done := make(chan error)
125 go func() {
126 done <- a.Run(nil)
127 }()
128
129 select {
130 case agentState := <-agentStates:
131 c.Assert(agentState, gc.NotNil)
132 c.Assert(a.Conf.Conf.APIInfo.Password, gc.Equals, "machine-passw ord")
133 case <-time.After(testing.LongWait):
134 c.Fatalf("state not opened")
135 }
136 err := a.Stop()
137 c.Assert(err, gc.IsNil)
138 c.Assert(<-done, gc.IsNil)
139 }
140
141 // Test that MachineAgent enforces the API password on startup even for machine> 0
142 func (s *UpgradeValidationMachineSuite) TestAgentEnsuresAPIInfoOnWorkers(c *gc.C ) {
143 // create a machine-0, then create a new machine-1
144 _, _ = s.Create1_10Machine(c)
145 m1, _ := s.Create1_10Machine(c)
146
147 a := &MachineAgent{}
148 s.initAgent(c, a, "--machine-id", m1.Id())
149
150 agentStates := make(chan *state.State, 1000)
151 undo := sendOpenedStates(agentStates)
152 defer undo()
153
154 done := make(chan error)
155 go func() {
156 done <- a.Run(nil)
157 }()
158
159 select {
160 case agentState := <-agentStates:
161 c.Assert(agentState, gc.NotNil)
162 c.Assert(a.Conf.Conf.APIInfo.Password, gc.Equals, "machine-passw ord")
163 case <-time.After(testing.LongWait):
164 c.Fatalf("state not opened")
165 }
166 err := a.Stop()
167 c.Assert(err, gc.IsNil)
168 c.Assert(<-done, gc.IsNil)
169 }
170
171 var _ = gc.Suite(&UpgradeValidationUnitSuite{})
172
173 type UpgradeValidationUnitSuite struct {
174 agentSuite
175 testing.GitSuite
176 }
177
178 func (s *UpgradeValidationUnitSuite) SetUpTest(c *gc.C) {
179 s.agentSuite.SetUpTest(c)
180 s.GitSuite.SetUpTest(c)
181 }
182
183 func (s *UpgradeValidationUnitSuite) TearDownTest(c *gc.C) {
184 s.GitSuite.SetUpTest(c)
185 s.agentSuite.TearDownTest(c)
186 }
187
188 func (s *UpgradeValidationUnitSuite) Create1_10Unit(c *gc.C) (*state.Unit, *agen t.Conf) {
189 svc, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpr ess"))
190 c.Assert(err, gc.IsNil)
191 unit, err := svc.AddUnit()
192 c.Assert(err, gc.IsNil)
193 err = unit.SetMongoPassword("unit-password")
194 c.Assert(err, gc.IsNil)
195 // We do not call SetPassword for the unit agent, and we force the
196 // APIInfo to be empty
197 conf, _ := s.agentSuite.primeAgent(c, unit.Tag(), "unit-password")
198 conf.APIInfo = nil
199 c.Assert(conf.Write(), gc.IsNil)
200 return unit, conf
201 }
202
203 func (s *UpgradeValidationUnitSuite) TestEnsureAPIInfo(c *gc.C) {
204 u, conf := s.Create1_10Unit(c)
205 // Opening the API should fail as is
206 c.Assert(func() { conf.OpenAPI(api.DialOpts{}) }, gc.PanicMatches, ".*ni l pointer dereference")
207
208 err := EnsureAPIInfo(conf, s.State, u)
209 c.Assert(err, gc.IsNil)
210 // The test suite runs the API on non-standard ports. Fix it
211 apiAddresses, err := s.State.APIAddresses()
212 c.Assert(err, gc.IsNil)
213 c.Assert(conf.APIInfo.Addrs, gc.DeepEquals, apiAddresses)
214 conf.APIInfo.Addrs = s.APIInfo(c).Addrs
215 apiState, newPassword, err := conf.OpenAPI(api.DialOpts{})
216 c.Assert(err, gc.IsNil)
217 c.Assert(apiState, gc.NotNil)
218 // We shouldn't need to set a new password
219 c.Assert(newPassword, gc.Equals, "")
220 }
221
222 func (s *UpgradeValidationUnitSuite) TestEnsureAPIInfo1_11(c *gc.C) {
223 // In 1.11 State.Password is actually "", and the valid password is
224 // OldPassword. This is because in 1.11 we only change the password in
225 // OpenAPI which we don't call until we actually have agent workers
226 // But we don't want to set the actual entity password to the empty stri ng
227 u, conf := s.Create1_10Unit(c)
228 conf.OldPassword = conf.StateInfo.Password
229 conf.StateInfo.Password = ""
230
231 err := EnsureAPIInfo(conf, s.State, u)
232 c.Assert(err, gc.IsNil)
233 // The test suite runs the API on non-standard ports. Fix it
234 apiAddresses, err := s.State.APIAddresses()
235 c.Assert(err, gc.IsNil)
236 c.Assert(conf.APIInfo.Addrs, gc.DeepEquals, apiAddresses)
237 conf.APIInfo.Addrs = s.APIInfo(c).Addrs
238 apiState, newPassword, err := conf.OpenAPI(api.DialOpts{})
239 c.Assert(err, gc.IsNil)
240 c.Assert(apiState, gc.NotNil)
241 // It should want to set a new Password
242 c.Assert(newPassword, gc.Not(gc.Equals), "")
243 }
244
245 func (s *UpgradeValidationUnitSuite) TestEnsureAPIInfo1_11Noop(c *gc.C) {
246 // We should notice if APIInfo is 'valid' in that it matches StateInfo
247 // even though in 1.1 both Password fields are empty.
248 u, conf := s.Create1_10Unit(c)
249 conf.OldPassword = conf.StateInfo.Password
250 conf.StateInfo.Password = ""
251 u.SetPassword(conf.OldPassword)
252 testAPIInfo := s.APIInfo(c)
253 conf.APIInfo = &api.Info{
254 Addrs: testAPIInfo.Addrs,
255 Tag: u.Tag(),
256 Password: "",
257 CACert: testAPIInfo.CACert,
258 }
259
260 err := EnsureAPIInfo(conf, s.State, u)
261 c.Assert(err, gc.IsNil)
262 // We should not have changed the API Addrs or Password
263 c.Assert(conf.APIInfo.Password, gc.Equals, "")
264 c.Assert(conf.APIInfo.Addrs, gc.DeepEquals, testAPIInfo.Addrs)
265 apiState, newPassword, err := conf.OpenAPI(api.DialOpts{})
266 c.Assert(err, gc.IsNil)
267 c.Assert(apiState, gc.NotNil)
268 // It should want to set a new Password
269 c.Assert(newPassword, gc.Not(gc.Equals), "")
270 }
271
272 // Test that UnitAgent enforces the API password on startup
273 func (s *UpgradeValidationUnitSuite) TestAgentEnsuresAPIInfo(c *gc.C) {
274 unit, _ := s.Create1_10Unit(c)
275 a := &UnitAgent{}
276 s.initAgent(c, a, "--unit-name", unit.Name())
277 go func() { c.Check(a.Run(nil), gc.IsNil) }()
278 waitForUnitStarted(s.State, unit, c)
279 c.Check(a.Stop(), gc.IsNil)
280 c.Check(a.Conf.APIInfo.Password, gc.Equals, "unit-password")
281 }
282
283 var _ = gc.Suite(&UpgradeValidationSuite{})
284
285 type UpgradeValidationSuite struct {
286 testing.LoggingSuite
287 }
288
289 type mockAddresser struct {
290 Addrs []string
291 Err error
292 }
293
294 func (m *mockAddresser) APIAddresses() ([]string, error) {
295 return m.Addrs, m.Err
296 }
297
298 func (s *UpgradeValidationSuite) TestapiInfoFromStateInfo(c *gc.C) {
299 cert := []byte("stuff")
300 stInfo := &state.Info{
301 Addrs: []string{"example.invalid:37070"},
302 CACert: cert,
303 Tag: "machine-0",
304 Password: "abcdefh",
305 }
306 apiAddresses := []string{"example.invalid:17070", "another.invalid:1234" }
307 apiInfo := apiInfoFromStateInfo(stInfo, &mockAddresser{Addrs: apiAddress es})
308 c.Assert(*apiInfo, gc.DeepEquals, api.Info{
309 Addrs: apiAddresses,
310 CACert: cert,
311 Tag: "machine-0",
312 Password: "abcdefh",
313 })
314
315 }
316
317 func (s *UpgradeValidationSuite) TestapiInfoFromStateInfoSwallowsError(c *gc.C) {
318 // No reason for it to die just because of this
319 cert := []byte("stuff")
320 stInfo := &state.Info{
321 Addrs: []string{"example.invalid:37070"},
322 CACert: cert,
323 Tag: "machine-0",
324 Password: "abcdefh",
325 }
326 apiAddresses := []string{}
327 apiInfo := apiInfoFromStateInfo(stInfo, &mockAddresser{Addrs: apiAddress es, Err: fmt.Errorf("bad")})
328 c.Assert(*apiInfo, gc.DeepEquals, api.Info{
329 Addrs: []string{},
330 CACert: cert,
331 Tag: "machine-0",
332 Password: "abcdefh",
333 })
334
335 }
OLDNEW
« no previous file with comments | « cmd/jujud/upgradevalidation.go ('k') | state/apiserver/common/remove_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b