skip to Main Content

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.

2

Answers


  1. 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
    

    Login or Signup to reply.
  2. 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"
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search