`defaults/main.yaml` is not being considering in `ansible-test integration`

defaults/main.yaml is not being considering in ansible-test integration

I am writing integration tests for netscaler.adc collection.

my tests directory structure is as below.

❯ tree tests/integration
tests/integration
├── integration_config.yml
├── integration_config.yml.template
└── targets
    └── nsip
        ├── defaults
        │   └── main.yaml
        └── tasks
            └── main.yaml

4 directories, 4 files

defaults/main.yaml

❯ cat tests/integration/targets/nsip/defaults/main.yaml
ns_common_args: &ns_common_args
  nsip: "{{ nsip }}"
  nitro_user: "{{ nitro_user }}"
  nitro_pass: "{{ nitro_pass }}"
  nitro_protocol: "{{ nitro_protocol }}"
  validate_certs: "{{ validate_certs }}"
  save_config: "{{ save_config }}"

tasks/main.yaml

- name: Add NSIP | --check
  delegate_to: localhost
  register: result
  check_mode: true
  netscaler.adc.nsip:
    <<: *nsip_defaults
    state: present
    ipaddress: 1.1.1.1
    netmask: 255.255.255.0
    type: VIP

- name: Assert on add | --check
  ansible.builtin.assert:
    that:
      - "result.failed==false"
      - "result.changed==true"

- name: Add NSIP
  delegate_to: localhost
  register: result
  netscaler.adc.nsip:
    <<: *nsip_defaults
    state: present
    ipaddress: 1.1.1.1
    netmask: 255.255.255.0
    type: VIP

command I am running

> ansible-test integration

Error I am getting

> ansible-test integration 
Running nsip integration test role
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)

Syntax Error while loading YAML.
  found undefined alias

The error appears to be in '/Users/sumanthlingappa/.ansible/collections/ansible_collections/netscaler/adc/tests/output/.tmp/integration/nsip-n09cxv3o-ÅÑŚÌβŁÈ/tests/integration/targets/nsip/tasks/main.yaml': line 6, column 9, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  netscaler.adc.nsip:
    <<: *nsip_defaults
        ^ here
NOTICE: To resume at this test target, use the option: --start-at nsip
FATAL: Command "ansible-playbook nsip-8fm3qycu.yml -i inventory" returned exit status 4.
make: *** [test_int] Error 1

Please help to solve this error.

YAML anchors do not work over multiple files. (That has nothing to do with ansible-test, that’s something YAML specific.)

1 Like

Gathering facts cannot be disabled to my knowledge. If you need more control over the environment, you might want to use runme.sh-based tests and run ansible-playbook in them yourself.

Thank you for your quick reply @felixfontein.

Can you please help me with a sample repo using runme.sh?

Also, I am writing integration-tests to netscaler.adc collection.

I would like to run a github-action integration test on every pull-request. Are you aware of any github-action examples please?

Sumanth

For an example using GitHub Actions see: collection_template/.github/workflows/ansible-test.yml at main · ansible-collections/collection_template · GitHub

For an runme.sh example see for example community.general/tests/integration/targets/lookup_etcd3/runme.sh at main · ansible-collections/community.general · GitHub. If runme.sh is present, that one is executed instead of treating the directory as a role. In the shell script you can do things like installing dependencies etc. This is especially needed for testing callback and connection plugins, which you cannot simply test in a role. (Look at tests for these kind of plugins, then you see more instances.)

Thanks again for your response @felixfontein

I am not understanding the error ./runme.sh: line 7: ../../init.sh: No such file or directory

Context:

Collection Repo: GitHub - netscaler/ansible-collection-netscaleradc: Custom Ansible modules for NetScaler ADC and NetScaler ADM

❯ tree tests/integration                                                                                                                                                                                        
tests/integration                                                                                                                                                                                               
├── ansible.cfg                                                                                                                                                                                                 
├── init.sh                                                                                                                                                                                                     
├── integration_config.yml                                                                                                                                                                                      
├── inventory                                                                                                                                                                                                   
└── targets                                                                                                                                                                                                     
    ├── ipset                                                                                                                                                                                                   
        ├── ipset.yaml                                                                                                                                                                                          
        └── runme.sh                                                                                                                                                                                            

I need to save the netscaler API authentication via environment variables.
I have written tests/integration/init.sh to read tests/integration/integration_config.yml as below

❯ cat tests/integration/init.sh
# set the environment variables
export NETSCALER_NSIP=$(cat integration_config.yml | grep nsip | awk '{print $2}')
export NETSCALER_NITRO_USER=$(cat integration_config.yml | grep nitro_user | awk '{print $2}')
export NETSCALER_NITRO_PASS=$(cat integration_config.yml | grep nitro_pass | awk '{print $2}')
export NETSCALER_NITRO_PROTOCOL=$(cat integration_config.yml | grep nitro_protocol | awk '{print $2}')
export NETSCALER_VALIDATE_CERTS=$(cat integration_config.yml | grep validate_certs | awk '{print $2}')
export NETSCALER_SAVE_CONFIG=$(cat integration_config.yml | grep save_config | awk '{print $2}')
❯ cat tests/integration/integration_config.yml
---
nsip: 10.10.10.10
nitro_user: nsuser
nitro_pass: verysecretpassword
nitro_protocol: https
validate_certs: false
save_config: false
❯ cat tests/integration/targets/ipset/runme.sh                                                                                                                                                                  
#!/usr/bin/env bash                                                                                                                                                                                             
                                                                                                                                               
source ../../init.sh                                                                                                                                                                                            
                                                                                                                                                                                        
exec ansible-playbook ipset.yaml    
❯ ansible-test integration ipset
Running ipset integration test script


./runme.sh: line 7: ../../init.sh: No such file or directory



[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'
 ________________________ 
< PLAY [Sample Playbook] >
 ------------------------ 

 ____________________________ 
< TASK [Sample Task | ipset] >
 ---------------------------- 

fatal: [localhost]: FAILED! => {"changed": false, "msg": "missing required arguments: nsip"}
 
< PLAY RECAP >
 

localhost                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

NOTICE: To resume at this test target, use the option: --start-at ipset
FATAL: Command "./runme.sh" returned exit status 2.

I am not understanding the error ./runme.sh: line 7: ../../init.sh: No such file or directory

I see that ansible creates a temporary folder for this integration test and my init.sh is not included in the temporary folder

/Users/sumanth/.ansible/collections/ansible_collections/netscaler/adc/tests/output/.tmp/integration/
└── ipset-w89nvo37-ÅÑŚÌβŁÈ
    └── tests
        └── integration
            ├── integration.cfg
            ├── integration_config.yml
            ├── inventory
            └── targets
                └── ipset
                    ├── ipset.yaml
                    └── runme.sh

You could symlink init.sh into that directory, then it will be copied along.

You could also add needs/file/init.sh to the test’s aliases file to tell ansible-test that it should copy it along.

2 Likes

I copied the the below to aliases file. Still there is no init.sh in the ansible temporary directory.
:frowning:

❯ cat tests/integration/targets/ipset/aliases
needs/file/tests/integration/targets/init.sh

I read in the below doc that the PATH should be relative to the git root directory.

https://docs.ansible.com/ansible/latest/dev_guide/testing/sanity/integration-aliases.html#dependencies

I changed the init.sh to tests/integration instead of tests/integration/targets and changed the alias accordingly. It worked.

Thank you for your help @felixfontein

You originally mentioned that init.sh in tests/intrgration. Your needs/file/ statement claims it is in tests/integration/targets.

I didnt understand your last comment @felixfontein

My comment referred to

where it was in the wrong directory.