FabrikFabrik
FabrikAWX Automation

Requests

The request wizard — picking a template, choosing APIC and AWX credentials, filling out the data grid, running validation, and submitting to AWX.

A request is one user's submission of data against an automation template. The wizard walks through five steps — info, connection, data, validation, review — and ends with either a launched AWX job (for immediate requests) or a request awaiting approval.

Requests are where everything comes together: the template's schema, the validation library, the approval workflow, and the target APIC and AWX credential all feed into a single form.

Starting a request

Two entry points:

  • From the Template Library — click a template, then New Request.
  • From Request TrackingNew Request, then pick a template.

Either way, the wizard opens at step 1.

Step 1 — Info

Three fields:

FieldNotes
Title (required)Shown in the tracking list and notifications. Use a meaningful summary — "Add 15 tenants to DC-EAST, 2026-04 batch" is much more useful than "Tenants".
DescriptionFree-form context. Change-request ticket number, hand-off notes, whatever helps the next person understand why this ran.
Check modeToggles Ansible's --check flag. Available if the template allows override. On by default if the template's enable_check_mode is set.

Check mode is useful to stage: submit once with check mode on, review the report, resubmit with it off.

Step 2 — Connection

Two pickers.

APIC connection

Which APIC this automation targets. Surfaces the APICs you can access (public + owned + shared). The selection is stored on the request and passed into any validation queries that fire — so "must be an existing tenant" checks against the right fabric.

Not every template needs an APIC target (pure network-device automations might not), but the wizard requires one selected for audit-trail consistency.

AWX credential

Which credential AWX should inject into the playbook for device authentication. This is the AWX Credential Picker:

  • The list comes from AWX itself (not stored in Fabrik).
  • If the connection has a credential_prefix configured, only credentials matching the prefix appear.
  • Fabrik stores only the credential ID and cached name on the request; the secret stays in AWX's vault.
  • Different requests against the same template can use different credentials — this is how one template serves many sites.

The AWX credential picker shows device credentials (SSH, network device, APIC). It does not show the AWX credential Fabrik uses to talk to AWX — that's a Fabrik-side credential, configured on the Connection.

Both pickers must have a selection before the wizard advances.

Step 3 — Data

The heart of the wizard: a spreadsheet-style grid per schema.

  • Single-schema template (job template) → one grid.
  • Multi-schema template (workflow template) → tabs, one per schema. Each tab corresponds to one workflow node.

The DataGrid

The grid handles:

  • Keyboard navigation — Tab / Shift+Tab between cells, Enter to move down, Esc to cancel edit.
  • Paste from Excel — copy a range in Excel / Google Sheets, paste into the grid. Columns line up by position. Rows past the grid's current count are appended.
  • Row operations — add, duplicate, delete, reorder.
  • Inline type renderingselect columns are dropdowns, boolean are checkboxes, date are date pickers.
  • Inline help — the column's help_text shows below the cell on focus.

Validation is deferred — you can enter whatever you want in step 3. The red squiggles come in step 4.

Row limits

If the schema defines min_rows / max_rows, the grid enforces them. Trying to submit with too few or too many triggers a block at the step transition.

Empty schemas on multi-sheet templates

Workflow templates can have schemas where you legitimately want no rows (an optional cleanup step, for example). Leaving schemas empty triggers a confirmation dialog at submit — "you didn't fill in X, did you mean to?" — to keep the accidental case from silently skipping.

Step 4 — Validation

Run Validation kicks off an async check.

Because query_list validation involves live APIC calls, validation runs as a Celery task, not inline in the HTTP request. The wizard:

  1. Submits the table data + connection ID to the backend.
  2. Receives a task ID.
  3. Polls progress every second.
  4. Displays real-time validating N of M rows status.
  5. When complete, renders the error list.

Every error carries:

  • The schema index (which sheet).
  • The row number.
  • The column name.
  • The value that failed.
  • The error message (custom or default).
  • For list-based validation, the first few allowed values as a hint.

Clicking a red cell opens a detail dialog with the full error message and suggested values.

Cancel and rerun

Long validation runs can be cancelled — the polling stops and the backend task is marked cancelled. Then fix the data in step 3 and Re-run Validation.

Bypass

If the template allows it and you have the awx.bypass_validation permission, a Bypass validation checkbox appears. Ticked, validation still runs and shows errors, but the wizard stops blocking the step transition. Use sparingly — bypassed requests are clearly flagged in the history.

