Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to discover current role in Python Fabric

Tags:

python

fabric

This is a very Fabric specific question, but more experienced python hackers might be able to answer this, even if they don't know Fabric.

I am trying to specify different behaviour in a command depending on which role it is running for, i.e.:

def restart():
    if (SERVERTYPE == "APACHE"):
        sudo("apache2ctl graceful",pty=True)
    elif (SERVERTYPE == "APE"):
        sudo("supervisorctl reload",pty=True)

I was hacking this with functions like this one:

def apache():
    global SERVERTYPE
    SERVERTYPE = "APACHE"
    env.hosts = ['xxx.xxx.com']

But that is obviously not very elegant and I just discovered roles, so my question is:

How do I figure out which role a current instance belongs to?

env.roledefs = {
    'apache': ['xxx.xxx.com'],
    'APE': ['yyy.xxx.com'],
}

Thanks!

like image 518
rdrey Avatar asked Jun 23 '10 04:06

rdrey


4 Answers

For everyone else ever with this question, here is my solution:

The key was finding env.host_string.

This is how I restart different types of servers with one command:

env.roledefs = {
    'apache': ['xxx.xxx.com'],
    'APE': ['yyy.xxx.com']
}

def apache():
    env.roles = ['apache']

...

def restart():
    if env.host_string in env.roledefs['apache']:
        sudo("apache2ctl graceful", pty=True)
    elif env.host_string in env.roledefs['APE']:
        sudo ("supervisorctl reload", pty=True)

enjoy!

like image 96
rdrey Avatar answered Oct 21 '22 19:10

rdrey


I didn't test it, but might work:

def _get_current_role():
    for role in env.roledefs.keys():
        if env.host_string in env.roledefs[role]:
            return role
    return None
like image 40
semente Avatar answered Oct 21 '22 19:10

semente


The env.roles will give you the roles specified by -R flag or hardcoded in the script itself. It won't contain the roles specified per task using the command line or using @roles decorator. There is currently no way of getting this kind of information.

The next release of fabric (1.9 probably) will provide env.effective_roles attribute with exactly what you want - the roles being used for the currently executed task. The code for that has already been merged into master.

Have a look at this issue.

like image 27
pbetkier Avatar answered Oct 21 '22 21:10

pbetkier


Update: Just checked the source code and it seems that this was already available as early as 1.4.2!

update 2: This seems not to work when using the @roles decorator (in 1.5.3)! It only works when specifying the roles using the -R command line flag.

For fabric 1.5.3 the current roles are directly available in `fabric.api.env.roles'. For example:

import fabric.api as fab

fab.env.roledefs['staging'] = ['bbs-evolution.ipsw.dt.ept.lu']
fab.env.roledefs['prod'] = ['bbs-arbiter.ipsw.dt.ept.lu']


@fab.task
def testrole():
    print fab.env.roles

Test output on the console:

› fab -R staging testrole
[bbs-evolution.ipsw.dt.ept.lu] Executing task 'testrole'
['staging']

Done.

Or:

› fab -R staging,prod testrole
[bbs-evolution.ipsw.dt.ept.lu] Executing task 'testrole'
['staging', 'prod']
[bbs-arbiter.ipsw.dt.ept.lu] Executing task 'testrole'
['staging', 'prod']

Done.

With this, we can do a simple in test in a fabric task:

@fab.task
def testrole():
    if 'prod' in fab.env.roles:
        do_production_stuff()
    elif 'staging' in fab.env.roles:
        do_staging_stuff()
    else:
        raise ValueError('No valid role specified!')
like image 36
exhuma Avatar answered Oct 21 '22 20:10

exhuma