This commit is contained in:
Krishnendu Bhowmick 2026-05-27 22:06:51 -05:00 committed by GitHub
commit d02a0f4e97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 82 additions and 8 deletions

View file

@ -0,0 +1,3 @@
---
minor_changes:
- vars_prompt now supports a `choices` key for input validation. If choices are defined, users must pick one of the provided options. Values supplied via `--extra-vars` are also validated against the choices list.

View file

@ -139,13 +139,48 @@ class PlaybookExecutor:
salt = var.get("salt", None)
unsafe = boolean(var.get("unsafe", False))
if vname not in self._variable_manager.extra_vars:
if self._tqm:
self._tqm.send_callback('v2_playbook_on_vars_prompt', vname, private, prompt, encrypt, confirm, salt_size, salt,
default, unsafe)
play.vars[vname] = display.do_var_prompt(vname, private, prompt, encrypt, confirm, salt_size, salt, default, unsafe)
else: # we are either in --list-<option> or syntax check
play.vars[vname] = default
# 🔹 New: support for choices
choices = var.get("choices")
if self._tqm:
self._tqm.send_callback(
'v2_playbook_on_vars_prompt',
vname, private, prompt, encrypt, confirm,
salt_size, salt, default, unsafe
)
# Skip prompt if provided via --extra-vars
if vname in self._variable_manager.extra_vars:
play.vars[vname] = self._variable_manager.extra_vars[vname]
# If choices are defined, validate extra-vars value too
if choices and play.vars[vname] not in choices:
raise ValueError(
f"Invalid value for '{vname}': "
f"'{play.vars[vname]}' not in allowed choices {choices}"
)
continue
answer = display.do_var_prompt(
vname, private, prompt, encrypt, confirm,
salt_size, salt, default, unsafe
)
# 🔹 Check choices for interactive input
if choices:
while answer not in choices:
display.display(
f"Invalid choice. Must be one of: {choices}",
color='red'
)
answer = display.do_var_prompt(
vname, private, prompt, encrypt, confirm,
salt_size, salt, default, unsafe
)
play.vars[vname] = answer
else:
play.vars[vname] = default
# Post validate so any play level variables are templated
all_vars = self._variable_manager.get_vars(play=play)

View file

@ -242,7 +242,7 @@ class Play(Base, Taggable, CollectionSearch):
if 'name' not in prompt_data:
raise AnsibleParserError("Invalid vars_prompt data structure, missing 'name' key", obj=ds)
for key in prompt_data:
if key not in ('name', 'prompt', 'default', 'private', 'confirm', 'encrypt', 'salt_size', 'salt', 'unsafe'):
if key not in ('name', 'prompt', 'default', 'private', 'confirm', 'encrypt', 'salt_size', 'salt', 'unsafe', 'choices'):
raise AnsibleParserError("Invalid vars_prompt data structure, found unsupported key '%s'" % key, obj=ds)
vars_prompts.append(prompt_data)
return vars_prompts

View file

@ -0,0 +1,2 @@
shippable/posix/group3
context/controller

View file

@ -0,0 +1,11 @@
- hosts: localhost
gather_facts: no
vars_prompt:
- name: color
prompt: "Choose a color"
choices:
- red
- green
tasks:
- debug:
var: color

View file

@ -0,0 +1,23 @@
- name: Run playbook with valid choice
command: >
ansible-playbook targets/vars_prompt_choices/main.yml
--extra-vars "color=red"
register: result_valid
ignore_errors: yes
- name: Assert valid choice succeeded
assert:
that:
- result_valid.rc == 0
- name: Run playbook with invalid choice
command: >
ansible-playbook targets/vars_prompt_choices/main.yml
--extra-vars "color=blue"
register: result_invalid
ignore_errors: yes
- name: Assert invalid choice failed
assert:
that:
- result_invalid.rc != 0