Passing the step

The validation step is only valid when validation has actually been run and returned zero errors. You can't skip to review without running — the intent is to make validation a deliberate act, not something to forget.

Step 5 — Review

A read-only summary:

  • Template name + AWX template name.
  • APIC connection.
  • AWX credential.
  • Check-mode flag.
  • Row counts per schema.
  • Validation result.
  • The transformed extra_vars preview (what AWX will actually receive).

The extra_vars preview is the single most useful thing on this page — it's the exact JSON the playbook sees. If the shape is wrong, fix the variable mapping on the template and restart.

Submit finalizes the request. Depending on the template's approval config, the request lands in one of two places:

  • Immediate execution. Status pending → picked up by a Celery worker within seconds → status running.
  • Awaiting approval. Status awaiting_approval. No AWX call yet; notification fires to approvers.

Idempotency

Every submission generates an idempotency_key on the frontend. The backend checks it before creating the request — if the same key was seen in the last N minutes, the existing request is returned instead of a duplicate.

This protects against double-clicks, network retries, and the "I refreshed the page and submitted again" case. You can't accidentally fire the same AWX job twice by being impatient.

Request tracking

AWX → Request Tracking is the list of every request, yours and (if public) others'. Filters match the lifecycle statuses: pending, awaiting approval, approved, rejected, running, successful, failed, cancelled.

The detail view shows:

  • The original input data (what the user submitted).
  • The transformed ansible_extra_vars (what AWX received).
  • Request metadata (client IP, user agent, timestamp) — for audit.
  • Approval history (approver, timestamp, rejection reason if any).
  • Linked executions.
  • Relaunch — re-submit the request with identical data.
  • Rollback (if the template has a rollback_template configured) — open a new request against the rollback template, pre-filled with the same data.

Approval flow

When a template requires approval, the flow is:

  1. User submits → status awaiting_approval.
  2. Approver users / groups get notified.
  3. An approver opens the request and clicks Approve or Reject.
  4. On approval — status approved, then Celery kicks off execution within seconds.
  5. On rejection — status rejected, rejection_reason is captured, no AWX call is ever made.

Auto-approve for owner, if enabled on the template, skips approval when the requester is the template's creator.

Approvers can't approve their own requests unless they're also in the approver list and auto_approve_for_owner isn't the mechanism — the two are independent toggles.

Scheduled requests

A request can carry a scheduled_for timestamp — "don't run this until 2026-04-22T02:00Z". If set, the request stays in pending (or awaiting_approval) until the scheduled time, then launches.

Useful for change windows. The UI surfaces scheduled requests clearly in the tracking list.

Metadata capture

Every request captures:

  • Client IP (X-Forwarded-For aware, validated as a real IP to prevent header injection).
  • User agent.
  • Session ID.
  • LDAP attributes (if LDAP is enabled).
  • Submission timestamp.

This metadata is the backbone of the audit trail. Combined with the frozen template_snapshot and the ansible_extra_vars the request actually sent, you can reconstruct exactly who did what with which data from which endpoint — months later.

Troubleshooting

Request wizard issues that come up often:

  • "I can't advance past step 4." Validation hasn't been run yet, or has unresolved errors. Click Run Validation and fix any reported issues.
  • "The AWX credential picker is empty." Either AWX has no matching credentials, or the connection's credential_prefix filters them all out. Check the Connection config.
  • "Paste from Excel puts everything in column 1." The paste handler splits on tab. Copying from a spreadsheet should use tab-delimited; copying from a regular text editor won't.
  • "Submit did nothing." Idempotency key collision — the backend returned the previous submission. Check the request tracking page; the request is probably already there.
  • "It says pending but nothing's happening." Celery workers may be down. Check docker compose logs celery-worker. For approval-gated requests, check whether it's actually awaiting_approval rather than pending.
  • "Approvers never got the notification." Approval notifications run through the standard notification system — check the user's notification preferences and verify the approver list on the template snapshot (not the template itself; those can drift).
  • "The extra_vars preview in review looks wrong." Fix the variable_mappings on the template and start a new request. The preview is what will actually be sent to AWX — if it's wrong here, the playbook will see it wrong.

Once submitted, the request becomes an Execution — a live AWX job. The next page covers monitoring, live output, per-host results, and relaunch/cancel semantics.