Home > Blockchain >  Modify .json file using Anisble
Modify .json file using Anisble

Time:12-27

My file structure is like below

[root@test exim]# cat exim.json
{
    "general": {
        "max_hourly_email": 0,
        "max_notify_email": 0,
        "enable_mail_retry": "1",
        "mail_retry": 15,
        "enable_roundcube": "1",
        "default_quota_val": 32768,
        "default_quota": "1",
        "eximmailtrap": "1",
        "no_local_emailing": "0",
        "dkim_selector": "x",
        "disable_ipv6": "0",
        "custom_mailips": "0",
        "message_linelength_limit": 2048

I want to change the value of "max_hourly_email" and "max_notify_email"

**I am trying to change the valued using following method:
**

- name: Set Max hourly emails per domain
  lineinfile:
    path: /var/webuzo/conf/exim/exim.json
    regexp: 'max_hourly_email'
    line: '        "max_hourly_email": 200,'
    state: present

It is changing the value but breaking the file sturcture like below

[root@test exim]# cat exim.json
{
    "general": {
**"max_hourly_email": 200,**
        "max_notify_email": 0,
        "enable_mail_retry": "1",
        "mail_retry": 15,
        "enable_roundcube": "1",
        "default_quota_val": 32768,
        "default_quota": "1",
        "eximmailtrap": "1",
        "no_local_emailing": "0",
        "dkim_selector": "x",
        "disable_ipv6": "0",
        "custom_mailips": "0",
        "message_linelength_limit": 2048

How may I change the values using ansible without breaking the structure. Thanks.

CodePudding user response:

Given the file with the sorted dictionary for simpler comparison

shell> cat exim.json
{
    "general": {
        "custom_mailips": "0",
        "default_quota": "1",
        "default_quota_val": 32768,
        "disable_ipv6": "0",
        "dkim_selector": "x",
        "enable_mail_retry": "1",
        "enable_roundcube": "1",
        "eximmailtrap": "1",
        "mail_retry": 15,
        "max_hourly_email": 0,
        "max_notify_email": 0,
        "message_linelength_limit": 2048,
        "no_local_emailing": "0"
    }
}

lineinfile

Create a dictionary with the updates. For example, if you want to keep the double quotes make them part of the string

  update:
    general:
      max_hourly_email: 200
      enable_mail_retry: '"3"'
      test: 9

The task below will update existing keys, but won't add a new one

    - lineinfile:
        backrefs: true
        path: "{{ my_file }}"
        regexp: '^(.*){{ item.key }}(.*):\s (.*)$'
        line: '\1{{ item.key }}\2: {{ item.value }},'
      loop: "{{ update.general|dict2items }}"

gives when running with options --check --diff

TASK [lineinfile] ****************************************************************************
--- before: /export/scratch/tmp7/test-117/exim.json (content)
    after: /export/scratch/tmp7/test-117/exim.json (content)
@@ -9,7  9,7 @@
         "enable_roundcube": "1",
         "eximmailtrap": "1",
         "mail_retry": 15,
-        "max_hourly_email": 0,
         "max_hourly_email": 200,
         "max_notify_email": 0,
         "message_linelength_limit": 2048,
         "no_local_emailing": "0"

changed: [localhost] => (item={'key': 'max_hourly_email', 'value': 200})
--- before: /export/scratch/tmp7/test-117/exim.json (content)
    after: /export/scratch/tmp7/test-117/exim.json (content)
@@ -5,7  5,7 @@
         "default_quota_val": 32768,
         "disable_ipv6": "0",
         "dkim_selector": "x",
-        "enable_mail_retry": "1",
         "enable_mail_retry": "3",
         "enable_roundcube": "1",
         "eximmailtrap": "1",
         "mail_retry": 15,

changed: [localhost] => (item={'key': 'enable_mail_retry', 'value': '"3"'})
ok: [localhost] => (item={'key': 'test', 'value': 9})

template

There is a more flexible option of combining the dictionaries and using a template. Remove the extra quotation

  update:
    general:
      max_hourly_email: 200
      enable_mail_retry: "3"
      test: 9

combine the dictionaries

    - copy:
        dest: "{{ playbook_dir }}/exim.json"
        content: |
          {{ orig|combine(update, recursive=true)|to_nice_json }}
      vars:
        orig: "{{ lookup('file', my_file)|from_yaml }}"

gives when running with options --check --diff

TASK [copy] **********************************************************************************
--- before: /export/scratch/tmp7/test-117/exim.json
    after: /home/admin/.ansible/tmp/ansible-local-888558_ztunphb/tmp9b2vctgc
@@ -5,13  5,14 @@
         "default_quota_val": 32768,
         "disable_ipv6": "0",
         "dkim_selector": "x",
-        "enable_mail_retry": "1",
         "enable_mail_retry": "3",
         "enable_roundcube": "1",
         "eximmailtrap": "1",
         "mail_retry": 15,
-        "max_hourly_email": 0,
         "max_hourly_email": 200,
         "max_notify_email": 0,
         "message_linelength_limit": 2048,
-        "no_local_emailing": "0"
         "no_local_emailing": "0",
         "test": 9
     }
 }

changed: [localhost]

Notes

Example of a complete playbook for testing

- hosts: localhost

  vars:

    my_file: "{{ playbook_dir }}/exim.json"
    
  tasks:

    - lineinfile:
        backrefs: true
        path: "{{ my_file }}"
        regexp: '^(.*){{ item.key }}(.*):\s (.*)$'
        line: '\1{{ item.key }}\2: {{ item.value }},'
      loop: "{{ update.general|dict2items }}"
      when: iter|d(true)|bool
      vars:
        update:
          general:
            max_hourly_email: 200
            enable_mail_retry: '"3"'
            test: 9

    - copy:
        dest: "{{ my_file }}"
        content: |
          {{ orig|combine(update, recursive=true)|to_nice_json }}
      when: not iter|d(true)|bool
      vars:
        orig: "{{ lookup('file', my_file)|from_yaml }}"
        update:
          general:
            max_hourly_email: 200
            enable_mail_retry: "3"
            test: 9

CodePudding user response:

Above answer by Vladimir is quite comprehensive , adding to above I have written a simple playbook using jinja expression which is easy to understand.

exim.j2

{
    "general": {
        "custom_mailips": "0",
        "default_quota": "1",
        "default_quota_val": 32768,
        "disable_ipv6": "0",
        "dkim_selector": "x",
        "enable_mail_retry": "1",
        "enable_roundcube": "1",
        "eximmailtrap": "1",
        "mail_retry": 15,
        "max_hourly_email": "{{ max_hourly_email }}",
        "max_notify_email": "{{ max_notify_email }}",
        "message_linelength_limit": 2048,
        "no_local_emailing": "0"
    }
}

Using the above jinja file in the below playbook

---
- name: Set variable in jinja file
  hosts: localhost
  become: true
  vars:
    max_hourly_email: 200
    max_notify_email: [email protected]
  tasks:
    - name: Deploy the file
      template:
        src: exim.j2
        dest: final.txt

Below is the output final.txt that is produced as desired.

{
    "general": {
        "custom_mailips": "0",
        "default_quota": "1",
        "default_quota_val": 32768,
        "disable_ipv6": "0",
        "dkim_selector": "x",
        "enable_mail_retry": "1",
        "enable_roundcube": "1",
        "eximmailtrap": "1",
        "mail_retry": 15,
        "max_hourly_email": "200",
        "max_notify_email": "[email protected]",
        "message_linelength_limit": 2048,
        "no_local_emailing": "0"
    }
}
  • Related