Skip to content

Instantly share code, notes, and snippets.

@termie
Last active December 30, 2015 10:39
Show Gist options
  • Select an option

  • Save termie/7817384 to your computer and use it in GitHub Desktop.

Select an option

Save termie/7817384 to your computer and use it in GitHub Desktop.
example code
from fabric import tasks
from fabric.api import env
env.skip_missing_roles = True
# Copied from https://github.com/fabric/fabric with a small change to
# use our class instead of the default
def task(*args, **kwargs):
"""
Decorator declaring the wrapped function to be a new-style task.
May be invoked as a simple, argument-less decorator (i.e. ``@task``) or
with arguments customizing its behavior (e.g. ``@task(alias='myalias')``).
Please see the :ref:`new-style task <task-decorator>` documentation for
details on how to use this decorator.
.. versionchanged:: 1.2
Added the ``alias``, ``aliases``, ``task_class`` and ``default``
keyword arguments. See :ref:`task-decorator-arguments` for details.
.. versionchanged:: 1.5
Added the ``name`` keyword argument.
.. seealso:: `~fabric.docs.unwrap_tasks`, `~fabric.tasks.WrappedCallableTask`
"""
invoked = bool(not args or kwargs)
task_class = kwargs.pop("task_class", AdvancedRolesTask)
if not invoked:
func, args = args[0], ()
def wrapper(func):
return task_class(func, *args, **kwargs)
return wrapper if invoked else wrapper(func)
def build_real_roles(roles):
all_roles = env.roledefs.keys()
out_roles = set()
# Special role that resolves to all defined hosts.
if 'all' in roles:
out_roles.add(all_roles)
for role in roles:
if role == 'all':
continue
if role.startswith('+'):
out_roles.add(role[1:])
elif role.startswith('-'):
out_roles.discard(role[1:])
else:
# If we skip missing check whether this role is defined first
if env.skip_missing_roles:
if role in all_roles:
out_roles.add(role)
else:
out_roles.add(role)
print list(out_roles)
return list(out_roles)
class AdvancedRolesTask(tasks.WrappedCallableTask):
"""Task that adds some additional features to roles.
Allows:
Prepending a role with '+' to require include.
Prepending a role with a '-' to force exclude.
A special role 'all' that resolves to all the roles.
By default skips roles that are missing.
"""
def get_hosts(self, *args, **kw):
roles = build_real_roles(getattr(self, 'roles', []))
setattr(self, 'roles', roles)
return super(AdvancedRolesTask, self).get_hosts(*args, **kw)
@roles('all')
@parallel
@task
def hosts():
hostsfile = util.files('farmboy/hosts')
hosts = []
# TODO(termie): does this break if we use callable roledefs?
for role, role_hosts in env.roledefs.iteritems():
if len(role_hosts) == 1:
hosts.append('%s %s' % (util.host(role_hosts[0]), role))
continue
for i, role_host in enumerate(role_hosts):
hosts.append('%s %s-%s' % (util.host(role_host), role, i))
hosts_str = '\n'.join(hosts)
print hosts_str
fabtools.require.files.template_file(
template_source = hostsfile,
context = {'hosts': hosts_str},
path = '/etc/hosts',
owner = 'root',
group = 'root',
mode = '644',
use_sudo = True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment