ansible / molecule

Molecule aids in the development and testing of Ansible content: collections, playbooks and roles
https://ansible.readthedocs.io/projects/molecule/
MIT License
3.89k stars 664 forks source link

Allow changes in the base directory name for the role #1567

Closed amarao closed 4 years ago

amarao commented 6 years ago

Issue Type

Molecule version

2.19.0, via pip

Desired Behavior

Right now molecule search for role to test in the parent directory. If molecule tests for role foo, it expects to have it to be in a directory foo. If this directory was renamed into something different ('f.e. ansible-foo, or username.foo), it fails with following message:

ERROR! the role 'foo' was not found in /path/ansible-foo/molecule/default/roles:/tmp/molecule/ansible-foo/default/roles:/path:/path/ansible-foo/molecule/default

The error appears to have been in '/path/ansible-foo/molecule/default/playbook.yml': line 5, column 7, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  roles:
    - role: foo
      ^ here

The key issue is that most ansible roles are stored not under the role name, but with some prefixes - user (galaxy roles), or, in case of github, ansbile-* is a common prefix. It's really strange to have configuration role to be kept in the same directory. github.com/example/docker is expected to my docker, and github.com/example/ansible-docker is expected to be ansible role for docker.

I found a workaround for affected people, but it's dirty.

mkdir molecule/default/roles
ln -s '../../..' molecule/default/roles/${REAL_ROLE_NAME}

f.e. for role 'foo' it should be molecule/default/roles/foo -> '../../..'

decentral1se commented 6 years ago

Ah, I might have re-read this issue in the first place when I prompted you to create the issue but this is nonetheless worth having a discussion about. There is also the option to do https://github.com/ansible/molecule/blob/master/test/scenarios/driver/docker/molecule/default/molecule.yml#L22 to specify the roles path. This could potentially need better documenting.

I'll create another issue for the thing I was talking about on IRC now ...

ssbarnea commented 6 years ago

As someone that was also confused about role location and how to deal with them, I support fixing this even if this may only need changing documentation or the way messages are printed.

icollar commented 6 years ago

Specifying the ANSIBLE_ROLE_PATH won't resolve this as Ansible looks for roles by searching all directories on the ANSIBLE_ROLE_PATH for directories with the same name as the role. Very quick example of this:

icollar@dev:~$ molecule init role --role-name rolename
--> Initializing new role rolename...
Initialized role in /home/icollar/rolename successfully.
icollar@dev:~$ cd rolename 
icollar@dev:~/rolename$ molecule syntax
--> Validating schema /home/icollar/rolename/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    └── syntax

--> Scenario: 'default'
--> Action: 'syntax'

    playbook: /home/icollar/rolename/molecule/default/playbook.yml

icollar@dev:~/rolename$ cd ..
icollar@dev:~$ mv rolename rolename_new
icollar@dev:~$ cd rolename_new 
icollar@dev:~/rolename_new$ molecule syntax
--> Validating schema /home/icollar/rolename_new/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    └── syntax

--> Scenario: 'default'
--> Action: 'syntax'
ERROR! the role 'rolename' was not found in /home/icollar/rolename_new/molecule/default/roles:/tmp/molecule/rolename_new/default/roles:/home/icollar:/home/icollar/rolename_new/molecule/default

The error appears to have been in '/home/icollar/rolename_new/molecule/default/playbook.yml': line 5, column 7, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  roles:
    - role: rolename
      ^ here

ERROR: 

The resolution for this needs to be some form of symlink created in a directoy like the dependency role directory, from my example this would be /tmp/molecule/rolename_new/default/roles. This only needs to happen if the directory name does not match the rolename. My preference for a symlink on this is due to being able to run molecule converge multiple times whilst developing a new role. This would allow updates to be picked up automatically.

Example of it working, carrying on from above:

icollar@dev:~/rolename_new$  mkdir -p /tmp/molecule/rolename_new/default/roles
icollar@dev:~/rolename_new$ ln -nfs $PWD /tmp/molecule/rolename_new/default/roles/rolename
icollar@dev:~/rolename_new$ molecule syntax
--> Validating schema /home/icollar/rolename_new/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    └── syntax

--> Scenario: 'default'
--> Action: 'syntax'

    playbook: /home/icollar/rolename_new/molecule/default/playbook.yml

There might be a more appropriate solution to add a new path to the ANSIBLE_ROLE_PATH, but I've only looked into this for briefly.

icollar commented 6 years ago

Jenkins jobs generated from Multibranch Pipeline or Bitbucket Team/Project fail due to this issue as they checkout into branch named directory. A workaround can be put into the Jenkinsfile, to create a symlink or change directory names, but it is a workaround.

icollar commented 6 years ago

Okay, I've another workaround, since I've realised that Ansible Roles are named by their directory, unless a rename is included in meta/main.yml. You can update your molecule/default/playbook.yml to lookup the current directory with the following:

- name: Converge
  hosts: all
  roles:
    - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"