TestPlayBook.py 6.64 KB
Newer Older
1 2 3 4 5 6 7 8

# tests are fairly 'live' (but safe to run)
# setup authorized_keys for logged in user such
# that the user can log in as themselves before running tests

import unittest
import getpass
import ansible.playbook
9
import ansible.utils as utils
10
import ansible.callbacks as ans_callbacks
11 12 13
import os
import shutil

14 15
EVENTS = []

16
class TestCallbacks(object):
17
    # using same callbacks class for both runner and playbook
18 19

    def __init__(self):
20
        pass
21 22 23 24 25

    def set_playbook(self, playbook):
        self.playbook = playbook

    def on_start(self):
26
        EVENTS.append('start')
27

28
    def on_skipped(self, host, item=None):
29
        EVENTS.append([ 'skipped', [ host ]])
30

31
    def on_import_for_host(self, host, filename):
32
        EVENTS.append([ 'import', [ host, filename ]])
33

34
    def on_error(self, host, msg):
35
        EVENTS.append([ 'stderr', [ host, msg ]])
36

37 38 39
    def on_not_import_for_host(self, host, missing_filename):
        pass

40 41 42
    def on_notify(self, host, handler):
        EVENTS.append([ 'notify', [ host, handler ]])

43
    def on_task_start(self, name, is_conditional):
44
        EVENTS.append([ 'task start', [ name, is_conditional ]])
45

Petros Moisiadis committed
46 47
    def on_failed(self, host, results, ignore_errors):
        EVENTS.append([ 'failed', [ host, results, ignore_errors ]])
48

49
    def on_ok(self, host, result):
50
        # delete certain info from host_result to make test comparisons easier
51
        host_result = result.copy()
52
        for k in [ 'ansible_job_id', 'results_file', 'md5sum', 'delta', 'start', 'end' ]:
53 54
            if k in host_result:
                del host_result[k]
55 56
        for k in host_result.keys():
            if k.startswith('facter_') or k.startswith('ohai_'):
Michael DeHaan committed
57
                del host_result[k]
58
        EVENTS.append([ 'ok', [ host, host_result ]])
59 60

    def on_play_start(self, pattern):
61
        EVENTS.append([ 'play start', [ pattern ]])
62

63 64
    def on_async_ok(self, host, res, jid):
        EVENTS.append([ 'async ok', [ host ]])
65

66
    def on_async_poll(self, host, res, jid, clock):
67
        EVENTS.append([ 'async poll', [ host ]])
68

69 70 71
    def on_async_failed(self, host, res, jid):
        EVENTS.append([ 'async failed', [ host ]])

72 73
    def on_unreachable(self, host, msg):
        EVENTS.append([ 'failed/dark', [ host, msg ]])
74

75
    def on_setup(self):
76
        pass
Michael DeHaan committed
77

78 79
    def on_no_hosts(self):
        pass
80

81
class TestPlaybook(unittest.TestCase):
82 83 84 85 86 87 88

   def setUp(self):
       self.user = getpass.getuser()
       self.cwd = os.getcwd()
       self.test_dir = os.path.join(self.cwd, 'test')
       self.stage_dir = self._prepare_stage_dir()

89 90 91 92 93
       if os.path.exists('/tmp/ansible_test_data_copy.out'):
           os.unlink('/tmp/ansible_test_data_copy.out')
       if os.path.exists('/tmp/ansible_test_data_template.out'):
           os.unlink('/tmp/ansible_test_data_template.out')

94 95 96 97 98 99 100 101 102 103 104 105 106 107
   def _prepare_stage_dir(self):
       stage_path = os.path.join(self.test_dir, 'test_data')
       if os.path.exists(stage_path):
           shutil.rmtree(stage_path, ignore_errors=False)
           assert not os.path.exists(stage_path)
       os.makedirs(stage_path)
       assert os.path.exists(stage_path)
       return stage_path

   def _get_test_file(self, filename):
       # get a file inside the test input directory
       filename = os.path.join(self.test_dir, filename)
       assert os.path.exists(filename)
       return filename
