1

I'm trying to use ansible to update telegraf.conf's [[inputs.ping]].

telegraf.conf looks like the following:

[[inputs.ping]]
  urls = ["tac-temp1","tac-temp2", "tac-temp3","tac-temp4"] #tac
  count = 30
  timeout = 15.0
  [inputs.ping.tags]
  name = "tac"

[[inputs.ping]]
  urls = ["prod-temp1","prod-temp2", "prod-temp3","prod-temp4"] #prod
  count = 30
  timeout = 15.0
  [inputs.ping.tags]
  name = "prod"

[[inputs.ping]]
  urls = ["test-temp1","test-temp2", "test-temp3","test-temp4"] #test
  count = 30
  timeout = 15.0
  [inputs.ping.tags]
  name = "test"

I'm trying to add ,"tac-temp10" after ,"tac-temp4" in line 2 shown above.

- hosts: Servers
  become: yes
  become_method: sudo
  tasks:
    - name: Loading telegraf.conf content for search
      shell: cat /tmp/telegraf.conf
      register: tele_lookup

    - name: Adding Server to  /tmp/telegraf.conf if does not exists
      lineinfile:
             path: /tmp/telegraf.conf
             state: present
             regexp: '^((.*)"] #tac$)'       
             line: ',"tac-temp10"'      
             backup: yes
      when: tele_lookup.stdout.find('tac-temp10') != '0'

regexp: '^((.*)"] #tac$)' is replacing the whole line with ,"tac-temp10". Expected output:

[[inputs.ping]]
  urls = ["tac-temp1","tac-temp2", "tac-temp3","tac-temp4","tac-temp10"] #tac
  count = 30
  timeout = 15.0
  [inputs.ping.tags]
  name = "tac"
james
  • 132
  • 12
  • Systemic would be to enhance [ini](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/lookup/ini.py) plugin and adopt this advanced configuration format when [template](https://docs.ansible.com/ansible/latest/modules/template_module.html#template-template-a-file-out-to-a-remote-server) does not fit the purpose. – Vladimir Botka Jun 14 '19 at 12:40

1 Answers1

0

Warning: Ugly regexp ahead. Beware of unpredictable understanding for next guys (including you after time passed by...) doing maintenance.

The following will add your server at the end of the list if it is not already present (anywhere in the list) with a single idempotent task.

    - name: add our server if needed
      lineinfile:
        path: /tmp/test.conf
        backup: yes
        state: present
        regexp: '^( *urls *= *\[)(("(?!tac-temp10)([a-zA-Z0-9_-]*)",? *)*)(\] #tac)$'
        backrefs: yes
        line: '\1\2, "tac-temp10"\5'

You need to use backreferences to put back on the line the already matched parts of the expression. I used backup: yes so I could easily come back to the original for my tests. Feel free to drop it.

As you can see (and as advised in my warning) this is pretty much impossible to understand for anyone having to quickly read the code. If you have to do anything more fancy/complicated, consider using a template and storing your server list in a variable somewhere.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66
  • That helped! Thanks, Zeitounator! I wonder how that worked! `tac-temp10` was actually mentioned in the regexp! Agree! I would need to consider using template and variables. – james Jun 14 '19 at 14:19
  • The mention in the regexp is a negative lookahead: there will be a match only if tac-temp10 is not in the list already. Since we use backrefs, the line will be modified only if there is a match, else nothing will happen. – Zeitounator Jun 14 '19 at 14:31
  • 1
    got it, thanks! one more question: in `line: '\1\2, "tac-temp10"\5'` could you let me know how `\1\2` and `\5` helps? – james Jun 14 '19 at 14:50
  • These are backreferences to the capturing groups in the regexp. For more info see [how this is matched exatly](https://regex101.com/r/OlLrJf/1/) – Zeitounator Jun 14 '19 at 15:04
  • Ah, groups! gotcha! that makes the regex a bit readable now. Thanks again! :) – james Jun 14 '19 at 15:19