New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fabric.api.env.roles not updated when using @roles #938

Closed
exhuma opened this Issue Jul 18, 2013 · 1 comment

Comments

Projects
None yet
2 participants
@exhuma

exhuma commented Jul 18, 2013

See also the following SO answer: http://stackoverflow.com/a/17724207/160665

When using the @roles decorator, fabric.api.env.roles does not reflect this choice. This could cause issues when running a nested task which uses env.roles. A practical example from my case (leaving out the non-essential stuff):

import fabric.api as fab

fab.env.roledefs.update({
    'prod': '1.2.3.4',
    'staging': '2.3.4.5'
})

@fab.task
@fab.roles('staging')
def stage():
    # ... snip ...
    fab.execute(deploy)
    # ... snip ...


@fab.task
@fab.roles('prod')
def prod():
    # ... snip ...
    fab.execute(deploy)
    # ... snip ...


@fab.task
def deploy():
    print fab.env.roles
    if 'prod' in fab.env.roles:
        apache_vhostname = 'migrate.tld.foo.bar'
    elif 'staging' in fab.env.roles:
        apache_vhostname = 'migrate-rc.tld.foo.bar'
    else:
        raise ValueError('Can only deploy on roles "prod" and "staging". '
                        'You told me to deploy on {0!r}'.format(fab.env.roles))
    # ... snip ...

As illustrative purpose, running this fabfile gives me:

/tmp› fab prod
[1] Executing task 'prod'
[]
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/fabric/main.py", line 736, in main
    *args, **kwargs
File "/usr/local/lib/python2.7/dist-packages/fabric/tasks.py", line 314, in execute
    multiprocessing
File "/usr/local/lib/python2.7/dist-packages/fabric/tasks.py", line 211, in _execute
    return task.run(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/fabric/tasks.py", line 121, in run
    return self.wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/fabric/decorators.py", line 51, in inner_decorator
    return func(*args, **kwargs)
File "/tmp/fabfile.py", line 20, in prod
    fab.execute(deploy)
File "/usr/local/lib/python2.7/dist-packages/fabric/tasks.py", line 347, in execute
    results['<local-only>'] = task.run(*args, **new_kwargs)
File "/usr/local/lib/python2.7/dist-packages/fabric/tasks.py", line 121, in run
    return self.wrapped(*args, **kwargs)
File "/tmp/fabfile.py", line 33, in deploy
    'You told me to deploy on {0!r}'.format(fab.env.roles))
ValueError: Can only deploy on roles "prod" and "staging". You told me to deploy on []

But I expected:

/tmp› fab prod
[1] Executing task 'prod'
['prod']
@pbetkier

This comment has been minimized.

pbetkier commented Apr 14, 2014

Calling fab.execute(deploy) would result in deploy task being executed in a fresh context, without any roles defined. The role you defined using @roles decorator would not be in effect. That's probably not what you want, so you should be calling deploy() directly. In the current version of fabric you cannot investigate the roles in use though.

Now, my PR introduces a new env var called effective_roles which contains the roles that are in effect in the currently executed task. Once it gets merged, you will be able to do this:

@fab.task
@fab.roles('prod')
def prod():
    # ... snip ...
    deploy()
    # ... snip ...

@fab.task
def deploy():
    print fab.env.effective_roles
    # ... snip ...

Actually, deploy doesn't necessarily have to be decorated as @fab.task, unless you also plan to call it directly from the command line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment