Abri um grupo novo, SRE - Site Reliability Engineer, e uma categoria nova sobre Ansible já que agora esse é meu mundo. Estou trabalhando nessa área mantendo servidores rodando na empresa nova.

Eu estou migrando um sistema que cria VMs de python, pela falta de suporte na biblioteca, pra outra forma via linha de comando. Mas essa parte não interessa muito. O interessante é sobre como fiz parte do trabalho.

E estou escrevendo a respeito porque foi difícil achar informação sobre isso na Internet. A maioria estava ou errada ou não funcionava como esperado.

Pra começar, vamos dar uma olhada na estrutura de dados que recebo do programa. Pra simular o mesmo no Ansible, vou trocar o comando por um: cat server.json (onde server.json contém esse dado). Meu objetivo aqui é pegar o IPv4 da interface pública pra depois provisionar o sistema com os programas que vamos usar.


  {
  "core_number": "1",
  "hostname": "helio-testing.loureiro.eng.br",
  "license": 0,
  "memory_amount": "1024",
  "plan": "1xCPU-1GB",
  "progress": "0",
  "state": "started",
  "tags": [],
  "title": "helio-testing.loureiro.eng.br (created via ansible)",
  "uuid": "87271929-a137-4910-9648-75d05b6d3ecb",
  "zone": "sweden-stockholm",
  "boot_order": "disk",
  "firewall": "off",
  "host": 12345678,
  "ip_addresses": [
    {
      "access": "internal",
      "address": "192.168.0.1",
      "family": "IPv4",
      "part_of_plan": "no",
      "ptr_record": "",
      "server": "",
      "mac": "",
      "floating": "no",
      "zone": ""
    },
    {
      "access": "public",
      "address": "1.2.3.4",
      "family": "IPv4",
      "part_of_plan": "yes",
      "ptr_record": "",
      "server": "",
      "mac": "",
      "floating": "no",
      "zone": ""
    }
  ],
  "labels": {
    "label": []
  },
  "metadata": "yes",
  "nic_model": "virtio",
  "networking": {
    "interfaces": [
      {
        "index": 1,
        "ip_addresses": [
          {
            "access": "",
            "address": "1.2.3.4",
            "family": "IPv4",
            "part_of_plan": "no",
            "ptr_record": "",
            "server": "",
            "mac": "",
            "floating": "no",
            "zone": ""
          }
        ],
        "mac": "a1:b2:c3:e4:f5:01",
        "network": "fb29cb51-5dd7-4674-baac-b0253a725305",
        "type": "public",
        "bootable": "no",
        "source_ip_filtering": "yes"
      },
      {
        "index": 2,
        "ip_addresses": [
          {
            "access": "",
            "address": "192.168.0.1",
            "family": "IPv4",
            "part_of_plan": "no",
            "ptr_record": "",
            "server": "",
            "mac": "",
            "floating": "no",
            "zone": ""
          }
        ],
        "mac": "a1:b2:c3:e4:f5:02",
        "network": "92351420-66ec-46e9-98ee-149e3a588bdf",
        "type": "utility",
        "bootable": "no",
        "source_ip_filtering": "yes"
      }
    ]
  },
  "server_group": "",
  "simple_backup": "no",
  "storage_devices": [
    {
      "address": "virtio:0",
      "storage": "fe128b6b-876c-4f7b-a070-3a8d6cec6159",
      "storage_size": 10,
      "storage_tier": "maxiops",
      "storage_title": "helio-testing.loureiro.eng.br-OS",
      "type": "disk",
      "boot_disk": "0"
    }
  ],
  "timezone": "UTC",
  "video_model": "vga",
  "remote_access_enabled": "no",
  "remote_access_type": "vnc",
  "remote_access_host": "",
  "remote_access_password": "abracadabra",
  "remote_access_port": "0"
}

Então vamos começar com como pegar a saída desse comando no ansible. Pra isso basta chamar uma parte simples que registra o resultado.

  
---
- debug: msg="running the command and getting json as result"
- name: read json file
  command: >
    cat /tmp/server.json
  register: result
  failed_when: result.rc != 0

