Using `lineinfile` to add a host variable in Ansible YAML inventory?

53 Views Asked by At

Hello everybody and thank you in advance for your help.

I have to add a variable stat: ON for some hosts in my YAML inventory that looks like:

all:
  hosts:     
    host_1: {db: true, bckp: false}
    host_2: {db: false, bckp: true}

To looks like:

all:
  hosts:     
    host_1: {db: true, bckp: false, stat: ON}
    host_2: {db: false, bckp: true}

I want to add it with Ansible (lineinfile or other module) when I execute a task that power-on a VM.

I try this:

- name: Add variable for with status stopped
  lineinfile:
    path: inventory/inv.yml
    insertafter: EOF
    line: "host_1: {db: true, bckp: false, stat: ON}"
  delegate_to: localhost

But it's not OK because I have to give only the hostname not other values that I can't know in advance.

I try also:

- name: Add variable for with status stopped
  add_host:
   name: host_1
   groups: group_name
   status: ON
 delegate_to: localhost

Not good because it add a new line instead of modify the existing one.

I've tried this also:

- name: Read inventory file
  slurp:
    path: inventory/inv.yml
  register: inventory_content

- name: Parse YAML inventory
  set_fact:
    parsed_inventory: "{{ inventory_content.content | b64decode | from_yaml }}"

- name: Add variable for with status stopped
  set_fact:
    parsed_inventory: |
          {{ parsed_inventory | to_yaml | regex_replace('^(all:\s*hosts:\s*host_1:)', '\\1\n  status: ON') }}

- name: Write updated inventory file
  copy:
    content: "{{ parsed_inventory }}"

It's not good because it change all my inventory and not add the value.

All what I tried didn't work as I expect, I want to:

  1. Find the line of given hostname (here host_1)
  2. Insert the new variable after existing variables like: host_1: {db: true, bckp: false} -> host_1: {db: true, bckp: false, stat: ON}

Thank you for your help.

1

There are 1 best solutions below

2
U880D On

According Organizing host and group variables, for the given inventory file example.com

one.example.com db=true bckp=false
two.example.com db=true bckp=false

just introduce a host_vars/one.example.com file with content of

stat: ON

in order to drop a fact and find an example playbook

---
- hosts: all
  become: false
  gather_facts: false

  tasks:

  - debug:
      var: hostvars[inventory_hostname].stat

called via

ansible-playbook --inventory example.com main.yml

resulting into an output of

TASK [debug] ************************************************
ok: [two.example.com] =>
  hostvars[inventory_hostname].stat: VARIABLE IS NOT DEFINED!
ok: [one.example.com] =>
  hostvars[inventory_hostname].stat: true

There is absolute no need for parsing or editing a file, using lineinfile, set_fact, regex_replace or programming at all.

Documentation

  • How to build your inventory

  • Things to know about programming using Ansible

    Ansible is not a language: If Ansible isn't a programming language, then what is it? Ansible is a tool written in Python, and it uses the declarative markup language YAML to describe the Desired State of devices and configuration. ... You declare aspects you want to be configured on a target device, such as that a file or directory exists, a package is installed, a service is running, and so on.

  • Ansible Best Practices: The Essentials

    Think declaratively: Ansible is a Desired State Engine by design. If you’re trying to “write code” in your plays and roles, you’re setting yourself up for failure. Our YAML-based playbooks were never meant to be for programming.

  • What is the XY problem?

and finally