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
- File Permissions ```yaml
-
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 ```
-
Error Handling ```yaml
-
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 ```
-
Validation ```yaml
-
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 ```
-
-
Documentation ```yaml
- 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 ```