Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't forget plugin deprecations after CLI init #73240

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/73240-dont-forget-later-deprecations.yml
@@ -0,0 +1,2 @@
bugfixes:
- "Deprecations for plugins that are loaded after CLI init, like lookup plugins, are now reported (https://github.com/ansible/ansible/issues/73051, https://github.com/ansible/ansible/pull/73240)."
15 changes: 4 additions & 11 deletions lib/ansible/cli/__init__.py
Expand Up @@ -58,6 +58,7 @@
from ansible.release import __version__
from ansible.utils.collection_loader import AnsibleCollectionConfig
from ansible.utils.collection_loader._collection_finder import _get_collection_name_from_path
from ansible.utils.deprecation import show_deprecation
from ansible.utils.path import unfrackpath
from ansible.utils.unsafe_proxy import to_unsafe_text
from ansible.vars.manager import VariableManager
Expand Down Expand Up @@ -116,17 +117,9 @@ def run(self):

# warn about deprecated config options
for deprecated in C.config.DEPRECATED:
name = deprecated[0]
why = deprecated[1]['why']
if 'alternatives' in deprecated[1]:
alt = ', use %s instead' % deprecated[1]['alternatives']
else:
alt = ''
ver = deprecated[1].get('version')
date = deprecated[1].get('date')
collection_name = deprecated[1].get('collection_name')
display.deprecated("%s option, %s%s" % (name, why, alt),
version=ver, date=date, collection_name=collection_name)
show_deprecation(display, deprecated[0], deprecated[1])

C.config.stop_collecting_deprecations(display)

@staticmethod
def split_vault_id(vault_id):
Expand Down
21 changes: 18 additions & 3 deletions lib/ansible/config/manager.py
Expand Up @@ -24,6 +24,7 @@
from ansible.parsing.quoting import unquote
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
from ansible.utils import py3compat
from ansible.utils.deprecation import show_deprecation
from ansible.utils.path import cleanup_tmp_file, makedirs_safe, unfrackpath


Expand Down Expand Up @@ -283,6 +284,8 @@ def __init__(self, conf_file=None, defs_file=None):
self._base_defs = {}
self._plugins = {}
self._parsers = {}
self._directly_show_deprecation = False
self._directly_show_deprecation_display = None