Michael DeHaan committed
108

109 110 111 112 113
   def _get_stage_file(self, filename):
       # get a file inside the test output directory
       filename = os.path.join(self.stage_dir, filename)
       return filename

114
   def _run(self, test_playbook, host_list='test/ansible_hosts'):
115 116 117 118
       ''' run a module and get the localhost results '''
       self.test_callbacks = TestCallbacks()
       self.playbook = ansible.playbook.PlayBook(
           playbook     = test_playbook,
119
           host_list    = host_list,
120 121 122 123 124
           module_path  = 'library/',
           forks        = 1,
           timeout      = 5,
           remote_user  = self.user,
           remote_pass  = None,
125 126 127
           stats            = ans_callbacks.AggregateStats(),
           callbacks        = self.test_callbacks,
           runner_callbacks = self.test_callbacks
128
       )
129 130
       result = self.playbook.run()
       return result
131 132 133

   def test_one(self):
       pb = os.path.join(self.test_dir, 'playbook1.yml')
134
       actual = self._run(pb)
135

Michael DeHaan committed
136
       # if different, this will output to screen
137
       print "**ACTUAL**"
138
       print utils.jsonify(actual, format=True)
Michael DeHaan committed
139
       expected =  {
140
            "localhost": {
Michael DeHaan committed
141 142 143 144
                "changed": 9,
                "failures": 0,
                "ok": 11,
                "skipped": 1,
145 146 147 148
                "unreachable": 0
            }
       }
       print "**EXPECTED**"
149 150 151
       print utils.jsonify(expected, format=True)

       assert utils.jsonify(expected, format=True) == utils.jsonify(actual,format=True)
152

153 154
       # make sure the template module took options from the vars section
       data = file('/tmp/ansible_test_data_template.out').read()
155
       print data
156 157
       assert data.find("ears") != -1, "template success"

158 159 160 161 162
   def test_aliased_node(self):
       pb = os.path.join(self.test_dir, 'alias_playbook.yml')
       actual = self._run(pb, 'test/alias_hosts')
       expected = {
           "alias-node.example.com": {
163
                "changed": 5,
164
                "failures": 0,
165
                "ok": 6,
166 167
                "skipped": 1,
                "unreachable": 0,
168 169 170 171 172 173 174 175
            },
            "other-alias-node.example.com": {
                "changed": 1,
                "failures": 0,
                "ok": 1,
                "skipped": 0,
                "unreachable": 1,
            },
176 177 178 179
       }

       assert utils.jsonify(expected, format=True) == utils.jsonify(actual, format=True)

180 181 182 183 184 185 186 187 188 189 190
   def test_playbook_vars(self): 
       test_callbacks = TestCallbacks()
       playbook = ansible.playbook.PlayBook(
           playbook=os.path.join(self.test_dir, 'test_playbook_vars', 'playbook.yml'),
           host_list='test/test_playbook_vars/hosts',
           stats=ans_callbacks.AggregateStats(),
           callbacks=test_callbacks,
           runner_callbacks=test_callbacks
       )
       playbook.run()

191 192 193 194 195 196 197 198 199 200 201
   def test_yaml_hosts_list(self):
       # Make sure playbooks support hosts: [host1, host2]
       # TODO: Actually run the play on more than one host
       test_callbacks = TestCallbacks()
       playbook = ansible.playbook.PlayBook(
           playbook=os.path.join(self.test_dir, 'hosts_list.yml'),
           host_list='test/ansible_hosts',
           stats=ans_callbacks.AggregateStats(),
           callbacks=test_callbacks,
           runner_callbacks=test_callbacks
       )
202
       play = ansible.playbook.Play(playbook, playbook.playbook[0], os.getcwd())
203
       assert play.hosts == ';'.join(('host1', 'host2', 'host3'))
204