ansible

ansible module to merge config files


Is it possible to merge(by auto resolving conflicts) 2 config files using Ansible?

For eg,

// c1.conf
A=20
B="Hello"
D=24

// c2.conf
X=30
A=20
B="Hello2"          
C=31
E=33

//output.conf
X=30
A=20
B="Hello"           # In case of update, give priority to c1.conf
C=31                # In case of add/delete, give priority to c2.conf
E=33

Solution

  • Declare the list of files

      files:
        - /tmp/c2.conf
        - /tmp/c1.conf
    

    and slurp them

      - slurp:
          src: "{{ item }}"
        loop: "{{ files }}"
        register: out
    

    Then, the declaration

      result: "{{ out.results | map(attribute='content')
                              | map('b64decode')
                              | map('community.general.jc', 'ini')
                              | combine }}"
    

    gives

      result:
        A: '20'
        B: Hello
        C: '31'
        D: '24'
        E: '33'
        X: '30'
    

    If you want to keep the c2 attributes only, declare the below dictionary and key list

      c2dict: "{{ out.results.0.content | b64decode
                                        | community.general.jc('ini') }}"
      c2keys: "{{ c2dict.keys() | sort }}"
    

    give

      c2dict:
        A: '20'
        B: Hello2
        C: '31'
        E: '33'
        X: '30'
    
      c2keys: [A, B, C, E, X]
    

    Then, keep the c2 keys in the result

    resul2: "{{ [result] | community.general.keep_keys(target=c2keys)
                         | first }}"
    

    gives

      resul2:
        A: '20'
        B: Hello
        C: '31'
        E: '33'
        X: '30'
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        files:
          - /tmp/c2.conf
          - /tmp/c1.conf
    
        result: "{{ out.results | map(attribute='content')
                                | map('b64decode')
                                | map('community.general.jc', 'ini')
                                | combine  }}"
    
        c2dict: "{{ out.results.0.content | b64decode
                                          | community.general.jc('ini') }}"
        c2keys: "{{ c2dict.keys() | sort }}"
        resul2: "{{ [result] | community.general.keep_keys(target=c2keys)
                             | first }}"
    
      tasks:
    
      - slurp:
          src: "{{ item }}"
        loop: "{{ files }}"
        register: out
    
      - debug:
          var: out.results
      - debug:
          var: result
      - debug:
          var: c2dict
      - debug:
          var: c2keys | to_yaml 
      - debug:
          var: resul2