Ability to import task lists and handler lists from a top level playbook file. It is possible

to use multiple import statements to implement 'class' like behavior, and also to share
a common list of handlers between multiple patterns.
This commit is contained in:
Michael DeHaan 2012-03-03 10:53:15 -05:00
parent 32c32abb4a
commit ab408b0000
5 changed files with 62 additions and 8 deletions

5
examples/base.yml Normal file
View file

@ -0,0 +1,5 @@
---
- name: no selinux
action: command /usr/sbin/setenforce 0
- name: no iptables
action: service name=iptables state=stopped

5
examples/handlers.yml Normal file
View file

@ -0,0 +1,5 @@
---
- name: restart apache
action: service name=httpd state=restarted
- name: restart memcached
action: service name=memcached state=restarted

View file

@ -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

View file

@ -15,14 +15,16 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#############################################
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:
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())
self.playbook = playbook
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)

View file

@ -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)