Discussion:
[Fab-user] with_settings decorator generating RuntimeError (generator didn't yield)
Felix Almeida
2015-03-11 23:53:09 UTC
Permalink
Hi all,

I need to validate if a certain UNIX account is able to log in to a series of servers of mixed flavors (HP-UX, Solaris, RHEL and AIX) so I'm trying to do it with fabric.

I wanted to apply hide("status") to an entire internal function, but I keep getting the following error:

elxin009: ~/fabric # fab main
[bsnbk001] out: SunOS
[bsnbk001] out:
[bsnbk001] OS is SunOS
Disconnecting from bsnbk001... done.
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/fabric/main.py", line 743, in main
*args, **kwargs
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 424, in execute
results['<local-only>'] = task.run(*args, **new_kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/home/felix/fabric/fabfile.py", line 24, in main
execute(_my_function, hosts=host_list)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 384, in execute
multiprocessing
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 274, in _execute
return task.run(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/decorators.py", line 215, in inner
with settings(*arg_settings, **kw_settings):
File "/usr/local/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/usr/local/lib/python2.7/contextlib.py", line 112, in nested
vars.append(enter())
File "/usr/local/lib/python2.7/contextlib.py", line 19, in __enter__
raise RuntimeError("generator didn't yield")
RuntimeError: generator didn't yield

This is a very simplified version of my original code that I'm using for troubleshooting since it generates the same error:

from fabric.api import task, hide, execute, env, puts, run, with_settings

env.use_shell = False
env.disable_known_hosts = True
env.warn_only = True
env.abort_on_prompts = True
env.skip_bad_hosts = True
env.command_timeout = 3
env.eagerly_disconnect = True
env.always_use_pty = False

@with_settings(hide("status"))
def _my_function():
try:
out = run("uname")
puts("OS is " + out)
except SystemExit:
puts("can't get the OS")

@task
def main():
host_list = [line.rstrip("\n") for line in open("hosts.txt")]
with hide("running"):
execute(_my_function, hosts=host_list)

The hosts.txt file is just a text file with one hostname per line. This was the content of the file when I captured the output above (just two servers):

bsnbk001
slxap003

In fact, none of the env settings makes any difference, but if I comment out the @with_settings line it works as expected. If the hosts.txt file contains only one hostname then it also works without any errors.

Please, any ideas of what I am doing wrong? I'm still learning Python so forgive me if I'm doing something silly.


Thank you,
Felix

PS: I'm running Fabric 1.10.1 and Paramiko 1.15.2 on RHEL.





________________________________
This communication is confidential. We only send and receive email on the basis of the terms set out at www.rogers.com/web/content/emailnotice<http://www.rogers.com/web/content/emailnotice>



Ce message est confidentiel. Notre transmission et r?ception de courriels se fait strictement suivant les modalit?s ?nonc?es dans l'avis publi? ? www.rogers.com/aviscourriel <http://www.rogers.com/aviscourriel>
________________________________
Carlos García
2015-03-12 09:04:29 UTC
Permalink
Hi Felix,

Have you try to use a context manager instead of the decorator? IÂŽm not
really sure if you can use it as a decorator...


def _my_function():

with_settings(hide("status")):

try:

out = run("uname")

puts("OS is " + out)

except SystemExit:

puts("can't get the OS")

That's the way I'm using it in my scripts and it seems to work, but we're
using it just for Ubuntu and CentOS...

Keep us posted

Regards!
Post by Felix Almeida
Hi all,
I need to validate if a certain UNIX account is able to log in to a
series of servers of mixed flavors (HP-UX, Solaris, RHEL and AIX) so I’m
trying to do it with fabric.
I wanted to apply *hide("status")* to an entire internal function, but
elxin009: ~/fabric # fab main
[bsnbk001] out: SunOS
[bsnbk001] OS is SunOS
Disconnecting from bsnbk001... done.
File "/usr/local/lib/python2.7/site-packages/fabric/main.py", line 743, in main
*args, **kwargs
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 424, in execute
results['<local-only>'] = task.run(*args, **new_kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/home/felix/fabric/fabfile.py", line 24, in main
execute(_my_function, hosts=host_list)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 384, in execute
multiprocessing
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 274, in _execute
return task.run(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/decorators.py", line 215, in inner
File "/usr/local/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/usr/local/lib/python2.7/contextlib.py", line 112, in nested
vars.append(enter())
File "/usr/local/lib/python2.7/contextlib.py", line 19, in __enter__
raise RuntimeError("generator didn't yield")
RuntimeError: generator didn't yield
This is a very simplified version of my original code that I’m using for
from fabric.api import task, hide, execute, env, puts, run, with_settings
env.use_shell = False
env.disable_known_hosts = True
env.warn_only = True
env.abort_on_prompts = True
env.skip_bad_hosts = True
env.command_timeout = 3
env.eagerly_disconnect = True
env.always_use_pty = False
@with_settings(hide("status"))
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
@task
host_list = [line.rstrip("\n") for line in open("hosts.txt")]
execute(_my_function, hosts=host_list)
The *hosts.txt* file is just a text file with one hostname per line.
This was the content of the file when I captured the output above (just two
bsnbk001
slxap003
In fact, none of the *env* settings makes any difference, but if I
*hosts.txt* file contains only one hostname then it also works without
any errors.
Please, any ideas of what I am doing wrong? I’m still learning Python so
forgive me if I’m doing something silly.
Thank you,
Felix
PS: I’m running Fabric 1.10.1 and Paramiko 1.15.2 on RHEL.
------------------------------
This communication is confidential. We only send and receive email on the
basis of the terms set out at www.rogers.com/web/content/emailnotice
Ce message est confidentiel. Notre transmission et réception de courriels
se fait strictement suivant les modalités énoncées dans l’avis publié à www.rogers.com/aviscourriel
------------------------------
_______________________________________________
Fab-user mailing list
https://lists.nongnu.org/mailman/listinfo/fab-user
Felix Almeida
2015-03-12 14:20:47 UTC
Permalink
Hi Carlos,

Yes, if I do that it works (in fact that’s how it was before):

def _my_function():
with settings(hide("status")):
try:
out = run("uname")
puts("OS is " + out)
except SystemExit:
puts("can't get the OS")

However having to indent the whole function body just because I want to hide the status messages is weird, especially after reading this:

“Allows you to wrap an entire function as if it was called inside a block with the settings context manager. This may be useful if you know you want a given setting applied to an entire function body...” (source: http://docs.fabfile.org/en/latest/api/core/decorators.html#fabric.decorators.with_settings).

Which is exactly what I want.

Anyway, maybe I should just do that and move on, but it’s kind of frustrating.
Moreover, now I’m curious about why this error is happening and I’m sure there is a learning opportunity there for me. ;)

Thanks,
Felix


From: Carlos García [mailto:***@stoneworksolutions.net]
Sent: Thursday, March 12, 2015 5:04 AM
To: Felix Almeida
Cc: fab-***@nongnu.org
Subject: Re: [Fab-user] with_settings decorator generating RuntimeError (generator didn't yield)

Hi Felix,

Have you try to use a context manager instead of the decorator? IÂŽm not really sure if you can use it as a decorator...


def _my_function():
with_settings(hide("status")):
try:
out = run("uname")
puts("OS is " + out)
except SystemExit:
puts("can't get the OS")

That's the way I'm using it in my scripts and it seems to work, but we're using it just for Ubuntu and CentOS...

Keep us posted

Regards!

2015-03-12 0:53 GMT+01:00 Felix Almeida <***@rci.rogers.com<mailto:***@rci.rogers.com>>:
Hi all,

I need to validate if a certain UNIX account is able to log in to a series of servers of mixed flavors (HP-UX, Solaris, RHEL and AIX) so I’m trying to do it with fabric.

I wanted to apply hide("status") to an entire internal function, but I keep getting the following error:

elxin009: ~/fabric # fab main
[bsnbk001] out: SunOS
[bsnbk001] out:
[bsnbk001] OS is SunOS
Disconnecting from bsnbk001... done.
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/fabric/main.py", line 743, in main
*args, **kwargs
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 424, in execute
results['<local-only>'] = task.run(*args, **new_kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/home/felix/fabric/fabfile.py", line 24, in main
execute(_my_function, hosts=host_list)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 384, in execute
multiprocessing
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 274, in _execute
return task.run(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/decorators.py", line 215, in inner
with settings(*arg_settings, **kw_settings):
File "/usr/local/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/usr/local/lib/python2.7/contextlib.py", line 112, in nested
vars.append(enter())
File "/usr/local/lib/python2.7/contextlib.py", line 19, in __enter__
raise RuntimeError("generator didn't yield")
RuntimeError: generator didn't yield

This is a very simplified version of my original code that I’m using for troubleshooting since it generates the same error:

from fabric.api import task, hide, execute, env, puts, run, with_settings

env.use_shell = False
env.disable_known_hosts = True
env.warn_only = True
env.abort_on_prompts = True
env.skip_bad_hosts = True
env.command_timeout = 3
env.eagerly_disconnect = True
env.always_use_pty = False

@with_settings(hide("status"))
def _my_function():
try:
out = run("uname")
puts("OS is " + out)
except SystemExit:
puts("can't get the OS")

@task
def main():
host_list = [line.rstrip("\n") for line in open("hosts.txt")]
with hide("running"):
execute(_my_function, hosts=host_list)

The hosts.txt file is just a text file with one hostname per line. This was the content of the file when I captured the output above (just two servers):

bsnbk001
slxap003

In fact, none of the env settings makes any difference, but if I comment out the @with_settings line it works as expected. If the hosts.txt file contains only one hostname then it also works without any errors.

Please, any ideas of what I am doing wrong? I’m still learning Python so forgive me if I’m doing something silly.


Thank you,
Felix

PS: I’m running Fabric 1.10.1 and Paramiko 1.15.2 on RHEL.





________________________________
This communication is confidential. We only send and receive email on the basis of the terms set out at www.rogers.com/web/content/emailnotice<http://www.rogers.com/web/content/emailnotice>



Ce message est confidentiel. Notre transmission et réception de courriels se fait strictement suivant les modalités énoncées dans l’avis publié à www.rogers.com/aviscourriel <http://www.rogers.com/aviscourriel>
________________________________
Brandon Whaley
2015-03-12 14:24:00 UTC
Permalink
Hi Felix,

You're not the first to hit this problem. When I've tested in the
past, it seems like the decorator code is getting executed more than
once, but since it relies on generators, that means the second time
fails. I haven't yet figured out why that happens but I may take some
time this weekend to come up with a minimal test case and go from
there.

On Thu, Mar 12, 2015 at 10:20 AM, Felix Almeida
Post by Felix Almeida
Hi Carlos,
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
However having to indent the whole function body just because I want to
“Allows you to wrap an entire function as if it was called inside a block
with the settings context manager. This may be useful if you know you want a
http://docs.fabfile.org/en/latest/api/core/decorators.html#fabric.decorators.with_settings).
Which is exactly what I want.
Anyway, maybe I should just do that and move on, but it’s kind of
frustrating.
Moreover, now I’m curious about why this error is happening and I’m sure
there is a learning opportunity there for me. ;)
Thanks,
Felix
Sent: Thursday, March 12, 2015 5:04 AM
To: Felix Almeida
Subject: Re: [Fab-user] with_settings decorator generating RuntimeError
(generator didn't yield)
Hi Felix,
Have you try to use a context manager instead of the decorator? I´m not
really sure if you can use it as a decorator...
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
That's the way I'm using it in my scripts and it seems to work, but we're
using it just for Ubuntu and CentOS...
Keep us posted
Regards!
Hi all,
I need to validate if a certain UNIX account is able to log in to a series
of servers of mixed flavors (HP-UX, Solaris, RHEL and AIX) so I’m trying to
do it with fabric.
I wanted to apply hide("status") to an entire internal function, but I
elxin009: ~/fabric # fab main
[bsnbk001] out: SunOS
[bsnbk001] OS is SunOS
Disconnecting from bsnbk001... done.
File "/usr/local/lib/python2.7/site-packages/fabric/main.py", line 743, in main
*args, **kwargs
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 424, in execute
results['<local-only>'] = task.run(*args, **new_kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/home/felix/fabric/fabfile.py", line 24, in main
execute(_my_function, hosts=host_list)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 384, in execute
multiprocessing
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 274, in _execute
return task.run(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/decorators.py", line 215, in inner
File "/usr/local/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/usr/local/lib/python2.7/contextlib.py", line 112, in nested
vars.append(enter())
File "/usr/local/lib/python2.7/contextlib.py", line 19, in __enter__
raise RuntimeError("generator didn't yield")
RuntimeError: generator didn't yield
This is a very simplified version of my original code that I’m using for
from fabric.api import task, hide, execute, env, puts, run, with_settings
env.use_shell = False
env.disable_known_hosts = True
env.warn_only = True
env.abort_on_prompts = True
env.skip_bad_hosts = True
env.command_timeout = 3
env.eagerly_disconnect = True
env.always_use_pty = False
@with_settings(hide("status"))
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
@task
host_list = [line.rstrip("\n") for line in open("hosts.txt")]
execute(_my_function, hosts=host_list)
The hosts.txt file is just a text file with one hostname per line. This
was the content of the file when I captured the output above (just two
bsnbk001
slxap003
In fact, none of the env settings makes any difference, but if I comment
contains only one hostname then it also works without any errors.
Please, any ideas of what I am doing wrong? I’m still learning Python so
forgive me if I’m doing something silly.
Thank you,
Felix
PS: I’m running Fabric 1.10.1 and Paramiko 1.15.2 on RHEL.
________________________________
This communication is confidential. We only send and receive email on the
basis of the terms set out at www.rogers.com/web/content/emailnotice
Ce message est confidentiel. Notre transmission et réception de courriels se
fait strictement suivant les modalités énoncées dans l’avis publié à
www.rogers.com/aviscourriel
________________________________
_______________________________________________
Fab-user mailing list
https://lists.nongnu.org/mailman/listinfo/fab-user
Felix Almeida
2015-03-12 14:30:19 UTC
Permalink
Thank you Brandon!
Please keep me posted on your progress.

Perhaps it would be wise to remove this decorator from the documentation until it gets fixed (assuming it's a bug). What do you guys think?


-----Original Message-----
From: Brandon Whaley [mailto:***@gmail.com]
Sent: Thursday, March 12, 2015 10:24 AM
To: Felix Almeida
Cc: Carlos García; fab-***@nongnu.org
Subject: Re: [Fab-user] with_settings decorator generating RuntimeError (generator didn't yield)

Hi Felix,

You're not the first to hit this problem. When I've tested in the past, it seems like the decorator code is getting executed more than once, but since it relies on generators, that means the second time fails. I haven't yet figured out why that happens but I may take some time this weekend to come up with a minimal test case and go from there.
Post by Felix Almeida
Hi Carlos,
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
However having to indent the whole function body just because I want
“Allows you to wrap an entire function as if it was called inside a
block with the settings context manager. This may be useful if you
http://docs.fabfile.org/en/latest/api/core/decorators.html#fabric.decorators.with_settings).
Which is exactly what I want.
Anyway, maybe I should just do that and move on, but it’s kind of
frustrating.
Moreover, now I’m curious about why this error is happening and I’m
sure there is a learning opportunity there for me. ;)
Thanks,
Felix
Sent: Thursday, March 12, 2015 5:04 AM
To: Felix Almeida
Subject: Re: [Fab-user] with_settings decorator generating
RuntimeError (generator didn't yield)
Hi Felix,
Have you try to use a context manager instead of the decorator? I´m
not really sure if you can use it as a decorator...
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
That's the way I'm using it in my scripts and it seems to work, but
we're using it just for Ubuntu and CentOS...
Keep us posted
Regards!
Hi all,
I need to validate if a certain UNIX account is able to log in to a
series of servers of mixed flavors (HP-UX, Solaris, RHEL and AIX) so
I’m trying to do it with fabric.
I wanted to apply hide("status") to an entire internal function, but
elxin009: ~/fabric # fab main
[bsnbk001] out: SunOS
[bsnbk001] OS is SunOS
Disconnecting from bsnbk001... done.
File "/usr/local/lib/python2.7/site-packages/fabric/main.py", line 743, in main
*args, **kwargs
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 424, in execute
results['<local-only>'] = task.run(*args, **new_kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/home/felix/fabric/fabfile.py", line 24, in main
execute(_my_function, hosts=host_list)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 384, in execute
multiprocessing
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 274, in _execute
return task.run(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/tasks.py", line 174, in run
return self.wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/fabric/decorators.py", line 215, in inner
File "/usr/local/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/usr/local/lib/python2.7/contextlib.py", line 112, in nested
vars.append(enter())
File "/usr/local/lib/python2.7/contextlib.py", line 19, in __enter__
raise RuntimeError("generator didn't yield")
RuntimeError: generator didn't yield
This is a very simplified version of my original code that I’m using
from fabric.api import task, hide, execute, env, puts, run,
with_settings
env.use_shell = False
env.disable_known_hosts = True
env.warn_only = True
env.abort_on_prompts = True
env.skip_bad_hosts = True
env.command_timeout = 3
env.eagerly_disconnect = True
env.always_use_pty = False
@with_settings(hide("status"))
out = run("uname")
puts("OS is " + out)
puts("can't get the OS")
@task
host_list = [line.rstrip("\n") for line in open("hosts.txt")]
execute(_my_function, hosts=host_list)
The hosts.txt file is just a text file with one hostname per line.
This was the content of the file when I captured the output above (just two
bsnbk001
slxap003
In fact, none of the env settings makes any difference, but if I
hosts.txt file contains only one hostname then it also works without any errors.
Please, any ideas of what I am doing wrong? I’m still learning
Python so forgive me if I’m doing something silly.
Thank you,
Felix
PS: I’m running Fabric 1.10.1 and Paramiko 1.15.2 on RHEL.
________________________________
This communication is confidential. We only send and receive email on
the basis of the terms set out at
www.rogers.com/web/content/emailnotice
Ce message est confidentiel. Notre transmission et réception de
courriels se fait strictement suivant les modalités énoncées dans
l’avis publié à www.rogers.com/aviscourriel
________________________________
_______________________________________________
Fab-user mailing list
https://lists.nongnu.org/mailman/listinfo/fab-user
________________________________
This communication is confidential. We only send and receive email on the basis of the terms set out at www.rogers.com/web/content/emailnotice<http://www.rogers.com/web/content/emailnotice>



Ce message est confidentiel. Notre transmission et réception de courriels se fait strictement suivant les modalités énoncées dans l’avis publié à www.rogers.com/aviscourriel <http://www.rogers.com/aviscourriel>
________________________________

Loading...