简体   繁体   中英

Ansible Nested variables and Jinja2 templates

I'm trying to figure out why my jinja2 template (and ansible for that matter) cannot find my variables in my inventory file.

Here is my inventory file:

all:
  hosts:
    test05:
      ansible_host: 192.168.x.x
      filebeat:
        version: 7.15.2
        applog:
          - title: Separate Application Log Path with Tags
            type: log
            paths: 
              - /var/log/something/moresomething/current
            tags: '["something", "application"]'
          - title: Separate Application Log Path, with Tags, and "decode_json_fields" processor.
            type: log
            paths:
              - /var/log/something/moresomething/blah-shell.log
            tags: ["application", "something"]
            fields: ["message"]
            depth: 2
          - title: Separate Application Log Path, with Tags, and Multiline fields
            type: log
            paths:
              - /var/log/something/moresomething/production.log
            tags: ["application", "something"]
            multiline_type: pattern
            multiline_patern: 'Started'
            multiline_negate: true
            multiline_match: after

Then attempting to get the first title. I'm doing the following:

- name: debugging
  debug:
    var: filebeat.applog.title

when I run this I end up getting filebeat.applog.title: VARIABLE IS NOT DEFINED! which I think is good since it doesn't know what title I want. So changing this to

- name: debugging
  debug:
    var: filebeat.applog.0.title

I end up getting what I want filebeat.applog.0.title: Separate Application Log Path with Tags . However, how do I use this in a jinja2 template?

I have the following for a template, I know I need to update this to loop through the different items in my inventory. That's a different problem on how to loop through this.

title: {{ filebeat.applog.title }}
  - type: {{ filebeat.applog.type }}
    enabled: true
    paths:
      - {{ filebeat.applog.path }}
   tags: {{ filebeat.applog.tags }}
{% if filebeat.applog.fields is defined %}
  processors:
    - decode_json_fields:
        fields: {{ filebeat.applog.fields }}
        max_depth: {{ filebeat.applog.depth }}
        target: {{ filebeat.applog.target | default "" }}
{% endif %}
{% if filebeat.applog.multiline_pattern  is defined %}
  multiline.type: {{ filebeat.applog.multiline_type }}
  multiline.pattern: {{ filebeat.applog.multiline_pattern }}
  multiline.negate: {{ filebeat.applog.multiline_negate }}
  multiline.match: {{ filebeat.applog.multiline_match }}
{% endif %}

each time I get the following, even when I do use {{ filebeat.applog.0.logtitle }} in the template:

fatal: [test05]: FAILED! => changed=false
  msg: |-
    AnsibleError: template error while templating string: expected token 'end of print statement', got 'string'. String: title: {{ filebeat.applog.title }}
      - type: {{ filebeat.applog.type }}
        enabled: true
        paths:
          - {{ filebeat.applog.path }}
       tags: {{ filebeat.applog.tags }}
    {% if filebeat.applog.fields is defined %}
      processors:
        - decode_json_fields:
            fields: {{ filebeat.applog.fields }}
            max_depth: {{ filebeat.applog.depth }}
            target: {{ filebeat.applog.target | default "" }}
    {% endif %}
    {% if filebeat.applog.multiline_pattern  is defined %}
      multiline.type: {{ filebeat.applog.multiline_type }}
      multiline.pattern: {{ filebeat.applog.multiline_pattern }}
      multiline.negate: {{ filebeat.applog.multiline_negate }}
      multiline.match: {{ filebeat.applog.multiline_match }}
    {% endif %}

I'm not sure what I'm missing or doing wrong. I'm thinking I'm doing something wrong since this the first time doing something like this.

So the template you have should either:

  • have a for loop to iterate over filebeat.applog

OR

  • reference n'th element of filebeat.applog

Aside from that, there are some errors like below:

1.

target: {{ filebeat.applog.target | default "" }}

This is the main one, and this is what the error message is complaining about, ie got 'string' . The correct usage for default filter is {{ some_variable | default("") }} {{ some_variable | default("") }} .

2.

{% if filebeat.applog.multiline_pattern is defined %}

In the inventory this variable is mis-spelled, ie multiline_patern (missing one "t"). Fix this in your inventory.

3.

when I do use {{ filebeat.applog.0.logtitle }} in the template

This should be {{ filebeat.applog.0.title }} to work.


Considering the above fixes, a template that loops over filebeat.applog such as below should work:

{% for applog in filebeat.applog %}
title: {{ applog.title }}
  - type: {{ applog.type }}
    enabled: true
    paths: {{ applog.paths }}
    tags: {{ applog.tags }}
{% if applog.fields is defined %}
  processors:
    - decode_json_fields:
        fields: {{ applog.fields }}
        max_depth: {{ applog.depth }}
        target: {{ applog.target | default("") }}
{% endif %}
{% if applog.multiline_pattern is defined %}
  multiline.type: {{ applog.multiline_type }}
  multiline.pattern: {{ applog.multiline_pattern }}
  multiline.negate: {{ applog.multiline_negate }}
  multiline.match: {{ applog.multiline_match }}
{% endif %}
{% endfor %}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM