Ansible

Command Meaning default SaltStack equivalent
--check Dry run no dry run test=True
-b, --become run operations with become no password prompting
-K, --ask-become-pass ask for privilege escalation password
--become-method=BECOME_METHOD privilege escalation method to use valid choices: [ sudo su pbrun pfexec doas dzdo ksu runas pmrun enable machinectl sudo sudo
--become-user=BECOME_USER run operations as this user root
Example meaning
ansible-playbook playbook.yml --user=b.dauphin --become-method=su -b -K su b.dauphin + password prompting
ansible-playbook playbook.yml --check --diff --limit 1.2.3.4 Dry run + show only diff + limit inventory to host 1.2.3.4

Examples

cd inventory
ls *.yml | xargs -I % ansible --user=baptiste -i % all -m shell  -a 'grep 8.8.8.8 /etc/resolv.conf || echo MISCONFIGURED'

Specify python interpreter path

ansible 1.2.3.4 -m ping -e 'ansible_python_interpreter=/usr/bin/python3'

list available variables

ansible 10.10.10.10 -m setup

get specific fact

ansible 10.10.10.10 -m setup -a 'filter=ansible_python_version'

Playbook start at a specific task

ansible-playbook --start-at-task="Gather Networks Facts into Variable"
ansible webservers -m service -a "name=httpd state=restarted"
ansible all -m ping -u user1 --private-key /home/baptiste/.ssh/id_rsa

enable usage of operations like < > | &
the remote system has to got the package python-apt

apt install python-apt
- debug: var=ansible_facts
start only specific task
ansible-playbook --tags "docker_login"
Debug ansible playbook
[...]
msg: "{{ lookup('vars', ansible_dns) }}"
[...]
[...]
- name: Gather Networks Facts into Variable
  setup:
  register: setup

- name: Debug Set Facts
  debug:
    var: setup.ansible_facts.ansible_python_version

Variables

Inside Playbook


---
- hosts: webservers
  vars:
    syslog_protocol_lvl_4: udp
    syslog_port: 514
    ansible_python_interpreter: /bin/python
    ansible_ssh_user: root

Cli override

ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

override playbook-defined variables (keep your playbook unmodified)

ansible-playbook lvm.yml --extra-vars "host=es_data_group remote_user=b.dauphin" -i ../inventory/es_data_staging.yml

Full doc of passing-variables-on-the-command-line

Precedence

Where should I put a variable ? Here is the order of precedence from least to greatest (the last listed variables winning prioritization):

  • command line values (eg “-u user”)
  • role defaults [1]
  • inventory file or script group vars [2]
  • inventory group_vars/all [3]
  • playbook group_vars/all [3]
  • inventory group_vars/* [3]
  • playbook group_vars/* [3]
  • inventory file or script host vars [2]
  • inventory host_vars/* [3]
  • playbook host_vars/* [3]
  • host facts / cached set_facts [4]
  • play vars
  • play vars_prompt
  • play vars_files
  • role vars (defined in role/vars/main.yml)
  • block vars (only for tasks in block)
  • task vars (only for the task)
  • include_vars
  • set_facts / registered vars
  • role (and include_role) params
  • include params
  • extra vars (always win precedence)

Lookup plugin

You can load data from various sources like : k8s, ini, file, vault, mongoDB, env var, etcd To get list of available lists of lookup plugins, you can use below command: –

ansible-doc -t lookup -l

Example

ansible_become_pass: "{{ lookup('hashi_vault', 'secret=secret/data/path/to/secret'+ ':data url=https://vault.example.com validate_certs=true cacert=/etc/ssl/certs/ca-certificates.crt').root}}"

SaltStack

Key management

--list=$ARG definition
pre,un,unaccepted list unaccepted/unsigned keys.
acc or accepted list accepted/signed keys.
rej or rejected list rejected keys
den or denied list denied keys
all list all above keys

Targeting

salt -S 192.168.40.20 test.version
salt -S 192.168.40.0/24 test.version

Compound match

salt -C 'S@10.0.0.0/24 and G@os:Debian' test.version
salt -C '( G@environment:staging or G@environment:production ) and G@soft:redis*' test.ping

full doc Compound matchers

Various useful module

salt '*' network.ip_addrs
salt '*' cmd.run
salt '*' state.Apply
salt '*' test.ping
salt '*' test.version
salt '*' grains.get
salt '*' grains.item
salt '*' grains.items
salt '*' grains.ls

Diff

Diff between 2 servers

salt-run survey.diff '*' cmd.run "ls /home"

Saltutils

Signal the minion to refresh the pillar data.

salt '*' saltutil.refresh_pillar

synchronizes custom modules, states, beacons, grains, returners, output modules, renderers, and utils.

salt '*' saltutil.sync_all

Forcibly removes all caches on a minion. WARNING: The safest way to clear a minion cache is by first stopping the minion and then deleting the cache files before restarting it.
soft way

salt '*' saltutil.clear_cache

sure way

systemctl stop salt-minion \
&& rm -rf /var/cache/salt/minion/ \
&& systemctl start salt-minion

Grains

Common

    - SSDs
    - biosreleasedate
    - biosversion
    - cpu_flags
    - cpu_model
    - cpuarch
    - disks
    - dns
    - domain
    - fqdn
    - fqdn_ip4
    - fqdn_ip6
    - gid
    - gpus
    - groupname
    - host
    - hwaddr_interfaces
    - id
    - init
    - ip4_gw
    - ip4_interfaces
    - ip6_gw
    - ip6_interfaces
    - ip_gw
    - ip_interfaces
    - ipv4
    - ipv6
    - kernel
    - kernelrelease
    - kernelversion
    - locale_info
    - localhost
    - lsb_distrib_codename
    - lsb_distrib_id
    - machine_id
    - manufacturer
    - master
    - mdadm
    - mem_total
    - nodename
    - num_cpus
    - num_gpus
    - os
    - os_family
    - osarch
    - oscodename
    - osfinger
    - osfullname
    - osmajorrelease
    - osrelease
    - osrelease_info
    - path
    - pid
    - productname
    - ps
    - pythonexecutable
    - pythonpath
    - pythonversion
    - saltpath
    - saltversion
    - saltversioninfo
    - selinux
    - serialnumber
    - server_id
    - shell
    - swap_total
    - systemd
    - uid
    - username
    - uuid
    - virtual
    - zfs_feature_flags
    - zfs_support
    - zmqversion

grains containing 'os'

    os:
        Debian
    os_family:
        Debian
    osarch:
        amd64
    oscodename:
        stretch
    osfinger:
        Debian-9
    osfullname:
        Debian
    osmajorrelease:
        9
    osrelease:
        9.5
    osrelease_info:
        - 9
        - 5

Upgrade Salt-Minion

State format

Upgrade Salt-Minion:
  cmd.run:
    - name: |
        exec 0>&- # close stdin
        exec 1>&- # close stdout
        exec 2>&- # close stderr
        nohup /bin/sh -c 'salt-call --local pkg.install salt-minion && salt-call --local service.restart salt-minion' &
    - onlyif: "[[ $(salt-call --local pkg.upgrade_available salt-minion 2>&1) == *'True'* ]]"

Bash script format

Upgrade salt-minion bash script

Useful exemple

Netcat
salt -C "minion.local or minion2.local" \
> cmd.run "docker run debian /bin/bash -c 'http_proxy=http://10.100.100.100:1598 apt update ; http_proxy=http://10.100.100.100:1598 apt install netcat -y ; nc -zvn 10.3.3.3 3306' | grep open"
minion.local:

    WARNING: apt does not have a stable CLI interface. Use with caution in scripts.


    WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

    debconf: delaying package configuration, since apt-utils is not installed
    (UNKNOWN) [10.3.3.3] 3306 (?) open

minion2.local:

    WARNING: apt does not have a stable CLI interface. Use with caution in scripts.


    WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

    debconf: delaying package configuration, since apt-utils is not installed
    (UNKNOWN) [10.3.3.3] 3306 (?) open
MySQL connexion

Will print you the GRANTS for the user

echo "enter your password" ; read -s password ; \
salt "*" \
cmd.run "docker pull imega/mysql-client ; docker run --rm imega/mysql-client mysql --host=10.10.10.10 --user=b.dauphin --password=$password --database=db1 --execute='SHOW GRANTS FOR CURRENT_USER();'" \
env='{"http_proxy": "http://10.10.10.10:9999"}'

Events

Salt provides a runner that displays events in real-time as they are received on the Salt master.

salt-run state.event pretty=True

Sources

Jinja2

Filter list

https://www.tailored.cloud/devops/how-to-filter-and-map-lists-in-ansible/

Playing with empty lines

{%   %}
{%-  %}
{%  -%}
{%- -%}

(By default) add an empty line before jinja rendering and add one after

{%  set site_url = 'www.' + domain  %}

remove the empty line before jinja rendering and add one after

{%- set site_url = 'www.' + domain  %}

add the empty line before jinja rendering and remove one after

{%  set site_url = 'www.' + domain -%}

remove the empty line before jinja rendering and remove one after

{%- set site_url = 'www.' + domain -%}

Test variable existence

{% if min_verbose_level is defined
      and min_verbose_level      %}
    and level({{ min_verbose_level }} .. emerg);
{% endif %}

Templating

Jinja2 is a rendering layer applied before the actual python (i.e. saltstack instruction) is interpreted.

{% set ipaddr = grains['fqdn_ip4'][0] %}
{% if (key | regex_match('.*dyn.company.tld.*', ignorecase=True)) != None %}
{% set syslog_java_application =
     pillar.get('syslog_java_application', {}) %}

{%  if syslog_java_application %}

{% set syslog_module_name = 
  syslog_java_application.get('name') %}
{% set types = 
  syslog_java_application.get('types') %}
{% set log_folder_path = 
  syslog_java_application.get('log_folder_path') %}
{% set log_file_name_prefix =
  syslog_java_application.get('log_file_name_prefix') %}

{% endif %}
{% for type in types %}

{% set source_name = syslog_module_name ~ '_' ~ type %}
{% set file_full_path = log_folder_path ~ '/' ~ log_file_name_prefix ~ type ~ '.log' %}
{% set program_override = syslog_module_name ~ '_' ~ type %}

syslog-ng app_function_{{ type }} configuration:
  file.managed:
    - name: /etc/syslog-ng/conf.d/{{ syslog_module_name }}_{{ type }}.conf
    - source: salt://template.tmpl
    - template: jinja
    - user: root
    - group: root
    - mode: 644
    - watch_in:
      - service: syslog-ng
    - context:
        name: {{ source_name }}
        file_full_path: {{ file_full_path }}
        program_override: {{ program_override }}

{% endfor %}

JSON parsing

# json_query_example.sls
{% set services = '
  {"services": [
    {"name": "http", "host": "1.2.3.4", "port": 80},
    {"name": "smtp", "host": "1.2.3.5", "port": 25},
    {"name": "ssh",  "host": "1.2.3.6", "port": 22}
  ]}' | load_json %}

{% set ports = services | json_query("services[].port") %}

results matching ""

    No results matching ""

    results matching ""

      No results matching ""