We want to test (ansible-test) a lookup plugin that depends on a number of environment variables existing on the controller. However, ansible-test seems to create a very limited environment to run tests in and this does not include the required env vars. Is there a supported way to customize the environment to have the needed vars?
Also, we run our tests within a container that has all of the community and 3rd party collections already but our code under test is in its own directory. We’ve had to make some workarounds so that the supporting collections are found but it would be ideal if we could customize ANSIBLE_COLLECTIONS_PATH for the test environment instead of it being set explicitly to the current working directory.
The limited documentation around this (here) is unclear on whether this is possible. It somewhat implies that you can modify util.py but that doesn’t seem like a sustainable approach.
Thank you for replying @gundalow . I was just looking for other lookup plugins that might depend on ENV vars and how they are tested. There aren’t many it seems. I did find this one and they seem to be trying to apply the environment keyword to the set_fact module/action but I’m pretty sure this doesn’t work as it didn’t work for me when I tried it.
environment only affects modules/remote execution, set_fact is a ‘controller action’ and never even touches the remote, even if it did, lookup plugins always run on the controller (all plugins do, except modules/module_utils).
You must invoke ansible itself in the context of any environment variable you want plugins to be affected by.
Yes. Exactly. The problem is that ansible-test generates its own very limited environment to launch ansible in. Because of this we lose all of the ENV vars that we need to test this plugin.
Generally speaking, instead of making the integration target a role (although it could still be shaped that way), you would make a runme.sh based integration test target, that could set the env vars in the script, and then invoke a playbook with ansible-playbook. There are a number of examples in the ansible/ansible repo of runme.sh targets.
It would not be able to rely on injecting local env vars into the test container though, you would have to use an integration_config.yml file to do that, and there are examples through the ansible-collections org on GitHub:
Ok, the way you gents are talking about this it sounds like runme.sh is a common testing pattern but I haven’t seen that mentioned in any of the testing documentation. Also, integration_config.yml is just mentioned briefly in the docs as being useful (here) but gives no information on its purpose or how to configure it. Don’t get me wrong, we use this file but we’ve just had to infer things from the limited documentation and whatever examples we can find.
Ah, now that you’ve made me aware of runme.sh I do see just a mention of it in the integration test documentation (here). But it is only mentioned - no detail is given on its use or how its execution differs from the role-based testing. This would be super useful information.
i believe that 99% of the use of runme.sh is done in testing ansible-core, so the community never bothered to really explain how it works for community testing.
It basically runs ‘instead’ of the role and the rc of the script determines success/failure of the test. It has a lot of flexibility, but the reporting is not as good, why i tend to use the ‘ansible calling ansible’ pattern in all new tests that require it.
Ok, so it appears that ansible-test still creates a limited environment when launching the script. It’s just now we have the ability to add vars back to the environment before launching ansible, right? So we’ll need something to capture the initial environment into a file or script and then restore that environment in runme.sh.
As of ansible-core 2.19, environment variables can be set on the controller using the aliases file of an integration test. For example:
This is intended for non-sensitive static values, which should be committed along with the tests. Prior to that feature being implemented, using a runme.sh was the best way to accomplish the same effect. If this feature would be useful in earlier versions of ansible-test, I’m open to backporting it.
For dynamic or sensitive values which should not be in version control, using integration_config.yml is the recommended approach, since it allows you to provide Ansible variables to the test environment, even if it’s running inside a container or on a remote host.
When ansible-test generates a playbook for running integration tests, it specifies integration_config.yml for the vars_files keyword. All of the variables in that file will be visible to the controller (ansible-playbook), regardless of where it’s running. Those variables can be used just like any other to affect module execution, whether on the controller or target.