ansible

[!NOTE|label:references:]

environment

$ sudo dnf install wget yum-utils make gcc openssl-devel bzip2-devel libffi-devel zlib-devel
$ sudo dnf groupinstall 'development tools
$ sudo dnf -y install epel-release
$ sudo dnf install python39
$ sudo update-alternatives --config python
$ sudo update-alternatives --config python3

install

$ python -m pip install --user ansible

# or via pipx
$ python3 -m pip install pipx
$ pipx ensurepath
$ pipx install ansible --include-deps
  • install for development

    $ python -m pip install --user https://github.com/ansible/ansible/archive/devel.tar.gz

upgrade

$ python -m pip install --user --upgrade ansible

# with pipx
$ pipx upgrade --include-injected ansible

$ python -m pip install --user argcomplete
$ cat >> ~/.bashrc << EOF
  command -v ansible > /dev/null && eval $(register-python-argcomplete ansible)           &&
                                    eval $(register-python-argcomplete ansible-config)    &&
                                    eval $(register-python-argcomplete ansible-console)   &&
                                    eval $(register-python-argcomplete ansible-doc)       &&
                                    eval $(register-python-argcomplete ansible-galaxy)    &&
                                    eval $(register-python-argcomplete ansible-inventory) &&
                                    eval $(register-python-argcomplete ansible-playbook)  &&
                                    eval $(register-python-argcomplete ansible-pull)      &&
                                    eval $(register-python-argcomplete ansible-vault)