- debug: 
    msg="{{ result }}"    
  

Não tem muito segredo aqui. Eu rodo o comando, que aqui eu troquei pelo cat e recebo o resultando em result. Eu olho se result.rc é diferente de zero pra saber se deu certo (não zero significa erro).

  
- name: parsing as json
  set_fact:
    json_result: "{{ result.stdout }}"

- debug: 
    msg=" from json_result "
    msg="{{ json_result}}"    
  

Aqui foi o primeiro pulo do gato. Pra receber o dado como json bastava só pegar de result.stdout. Em muitos lugares achei receitas exotéricas como {{ result | to_json }}. Todas erradas.

  
- name: getting IPs
  set_fact:
    json_ip_addresses: "{{ json_result.ip_addresses }}"

- debug: msg="{{ json_ip_addresses }}"    
  

Do código json que recebo, eu filtro somente ip_addresses, que é a parte que me interessa.

  
- name: filtering public IPs
  set_fact:
    public_ip_addresses: "{{ json_ip_addresses | json_query(query) }}"
  vars:
    query: "[?access=='public']"

- debug: msg="{{ public_ip_addresses }}"    
  

Em seguida eu aplico filtro de json usando a sintaxe de jpath. Na parte da query, que tem um array, eu quero somente aquela que tem a propriedade "access" com o valor "public". A query vai dentro de vars por causa das aspas simples e duplas.

  
- name: filtering IPv4 only
  set_fact:
    public_ipv4_address: "{{ public_ip_addresses | json_query(query) }}"
  vars:
    query: "[?family=='IPv4'].address"
  
- debug: msg="{{ public_ipv4_address }}"    
  

No exemplo que tenho eu já não tenho mais nada, mas em alguns casos eu tenho um array com 2 elementos: IPv4 e IPv6. Então essa segunda query é pra filtrar qual estrutura tem a propriedade "family" com valor "IPv4". Dessa estrutura eu quero o valor de "address". E pronto! Está aí o IPv4 filtrado. O valor é 1.2.3.4, que é o esperado.

Agora rodando com Ansbile:

  
❯ ansible-playbook deploy.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [get JSON] ***************************************************************************************************************************************************************************

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "running from roles/getjson/tasks"
}

