The Ansible Tower Plugin connects Jenkins to Ansible Tower, AWX, and Red Hat Ansible Automation Platform (AAP). It supports Freestyle projects and Pipeline jobs that need to:
- Launch job templates and workflow job templates.
- Wait for jobs and import controller output.
- Run project syncs.
- Change a project's SCM revision.
- Pass Jenkins environment variables to launch parameters.
- Return job metadata and exported Ansible values to Jenkins.
- Jenkins 2.504.3 or newer. Compatibility is also verified against the Jenkins 2.554 weekly release.
- Java 17 or newer at runtime, as derived from the Jenkins 2.504.3 baseline.
- JDK 21 and Maven 3.9.6 or newer to build the plugin locally. Jenkins CI and the official Maven CD workflow also use JDK 21.
- A reachable Tower, AWX, or AAP controller API.
- A Jenkins credential with sufficient controller permissions.
For local development, use JDK 21 and Maven 3.9.6 or newer.
- Open Manage Jenkins → Plugins.
- Search the Available plugins tab for Ansible Tower.
- Install the plugin and restart Jenkins if requested.
- Alternatively, upload a locally built
ansible-tower.hpifrom the plugin manager's advanced settings.
After installation, configure at least one controller under Manage Jenkins → System → Ansible Tower.
- Open Manage Jenkins → System.
- Find the Ansible Tower section.
- Select Add Tower Installation.
- Enter the installation name, URL, API Base Path, credential, and TLS/debug options.
- Select Test Connection.
- Save the Jenkins system configuration after the test succeeds.
The screenshot is from an earlier plugin release. Current releases also display the API Base Path selector used for Tower/AWX and AAP 2.5+ compatibility.
Each configured installation has the following fields:
| Field | Description |
|---|---|
| Name | Name used by Freestyle builds and the Pipeline towerServer parameter. |
| URL | Controller or AAP gateway base URL, without an API path; for example https://aap.example.com. |
| API Base Path | Use /api/v2 for Tower/AWX or /api/controller/v2 for AAP 2.5+ controller APIs. |
| Credentials | Default Jenkins credential for this installation. Pipeline and Freestyle steps can override it. |
| Force Trust Cert | Disables normal TLS certificate validation. Use only for controlled test environments. |
| Enable Debugging | Allows detailed FINE diagnostics. A Jenkins Log Recorder must also enable FINE or ALL. |
Use Test Connection to verify the URL, API path, TLS setting, and credential.
Configure an AAP gateway/controller installation as follows:
URL: https://aap-gateway.example.com
API Base Path: /api/controller/v2
Controller calls then use /api/controller/v2/.... OAuth tokens created from username/password credentials use the AAP gateway endpoint /api/gateway/v1/tokens/.
The configured API path also controls generated UI links:
- Tower/AWX workflow:
/#/jobs/workflow/<id> - AAP workflow:
/execution/jobs/workflow/<id>/output - AAP job:
/execution/jobs/playbook/<id>/output
The plugin accepts these Jenkins credential types:
To configure username/password authentication:
- Open Manage Jenkins → Credentials.
- Add a Username with password credential.
- Use a dedicated controller service account with only the required permissions.
- Select the new credential in the global Ansible Tower installation.
- Use Test Connection to validate it.
When a username/password credential is selected, the plugin attempts authentication in this order:
- Create an OAuth token.
- Try the legacy authtoken endpoint when supported.
- Fall back to HTTP Basic authentication.
The account should be a dedicated service account with only the permissions required to read and launch the configured resources.
To configure a pre-created bearer token:
- Create an OAuth access token for the Jenkins service account in Tower, AWX, or AAP.
- Copy the access token value when the controller displays it.
- Open Manage Jenkins → Credentials.
- Add a Secret text credential and paste the access token into Secret.
- Select the new credential in the global Ansible Tower installation.
- Use Test Connection to validate it.
Store the actual OAuth access token value in a Jenkins Secret text credential. The plugin sends it as a bearer token and does not create or delete that externally managed token.
Secret text credentials require the Plain Credentials Plugin.
Do not enter a token database ID or token record ID; Jenkins needs the access token value.
Freestyle projects provide an Ansible Tower build step. Pipeline jobs use ansibleTower.
- Open or create a Freestyle project.
- Select Configure.
- Under Build Steps, select Add build step → Ansible Tower.
- Choose the configured Tower/AWX/AAP server and optional credential override.
- Select
joborworkflow, then enter the template name or numeric ID. - Configure launch overrides and output import behavior as required.
- Save and run the project.
The minimum Pipeline configuration is towerServer, towerCredentialsId, jobTemplate, and jobType. towerCredentialsId may be an empty string to use the globally configured credential.
def result = ansibleTower(
towerServer: 'AAP UAT',
towerCredentialsId: '',
jobTemplate: 'Deploy application',
jobType: 'run',
templateType: 'job',
towerLogLevel: 'full',
extraVars: '''---
deployment_environment: uat
release: "${BUILD_TAG}"
''',
inventory: 'UAT Inventory',
removeColor: true,
throwExceptionWhenFail: true,
async: false
)
// The step currently returns java.util.Properties. Printing the whole result is
// Sandbox-safe and includes JOB_ID, JOB_URL, JOB_RESULT, and LOG_IMPORT_RESULT.
echo "AAP result: ${result}"
| Parameter | Values/default | Description |
|---|---|---|
towerServer |
Required | Name of a globally configured installation. |
towerCredentialsId |
Required; '' uses global credential |
Optional per-build credential override. |
jobTemplate |
Required | Template name or numeric ID. |
jobType |
run or check; default run |
Job launch type. |
templateType |
job or workflow; default job |
Selects job template or workflow job template APIs. |
extraVars |
Empty | YAML or JSON launch variables. |
inventory |
Empty | Inventory name or numeric ID. |
credential |
Empty | Controller credential name or numeric ID. Multiple credentials may be comma-separated where supported. |
limit |
Empty | Host limit passed at launch. |
jobTags |
Empty | Job tags passed at launch. |
skipJobTags |
Empty | Tags to skip. |
scmBranch |
Empty | SCM branch override. The template must allow prompting for SCM branch. |
towerLogLevel |
false |
Output import mode described below. |
importWorkflowChildLogs |
false |
Imports child job output for workflows. |
removeColor |
false |
Removes ANSI color sequences from imported output. |
verbose |
false |
Adds progress messages, including some expanded launch values, to the Jenkins build console. Avoid placing secrets in launch parameters when this is enabled. |
throwExceptionWhenFail |
true |
Fails the Pipeline step when the controller operation fails. |
async |
false |
Returns immediately with a job handle. |
The controller template must permit prompting for any launch-time overrides you provide, such as inventory, credential, variables, tags, limit, job type, or SCM branch.
towerLogLevel |
Behavior |
|---|---|
false |
Do not import controller output. |
true |
Import the output exposed by the controller UI. Long lines may be truncated. |
full |
Import full event output where available. |
vars |
Process exported variables without printing controller output. |
The legacy Boolean importTowerLogs option remains supported for compatibility, but new Pipeline code should use towerLogLevel.
Freestyle projects provide Ansible Tower Project Sync. Pipeline jobs use ansibleTowerProjectSync:
For a Freestyle project:
- Open the project configuration.
- Select Add build step → Ansible Tower Project Sync.
- Choose the Tower server and optional credential override.
- Enter the controller project name.
- Select output, color, failure, and async behavior.
- Save and run the project.
Pipeline example:
def result = ansibleTowerProjectSync(
towerServer: 'AAP UAT',
towerCredentialsId: '',
project: 'Application Project',
importTowerLogs: true,
removeColor: true,
throwExceptionWhenFail: true,
async: false,
verbose: false
)
echo "Project sync result: ${result}"
Freestyle projects provide Ansible Tower Project Revision. Pipeline jobs use ansibleTowerProjectRevision:
For a Freestyle project:
- Open the project configuration.
- Select Add build step → Ansible Tower Project Revision.
- Choose the Tower server and optional credential override.
- Enter the project name and desired SCM revision.
- Select failure and verbose behavior.
- Save and run the project.
Pipeline example:
ansibleTowerProjectRevision(
towerServer: 'AAP UAT',
towerCredentialsId: '',
project: 'Application Project',
revision: 'release/1.4',
throwExceptionWhenFail: true,
verbose: false
)
Changing the revision may cause the controller to synchronize an SCM-backed project automatically. A manual project may accept the revision request without performing an SCM operation.
With async: true, a launch returns before the controller operation completes.
An asynchronous ansibleTower result contains:
JOB_IDJOB_URLLOG_IMPORT_RESULTwith valueDEFERREDjob, aTowerJobhandle
The advanced async example below accesses a Java object returned by the plugin. In a sandboxed Pipeline, an administrator must first approve method java.util.Dictionary get java.lang.Object and may also need to approve the TowerJob methods used by the Pipeline. Synchronous Pipelines do not need these approvals when they only print the complete result as shown above.
def submitted = ansibleTower(
towerServer: 'AAP UAT',
towerCredentialsId: '',
jobTemplate: 'Long deployment',
jobType: 'run',
templateType: 'workflow',
async: true
)
def job = submitted.get('job')
try {
timeout(time: 30, unit: 'MINUTES') {
waitUntil {
job.isComplete()
}
}
job.getLogs().each { line -> echo line }
if (!job.wasSuccessful()) {
error 'AAP workflow failed'
}
} finally {
job.releaseToken()
}
TowerJob exposes isComplete(), wasSuccessful(), getLogs(), getExports(), cancelJob(), and releaseToken().
An asynchronous project sync result contains SYNC_ID, SYNC_URL, and a sync handle. TowerProjectSync exposes isComplete(), wasSuccessful(), getLogs(), cancelSync(), getURL(), getID(), and releaseToken().
Jenkins may require additional Script Security approvals before untrusted Pipeline code can invoke methods on these returned Java objects.
When username/password authentication creates a temporary token, async mode releases the launch token before returning. Later handle calls may acquire another token; call releaseToken() when the handle is no longer needed.
Synchronous job results are returned as a java.util.Properties object containing:
| Key | Availability | Description |
|---|---|---|
JOB_ID |
Always after launch | Controller job ID. |
JOB_URL |
Always after launch | Link to controller job output. |
JOB_RESULT |
Synchronous execution | SUCCESS or FAILED. |
LOG_IMPORT_RESULT |
Always after launch | SKIPPED, DEFERRED, SUCCESS, or PARTIAL. |
| Exported keys | After export processing | Values produced through JENKINS_EXPORT. |
JOB_RESULT reflects only the final AAP job result. Event import is best-effort: if AAP finishes successfully while its event or workflow-node endpoints remain unavailable, the step returns JOB_RESULT=SUCCESS and LOG_IMPORT_RESULT=PARTIAL.
Project sync results similarly contain SYNC_ID, SYNC_URL, and, for synchronous execution, SYNC_RESULT.
Groovy property access such as result.JOB_ID, result['JOB_ID'], or result.get('JOB_ID') can resolve to java.util.Dictionary.get(Object) and be rejected by Jenkins Pipeline Sandbox. Print the complete result, or have an administrator review and approve that signature under Manage Jenkins → In-process Script Approval.
The plugin recognizes a purpose-driven output line:
- name: Export a value to Jenkins
ansible.builtin.debug:
msg: "JENKINS_EXPORT IMAGE_TAG=1.4.2"
It also recognizes controller artifacts created with set_stats:
- name: Export structured values to Jenkins
ansible.builtin.set_stats:
data:
JENKINS_EXPORT:
- image_tag: "1.4.2"
- deployment_id: "deploy-42"
aggregate: true
per_host: false
Pipeline jobs receive exported values in the returned result. Freestyle jobs can inject them through the optional EnvInject Plugin. EnvInject has limited Pipeline compatibility, so Pipeline code should use the returned result instead of relying on env.
The plugin expands Jenkins environment variables in these inputs before calling the controller:
- Job template
- Extra variables
- Limit
- Job and skip tags
- Inventory
- Controller credential
- SCM branch
- Project and project revision
Example:
release: "$BUILD_TAG"
environment: "$DEPLOY_ENV"
Set removeColor: true to strip ANSI sequences. To preserve and render colors, install the AnsiColor Plugin and configure the Pipeline accordingly.
Plugin diagnostics use java.util.logging under this namespace:
org.jenkinsci.plugins.ansible_tower
To collect detailed diagnostics:
- Select Enable Debugging on the global Tower installation.
- Open Manage Jenkins → System Log.
- Add a Log Recorder for
org.jenkinsci.plugins.ansible_toweratFINEorALL.
Logging is split between two audiences. The build console always shows user-facing milestones, retry notices, and failures needed to diagnose the current run. Jenkins System Log keeps lower-level diagnostics; successful HTTP request metadata is available at FINE, while operational WARNING and SEVERE records are emitted even when debugging is disabled. Messages retain the [Ansible-Tower] prefix.
Neither destination logs request or response payloads, extra variables, credentials, authorization headers, passwords, or tokens. Endpoint query values are redacted. The verbose build-console option adds safe expansion and launch progress details, but does not expose expanded extra variables or credential values.
Typical build-console diagnostics look like:
[Ansible-Tower] INFO: Resolving job template: template=deploy
[Ansible-Tower] ERROR: HTTP request failed: method=GET, url=https://aap.example.com/api/controller/v2/job_templates/?name=<redacted>, httpStatus=502, durationMs=103
[Ansible-Tower] ERROR: Job was not launched because the job template lookup failed
If a launch request receives a transient gateway response or loses its connection, the console explicitly reports that the launch outcome is unknown. The plugin does not automatically retry that POST because the controller may already have created the job:
[Ansible-Tower] WARNING: Tower launch outcome is unknown; the controller may have created the job, but Jenkins received HTTP 502. Automatic retry was not performed.
Polling recovery continues to report both the retry and recovery in the build console, including the job ID, endpoint, status, attempt, and retry delay.
For Jenkins installed as a Linux systemd service:
sudo journalctl -u jenkins --since "24 hours ago" --no-pager \
| grep -F '[Ansible-Tower]'
To find transient gateway failures and retries:
sudo journalctl -u jenkins --no-pager \
| grep -E '\[Ansible-Tower\].*(502|503|504|attempt=|exhausted retries)'
Synchronous jobs poll status every five seconds and events every ten seconds. Status HTTP 502, 503, and 504 responses back off for 5, 10, 20, 30, and 30 seconds before the status path fails. Event failures use an independent 10, 20, then 30-second backoff and never delay status polling. After completion, event import is attempted immediately and, for transient failures, again after two and five seconds.
All controller HTTP clients use a 10-second connect timeout, a 10-second connection pool timeout, and a 30-second read timeout. Transport timeouts, refused/reset connections, and empty HTTP responses are treated as transient; TLS, URL, and configuration errors are not.
- A
401normally indicates an invalid or expired credential. - A
403normally indicates insufficient controller permissions. - A
404often indicates the wrong API Base Path or a resource that does not exist. - Repeated
502,503, or504responses usually point to the AAP gateway, route, load balancer, or controller availability rather than a Jenkins credential issue. - If launch overrides are ignored, enable the corresponding Prompt on launch option on the controller template.
Run the test suite:
mvn test
Build and verify the plugin:
mvn verify
The HPI is generated at target/ansible-tower.hpi.
- Report reproducible defects through GitHub Issues.
- Review published changes in GitHub Releases.
- Contributions should include tests for behavior changes and pass
mvn verify.
This project is licensed under the MIT License.



