aoenger
aoenger

Reputation: 19

ansible undefined variable in task

I use molecule to test ansible role. Task is copy template using variable.
ansible/task/main.yml

---
- name: copy manifest billing
  template:
    src: templates/service.j2
    dest: "{{ item }}"
    with_items:
      "{{ services }}"

ansible/vars/main.yml

services:
  - billing
  - cart
  - checkout

When i run "molecule converge" I get error

TASK [ansible : copy manifest billing] *****************************************
fatal: [instance]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/home/user/ansible/tasks/main.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n- name: copy manifest billing\n  ^ here\n"}

Upvotes: 1

Views: 22101

Answers (4)

Vladimir Botka
Vladimir Botka

Reputation: 68274

Q: "The error was: 'item' is undefined"

A: The indentation is wrong. with_items is not a parameter of the module. It's the directive to loop the module. Correct syntax is

    ---
    - name: copy manifest billing
      template:
        src: templates/service.j2
        dest: "{{ item }}"
      with_items:
        "{{ services }}"

Notes

    with_items: "{{ services }}"
  • With the release of Ansible 2.5, the recommended way to perform loops is the use of the new loop keyword instead of with_X style loop
    loop: "{{ services }}"
  • Inconsistent results of the command ansible-playbook playbook.yml --check. The command does NOT complain "Invalid options for template: with_items"! But, for example, with the module debug the checking works as expected
    - debug:
        var: item
        with_items: "{{ services }}"
fatal: [localhost]: FAILED! => {"msg": "Invalid options for debug: with_items"}

Upvotes: 5

aoenger
aoenger

Reputation: 19

Thanks you.
I use one j2 template for multiple config.
I need take every item in services items in same config file name.
Part of my templates/service.j2

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: "{{ common.fullname }}-{% for item in services %}{{ item }}{% endfor %}"

But it's not work right for me.
I should get one of the list values in the file of the same name and the next value from the list in the corresponding file name.
Now it take

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: "hf-billingcartcheckout"

Upvotes: 0

zegoat7
zegoat7

Reputation: 579

As mentioned in the answers before, it is an indentation problem.

Try the Ansible Template tester. It is very useful when it comes to checking your Ansible templates before adding them to your playbook.

Upvotes: 0

ozlevka
ozlevka

Reputation: 2156

You should include variables from file:

---
- hosts: localhost
  tasks:
  - include_vars: 
     file: ansible/vars/main.yml
  - name: copy manifest billing
    template:
      src: templates/service.j2
      dest: "{{ item }}"
    with_items:
      "{{ services }}"

Or explicitly add vars_files

- hosts: localhost
  vars_files:
    - ansible/vars/main.yml
  tasks:   
  - name: copy manifest billing
    template:
      src: templates/service.j2
      dest: "{{ item }}"
    with_items:
      "{{ services }}"

Upvotes: 2

Related Questions