Skip to content

Ansible File Operations Guide

Overview

Ansible provides robust capabilities for handling various file types, including YAML, JSON, text, and configuration files. This guide covers common file operations, best practices, and patterns for file manipulation.

YAML File Operations

Reading YAML Files

# Read single YAML file
- name: Load YAML configuration
  ansible.builtin.include_vars:
    file: config.yml
    name: config_vars

# Read all YAML files in directory
- name: Load all YAML configs
  ansible.builtin.include_vars:
    dir: config_files
    extensions: 
      - yml
      - yaml
    name: all_configs

Writing YAML Files

# Write simple YAML file
- name: Create YAML configuration
  ansible.builtin.copy:
    content: "{{ config_data | to_nice_yaml }}"
    dest: /etc/app/config.yml
    mode: '0644'

# Write YAML with advanced formatting
- name: Generate complex YAML config
  ansible.builtin.template:
    src: complex_config.yml.j2
    dest: /etc/app/complex_config.yml
    mode: '0644'
  vars:
    custom_indent: 2
    config_data:
      server:
        host: "{{ server_host }}"
        port: "{{ server_port }}"
      database:
        url: "{{ db_url }}"
        credentials:
          username: "{{ db_user }}"
          password: "{{ db_password | password_hash('sha512') }}"

# Template example (complex_config.yml.j2)
server:
{{ config_data.server | to_nice_yaml(indent=2) | indent(2, first=true) }}
database:
{{ config_data.database | to_nice_yaml(indent=2) | indent(2, first=true) }}

JSON File Operations

Reading JSON Files

# Read JSON file
- name: Load JSON data
  ansible.builtin.set_fact:
    json_data: "{{ lookup('file', 'data.json') | from_json }}"

# Read and parse JSON with custom parameters
- name: Load complex JSON
  ansible.builtin.slurp:
    src: /path/to/large.json
  register: json_content

- name: Parse JSON content
  ansible.builtin.set_fact:
    parsed_json: "{{ json_content['content'] | b64decode | from_json }}"

Writing JSON Files

# Write JSON file with formatting
- name: Create formatted JSON
  ansible.builtin.copy:
    content: "{{ json_data | to_nice_json }}"
    dest: /path/to/output.json
    mode: '0644'

# Write JSON with custom formatting
- name: Generate custom formatted JSON
  ansible.builtin.template:
    src: template.json.j2
    dest: /path/to/custom.json
    mode: '0644'
  vars:
    indent_level: 4

JSON Manipulation

# Modify existing JSON
- name: Update JSON content
  ansible.builtin.copy:
    content: >
      {{ existing_json | combine(
           {'new_key': 'new_value'},
           {'config': {'nested_key': 'nested_value'}},
           recursive=True
         ) | to_nice_json }}
    dest: /path/to/updated.json

