starryn1ght
starryn1ght

Reputation: 123

How can I save a nested dictionary as variable in jinja2 ansible?

I am trying to create a prometheus.yml.j2 template for our ansible role. This is the variable:

SCRAPE_CONFIGS:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'postgresql'
    static_configs:
      - targets: ['postgresql-exporter:9187']

I tried:

scrape_config:
  {% for scrape in SCRAPE_CONFIGS -%}
    {{ scrape }}
  {% endfor %}

This is the output:

scrape_config:
  {'job_name': 'prometheus', 'static_configs': [{'targets': ['localhost:9090']}]}
  {'job_name': 'postgresql', 'static_configs': [{'targets': ['postgresql-exporter:9187']}]}

But it should look like the variable itself:

  scrape_config:
    - job_name: 'prometheus'
      static_configs:
        - targets: ['localhost:9090']

    - job_name: 'postgresql'
      static_configs:
        - targets: ['postgresql-exporter:9187']

Otherwise the prometheus container will throw an syntax error because it can't read the prometheus.yml config file correctly. Does anyone have a better suggestion how to iterate through this nested dictonary? The structure should remain the same. It should also be possible to add different scrape_configs with more entries like:

- job_name: 'elasticsearch'
  scrape_intervall: 10s
  scrape_timeout: 5s
  static_configs:
    - targets: ['elasticsearch-exporter:9114']

Upvotes: 1

Views: 496

Answers (1)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39119

Why don't you just use a set_fact in order to recreate you requested dictionnary structure, then dump the whole thing as YAML with the filter to_yaml?

Given the playbook:

- hosts: all
  gather_facts: no

  tasks:
    - set_fact:
        config: 
          scrape_config: "{{ SCRAPE_CONFIGS }}"
      vars:
        SCRAPE_CONFIGS:
          - job_name: 'prometheus'
            static_configs:
              - targets: ['localhost:9090']

          - job_name: 'postgresql'
            static_configs:
              - targets: ['postgresql-exporter:9187']

    - copy:
        content: "{{ config | to_yaml }}"
        dest: prometheus.yml.j2

This will create a file prometheus.yml.j2 with the content:

scrape_config:
- job_name: prometheus
  static_configs:
  - targets: ['localhost:9090']
- job_name: postgresql
  static_configs:
  - targets: ['postgresql-exporter:9187']

And to add an extra element, the playbook

- hosts: all
  gather_facts: no

  tasks:
    - set_fact:
        config: 
          scrape_config: "{{ SCRAPE_CONFIGS + elements_to_add }}"
      vars:
        SCRAPE_CONFIGS:
          - job_name: 'prometheus'
            static_configs:
              - targets: ['localhost:9090']

          - job_name: 'postgresql'
            static_configs:
              - targets: ['postgresql-exporter:9187']

        elements_to_add:
          - job_name: 'elasticsearch'
            scrape_intervall: 10s
            scrape_timeout: 5s
            static_configs:
              - targets: ['elasticsearch-exporter:9114']

    - copy:
        content: "{{ config | to_yaml }}"
        dest: prometheus.yml.j2

Will create a file prometheus.yml.j2 with the content:

scrape_config:
- job_name: prometheus
  static_configs:
  - targets: ['localhost:9090']
- job_name: postgresql
  static_configs:
  - targets: ['postgresql-exporter:9187']
- job_name: elasticsearch
  scrape_intervall: 10s
  scrape_timeout: 5s
  static_configs:
  - targets: ['elasticsearch-exporter:9114']

Upvotes: 2

Related Questions