Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a new key-value to a json file using Ansible

Tags:

json

ansible

I'm using Ansible to automate some configuration steps for my application VM, but having difficult to insert a new key-value to an existing json file on the remote host.

Say I have this json file:

{   "foo": "bar" } 

And I want to insert a new key value pair to make the file become:

{   "foo": "bar",   "hello": "world" } 

Since json format is not line based, I'm excluding lineinfile module from my options. Also, I would prefer not to use any external modules. Google keeps giving me examples to show how to read json file, but nothing about change json values and write them back to file. Really appreciate your help please!

like image 561
fengye87 Avatar asked Jun 11 '18 11:06

fengye87


People also ask

How do you write a key-value pair in JSON?

Each key-value pair is separated by a comma, so the middle of a JSON lists as follows: "key" : "value", "key" : "value", "key": "value" . In the previous example, the first key-value pair is "first_name" : "Sammy" . JSON keys are on the left side of the colon.

Can a value be the key in JSON?

Keys must be strings, and values must be a valid JSON data type: string. number.

Is JSON a key-value store?

A JSON database makes it possible to store data as JSON and provide it to applications in other forms. For example, it can operate as an in-memory key-value store for applications that just need quick and easy access. Or, indexing and querying can make JSON data appear as a table.

How can I get the key-value in a JSON object?

To get the key and value from a JSON string you can use the JSON. parse() method it will convert the JSON string to a JSON object and you can easily get key and value.


2 Answers

since the file is of json format, you could import the file to a variable, append the extra key:value pairs you want, and then write back to the filesystem.

here is a way to do it:

--- - hosts: localhost   connection: local   gather_facts: false   vars:    tasks:   - name: load var from file     include_vars:       file: /tmp/var.json       name: imported_var    - debug:       var: imported_var    - name: append more key/values     set_fact:       imported_var: "{{ imported_var | default([]) | combine({ 'hello': 'world' }) }}"    - debug:       var: imported_var    - name: write var to file     copy:        content: "{{ imported_var | to_nice_json }}"        dest: /tmp/final.json 

UPDATE:

as OP updated, the code should work towards remote host, in this case we cant use included_vars or lookups. We could use the slurp module.

NEW code for remote hosts:

--- - hosts: greenhat   # connection: local   gather_facts: false   vars:    tasks:   - name: load var from file     slurp:       src: /tmp/var.json     register: imported_var    - debug:       msg: "{{ imported_var.content|b64decode|from_json }}"    - name: append more key/values     set_fact:       imported_var: "{{ imported_var.content|b64decode|from_json | default([]) | combine({ 'hello': 'world' }) }}"    - debug:       var: imported_var    - name: write var to file     copy:        content: "{{ imported_var | to_nice_json }}"        dest: /tmp/final.json 

hope it helps

like image 135
ilias-sp Avatar answered Sep 20 '22 13:09

ilias-sp


ilias-sp's solution is great!

In my case, it lacked the case when we may have to create a base json file. So I had to add this task in the beginning of the play:

- name: Ensure json file exists copy:   content: "{}"   dest: /tmp/var.json   force: false 
like image 45
Herve Nicol Avatar answered Sep 19 '22 13:09

Herve Nicol