feat(validation): expand glob patterns in the spec list
This commit is contained in:
@@ -7,6 +7,7 @@ against that sub-option, and a null entry means the entry is not managed. Messag
|
|||||||
and the types involved but never a value, so secrets cannot leak into job output.
|
and the types involved but never a value, so secrets cannot leak into job output.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import glob
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
@@ -111,7 +112,15 @@ class ActionModule(ActionBase):
|
|||||||
task_vars = task_vars or {}
|
task_vars = task_vars or {}
|
||||||
validator = _Validator(self._templar)
|
validator = _Validator(self._templar)
|
||||||
declared = {}
|
declared = {}
|
||||||
for path in self._task.args["specs"]:
|
paths = []
|
||||||
|
# A pattern (`.../*/roles/*/meta/argument_specs.yml`) picks up every role's spec without a list
|
||||||
|
# to keep in sync; one that matches nothing is a broken path, not an empty set.
|
||||||
|
for entry in self._task.args["specs"]:
|
||||||
|
matches = sorted(glob.glob(entry)) if glob.has_magic(entry) else [entry]
|
||||||
|
if not matches:
|
||||||
|
raise AnsibleError(f"no spec file matches {entry}")
|
||||||
|
paths.extend(matches)
|
||||||
|
for path in paths:
|
||||||
options = self._loader.load_from_file(path)["argument_specs"]["inputs"]["options"]
|
options = self._loader.load_from_file(path)["argument_specs"]["inputs"]["options"]
|
||||||
_check_spec(options, path)
|
_check_spec(options, path)
|
||||||
for name, spec in options.items():
|
for name, spec in options.items():
|
||||||
|
|||||||
@@ -14,6 +14,41 @@
|
|||||||
loop_var: inf
|
loop_var: inf
|
||||||
label: "{{ inf.name }}"
|
label: "{{ inf.name }}"
|
||||||
|
|
||||||
|
- name: Expand a spec pattern
|
||||||
|
validate_inputs:
|
||||||
|
specs:
|
||||||
|
- "{{ playbook_dir }}/fixture_*.yml"
|
||||||
|
vars:
|
||||||
|
fixture:
|
||||||
|
name: web01
|
||||||
|
servers: [10.0.0.1]
|
||||||
|
register: inputs_pattern_result
|
||||||
|
|
||||||
|
- name: Assert the pattern matched the fixture spec
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- inputs_pattern_result is succeeded
|
||||||
|
success_msg: "[inputs pattern] OK"
|
||||||
|
|
||||||
|
- name: Refuse a pattern that matches nothing
|
||||||
|
block:
|
||||||
|
- name: Run the validator with a pattern that matches no file
|
||||||
|
validate_inputs:
|
||||||
|
specs:
|
||||||
|
- "{{ playbook_dir }}/nothing_*.yml"
|
||||||
|
register: inputs_nomatch_result
|
||||||
|
rescue:
|
||||||
|
- name: Keep the no-match failure
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
inputs_nomatch_result: "{{ ansible_failed_result }}"
|
||||||
|
|
||||||
|
- name: Assert the empty pattern was refused
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- inputs_nomatch_result.msg is search('no spec file matches')
|
||||||
|
fail_msg: "[inputs no-match] got {{ inputs_nomatch_result.msg | default('') }}"
|
||||||
|
success_msg: "[inputs no-match] OK"
|
||||||
|
|
||||||
- name: Refuse a variable declared by two specs
|
- name: Refuse a variable declared by two specs
|
||||||
block:
|
block:
|
||||||
- name: Run the validator with the fixture spec twice
|
- name: Run the validator with the fixture spec twice
|
||||||
|
|||||||
Reference in New Issue
Block a user