Remove deprecated features from ansible.playbook.helpers (#74809)
* Remove deprecated features from ansible.playbook.helpers. Fixes #74135
This commit is contained in:
parent
27f61db86b
commit
d27ce4cef3
10 changed files with 43 additions and 140 deletions
|
@ -0,0 +1,3 @@
|
||||||
|
bugfixes:
|
||||||
|
- include - Remove deprecated ``static`` argument for ``include``
|
||||||
|
(https://github.com/ansible/ansible/issues/74135)
|
|
@ -697,19 +697,6 @@ DEFAULT_GATHER_TIMEOUT:
|
||||||
- {key: gather_timeout, section: defaults}
|
- {key: gather_timeout, section: defaults}
|
||||||
type: integer
|
type: integer
|
||||||
yaml: {key: defaults.gather_timeout}
|
yaml: {key: defaults.gather_timeout}
|
||||||
DEFAULT_HANDLER_INCLUDES_STATIC:
|
|
||||||
name: Make handler M(ansible.builtin.include) static
|
|
||||||
default: False
|
|
||||||
description:
|
|
||||||
- "Since 2.0 M(ansible.builtin.include) can be 'dynamic', this setting (if True) forces that if the include appears in a ``handlers`` section to be 'static'."
|
|
||||||
env: [{name: ANSIBLE_HANDLER_INCLUDES_STATIC}]
|
|
||||||
ini:
|
|
||||||
- {key: handler_includes_static, section: defaults}
|
|
||||||
type: boolean
|
|
||||||
deprecated:
|
|
||||||
why: include itself is deprecated and this setting will not matter in the future
|
|
||||||
version: "2.12"
|
|
||||||
alternatives: none as its already built into the decision between include_tasks and import_tasks
|
|
||||||
DEFAULT_HASH_BEHAVIOUR:
|
DEFAULT_HASH_BEHAVIOUR:
|
||||||
name: Hash merge behaviour
|
name: Hash merge behaviour
|
||||||
default: replace
|
default: replace
|
||||||
|
@ -1095,20 +1082,6 @@ DEFAULT_SYSLOG_FACILITY:
|
||||||
env: [{name: ANSIBLE_SYSLOG_FACILITY}]
|
env: [{name: ANSIBLE_SYSLOG_FACILITY}]
|
||||||
ini:
|
ini:
|
||||||
- {key: syslog_facility, section: defaults}
|
- {key: syslog_facility, section: defaults}
|
||||||
DEFAULT_TASK_INCLUDES_STATIC:
|
|
||||||
name: Task include static
|
|
||||||
default: False
|
|
||||||
description:
|
|
||||||
- The `include` tasks can be static or dynamic, this toggles the default expected behaviour if autodetection fails and it is not explicitly set in task.
|
|
||||||
env: [{name: ANSIBLE_TASK_INCLUDES_STATIC}]
|
|
||||||
ini:
|
|
||||||
- {key: task_includes_static, section: defaults}
|
|
||||||
type: boolean
|
|
||||||
version_added: "2.1"
|
|
||||||
deprecated:
|
|
||||||
why: include itself is deprecated and this setting will not matter in the future
|
|
||||||
version: "2.12"
|
|
||||||
alternatives: None, as its already built into the decision between include_tasks and import_tasks
|
|
||||||
DEFAULT_TERMINAL_PLUGIN_PATH:
|
DEFAULT_TERMINAL_PLUGIN_PATH:
|
||||||
name: Terminal Plugins Path
|
name: Terminal Plugins Path
|
||||||
default: ~/.ansible/plugins/terminal:/usr/share/ansible/plugins/terminal
|
default: ~/.ansible/plugins/terminal:/usr/share/ansible/plugins/terminal
|
||||||
|
|
|
@ -154,15 +154,9 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
is_static = False
|
is_static = False
|
||||||
elif action in C._ACTION_IMPORT_TASKS:
|
elif action in C._ACTION_IMPORT_TASKS:
|
||||||
is_static = True
|
is_static = True
|
||||||
elif t.static is not None:
|
|
||||||
display.deprecated("The use of 'static' has been deprecated. "
|
|
||||||
"Use 'import_tasks' for static inclusion, or 'include_tasks' for dynamic inclusion",
|
|
||||||
version='2.12', collection_name='ansible.builtin')
|
|
||||||
is_static = t.static
|
|
||||||
else:
|
else:
|
||||||
is_static = C.DEFAULT_TASK_INCLUDES_STATIC or \
|
display.deprecated('"include" is deprecated, use include_tasks/import_tasks instead', "2.16")
|
||||||
(use_handlers and C.DEFAULT_HANDLER_INCLUDES_STATIC) or \
|
is_static = not templar.is_template(t.args['_raw_params']) and t.all_parents_static() and not t.loop
|
||||||
(not templar.is_template(t.args['_raw_params']) and t.all_parents_static() and not t.loop)
|
|
||||||
|
|
||||||
if is_static:
|
if is_static:
|
||||||
if t.loop is not None:
|
if t.loop is not None:
|
||||||
|
@ -234,35 +228,18 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
else:
|
else:
|
||||||
include_file = loader.path_dwim(include_target)
|
include_file = loader.path_dwim(include_target)
|
||||||
|
|
||||||
try:
|
data = loader.load_from_file(include_file)
|
||||||
data = loader.load_from_file(include_file)
|
if not data:
|
||||||
if not data:
|
display.warning('file %s is empty and had no tasks to include' % include_file)
|
||||||
display.warning('file %s is empty and had no tasks to include' % include_file)
|
|
||||||
continue
|
|
||||||
elif not isinstance(data, list):
|
|
||||||
raise AnsibleParserError("included task files must contain a list of tasks", obj=data)
|
|
||||||
|
|
||||||
# since we can't send callbacks here, we display a message directly in
|
|
||||||
# the same fashion used by the on_include callback. We also do it here,
|
|
||||||
# because the recursive nature of helper methods means we may be loading
|
|
||||||
# nested includes, and we want the include order printed correctly
|
|
||||||
display.vv("statically imported: %s" % include_file)
|
|
||||||
except AnsibleFileNotFound:
|
|
||||||
if action not in C._ACTION_INCLUDE or t.static or \
|
|
||||||
C.DEFAULT_TASK_INCLUDES_STATIC or \
|
|
||||||
C.DEFAULT_HANDLER_INCLUDES_STATIC and use_handlers:
|
|
||||||
raise
|
|
||||||
display.deprecated(
|
|
||||||
"Included file '%s' not found, however since this include is not "
|
|
||||||
"explicitly marked as 'static: yes', we will try and include it dynamically "
|
|
||||||
"later. In the future, this will be an error unless 'static: no' is used "
|
|
||||||
"on the include task. If you do not want missing includes to be considered "
|
|
||||||
"dynamic, use 'static: yes' on the include or set the global ansible.cfg "
|
|
||||||
"options to make all includes static for tasks and/or handlers" % include_file,
|
|
||||||
version="2.12", collection_name='ansible.builtin'
|
|
||||||
)
|
|
||||||
task_list.append(t)
|
|
||||||
continue
|
continue
|
||||||
|
elif not isinstance(data, list):
|
||||||
|
raise AnsibleParserError("included task files must contain a list of tasks", obj=data)
|
||||||
|
|
||||||
|
# since we can't send callbacks here, we display a message directly in
|
||||||
|
# the same fashion used by the on_include callback. We also do it here,
|
||||||
|
# because the recursive nature of helper methods means we may be loading
|
||||||
|
# nested includes, and we want the include order printed correctly
|
||||||
|
display.vv("statically imported: %s" % include_file)
|
||||||
|
|
||||||
ti_copy = t.copy(exclude_parent=True)
|
ti_copy = t.copy(exclude_parent=True)
|
||||||
ti_copy._parent = block
|
ti_copy._parent = block
|
||||||
|
@ -277,28 +254,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
variable_manager=variable_manager,
|
variable_manager=variable_manager,
|
||||||
)
|
)
|
||||||
|
|
||||||
# FIXME: remove once 'include' is removed
|
tags = ti_copy.tags[:]
|
||||||
# pop tags out of the include args, if they were specified there, and assign
|
|
||||||
# them to the include. If the include already had tags specified, we raise an
|
|
||||||
# error so that users know not to specify them both ways
|
|
||||||
tags = ti_copy.vars.pop('tags', [])
|
|
||||||
if isinstance(tags, string_types):
|
|
||||||
tags = tags.split(',')
|
|
||||||
|
|
||||||
if len(tags) > 0:
|
|
||||||
if action in C._ACTION_ALL_PROPER_INCLUDE_IMPORT_TASKS:
|
|
||||||
raise AnsibleParserError('You cannot specify "tags" inline to the task, it is a task keyword')
|
|
||||||
if len(ti_copy.tags) > 0:
|
|
||||||
raise AnsibleParserError(
|
|
||||||
"Include tasks should not specify tags in more than one way (both via args and directly on the task). "
|
|
||||||
"Mixing styles in which tags are specified is prohibited for whole import hierarchy, not only for single import statement",
|
|
||||||
obj=task_ds,
|
|
||||||
suppress_extended_error=True,
|
|
||||||
)
|
|
||||||
display.deprecated("You should not specify tags in the include parameters. All tags should be specified using the task-level option",
|
|
||||||
version="2.12", collection_name='ansible.builtin')
|
|
||||||
else:
|
|
||||||
tags = ti_copy.tags[:]
|
|
||||||
|
|
||||||
# now we extend the tags on each of the included blocks
|
# now we extend the tags on each of the included blocks
|
||||||
for b in included_blocks:
|
for b in included_blocks:
|
||||||
|
@ -332,12 +288,6 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
if action in C._ACTION_IMPORT_ROLE:
|
if action in C._ACTION_IMPORT_ROLE:
|
||||||
is_static = True
|
is_static = True
|
||||||
|
|
||||||
elif ir.static is not None:
|
|
||||||
display.deprecated("The use of 'static' for 'include_role' has been deprecated. "
|
|
||||||
"Use 'import_role' for static inclusion, or 'include_role' for dynamic inclusion",
|
|
||||||
version='2.12', collection_name='ansible.builtin')
|
|
||||||
is_static = ir.static
|
|
||||||
|
|
||||||
if is_static:
|
if is_static:
|
||||||
if ir.loop is not None:
|
if ir.loop is not None:
|
||||||
if action in C._ACTION_IMPORT_ROLE:
|
if action in C._ACTION_IMPORT_ROLE:
|
||||||
|
|
|
@ -118,8 +118,6 @@ class IncludedFile:
|
||||||
|
|
||||||
if original_task.action in C._ACTION_ALL_INCLUDE_TASKS:
|
if original_task.action in C._ACTION_ALL_INCLUDE_TASKS:
|
||||||
include_file = None
|
include_file = None
|
||||||
if original_task.static:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if original_task._parent:
|
if original_task._parent:
|
||||||
# handle relative includes by walking up the list of parent include
|
# handle relative includes by walking up the list of parent include
|
||||||
|
|
|
@ -46,11 +46,6 @@ class TaskInclude(Task):
|
||||||
'loop_with', 'name', 'no_log', 'register', 'run_once', 'tags', 'timeout', 'vars',
|
'loop_with', 'name', 'no_log', 'register', 'run_once', 'tags', 'timeout', 'vars',
|
||||||
'when'))
|
'when'))
|
||||||
|
|
||||||
# =================================================================================
|
|
||||||
# ATTRIBUTES
|
|
||||||
|
|
||||||
_static = FieldAttribute(isa='bool', default=None)
|
|
||||||
|
|
||||||
def __init__(self, block=None, role=None, task_include=None):
|
def __init__(self, block=None, role=None, task_include=None):
|
||||||
super(TaskInclude, self).__init__(block=block, role=role, task_include=task_include)
|
super(TaskInclude, self).__init__(block=block, role=role, task_include=task_include)
|
||||||
self.statically_loaded = False
|
self.statically_loaded = False
|
||||||
|
|
|
@ -26,8 +26,7 @@
|
||||||
- "_include_role_result is failed"
|
- "_include_role_result is failed"
|
||||||
msg: "'include_role' did not evaluate it's attached condition and failed"
|
msg: "'include_role' did not evaluate it's attached condition and failed"
|
||||||
|
|
||||||
- include: include_that_defines_var.yml
|
- import_tasks: include_that_defines_var.yml
|
||||||
static: yes
|
|
||||||
when:
|
when:
|
||||||
- "_undefined == 'yes'"
|
- "_undefined == 'yes'"
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
# 'canary2' used instead of 'canary', otherwise a "recursive loop detected in
|
# 'canary2' used instead of 'canary', otherwise a "recursive loop detected in
|
||||||
# template string" occurs when both includes use static=yes
|
# template string" occurs when both includes use static=yes
|
||||||
- include: 'leaf_sublevel.yml canary2={{ canary }}'
|
- import_tasks: leaf_sublevel.yml
|
||||||
static: yes
|
vars:
|
||||||
|
canary2: '{{ canary }}'
|
||||||
when: 'nested_include_static|bool' # value for 'static' can not be a variable, hence use 'when'
|
when: 'nested_include_static|bool' # value for 'static' can not be a variable, hence use 'when'
|
||||||
|
|
||||||
- include: 'leaf_sublevel.yml canary2={{ canary }}'
|
- include_tasks: leaf_sublevel.yml
|
||||||
static: no
|
vars:
|
||||||
|
canary2: '{{ canary }}'
|
||||||
when: 'not nested_include_static|bool'
|
when: 'not nested_include_static|bool'
|
||||||
|
|
|
@ -81,26 +81,34 @@
|
||||||
- included_handler
|
- included_handler
|
||||||
- verify_handler
|
- verify_handler
|
||||||
|
|
||||||
- include: branch_toplevel.yml canary=value1 nested_include_static=no
|
- include_tasks: branch_toplevel.yml
|
||||||
static: no
|
vars:
|
||||||
|
canary: value1
|
||||||
|
nested_include_static: 'no'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- 'canary_fact == "value1"'
|
- 'canary_fact == "value1"'
|
||||||
|
|
||||||
- include: branch_toplevel.yml canary=value2 nested_include_static=yes
|
- include_tasks: branch_toplevel.yml
|
||||||
static: no
|
vars:
|
||||||
|
canary: value2
|
||||||
|
nested_include_static: 'yes'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- 'canary_fact == "value2"'
|
- 'canary_fact == "value2"'
|
||||||
|
|
||||||
- include: branch_toplevel.yml canary=value3 nested_include_static=no
|
- import_tasks: branch_toplevel.yml
|
||||||
static: yes
|
vars:
|
||||||
|
canary: value3
|
||||||
|
nested_include_static: 'no'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- 'canary_fact == "value3"'
|
- 'canary_fact == "value3"'
|
||||||
|
|
||||||
- include: branch_toplevel.yml canary=value4 nested_include_static=yes
|
- import_tasks: branch_toplevel.yml
|
||||||
static: yes
|
vars:
|
||||||
|
canary: value4
|
||||||
|
nested_include_static: 'yes'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- 'canary_fact == "value4"'
|
- 'canary_fact == "value4"'
|
||||||
|
|
|
@ -114,7 +114,6 @@ lib/ansible/modules/yum_repository.py validate-modules:undocumented-parameter
|
||||||
lib/ansible/parsing/vault/__init__.py pylint:blacklisted-name
|
lib/ansible/parsing/vault/__init__.py pylint:blacklisted-name
|
||||||
lib/ansible/playbook/base.py pylint:blacklisted-name
|
lib/ansible/playbook/base.py pylint:blacklisted-name
|
||||||
lib/ansible/playbook/collectionsearch.py required-and-default-attributes # https://github.com/ansible/ansible/issues/61460
|
lib/ansible/playbook/collectionsearch.py required-and-default-attributes # https://github.com/ansible/ansible/issues/61460
|
||||||
lib/ansible/playbook/helpers.py pylint:ansible-deprecated-version
|
|
||||||
lib/ansible/playbook/helpers.py pylint:blacklisted-name
|
lib/ansible/playbook/helpers.py pylint:blacklisted-name
|
||||||
lib/ansible/plugins/action/__init__.py pylint:ansible-deprecated-version
|
lib/ansible/plugins/action/__init__.py pylint:ansible-deprecated-version
|
||||||
lib/ansible/plugins/action/async_status.py pylint:ansible-deprecated-version
|
lib/ansible/plugins/action/async_status.py pylint:ansible-deprecated-version
|
||||||
|
|
|
@ -193,8 +193,7 @@ class TestLoadListOfTasks(unittest.TestCase, MixinForMocks):
|
||||||
self.assertEqual(len(res), 0)
|
self.assertEqual(len(res), 0)
|
||||||
|
|
||||||
def test_one_bogus_include_static(self):
|
def test_one_bogus_include_static(self):
|
||||||
ds = [{'include': 'somefile.yml',
|
ds = [{'import_tasks': 'somefile.yml'}]
|
||||||
'static': 'true'}]
|
|
||||||
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
||||||
variable_manager=self.mock_variable_manager, loader=self.fake_loader)
|
variable_manager=self.mock_variable_manager, loader=self.fake_loader)
|
||||||
self.assertIsInstance(res, list)
|
self.assertIsInstance(res, list)
|
||||||
|
@ -241,28 +240,6 @@ class TestLoadListOfTasks(unittest.TestCase, MixinForMocks):
|
||||||
self.assertIn('test_one_parent_include_tags_tag1', res[0].tags)
|
self.assertIn('test_one_parent_include_tags_tag1', res[0].tags)
|
||||||
self.assertIn('and_another_tag2', res[0].tags)
|
self.assertIn('and_another_tag2', res[0].tags)
|
||||||
|
|
||||||
# It would be useful to be able to tell what kind of deprecation we encountered and where we encountered it.
|
|
||||||
def test_one_include_tags_deprecated_mixed(self):
|
|
||||||
ds = [{'include': "/dev/null/includes/other_test_include.yml",
|
|
||||||
'vars': {'tags': "['tag_on_include1', 'tag_on_include2']"},
|
|
||||||
'tags': 'mixed_tag1, mixed_tag2'
|
|
||||||
}]
|
|
||||||
self.assertRaisesRegexp(errors.AnsibleParserError, 'Mixing styles',
|
|
||||||
helpers.load_list_of_tasks,
|
|
||||||
ds, play=self.mock_play,
|
|
||||||
variable_manager=self.mock_variable_manager, loader=self.fake_include_loader)
|
|
||||||
|
|
||||||
def test_one_include_tags_deprecated_include(self):
|
|
||||||
ds = [{'include': '/dev/null/includes/other_test_include.yml',
|
|
||||||
'vars': {'tags': ['include_tag1_deprecated', 'and_another_tagB_deprecated']}
|
|
||||||
}]
|
|
||||||
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
|
||||||
variable_manager=self.mock_variable_manager, loader=self.fake_include_loader)
|
|
||||||
self._assert_is_task_list_or_blocks(res)
|
|
||||||
self.assertIsInstance(res[0], Block)
|
|
||||||
self.assertIn('include_tag1_deprecated', res[0].tags)
|
|
||||||
self.assertIn('and_another_tagB_deprecated', res[0].tags)
|
|
||||||
|
|
||||||
def test_one_include_use_handlers(self):
|
def test_one_include_use_handlers(self):
|
||||||
ds = [{'include': '/dev/null/includes/other_test_include.yml'}]
|
ds = [{'include': '/dev/null/includes/other_test_include.yml'}]
|
||||||
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
||||||
|
@ -286,11 +263,10 @@ class TestLoadListOfTasks(unittest.TestCase, MixinForMocks):
|
||||||
# figure out how to get the non-static errors to be raised, this seems to just ignore everything
|
# figure out how to get the non-static errors to be raised, this seems to just ignore everything
|
||||||
def test_one_include_not_static(self):
|
def test_one_include_not_static(self):
|
||||||
ds = [{
|
ds = [{
|
||||||
'include': '/dev/null/includes/static_test_include.yml',
|
'include_tasks': '/dev/null/includes/static_test_include.yml',
|
||||||
'static': False
|
|
||||||
}]
|
}]
|
||||||
# a_block = Block()
|
# a_block = Block()
|
||||||
ti_ds = {'include': '/dev/null/includes/ssdftatic_test_include.yml'}
|
ti_ds = {'include_tasks': '/dev/null/includes/ssdftatic_test_include.yml'}
|
||||||
a_task_include = TaskInclude()
|
a_task_include = TaskInclude()
|
||||||
ti = a_task_include.load(ti_ds)
|
ti = a_task_include.load(ti_ds)
|
||||||
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
res = helpers.load_list_of_tasks(ds, play=self.mock_play,
|
||||||
|
|
Loading…
Reference in a new issue