Skip to main content

Ansible Playbooks

Ansible is the preferred provisioner for complex configurations in Klarity ImageFactory. It provides a powerful, declarative language for describing the desired state of a system, ensuring that components are idempotent and maintainable across different operating systems.

Playbook Structure and Requirements

All Ansible playbooks used in ImageFactory must adhere to specific formatting and structural requirements to ensure they can be executed correctly by the backend workers.

  1. Valid YAML: The playbook must be a syntactically correct YAML file.
  2. Hosts Definition: Every play in the playbook must have the hosts attribute set to either default or all. This is because ImageFactory executes the playbook against a single target instance during the build process.
  3. Privilege Escalation: For tasks requiring root or administrator privileges, use become: yes. This is standard practice for installing packages or modifying system configurations.

Playbook Validation

ImageFactory performs automated validation of playbooks against a predefined JSON schema. This schema ensures that the playbook structure is compatible with the ImageFactory execution environment. The validation schema is stored at artifacts/ansible_schemas/playbook.json within the system.

If a playbook fails validation, the component creation or version update will be rejected with a detailed error message indicating the structural issue.

Directory Structure for System Components

System components follow a standardized directory structure to separate logic for different operating systems:

component-name/
├── linux/
│ ├── playbook.yml
│ └── tasks/
│ └── main.yml
└── windows/
├── playbook.yml
└── tasks/
└── main.yml

Example Linux Playbook

---
- hosts: all
become: yes
tasks:
- name: Install security updates
apt:
upgrade: dist
update_cache: yes
when: ansible_os_family == "Debian"

- name: Install common utilities
package:
name:
- curl
- vim
- git
state: present

Advanced Execution Control

ImageFactory provides several mechanisms for fine-tuning how Ansible playbooks are executed:

Ansible Tags

You can use tags to selectively execute specific parts of a playbook. This is useful for large playbooks where only a subset of tasks needs to run for a particular image.

Extra Variables

Distributions can define ansible_extra_vars, which are passed to the playbook at runtime. These variables can be used to customize the behavior of the playbook based on the specific OS version or cloud provider.

Skipped Tags

Similarly, distributions can define skipped_tags to exclude certain tasks from execution. This is often used to skip tasks that are known to be incompatible with a specific distribution or environment.

Component Properties

When a component is added to an image template, users can define component properties. These are key-value pairs that are automatically injected into the Ansible execution environment as variables.

For example, if a component has a property named app_version with the value 2.1.0, it can be accessed in the playbook as {{ app_version }}.

Best Practices

To ensure your Ansible components are reliable and efficient, follow these best practices:

  • Idempotency: Always write tasks that can be run multiple times without changing the result. Use modules like apt, yum, template, and file which are idempotent by design.
  • Check Mode Support: Where possible, ensure your tasks support Ansible's check mode (--check). This allows for dry-runs to verify what changes would be made.
  • Error Handling: Use failed_when and ignore_errors judiciously to handle expected failure scenarios gracefully.
  • OS Conditionals: Use the ansible_facts (e.g., ansible_os_family, ansible_distribution) to write cross-platform playbooks that adapt to the target environment.
  • Modular Tasks: Break down large playbooks into smaller, logical task files included via include_tasks or import_tasks.