Sgoettschkes
Sgoettschkes

Reputation: 13189

Fabric used as library not working

I cannot get fabric working when used as a library within my own python scripts. I made a very short example fabfile.py to demonstrate my problem:

#!/usr/bin/env python

from fabric.api import *

print("Hello")

def test():
    with settings(host_string='myIp', user="myUser", password="myPassword"):
        run("hostname")

if __name__ == '__main__':
   test()

Running fab works like a charm:

$ fab test
Hello
[myIp] run: hostname
[myIp] out: ThisHost
[myIp] out:


Done.
Disconnecting from myUser@myIp... done.

Ok, now, running the python script without fab seems to break somewhere:

$ python fabfile.py
Hello
[myIp] run: hostname

It immediatly returns, so it does not even seem to wait for a response. Maybe there are errors, but I don't see how to output those.

I am running this script inside my vagrant virtual machine. As fab executes without any errors, I guess this should not be a problem!

UPDATE

The script seems to crash as it does not execute anything after the first run. local on the other hand works!

We executed the script on a co-workers laptop and it runs without any issues. I am using Python 2.6.5 on Ubuntu 10.04 with fabric 1.5.1, so I guess there is a problem with some of this! Is there any way to debug this properly?

Upvotes: 3

Views: 2395

Answers (2)

Christian
Christian

Reputation: 309

I've experienced a similar issue, that the fab command exited without error but just a blank line on the first run()/sudo() command.

So I put the run() command into a try: except: block and printed the traceback:

def do_something():
    print(green("Executing on %(host)s as %(user)s" % env))
    try:
        run("uname -a")
    except:
        import traceback
        tb = traceback.format_exc()
        print(tb)

I saw that it the script exited in the fabfile/network.py at line 419 when it caught an EOFError or TypeError. I modified the script to:

...
except (EOFError, TypeError) as err:
    print err
    # Print a newline (in case user was sitting at prompt)
    print('')
    sys.exit(0)
...

which then printed out:

connect() got an unexpected keyword argument 'sock'

So I remove the sock keyword argument in the connect method a few lines above and it worked like charm. I guess it is a problem with a paramiko version, that does not allow the sock keyword.

Versions:

Python 2.7.3
Fabric >= 1.5.3
paramiko 1.10.0

Upvotes: 2

Christian Thieme
Christian Thieme

Reputation: 1124

if you look at the fab command it looks like this:

sys.exit(
   load_entry_point('Fabric==1.4.3', 'console_scripts', 'fab')()
)

this means it looks for a block labeled console_scripts in a file called entry_points.txt in the Fabric package and executes the methods listed there, in this case fabric.main:main

when we look at this method we see argument parsing, interesting fabfile importing and then:

if fabfile:
    docstring, callables, default = load_fabfile(fabfile)
    state.commands.update(callables)
....
for name, args, kwargs, arg_hosts, arg_roles, arg_exclude_hosts in commands_to_run:
    execute(
            name,
            hosts=arg_hosts,
            roles=arg_roles,
            exclude_hosts=arg_exclude_hosts,
            *args, **kwargs
        )   

with some experimentation we can come up with something like:

from fabric import state
from fabric.api import *
from fabric.tasks import execute
from fabric.network import disconnect_all

def test():
    with settings(host_string='host', user="user", password="password"):
        print run("hostname")

if __name__ == '__main__':
    state.commands.update({'test': test})
    execute("test") 

    if state.output.status:
        print("\nDone.")
    disconnect_all()

which is obviously very incomplete, but perhaps you only need to add the

disconnect_all()

line at the end of your script

Upvotes: 1

Related Questions