From 6969edc3c080c0ae908c8630a477f760eafcca69 Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Mon, 26 Nov 2018 13:09:11 -0600 Subject: [PATCH] [stable-2.6] Prevent metadata changes in a stable branch (#48994). (#49134) * [stable-2.6] Prevent metadata changes in a stable branch (#48994). (cherry picked from commit 7287d396e2fa49739a28ce573d921c24f532caae) Co-authored-by: Matt Martz * Address rebase issues * Fix metadata comparison --- .../dev_guide/testing_validate-modules.rst | 1 + test/sanity/validate-modules/main.py | 105 ++++++++++-------- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/docs/docsite/rst/dev_guide/testing_validate-modules.rst b/docs/docsite/rst/dev_guide/testing_validate-modules.rst index 2e49a9c3316..393a3c412ec 100644 --- a/docs/docsite/rst/dev_guide/testing_validate-modules.rst +++ b/docs/docsite/rst/dev_guide/testing_validate-modules.rst @@ -118,6 +118,7 @@ Errors 329 Default value from the argument_spec is not compatible with type defined in the argument_spec 330 Choices value from the argument_spec is not compatible with type defined in the argument_spec 332 ``AnsibleModule`` schema validation error + 334 ``ANSIBLE_METADATA`` cannot be changed in a point release for a stable branch .. --------- ------------------- **4xx** **Syntax** diff --git a/test/sanity/validate-modules/main.py b/test/sanity/validate-modules/main.py index 8d3523461a2..f63dbc2ef7b 100755 --- a/test/sanity/validate-modules/main.py +++ b/test/sanity/validate-modules/main.py @@ -803,6 +803,51 @@ class ModuleValidator(Validator): doc_info = self._get_docs() deprecated = False doc = None + + metadata = None + if not bool(doc_info['ANSIBLE_METADATA']['value']): + self.reporter.error( + path=self.object_path, + code=314, + msg='No ANSIBLE_METADATA provided' + ) + else: + if isinstance(doc_info['ANSIBLE_METADATA']['value'], ast.Dict): + metadata = ast.literal_eval( + doc_info['ANSIBLE_METADATA']['value'] + ) + else: + # ANSIBLE_METADATA doesn't properly support YAML + # we should consider removing it from the spec + # Below code kept, incase we change our minds + + # metadata, errors, traces = parse_yaml( + # doc_info['ANSIBLE_METADATA']['value'].s, + # doc_info['ANSIBLE_METADATA']['lineno'], + # self.name, 'ANSIBLE_METADATA' + # ) + # for error in errors: + # self.reporter.error( + # path=self.object_path, + # code=315, + # **error + # ) + # for trace in traces: + # self.reporter.trace( + # path=self.object_path, + # tracebk=trace + # ) + + self.reporter.error( + path=self.object_path, + code=315, + msg='ANSIBLE_METADATA was not provided as a dict, YAML not supported' + ) + + if metadata: + self._validate_docs_schema(metadata, metadata_1_1_schema(deprecated), + 'ANSIBLE_METADATA', 316) + if not bool(doc_info['DOCUMENTATION']['value']): self.reporter.error( path=self.object_path, @@ -873,7 +918,7 @@ class ModuleValidator(Validator): self._validate_docs_schema(doc, doc_schema(self.object_name.split('.')[0]), 'DOCUMENTATION', 305) self._check_version_added(doc) - self._check_for_new_args(doc) + self._check_for_new_args(doc, metadata) if not bool(doc_info['EXAMPLES']['value']): self.reporter.error( @@ -930,50 +975,6 @@ class ModuleValidator(Validator): tracebk=trace ) - if not bool(doc_info['ANSIBLE_METADATA']['value']): - self.reporter.error( - path=self.object_path, - code=314, - msg='No ANSIBLE_METADATA provided' - ) - else: - metadata = None - if isinstance(doc_info['ANSIBLE_METADATA']['value'], ast.Dict): - metadata = ast.literal_eval( - doc_info['ANSIBLE_METADATA']['value'] - ) - else: - # ANSIBLE_METADATA doesn't properly support YAML - # we should consider removing it from the spec - # Below code kept, incase we change our minds - - # metadata, errors, traces = parse_yaml( - # doc_info['ANSIBLE_METADATA']['value'].s, - # doc_info['ANSIBLE_METADATA']['lineno'], - # self.name, 'ANSIBLE_METADATA' - # ) - # for error in errors: - # self.reporter.error( - # path=self.object_path, - # code=315, - # **error - # ) - # for trace in traces: - # self.reporter.trace( - # path=self.object_path, - # tracebk=trace - # ) - - self.reporter.error( - path=self.object_path, - code=315, - msg='ANSIBLE_METADATA was not provided as a dict, YAML not supported' - ) - - if metadata: - self._validate_docs_schema(metadata, metadata_1_1_schema(deprecated), - 'ANSIBLE_METADATA', 316) - return doc_info, doc def _check_version_added(self, doc): @@ -1204,13 +1205,13 @@ class ModuleValidator(Validator): msg='"%s" is listed in DOCUMENTATION.options, but not accepted by the module' % arg ) - def _check_for_new_args(self, doc): + def _check_for_new_args(self, doc, metadata): if not self.base_branch or self._is_new_module(): return with CaptureStd(): try: - existing_doc = get_docstring(self.base_module, fragment_loader, verbose=True)[0] + existing_doc, dummy_examples, dummy_return, existing_metadata = get_docstring(self.base_module, fragment_loader, verbose=True) existing_options = existing_doc.get('options', {}) or {} except AssertionError: fragment = doc['extends_documentation_fragment'] @@ -1241,6 +1242,16 @@ class ModuleValidator(Validator): except ValueError: mod_version_added = StrictVersion('0.0') + if self.base_branch and 'stable-' in self.base_branch: + metadata.pop('metadata_version', None) + metadata.pop('version', None) + if metadata != existing_metadata: + self.reporter.error( + path=self.object_path, + code=334, + msg=('ANSIBLE_METADATA cannot be changed in a point release for a stable branch') + ) + options = doc.get('options', {}) or {} should_be = '.'.join(ansible_version.split('.')[:2])