mongodb_user state issue: only works on 2nd run

307 views
Skip to first unread message

Evan Johnson

unread,
Nov 4, 2013, 12:10:41 AM11/4/13
to salt-...@googlegroups.com
This issue has plagued me for a while, so I thought maybe I'd post about it here and see if I can get some guidance to solve it. Any input is much appreciated!

Here is an isolated example state file to illustrate the issue: https://gist.github.com/thaddeusmt/7298139

For testing, I am running it master-less, like so:
sudo salt-call --local state.sls saltstack_mongodb_user

The first time I run it, everything completes except the 'mongodb_user.present' task, which gives this error:

 State: - mongodb_user
    Name:      root
    Function:  present
        Result:    False
        Comment:   An exception occurred in this state: Traceback (most recent call last):
  File "/usr/lib/pymodules/python2.7/salt/state.py", line 1260, in call
    ret = self.states[cdata['full']](*cdata['args'])
  File "/usr/lib/pymodules/python2.7/salt/states/mongodb_user.py", line 45, in present
    if __salt__['mongodb.user_exists'](name, user, password, host, port, database):
  File "/usr/lib/pymodules/python2.7/salt/modules/mongodb.py", line 186, in user_exists
    if name == dict(user).get('user'):
ValueError: dictionary update sequence element #0 has length 1; 2 is required

If I do nothing else, and run salt-call on the state again, it then completes without a complaint:

State: - mongodb_user
    Name:      root
    Function:  present
        Result:    True
        Comment:   User root has been created
        Changes:   root: Present

I thought it might be an ordering issue, which is why I took another stab at this with the new 0.17.1 salt release's Definition Ordering - but it's still occurring. I tried the "lowstate" thing to see if it was executing mongodb_user before the service was running or something, but it looks OK to my untrained eye: https://gist.github.com/thaddeusmt/7298204

I have also tried it after removing the "require" directives (they are unnecessary with Definition Ordering now?), with the same error.

Maybe mongo takes a while to start up and that's why the user create fails? (Or, the user_exists, according to the error). Then when it's run the 2nd time it's ready to go?

Any assistance on this would be greatly appreciated. I started to dig in to the python code in mongodb_user.py and mongodb.py but I have no python chops, and this one bug is starting to eat too much time so I'm just about to have to move on.

Thanks!
Evan

David Anderson

unread,
Nov 4, 2013, 11:59:07 AM11/4/13
to salt-...@googlegroups.com
These mongodb modules and states are a bit confusing. In your state you
have:

mongo_root:
mongodb_user.present:
- name: root
- passwd: root_pass
- host: localhost
- port: 27017
- database: admin
- require:
- service: mongodb
- pip: pymongo The mongodb_user.present function actually needs the args
'name' and 'passwd' for the user you want to create. You also need to
pass 'user' and 'password'. 'user'/'password' needs to be a user that is
already created and has sufficient privileges to create the new user of
'name'/'passwd'.
http://docs.saltstack.com/ref/states/all/salt.states.mongodb_user.html#salt.states.mongodb_user.present
-- Dave
> --
> You received this message because you are subscribed to the Google
> Groups "Salt-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to salt-users+...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Evan Johnson

unread,
Nov 4, 2013, 12:42:13 PM11/4/13
to salt-...@googlegroups.com
Thanks for the response, Dave.

You are saying that the "user" and "password" args (not to be confused with "name" and "passwd", which are for the new user) need to be supplied using a user that is "already created and has sufficient privileges". That makes sense - except how does that work when running this immediately after installed MongoDb for the first time, before any users or privileges have been set up? 

I am attempting to create the first user here - the 'root' user. No users have been created. What "user" and "password" would I supply at this stage?

I get the same error result if I specify a blank "user"/"password", or a made up "user" and a blank "password", or made up "user" AND "password". What else should I try?

It does complete on the 2nd run, still without specifying a "user" and "password". It just doesn't work on the 1st run.

Also, "auth" is "False". It's my understanding that user's don't need passwords anyway under this configuration? I intend to eventually enable "auth" - which is why I am creating the "root" user with a password - but for the sake of simplifying my question and this test case, I am not running with "auth" enabled.

Since I do want auth enabled eventually, I may have to just use direct cmd.run commands. I think I'll need to start mongod with the enableLocalHostAuthBypass parameter (http://docs.mongodb.org/manual/tutorial/add-user-administrator/) to get the initial root user set up with auth enabled anyway, so these mongodb salt states might not do what I need.

Thanks again, and I welcome any additional input - especially from anyone who has used Salt to set up their initial MongoDb users with Authentication enabled?

-Evan

David Anderson

unread,
Nov 5, 2013, 11:31:25 AM11/5/13
to salt-...@googlegroups.com
You're right, it should still work as your describe. You are likely
right that it cannot connect to the database when trying user.present.
Have you checked the minion logs? If it cannot connect to the database,
it should log this:

log.error('Error connecting to database {0}'.format(database))

The mongodb_user.present first checks to see if the user is already in
the database before it tries to add it. Following the mongodb.py module
code, and by the Traceback you are seeing in your state run output, the
user_exists() function is returning a string on error:

>>> user = 'Failed to connect to mongo database'
>>> name = 'root'
>>> if name == dict(user).get('user'):
... print name
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #0 has length 1; 2 is
required


As a workaround, maybe you can add a cmd.run to sleep for a few seconds
in between the service restart and adding the first user?

Regardless, tracebacks are bad and a bug should be filed to fix this -
please file one on github.
--
Dave

On 11/4/13 10:42 AM, Evan Johnson wrote:
> Thanks for the response, Dave.
>
> You are saying that the "user" and "password" args (not to be confused
> with "name" and "passwd", which are for the /new /user) need to be
> supplied using a user that is "already created and has sufficient
> privileges". That makes sense - except how does that work when running
> this immediately after installed MongoDb for the first time, before
> any users or privileges have been set up?
>
> I am attempting to create the first user here - the 'root' user. No
> users have been created. What "user" and "password" would I supply at
> this stage?
>
> I get the same error result if I specify a blank "user"/"password", or
> a made up "user" and a blank "password", or made up "user" AND
> "password". What else should I try?
>
> It /does/ complete on the 2nd run, still without specifying a "user"
> and "password". It just doesn't work on the 1st run.
>
> Also, "auth" is "False". It's my understanding that user's don't need
> passwords anyway under this configuration? I intend to eventually
> enable "auth" - which is why I am creating the "root" user with a
> password - but for the sake of simplifying my question and this test
> case, I am not running with "auth" enabled.
>
> Since I /do/ want auth enabled eventually, I may have to just use
> > an email to salt-users+...@googlegroups.com <javascript:>.
> > For more options, visit https://groups.google.com/groups/opt_out
> <https://groups.google.com/groups/opt_out>.

Evan Johnson

unread,
Dec 2, 2013, 12:15:31 AM12/2/13
to salt-...@googlegroups.com
I finally have time to return to this issue. I filed a bug on GitHub:

FYI there is also this error in the minion log:

2013-12-01 20:56:15,918 [salt.loaded.int.module.mongodb][ERROR   ] Error connecting to database admin

And in case anyone is running in to the same issue, I am working around it by running a JS script directly via the `mongo` command line to create my users.

Thanks,
Evan
Reply all
Reply to author
Forward
0 new messages