Home > Net >  Use ansible to gather and modify fact and POST modified json to http API
Use ansible to gather and modify fact and POST modified json to http API

Time:01-18

Before patching a yum based Linux host using Ansible, I want to gather facts about packages currently installed and write the details to an http API.

The first task is to gather the facts and store it in a variable:

  tasks:
  - name: Gather installed packages
    yum:
      list: installed
    register: installed_packages

The output of which looks like this:

[
  {
      "arch": "noarch", 
      "envra": "0:yum-3.4.3-168.el7.centos.noarch", 
      "epoch": "0", 
      "name": "yum", 
      "release": "168.el7.centos", 
      "repo": "installed", 
      "version": "3.4.3", 
      "yumstate": "installed"
  }, 
  {
      "arch": "x86_64", 
      "envra": "0:zlib-1.2.7-19.el7_9.x86_64", 
      "epoch": "0", 
      "name": "zlib", 
      "release": "19.el7_9", 
      "repo": "installed", 
      "version": "1.2.7", 
      "yumstate": "installed"
  }
]

My API expects additional fields; server_hostname, server_ip_address and review_id and I need to add them into each element of the json array. I have tried using combine and the best I can come up with is:

 - name: Create empty list
   set_fact:
     list_two: []

 - name: Add additional details to installed_packages fact
   set_fact:
     list_two: "{{ list_two   [item | combine ({ 'server_hostname': 'server-name','server_ip_address': '1.2.3.4','review_id': 'guid' })] }}"
   with_items: "{{ installed_packages.results }}"

This is very slow on one of my development servers and hangs (and never finishes) on another development server. How can I add these fields to the installed_packages fact so it looks like the below and perform a POST using the uri module.

[
  {
      "arch": "noarch", 
      "envra": "0:yum-3.4.3-168.el7.centos.noarch", 
      "epoch": "0", 
      "name": "yum", 
      "release": "168.el7.centos", 
      "repo": "installed", 
      "version": "3.4.3", 
      "yumstate": "installed",
      "server_hostname": "server-name",
      "server_ip_address": "1.2.3.4",
      "review_id": "guid"
  }, 
  {
      "arch": "x86_64", 
      "envra": "0:zlib-1.2.7-19.el7_9.x86_64", 
      "epoch": "0", 
      "name": "zlib", 
      "release": "19.el7_9", 
      "repo": "installed", 
      "version": "1.2.7", 
      "yumstate": "installed",
      "server_hostname": "server-name",
      "server_ip_address": "1.2.3.4",
      "review_id": "guid"
  }
]

CodePudding user response:

This is quite hard to tell exactly why your current attempt with a loop is indeed failing, but here is an alternative way without a loop:

- debug:
    msg: "{{ installed_packages.results | map('combine', _host_info) }}"
  vars:
    _host_info:
      server_hostname: server-name
      server_ip_address: 1.2.3.4
      review_id: guid 

Which you can, then, directly tailor in an uri task, e.g.:

- ansible.builtin.uri:
    url: https://httpbin.org/post
    method: POST
    body_format: json
    body:
      packages: "{{ installed_packages.results | map('combine', _host_info) }}"
  vars:
    _host_info:
      server_hostname: server-name
      server_ip_address: 1.2.3.4
      review_id: guid
  • Related