TASK [getjson : read json file] ***********************************************************************************************************************************************************
changed: [localhost]

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "changed": true,
        "cmd": [
            "cat",
            "../server.json"
        ],
        "delta": "0:00:00.002636",
        "end": "2024-11-23 16:02:30.099466",
        "failed": false,
        "failed_when_result": false,
        "msg": "",
        "rc": 0,
        "start": "2024-11-23 16:02:30.096830",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "{\n  \"core_number\": \"1\",\n  \"hostname\": \"helio-testing.loureiro.eng.br\",\n  \"license\": 0,\n  \"memory_amount\": \"1024\",\n  \"plan\": \"1xCPU-1GB\",\n  \"progress\": \"0\",\n  \"state\": \"started\",\n  \"tags\": [],\n  \"title\": \"helio-testing.loureiro.eng.br (created via ansible)\",\n  \"uuid\": \"87271929-a137-4910-9648-75d05b6d3ecb\",\n  \"zone\": \"sweden-stockholm\",\n  \"boot_order\": \"disk\",\n  \"firewall\": \"off\",\n  \"host\": 12345678,\n  \"ip_addresses\": [\n    {\n      \"access\": \"internal\",\n      \"address\": \"192.168.0.1\",\n      \"family\": \"IPv4\",\n      \"part_of_plan\": \"no\",\n      \"ptr_record\": \"\",\n      \"server\": \"\",\n      \"mac\": \"\",\n      \"floating\": \"no\",\n      \"zone\": \"\"\n    },\n    {\n      \"access\": \"public\",\n      \"address\": \"1.2.3.4\",\n      \"family\": \"IPv4\",\n      \"part_of_plan\": \"yes\",\n      \"ptr_record\": \"\",\n      \"server\": \"\",\n      \"mac\": \"\",\n      \"floating\": \"no\",\n      \"zone\": \"\"\n    }\n  ],\n  \"labels\": {\n    \"label\": []\n  },\n  \"metadata\": \"yes\",\n  \"nic_model\": \"virtio\",\n  \"networking\": {\n    \"interfaces\": [\n      {\n        \"index\": 1,\n        \"ip_addresses\": [\n          {\n            \"access\": \"\",\n            \"address\": \"1.2.3.4\",\n            \"family\": \"IPv4\",\n            \"part_of_plan\": \"no\",\n            \"ptr_record\": \"\",\n            \"server\": \"\",\n            \"mac\": \"\",\n            \"floating\": \"no\",\n            \"zone\": \"\"\n          }\n        ],\n        \"mac\": \"a1:b2:c3:e4:f5:01\",\n        \"network\": \"fb29cb51-5dd7-4674-baac-b0253a725305\",\n        \"type\": \"public\",\n        \"bootable\": \"no\",\n        \"source_ip_filtering\": \"yes\"\n      },\n      {\n        \"index\": 2,\n        \"ip_addresses\": [\n          {\n            \"access\": \"\",\n            \"address\": \"192.168.0.1\",\n            \"family\": \"IPv4\",\n            \"part_of_plan\": \"no\",\n            \"ptr_record\": \"\",\n            \"server\": \"\",\n            \"mac\": \"\",\n            \"floating\": \"no\",\n            \"zone\": \"\"\n          }\n        ],\n        \"mac\": \"a1:b2:c3:e4:f5:02\",\n        \"network\": \"92351420-66ec-46e9-98ee-149e3a588bdf\",\n        \"type\": \"utility\",\n        \"bootable\": \"no\",\n        \"source_ip_filtering\": \"yes\"\n      }\n    ]\n  },\n  \"server_group\": \"\",\n  \"simple_backup\": \"no\",\n  \"storage_devices\": [\n    {\n      \"address\": \"virtio:0\",\n      \"storage_encrypted\": \"yes\",\n      \"part_of_plan\": \"\",\n      \"storage\": \"fe128b6b-876c-4f7b-a070-3a8d6cec6159\",\n      \"storage_size\": 50,\n      \"storage_tier\": \"maxiops\",\n      \"storage_title\": \"helio-testing.loureiro.eng.br-OS\",\n      \"type\": \"disk\",\n      \"boot_disk\": \"0\"\n    }\n  ],\n  \"timezone\": \"UTC\",\n  \"video_model\": \"vga\",\n  \"remote_access_enabled\": \"no\",\n  \"remote_access_type\": \"vnc\",\n  \"remote_access_host\": \"\",\n  \"remote_access_password\": \"abracadabra\",\n  \"remote_access_port\": \"0\"\n}",
        "stdout_lines": [
            "{",
            "  \"core_number\": \"1\",",
            "  \"hostname\": \"helio-testing.loureiro.eng.br\",",
            "  \"license\": 0,",
            "  \"memory_amount\": \"1024\",",
            "  \"plan\": \"1xCPU-1GB\",",
            "  \"progress\": \"0\",",
            "  \"state\": \"started\",",
            "  \"tags\": [],",
            "  \"title\": \"helio-testing.loureiro.eng.br (created via ansible)\",",
            "  \"uuid\": \"87271929-a137-4910-9648-75d05b6d3ecb\",",
            "  \"zone\": \"sweden-stockholm\",",
            "  \"boot_order\": \"disk\",",
            "  \"firewall\": \"off\",",
            "  \"host\": 12345678,",
            "  \"ip_addresses\": [",
            "    {",
            "      \"access\": \"internal\",",
            "      \"address\": \"192.168.0.1\",",
            "      \"family\": \"IPv4\",",
            "      \"part_of_plan\": \"no\",",
            "      \"ptr_record\": \"\",",
            "      \"server\": \"\",",
            "      \"mac\": \"\",",
            "      \"floating\": \"no\",",
            "      \"zone\": \"\"",
            "    },",
            "    {",
            "      \"access\": \"public\",",
            "      \"address\": \"1.2.3.4\",",
            "      \"family\": \"IPv4\",",
            "      \"part_of_plan\": \"yes\",",
            "      \"ptr_record\": \"\",",
            "      \"server\": \"\",",
            "      \"mac\": \"\",",
            "      \"floating\": \"no\",",
            "      \"zone\": \"\"",
            "    }",
            "  ],",
            "  \"labels\": {",
            "    \"label\": []",
            "  },",
            "  \"metadata\": \"yes\",",
            "  \"nic_model\": \"virtio\",",
            "  \"networking\": {",
            "    \"interfaces\": [",
            "      {",
            "        \"index\": 1,",
            "        \"ip_addresses\": [",
            "          {",
            "            \"access\": \"\",",
            "            \"address\": \"1.2.3.4\",",
            "            \"family\": \"IPv4\",",
            "            \"part_of_plan\": \"no\",",
            "            \"ptr_record\": \"\",",
            "            \"server\": \"\",",
            "            \"mac\": \"\",",
            "            \"floating\": \"no\",",
            "            \"zone\": \"\"",
            "          }",
            "        ],",
            "        \"mac\": \"a1:b2:c3:e4:f5:01\",",
            "        \"network\": \"fb29cb51-5dd7-4674-baac-b0253a725305\",",
            "        \"type\": \"public\",",
            "        \"bootable\": \"no\",",
            "        \"source_ip_filtering\": \"yes\"",
            "      },",
            "      {",
            "        \"index\": 2,",
            "        \"ip_addresses\": [",
            "          {",
            "            \"access\": \"\",",
            "            \"address\": \"192.168.0.1\",",
            "            \"family\": \"IPv4\",",
            "            \"part_of_plan\": \"no\",",
            "            \"ptr_record\": \"\",",
            "            \"server\": \"\",",
            "            \"mac\": \"\",",
            "            \"floating\": \"no\",",
            "            \"zone\": \"\"",
            "          }",
            "        ],",
            "        \"mac\": \"a1:b2:c3:e4:f5:02\",",
            "        \"network\": \"92351420-66ec-46e9-98ee-149e3a588bdf\",",
            "        \"type\": \"utility\",",
            "        \"bootable\": \"no\",",
            "        \"source_ip_filtering\": \"yes\"",
            "      }",
            "    ]",
            "  },",
            "  \"server_group\": \"\",",
            "  \"simple_backup\": \"no\",",
            "  \"storage_devices\": [",
            "    {",
            "      \"address\": \"virtio:0\",",
            "      \"storage_encrypted\": \"yes\",",
            "      \"part_of_plan\": \"\",",
            "      \"storage\": \"fe128b6b-876c-4f7b-a070-3a8d6cec6159\",",
            "      \"storage_size\": 50,",
            "      \"storage_tier\": \"maxiops\",",
            "      \"storage_title\": \"helio-testing.loureiro.eng.br-OS\",",
            "      \"type\": \"disk\",",
            "      \"boot_disk\": \"0\"",
            "    }",
            "  ],",
            "  \"timezone\": \"UTC\",",
            "  \"video_model\": \"vga\",",
            "  \"remote_access_enabled\": \"no\",",
            "  \"remote_access_type\": \"vnc\",",
            "  \"remote_access_host\": \"\",",
            "  \"remote_access_password\": \"abracadabra\",",
            "  \"remote_access_port\": \"0\"",
            "}"
        ]
    }
}