# Transform JSON structure
- name: Transform JSON data
  ansible.builtin.set_fact:
    transformed_json: >
      {{ original_json | json_query('items[*].{
           id: id,
           name: name,
           status: attributes.status
         }') }}

Text File Operations

Reading Text Files

# Read entire text file
- name: Load text file content
  ansible.builtin.set_fact:
    file_content: "{{ lookup('file', 'input.txt') }}"

# Read file line by line
- name: Read file lines
  ansible.builtin.command: cat /path/to/file.txt
  register: file_lines
  changed_when: false

- name: Process file lines
  ansible.builtin.set_fact:
    processed_lines: "{{ file_lines.stdout_lines }}"

Writing Text Files

# Write simple text file
- name: Create text file
  ansible.builtin.copy:
    content: "{{ text_content }}"
    dest: /path/to/output.txt
    mode: '0644'

# Append to text file
- name: Append to file
  ansible.builtin.lineinfile:
    path: /path/to/file.txt
    line: "{{ new_line }}"
    create: yes

# Insert line at specific position
- name: Insert line after match
  ansible.builtin.lineinfile:
    path: /path/to/file.txt
    line: "{{ new_line }}"
    insertafter: "^# Configuration section"
    create: yes

Text File Manipulation

# Replace in file
- name: Replace text in file
  ansible.builtin.replace:
    path: /path/to/file.txt
    regexp: '^(#\s*)?parameter=.*$'
    replace: 'parameter={{ new_value }}'

# Remove lines matching pattern
- name: Remove matching lines
  ansible.builtin.lineinfile:
    path: /path/to/file.txt
    regexp: '^#.*$'
    state: absent

# Process file with multiple modifications
- name: Multiple file modifications
  ansible.builtin.blockinfile:
    path: /path/to/file.txt
    marker: "# {mark} ANSIBLE MANAGED BLOCK"
    block: |
      # Configuration added {{ ansible_date_time.iso8601 }}
      parameter1={{ value1 }}
      parameter2={{ value2 }}

Configuration File Operations

INI File Handling

# Modify INI file
- name: Update INI configuration
  ansible.builtin.ini_file:
    path: /etc/app/config.ini
    section: database
    option: host
    value: "{{ db_host }}"
    create: yes

# Multiple INI changes
- name: Configure multiple INI options
  ansible.builtin.ini_file:
    path: /etc/app/config.ini
    section: "{{ item.section }}"
    option: "{{ item.option }}"
    value: "{{ item.value }}"
  loop:
    - { section: 'database', option: 'host', value: "{{ db_host }}" }
    - { section: 'database', option: 'port', value: "{{ db_port }}" }
    - { section: 'api', option: 'key', value: "{{ api_key }}" }

Properties File Handling

# Update Java properties file
- name: Set property value
  ansible.builtin.lineinfile:
    path: /path/to/application.properties
    regexp: '^{{ item.key }}='
    line: '{{ item.key }}={{ item.value }}'
    create: yes
  loop:
    - { key: 'spring.datasource.url', value: "{{ db_url }}" }
    - { key: 'spring.datasource.username', value: "{{ db_user }}" }

Advanced File Operations

File Templates

# Template with conditionals
- name: Generate complex configuration
  ansible.builtin.template:
    src: complex_template.j2
    dest: /etc/app/config.conf
  vars:
    template_data:
      environment: production
      features:
        - name: feature1
          enabled: true
        - name: feature2
          enabled: false

# Template content (complex_template.j2)
{% for feature in template_data.features %}
{% if feature.enabled %}
enable_{{ feature.name }}=true
{% else %}
enable_{{ feature.name }}=false
{% endif %}
{% endfor %}

File Transformations

# Transform file content
- name: Transform configuration
  ansible.builtin.template:
    src: transform.j2
    dest: /path/to/output.conf
  vars:
    transform_rules:
      - match: '^#\s*Port\s+\d+'
        replace: 'Port {{ ssh_port }}'
      - match: '^#\s*PermitRootLogin\s+\w+'
        replace: 'PermitRootLogin no'

Backup and Restore

# Backup files before modification
- name: Backup configuration
  ansible.builtin.copy:
    src: "{{ item }}"
    dest: "{{ item }}.bak"
    remote_src: yes
    force: no
  loop:
    - /etc/app/config.yml
    - /etc/app/settings.json

# Restore from backup
- name: Restore configuration
  ansible.builtin.copy:
    src: "{{ item }}.bak"
    dest: "{{ item }}"
    remote_src: yes
    force: yes
  loop:
    - /etc/app/config.yml
    - /etc/app/settings.json
  when: restore_needed | bool

Best Practices

  1. File Permissions ```yaml
  2. name: Ensure secure file permissions ansible.builtin.file: path: "{{ item }}" mode: '0600' owner: root group: root loop:

    • /etc/app/secrets.yml
    • /etc/app/credentials.json ```
  3. Error Handling ```yaml

  4. name: Safely modify files block:

    • name: Update configuration ansible.builtin.template: src: config.j2 dest: /etc/app/config.yml rescue:
    • name: Restore backup on failure ansible.builtin.copy: src: /etc/app/config.yml.bak dest: /etc/app/config.yml remote_src: yes when: backup_exists | bool ```
  5. Validation ```yaml

  6. name: Validate configuration block:

    • name: Check YAML syntax ansible.builtin.command: python -c "import yaml; yaml.safe_load(open('/etc/app/config.yml'))" changed_when: false

    • name: Verify JSON format ansible.builtin.command: jq '.' /etc/app/config.json changed_when: false ```

  7. Documentation ```yaml

  8. name: Add file documentation ansible.builtin.blockinfile: path: "{{ item }}" marker: "# {mark} ANSIBLE MANAGED CONFIGURATION" insertbefore: BOF block: | # Configuration managed by Ansible # Last modified: {{ ansible_date_time.iso8601 }} # Do not edit manually loop:
    • /etc/app/config.yml
    • /etc/app/settings.json ```