- environment
- ansible-vault
- ansible-galaxy
- ansible-playbook
- vault CLI
- ansible-config
- ansible-lint
- ansible-tools
- plugin
- troubleshooting
[!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
completion
$ 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
-
$ 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}')"
- or via
ansible-vault
[!NOTE]
encrypted files
[!NOTE|label:references:]
- Why should text files end with a newline?
- Removing a newline character at the end of a file
$ truncate -s -1 /path/to/yaml
- sed solution
$ sed -z s/.$// pw.txt | od -c 0000000 a b c 0000003
$ printf %s "$(< pw.txt)" | od -c 0000000 a b c 0000003
$ head -c -1 pw.txt | od -c 0000000 a b c \n e f g 0000007
$ 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
prompt for the password
[!TIP] via
--vault-id @prompt
- How to see special characters?
- be aware of the
echo
will automatically appending the\n
in the end of the line:$ echo 'abc' | od -c 0000000 a b c \n 0000004
- with
echo -n
$ 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
-
- 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
kv get
$ 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
kv list
$ vault kv list project/service-account
Keys
----
account
ansible-config
[!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
lookup
[!NOTE|label:references:]
- 自动化运维 | Ansible lookup
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
Become
[!NOTE|label:references:]
troubleshooting
- generate the final yaml via
ansible.builtin.template
# in tasks/main.yaml - name: Template a file to local ansible.builtin.template: src: file_in_template.yaml dest: /local/path/to/yaml