task_utils.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. from fabric.utils import abort, indent
  2. from fabric import state
  3. # For attribute tomfoolery
  4. class _Dict(dict):
  5. pass
  6. def _crawl(name, mapping):
  7. """
  8. ``name`` of ``'a.b.c'`` => ``mapping['a']['b']['c']``
  9. """
  10. key, _, rest = name.partition('.')
  11. value = mapping[key]
  12. if not rest:
  13. return value
  14. return _crawl(rest, value)
  15. def crawl(name, mapping):
  16. try:
  17. result = _crawl(name, mapping)
  18. # Handle default tasks
  19. if isinstance(result, _Dict):
  20. if getattr(result, 'default', False):
  21. result = result.default
  22. # Ensure task modules w/ no default are treated as bad targets
  23. else:
  24. result = None
  25. return result
  26. except (KeyError, TypeError):
  27. return None
  28. def merge(hosts, roles, exclude, roledefs):
  29. """
  30. Merge given host and role lists into one list of deduped hosts.
  31. """
  32. # Abort if any roles don't exist
  33. bad_roles = [x for x in roles if x not in roledefs]
  34. if bad_roles:
  35. abort("The following specified roles do not exist:\n%s" % (
  36. indent(bad_roles)
  37. ))
  38. # Coerce strings to one-item lists
  39. if isinstance(hosts, basestring):
  40. hosts = [hosts]
  41. # Look up roles, turn into flat list of hosts
  42. role_hosts = []
  43. for role in roles:
  44. value = roledefs[role]
  45. # Handle dict style roledefs
  46. if isinstance(value, dict):
  47. value = value['hosts']
  48. # Handle "lazy" roles (callables)
  49. if callable(value):
  50. value = value()
  51. role_hosts += value
  52. # Strip whitespace from host strings.
  53. cleaned_hosts = [x.strip() for x in list(hosts) + list(role_hosts)]
  54. # Return deduped combo of hosts and role_hosts, preserving order within
  55. # them (vs using set(), which may lose ordering) and skipping hosts to be
  56. # excluded.
  57. # But only if the user hasn't indicated they want this behavior disabled.
  58. all_hosts = cleaned_hosts
  59. if state.env.dedupe_hosts:
  60. deduped_hosts = []
  61. for host in cleaned_hosts:
  62. if host not in deduped_hosts and host not in exclude:
  63. deduped_hosts.append(host)
  64. all_hosts = deduped_hosts
  65. return all_hosts
  66. def parse_kwargs(kwargs):
  67. new_kwargs = {}
  68. hosts = []
  69. roles = []
  70. exclude_hosts = []
  71. for key, value in kwargs.iteritems():
  72. if key == 'host':
  73. hosts = [value]
  74. elif key == 'hosts':
  75. hosts = value
  76. elif key == 'role':
  77. roles = [value]
  78. elif key == 'roles':
  79. roles = value
  80. elif key == 'exclude_hosts':
  81. exclude_hosts = value
  82. else:
  83. new_kwargs[key] = value
  84. return new_kwargs, hosts, roles, exclude_hosts