Files
FabledSteward/steward/templates/ansible/playbook_editor.html
T
bvandeusenandClaude Opus 5.5 72a3261582
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 55s
CI / unit (push) Failing after 1m20s
CI / publish (push) Skipped
feat(ansible): Playbooks as one list, and a page per playbook that runs it (#5331, #5330)
- /ansible/playbooks lists every playbook across sources: what it says it
  does, its category and destructive flag, how it last ran; the whole row
  opens the playbook. A source with none is one quiet line.
- /ansible/playbooks/<source>/<path>: the verdict (what it does, flagged
  destructive, last ran), the run form in place (dry run beside the button,
  options folded), the schedules that use it, its recent runs, the playbook
  itself folded. ?from=<run> fills the form from that run: Run again on a
  run's page.
- /ansible/browse, its view page and the /run-form fragment are gone, not
  redirected (rule 122); every link points at the new pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:49:05 -04:00

67 lines
3.3 KiB
HTML

{% extends "base.html" %}
{% from "ansible/_tabs.html" import ansible_tabs %}
{% from "_macros.html" import crumbs %}
{% block title %}{{ "Edit" if editing else "New" }} Playbook — Steward{% endblock %}
{% block breadcrumb %}{{ crumbs([("Ansible", "/ansible/"), ("Playbooks", "/ansible/playbooks"), (("Edit " ~ playbook_path) if editing else "New playbook", "")]) }}{% endblock %}
{% block content %}
{{ ansible_tabs("playbooks") }}
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem;gap:1rem;flex-wrap:wrap;">
<h1 class="page-title" style="margin-bottom:0;">{{ "Edit playbook" if editing else "New playbook" }}</h1>
</div>
{% if error %}<div class="alert alert-error">{{ error }}</div>{% endif %}
{% if not editable_sources %}
<div class="card empty">
No writable playbook source is available. The built-in <code>steward-local</code> source should appear
automatically; you can also configure a local-dir source under <a href="/settings/ansible/">Settings → Ansible</a>.
</div>
{% else %}
<form method="post" action="/ansible/playbooks/save">{{ csrf_field() }}
<input type="hidden" name="editing" value="{{ '1' if editing else '0' }}">
<div style="display:flex;gap:1rem;flex-wrap:wrap;margin-bottom:1rem;">
<div class="form-group" style="margin-bottom:0;">
<label>Source</label>
{% if editing %}
<input type="text" value="{{ source_name }}" readonly style="color:var(--text-muted);">
<input type="hidden" name="source_name" value="{{ source_name }}">
{% else %}
<select name="source_name" required>
{% for s in editable_sources %}
<option value="{{ s.name }}" {% if s.name == source_name %}selected{% endif %}>{{ s.name }}</option>
{% endfor %}
</select>
{% endif %}
</div>
<div class="form-group" style="margin-bottom:0;flex:1;min-width:240px;">
<label>Filename / path (.yml or .yaml)</label>
<input type="text" name="playbook_path" value="{{ playbook_path }}" required
{% if editing %}readonly style="color:var(--text-muted);"{% endif %}
placeholder="maintenance/restart_nginx.yml">
</div>
</div>
<div class="form-group">
<label>Playbook (YAML)</label>
<textarea name="content" rows="22" spellcheck="false"
style="width:100%;font-family:ui-monospace,monospace;font-size:0.85rem;white-space:pre;overflow-wrap:normal;overflow-x:auto;">{{ content }}</textarea>
<p style="color:var(--text-dim);font-size:0.75rem;margin-top:0.35rem;">
Validated as YAML on save. Runs as the configured Ansible user — admin only.
</p>
</div>
<div style="display:flex;gap:0.5rem;">
<button type="submit" class="btn">Save</button>
<a href="{{ ('/ansible/playbooks/' ~ source_name ~ '/' ~ playbook_path) if editing else '/ansible/playbooks' }}" class="btn btn-ghost">Cancel</a>
</div>
</form>
{% if editing %}
<form method="post" action="/ansible/playbooks/delete" style="margin-top:1rem;"
data-confirm="Delete {{ playbook_path }}?">{{ csrf_field() }}
<input type="hidden" name="source_name" value="{{ source_name }}">
<input type="hidden" name="playbook_path" value="{{ playbook_path }}">
<button type="submit" class="btn btn-danger btn-sm">Delete playbook</button>
</form>
{% endif %}
{% endif %}
{% endblock %}