Ansible-lint resolving symlinks to their destinations?

I’ve started seeing a weird behavior with ansible-lint quite recently. Specifically, that it seems it started to resolving symlinks to their destination.

While it can be fine in most cases, it is very confusing in CI, where instead of installing role as it should be installed, we symlink it from CI-prepared directory to DEFAULT_ROLES_PATH

An example of that is Zuul

We make a symlink from /home/zuul/src/opendev.org/openstack/ansible-role-httpd/ to /etc/ansible/roles/httpd/ (as we expect users to have role installed under it’s proper name).

Then, our example playbook tries to be quite abstract, ie:

---

- name: Installing Apache Web Server
  hosts: httpd
  roles:
    - role: "{{ playbook_dir | dirname | basename }}"

So while we run ansible-lint /etc/ansible/roles/httpd/examples/playbook.yml it actually seems to launch “original” location:
/home/zuul/src/opendev.org/openstack/ansible-role-httpd/examples/playbook.yml

Full output is like this:

+ /opt/ansible-runtime/bin/ansible-lint /etc/ansible/roles/httpd/examples/playbook.yml -c /home/zuul/src/opendev.org/openstack/openstack-ansible/.ansible-lint
WARNING: PATH altered to include /opt/ansible-runtime/bin, /opt/ansible-runtime/bin :: This is usually a sign of broken local setup, which can cause unexpected behaviors.
[DEPRECATION WARNING]: DEFAULT_GATHER_SUBSET option, the module_defaults 
keyword is a more generic version and can apply to all calls to the 
M(ansible.builtin.gather_facts) or M(ansible.builtin.setup) actions, use 
module_defaults instead. This feature will be removed from ansible-core in 
version 2.18. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.
WARNING  Listing 1 violation(s) that are fatal
syntax-check[specific]: the role 'ansible-role-httpd' was not found in /home/zuul/src/opendev.org/openstack/ansible-role-httpd/examples/roles:/root/.cache/ansible-compat/8cbc9d/roles:/etc/ansible/roles:/etc/ansible/roles/ceph-ansible/roles:/home/zuul/src/opendev.org/openstack/ansible-role-httpd/examples
/home/zuul/src/opendev.org/openstack/ansible-role-httpd/examples/playbook.yml:5:7


# Rule Violation Summary

  1 syntax-check profile:min tags:core,unskippable

Failed: 1 failure(s), 0 warning(s) on 1 files.

Any ideas on how to prevent this from happening?

Is this the same issue as this molecule one?

Does setting ANSIBLE_ROLES_PATH to something like this solve the issue?

/home/zuul/src/opendev.org/openstack:/root/.cache/ansible-compat/8cbc9d/roles:/etc/ansible/roles:/etc/ansible/roles/ceph-ansible/roles```

Yeah, I think that the bug report mentioned is related. I think we’ve started observing the issue between Jan 14 and Feb 17.

And sure, adjusting ANSIBLE_ROLES_PATH would sort it out. But the point is kind of to set the CI in a way that most consumers will use roles as well, so we’d love to avoid this workaround.

Another workaround would be in our case to leave an example playbook alone, and supply molecule a different converge file. As this approach with role: "{{ playbook_dir | dirname | basename }}" was to satisfy both molecule and ansible-lint which we execute separately.

At this moment there are no plans to change this because only by resolving the paths we can get a normalized file path that we can compare with others and avoid duplicates. Also there are tools that fail to resolve symlinked paths so resolving them gives a better experience.

If the very long path annoys you, you can probably ensure that your preinstalled dependencies are copied inside the current project because in this case ansible-lint will report paths relative to project directory.

1 Like

It is slightly more complicated, unfortunately

Zuul does prepare for us repositories in /home/user/zuul/repo/ansible-role-$role_name

So what we are doing, is symlinking from that path to ANSIBLE_ROLES_PATH with renaming from ansible-role-$role_name to expected $role_name

Thus eventually you would get a completely different role name depending if you execute molecule or ansible. And then also a difference if you run with zuul or locally, where installation will be handled by galaxy.

With that such approach allows to test current role/collection dependencies as well, as zuul can include other patches and speculatively merge them in CI jobs… I think we’ve found a workaround this somehow for now though, but it’s just a bit unfortunate that behavior is different.