user63898
user63898

Reputation: 30933

Ansible loop JSON array contains objects and replace each found element in JSON in file

i have this JSON :

[{
        "${foo1}": "somevalue1",
        "${foo2}": "somevalue2"
    }, {
        "${zoo1}": "somevalue111",
        "${zoo2}": "somevalue222"
}]

In which i need to loop over in ansible and each object in the JSON array each key / pair value I like to check if the key exists in the file and replace it with the value . For example: if in the file i have

key1=${foo1}

it will be replaced with

key1=somevalue1

i use to have hard coded ansible task :

replace:
    path: "/myfile.txt"
    regexp: "{{ item.regexp }}"
    replace: "{{ item.replace }}"
  with_items:
    - { regexp: '${foo1}', replace: "new_value" }

i like to convert it to dynamically search and replace according to the given JSON

i capture the JSON like this : ( this is trim down YAML )

---
-
  gather_facts: false
  hosts: localhost
  name: test
  tasks:
    - name: debug
      debug:
        msg: "{{ AAA| to_json }}"
    - name: set fact
      set_fact:
         multi_parms: "{{ AAA| to_json }}"
    - name: debug multi_parms
      debug:
        var: multi_parms 

Upvotes: 1

Views: 1627

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68229

Read the JSON file into a single dictionary, e.g.

    - set_fact:
        my_data: "{{ my_data|d({})|combine(item) }}"
      loop: "{{ lookup('file', 'test.json') }}"

gives

  my_data:
    ${foo1}: somevalue1
    ${foo2}: somevalue2
    ${zoo1}: somevalue111
    ${zoo2}: somevalue222

Given an INI file, e.g.

shell> cat conf.ini
key1=${foo1}
key2=${foo2}
key3=xyz

parse the configuration into a dictionary, e.g.

    - set_fact:
        my_ini: "{{ dict(_keys|zip(_vals)) }}"
      vars:
        _lines: "{{ lookup('file', 'conf.ini').splitlines() }}"
        _regex: '^(.*)=(.*)$'
        _keys: "{{ _lines|map('regex_replace', _regex, '\\1') }}"
        _vals: "{{ _lines|map('regex_replace', _regex, '\\2') }}"

gives

  my_ini:
    key1: ${foo1}
    key2: ${foo2}
    key3: xyz

Then use the module ini_file to substitute the data, e.g.

    - ini_file:
        path: conf.ini
        section:
        option: "{{ item }}"
        value: "{{ my_data[my_ini[item]] }}"
        no_extra_spaces: true
      loop: "{{ my_ini|list }}"
      when: my_ini[item] in my_data

gives

shell> cat conf.ini
key1=somevalue1
key2=somevalue2
key3=xyz

Q: "How can I do the search and replace in the destination file?"

A: See below the "--diff" output of each iteration.

TASK [ini_file] ***************************************************
--- before: conf.ini (content)
+++ after: conf.ini (content)
@@ -1,3 +1,3 @@
-key1=${foo1}
+key1=somevalue1
 key2=${foo2}
 key3=xyz

changed: [localhost] => (item=key1)
--- before: conf.ini (content)
+++ after: conf.ini (content)
@@ -1,3 +1,3 @@
 key1=${foo1}
-key2=${foo2}
+key2=somevalue2
 key3=xyz

changed: [localhost] => (item=key2)
skipping: [localhost] => (item=key3)

Upvotes: 1

JBone
JBone

Reputation: 1836

this code in j2 template

  {% for  item in json_data %}
    {% for k, v in item.items() %}
   
      key{{loop.index}}  =  {{ v }}
 
     {% endfor %}
   {% endfor %} 

gets you this result

  key1  =  somevalue1

   key2  =  somevalue2

   key1  =  somevalue111

  key2  =  somevalue222

is this what you were looking for?

Upvotes: 0

Related Questions