TestPlayVarsFiles.py 12.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
#!/usr/bin/env python

import os
import shutil
from tempfile import mkstemp
from tempfile import mkdtemp
from ansible.playbook.play import Play
import ansible

import unittest
from nose.plugins.skip import SkipTest


class FakeCallBacks(object):
    def __init__(self):
        pass
    def on_vars_prompt(self):
        pass
    def on_import_for_host(self, host, filename):
        pass

class FakeInventory(object):
    def __init__(self):
        self.hosts = {}
    def basedir(self):
        return "."        
    def get_variables(self, host, vault_password=None):
        if host in self.hosts:
            return self.hosts[host]        
        else:
            return {}            

class FakePlayBook(object):
    def __init__(self):
        self.extra_vars = {}
        self.remote_user = None
        self.remote_port = None
        self.sudo = None
        self.sudo_user = None
        self.su = None
        self.su_user = None
        self.transport = None
        self.only_tags = None
        self.skip_tags = None
        self.VARS_CACHE = {}
        self.SETUP_CACHE = {}
        self.inventory = FakeInventory()
        self.callbacks = FakeCallBacks()

        self.VARS_CACHE['localhost'] = {}


class TestMe(unittest.TestCase):

    ########################################
    # BASIC FILE LOADING BEHAVIOR TESTS
    ########################################

    def test_play_constructor(self):
        # __init__(self, playbook, ds, basedir, vault_password=None)
        playbook = FakePlayBook()
        ds = { "hosts": "localhost"}
        basedir = "."
        play = Play(playbook, ds, basedir)

    def test_vars_file(self):

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # create a play with a vars_file
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": [temp_path]}
        basedir = "."
        play = Play(playbook, ds, basedir)
        os.remove(temp_path)

        # make sure the variable was loaded
        assert 'foo' in play.vars, "vars_file was not loaded into play.vars"
        assert play.vars['foo'] == 'bar', "foo was not set to bar in play.vars"

    def test_vars_file_nonlist_error(self):

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # create a play with a string for vars_files
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": temp_path}
        basedir = "."
        error_hit = False
        try:
            play = Play(playbook, ds, basedir)
        except:
            error_hit = True
        os.remove(temp_path)

        assert error_hit == True, "no error was thrown when vars_files was not a list"


    def test_multiple_vars_files(self):

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # make a second vars file
        fd, temp_path2 = mkstemp()
        f = open(temp_path2, "wb")
        f.write("baz: bang\n")
        f.close()


        # create a play with two vars_files
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": [temp_path, temp_path2]}
        basedir = "."
        play = Play(playbook, ds, basedir)
        os.remove(temp_path)
        os.remove(temp_path2)

        # make sure the variables were loaded
        assert 'foo' in play.vars, "vars_file was not loaded into play.vars"
        assert play.vars['foo'] == 'bar', "foo was not set to bar in play.vars"
        assert 'baz' in play.vars, "vars_file2 was not loaded into play.vars"
        assert play.vars['baz'] == 'bang', "baz was not set to bang in play.vars"

    def test_vars_files_first_found(self):

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # get a random file path        
        fd, temp_path2 = mkstemp()
        # make sure this file doesn't exist
        os.remove(temp_path2)

        # create a play
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": [[temp_path2, temp_path]]}
        basedir = "."
        play = Play(playbook, ds, basedir)
        os.remove(temp_path)

        # make sure the variable was loaded
        assert 'foo' in play.vars, "vars_file was not loaded into play.vars"
        assert play.vars['foo'] == 'bar', "foo was not set to bar in play.vars"

    def test_vars_files_multiple_found(self):

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # make a second vars file
        fd, temp_path2 = mkstemp()
        f = open(temp_path2, "wb")
        f.write("baz: bang\n")
        f.close()

        # create a play
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": [[temp_path, temp_path2]]}
        basedir = "."
        play = Play(playbook, ds, basedir)
        os.remove(temp_path)
        os.remove(temp_path2)

        # make sure the variables were loaded
        assert 'foo' in play.vars, "vars_file was not loaded into play.vars"
        assert play.vars['foo'] == 'bar', "foo was not set to bar in play.vars"
        assert 'baz' not in play.vars, "vars_file2 was loaded after vars_file1 was loaded"

    def test_vars_files_assert_all_found(self):

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # make a second vars file
        fd, temp_path2 = mkstemp()
        # make sure it doesn't exist
        os.remove(temp_path2)

        # create a play
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": [temp_path, temp_path2]}
        basedir = "."

        error_hit = False
        error_msg = None

        try:
            play = Play(playbook, ds, basedir)
        except ansible.errors.AnsibleError, e:
            error_hit = True
            error_msg = e

        os.remove(temp_path)
        assert error_hit == True, "no error was thrown for missing vars_file"


    ########################################
    # VARIABLE PRECEDENCE TESTS
    ########################################

    # On the first run vars_files are loaded into play.vars by host == None
    #   * only files with vars from host==None will work here
    # On the secondary run(s), a host is given and the vars_files are loaded into VARS_CACHE
    #   * this only occurs if host is not None, filename2 has vars in the name, and filename3 does not

    # filename  -- the original string
    # filename2 -- filename templated with play vars
    # filename3 -- filename2 template with inject (hostvars + setup_cache + vars_cache)
    # filename4 -- path_dwim(filename3)

    def test_vars_files_for_host(self):

        # host != None
        # vars in filename2
        # no vars in filename3

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # build play attributes
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": ["{{ temp_path }}"]}
        basedir = "."
        playbook.VARS_CACHE['localhost']['temp_path'] = temp_path

        # create play and do first run        
        play = Play(playbook, ds, basedir)

        # the second run is started by calling update_vars_files        
        play.update_vars_files(['localhost'])
        os.remove(temp_path)

        assert 'foo' in play.playbook.VARS_CACHE['localhost'], "vars_file vars were not loaded into vars_cache"
        assert play.playbook.VARS_CACHE['localhost']['foo'] == 'bar', "foo does not equal bar"

    def test_vars_files_for_host_with_extra_vars(self):

        # host != None
        # vars in filename2
        # no vars in filename3

        # make a vars file
        fd, temp_path = mkstemp()
        f = open(temp_path, "wb")
        f.write("foo: bar\n")
        f.close()

        # build play attributes
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars_files": ["{{ temp_path }}"]}
        basedir = "."
        playbook.VARS_CACHE['localhost']['temp_path'] = temp_path
        playbook.extra_vars = {"foo": "extra"}

        # create play and do first run        
        play = Play(playbook, ds, basedir)

        # the second run is started by calling update_vars_files        
        play.update_vars_files(['localhost'])
        os.remove(temp_path)

        assert 'foo' in play.vars, "extra vars were not set in play.vars"
        assert 'foo' in play.playbook.VARS_CACHE['localhost'], "vars_file vars were not loaded into vars_cache"
        assert play.playbook.VARS_CACHE['localhost']['foo'] == 'extra', "extra vars did not overwrite vars_files vars"


    ########################################
    # COMPLEX FILENAME TEMPLATING TESTS
    ########################################

    def test_vars_files_two_vars_in_name(self):

        # self.vars = ds['vars']
        # self.vars += _get_vars() ... aka extra_vars

        # make a temp dir
        temp_dir = mkdtemp()

        # make a temp file
        fd, temp_file = mkstemp(dir=temp_dir)
        f = open(temp_file, "wb")
        f.write("foo: bar\n")
        f.close()

        # build play attributes
        playbook = FakePlayBook()
        ds = { "hosts": "localhost",
               "vars": { "temp_dir": os.path.dirname(temp_file),
                         "temp_file": os.path.basename(temp_file) },
               "vars_files": ["{{ temp_dir + '/' + temp_file }}"]}
        basedir = "."

        # create play and do first run        
        play = Play(playbook, ds, basedir)

        # cleanup
        shutil.rmtree(temp_dir)

        assert 'foo' in play.vars, "double var templated vars_files filename not loaded"
    
    def test_vars_files_two_vars_different_scope(self):

        #
        # Use a play var and an inventory var to create the filename
        #

        # self.playbook.inventory.get_variables(host)
        #   {'group_names': ['ungrouped'], 'inventory_hostname': 'localhost', 
        #   'ansible_ssh_user': 'root', 'inventory_hostname_short': 'localhost'}

        # make a temp dir
        temp_dir = mkdtemp()

        # make a temp file
        fd, temp_file = mkstemp(dir=temp_dir)
        f = open(temp_file, "wb")
        f.write("foo: bar\n")
        f.close()

        # build play attributes
        playbook = FakePlayBook()
        playbook.inventory.hosts['localhost'] = {'inventory_hostname': os.path.basename(temp_file)}
        ds = { "hosts": "localhost",
               "vars": { "temp_dir": os.path.dirname(temp_file)},
               "vars_files": ["{{ temp_dir + '/' + inventory_hostname }}"]}
        basedir = "."

        # create play and do first run        
        play = Play(playbook, ds, basedir)

        # do the host run        
        play.update_vars_files(['localhost'])

        # cleanup
        shutil.rmtree(temp_dir)

        assert 'foo' not in play.vars, \
            "mixed scope vars_file loaded into play vars"
        assert 'foo' in play.playbook.VARS_CACHE['localhost'], \
            "differently scoped templated vars_files filename not loaded"
        assert play.playbook.VARS_CACHE['localhost']['foo'] == 'bar', \
            "foo is not bar"    

    def test_vars_files_two_vars_different_scope_first_found(self):

        #
        # Use a play var and an inventory var to create the filename
        #

        # make a temp dir
        temp_dir = mkdtemp()

        # make a temp file
        fd, temp_file = mkstemp(dir=temp_dir)
        f = open(temp_file, "wb")
        f.write("foo: bar\n")
        f.close()

        # build play attributes
        playbook = FakePlayBook()
        playbook.inventory.hosts['localhost'] = {'inventory_hostname': os.path.basename(temp_file)}
        ds = { "hosts": "localhost",
               "vars": { "temp_dir": os.path.dirname(temp_file)},
               "vars_files": [["{{ temp_dir + '/' + inventory_hostname }}"]]}
        basedir = "."

        # create play and do first run        
        play = Play(playbook, ds, basedir)

        # do the host run        
        play.update_vars_files(['localhost'])

        # cleanup
        shutil.rmtree(temp_dir)

        assert 'foo' not in play.vars, \
            "mixed scope vars_file loaded into play vars"
        assert 'foo' in play.playbook.VARS_CACHE['localhost'], \
            "differently scoped templated vars_files filename not loaded"
        assert play.playbook.VARS_CACHE['localhost']['foo'] == 'bar', \
            "foo is not bar"