TASK [getjson : parsing as json] **********************************************************************************************************************************************************
ok: [localhost]

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "boot_order": "disk",
        "core_number": "1",
        "firewall": "off",
        "host": 12345678,
        "hostname": "helio-testing.loureiro.eng.br",
        "ip_addresses": [
            {
                "access": "internal",
                "address": "192.168.0.1",
                "family": "IPv4",
                "floating": "no",
                "mac": "",
                "part_of_plan": "no",
                "ptr_record": "",
                "server": "",
                "zone": ""
            },
            {
                "access": "public",
                "address": "1.2.3.4",
                "family": "IPv4",
                "floating": "no",
                "mac": "",
                "part_of_plan": "yes",
                "ptr_record": "",
                "server": "",
                "zone": ""
            }
        ],
        "labels": {
            "label": []
        },
        "license": 0,
        "memory_amount": "1024",
        "metadata": "yes",
        "networking": {
            "interfaces": [
                {
                    "bootable": "no",
                    "index": 1,
                    "ip_addresses": [
                        {
                            "access": "",
                            "address": "1.2.3.4",
                            "family": "IPv4",
                            "floating": "no",
                            "mac": "",
                            "part_of_plan": "no",
                            "ptr_record": "",
                            "server": "",
                            "zone": ""
                        }
                    ],
                    "mac": "a1:b2:c3:e4:f5:01",
                    "network": "fb29cb51-5dd7-4674-baac-b0253a725305",
                    "source_ip_filtering": "yes",
                    "type": "public"
                },
                {
                    "bootable": "no",
                    "index": 2,
                    "ip_addresses": [
                        {
                            "access": "",
                            "address": "192.168.0.1",
                            "family": "IPv4",
                            "floating": "no",
                            "mac": "",
                            "part_of_plan": "no",
                            "ptr_record": "",
                            "server": "",
                            "zone": ""
                        }
                    ],
                    "mac": "a1:b2:c3:e4:f5:02",
                    "network": "92351420-66ec-46e9-98ee-149e3a588bdf",
                    "source_ip_filtering": "yes",
                    "type": "utility"
                }
            ]
        },
        "nic_model": "virtio",
        "plan": "1xCPU-1GB",
        "progress": "0",
        "remote_access_enabled": "no",
        "remote_access_host": "",
        "remote_access_password": "abracadabra",
        "remote_access_port": "0",
        "remote_access_type": "vnc",
        "server_group": "",
        "simple_backup": "no",
        "state": "started",
        "storage_devices": [
            {
                "address": "virtio:0",
                "boot_disk": "0",
                "part_of_plan": "",
                "storage": "fe128b6b-876c-4f7b-a070-3a8d6cec6159",
                "storage_encrypted": "yes",
                "storage_size": 50,
                "storage_tier": "maxiops",
                "storage_title": "helio-testing.loureiro.eng.br-OS",
                "type": "disk"
            }
        ],
        "tags": [],
        "timezone": "UTC",
        "title": "helio-testing.loureiro.eng.br (created via ansible)",
        "uuid": "87271929-a137-4910-9648-75d05b6d3ecb",
        "video_model": "vga",
        "zone": "sweden-stockholm"
    }
}

