feat(ansible): structured playbook-variable fields on the schedule form
CI / lint (push) Successful in 2s
CI / unit (push) Successful in 45s
CI / integration (push) Successful in 2m20s
CI / publish (push) Successful in 1m14s

The Ansible Schedules form only offered a free-form extra-vars textarea,
unlike the browse/host run forms which auto-populate a field per declared
playbook variable (vars:/vars_prompt:) plus the playbook description. Wire
the schedule form to the same shared `_playbook_vars.html` partial:

- Playbook <select> now loads /ansible/playbook-vars?schedule=1 on change
  into a #sch-playbook-vars container (mirrors the host detail form).
- Edit mode pre-renders the saved playbook's variables server-side with
  their stored values; the extra-vars textarea keeps only leftover
  (non-declared) vars.
- Partial gains optional `values` (prefill) and `schedule` flags. In the
  schedule context secret vars render disabled ("secrets can't be
  scheduled") since they're dropped downstream, and the destructive-confirm
  gate is shown but not required.

Backend already parsed var__* fields for schedules, so this is the
front-end/partial parity fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-30 23:03:54 -04:00
parent f40063a74d
commit efc11c1837
3 changed files with 61 additions and 8 deletions
+27 -5
View File
@@ -75,6 +75,8 @@
{# ── Create / edit form ───────────────────────────────────────────────────── #}
{% set p = (editing.params or {}) if editing else {} %}
{% set saved_vars = p.get('extra_vars_map') or {} %}
{% set declared_names = (edit_variables or []) | map(attribute='name') | list %}
<div class="card" id="form">
<h2 class="section-title" style="margin-bottom:1rem;">{{ "Edit schedule" if editing else "New schedule" }}</h2>
<form method="post" action="{{ '/ansible/schedules/' ~ editing.id if editing else '/ansible/schedules' }}">
@@ -96,7 +98,9 @@
</div>
<div class="form-group" style="margin-bottom:0;">
<label>Playbook</label>
<select name="playbook_path" id="sch-playbook" required>
<select name="playbook_path" id="sch-playbook" required
hx-get="/ansible/playbook-vars?schedule=1" hx-trigger="change"
hx-target="#sch-playbook-vars" hx-swap="innerHTML" hx-include="closest form">
<option value="">— choose playbook —</option>
{% for pb in all_playbooks %}
<option value="{{ pb }}" {% if editing and editing.playbook_path == pb %}selected{% endif %}>{{ pb }}</option>
@@ -132,11 +136,29 @@
<input type="text" name="tags" value="{{ p.get('tags', '') }}" placeholder="tag1,tag2">
</div>
</div>
<div class="form-group" style="margin-top:1rem;">
<label>Extra vars (one key=value per line)</label>
<textarea name="extra_vars" rows="3" placeholder="prune_volumes=false">{% for k, v in (p.get('extra_vars_map') or {}).items() %}{{ k }}={{ v }}
{% endfor %}</textarea>
{# Declared playbook variables (vars:/vars_prompt:) — loaded via HTMX on
playbook change; pre-rendered here in edit mode so saved values show. #}
<div id="sch-playbook-vars" style="margin-top:1rem;">
{% if editing %}
{% set variables = edit_variables %}
{% set description = edit_description %}
{% set category = edit_category %}
{% set confirm = edit_confirm %}
{% set values = saved_vars %}
{% set schedule = true %}
{% include "ansible/_playbook_vars.html" %}
{% endif %}
</div>
<details style="margin-top:0.75rem;">
<summary style="cursor:pointer;font-size:0.82rem;color:var(--text-muted);">Extra vars</summary>
<div class="form-group" style="margin-top:0.6rem;">
<label>Extra vars <span style="color:var(--text-muted);font-weight:normal;">(one key=value per line — for vars not listed above)</span></label>
<textarea name="extra_vars" rows="3" placeholder="prune_volumes=false">{% for k, v in saved_vars.items() if k not in declared_names %}{{ k }}={{ v }}
{% endfor %}</textarea>
</div>
</details>
<div class="form-group" style="display:flex;align-items:center;gap:0.5rem;">
<input type="checkbox" name="check" id="check" style="width:auto;" {% if p.get('check') %}checked{% endif %}>
<label for="check" style="margin-bottom:0;">Dry run (--check --diff)</label>