# test code for iterating with lookup plugins
# (c) 2014, James Tanner <tanner.jc@gmail.com>

# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

# WITH_ITEMS

- name: test with_items
  set_fact: "{{ item }}=moo"
  with_items:
    - 'foo'
    - 'bar'

- debug: var=foo
- debug: var=bar

- name: verify with_items results
  assert:
    that:
        - "foo == 'moo'"
        - "bar == 'moo'"

# WITH_NESTED

- name: test with_nested
  set_fact: "{{ item.0 + item.1 }}=x"
  with_nested:
    - [ 'a', 'b' ]
    - [ 'c', 'd' ]

- debug: var=ac
- debug: var=ad
- debug: var=bc
- debug: var=bd

- name: verify with_nested results
  assert:
    that:
        - "ac == 'x'"
        - "ad == 'x'"
        - "bc == 'x'"
        - "bd == 'x'"

# WITH_SEQUENCE

- name: test with_sequence
  set_fact: "{{ 'x' + item }}={{ item }}"
  with_sequence: start=0 end=3

- name: test with_sequence backwards
  set_fact: "{{ 'y' + item }}={{ item }}"
  with_sequence: start=3 end=0 stride=-1

- name: verify with_sequence
  assert:
    that:
        - "x0 == '0'"
        - "x1 == '1'"
        - "x2 == '2'"
        - "x3 == '3'"
        - "y3 == '3'"
        - "y2 == '2'"
        - "y1 == '1'"
        - "y0 == '0'"

- name: test with_sequence not failing on count == 0
  debug: msg='previously failed with backward counting error'
  with_sequence: count=0
  register: count_of_zero

- name: test with_sequence does 1 when start == end
  debug: msg='should run once'
  with_sequence: start=1 end=1
  register: start_equal_end

- name: test with_sequence count 1
  set_fact: "{{ 'x' + item }}={{ item }}"
  with_sequence: count=1
  register: count_of_one

- assert:
    that:
        - start_equal_end is not skipped
        - count_of_zero is skipped
        - count_of_one is not skipped

- name: test with_sequence shortcut syntax (end)
  set_fact: "{{ 'ws_z_' + item }}={{ item }}"
  with_sequence: '4'

- name: test with_sequence shortcut syntax (start-end/stride)
  set_fact: "{{ 'ws_z_' + item }}=stride_{{ item }}"
  with_sequence: '2-6/2'

- name: test with_sequence shortcut syntax (start-end:format)
  set_fact: "{{ 'ws_z_' + item }}={{ item }}"
  with_sequence: '7-8:host%02d'

- name: verify with_sequence shortcut syntax
  assert:
    that:
        - "ws_z_1 == '1'"
        - "ws_z_2 == 'stride_2'"
        - "ws_z_3 == '3'"
        - "ws_z_4 == 'stride_4'"
        - "ws_z_6 == 'stride_6'"
        - "ws_z_host07 == 'host07'"
        - "ws_z_host08 == 'host08'"

# WITH_RANDOM_CHOICE

- name: test with_random_choice
  set_fact: "random={{ item }}"
  with_random_choice:
    - "foo"
    - "bar"

- name: verify with_random_choice
  assert:
    that:
        - "random in ['foo', 'bar']"

# WITH_SUBELEMENTS

- name: test with_subelements
  set_fact: "{{ '_'+ item.0.id + item.1 }}={{ item.1 }}"
  with_subelements:
    - "{{element_data}}"
    - the_list

- name: verify with_subelements results
  assert:
    that:
        - "_xf == 'f'"
        - "_xd == 'd'"
        - "_ye == 'e'"
        - "_yf == 'f'"

- name: test with_subelements in subkeys
  set_fact: "{{ '_'+ item.0.id + item.1 }}={{ item.1 }}"
  with_subelements:
    - "{{element_data}}"
    - the.sub.key.list

- name: verify with_subelements in subkeys results
  assert:
    that:
        - "_xq == 'q'"
        - "_xr == 'r'"
        - "_yi == 'i'"
        - "_yo == 'o'"

- name: test with_subelements with missing key or subkey
  set_fact: "{{ '_'+ item.0.id + item.1 }}={{ item.1 }}"
  with_subelements:
    - "{{element_data_missing}}"
    - the.sub.key.list
    - skip_missing: yes
  register: _subelements_missing_subkeys

