Codemiester Codemiester - 3 months ago 92
Python Question

Ansible CSV lookup in Jinja2 template, how to handle missing key

j2 template and here is a snippet:

{% set denyGroups %}
{{lookup('csvfile', '{{ ansible_hostname }} file={{ csvFile }} delimiter=, col=5')}}
{% endset %}
{%- if denyGroups |trim() -%}
simple_deny_groups = {{ denyGroups |replace(";", ",") }}
{%- endif -%}


I am injecting values into the template based on csv values. However, if the key (ansible_hostname ) is not found in the csv, get this error:
AnsibleError: csvfile: list index out of range


How can I do this error handling? Check if its in the csv first. Now I could inject the value in tasks, but that will be a bit more cumbersome, and I prefer this template way. Thanks

Answer

list index out of range – it's a problem with number of columns.
Columns are counted from zero, so for col=5 – there must be 6 columns in the file.
If you want to return a default item if key is missing, use default=myvalue option.

Update: Let's look into the code:

def read_csv(self, filename, key, delimiter, encoding='utf-8', dflt=None, col=1):

    try:
        f = open(filename, 'r')
        creader = CSVReader(f, delimiter=to_bytes(delimiter), encoding=encoding)

        for row in creader:
            if row[0] == key:
                return row[int(col)]
    except Exception as e:
        raise AnsibleError("csvfile: %s" % to_str(e))

    return dflt

So in the csv like this:

mykey,val_a,val_b.val_c

key (column 0) is mykey, column 1 - val_a, column 2 - val_b, column 3 - val_c.

If there is a format error or your parameters are incorrect, exception will be triggered – you can't do anything about it. Trying to use col=4 with my example csv file will rise list index out of range exception.

If the key is not found in the file (row[0] == key was false for every line), default value will be returned (the one you specify with default= option).