Ansible
Run command with JSON output, save output to variable, show varialbe
- name: Localhost | Yandex Cloud Create network
ansible.builtin.command: "yc vpc network create --name network-01 --format json"
register: network_created
- name: Localhost | Set fact
ansible.builtin.set_fact:
network_created_json: "{{ network_created.stdout | from_json }}"
- name: Print fact
ansible.builtin.debug:
msg: "Created {{ network_created_json['name'] }}"
Ansible restart service with specific name
- name: PHP| Restart services
ansible.builtin.systemd:
name: "{{ item }}"
state: restarted
loop: "{{ ansible_facts.services | select('search', '(apache|httpd|php)') | list }}"
ignore_errors: true
Ansible sync file between hosts
This task runs on delegate_to host:
- Copies file from local /tmp directory
- Pastes file to remote inventory_hostname host's /opt directory
- name: "Sync database backup from app-test to {{ inventory_hostname }}"
delegate_to: "app-test.company.com"
ansible.builtin.synchronize:
src: "/tmp/app-demo-{{ ansible_date_time.date }}.sql"
dest: "/opt/app/app/db/backups"
verify_host: false
copy_links: True
set_remote_user: False
partial: true
rsync_opts:
- "--chown=postgres:postgres"
Ansible debug template deploy
- debug-template.yml playbook
- name: Deploy debug-template.yml.j2 file
hosts: localhost
gather_facts: false
tasks:
- name: Copy debug-template.yml.j2 file
template:
src: debug-template.yml.j2
dest: /tmp/debug-template.yml
-
debug-template.yml.j2 jinja2 template
--- FRA Hosts: skip_if_host_in_group: {{ groups | select('match', '^pvefra.*_host_for|esx32_host_for') | list }}
-
Apply Ansible playbook
ansible-playbook debug-template.yml
-
See deployed template
cat /tmp/debug-template.yml
This template selects Ansible groups from the Ansible inventory and make a list
Ansible task copy file from remote host to remote host
- name: Copy Ansible inventory sample for Kubespray
ansible.builtin.copy:
src: /home/ubuntu/kubespray/inventory/sample/
dest: /home/ubuntu/kubespray/inventory/mycluster/
remote_src: yes
Ansible playbook find text in multiple files
This is when there are symbolic links exists. Look for Kerberos keytab path in Apache config. Set file permission on found keytab files.
---
# Apply Ansible playbook
## ansible-playbook do_not_push_playbook.yml
- name: Test playbook. Do not push.
hosts: <Host_Group_From_Ansible_Inventory>
become: True
gather_facts: True
tasks:
- name: Set variable apache_conf_path
set_fact:
apache_conf_path: "/etc/apache2"
when: ansible_os_family == "Debian"
- name: Set variable apache_conf_path
set_fact:
apache_conf_path: "/etc/httpd/conf.d"
when: ansible_os_family == "RedHat"
- name: Find Apache config files for Debian
ansible.builtin.find:
paths: "{{ apache_conf_path }}/sites-enabled"
patterns: '*.conf'
follow: true
recurse: true
file_type: any
register: deb_conf_files
when: ansible_os_family == "Debian"
- name: Find Apache config files for RedHat
ansible.builtin.find:
paths: "{{ apache_conf_path }}"
patterns: '*.conf'
follow: true
recurse: true
file_type: any
register: rh_conf_files
when: ansible_os_family == 'RedHat'
- name: Combine conf files results
set_fact:
conf_files: "{{ (deb_conf_files.files|default([])) + (rh_conf_files.files|default([])) }}"
- name: Read file contents while following symlinks
ansible.builtin.slurp:
src: "{{ item.path }}"
register: file_contents
loop: "{{ conf_files }}"
- name: Find keytab paths
set_fact:
keytab_path: "{{ (item.content | b64decode | regex_findall('\\s*Krb5KeyTab\\s*(\\S*)', ignorecase=True)) }}"
loop: "{{ file_contents.results }}"
register: keytab_paths_set
- name: Combine results into list (remove empty elements and select unique)
set_fact:
keytab_paths: "{{ keytab_paths_set.results | map(attribute='ansible_facts.keytab_path') | flatten | reject('none') | unique | list }}"
- name: Print fact keytab_paths
ansible.builtin.debug:
msg: "{{ keytab_paths }}"
- name: Grant access of keytab file to Apache group for Debian
ansible.builtin.file:
path: "{{ item }}"
owner: "root"
group: "www-data"
mode: "0640"
loop: "{{ keytab_paths }}"
when: ansible_os_family == "Debian"
- name: Grant access of keytab file to Apache group for RedHat
ansible.builtin.file:
path: "{{ item }}"
owner: "root"
group: "apache"
mode: "0640"
loop: "{{ keytab_paths }}"
when: ansible_os_family == "RedHat"
Ansible RESP API HTTP request with authentication
- name: Authorize and move build-agent to TeamCity's server pool
ansible.builtin.uri:
url: "https://{{ teamcity_server }}/app/rest/agents/{{ item }}/authorized"
method: PUT
return_content: true
headers:
Authorization: "Bearer {{ auth_token }}"
Content-Type: text/plain
body: "true"
force_basic_auth: true
status_code: 200
validate_certs: true
loop: "{{ tcagent_name }}"
delegate_to: localhost
Ansible Jinja global variable
Ansible uses Jinja for templates. It supports loops. Variables inside a loop are all local. Variable assignment in loop is cleared at the end of the iteration and cannot outlive the loop scope. When a variable is changed inside the loop, the scope of the variable stays local, and once the loop ends the original value of the variable is restored. That’s even true for variables which are created outside the loop.
But since version 2.10 you can use namespaces:
{% set ns = namespace(beds=0) %}
{% for room in house %}
{% if room.has_bed %}
{% set ns.beds = ns.beds + 1 %}
{% endif %}
{% endfor %}
{{ house.address }} has {{ ns.beds }} beds.
In this case beds
variable is in global scope and will keep changes after loop is done.
Ansible include variables specific for Linux distribution
First, add Debian.yml or RedHat.yml in vars
directory of the Ansible role
Then add task to import the variables:
- ansible.builtin.include_vars:
file: "{{ ansible_os_family }}.yml"
Ansible include tasks specific for Linux distribution
First, add Debian.yml or RedHat.yml in tasks
directory of the Ansible role
Then add task to import the tasks:
- name: extra tasks OS based
ansible.builtin.include_tasks:
file: "{{ ansible_os_family }}.yml"
For example: - roles/example/tasks/main.yml
- name: Install the correct web server for RHEL
import_tasks: redhat.yml
when: ansible_facts['os_family']|lower == 'redhat'
- name: Install the correct web server for Debian
import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian'
- name: Install web server
ansible.builtin.yum:
name: "httpd"
state: present
- name: Install web server
ansible.builtin.apt:
name: "apache2"
state: present
Ansible validate variable for invalid characterds
- name: Validate variable
ansible.builtin.fail:
msg: "Invalid entry found in variable: {{ variable }}"
when:
- variable is defined
- variable | length > 0
- not variable | select('search', '[^.0-9:]') | list | length == 0
Ansible template variable from host_vars
- host_vars/postgresql.yml
postgresql_users: - name: "dbuser" password: "secretpassword" db: "dbname"
- roles/template/template.j2
keyname={{ postgresql_users | selectattr('name', 'equalto', 'dbuser') | map(attribute='password') | first }}
Components Breakdown:
1. {{ ... }}
: This syntax is used in Jinja2 templates to denote an expression that should be evaluated and replaced with its result.
2. postgresql_users
: This is expected to be a list of dictionaries (Ansible variables) where each dictionary contains details about a PostgreSQL user. For example:
```
postgresql_users:
- name: dbuser
password: secure_password_123
- name: analytics
password: another_password
```
-
selectattr('name', 'equalto', 'dbuser')
: This filter selects the elements from the postgresql_users list where the name attribute is equal to 'dbuser'. In our example, it will select the following dictionary:{ 'name': 'dbuser', 'password': 'secure_password_123' }
-
map(attribute='password')
: This filter applies to the selected elements. It extracts the value of the password attribute from the filtered list. From our selected dictionary, this results in:[ 'secure_password_123' ]
-
first
: This filter returns the first item in the resulting sequence from the previous operation. Since our sequence only has one item, it simply returns:'secure_password_123'
Ansible role vars directory
Variables defined in the vars directory of a role have a higher precedence than those defined in host_vars. This means that host_vars cannot override variables that are set in the vars directory of a role.