Ansible

From Omnia
Jump to navigation Jump to search

Ansible

Install

Sample 2.10.7 version:

sudo pip3 uninstall ansible ansible-base ansible-core
sudo pip3 install ansible==2.10.7

Useful Variables

Useful magic variables

Discovering variables: facts and magic variables
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_vars_facts.html

To see the raw information gathered:

ansible <hostname> -m ansible.builtin.setup

Remember these:

{{ ansible_architecture }} == "x86_64"
{{ ansible_default_ipv4.address }} == "x.x.x.x"
{{ ansible_default_ipv4.interface }} == "eth0"
   "ansible_distribution": "CentOS",
   "ansible_distribution_file_parsed": true,
   "ansible_distribution_file_path": "/etc/redhat-release",
   "ansible_distribution_file_variety": "RedHat",
   "ansible_distribution_major_version": "7",
   "ansible_distribution_release": "Core",
   "ansible_distribution_version": "7.5.1804",
   "ansible_kernel": "3.10.0-862.14.4.el7.x86_64",
   "ansible_machine": "x86_64",
   "ansible_env": {
       "HOME": "/home/zuul",
       "PATH": "/usr/local/bin:/usr/bin",
       "USER": "zuul",
   "ansible_fqdn": "centos-7-rax-dfw-0003427354",
   "ansible_hostname": "centos-7-rax-dfw-0003427354",
   "ansible_domain": "",
   "ansible_lsb": {
       "codename": "Core",
       "description": "CentOS Linux release 7.5.1804 (Core)",
       "id": "CentOS",
       "major_release": "7",
       "release": "7.5.1804"
   "ansible_memfree_mb": 7709,
   "ansible_nodename": "centos-7-rax-dfw-0003427354",
   "ansible_os_family": "RedHat"

OS Version

{{ansible_distribution}} - Debian / Ubuntu
{{ansible_distribution_release}} - buster / focal
{{ansible_distribution_version}} - 10 / 18.04
{{ansible_distribution_major_version}} - 10 / 18

copy

copy - Copies files to remote locations — Ansible Documentation https://docs.ansible.com/ansible/2.6/modules/copy_module.html

- name: example copying file with owner and permissions
  copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: 0644
- name: example copying file with owner and permissions
  copy: src=foo.conf dest=/etc/foo.conf

Ansible Misc

~/metricbeat/metricbeat.yml

metricbeat.modules:
- module: system
  metricsets:
    - cpu
    - filesystem
    - memory
    - network
    - process
  enabled: true
  period: 10s
  processes: ['.*']
  cpu_ticks: false
- module: docker
  metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"]
  hosts: ["unix:///var/run/docker.sock"]
  period: 100s
output.elasticsearch:
  hosts: ["test.oeey.com:9200"]
setup.kibana:
  host: "test.oeey.com:8081"

---

Working With Playbooks — Ansible Documentation - https://docs.ansible.com/ansible/latest/user_guide/playbooks.html

Intro to Playbooks — Ansible Documentation - https://docs.ansible.com/ansible/2.5/user_guide/playbooks_intro.html

YAML Syntax — Ansible Documentation - https://docs.ansible.com/ansible/2.5/reference_appendices/YAMLSyntax.html#yaml-syntax

---

Here’s a playbook that contains just one play:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service:
      name: httpd
      state: started
      enabled: yes
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted

YAML

See YAML

YAML Syntax — Ansible Documentation - https://docs.ansible.com/ansible/2.5/reference_appendices/YAMLSyntax.html#yaml-syntax

Raspberry Pi

How to Setup the Raspberry Pi 3 Using Ansible | Datahovel - https://datahovel.com/2016/03/20/how-to-setup-the-raspberry-pi-using-ansible/

ansible-playground/raspbian-bootstrap at master · Condla/ansible-playground · GitHub - https://github.com/Condla/ansible-playground/tree/master/raspbian-bootstrap

Automating Raspberry Pi setup with Ansible - http://www.hietala.org/automating-raspberry-pi-setup-with-ansible.html

--

Raspbian Bootstrap

This is simple ansible playbook to setup one or more of your Raspberry Pis running a fresh Raspbian installation on it. I used the imag e from March 2016 available to download from the official website. This playbook bootstraps your Raspberry Pi 3 to be used over your WPA

Wifi network, if you provide a correct SSID and password as a playbook variable. It will additionally install software required to use

Amazon's AWS IoT NodeJS SDK. (http://docs.aws.amazon.com/iot/latest/developerguide/iot-device-sdk-node.html).

After the first time boot of your Raspberry Pi, follow these few steps in order to bootstrap your machine.

  • Install Ansible and Git on your "Controller" machine.
  • Clone this git repository.
  • Configure hostname/IP address in the "hosts" file
  • Unfortunately: Login to Raspi and expand SD card with "sudo raspi-config" -
 This will be automated in the future!
  • Exectute playbook
# Install Ansible and Git on the machine.
sudo apt-get install python-pip git python-dev sshpass
sudo pip install ansible

# Clone this repo:
git clone https://github.com/Condla/ansible-playground.git
cd ansible-playground/raspbian-bootstrap/

# Configure IP address in "hosts" file. If you have more than one
# Raspberry Pi, add more lines and enter details

# Execute playbook
./playbook.yml


Small sample:

files: ansible.cfg files/ hosts playbook.yml README.md templates/

ansible.cfg:

[defaults]
hostfile = ./hosts
inventory = ./hosts

hosts:

[local]
localhost

playbook.yml:

#!/usr/bin/env ansible-playbook
---
- hosts: local
  gather_facts: yes
  connection: local
  vars:

    packages_to_install: [
        build-essential, tree,
        ]

    pip_packages_to_install: [ pip, pySerial ]

  tasks:

    - name: install ubuntu packages
      apt: pkg={{ item }} state=present
      with_items: '{{packages_to_install}}'
      become: yes

    - name: install python modules
      pip: name={{ item }}
      with_items: '{{pip_packages_to_install}}'
      become: yes

---

helloworld-playbook.yml

#!/usr/bin/env ansible-playbook

---
- name: This is a hello-world example
  hosts: local
  tasks:
  - name: Create a file called '/tmp/testfile.txt' with the content 'hello world'.
    copy: content="hello world\n" dest=/tmp/testfile.txt

Ansible – A “hello world” Playbook – Codingbee - https://codingbee.net/tutorials/ansible/ansible-a-hello-world-playbook

To avoid the "no host matching" use:

hosts: localhost

Hello World

Ansible – A “hello world” Playbook – Codingbee - https://codingbee.net/tutorials/ansible/ansible-a-hello-world-playbook

tower-example/helloworld.yml at master · ansible/tower-example · GitHub - https://github.com/ansible/tower-example/blob/master/helloworld.yml

---
- name: Hello World!
  # hosts: all
  hosts: localhost
 
  tasks:
 
  - name: Hello World!
    shell: echo "Hi! Ansible is working."

Inventory

ini version:

# inventory/hosts:
[webservers]
web1.example.com

[fileservers]
file1.example.com

[all:children]
webservers
filservers

---

yaml version:

---
# inventory/hosts.yaml

webservers:
  children:
    web11.example.com

fileservers:
  children:
     file1.example.com

all:
  children:
    webservers:
      children:
        more_webservers
          children:
            even_more_webservers
    fileservers:

Embedded Inventory

Crazy embedded inventory option:

https://stackoverflow.com/questions/47159541/ansible-playbook-load-internal-inventory-file-while-running

- name: 'Parse dictionary hosts'
  hosts: 'localhost'
  vars:
    my_parsed_hosts:
      controller-a:
        name: 'controller-node'
        ansible_user: 'ubuntu'
        ansible_host: '10.0.10.1'
        my_variable: false
      worker-b:
        name: 'worker-node'
        ansible_user: 'ubuntu'
        ansible_host: '127.0.0.1'
        my_variable: false
      aws-worker-custom-c:
        name: 'aws-worker-custom'
        ansible_user: 'ubuntu'
        ansible_host: '192.168.42.128'
        my_variable: true
  tasks:
    - name: 'Add new hosts to this playbook from dictionary'
      ansible.builtin.add_host:
        name: '{{ item.value.name }}'
        ansible_user: '{{ item.value.ansible_user }}'
        ansible_host: '{{ item.value.ansible_host }}'
        my_variable: '{{ item.value.my_variable }}'
        groups:
          - 'worker_nodes'
          - 'grafana'
      with_dict: '{{ my_parsed_hosts }}'
      when:
        - ('worker_nodes' not in groups)
        - ('worker' in item.value.name)
        - (item.value.name not in ansible_play_hosts_all)

- name: 'Use parsed dictionary hosts'
  hosts: 'worker_nodes'
  tasks:
    - name: 'Print debug welcome message'
      ansible.builtin.debug:
        msg: >
          Node {{ ansible_host }} says welcome!

Inventory Host Vars

sample inventory.ini:

[lab]
unit1  description="system number 1"

[lab:vars]
somevar="another var"
anothervar="another var"

to use in playbook:

 {{ description }} and {{ somevar }}, etc


See:

Run Task when node in group

Run when in specific group: [1]

when: inventory_hostname in groups["appservers"]
when: ( inventory_hostname in groups["appservers"] or
        inventory_hostname in groups["webservers"] )

Logging

ansible.cfg:

[defaults]
log_path = /var/log/ansible.log

Via ENV:

export ANSIBLE_LOG_PATH=~/ansible.log

Enable debug:

export ANSIBLE_DEBUG=True

Set Ansible Username and Password

NOTE: Before Ansible 2.0 "ansible_user" was "ansible_ssh_user". "ansible_password" or "ansible_pass" or "ansible_ssh_pass" or do all work?? " Option 1 - Inventory:

[master]
192.168.1.10 ansible_connection=ssh ansible_ssh_user=vagrant ansible_ssh_pass=vagrant

Option 2 - Inventory Vars:

[all:vars]
ansible_connection=ssh
ansible_port=22
ansible_user=vagrant
ansible_pass=vagrant ?? # or ansible_ssh_pass=vagrant  # or ansible_password=vagrant ?

Option 3 - group_vars/all:

---
# file: group_vars/all
ansible_connection: ssh 
ansible_ssh_user: vagrant 
ansible_ssh_pass: vagrant

Option 4 - extra-vars

ansible --module-name ping \
 --extra-vars 'ansible_user=domain\user ansible_password=PASSWORD' \ 
 --inventory 10.10.6.184, all

ref:

Apt

apt - Manages apt-packages — Ansible Documentatio - https://docs.ansible.com/ansible/latest/modules/apt_module.html

- name: Remove "foo" package
  apt:
    name: foo
    state: absent
- name: Install a list of packages
  apt:
    name: "{{ packages }}"
  vars:
    packages:
    - foo
    - foo-tools

name inline list: [2]

- name: Install MongoDB
  apt:
    pkg:
      - mongodb-org-server
      - mongodb-org-mongos
      - mongodb-org-shell
      - mongodb-org-tools 
    state: latest
    update_cache: true
vars:
  mongo_packages:
   - mongodb-org-server
   - mongodb-org-mongos
   - mongodb-org-shell
   - mongodb-org-tools

- name: Install mongodb
  yum:
    name: "{{ item }}-{{ mongo_version }}"
    state: present
  with_items: "{{ mongo_packages }}"
  notify: Restart MongoDB



- name: Install mongodb
  yum:
    name: "{{ item }}"
    state: present
  with_items: "{{ mongo_packages }}"
  notify: Restart MongoDB
  vars:
    mongo_packages:
     - mongodb-org-server
     - mongodb-org-mongos
     - mongodb-org-shell
     - mongodb-org-tools

Pip

Ansible Pip Module - Managing Python Packages - Ansible Tutorials - http://www.mydailytutorials.com/ansible-pip-module/

pip - Manages Python library dependencies — Ansible Documentation - https://docs.ansible.com/ansible/2.6/modules/pip_module.html

  tasks:
  - name: Installing NumPy python library using Ansible pip module
    pip:
      name: NumPy
  tasks:
    - name: Update Pip
      pip:
        name: pip
        state: latest
    - name: Specific fabric
      pip:
        name: fabric<2.0
    - name: More Pip packages
      pip:
        name: python-jenkins jira slackclient

-

pip - Ansible: install multiple Python packages on a single session - Stack Overflow https://stackoverflow.com/questions/31396130/ansible-install-multiple-python-packages-on-a-single-session

  - name: "Install Python Packages: {{ python_packages_to_install }}"
    pip: name={{ item }}
    with_items: "{{ python_packages_to_install }}"
    vars:
      python_packages_to_install:
        - fabric<2.0
        - python-jenkins
        - jira
        - slackclient
        - xmodem
        - pySerial
        - numpy

NFS

mount - Control active and configured mount points — Ansible Documentation - https://docs.ansible.com/ansible/2.5/modules/mount_module.html

  tasks:
  - name: nfs-store5 NFS
    mount:
      name: /nfs-store5
      src: nfs-store5:/wbt
      fstype: nfs
      state: mounted

Dry Run

Dry Run: [1]

ansible-playbook --check playbook.yml

Include Playbook

- include: other.yml

And Include at different levels

  Tasks:
  - include tasks.yml

Create Empty File

- name: ensure file exists
  copy:
    content: ""
    dest: /etc/nologin
    force: no
    group: sys
    owner: root
    mode: 0555

This will touch a file each time (yellow update each time) [2]

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555

With command module:

- name: Create file
  command: touch /path/to/file
  args:
    creates: /path/to/file

Remove File

- name: Clear Pi Warnings
  hosts: localhost
  tasks:

  - name: Remove pi password warning
    file:
      state: absent
      path: /etc/profile.d/sshpwd.sh

  - name: Remove Wifi warning
    file:
      state: absent
      path: /etc/profile.d/wifi-country.sh

Don't Fail on Error

- name: Do not count this as a failure
  ansible.builtin.command: /bin/false
  ignore_errors: true

ref: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_error_handling.html

Windows PATH

- name: Ensure that system32 and Powershell are present on the global system path, and in the specified order
  ansible.windows.win_path:
    elements:
      - '%SystemRoot%\system32'
      - '%SystemRoot%\system32\WindowsPowerShell\v1.0'
- name: Ensure that C:\Program Files\MyJavaThing is not on the current user's CLASSPATH
  ansible.windows.win_path:
    name: CLASSPATH
    elements: C:\Program Files\MyJavaThing
    scope: user
    state: absent

ref: https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_path_module.html

Execute Script

script - Runs a local script on a remote node after transferring it — Ansible Documentation - https://docs.ansible.com/ansible/2.6/modules/script_module.html

# Example from Ansible Playbooks
- script: /some/local/script.sh --some-arguments 1234

# Run a script that creates a file, but only if the file is not yet created
- script: /some/local/create_file.sh --some-arguments 1234
  args:
    creates: /the/created/file.txt

# Run a script that removes a file, but only if the file is not yet removed
- script: /some/local/remove_file.sh --some-arguments 1234
  args:
    removes: /the/removed/file.txt

# Run a script using a executable in a non-system path
- script: /some/local/script
  args:
    executable: /some/remote/executable

# Run a script using a executable in a system path
- script: /some/local/script.py
  args:
    executable: python3

Execute Shell

shell - Execute commands in nodes. — Ansible Documentation - https://docs.ansible.com/ansible/2.5/modules/shell_module.html

- name: Execute the command in remote shell; stdout goes to the specified file on the remote.
  shell: somescript.sh >> somelog.txt

- name: Change the working directory to somedir/ before executing the command.
  shell: somescript.sh >> somelog.txt
  args:
    chdir: somedir/

# You can also use the 'args' form to provide the options.
- name: This command will change the working directory to somedir/ and will only run when somedir/somelog.txt doesn't exist.
  shell: somescript.sh >> somelog.txt
  args:
    chdir: somedir/
    creates: somelog.txt

- name: Run a command that uses non-posix shell-isms (in this example /bin/sh doesn't handle redirection and wildcards together but bash does)
  shell: cat < /tmp/*txt
  args:
    executable: /bin/bash

- name: Run a command using a templated variable (always use quote filter to avoid injection)
  shell: cat {{ myfile|quote }}

# You can use shell to run other executables to perform actions inline
- name: Run expect to wait for a successful PXE boot via out-of-band CIMC
  shell: |
    set timeout 300
    spawn ssh admin@{{ cimc_host }}

    expect "password:"
    send "{{ cimc_password }}\n"

    expect "\n{{ cimc_name }}"
    send "connect host\n"

    expect "pxeboot.n12"
    send "\n"

    exit 0
  args:
    executable: /usr/bin/expect
  delegate_to: localhost

Download File

get_url - Downloads files from HTTP, HTTPS, or FTP to node — Ansible Documentation - https://docs.ansible.com/ansible/2.5/modules/get_url_module.html

- name: Download foo.conf
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    mode: 0440

- name: Download file and force basic auth
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    force_basic_auth: yes

- name: Download file with custom HTTP headers
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    headers: 'key:value,key:value'

- name: Download file with check (sha256)
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    checksum: sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c

- name: Download file with check (md5)
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    checksum: md5:66dffb5228a211e61d6d7ef4a86f5758

- name: Download file from a file path
  get_url:
    url: file:///tmp/afile.txt
    dest: /tmp/afilecopy.txt

Build Program from Source

Using Ansible to Compile NGINX from Sources with Custom Modules - https://medium.com/bigpanda-engineering/using-ansible-to-compile-nginx-from-sources-with-custom-modules-f6e6c6a42493

compile_nginx_from_sources.yml:

---

- name: Compile NGINX from sources
  hosts: webserver
  vars:
    nginx_version: nginx-1.13.4
    nginx_tarball_url: "http://nginx.org/download/{{ nginx_version }}.tar.gz"
    nginx_install_dir: "/tmp/{{ nginx_version }}"
    nginx_sbin_path: "/usr/sbin/nginx"
    nginx_conf_path: "/etc/nginx/nginx.conf"
    nginx_custom_modules: "--with-http_auth_request_module"

  tasks:
  - name: Installing NGINX Dependencies
    become: yes
    apt:
      name: "{{ item }}"
      update_cache: yes
    with_items:
      - libssl-dev
      - zlib1g-dev
      - libpcre3
      - libpcre3-dev
      - unzip

  - name: Downloading NGINX sources
    get_url:
      url: "{{ nginx_tarball_url }}"
      dest: "/tmp/{{ nginx_version }}.tar.gz"
    register: nginx_source

  - name: Unpacking NGINX
    unarchive:
      copy: no
      dest: /tmp/
      src: "{{ nginx_source.dest }}"
    when: nginx_source.changed
    register: nginx_source_unpack

  - name: Create required Nginx dirs
    become: yes
    file:
      path: /etc/nginx
      state: directory
      owner: root
      mode: 0755

  - name: Configuring NGINX source with custom modules
    command: "./configure --sbin-path={{ nginx_sbin_path }} --conf-path={{ nginx_conf_path }} {{ nginx_custom_modules }}"
    args:
      chdir: "{{ nginx_install_dir }}"
    when: nginx_source_unpack|changed
    register: nginx_configure

  - name: Installing NGINX
    become: yes
    shell: make && make install
    args:
      chdir: "{{ nginx_install_dir }}"
    when: nginx_configure|changed

  - name: Creating NGINX conf file
    become: yes
    template:
      src: nginx.conf
      dest: "{{ nginx_conf_path }}"
      owner: "{{ ansible_user }}"
      group: "{{ ansible_user }}"
      mode: 0644

  - name: Installing NGINX init script (service)
    become: yes
    template:
      src: nginx.init
      dest: /etc/init.d/nginx
      owner: root
      group: root
      mode: 0755

  - name: Starting NGINX
    become: yes
    service:
      name: nginx
      state: started

Build tio

tio.yml:

- name: Compile tio from sources
  hosts: localhost
  vars:
    tio_version: v1.30
    tio_install_dir: "/root/.src/tio"
    tio_sbin_path: "/usr/local/bin/tio"

  tasks:
  - name: Git fun
    git:
      name: 'https://github.com/tio/tio.git'
      dest: "{{tio_install_dir}}"
      version: "{{tio_version}}"
    register: tio_git

  - name: Make tio configure
    command: "sh autogen.sh"
    args:
      chdir: "{{ tio_install_dir }}"
      creates: "{{tio_sbin_path}}"
    register: tio_make_configure

  - name: Configuring tio source
    command: "./configure"
    args:
      chdir: "{{ tio_install_dir }}"
    when: tio_make_configure|changed
    register: tio_configure

  - name: Installing tio
    become: yes
    shell: make && make install
    args:
      chdir: "{{ tio_install_dir }}"
    when: tio_configure|changed

Encrypt Files

vault-id:

# single password --vault-id pass
# multiple passwords: --vault-id dev@passwords
 dev: mypassword

Note: vault id can also specify a script! [3]

ansible-playbook --vault-id dev@contrib/vault/vault-keyring-client.py

Create new file:

ansible-vault create --vault-id test@multi_password_file foo.yml

Encrypt existing:

ansible-vault encrypt foo.yml bar.yml baz.yml
ansible-vault encrypt --vault-id project@prompt foo.yml bar.yml baz.yml

View encrypted file:

ansible-vault view foo.yml bar.yml baz.yml

Decrypt file:

ansible-vault decrypt foo.yml bar.yml baz.yml

Always use a password file:

alias ansible='ansible-playbook --vault-id /etc/ansible/password'
alias ansible-playbook='ansible-playbook --vault-id /etc/ansible/password'


ref: [3]

Encrypt Variable

encrypt_string      Encrypt a string

Usage:

ansible-vault encrypt_string <password_source> '<string_to_encrypt>' --name '<string_name_of_variable>'

Example: (encrypt 'foobar' using only password in a_password_file)

ansible-vault encrypt_string --vault-password-file a_password_file 'foobar' --name 'the_secret'
the_secret: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      62313365396662343061393464336163383764373764613633653634306231386433626436623361
      6134333665353966363534333632666535333761666131620a663537646436643839616531643561
      63396265333966386166373632626539326166353965363262633030333630313338646335303630
      3438626666666137650a353638643435666633633964366338633066623234616432373231333331
      6564

Encrypt using vault ID 'dev' in password file:

ansible-vault encrypt_string --vault-id dev@a_password_file 'foooodev' --name 'the_dev_secret'

Encrypt as passed in:

echo -n 'letmein' | ansible-vault encrypt_string --vault-id dev@a_password_file --stdin-name 'db_password'

To view the encrypted variable in vars file:

ansible localhost -m ansible.builtin.debug -a var="new_user_password" -e "@vars.yml" --vault-id dev@a_password_file
# ansible localhost -m debug -a var="new_user_password" -e "@vars.yml" --ask-vault-pass

Embedding in playbook: (not the recommended way!)

- name: Some playbook
  hosts: [myhosts]
  vars:
    ansible_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          3734356233663562...

NOTE: Note sure how to view encrypted var embedded inside a playbook??

ref: https://docs.ansible.com/ansible/latest/vault_guide/vault_encrypting_content.html

Ansible Lint

Install:

pip install ansible-lint

Use:

ansible-lint [playbook]

AWX

AWX provides a web-based user interface, REST API, and task engine built on top of Ansible. It is the upstream project for Tower, a commercial derivative of AWX.

https://github.com/ansible/awx

AWX stands for "Ansible WorX" a play on AnsibleWorks.

Ref: [4] [5]

--

AWX in Ansible AWX stands for Ansible WorX

It is found inside this commit https://github.com/ansible/awx/commit/5c6895e6065a81f4483dfb6bc7650706f8866e1e

They used an X instead of ks

ref: https://stackoverflow.com/questions/63509580/ansible-awx-what-awx-stands-for

Galaxy Framework

Galaxy Framework Role Initalize

ansible-galaxy init [role]

Example:

ansible-galaxy init linux-common
`-- linux-common
    |-- README.md
    |-- defaults
    |   `-- main.yml
    |-- files
    |-- handlers
    |   `-- main.yml
    |-- meta
    |   `-- main.yml
    |-- tasks
    |   `-- main.yml
    |-- templates
    |-- tests
    |   |-- inventory
    |   `-- test.yml
    `-- vars
        `-- main.yml

See https://docs.ansible.com/ansible/latest/cli/ansible-galaxy.html#collection-init

Galaxy Community Collections

Install:

Install docker community - https://galaxy.ansible.com/ui/repo/published/community/docker/

ansible-galaxy collection install community.docker

Download:

Download docker community - https://galaxy.ansible.com/ui/repo/published/community/docker/

ansible-galaxy collection download community.docker
Downloads into "collections" folder
collections/community-docker-3.12.1.tar.gz
collections/community-library_inventory_filtering_v1-1.0.1.tar.gz
collections/requirements.yml
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/community-docker-3.12.1.tar.gz
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/community-library_inventory_filtering_v1-1.0.1.tar.gz
requirements.yml
# cat requirements.yml
collections:
- name: community-docker-3.12.1.tar.gz
  version: 3.12.1
- name: community-library_inventory_filtering_v1-1.0.1.tar.gz
  version: 1.0.1

To use archive with ansible project:

ansible.cfg:

[defaults]
collections_paths = collections

Extract community-docker-3.12.1.tar.gz into /collections/ansible_collections/community/docker/

Collections structure:

/collections/
  /ansible_collections/
    /ansible/
      /posix/
      /windows/
    /chocolatey/
      /chocolatey/
    /community/
      /crypto/
      /docker/
      /general/
      /mysql/
      /windows/
    /devsec/
      /hardening/
    /kubernetes/
      /core/
- name: docker_login_artifactory
  docker_login:
    registry: "{{ item }}"
    username: "{{ artifactory_api_username }}"
    password: "{{ artifactory_api_key }}"
    reauthorize: yes
  with_items:
    - "{{ docker_artifactory_cache }}"
    - "{{ docker_artifactory_registry }}"
  tags:
    - docker_login_artifactory

Sample Ansible Simple Playbook

inventory:

[webservers]
server1
server2

[databases]
server3
server4

playbook.yml:

---
- name: Update web servers
  hosts: webservers
  remote_user: root

  tasks:
  - name: Ensure apache is at the latest version
    ansible.builtin.yum:
      name: httpd
      state: latest

  - name: Write the apache config file
    ansible.builtin.template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf

- name: Update db servers
  hosts: databases
  remote_user: root

  tasks:
  - name: Ensure postgresql is at the latest version
    ansible.builtin.yum:
      name: postgresql
      state: latest

  - name: Ensure that postgresql is started
    ansible.builtin.service:
      name: postgresql
      state: started

Run:

ansible-playbook -i inventory playbook.yml

ref: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html

Sample Ansible Setup

ansible.cfg

inventory/
  systems.ini
  #or
  systems.yml

group_vars/
  group1.yml

host_vars/
  hostname1.yml

playbook1.yml
# or - if do this you will need to modify the roles_path in ansible.cfg
# playbooks/
#   playbook1.yml

roles/
  role1/
    ....
    tasks/
      main.yml

ansible.cfg:

[defaults]
inventory = inventory

inventory/systems: (ini format, but no .ini extension)

[linux]
host1
host2

inventory/systems.yml:

linux:
  hosts:
    host1
    host2

playbook1.yml:

- hosts: [linux]
  roles:
    - linux-common

roles/linux-common/tasks/main.yml:

- import_tasks: update_apt.yml

roles/linux-common/tasks/update_apt.yml:

# Ref: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html

- name: Run an apt-get update [tag - apt_update]
  ansible.builtin.apt:
    update_cache: yes
  tags:
    - apt_update

- name: Run an apt-get upgrade [tag - apt_upgrade]
  ansible.builtin.apt:
    update_cache: yes
    upgrade: yes
  tags:
    - apt_upgrade

Run examples:

ansible-playbook playbook1.yml
ansible-playbook playbook1.yml -t apt_update

See https://docs.ansible.com/ansible/latest/tips_tricks/sample_setup.html

Variable Precedence

Understanding variable precedence

Ansible does apply variable precedence, and you might have a use for it. Here is the order of precedence from least to greatest (the last listed variables override all other variables):

  1. command line values (for example, -u my_user, these are not variables)
  2. role defaults (defined in role/defaults/main.yml) 1
  3. inventory file or script group vars 2
  4. inventory group_vars/all 3
  5. playbook group_vars/all 3
  6. inventory group_vars/* 3
  7. playbook group_vars/* 3
  8. inventory file or script host vars 2
  9. inventory host_vars/* 3
  10. playbook host_vars/* 3
  11. host facts / cached set_facts 4
  12. play vars
  13. play vars_prompt
  14. play vars_files
  15. role vars (defined in role/vars/main.yml)
  16. block vars (only for tasks in block)
  17. task vars (only for the task)
  18. include_vars
  19. set_facts / registered vars
  20. role (and include_role) params
  21. include params
  22. extra vars (for example, -e "user=my_user")(always win precedence)

ref:

Using Variables — Ansible Documentation
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html

keywords