- debug: var=_subelements_missing_subkeys
- debug: var=_subelements_missing_subkeys.results|length
- name: verify with_subelements in subkeys results
  assert:
    that:
        - _subelements_missing_subkeys.skipped is not defined
        - _subelements_missing_subkeys.results|length == 2
        - "_xk == 'k'"
        - "_xl == 'l'"


# WITH_TOGETHER

- name: test with_together
  #shell: echo {{ item }}
  set_fact: "{{ item.0 }}={{ item.1 }}"
  with_together:
    - [ 'a', 'b', 'c', 'd' ]
    - [ '1', '2', '3', '4' ]

- name: verify with_together results
  assert:
    that:
        - "a == '1'"
        - "b == '2'"
        - "c == '3'"
        - "d == '4'"

# WITH_FIRST_FOUND

- name: test with_first_found
  #shell: echo {{ item }}
  set_fact: "first_found={{ item }}"
  with_first_found:
    - "{{ role_path + '/files/does_not_exist' }}"
    - "{{ role_path + '/files/foo1' }}"
    - "{{ role_path + '/files/bar1' }}"

- name: set expected
  set_fact: first_expected="{{ role_path + '/files/foo1' }}"

- name: set unexpected
  set_fact: first_unexpected="{{ role_path + '/files/bar1' }}"

- name: verify with_first_found results
  assert:
    that:
        - "first_found == first_expected"
        - "first_found != first_unexpected"

# WITH_LINES

- name: test with_lines
  #shell: echo "{{ item }}"
  set_fact: "{{ item }}=set"
  with_lines: for i in $(seq 1 5); do echo "l$i" ; done;

- name: verify with_lines results
  assert:
    that:
        - "l1 == 'set'"
        - "l2 == 'set'"
        - "l3 == 'set'"
        - "l4 == 'set'"
        - "l5 == 'set'"

# WITH_INDEX
- name: create unindexed list
  shell: for i in $(seq 1 5); do echo "x" ; done;
  register: list_data

- name: create indexed list
  set_fact: "{{ item[1] + item[0]|string }}=set"
  with_indexed_items: "{{list_data.stdout_lines}}"

- name: verify with_indexed_items result
  assert:
    that:
        - "x0 == 'set'"
        - "x1 == 'set'"
        - "x2 == 'set'"
        - "x3 == 'set'"
        - "x4 == 'set'"

# WITH_FLATTENED

- name: test with_flattened
  set_fact: "{{ item }}=flattened"
  with_flattened:
    - [ 'a__' ]
    - [ 'b__', ['c__', 'd__'] ]

- name: verify with_flattened results
  assert:
    that:
        - "a__ == 'flattened'"
        - "b__ == 'flattened'"
        - "c__ == 'flattened'"
        - "d__ == 'flattened'"


# q(FIRST_FOUND)
- name: test q(first_found) with no files produces empty list
  set_fact:
    first_found_var: "{{ q('first_found', params, errors='ignore') }}"
  vars:
    params:
      files: "not_a_file.yaml"

- name: verify q(first_found) result
  assert:
    that:
      - "first_found_var == []"

- name: test lookup(first_found) with no files produces empty string
  set_fact:
    first_found_var: "{{ lookup('first_found', params, errors='ignore') }}"
  vars:
    params:
      files: "not_a_file.yaml"

- name: verify lookup(first_found) result
  assert:
    that:
      - "first_found_var == ''"

# NOTE: skip: True deprecated e17a2b502d6601be53c60d7ba1c627df419460c9, remove 2.12
- name: test first_found with no matches and skip=True does nothing
  set_fact: "this_not_set={{ item }}"
  vars:
    params:
      files:
        - not/a/file.yaml
        - another/non/file.yaml
      skip: True
  loop: "{{ q('first_found', params) }}"

- name: verify skip
  assert:
    that:
      - "this_not_set is not defined"

- name: test first_found with no matches and errors='ignore' skips in a loop
  set_fact: "this_not_set={{ item }}"
  vars:
    params:
      files:
        - not/a/file.yaml
        - another/non/file.yaml
  loop: "{{ query('first_found', params, errors='ignore') }}"

- name: verify errors=ignore
  assert:
    that:
      - "this_not_set is not defined"
