From 50dae8087eb731fe789ee97c56bfd737a6dbdf9a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 26 Sep 2022 13:35:43 +0200 Subject: [PATCH] runtime-metadata sanity test: ensure redirects are FQCRs (#78802) * Ensure that meta/runtime.yml redirects are FQCRs. * Avoid crash when YAML errors without context mark happen, for example if file starts with 'foo---' instead of '---'. --- .../fragments/78802-sanity-meta-runtime.yml | 4 +++ .../ns/col/meta/runtime.yml | 9 ++++- .../sanity/code-smell/runtime-metadata.py | 35 ++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/78802-sanity-meta-runtime.yml diff --git a/changelogs/fragments/78802-sanity-meta-runtime.yml b/changelogs/fragments/78802-sanity-meta-runtime.yml new file mode 100644 index 00000000000..e4312fb28c6 --- /dev/null +++ b/changelogs/fragments/78802-sanity-meta-runtime.yml @@ -0,0 +1,4 @@ +minor_changes: + - "ansible-test runtime-metadata sanity test - ensure that ``redirect`` entries in ``meta/runtime.yml`` contain collection names, except for ``module_utils`` plugin redirects and ``import_redirect`` redirects (https://github.com/ansible/ansible/pull/78802)." +bugfixes: + - "ansible-test runtime-metadata sanity test - do not crash on YAML parsing errors without a context mark (https://github.com/ansible/ansible/pull/78802)." diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml index fee22ad8c68..76ead137a39 100644 --- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml +++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml @@ -2,4 +2,11 @@ requires_ansible: '>=2.11' # force ansible-doc to check the Ansible version (re plugin_routing: modules: hi: - redirect: hello + redirect: ns.col2.hello + hiya: + redirect: ns.col2.package.subdir.hiya + module_utils: + hi: + redirect: ansible_collections.ns.col2.plugins.module_utils + hello: + redirect: ns.col2.hiya diff --git a/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py b/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py index 6cf2777401a..8d1fe362fb0 100644 --- a/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +++ b/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py @@ -16,9 +16,19 @@ from voluptuous.humanize import humanize_error from ansible.module_utils.compat.version import StrictVersion, LooseVersion from ansible.module_utils.six import string_types +from ansible.utils.collection_loader import AnsibleCollectionRef from ansible.utils.version import SemanticVersion +def fqcr(value): + """Validate a FQCR.""" + if not isinstance(value, string_types): + raise Invalid('Must be a string that is a FQCR') + if not AnsibleCollectionRef.is_valid_fqcr(value): + raise Invalid('Must be a FQCR') + return value + + def isodate(value, check_deprecation_date=False, is_tombstone=False): """Validate a datetime.date or ISO 8601 date string.""" # datetime.date objects come from YAML dates, these are ok @@ -126,12 +136,15 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False): with open(path, 'r', encoding='utf-8') as f_path: routing = yaml.safe_load(f_path) except yaml.error.MarkedYAMLError as ex: - print('%s:%d:%d: YAML load failed: %s' % (path, ex.context_mark.line + - 1, ex.context_mark.column + 1, re.sub(r'\s+', ' ', str(ex)))) + print('%s:%d:%d: YAML load failed: %s' % ( + path, + ex.context_mark.line + 1 if ex.context_mark else 0, + ex.context_mark.column + 1 if ex.context_mark else 0, + re.sub(r'\s+', ' ', str(ex)), + )) return except Exception as ex: # pylint: disable=broad-except - print('%s:%d:%d: YAML load failed: %s' % - (path, 0, 0, re.sub(r'\s+', ' ', str(ex)))) + print('%s:%d:%d: YAML load failed: %s' % (path, 0, 0, re.sub(r'\s+', ' ', str(ex)))) return if is_ansible: @@ -185,6 +198,15 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False): ) plugin_routing_schema = Any( + Schema({ + ('deprecation'): Any(deprecation_schema), + ('tombstone'): Any(tombstoning_schema), + ('redirect'): fqcr, + }, extra=PREVENT_EXTRA), + ) + + # Adjusted schema for module_utils + plugin_routing_schema_mu = Any( Schema({ ('deprecation'): Any(deprecation_schema), ('tombstone'): Any(tombstoning_schema), @@ -195,6 +217,9 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False): list_dict_plugin_routing_schema = [{str_type: plugin_routing_schema} for str_type in string_types] + list_dict_plugin_routing_schema_mu = [{str_type: plugin_routing_schema_mu} + for str_type in string_types] + plugin_schema = Schema({ ('action'): Any(None, *list_dict_plugin_routing_schema), ('become'): Any(None, *list_dict_plugin_routing_schema), @@ -207,7 +232,7 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False): ('httpapi'): Any(None, *list_dict_plugin_routing_schema), ('inventory'): Any(None, *list_dict_plugin_routing_schema), ('lookup'): Any(None, *list_dict_plugin_routing_schema), - ('module_utils'): Any(None, *list_dict_plugin_routing_schema), + ('module_utils'): Any(None, *list_dict_plugin_routing_schema_mu), ('modules'): Any(None, *list_dict_plugin_routing_schema), ('netconf'): Any(None, *list_dict_plugin_routing_schema), ('shell'): Any(None, *list_dict_plugin_routing_schema),