self._config_file = conf_file
self.data = ConfigData()
Expand Down Expand Up @@ -391,6 +394,18 @@ def get_configuration_definitions(self, plugin_type=None, name=None, ignore_priv

return ret

def stop_collecting_deprecations(self, display):
''' stop to collect deprecations in self.DEPRECATED, print them instead '''
self._directly_show_deprecation = True
self._directly_show_deprecation_display = display

def _add_deprecation(self, name, deprecation):
''' add deprecation '''
if self._directly_show_deprecation:
show_deprecation(self._directly_show_deprecation_display, name, deprecation)
else:
self.DEPRECATED.append((name, deprecation))

def _loop_entries(self, container, entry_list):
''' repeat code for value entry assignment '''

Expand All @@ -413,7 +428,7 @@ def _loop_entries(self, container, entry_list):

# deal with deprecation of setting source, if used
if 'deprecated' in entry:
self.DEPRECATED.append((entry['name'], entry['deprecated']))
self._add_deprecation(entry['name'], entry['deprecated'])

return value, origin

Expand Down Expand Up @@ -504,7 +519,7 @@ def get_config_value_and_origin(self, config, cfile=None, plugin_type=None, plug
value = temp_value
origin = cfile
if 'deprecated' in ini_entry:
self.DEPRECATED.append(('[%s]%s' % (ini_entry['section'], ini_entry['key']), ini_entry['deprecated']))
self._add_deprecation('[%s]%s' % (ini_entry['section'], ini_entry['key']), ini_entry['deprecated'])
except Exception as e:
sys.stderr.write("Error while loading ini config %s: %s" % (cfile, to_native(e)))
elif ftype == 'yaml':
Expand Down Expand Up @@ -552,7 +567,7 @@ def get_config_value_and_origin(self, config, cfile=None, plugin_type=None, plug

# deal with deprecation of the setting
if 'deprecated' in defs[config] and origin != 'default':
self.DEPRECATED.append((config, defs[config].get('deprecated')))
self._add_deprecation(config, defs[config].get('deprecated'))
else:
raise AnsibleError('Requested entry (%s) was not defined in configuration.' % to_native(_get_entry(plugin_type, plugin_name, config)))

Expand Down
32 changes: 32 additions & 0 deletions lib/ansible/utils/deprecation.py
@@ -0,0 +1,32 @@
# (c) 2020, Ansible Project
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type


def show_deprecation(display, name, deprecation):
why = deprecation['why']
if 'alternatives' in deprecation:
alt = ', use %s instead' % deprecation['alternatives']
else:
alt = ''
ver = deprecation.get('version')
date = deprecation.get('date')
collection_name = deprecation.get('collection_name')
display.deprecated("%s option, %s%s" % (name, why, alt),
version=ver, date=date, collection_name=collection_name)
2 changes: 2 additions & 0 deletions test/integration/targets/config_manager/aliases
@@ -0,0 +1,2 @@
shippable/posix/group1
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
context/controller
2 changes: 2 additions & 0 deletions test/integration/targets/config_manager/ansible.cfg
@@ -0,0 +1,2 @@
[default]
lookup_plugins=lookup_plugins
@@ -0,0 +1,3 @@
namespace: foo_ns
name: bar
version: 0.0.1
@@ -0,0 +1,37 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = '''
lookup: lookup_2
author: Felix Fontein
short_description: Test lookup
description:
- Nothing.
options:
deprecated_option:
description: Deprecated
type: str
deprecated:
why: this option should not be used
version: 1.0.0
alternatives: no option instead
'''

RETURN = """
_raw:
description:
- The input list.
type: list
elements: str
"""

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase


class LookupModule(LookupBase):

def run(self, terms, variables, **kwargs):
self.set_options(var_options=variables, direct=kwargs)

return terms
37 changes: 37 additions & 0 deletions test/integration/targets/config_manager/lookup_plugins/lookup_1.py
@@ -0,0 +1,37 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = '''
lookup: lookup_1
author: Felix Fontein
short_description: Test lookup
description:
- Nothing.
options:
deprecated_option:
description: Deprecated
type: str
deprecated:
why: this option should not be used
version: 10.0.0
alternatives: no option instead
'''

RETURN = """
_raw:
description:
- The input list.
type: list
elements: str
"""

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase


class LookupModule(LookupBase):

def run(self, terms, variables, **kwargs):
self.set_options(var_options=variables, direct=kwargs)

return terms
17 changes: 17 additions & 0 deletions test/integration/targets/config_manager/runme.sh
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

set -eux

# Test lookup plugin option deprecation
ANSIBLE_DEPRECATION_WARNINGS=true ansible-playbook test.yml 2>&1 | tee out.txt

grep "deprecated_option option, this option should not be" out.txt
grep "used, use no option instead instead. This feature will be removed in version" out.txt
grep -E "(0;35m|^)10.0.0. Deprecation" out.txt

grep "deprecated_option option, this option should not be" out.txt
grep "used, use no option instead instead. This feature will be removed in version" out.txt
grep -E "(0;35m|^)1.0.0. Deprecation" out.txt
# Once https://github.com/ansible/ansible/pull/73239 is merged, replace the last two lines by:
# grep "used, use no option instead instead. This feature will be removed from" out.txt
# grep "foo_ns.bar in version 1.0.0. Deprecation" out.txt
10 changes: 10 additions & 0 deletions test/integration/targets/config_manager/test.yml
@@ -0,0 +1,10 @@
---
- hosts: localhost
tasks:
- name: Lookup option deprecation (local)
debug:
msg: "{{ lookup('lookup_1', deprecated_option='') }}"

- name: Lookup option deprecation (collection)
debug:
msg: "{{ lookup('foo_ns.bar.lookup_2', deprecated_option='') }}"