Custom facts em Ansible. ME SOLTA! Quero personalizar minhas tasks…

Opa pessoal, voltando com TUDO 🚀 eu fiquei um tempinho sem escrever, e dessa vez venho mostrar um recurso bem legal do projeto do Ansible, muitos devem conhecer esse recurso mas resolvi compartilhar para ajudar quem está começando na ferramenta. Bora automatizar, né!? 😜

Sem perder muito tempo vamos ver essa parada de custom facts logo… A ideia aqui hoje é ser bem simples e rápido com o post, afinal o exemplo que eu pretendo mostrar é fácil de tudo, alguns comandos Linux e já fica prontinho.

Bom, antes de passar a ementa do que vamos ver aqui, sugiro abrirem a documentação oficial do , para que possamos entender antes de tudo, o que é custom facts, para que serve e como podemos utilizar esse recurso.

Feito sua leitura, vamos seguir…

  • O que será abordado aqui hoje?

- O que precisamos e para onde vamos…
- Comandos Ad-hoc usando o módulo setup
- Shell Script ❤
- Construindo nossa playbook
- Filtrando nossa saída com Ad-hoc
- Fechando o post

  • O que precisamos e para onde vamos…

O Ansible trabalha com muitos mas muitos módulos, tais como, , apt, , , lineinfile, fetch, módulos de cloud, etc, e o que vamos estudar hoje é o módulo . O módulo setup basicamente pega fatos dos hosts remotos que o Ansible está afetando, como interfaces de redes, filesystems, release do sistema, kernel, uso de swap, tudo isso de forma automática em forma de variáveis.

  • Comandos Ad-hoc usando o módulo setup:

1- Filtrando o diretório do usuário:

ansible elliot01 -m setup -a "filter=ansible_user_dir" -i inventory.yml
elliot01 | SUCCESS => {
"ansible_facts": {
"ansible_user_dir": "/home/ec2-user",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

2- Filtrando o shell utilizado:

ansible elliot01 -m setup -a "filter=ansible_user_shell" -i inventory.yml
elliot01 | SUCCESS => {
"ansible_facts": {
"ansible_user_shell": "/bin/bash",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

3- Filtrando as definições do SELinux:

ansible elliot01 -m setup -a "filter=ansible_selinux" -i inventory.yml
elliot01 | SUCCESS => {
"ansible_facts": {
"ansible_selinux": {
"config_mode": "enforcing",
"mode": "enforcing",
"policyvers": 31,
"status": "enabled",
"type": "targeted"
},
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

4- Filtrando a versão da BIOS:

ansible elliot01 -m setup -i inventory.yml | grep -i amazon
"ansible_bios_version": "4.2.amazon"

No exemplo que pretendo mostrar aqui, os facts do Ansible por padrão não trazem o que queremos, eu terei que customizar os facts para que ele me traga alguns comandos e é justamente isso que precisamos fazer, customizar alguns facts para que ele se adeque ao nosso cenário.

E para onde vamos com isso?
Vamos mostrar como é simples criar custom facts para que você possa usar aí do seu lado no seu ambiente.

Nota de (IaC): use infraestrutura como código, use Terraform para provisionar suas instâncias na cloud e gerencie tudo com Ansible, um tempo atrás eu publiquei um artigo aqui onde mostro isso, é uma forma rápida de lançar suas instâncias EC2 e já usar Ansible para gerência de configuração.

Agora vamos avançar, veja um exemplo abaixo pegando um trecho de facts do host:

$ ansible elliot01 -m setup -i inventory.yml
"ansible_architecture": "x86_64",
"ansible_bios_date": "08/24/2006",
"ansible_bios_version": "4.2.amazon"

A saída desse comando seria gigante, e para mostrar apenas um exemplo, eu peguei um trecho bem curto da saída, veja que ele trouxe a arquitetura, a versão da BIOS, eu quero usar o custom facts para pegar o uptime do servidor, se ele está UP e quanto tempo ele está rodando.

  • Shell Script

Bom, aqui vou usar Shell Script para gerar um bash básico e grepar a saída com o comando cut, existem outras formas de se fazer isso, mas eu gosto de usar o Shell para gerar esses comandos:

#!/usr/bin/env bash

UP=`uptime | cut -d " " -f 3,4,5`
cat <<EOF
{
"server_uptime" : "$UP"
}
EOF

De acordo com a documentação, os arquivos, aqui no nosso caso, nosso Shell Script podem ser JSON, INI ou arquivos executáveis que retornam JSON, por isso eu tive que usar o comando cat com EOF, para que ele me retorne uma saída JSON do uptime, veja que o comando uptime é bem simples.

O que precisamos saber é, existem duas formas de custom facts (facts.d ou local facts), no nosso caso, vou demonstrar o uso do facts.d, que nada mais é segundo a documentação do Ansible, criar um diretório no host remoto com o seguinte caminho /etc/ansible/facts.d isso se faz necessário para que o Ansible entenda o caminho no host remoto e o arquivo que ele quer atingir. Outro ponto é, quando usamos o facts.d, todos os nomes de arquivos devem terminar com a extensão .fact

Se eu executar o script, ele retorna essa saída abaixo, exatamente isso que pretendo com custom facts lá na frente assim que rodarsmos um Ad-hoc:

$ ./up.fact
{
"server_uptime" : "up 3:53,"
}
  • Construindo nosso playbook!

Bom, essa parte da playbook também é bem simples, como vamos usar custom facts no host remoto, podemos antes fazer um pre-check de alguns itens para validar se está tudo certo no hosts para receber o custom facts.

Eu escrevi algo assim:

Com a nossa playbook desenvolvida, vamos executar para já validar se está tudo ok no host remoto. Para isso execute o seguinte comando:

$ ansible-playbook play-custom-facts.yml --extra-vars  "inventory=elliot01" -i inventory.yml

Teremos o seguinte output:

Playbook output
  • Filtrando nossa saída com ad-hoc

Chegou a hora de validar se ocorreu tudo bem, vamos testar usando o comando Ad-hoc se o nosso uptime esta correto do jeito que configuramos no script:

ansible elliot01 -m setup -a "filter=ansible_local" -i inventory.yml
elliot01 | SUCCESS => {
"ansible_facts": {
"ansible_local": {
"up": {
"server_uptime": "up 23:50, "
}
},
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

Podemos grepar também que teremos a mesma saída:

ansible elliot01 -m setup  -i inventory.yml | grep -i server
"server_uptime": "up 23:51, "
  • Fechando nosso post

A ideia foi bem simples, realmente sabemos o quão o Ansible é poderoso, esse é apenas um dos tantos recursos que existem disponíveis para serem utilizados, sem contar as integrações com outras ferramentas de DevOps

Valeww pessoal, obrigado pela leitura e até o próximo post sobre Ansible (vai ser maravilhoso haha’). Fui! 🚀

Passion for DevOps