EOF
  • completion.bash

    $ mkdir -p ~/.marslo/.completion
    # older version
    $ git clone git@github.com:dysosmus/ansible-completion.git ~/.marslo/.completion/ansible-completion
    
    # new version
    $ git clone git@github.com:marslo/ansible-completion.git   ~/.marslo/.completion/ansible-completion
    
    $ cat >> ~/.bashrc << EOF
    [ -d '~/.marslo/.completion/ansible-completion' ] && eval $(cat ~/.marslo/.completion/ansible-completion/*.bash)
    EOF
    • or via ln

      $ ls -1 --color=none /path/to/ansible-completion/*.bash |
           xargs -t -I{} bash -c "ln -svf {} /usr/local/share/bash-completion/completions/\$(basename {} | awk -F'.' '{print \$1}')"

ansible-vault

[!NOTE]

[!NOTE|label:references:]

$ truncate -s -1 foo.yml

## encrypt file
$ ansible-vault encrypt --vault-id @prompt foo.yml
New vault password (default):
Confirm new vault password (default):

## create new file
$ ansible-vault create --vault-id @prompt foo.yml
New vault password (default):
Confirm new vault password (default):

$ cat foo.yml
$ANSIBLE_VAULT;1.1;AES256
65393763393937353538636266646432646265643531343530623436373462633663333234653032
6131396532663939376339306261616637316561343531350a393536353331343837653265383037
30343839316531666530336134623135313535336136653232653533643131303364306265393336
3234366662313332640a613963633766663061643064356530643863373138393039326466333638
3638
  • create with name

    $ ansible-vault create --vault-id test@prompt foo.yml
    New vault password (test):
    Confirm new vault password (test):
    
    $ cat foo.yml
    $ANSIBLE_VAULT;1.2;AES256;test
    33303164313336626433376532306266633237333038653931386531616637666637626238346339
    3764383262343066636236626666613562363130636565630a313966376138323931333635333266
    32633330356132626637663534633165356133653639653130303839336338336261316362343065
    3964613438623337630a663735313836353566326333323732303232303864393063646432353463
    3631

[!TIP] via --vault-id @prompt

- [How to see special characters?](https://www.unix.com/unix-for-dummies-questions-and-answers/151193-how-see-special-characters.html) - be aware of the `echo` will automatically appending the `\n` in the end of the line: ```bash $ echo 'abc' | od -c 0000000 a b c \n 0000004 ``` - with `echo -n` ```bash $ echo -n 'abc' | od -c 0000000 a b c 0000003 ```

$ echo -n 'Test123!' | ansible-vault encrypt_string --vault-id @prompt
New vault password (default):
Confirm new vault password (default):
Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline)

Encryption successful
!vault |
          $ANSIBLE_VAULT;1.1;AES256
          62306630653236616438653236353135623936626332636337396432346235376364386233363938
          3930663634396138373139643031396433386339353634640a323938323431356330323363353335
          61636134636539326539623665393261643462396239653864313861393761633762313161386464
          3166333136366465370a323765386238646539613438333334633434613533373565326464383836
          6464
  • or

    $ ansible-vault encrypt_string
    New Vault password:
    Confirm New Vault password:
    Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline)
    abc^D                          # ctrl-d twice
    Encryption successful
    !vault |
              $ANSIBLE_VAULT;1.1;AES256
              39323234633365393633306135386362373463356636633937336236643763616232383832396333
              3136343265346534306638343738363435393964353262330a313331323161653832656365336331
              36356564653565613664666631346434306366666163393463633030363732336436346364613638
              3038303934366166320a633064326333623062663362343031633065333138313762353534643530
              633

reset key

$ ansible-vault rekey --vault-id @prompt /path/to/file

encrypt

$ ansible-vault encrypt --vault-id @prompt /path/to/file

decrypt

$ ansible-vault decrypt --vault-id @prompt /path/to/file
  • decrypt from string

    # encrypt
    $ echo -n 'a' | ansible-vault encrypt_string
    Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline)
    
    Encryption successful
    !vault |
              $ANSIBLE_VAULT;1.1;AES256
              63666334316139653431343330386139346466356439373263643566373062613666653362353738
              3630386133363464313964666230313062666662396161650a313165353966393136643932643434
              64306666613835333130613866303730623538313136323236653732663461623532343035626262
              3932643631653739350a306131666337633831653233623638396438386535623938626133653332
              3464
    
    # decrypt
    $ echo -n '$ANSIBLE_VAULT;1.1;AES256
    63666334316139653431343330386139346466356439373263643566373062613666653362353738
    3630386133363464313964666230313062666662396161650a313165353966393136643932643434
    64306666613835333130613866303730623538313136323236653732663461623532343035626262
    3932643631653739350a306131666337633831653233623638396438386535623938626133653332
    3464' | ansible-vault decrypt
    Decryption successful
    a

view

$ ansible-vault view --vault-id @prompt /path/to/file

ansible-galaxy

[!NOTE|label:references:]

$ ansible-galaxy collection install kubernetes.core

# or
$ ansible-galaxy install -r requirements.yml
  • example

    - name: Deploy latest version of Prometheus chart inside monitoring namespace (and create it)
      kubernetes.core.helm:
        name: test
        chart_ref: stable/prometheus
        release_namespace: monitoring
        create_namespace: true
    
    # From repository
    - name: Add stable chart repo
      kubernetes.core.helm_repository:
        name: stable
        repo_url: "https://kubernetes.github.io/ingress-nginx"
    
    - name: Deploy latest version of Grafana chart inside monitoring namespace with values
      kubernetes.core.helm:
        name: test
        chart_ref: stable/grafana
        release_namespace: monitoring
        values:
          replicas: 2
    
    - name: Deploy Grafana chart on 5.0.12 with values loaded from template
      kubernetes.core.helm:
        name: test
        chart_ref: stable/grafana
        chart_version: 5.0.12
        values: "{{ lookup('template', 'somefile.yaml') | from_yaml }}"
    
    - name: Deploy Grafana chart using values files on target
      kubernetes.core.helm:
        name: test
        chart_ref: stable/grafana
        release_namespace: monitoring
        values_files:
          - /path/to/values.yaml
    
    - name: Remove test release and waiting suppression ending
      kubernetes.core.helm:
        name: test
        state: absent
        wait: true
    
    - name: Separately update the repository cache
      kubernetes.core.helm:
        name: dummy
        namespace: kube-system
        state: absent
        update_repo_cache: true
    
    - name: Deploy Grafana chart using set values on target
      kubernetes.core.helm:
        name: test
        chart_ref: stable/grafana
        release_namespace: monitoring
        set_values:
          - value: phase=prod
            value_type: string
    
    # From git
    - name: Git clone stable repo on HEAD
      ansible.builtin.git:
        repo: "http://github.com/helm/charts.git"
        dest: /tmp/helm_repo
    
    - name: Deploy Grafana chart from local path
      kubernetes.core.helm:
        name: test
        chart_ref: /tmp/helm_repo/stable/grafana
        release_namespace: monitoring
    
    # From url
    - name: Deploy Grafana chart on 5.6.0 from url
      kubernetes.core.helm:
        name: test
        chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
        release_namespace: monitoring
    
    # Using complex Values
    - name: Deploy new-relic client chart
      kubernetes.core.helm:
        name: newrelic-bundle
        chart_ref: newrelic/nri-bundle
        release_namespace: default
        force: True
        wait: True
        replace: True
        update_repo_cache: True
        disable_hook: True
        values:
          global:
            licenseKey: "{{ nr_license_key }}"
            cluster: "{{ site_name }}"
          newrelic-infrastructure:
            privileged: True
          ksm:
            enabled: True
          prometheus:
            enabled: True
          kubeEvents:
            enabled: True
          logging:
            enabled: True

ansible-playbook

[!NOTE|label:references:]

# without password
$ export ANSIBLE_VAULT_PASSWORD_FILE=/path/to/password.txt
$ ansible-playbook -i hosts /path/to/yaml

# with password
$ ansible-playbook -i hosts /path/to/yaml --vault-id @prompt

tags

[!NOTE|label:references]

never

$ cat sample.yaml
---

- hosts: localhost
  gather_facts: False
  tasks:

    - name: Hello tag example
      debug:
        msg: "Hello!"
      tags:
        - hello

    - name: No tag example
      debug:
        msg: "How are you?"

    - name: Goodbye tag example
      debug:
        msg: "Goodbye!"
      tags:
        - goodbye
        - never                        # will not be executed unless using `--tags goodbye`
  • result

    $ ansible-playbook sample.yaml
    
    PLAY [localhost] *************************************************************************
    TASK [Hello tag example] *****************************************************************
    ok: [localhost] => {
        "msg": "Hello!"
    }
    
    TASK [No tag example] ********************************************************************
    ok: [localhost] => {
        "msg": "How are you?"
    }
    
    PLAY RECAP *******************************************************************************
    localhost           : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • result with --tags

    $ ansible-playbook sample.yaml --tags goodbye
    
    PLAY [localhost] *************************************************************************
    
    TASK [Goodbye tag example] ***************************************************************
    ok: [localhost] => {
        "msg": "Goodbye!"
    }
    
    PLAY RECAP *******************************************************************************
    localhost           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

vault CLI

[!NOTE|label:references:]

environment variables

$ export VAULT_ADDR=https://vault.example.com
$ export VAULT_TOKEN=s.s**********************K

$ vault kv get -mount=project service-account/account
============= Secret Path =============
project/data/service-account/account

======= Metadata =======
Key                Value
---                -----
created_time       2024-06-19T06:51:35.036120169Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            9

============= Data =============
Key                       Value
---                       -----
email                     account@sample.com
password                  eW7[xRF(rgA@x)n£LN75?R5b.k2z1+
username                  account

# with json foramt
$ vault kv get -format=json -mount=project service-account/account

$ vault kv list project/service-account
Keys
----
account

[!NOTE|label:referencs:]

get all default

$ ansible-config init --disabled -t all
  • disable localhost warning

    $ cat ansible.cfg
    [defaults]
    localhost_warning=false

ansible-lint

[!NOET|label:references:]

  • Configuration

    • .ansible-lint

    • .config/ansible-lint.yml

    • .config/ansible-lint.yaml

ansible-tools

[!NOTE|label:references:]

plugin

[!NOTE|label:references:]

  • sample code

    $ ls --color=none lookup* | xargs -n1 -t cat
    cat lookup-content.txt
    hello world
    
    cat lookup.yaml
    ---
    - hosts: localhost
      tasks:
      vars:
         contents: "{{ lookup('file', '/home/marslo/iMarslo/study/code/ansible/lookup-content.txt')}}"
      tasks:
         - debug: msg="the content of file lookup-content.txt is {{contents}}"
$ ansible-playbook lookup.yaml
PLAY [localhost] *************************************************************************

TASK [Gathering Facts] *******************************************************************
Monday 24 July 2023  17:43:51 -0700 (0:00:00.007)       0:00:00.007 ***********
ok: [localhost]

TASK [debug] *****************************************************************************
Monday 24 July 2023  17:43:51 -0700 (0:00:00.935)       0:00:00.943 ***********
ok: [localhost] => {}

MSG:

the content of file lookup-content.txt is hello world

PLAY RECAP *******************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Monday 24 July 2023  17:43:52 -0700 (0:00:00.030)       0:00:00.974 ***********
===============================================================================
Gathering Facts ------------------------------------------------------------------- 0.94s
debug ----------------------------------------------------------------------------- 0.03s

[!NOTE|label:references:]

troubleshooting

Last updated