Skip to content

Commit

Permalink
Add support for dict style roledefs
Browse files Browse the repository at this point in the history
  • Loading branch information
lundberg committed Aug 11, 2014
1 parent d243ebb commit a779c6f
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 5 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ Neilen Marais
Rory Geoghegan
Alexey Diyan
Kamil Kisiel
Jonas Lundberg
3 changes: 3 additions & 0 deletions fabric/task_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ def merge(hosts, roles, exclude, roledefs):
role_hosts = []
for role in roles:
value = roledefs[role]
# Handle dict style roledefs
if isinstance(value, dict):
value = value['hosts']
# Handle "lazy" roles (callables)
if callable(value):
value = value()
Expand Down
28 changes: 23 additions & 5 deletions sites/docs/usage/execution.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,29 @@ loading other fabfiles which also modify it, of course)::
'dns': ['ns1', 'ns2']
}

In addition to list/iterable object types, the values in ``env.roledefs`` may
be callables, and will thus be called when looked up when tasks are run instead
of at module load time. (For example, you could connect to remote servers
to obtain role definitions, and not worry about causing delays at fabfile load
time when calling e.g. ``fab --list``.)
Role definitions are not necessary configuration of hosts only, but could hold
other role specific settings of your choice. This is achieved by defining the
roles as dicts and host strings under a ``hosts`` key::

from fabric.api import env

env.roledefs = {
'web': {
'hosts': ['www1', 'www2', 'www3'],
'foo': 'bar'
},
'dns': {
'hosts': ['ns1', 'ns2'],
'foo': 'baz'
}
}

In addition to list/iterable object types, the values in ``env.roledefs``
(or value of ``hosts`` key in dict style definition) may be callables, and will
thus be called when looked up when tasks are run instead of at module load
time. (For example, you could connect to remote servers to obtain role
definitions, and not worry about causing delays at fabfile load time when
calling e.g. ``fab --list``.)

Use of roles is not required in any way -- it's simply a convenience in
situations where you have common groupings of servers.
Expand Down
2 changes: 2 additions & 0 deletions sites/www/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Changelog
=========

* :feature:`1098` Add support for dict style roledefs.
Thanks to Jonas Lundberg, `@lundberg`
* :release:`1.9.1 <2014-08-06>`
* :release:`1.8.5 <2014-08-06>`
* :release:`1.7.5 <2014-08-06>`
Expand Down
15 changes: 15 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,21 @@ def command():
eq_hosts(command, ['a', 'b'], env={'roledefs': spaced_roles})


dict_roles = {
'r1': {'hosts': ['a', 'b']},
'r2': ['b', 'c'],
}

def test_hosts_in_role_dict():
"""
Make sure hosts defined in env.roles are cleaned of extra spaces
"""
@roles('r1')
def command():
pass
eq_hosts(command, ['a', 'b'], env={'roledefs': dict_roles})


def test_hosts_decorator_expands_single_iterable():
"""
@hosts(iterable) should behave like @hosts(*iterable)
Expand Down

0 comments on commit a779c6f

Please sign in to comment.