Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
8a1fbed5
Commit
8a1fbed5
authored
Aug 15, 2014
by
James Cammarata
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Correct variable blending from vars_files with hostvars in them
Fixes #8638
parent
8956c636
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
69 additions
and
64 deletions
+69
-64
lib/ansible/playbook/__init__.py
+1
-0
lib/ansible/playbook/play.py
+37
-29
lib/ansible/runner/__init__.py
+7
-1
lib/ansible/utils/__init__.py
+10
-0
test/integration/roles/test_var_precedence/tasks/main.yml
+1
-0
test/integration/roles/test_var_precedence_role1/tasks/main.yml
+2
-0
test/integration/roles/test_var_precedence_role1/vars/main.yml
+2
-1
test/integration/roles/test_var_precedence_role2/tasks/main.yml
+2
-0
test/integration/roles/test_var_precedence_role2/vars/main.yml
+1
-1
test/integration/roles/test_var_precedence_role3/tasks/main.yml
+2
-0
test/integration/roles/test_var_precedence_role3/vars/main.yml
+1
-1
test/integration/test_var_precedence.yml
+2
-0
test/integration/vars/test_var_precedence.yml
+1
-0
test/units/TestPlayVarsFiles.py
+0
-31
No files found.
lib/ansible/playbook/__init__.py
View file @
8a1fbed5
...
@@ -396,6 +396,7 @@ class PlayBook(object):
...
@@ -396,6 +396,7 @@ class PlayBook(object):
remote_port
=
task
.
play
.
remote_port
,
remote_port
=
task
.
play
.
remote_port
,
module_vars
=
task
.
module_vars
,
module_vars
=
task
.
module_vars
,
default_vars
=
task
.
default_vars
,
default_vars
=
task
.
default_vars
,
extra_vars
=
self
.
extra_vars
,
private_key_file
=
self
.
private_key_file
,
private_key_file
=
self
.
private_key_file
,
setup_cache
=
self
.
SETUP_CACHE
,
setup_cache
=
self
.
SETUP_CACHE
,
vars_cache
=
self
.
VARS_CACHE
,
vars_cache
=
self
.
VARS_CACHE
,
...
...
lib/ansible/playbook/play.py
View file @
8a1fbed5
...
@@ -89,15 +89,15 @@ class Play(object):
...
@@ -89,15 +89,15 @@ class Play(object):
self
.
vars_files
=
ds
.
get
(
'vars_files'
,
[])
self
.
vars_files
=
ds
.
get
(
'vars_files'
,
[])
if
not
isinstance
(
self
.
vars_files
,
list
):
if
not
isinstance
(
self
.
vars_files
,
list
):
raise
errors
.
AnsibleError
(
'vars_files must be a list'
)
raise
errors
.
AnsibleError
(
'vars_files must be a list'
)
self
.
_update_vars_files_for_host
(
None
)
processed_vars_files
=
self
.
_update_vars_files_for_host
(
None
)
# now we load the roles into the datastructure
# now we load the roles into the datastructure
self
.
included_roles
=
[]
self
.
included_roles
=
[]
ds
=
self
.
_load_roles
(
self
.
roles
,
ds
)
ds
=
self
.
_load_roles
(
self
.
roles
,
ds
)
# and finally re-process the vars files as they may have
# and finally re-process the vars files as they may have
been updated
# b
een updated by the included roles
# b
y the included roles, but exclude any which have been processed
self
.
vars_files
=
ds
.
get
(
'vars_files'
,
[]
)
self
.
vars_files
=
utils
.
list_difference
(
ds
.
get
(
'vars_files'
,
[]),
processed_vars_files
)
if
not
isinstance
(
self
.
vars_files
,
list
):
if
not
isinstance
(
self
.
vars_files
,
list
):
raise
errors
.
AnsibleError
(
'vars_files must be a list'
)
raise
errors
.
AnsibleError
(
'vars_files must be a list'
)
...
@@ -765,27 +765,37 @@ class Play(object):
...
@@ -765,27 +765,37 @@ class Play(object):
""" Render the raw filename into 3 forms """
""" Render the raw filename into 3 forms """
# filename2 is the templated version of the filename, which will
# be fully rendered if any variables contained within it are
# non-inventory related
filename2
=
template
(
self
.
basedir
,
filename
,
self
.
vars
)
filename2
=
template
(
self
.
basedir
,
filename
,
self
.
vars
)
# filename3 is the same as filename2, but when the host object is
# available, inventory variables will be expanded as well since the
# name is templated with the injected variables
filename3
=
filename2
filename3
=
filename2
if
host
is
not
None
:
if
host
is
not
None
:
filename3
=
template
(
self
.
basedir
,
filename2
,
inject
)
filename3
=
template
(
self
.
basedir
,
filename2
,
inject
)
# filename4 is the dwim'd path, but may also be mixed-scope, so we use
# both play scoped vars and host scoped vars to template the filepath
if
self
.
_has_vars_in
(
filename3
)
and
host
is
not
None
:
if
self
.
_has_vars_in
(
filename3
)
and
host
is
not
None
:
# allow play scoped vars and host scoped vars to template the filepath
inject
.
update
(
self
.
vars
)
inject
.
update
(
self
.
vars
)
filename4
=
template
(
self
.
basedir
,
filename3
,
inject
)
filename4
=
template
(
self
.
basedir
,
filename3
,
inject
)
filename4
=
utils
.
path_dwim
(
self
.
basedir
,
filename4
)
filename4
=
utils
.
path_dwim
(
self
.
basedir
,
filename4
)
else
:
else
:
filename4
=
utils
.
path_dwim
(
self
.
basedir
,
filename3
)
filename4
=
utils
.
path_dwim
(
self
.
basedir
,
filename3
)
return
filename2
,
filename3
,
filename4
return
filename2
,
filename3
,
filename4
def
update_vars_cache
(
host
,
inject
,
data
,
filenam
e
):
def
update_vars_cache
(
host
,
data
,
target_filename
=
Non
e
):
""" update a host's varscache with new var data """
""" update a host's varscache with new var data """
data
=
utils
.
combine_vars
(
inject
,
data
)
self
.
playbook
.
VARS_CACHE
[
host
]
=
utils
.
combine_vars
(
self
.
playbook
.
VARS_CACHE
.
get
(
host
,
{}),
data
)
self
.
playbook
.
VARS_CACHE
[
host
]
=
utils
.
combine_vars
(
self
.
playbook
.
VARS_CACHE
.
get
(
host
,
{}),
data
)
self
.
playbook
.
callbacks
.
on_import_for_host
(
host
,
filename4
)
if
target_filename
:
self
.
playbook
.
callbacks
.
on_import_for_host
(
host
,
target_filename
)
def
process_files
(
filename
,
filename2
,
filename3
,
filename4
,
host
=
None
):
def
process_files
(
filename
,
filename2
,
filename3
,
filename4
,
host
=
None
):
...
@@ -796,21 +806,19 @@ class Play(object):
...
@@ -796,21 +806,19 @@ class Play(object):
if
type
(
data
)
!=
dict
:
if
type
(
data
)
!=
dict
:
raise
errors
.
AnsibleError
(
"
%
s must be stored as a dictionary/hash"
%
filename4
)
raise
errors
.
AnsibleError
(
"
%
s must be stored as a dictionary/hash"
%
filename4
)
if
host
is
not
None
:
if
host
is
not
None
:
if
self
.
_has_vars_in
(
filename2
)
and
not
self
.
_has_vars_in
(
filename3
):
target_filename
=
None
# running a host specific pass and has host specific variables
if
self
.
_has_vars_in
(
filename2
):
# load into setup cache
if
not
self
.
_has_vars_in
(
filename3
):
update_vars_cache
(
host
,
inject
,
data
,
filename4
)
target_filename
=
filename3
elif
self
.
_has_vars_in
(
filename3
)
and
not
self
.
_has_vars_in
(
filename4
):
else
:
# handle mixed scope variables in filepath
target_filename
=
filename4
update_vars_cache
(
host
,
inject
,
data
,
filename4
)
update_vars_cache
(
host
,
data
,
target_filename
=
target_filename
)
else
:
elif
not
self
.
_has_vars_in
(
filename4
):
self
.
vars
=
utils
.
combine_vars
(
self
.
vars
,
data
)
# found a non-host specific variable, load into vars and NOT
# we did process this file
# the setup cache
return
True
if
host
is
not
None
:
# we did not process this file
self
.
vars
.
update
(
data
)
return
False
else
:
self
.
vars
=
utils
.
combine_vars
(
self
.
vars
,
data
)
# Enforce that vars_files is always a list
# Enforce that vars_files is always a list
if
type
(
self
.
vars_files
)
!=
list
:
if
type
(
self
.
vars_files
)
!=
list
:
...
@@ -825,6 +833,7 @@ class Play(object):
...
@@ -825,6 +833,7 @@ class Play(object):
else
:
else
:
inject
=
None
inject
=
None
processed
=
[]
for
filename
in
self
.
vars_files
:
for
filename
in
self
.
vars_files
:
if
type
(
filename
)
==
list
:
if
type
(
filename
)
==
list
:
# loop over all filenames, loading the first one, and failing if none found
# loop over all filenames, loading the first one, and failing if none found
...
@@ -835,7 +844,8 @@ class Play(object):
...
@@ -835,7 +844,8 @@ class Play(object):
sequence
.
append
(
filename4
)
sequence
.
append
(
filename4
)
if
os
.
path
.
exists
(
filename4
):
if
os
.
path
.
exists
(
filename4
):
found
=
True
found
=
True
process_files
(
filename
,
filename2
,
filename3
,
filename4
,
host
=
host
)
if
process_files
(
filename
,
filename2
,
filename3
,
filename4
,
host
=
host
):
processed
.
append
(
filename
)
elif
host
is
not
None
:
elif
host
is
not
None
:
self
.
playbook
.
callbacks
.
on_not_import_for_host
(
host
,
filename4
)
self
.
playbook
.
callbacks
.
on_not_import_for_host
(
host
,
filename4
)
if
found
:
if
found
:
...
@@ -844,14 +854,12 @@ class Play(object):
...
@@ -844,14 +854,12 @@ class Play(object):
raise
errors
.
AnsibleError
(
raise
errors
.
AnsibleError
(
"
%
s: FATAL, no files matched for vars_files import sequence:
%
s"
%
(
host
,
sequence
)
"
%
s: FATAL, no files matched for vars_files import sequence:
%
s"
%
(
host
,
sequence
)
)
)
else
:
else
:
# just one filename supplied, load it!
# just one filename supplied, load it!
filename2
,
filename3
,
filename4
=
generate_filenames
(
host
,
inject
,
filename
)
filename2
,
filename3
,
filename4
=
generate_filenames
(
host
,
inject
,
filename
)
if
self
.
_has_vars_in
(
filename4
):
if
self
.
_has_vars_in
(
filename4
):
continue
continue
process_files
(
filename
,
filename2
,
filename3
,
filename4
,
host
=
host
)
if
process_files
(
filename
,
filename2
,
filename3
,
filename4
,
host
=
host
):
processed
.
append
(
filename
)
# finally, update the VARS_CACHE for the host, if it is set
return
processed
if
host
is
not
None
:
self
.
playbook
.
VARS_CACHE
.
setdefault
(
host
,
{})
.
update
(
self
.
playbook
.
extra_vars
)
lib/ansible/runner/__init__.py
View file @
8a1fbed5
...
@@ -130,6 +130,7 @@ class Runner(object):
...
@@ -130,6 +130,7 @@ class Runner(object):
sudo_user
=
C
.
DEFAULT_SUDO_USER
,
# ex: 'root'
sudo_user
=
C
.
DEFAULT_SUDO_USER
,
# ex: 'root'
module_vars
=
None
,
# a playbooks internals thing
module_vars
=
None
,
# a playbooks internals thing
default_vars
=
None
,
# ditto
default_vars
=
None
,
# ditto
extra_vars
=
None
,
# extra vars specified with he playbook(s)
is_playbook
=
False
,
# running from playbook or not?
is_playbook
=
False
,
# running from playbook or not?
inventory
=
None
,
# reference to Inventory object
inventory
=
None
,
# reference to Inventory object
subset
=
None
,
# subset pattern
subset
=
None
,
# subset pattern
...
@@ -170,6 +171,8 @@ class Runner(object):
...
@@ -170,6 +171,8 @@ class Runner(object):
self
.
module_vars
=
utils
.
default
(
module_vars
,
lambda
:
{})
self
.
module_vars
=
utils
.
default
(
module_vars
,
lambda
:
{})
self
.
default_vars
=
utils
.
default
(
default_vars
,
lambda
:
{})
self
.
default_vars
=
utils
.
default
(
default_vars
,
lambda
:
{})
self
.
extra_vars
=
utils
.
default
(
extra_vars
,
lambda
:
{})
self
.
always_run
=
None
self
.
always_run
=
None
self
.
connector
=
connection
.
Connector
(
self
)
self
.
connector
=
connection
.
Connector
(
self
)
self
.
conditional
=
conditional
self
.
conditional
=
conditional
...
@@ -605,10 +608,13 @@ class Runner(object):
...
@@ -605,10 +608,13 @@ class Runner(object):
module_vars
=
template
.
template
(
self
.
basedir
,
self
.
module_vars
,
module_vars_inject
)
module_vars
=
template
.
template
(
self
.
basedir
,
self
.
module_vars
,
module_vars_inject
)
inject
=
{}
inject
=
{}
inject
=
utils
.
combine_vars
(
inject
,
self
.
default_vars
)
inject
=
utils
.
combine_vars
(
inject
,
self
.
default_vars
)
inject
=
utils
.
combine_vars
(
inject
,
host_variables
)
inject
=
utils
.
combine_vars
(
inject
,
host_variables
)
inject
=
utils
.
combine_vars
(
inject
,
self
.
setup_cache
.
get
(
host
,
{}))
inject
=
utils
.
combine_vars
(
inject
,
module_vars
)
inject
=
utils
.
combine_vars
(
inject
,
module_vars
)
inject
=
utils
.
combine_vars
(
inject
,
combined_cache
.
get
(
host
,
{}))
inject
=
utils
.
combine_vars
(
inject
,
self
.
vars_cache
.
get
(
host
,
{}))
inject
=
utils
.
combine_vars
(
inject
,
self
.
extra_vars
)
inject
.
setdefault
(
'ansible_ssh_user'
,
self
.
remote_user
)
inject
.
setdefault
(
'ansible_ssh_user'
,
self
.
remote_user
)
inject
[
'hostvars'
]
=
hostvars
inject
[
'hostvars'
]
=
hostvars
inject
[
'group_names'
]
=
host_variables
.
get
(
'group_names'
,
[])
inject
[
'group_names'
]
=
host_variables
.
get
(
'group_names'
,
[])
...
...
lib/ansible/utils/__init__.py
View file @
8a1fbed5
...
@@ -1163,6 +1163,16 @@ def list_intersection(a, b):
...
@@ -1163,6 +1163,16 @@ def list_intersection(a, b):
result
.
append
(
x
)
result
.
append
(
x
)
return
result
return
result
def
list_difference
(
a
,
b
):
result
=
[]
for
x
in
a
:
if
x
not
in
b
and
x
not
in
result
:
result
.
append
(
x
)
for
x
in
b
:
if
x
not
in
a
and
x
not
in
result
:
result
.
append
(
x
)
return
result
def
safe_eval
(
expr
,
locals
=
{},
include_exceptions
=
False
):
def
safe_eval
(
expr
,
locals
=
{},
include_exceptions
=
False
):
'''
'''
This is intended for allowing things like:
This is intended for allowing things like:
...
...
test/integration/roles/test_var_precedence/tasks/main.yml
View file @
8a1fbed5
...
@@ -3,3 +3,4 @@
...
@@ -3,3 +3,4 @@
-
'
extra_var
==
"extra_var"'
-
'
extra_var
==
"extra_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var_role
==
"vars_files_var_role3"'
test/integration/roles/test_var_precedence_role1/tasks/main.yml
View file @
8a1fbed5
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
-
debug
:
var=param_var
-
debug
:
var=param_var
-
debug
:
var=vars_var
-
debug
:
var=vars_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var_role
-
debug
:
var=defaults_file_var_role1
-
debug
:
var=defaults_file_var_role1
-
assert
:
-
assert
:
that
:
that
:
...
@@ -9,4 +10,5 @@
...
@@ -9,4 +10,5 @@
-
'
param_var
==
"param_var_role1"'
-
'
param_var
==
"param_var_role1"'
-
'
vars_var
==
"vars_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var_role
==
"vars_files_var_role3"'
-
'
defaults_file_var_role1
==
"defaults_file_var_role1"'
-
'
defaults_file_var_role1
==
"defaults_file_var_role1"'
test/integration/roles/test_var_precedence_role1/vars/main.yml
View file @
8a1fbed5
---
---
# should override the global vars_files_var since it's local to the role
# should override the global vars_files_var since it's local to the role
vars_files_var
:
"
vars_files_var_role1"
# but will be set to the value in the last role included which defines it
vars_files_var_role
:
"
vars_files_var_role1"
test/integration/roles/test_var_precedence_role2/tasks/main.yml
View file @
8a1fbed5
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
-
debug
:
var=param_var
-
debug
:
var=param_var
-
debug
:
var=vars_var
-
debug
:
var=vars_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var_role
-
debug
:
var=defaults_file_var_role1
-
debug
:
var=defaults_file_var_role1
-
assert
:
-
assert
:
that
:
that
:
...
@@ -9,4 +10,5 @@
...
@@ -9,4 +10,5 @@
-
'
param_var
==
"param_var_role2"'
-
'
param_var
==
"param_var_role2"'
-
'
vars_var
==
"vars_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var_role
==
"vars_files_var_role3"'
-
'
defaults_file_var_role2
==
"overridden
by
role
vars"'
-
'
defaults_file_var_role2
==
"overridden
by
role
vars"'
test/integration/roles/test_var_precedence_role2/vars/main.yml
View file @
8a1fbed5
---
---
# should override the global vars_files_var since it's local to the role
# should override the global vars_files_var since it's local to the role
vars_files_var
:
"
vars_files_var_role1
"
vars_files_var
_role
:
"
vars_files_var_role2
"
# should override the value in defaults/main.yml for role 2
# should override the value in defaults/main.yml for role 2
defaults_file_var_role2
:
"
overridden
by
role
vars"
defaults_file_var_role2
:
"
overridden
by
role
vars"
test/integration/roles/test_var_precedence_role3/tasks/main.yml
View file @
8a1fbed5
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
-
debug
:
var=param_var
-
debug
:
var=param_var
-
debug
:
var=vars_var
-
debug
:
var=vars_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var_role
-
debug
:
var=defaults_file_var_role1
-
debug
:
var=defaults_file_var_role1
-
assert
:
-
assert
:
that
:
that
:
...
@@ -9,4 +10,5 @@
...
@@ -9,4 +10,5 @@
-
'
param_var
==
"param_var_role3"'
-
'
param_var
==
"param_var_role3"'
-
'
vars_var
==
"vars_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var_role
==
"vars_files_var_role3"'
-
'
defaults_file_var_role3
==
"overridden
from
inventory"'
-
'
defaults_file_var_role3
==
"overridden
from
inventory"'
test/integration/roles/test_var_precedence_role3/vars/main.yml
View file @
8a1fbed5
---
---
# should override the global vars_files_var since it's local to the role
# should override the global vars_files_var since it's local to the role
vars_files_var
:
"
vars_files_var_role1
"
vars_files_var
_role
:
"
vars_files_var_role3
"
test/integration/test_var_precedence.yml
View file @
8a1fbed5
...
@@ -12,8 +12,10 @@
...
@@ -12,8 +12,10 @@
-
debug
:
var=extra_var
-
debug
:
var=extra_var
-
debug
:
var=vars_var
-
debug
:
var=vars_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var
-
debug
:
var=vars_files_var_role
-
assert
:
-
assert
:
that
:
that
:
-
'
extra_var
==
"extra_var"'
-
'
extra_var
==
"extra_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_var
==
"vars_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var
==
"vars_files_var"'
-
'
vars_files_var_role
==
"vars_files_var_role3"'
test/integration/vars/test_var_precedence.yml
View file @
8a1fbed5
...
@@ -2,3 +2,4 @@
...
@@ -2,3 +2,4 @@
extra_var
:
"
BAD!"
extra_var
:
"
BAD!"
role_var
:
"
BAD!"
role_var
:
"
BAD!"
vars_files_var
:
"
vars_files_var"
vars_files_var
:
"
vars_files_var"
vars_files_var_role
:
"
should
be
overridden
by
roles"
test/units/TestPlayVarsFiles.py
View file @
8a1fbed5
...
@@ -266,37 +266,6 @@ class TestMe(unittest.TestCase):
...
@@ -266,37 +266,6 @@ class TestMe(unittest.TestCase):
assert
'foo'
in
play
.
playbook
.
VARS_CACHE
[
'localhost'
],
"vars_file vars were not loaded into vars_cache"
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"
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
# COMPLEX FILENAME TEMPLATING TESTS
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment