Merge lp:~axwalk/juju-core/lp1306902-mongo-ensureadminuser into lp:~go-bot/juju-core/trunk
- lp1306902-mongo-ensureadminuser
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andrew Wilkins |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2629 |
Proposed branch: | lp:~axwalk/juju-core/lp1306902-mongo-ensureadminuser |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
433 lines (+258/-48) 7 files modified
agent/mongo/mongo.go (+24/-0) agent/mongo/mongo_test.go (+55/-0) agent/mongo/upgrade.go (+101/-0) cmd/jujud/machine.go (+42/-6) cmd/jujud/machine_test.go (+34/-0) state/compat_test.go (+0/-32) state/open.go (+2/-10) |
To merge this branch: | bzr merge lp:~axwalk/juju-core/lp1306902-mongo-ensureadminuser |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+215821@code.launchpad.net |
Commit message
Ensure state server has Mongo admin rights
The machine agent is updated so that if it
fails to open state with an unauthorized error,
then the agent will attempt to give itself
admin rights by temporarily restarting mongo
with --noauth.
There will be follow-ups to perform replset
initiation, and to upgrade the upstart config.
Description of the change
Ensure state server has Mongo admin rights
The machine agent is updated so that if it
fails to open state with an unauthorized error,
then the agent will attempt to give itself
admin rights by temporarily restarting mongo
with --noauth.
There will be follow-ups to perform replset
initiation, and to upgrade the upstart config.
Andrew Wilkins (axwalk) wrote : | # |
Roger Peppe (rogpeppe) wrote : | # |
LGTM assuming it's been tested live (both upgrade and normal bootstrap).
Good stuff.
https:/
File agent/mongo/
https:/
agent/mongo/
Hmm, I wonder if that was the source of some problems.
https:/
File agent/mongo/
https:/
agent/mongo/
cleanly terminate: %v", err)
"cannot kill mongod: %v"
?
https:/
File cmd/jujud/
https:/
cmd/jujud/
// TODO remove this when we no longer need
// compatibility with pre-HA environments.
?
https:/
cmd/jujud/
a.ensureMongoAd
Perhaps slightly easier to follow the logic if we return
early when possible?
added, ensureErr := a.ensureMongoAd
namespace)
if ensureErr != nil {
return nil, fmt.Errorf("cannot ensure admin user: %v", ensureErr)
}
if !added {
// No user added, so it's probably a genuine unauthorized error.
return nil, err
}
st, m, err = openState(
Andrew Wilkins (axwalk) wrote : | # |
Please take a look.
https:/
File agent/mongo/
https:/
agent/mongo/
cleanly terminate: %v", err)
On 2014/04/15 08:33:38, rog wrote:
> "cannot kill mongod: %v"
> ?
Done.
https:/
File cmd/jujud/
https:/
cmd/jujud/
On 2014/04/15 08:33:38, rog wrote:
> // TODO remove this when we no longer need
> // compatibility with pre-HA environments.
> ?
Done.
https:/
cmd/jujud/
a.ensureMongoAd
On 2014/04/15 08:33:38, rog wrote:
> Perhaps slightly easier to follow the logic if we return
> early when possible?
> added, ensureErr := a.ensureMongoAd
info.StatePort,
> namespace)
> if ensureErr != nil {
> return nil, fmt.Errorf("cannot ensure admin user: %v", ensureErr)
> }
> if !added {
> // No user added, so it's probably a genuine unauthorized error.
> return nil, err
> }
> st, m, err = openState(
Done.
Andrew Wilkins (axwalk) wrote : | # |
Please take a look.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~axwalk/juju-core/lp1306902-mongo-ensureadminuser into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
panic: Session already closed
goroutine 1955 [running]:
labix.org/
/home/
labix.org/
/home/
labix.org/
/home/
launchpad.
/home/
launchpad.
/home/
launchpad.
/home/
created by launchpad.
/home/
goroutine 1 [chan receive]:
testing.
/usr/lib/
testing.
/usr/lib/
main.main()
launchpad.
goroutine 2 [syscall]:
goroutine 4 [syscall]:
os/signal.loop()
/usr/lib/
created by os/signal.init·1
/usr/lib/
goroutine 6 [chan receive]:
launchpad.
/home/
created by launchpad.
/home/
goroutine 9 [chan receive]:
launchpad.
/home/
launchpad.
/home/
laun...
Preview Diff
1 | === modified file 'agent/mongo/mongo.go' |
2 | --- agent/mongo/mongo.go 2014-04-15 03:40:01 +0000 |
3 | +++ agent/mongo/mongo.go 2014-04-15 09:07:40 +0000 |
4 | @@ -302,3 +302,27 @@ |
5 | } |
6 | return conf, nil |
7 | } |
8 | + |
9 | +// mongoNoauthCommand returns an os/exec.Cmd that may be executed to |
10 | +// run mongod without security. |
11 | +func mongoNoauthCommand(dataDir string, port int) (*exec.Cmd, error) { |
12 | + sslKeyFile := path.Join(dataDir, "server.pem") |
13 | + dbDir := filepath.Join(dataDir, "db") |
14 | + mongopath, err := MongodPath() |
15 | + if err != nil { |
16 | + return nil, err |
17 | + } |
18 | + cmd := exec.Command(mongopath, |
19 | + "--noauth", |
20 | + "--dbpath", dbDir, |
21 | + "--sslOnNormalPorts", |
22 | + "--sslPEMKeyFile", sslKeyFile, |
23 | + "--sslPEMKeyPassword", "ignored", |
24 | + "--bind_ip", "127.0.0.1", |
25 | + "--port", fmt.Sprint(port), |
26 | + "--noprealloc", |
27 | + "--syslog", |
28 | + "--smallfiles", |
29 | + ) |
30 | + return cmd, nil |
31 | +} |
32 | |
33 | === modified file 'agent/mongo/mongo_test.go' |
34 | --- agent/mongo/mongo_test.go 2014-04-15 03:40:01 +0000 |
35 | +++ agent/mongo/mongo_test.go 2014-04-15 09:07:40 +0000 |
36 | @@ -3,13 +3,16 @@ |
37 | import ( |
38 | "encoding/base64" |
39 | "io/ioutil" |
40 | + "net" |
41 | "os" |
42 | "path" |
43 | "path/filepath" |
44 | + "strconv" |
45 | "strings" |
46 | "testing" |
47 | |
48 | jc "github.com/juju/testing/checkers" |
49 | + "labix.org/v2/mgo" |
50 | gc "launchpad.net/gocheck" |
51 | |
52 | "launchpad.net/juju-core/instance" |
53 | @@ -165,6 +168,7 @@ |
54 | inst := &coretesting.MgoInstance{Params: []string{"--replSet", "juju"}} |
55 | err = inst.Start(true) |
56 | c.Assert(err, gc.IsNil) |
57 | + defer inst.Destroy() |
58 | |
59 | info := inst.DialInfo() |
60 | |
61 | @@ -230,6 +234,57 @@ |
62 | c.Assert(address, gc.Equals, "10.0.0.1:37017") |
63 | } |
64 | |
65 | +func (s *MongoSuite) TestEnsureAdminUser(c *gc.C) { |
66 | + inst := &coretesting.MgoInstance{} |
67 | + err := inst.Start(true) |
68 | + c.Assert(err, gc.IsNil) |
69 | + defer inst.Destroy() |
70 | + dialInfo := inst.DialInfo() |
71 | + // First call succeeds, as there are no users yet. |
72 | + added, err := s.ensureAdminUser(c, dialInfo, "whomever", "whatever") |
73 | + c.Assert(err, gc.IsNil) |
74 | + c.Assert(added, jc.IsTrue) |
75 | + // Second call succeeds, as the admin user is already there. |
76 | + added, err = s.ensureAdminUser(c, dialInfo, "whomever", "whatever") |
77 | + c.Assert(err, gc.IsNil) |
78 | + c.Assert(added, jc.IsFalse) |
79 | +} |
80 | + |
81 | +func (s *MongoSuite) TestEnsureAdminUserError(c *gc.C) { |
82 | + inst := &coretesting.MgoInstance{} |
83 | + err := inst.Start(true) |
84 | + c.Assert(err, gc.IsNil) |
85 | + defer inst.Destroy() |
86 | + dialInfo := inst.DialInfo() |
87 | + |
88 | + // First call succeeds, as there are no users yet (mimics --noauth). |
89 | + added, err := s.ensureAdminUser(c, dialInfo, "whomever", "whatever") |
90 | + c.Assert(err, gc.IsNil) |
91 | + c.Assert(added, jc.IsTrue) |
92 | + |
93 | + // Second call fails, as there is another user and the database doesn't |
94 | + // actually get reopened with --noauth in the test; mimics AddUser failure |
95 | + _, err = s.ensureAdminUser(c, dialInfo, "whomeverelse", "whateverelse") |
96 | + c.Assert(err, gc.ErrorMatches, `failed to add "whomeverelse" to admin database: not authorized for upsert on admin.system.users`) |
97 | +} |
98 | + |
99 | +func (s *MongoSuite) ensureAdminUser(c *gc.C, dialInfo *mgo.DialInfo, user, password string) (added bool, err error) { |
100 | + _, portString, err := net.SplitHostPort(dialInfo.Addrs[0]) |
101 | + c.Assert(err, gc.IsNil) |
102 | + port, err := strconv.Atoi(portString) |
103 | + c.Assert(err, gc.IsNil) |
104 | + s.PatchValue(&JujuMongodPath, "/bin/true") |
105 | + s.PatchValue(&processSignal, func(*os.Process, os.Signal) error { |
106 | + return nil |
107 | + }) |
108 | + return EnsureAdminUser(EnsureAdminUserParams{ |
109 | + DialInfo: dialInfo, |
110 | + Port: port, |
111 | + User: user, |
112 | + Password: password, |
113 | + }) |
114 | +} |
115 | + |
116 | func (s *MongoSuite) TestGenerateSharedSecret(c *gc.C) { |
117 | secret, err := GenerateSharedSecret() |
118 | c.Assert(err, gc.IsNil) |
119 | |
120 | === added file 'agent/mongo/upgrade.go' |
121 | --- agent/mongo/upgrade.go 1970-01-01 00:00:00 +0000 |
122 | +++ agent/mongo/upgrade.go 2014-04-15 09:07:40 +0000 |
123 | @@ -0,0 +1,101 @@ |
124 | +// Copyright 2014 Canonical Ltd. |
125 | +// Licensed under the AGPLv3, see LICENCE file for details. |
126 | + |
127 | +package mongo |
128 | + |
129 | +import ( |
130 | + "fmt" |
131 | + "os" |
132 | + "syscall" |
133 | + |
134 | + "labix.org/v2/mgo" |
135 | + |
136 | + "launchpad.net/juju-core/upstart" |
137 | +) |
138 | + |
139 | +var ( |
140 | + processSignal = (*os.Process).Signal |
141 | +) |
142 | + |
143 | +type EnsureAdminUserParams struct { |
144 | + // DialInfo specifies how to connect to the mongo server. |
145 | + DialInfo *mgo.DialInfo |
146 | + // Namespace is the agent namespace, used to derive the Mongo service name. |
147 | + Namespace string |
148 | + // DataDir is the Juju data directory, used to start a --noauth server. |
149 | + DataDir string |
150 | + // Port is the listening port of the Mongo server. |
151 | + Port int |
152 | + // User holds the user to log in to the mongo server as. |
153 | + User string |
154 | + // Password holds the password for the user to log in as. |
155 | + Password string |
156 | +} |
157 | + |
158 | +// EnsureAdminUser ensures that the specified user and password |
159 | +// are added to the admin database. |
160 | +// |
161 | +// This function will stop the Mongo service if it needs to add |
162 | +// the admin user, as it must restart Mongo in --noauth mode. |
163 | +func EnsureAdminUser(p EnsureAdminUserParams) (added bool, err error) { |
164 | + if len(p.DialInfo.Addrs) > 1 { |
165 | + logger.Infof("more than one state server; admin user must exist") |
166 | + return false, nil |
167 | + } |
168 | + p.DialInfo.Addrs = []string{fmt.Sprintf("127.0.0.1:%d", p.Port)} |
169 | + p.DialInfo.Direct = true |
170 | + |
171 | + // Attempt to login to the admin database first. |
172 | + session, err := mgo.DialWithInfo(p.DialInfo) |
173 | + if err != nil { |
174 | + return false, fmt.Errorf("can't dial mongo to ensure admin user: %v", err) |
175 | + } |
176 | + err = session.DB("admin").Login(p.User, p.Password) |
177 | + session.Close() |
178 | + if err == nil { |
179 | + return false, nil |
180 | + } |
181 | + |
182 | + // Login failed, so we need to add the user. |
183 | + // Stop mongo, so we can start it in --noauth mode. |
184 | + mongoServiceName := ServiceName(p.Namespace) |
185 | + mongoService := upstart.NewService(mongoServiceName) |
186 | + if err := mongoService.Stop(); err != nil { |
187 | + return false, fmt.Errorf("failed to stop %v: %v", mongoServiceName, err) |
188 | + } |
189 | + |
190 | + // Start mongod in --noauth mode. |
191 | + logger.Debugf("starting mongo with --noauth") |
192 | + cmd, err := mongoNoauthCommand(p.DataDir, p.Port) |
193 | + if err != nil { |
194 | + return false, fmt.Errorf("failed to prepare mongod command: %v", err) |
195 | + } |
196 | + if err := cmd.Start(); err != nil { |
197 | + return false, fmt.Errorf("failed to start mongod: %v", err) |
198 | + } |
199 | + defer cmd.Process.Kill() |
200 | + |
201 | + // Add the user to the admin database. |
202 | + logger.Debugf("setting admin password") |
203 | + if session, err = mgo.DialWithInfo(p.DialInfo); err != nil { |
204 | + return false, fmt.Errorf("can't dial mongo to ensure admin user: %v", err) |
205 | + } |
206 | + err = session.DB("admin").AddUser(p.User, p.Password, false) |
207 | + session.Close() |
208 | + if err != nil { |
209 | + return false, fmt.Errorf("failed to add %q to admin database: %v", p.User, err) |
210 | + } |
211 | + logger.Infof("added %q to admin database", p.User) |
212 | + |
213 | + // Restart mongo using upstart. |
214 | + if err := processSignal(cmd.Process, syscall.SIGTERM); err != nil { |
215 | + return false, fmt.Errorf("cannot kill mongod: %v", err) |
216 | + } |
217 | + if err := cmd.Wait(); err != nil { |
218 | + return false, fmt.Errorf("mongod did not cleanly terminate: %v", err) |
219 | + } |
220 | + if err := mongoService.Start(); err != nil { |
221 | + return false, err |
222 | + } |
223 | + return true, nil |
224 | +} |
225 | |
226 | === modified file 'cmd/jujud/machine.go' |
227 | --- cmd/jujud/machine.go 2014-04-15 03:40:01 +0000 |
228 | +++ cmd/jujud/machine.go 2014-04-15 09:07:40 +0000 |
229 | @@ -74,6 +74,7 @@ |
230 | // allow the tests to intercept calls to the functions. |
231 | ensureMongoServer = mongo.EnsureMongoServer |
232 | maybeInitiateMongoServer = mongo.MaybeInitiateMongoServer |
233 | + ensureMongoAdminUser = mongo.EnsureAdminUser |
234 | newSingularRunner = singular.New |
235 | |
236 | // reportOpenedAPI is exposed for tests to know when |
237 | @@ -390,6 +391,26 @@ |
238 | return nil |
239 | } |
240 | |
241 | +func (a *MachineAgent) ensureMongoAdminUser(agentConfig agent.Config, port int, namespace string) (added bool, err error) { |
242 | + stateInfo := agentConfig.StateInfo() |
243 | + dialInfo, err := state.DialInfo(stateInfo, state.DefaultDialOpts()) |
244 | + if err != nil { |
245 | + return false, err |
246 | + } |
247 | + if len(dialInfo.Addrs) > 1 { |
248 | + logger.Infof("more than one state server; admin user must exist") |
249 | + return false, nil |
250 | + } |
251 | + return ensureMongoAdminUser(mongo.EnsureAdminUserParams{ |
252 | + DialInfo: dialInfo, |
253 | + Namespace: namespace, |
254 | + DataDir: agentConfig.DataDir(), |
255 | + Port: port, |
256 | + User: stateInfo.Tag, |
257 | + Password: stateInfo.Password, |
258 | + }) |
259 | +} |
260 | + |
261 | // StateJobs returns a worker running all the workers that require |
262 | // a *state.State connection. |
263 | func (a *MachineAgent) StateWorker() (worker.Worker, error) { |
264 | @@ -408,16 +429,31 @@ |
265 | if err != nil { |
266 | return nil, err |
267 | } |
268 | + |
269 | + st, m, err := openState(agentConfig) |
270 | + if errors.IsUnauthorizedError(err) { |
271 | + // TODO(axw) remove this when we no longer need |
272 | + // to upgrade from pre-HA-capable environments. |
273 | + logger.Debugf("failed to open state, reattempt after ensuring admin user exists: %v", err) |
274 | + added, ensureErr := a.ensureMongoAdminUser(agentConfig, info.StatePort, namespace) |
275 | + if ensureErr != nil { |
276 | + err = ensureErr |
277 | + } |
278 | + if !added { |
279 | + // No user added, so it's probably a genuine unauthorized error. |
280 | + return nil, err |
281 | + } |
282 | + st, m, err = openState(agentConfig) |
283 | + } |
284 | + if err != nil { |
285 | + return nil, err |
286 | + } |
287 | + reportOpenedState(st) |
288 | + |
289 | // TODO(rog) call maybeInitiateMongoServer to upgrade mongo |
290 | // from old environments. We'll need to acquire a non-localhost |
291 | // address for the current instance before we do. |
292 | |
293 | - st, m, err := openState(agentConfig) |
294 | - if err != nil { |
295 | - return nil, err |
296 | - } |
297 | - reportOpenedState(st) |
298 | - |
299 | singularStateConn := singularStateConn{st.MongoSession(), m} |
300 | runner := newRunner(connectionIsFatal(st), moreImportant) |
301 | singularRunner, err := newSingularRunner(runner, singularStateConn) |
302 | |
303 | === modified file 'cmd/jujud/machine_test.go' |
304 | --- cmd/jujud/machine_test.go 2014-04-15 03:40:01 +0000 |
305 | +++ cmd/jujud/machine_test.go 2014-04-15 09:07:40 +0000 |
306 | @@ -17,6 +17,7 @@ |
307 | gc "launchpad.net/gocheck" |
308 | |
309 | "launchpad.net/juju-core/agent" |
310 | + "launchpad.net/juju-core/agent/mongo" |
311 | "launchpad.net/juju-core/charm" |
312 | "launchpad.net/juju-core/cmd" |
313 | lxctesting "launchpad.net/juju-core/container/lxc/testing" |
314 | @@ -895,6 +896,39 @@ |
315 | c.Fatalf("timeout while waiting for agent config to change") |
316 | } |
317 | |
318 | +func (s *MachineSuite) TestMachineAgentEnsureAdminUser(c *gc.C) { |
319 | + m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) |
320 | + err := s.State.MongoSession().DB("admin").RemoveUser(m.Tag()) |
321 | + c.Assert(err, gc.IsNil) |
322 | + |
323 | + s.PatchValue(&ensureMongoAdminUser, func(p mongo.EnsureAdminUserParams) (bool, error) { |
324 | + err := s.State.MongoSession().DB("admin").AddUser(p.User, p.Password, false) |
325 | + c.Assert(err, gc.IsNil) |
326 | + return true, nil |
327 | + }) |
328 | + |
329 | + stateOpened := make(chan eitherState, 1) |
330 | + s.PatchValue(&reportOpenedState, func(st eitherState) { |
331 | + select { |
332 | + case stateOpened <- st: |
333 | + default: |
334 | + } |
335 | + }) |
336 | + |
337 | + // Start the machine agent, and wait for state to be opened. |
338 | + a := s.newAgent(c, m) |
339 | + done := make(chan error) |
340 | + go func() { done <- a.Run(nil) }() |
341 | + defer a.Stop() // in case of failure |
342 | + select { |
343 | + case st := <-stateOpened: |
344 | + c.Assert(st, gc.NotNil) |
345 | + case <-time.After(coretesting.LongWait): |
346 | + c.Fatalf("state not opened") |
347 | + } |
348 | + s.waitStopped(c, state.JobManageEnviron, a, done) |
349 | +} |
350 | + |
351 | // MachineWithCharmsSuite provides infrastructure for tests which need to |
352 | // work with charms. |
353 | type MachineWithCharmsSuite struct { |
354 | |
355 | === modified file 'state/compat_test.go' |
356 | --- state/compat_test.go 2014-04-14 19:17:58 +0000 |
357 | +++ state/compat_test.go 2014-04-15 09:07:40 +0000 |
358 | @@ -10,7 +10,6 @@ |
359 | |
360 | "launchpad.net/juju-core/testing" |
361 | "launchpad.net/juju-core/testing/testbase" |
362 | - "launchpad.net/juju-core/utils" |
363 | ) |
364 | |
365 | // compatSuite contains backwards compatibility tests, |
366 | @@ -105,34 +104,3 @@ |
367 | c.Assert(include, gc.HasLen, 0) |
368 | c.Assert(exclude, gc.HasLen, 0) |
369 | } |
370 | - |
371 | -func (s *compatSuite) TestOpenStateWithoutAdmin(c *gc.C) { |
372 | - // https://launchpad.net/bugs/1306902 |
373 | - // In 1.18, machine-0 did not have access to the "admin" database. In |
374 | - // newer versions we need access in order to do replicaSet mutations. |
375 | - // However, we have not added the ability during upgrade to add |
376 | - // machine-0 to the admin db, so we should still continue even when it |
377 | - // doesn't have rights. |
378 | - machine, err := s.state.AddMachine("quantal", JobManageEnviron) |
379 | - c.Assert(err, gc.IsNil) |
380 | - machinePassword, err := utils.RandomPassword() |
381 | - c.Assert(err, gc.IsNil) |
382 | - err = machine.SetPassword(machinePassword) |
383 | - c.Assert(err, gc.IsNil) |
384 | - err = machine.SetMongoPassword(machinePassword) |
385 | - c.Assert(err, gc.IsNil) |
386 | - // (jam) The only way I've found to actually ensure "machine-0" is |
387 | - // removed from the Admin database is to actually login *as* the |
388 | - // machine agent we just gave admin rights to, and then remove it. |
389 | - adminDB := s.state.db.Session.DB("admin") |
390 | - err = adminDB.Login(machine.Tag(), machinePassword) |
391 | - c.Assert(err, gc.IsNil) |
392 | - err = adminDB.RemoveUser(machine.Tag()) |
393 | - c.Assert(err, gc.IsNil) |
394 | - info := TestingStateInfo() |
395 | - info.Tag = machine.Tag() |
396 | - info.Password = machinePassword |
397 | - machineState, err := Open(info, TestingDialOpts(), Policy(nil)) |
398 | - c.Assert(err, gc.IsNil) |
399 | - machineState.Close() |
400 | -} |
401 | |
402 | === modified file 'state/open.go' |
403 | --- state/open.go 2014-04-14 19:30:01 +0000 |
404 | +++ state/open.go 2014-04-15 09:07:40 +0000 |
405 | @@ -251,6 +251,7 @@ |
406 | func newState(session *mgo.Session, info *Info, policy Policy) (*State, error) { |
407 | db := session.DB("juju") |
408 | pdb := session.DB("presence") |
409 | + admin := session.DB("admin") |
410 | if info.Tag != "" { |
411 | if err := db.Login(info.Tag, info.Password); err != nil { |
412 | return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to juju database as %q", info.Tag)) |
413 | @@ -258,19 +259,10 @@ |
414 | if err := pdb.Login(info.Tag, info.Password); err != nil { |
415 | return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to presence database as %q", info.Tag)) |
416 | } |
417 | - admin := session.DB("admin") |
418 | if err := admin.Login(info.Tag, info.Password); err != nil { |
419 | - if isUnauthorized(err) { |
420 | - // TODO(jam) https://launchpad.net/bugs/1306902 in juju <=1.18, |
421 | - // machine-0 was not an admin, so it cannot login to the "admin" |
422 | - // database until bug #1306902 is fixed. |
423 | - logger.Infof("ignoring failure to login to \"admin\" database as %q (bug #1306902): %v", info.Tag, err) |
424 | - } else { |
425 | - return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to admin database as %q", info.Tag)) |
426 | - } |
427 | + return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to admin database as %q", info.Tag)) |
428 | } |
429 | } else if info.Password != "" { |
430 | - admin := session.DB("admin") |
431 | if err := admin.Login(AdminUser, info.Password); err != nil { |
432 | return nil, maybeUnauthorized(err, "cannot log in to admin database") |
433 | } |
Reviewers: mp+215821_ code.launchpad. net,
Message:
Please take a look.
Description:
Ensure state server has Mongo admin rights
The machine agent is updated so that if it
fails to open state with an unauthorized error,
then the agent will attempt to give itself
admin rights by temporarily restarting mongo
with --noauth.
There will be follow-ups to perform replset
initiation, and to upgrade the upstart config.
https:/ /code.launchpad .net/~axwalk/ juju-core/ lp1306902- mongo-ensureadm inuser/ +merge/ 215821
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/88030043/
Affected files (+255, -48 lines): mongo.go mongo_test. go upgrade. go machine. go machine_ test.go test.go
A [revision details]
M agent/mongo/
M agent/mongo/
A agent/mongo/
M cmd/jujud/
M cmd/jujud/
M state/compat_
M state/open.go