Home > Back-end >  ansible shell module fails to run sed for string insert operation
ansible shell module fails to run sed for string insert operation

Time:12-09

I am trying to insert a string in docker.conf file and it is failing on ansible may be due to my syntax. Works when I do it manually.

vars:

memlock_value: "16777216:16777216"
docker_options_file: "/etc/systemd/system/docker.service.d/docker-options.conf"

The task is

     - name: "Set in flag for ulimit in docker conf"
       shell: |
         - "sed '/^Environment=/ s/\"$/ --default-ulimit memlock={{ memlock_value }}\"/' {{ docker_options_file }} -i"

output:

 task path: /ansible-managed/jenkins-slave/slave1/workspace/teamd/run_ansible_playbook/k8s/baremetal/roles/team-node-config/tasks/main.yml
23:27:53  Tuesday 07 December 2021  07:27:53  0000 (0:00:11.047)       0:00:19.487 ****** 
fatal: [node1]: FAILED! => {"changed": true, "cmd": "- \"sed '/^Environment=/ s/\\\"$/ --default-ulimit memlock=16777216:16777216\\\"/' /etc/systemd/system/docker.service.d/docker-options.conf -i\"\n    \n", "delta": "0:00:00.004384", "end": "2021-12-07 07:27:53.586179", "msg": "non-zero return code", "rc": 2, "start": "2021-12-07 07:27:53.581795", "stderr": "/bin/sh: 0: Illegal option - ", "stderr_lines": ["/bin/sh: 0: Illegal option - "], "stdout": "", "stdout_lines": []}

The manual command works:

sed '/^Environment=/ s/"$/ --default-ulimit memlock=16777216:16777216"/' /etc/systemd/system/docker.service.d/docker-options.conf -i

I also tried lineinefile but it replaces the whole line instead of just inserting at end

    - name: "Set in flag for ulimit in docker conf"
      lineinfile:
        path: "{{ docker_options_file_dummy }}"
        regexp: '^Environment='
        insertafter: '^Environment=. $'
        line: "--default-ulimit memlock={{ memlock_value }}"
      ignore_errors: yes

output

=> {"backup": "", "changed": true, "msg": "line replaced"}
[Service]
--default-ulimit memlock=16777216:16777216

CodePudding user response:

Finally was able to figure out here it is but am still trying to figure out how to make it idempotent. multiple runs is keeping on adding the content at end of line.

    - name: "add ulimit in tests file to end of line in {{ dummy_file }}"
      lineinfile:
        dest: "{{ dummy_file }}"
        state: present
        regexp: '^(Environment="[^"]*)'
        backrefs: yes
        line: '\1 {{ ulimit_memlock_flag }}"'

file before task

[Service]
Environment="DOCKER_OPTS=  --data-root=/var/lib/docker --log-opt max-size=50m --log-opt max-file=5 --iptables=false"

file after task

[Service]
Environment="DOCKER_OPTS=  --data-root=/var/lib/docker --log-opt max-size=50m --log-opt max-file=5 --iptables=false --default-ulimit memlock=16777216:16777216"

CodePudding user response:

The literal text inside | block is not an array. Also, remove global " quotes - a command is not a single command but is split on spaces, so spaces have to be there.

Try:

   shell: |
     sed "'/^Environment=/ s/\"$/ --default-ulimit memlock={{ memlock_value }}\"/'" "{{ docker_options_file }}" -i

It's odd that -i option is on the end. I think It would be nicer to:

   shell: <
     sed -i -e
     "'/^Environment=/ s/\"$/ --default-ulimit memlock={{ memlock_value }}\"/'
     "{{ docker_options_file }}"

You should prefer command over shell

   command:
     argv:
       - sed
       - -i
       - -e
       - '/^Environment=/ s/"$/ --default-ulimit memlock={{ memlock_value }}"/'
       - "{{ docker_options_file }}"

And, you should prefer lininfile over sed. Something along:

 lineinfile:
    regexp: '^(Environment=[^"]*)"'
    backrefs: yes
    line: '\1  --default-ulimit memlock={{ memlock_value }}"'
    path: "{{ docker_options_file }}"
  • Related