jayshilling
jayshilling

Reputation: 351

How to run Fabric tasks directly from Python catching exceptions and output?

I'd like to run my existing fabfile tasks without the cli directly from Python. How do I catch 'execute' exceptions and capture the output for logging if any exceptions occur?

@roles(['localhost'])
def my_sudo_task():
    sudo('ls -l /root/')

from fabfile import my_sudo_task
from fabric.tasks import execute

execute(my_sudo_task)

here is my exact problem:

try:
    # is there a way to leave out stderr and capture it somehow?
    with settings(hide('stdout', 'stderr', 'aborts', 'warnings', 'running')):
        execute(my_sudo_task)
except Exception as e:  # doesnt catch error
    print ('ERROR')
    raise
except:
    print ('ERROR')  # catches but lacks the error message that i can log

Upvotes: 0

Views: 986

Answers (3)

Kris Musard
Kris Musard

Reputation: 11

The NetworkError and CommandTimeout exceptions are defined in the fabric.exceptions module. The execute() call returns a dictionary of whatever is returned by the task it executes with the hostnames as the keys. If an exception is encountered it will be stored in the dictionary as well. You can inspect the exception's 'message' attribute for a string description of the issue. See the following example:

>>> from fabric.api import run, execute
>>> from fabric.context_managers import quiet
>>> from fabric.state import env
>>> env.skip_bad_hosts = True
>>> env.warn_only = True
>>> def task_a():
...  return run('pwd')
...
>>> with quiet():
...  a = execute(task_a,hosts=['badhost'])
...
>>> a
{'badhost': NetworkError(Name lookup failed for badhost) => gaierror(8, 'nodename nor servname provided, or not known')}
>>> type(a['badhost'])
<class 'fabric.exceptions.NetworkError'>
>>> a['badhost'].message
'Name lookup failed for badhost'

Upvotes: 0

jayshilling
jayshilling

Reputation: 351

The following solved my issue

try:
    with settings(hide('stdout', 'stderr', 'aborts', 'warnings', 'running')):
        execute(my_sudo_task)
except SystemExit as e:
    print (e.message)

because 'execute' doesn't technically throw an exception

issubclass(SystemExit, Exception) = False

Upvotes: 0

jumbopap
jumbopap

Reputation: 4137

You should handle errors by examining result codes inside the task. Exceptions aren't going to be descriptive enough.

from fabric.api import *

@roles(['localhost'])
def my_sudo_task():
    with settings(warn_only=True):
        result = sudo('ls -l /root/')

    if result.return_code == 0:
        [do something...]
    elif result.return_code == 1:
        [do something...]
    else:
        [do something else...]



from fabfile import my_sudo_task
from fabric.tasks import execute

execute(my_sudo_task)

See the tutorial section on failure handling.

Upvotes: 1

Related Questions