Omri
Omri

Reputation: 1646

Modify json using Ansible

I have a simple json that looks like this:

{
   "aaa": "true",
   "bbb": "false",
   "ccc": "true"
}

I would like enable 'bbb' value using ansible. Here is my playbook:

---
- hosts: "{{hosts}}"
  remote_user: 'centos'
  gather_facts: yes
  become: yes

  tasks:
  - name: Load current facts
    slurp:
      path: "/tmp/file.json"
    register: facts

  - name: Enable fact
    set_fact:
      facts: "{{ facts | combine({ 'bbb': 'true' }) }}"

Nothing happen when i run this playbook, and the json file stays the same. What could be the issue?

Upvotes: 1

Views: 2873

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 67959

Q: "I would like to enable 'bbb' value ... the JSON file stays the same."

shell> cat /tmp/file.json 
{
    "aaa": "true",
    "bbb": "false",
    "ccc": "true"
}

A: Use replace to modify the file. For example

    - replace:
        path: /tmp/file.json
        regexp: '"bbb": "false"'
        replace: '"bbb": "true"'

gives

shell> cat /tmp/file.json 
{
    "aaa": "true",
    "bbb": "true",
    "ccc": "true"
}

Upvotes: 0

larsks
larsks

Reputation: 311248

You've got a few problems. First, you'll want to inspect the content of the facts variable after your Load current facts task has completed:

  - name: Load current facts
    slurp:
      path: "/tmp/file.json"
    register: facts

  - debug:
      var: facts

This will show you that the contents of your facts variable is not what you think:

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => {
    "facts": {
        "changed": false,
        "content": "ewogICAiYWFhIjogInRydWUiLAogICAiYmJiIjogImZhbHNlIiwKICAgImNjYyI6ICJ0cnVlIgp9Cgo=",
        "encoding": "base64",
        "failed": false,
        "source": "file.json"
    }
}

To actual get the data from your JSON file, you would need to base64-decode the content key:

- debug:
    var: facts.content|b64decode

Which gets you:

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => {
    "facts.content|b64decode": {
        "aaa": "true",
        "bbb": "false",
        "ccc": "true"
    }
}

Putting that together gives us a playbook that looks something like this:

---
- hosts: localhost
  gather_facts: false
  tasks:
  - name: Load current facts
    slurp:
      path: "file.json"
    register: facts_raw

  - name: Enable fact
    set_fact:
      facts: "{{ facts | combine({ 'bbb': 'true' }) }}"
    vars:
      facts: "{{ facts_raw.content|b64decode }}"

  - debug:
      var: facts

Which will output:

TASK [Load current facts] ********************************************************************************************************************************************************************
ok: [localhost]

TASK [Enable fact] ***************************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => {
    "facts": {
        "aaa": "true",
        "bbb": "true",
        "ccc": "true"
    }
}

Nothing happen when i run this playbook, and the json file stays the same. What could be the issue?

The set_fact simply creates an Ansible variable. If your goal is to actually modify /tmp/file.json, you will need to add a task to write out the modified data to that file. Something like:

- name: write modified data to file
  copy:
    content: "{{ facts | to_nice_json }}"
    dest: /tmp/file.json

Upvotes: 3

Related Questions