# Module to patch (update) environment variables file with version

**URL:** <https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254>\
**Category:** Get Help\
**Tags:** playbook, ansible-core\
**Created:** [May 2, 2024, 9:59am UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254 "2024-05-02T09:59:18Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ShanDesai](https://avatars.discourse-cdn.com/v4/letter/s/838e76/32.png) [@ShanDesai](https://forum.ansible.com/u/ShanDesai)\
**Post date:** [May 2, 2024, 9:59am UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/1 "2024-05-02T09:59:18Z")

</div>

## Scenario

I have an artifact with an `.env` file which can have the following structure:

```auto
vSERVICE1=1.8.1
vSERVICE2=2.0.0

```

The values of the env vars are _updated_ which I would like patch to an existing production `.env` in the `/home/user/project/.env`

The production `.env` file has more environment variables e.g.:

```auto
vSERVICE1=1.8.0
vSERVICE2=1.9.0
vSERVICE3=2.1.2
vSERVICE4=0.0.1

```

I wish to patch the `vSERVICE1` and `vSERVICE2` environment variables without altering the other values in the production `.env` file.

At the moment I can obtain the difference using `diff` and `check_mode`:

```yaml
- ansible.builtin.copy:
    src: /tmp/artifacts/.env
    dest: /home/user/project/.env
    check_mode: true
    diff: true

```

which is overwriting the production file which implies `copy` might not be the best solution. Can patch the file without regex gymnastics or do I have to resort to `lineinfile` module?

---

<div class="post-metadata">

**Author:** ![ShanDesai](https://avatars.discourse-cdn.com/v4/letter/s/838e76/32.png) [@ShanDesai](https://forum.ansible.com/u/ShanDesai)\
**Post date:** [May 2, 2024, 10:26am UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/2 "2024-05-02T10:26:47Z")

</div>

## Initial Solution

```yaml
- hosts: localhost
  gather_facts: false
  tasks:
    - name: 'read each line of the new env var file'
      ansible.builtin.set_fact:
        new_env: "{{ lookup('ansible.builtin.file', '/tmp/artifacts/.env') | split }}"
   - name: 'replace any lines that match the env vars of the new file'
     ansible.builtin.lineinfile:
       path: /home/user/project/.env
       regexp: '^{{ service_name }}='
       line: "{{ item }}"
     check_mode: true
     diff: true
     vars:
       service_name: "{{ item.split('=')[0] }}"
     loop: "{{ new_env }}"

```

This works because I read the new env var file and split it based on `=` character. I use the first instance and call it `service_name` in a loop and tell `lineinfile` to replace the instance with the updated value.

I am open to better solutions but thought I would keep this solution if there isn’t any

---

<div class="post-metadata">

**Author:** ![kurokobo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kurokobo/32/182_2.png) [@kurokobo](https://forum.ansible.com/u/kurokobo)\
**Post date:** [May 2, 2024, 12:11pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/3 "2024-05-02T12:11:35Z")

</div>

I suppose you could use `ansible.builtin.combine`, although any comments or blank lines in the production env file will be lost.

- Load env files as dict, by reading it as YAML file after replacing `=` with `: `
- Merge those two dict
- Save production env file by converting merged dict to YAML string and replacing `: ` with `=`

```yaml
- hosts: localhost
  gather_facts: false
  vars:
    env_production: "prod.env"
    env_patch: "patch.env"
  
  tasks:
    - name: Patch production env file
      ansible.builtin.copy:
        content: "{{ dict_merged | ansible.builtin.to_nice_yaml | regex_replace(': ', '=') }}"
        dest: "{{ env_production }}"
      vars:
        dict_production: "{{ lookup('file', env_production) | replace('=', ': ') | ansible.builtin.from_yaml }}"
        dict_patch: "{{ lookup('file', env_patch) | replace('=', ': ') | ansible.builtin.from_yaml }}"
        dict_merged: "{{ dict_production | ansible.builtin.combine(dict_patch) }}"

```

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [May 2, 2024, 1:07pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/4 "2024-05-02T13:07:09Z")

</div>

There are several great ways to read, write and modify INI files using Ansible, I [linked to them in this comment](http://forum.ansible.com/t/call-to-action-send-us-your-see-also-suggestions/4093/2#ini-conf-1), `.ini` / `.conf` / `.env` file lookup, fliters and modules:

- [community.general.ini\_file module](https://docs.ansible.com/ansible/latest/collections/community/general/ini_file_module.html)
- [ansible.builtin.ini lookup](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/ini_lookup.html)
- [community.general.to\_ini filter](https://docs.ansible.com/ansible/latest/collections/community/general/to_ini_filter.html)
- [community.general.from\_ini filter](https://docs.ansible.com/ansible/latest/collections/community/general/from_ini_filter.html)

JC INI parsers that can be used with [the JC filter](https://docs.ansible.com/ansible/latest/collections/community/general/jc_filter.html):

- [jc.parsers.ini](https://kellyjonbrazil.github.io/jc/docs/parsers/ini)
- [jc.parsers.ini\_dup](https://kellyjonbrazil.github.io/jc/docs/parsers/ini_dup)

I’d suggest using these rather than `lineinfile`.

---

<div class="post-metadata">

**Author:** ![kurokobo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kurokobo/32/182_2.png) [@kurokobo](https://forum.ansible.com/u/kurokobo)\
**Post date:** [May 2, 2024, 2:11pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/5 "2024-05-02T14:11:29Z")

</div>

@chris  
Thanks for updating, I first thought about treating it as an ini file, but I’m a bit obsessed with a solution that doesn’t use community.general as much as possible 😃

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [May 2, 2024, 2:16pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/6 "2024-05-02T14:16:20Z")

</div>

Fair enough, I suspect I don’t have any roles that don’t make a lot of use of `community.general` and especially the `jc` and `json_query` filters!

---

<div class="post-metadata">

**Author:** ![Denney-tech](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/denney-tech/32/1556_2.png) [@Denney-tech](https://forum.ansible.com/u/Denney-tech)\
**Post date:** [May 2, 2024, 5:11pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/7 "2024-05-02T17:11:47Z")

</div>

> [@chris](#):
>
> Fair enough, I suspect I don’t have any roles that don’t make a lot of use of `community.general` and especially the `jc` and `json_query` filters!

I don’t know what I do without `json_query`!

---

<div class="post-metadata">

**Author:** ![shertel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shertel/32/1241_2.png) [@shertel](https://forum.ansible.com/u/shertel)\
**Post date:** [May 6, 2024, 3:15pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/8 "2024-05-06T15:15:54Z")

</div>

> [@Denney-tech](#):
>
> I don’t know what I do without `json_query`!

since the filter moved to community.general I’ve just been using [GitHub - jqlang/jq: Command-line JSON processor](https://github.com/jqlang/jq) (so lightweight!)

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [June 5, 2024, 3:16pm UTC](https://forum.ansible.com/t/module-to-patch-update-environment-variables-file-with-version/5254/9 "2024-06-05T15:16:09Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
