Free tech learning for everyone, from basics to pro

AnsibleProgramming and Application SecurityAdvanced

Testing and running Ansible at scale: ansible-lint, Molecule and AWX

In short: Before automation touches production, lint it, syntax-check it, test roles with Molecule and preview changes in check mode. At scale, run playbooks from AWX or automation controller so credentials are protected, access is role based and every job is logged.

Why testing automation matters

A playbook that runs against 300 switches deserves at least as much testing as a manual change on one. Testing Ansible is about catching problems at the cheapest point: style and syntax errors on your laptop, logic errors in a disposable lab, and unexpected changes in a dry run, before the real deployment.

Quality gates for a playbookLintyamllint,ansible-lintSyntax--syntax-checkUnit / roleMoleculeDry run--check --diffDeploycontroller job
Figure 1. Each gate catches a different kind of mistake before automation reaches production devices.

Linting and static checks

pip install ansible-lint yamllint
yamllint .
ansible-lint                         # checks against best-practice rules
ansible-playbook site.yml --syntax-check

ansible-lint flags issues such as missing task names, short module names instead of FQCNs, use of command where a module exists, risky file permissions and tasks that are not idempotent. You can choose a profile (for example production) in .ansible-lint to set how strict it is.

Molecule and check mode

Molecule tests roles by creating a temporary instance, usually a container, applying the role, running it a second time to confirm idempotency, verifying the result and destroying the instance.

pip install molecule molecule-plugins[docker]
cd roles/base_linux
molecule init scenario default --driver-name docker
molecule test        # create, converge, idempotence, verify, destroy

Molecule works best for Linux server roles. For network roles, teams often test against virtual devices in a lab built with Containerlab or vendor virtual images, or use the rendered state of resource modules to compare generated commands with expected output. Before production runs, --check --diff --limit on a small group is the final preview. Remember that check mode depends on module support and cannot predict everything, for example the result of a task that needs a previous change to have happened.

A CI pipeline

# .gitlab-ci.yml (simplified)
stages: [lint, test]

lint:
  stage: lint
  image: python:3.12
  script:
    - pip install ansible-core ansible-lint yamllint
    - yamllint .
    - ansible-lint

molecule:
  stage: test
  script:
    - pip install molecule molecule-plugins[docker] ansible-core
    - cd roles/base_linux && molecule test

Running these checks on every merge request means reviewers see test results before approving, and the main branch stays deployable.

Running at scale with AWX or automation controller

Automation controller / AWXControllerweb UI and APIProjectsGit reposInventoriesstatic, dynamicCredentialsstored encryptedJob templatesplaybook + inventoryRBACwho can run whatSchedulesand workflows
Figure 2. The controller joins code, inventory and credentials into job templates that authorised users can run and audit.

AWX is the open-source upstream project; automation controller is the supported version within Red Hat Ansible Automation Platform. Both provide a web interface and REST API in front of Ansible. A job template combines a project (playbooks from Git), an inventory, credentials and an execution environment. Helpdesk staff can be allowed to run "Bounce access port" without ever seeing the device password, and every run is logged with who started it and what changed.

Jobs run inside execution environments: container images holding ansible-core, collections and Python dependencies. You build them with ansible-builder and test them locally with ansible-navigator, so the same versions run on your laptop, in CI and in the controller.

NeedController feature
Stop secrets leaking to usersCredentials with encrypted storage
Let juniors run approved jobs onlyRole-based access control on job templates
Chain backup, change and verifyWorkflow templates with approval nodes
Nightly compliance checksSchedules and notifications

Tip: you can run AWX in a home lab on a small Kubernetes cluster using the AWX Operator, which is good practice for interviews that mention Ansible Automation Platform.

Practice

What does Molecule check that a single playbook run does not?
It runs the role twice and fails if the second run reports changes, proving idempotency, then verifies and destroys the test instance.
Why use execution environments?
They package ansible-core, collections and dependencies in a container so every run uses identical, tested versions.
How does a controller let helpdesk staff run a job without knowing device passwords?
Credentials are stored encrypted in the controller and attached to the job template; RBAC grants staff permission to run the template only.

Key takeaways

  • Catch errors early with yamllint, ansible-lint and --syntax-check.
  • Use Molecule to test roles and prove idempotency.
  • Preview real changes with --check --diff on a limited group.
  • Run lint and tests in CI on every merge request.
  • Use AWX or automation controller for credentials, RBAC, scheduling and audit.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.