Add InfluxDB settings in Telegraf using Ansible: [WARNING]: The value [...] (type list) in a string field was converted to "[...]" (type string)

Posted by ads' corner on Tuesday, 2020-06-23
Posted in [Ansible][Influxdb][Linux][Software]

I’m in the process of updating my entire home setup, and integrate everything properly. Part of this process is to automate everything, and use Ansible Playbooks to deploy devices and configurations.

Today: install Telegraf and send data to InfluxDB

Along the way something broke, and Ansible doesn’t really like me anymore. But let’s start at the beginning.

In the Telegraf configuration in /etc/telegraf/telegraf.conf one can specify output plugins. One of them (probably the most used one) is “InfluxDB”. The InfluxDB instance(s) are specified as a [...] list. In Ansible I somehow need to have this list as a string, and write it into the configuration file. This happens:

TASK [Update telegraf.conf InfluxDB settings] ***************************************************
changed: [localhost] => (item={'section': '[outputs.influxdb]', 'option': 'urls', 'value': ['http://192.168.xxx.xxx:8086'], 'state': 'present'})
[WARNING]: The value ['http://192.168.xxx.xxx:8086'] (type list) in a string field was converted to "['http://192.168.xxx.xxx:8086']" (type string). If this does not look like what you expect, quote the entire value to ensure it does not change.

Looks nasty …

The Playbook I’m using:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  # setup the InfluxDB output plugin
  - name: Update telegraf.conf InfluxDB settings
    ini_file:
      path: "/etc/telegraf/telegraf.conf"
      section: "{{ item.section }}"
      option: "{{ item.option }}"
      value: "{{ item.value }}"
      state: "{{ item.state }}"
    loop:
      - { section: "[outputs.influxdb]", option: "urls", value: "{{ influxdb_url }}", state: present }
    notify:
      - restart telegraf

The Task is a bit longer than that, but for this purpose the above example is enough. Note that even though the [ini_file](https://docs.ansible.com/ansible/latest/modules/ini_file_module.html) plugin understands sections, you have to specify an extra set of square backets here, because the Telegraf config is using [[...]] instead of [...]:

1
2
# Configuration for sending metrics to InfluxDB
[[outputs.influxdb]]

The InfluxDB urls are supposed to be a list:

1
urls = ["http://192.168.0.1:8086", "http://192.168.0.3:8086", "http://192.168.0.3:8086"]

If you store that list in an Ansible variable, Ansible (or more exactly: the YAML parser) complains that it recognized a list and converts that into what it thinks is the right data type. But in this case that’s neither nesessary nor what I want. There are two ways to work around that problem:

The config approach

The Ansible configuration file (ansible.cfg) knows a variable string_conversion_action. Since Ansible 2.8 this is set to warn, and apparently will change to error in 2.12. If this is set to ignore, the problem goes away.

However that is quite a brutal approach: this applies to all Playbooks. There might be valid use cases which will be hidden if that setting is changed to ignore.

The string approach

After testing around for a while I found that the YAML parser only complains (and converts) if the string starts with a [. And Telegraf doesn’t care how many spaces are after the =. The easy solution is:

1
influxdb_url: ' ["http://192.168.xxx.xxx:8086"]'

Note there is a space at the beginning of the string. This makes the YAML parser happy, and no longer converts the string into an Ansible list. As a result the /etc/telegraf/telegraf.conf looks like:

1
2
[[outputs.influxdb]]
urls =  ["http://192.168.xxx.xxx:8086"]

Categories: [Ansible] [Influxdb] [Linux] [Software]