75
75
.. _playbooks: http://www.ansibleworks.com/docs/playbooks.html
76
76
.. _modules: http://www.ansibleworks.com/docs/modules.html
78
A further feature os the ansible hooks is to provide a light weight "action"
79
scripting tool. This is a decorator that you apply to a function, and that
80
function can now receive cli args, and can pass extra args to the playbook.
86
def some_action(amount, force="False"):
87
"Usage: some-action AMOUNT [force=True]" # <-- shown on error
88
# process the arguments
90
# return extra-vars to be passed to ansible-playbook
92
'amount': int(amount),
96
You can now create a symlink to hooks.py that can be invoked like a hook, but
99
# link actions/some-action to hooks/hooks.py
101
actions/some-action amount=10 force=true
82
109
import charmhelpers.contrib.templating.contexts
83
110
import charmhelpers.core.host
112
139
hosts_file.write('localhost ansible_connection=local')
115
def apply_playbook(playbook, tags=None):
142
def apply_playbook(playbook, tags=None, extra_vars=None):
116
143
tags = tags or []
117
144
tags = ",".join(tags)
118
145
charmhelpers.contrib.templating.contexts.juju_state_to_yaml(
119
146
ansible_vars_path, namespace_separator='__',
120
allow_hyphens_in_keys=False)
147
allow_hyphens_in_keys=False, mode=(stat.S_IRUSR | stat.S_IWUSR))
121
149
# we want ansible's log output to be unbuffered
122
150
env = os.environ.copy()
123
151
env['PYTHONUNBUFFERED'] = "1"
131
159
call.extend(['--tags', '{}'.format(tags)])
161
extra = ["%s=%s" % (k, v) for k, v in extra_vars.items()]
162
call.extend(['--extra-vars', " ".join(extra)])
132
163
subprocess.check_call(call, env=env)
172
203
"""Register any hooks handled by ansible."""
173
204
super(AnsibleHooks, self).__init__()
175
207
self.playbook_path = playbook_path
177
209
default_hooks = default_hooks or []
182
214
for hook in default_hooks:
183
215
self.register(hook, noop)
217
def register_action(self, name, function):
218
"""Register a hook"""
219
self._actions[name] = function
185
221
def execute(self, args):
186
222
"""Execute the hook followed by the playbook using the hook as tag."""
187
super(AnsibleHooks, self).execute(args)
188
223
hook_name = os.path.basename(args[0])
225
if hook_name in self._actions:
226
extra_vars = self._actions[hook_name](args[1:])
228
super(AnsibleHooks, self).execute(args)
189
230
charmhelpers.contrib.ansible.apply_playbook(
190
self.playbook_path, tags=[hook_name])
231
self.playbook_path, tags=[hook_name], extra_vars=extra_vars)
233
def action(self, *action_names):
234
"""Decorator, registering them as actions"""
235
def action_wrapper(decorated):
237
@functools.wraps(decorated)
239
kwargs = dict(arg.split('=') for arg in argv)
241
return decorated(**kwargs)
242
except TypeError as e:
243
if decorated.__doc__:
244
e.args += (decorated.__doc__,)
247
self.register_action(decorated.__name__, wrapper)
248
if '_' in decorated.__name__:
249
self.register_action(
250
decorated.__name__.replace('_', '-'), wrapper)
254
return action_wrapper