TASK [getjson : getting IPs] **************************************************************************************************************************************************************
ok: [localhost]

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "access": "internal",
            "address": "192.168.0.1",
            "family": "IPv4",
            "floating": "no",
            "mac": "",
            "part_of_plan": "no",
            "ptr_record": "",
            "server": "",
            "zone": ""
        },
        {
            "access": "public",
            "address": "1.2.3.4",
            "family": "IPv4",
            "floating": "no",
            "mac": "",
            "part_of_plan": "yes",
            "ptr_record": "",
            "server": "",
            "zone": ""
        }
    ]
}

TASK [getjson : filtering public IPs] *****************************************************************************************************************************************************
ok: [localhost]

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "access": "public",
            "address": "1.2.3.4",
            "family": "IPv4",
            "floating": "no",
            "mac": "",
            "part_of_plan": "yes",
            "ptr_record": "",
            "server": "",
            "zone": ""
        }
    ]
}

TASK [getjson : filtering IPv4 only] ******************************************************************************************************************************************************
ok: [localhost]

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "1.2.3.4"
    ]
}

TASK [getjson : cloud server IP] ********************************************************************************************************************************************************
ok: [localhost]

TASK [getjson : debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "1.2.3.4"
}

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

Bom ansible and happy coding 😄

We use cookies

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.