diff --git a/examples/base.yml b/examples/base.yml new file mode 100644 index 0000000000..8841afb1d5 --- /dev/null +++ b/examples/base.yml @@ -0,0 +1,5 @@ +--- +- name: no selinux + action: command /usr/sbin/setenforce 0 +- name: no iptables + action: service name=iptables state=stopped diff --git a/examples/handlers.yml b/examples/handlers.yml new file mode 100644 index 0000000000..44b2b3d895 --- /dev/null +++ b/examples/handlers.yml @@ -0,0 +1,5 @@ +--- +- name: restart apache + action: service name=httpd state=restarted +- name: restart memcached + action: service name=memcached state=restarted diff --git a/examples/playbook.yml b/examples/playbook.yml index 188e24fcd7..fc4310976d 100644 --- a/examples/playbook.yml +++ b/examples/playbook.yml @@ -1,6 +1,7 @@ --- - hosts: '*' tasks: + - include: base.yml - name: configure template & module variables for future template calls action: setup http_port=80 max_clients=200 - name: write the apache config file @@ -10,5 +11,4 @@ - name: ensure apache is running action: service name=httpd state=started handlers: - - name: restart apache - - action: service name=httpd state=restarted + - include: handlers.yml diff --git a/lib/ansible/playbook.py b/lib/ansible/playbook.py index f236a33497..e89ee67cf1 100755 --- a/lib/ansible/playbook.py +++ b/lib/ansible/playbook.py @@ -15,14 +15,16 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . +############################################# + import ansible.runner import ansible.constants as C from ansible.utils import * import yaml import shlex +import os -# TODO: make a constants file rather than -# duplicating these +############################################# class PlayBook(object): @@ -72,9 +74,43 @@ class PlayBook(object): # playbook file can be passed in as a path or # as file contents (to support API usage) - if type(playbook) == str: - playbook = yaml.load(file(playbook).read()) - self.playbook = playbook + self.playbook = self._parse_playbook(playbook) + + def _parse_playbook(self, playbook): + ''' load YAML file, including handling for imported files ''' + + dirname = os.path.dirname(playbook) + playbook = yaml.load(file(playbook).read()) + + for play in playbook: + tasks = play.get('tasks',[]) + handlers = play.get('handlers', []) + + # process tasks in this file as well as imported tasks + new_tasks = [] + for task in tasks: + if 'include' in task: + path = path_dwim(dirname, task['include']) + included = yaml.load(file(path).read()) + for x in included: + new_tasks.append(x) + else: + new_tasks.append(task) + play['tasks'] = new_tasks + + # process handlers as well as imported handlers + new_handlers = [] + for handler in handlers: + if 'include' in handler: + path = path_dwim(dirname, handler['include']) + included = yaml.load(file(path).read()) + for x in included: + new_handlers.append(x) + else: + new_handlers.append(handler) + play['handlers'] = new_handlers + + return playbook def run(self): ''' run all patterns in the playbook ''' @@ -227,7 +263,7 @@ class PlayBook(object): if match_name == name: # flag the handler with the list of hosts # it needs to be run on, it will be run later - if not run in x: + if not 'run' in x: x['run'] = [] x['run'].append(host) diff --git a/lib/ansible/utils.py b/lib/ansible/utils.py index 5e80f8c0e8..29f37bdd22 100755 --- a/lib/ansible/utils.py +++ b/lib/ansible/utils.py @@ -165,4 +165,12 @@ def prepare_writeable_dir(tree): if not os.access(tree, os.W_OK): exit("Cannot write to path %s" % tree) +def path_dwim(basedir, given): + if given.startswith("/"): + return given + elif given.startswith("~/"): + return os.path.expanduser(given) + else: + return os.path.join(basedir, given) +