I managed to stumble on this when using an ep.io account.
I have no name!@app-runner02:/mnt/bundles/port-8840/app_image/app$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from fabric.api import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/bundles/port-8840/app_image/pyenv/lib/python2.7/site-packages/fabric/api.py", line 9, in <module>
from fabric.context_managers import cd, hide, settings, show, path, prefix, lcd
File "/bundles/port-8840/app_image/pyenv/lib/python2.7/site-packages/fabric/context_managers.py", line 13, in <module>
from fabric.state import env, output, win32
File "/bundles/port-8840/app_image/pyenv/lib/python2.7/site-packages/fabric/state.py", line 128, in <module>
File "/bundles/port-8840/app_image/pyenv/lib/python2.7/site-packages/fabric/state.py", line 75, in _get_system_username
KeyError: 'getpwuid(): uid not found: 26442'
I'm not sure what the correct behaviour should be, but a better error would indeed help.
As a work around I done something bad:
import pwd; pwd.getpwuid = lambda x: ["Monkey",]
... but it works fine (so far!)
If this username is only being collected to be used as a default when connecting to a remote host it would presumably be better to just make it a required parameter if one is not available? I am overwriting this anyway in my case.
Originally submitted by Dougal Matthews (d0ugal) on 2011-07-28 at 05:20am EDT
Jeff Forcier (bitprophet) posted:
Hah, I had no idea this was even possible. Good catch, we should definitely do something cleaner to handle that situation. Hopefully not by monkeypatching pwd, of course, but you know what they say about drastic times ;)
on 2011-07-28 at 01:17pm EDT
Im also trying to deploy to ep.io. Where did execute/put import pwd; pwd.getpwuid = lambda x: ["Monkey",]? In the fabfile.py?
import pwd; pwd.getpwuid = lambda x: ["Monkey",]
@saulshanabrook Yes, I think sticking that at the top of your fabfile might work. otherwise, I'm not sure where @d0ugal put it and you'll have to ask him.
I added it to my Django settings file, but at the top of the fabfile should be fine too.
I was trying to come up with a fix for this today with no luck
@d0ugal I tried adding import pwd; pwd.getpwuid = lambda x: ["Monkey",] in the first line of my fabfile.py and settings.py with no luck. When I try do epio run_command -- fab sync I still get KeyError: 'getpwuid(): uid not found: 42295'
epio run_command -- fab sync
'getpwuid(): uid not found: 42295'
@d0ugal -- seriously? Unless I miss my mark the problem is actually very simple, Fabric tries to be "nice" and pull in your system username for a default, in case the user did not specify env.user or user@hostname etc.
All we should really have to do is ensure the block calling getpwuid A) doesn't error in this situation and B) provides some dummy/default value if it can't get a real username.
Ideally something obvious so somebody who deploys on eg ep.io and does not provide their own username, is not confused. Maybe something stupid like "<no local user found>" and spit out a warning to stderr when it runs too.
"<no local user found>"
Sorry I had worded my reply a bit hastily - I didn't have a solution I was totally happy with.
Your suggestion is simpler than what I had in mind. I wasn't sure I liked the idea of using a default/dummy name, but one like you suggested would actually be clear enough in my opinion. I had wondered if it would be a good idea to set a default name and a flag of sorts(e.g. requires_username = True) so that we could provide a clearer error later. I'm not sure what the error would look like if nonexistant username is used.
Re: clearer error: I guess we could update the lazy connection machinery (the stuff that spits out the "you didn't give me a host, what's the host string?" message) to check for the default sentinel value (which I guess might as well be None after all) and alter that message to e.g "You don't have a user -- please specify user@host" if there's no user.
Would still be pretty easy to implement, even updating the existing "loop until I get something useful" logic to make sure we do get a user@ value (in the same way that it currently loops if you give it an empty string.)
Actually diving into it, and I think a simpler solution is simply to try/except and set to None. I'm willing to bet those of you encountering this error are manually setting env.user (or have a user value in env.host_string) since the platform you're deploying from has no real usernames -- am I right?
If that is the case, then adding more code to prompt the runner for input is kind of pointless -- the core bug here would be "I cannot continue past this point due to the exception" and not "users are confused when the default username is bad".
Please feel free to comment if you disagree with the above and would find some additional prompts (or perhaps erroring out, but with a useful message instead of KeyError) a better fix for your situation.
Set default username to None for bad getpwuid()
I think that fixes it. In fact, I looked into fixing it and came up with basically the same solution - I've been using this for a few days with no problems. Was waiting to use it in a more substantial project before reporting back:
Thanks for the fix!
Ha, in fact that is literally the same except I am returning an explicit, not implicit, None. (Mostly because I wanted to make it clear None was a specific sentinel value, I guess.)
Glad it works for you -- thanks for the report. I'll be releasing bugfixes for 1.1.x-1.3.x today most likely.