Skip to content

Commit

Permalink
Fix role name handling in prerun.py (#1490)
Browse files Browse the repository at this point in the history
* src/ansiblelint/prerun.py: Fix role name from SCM

According to
https://galaxy.ansible.com/docs/contributing/creating_role.html#role-metadata:

"role_name is not used at all if the role is installed using its Git URL.
 Instead, the name of the repo is used."

So, make _install_galaxy_role() respect this to compute the role
name. To avoid importing ansible galaxy files, the SCM list
is hardcoded to git or hg.

Signed-off-by: Arnaud Patard <[email protected]>

* src/ansiblelint/prerun.py: Use computed fqrn in _install_galaxy_role()

_install_galaxy_role() is taking great pain to get and check
the fqrn, even handling/using the  shortname when the 'role-name'
check is in skip_list but the code is not using the fqrn value to
create the symlink in .cache/roles.
Correct this by using the computed fqrn name for the link name.

Signed-off-by: Arnaud Patard <[email protected]>

* playbooks/eco.yml: Change geerlingguy.mysql checkout path

Change the ansible-role-mysql git clone path to match the role
fqrn as it's what's used with galaxy and what's currently done
by the role ci.
(ref: https://github.com/geerlingguy/ansible-role-mysql/blob/86ffba892e1553b7e6f042ec007eef25daa8f5db/.github/workflows/ci.yml#L21)

Signed-off-by: Arnaud Patard <[email protected]>

* Keep testing both folder names

* src/ansiblelint/prerun.py: Try to handle author name in metadata author

If the author field in meta/main.yml looks like "John Doe" (at least 2 words
separated by a space), act as if there was no namespace.
It's not perfect but it's not possible to match author<->galaxy account
and there will still be a warning/error issued about it, since
the fqrn won't match namespace.role_name.

Signed-off-by: Arnaud Patard <[email protected]>

* src/ansiblelint/prerun.py: Fix role regexp used to strip prefixes

According to :
https://galaxy.ansible.com/docs/contributing/creating_role.html#role-metadata:

In the past, Galaxy would apply a regex expression to the GitHub repository
name and automatically remove 'ansible-' and 'ansible-role-'. For example, if
your repository name was 'ansible-role-apache', the role name would translate
to 'apache',

So update the regexp to handle ansible-role- and ansible-

Signed-off-by: Arnaud Patard <[email protected]>

* src/ansiblelint/prerun.py: Fix link name when 'role-name' in skip_list

If the role-name rule is in skip_list:
- if role_name is set in meta/main.yml, assume that the author wants
  to use this name, even if it's still not up to standards and set
  the link name to the computed fqrn,
- if the role_name is not set, just use the current directory name.
  Note: don't use 'role_name' variable here since some part of the
  name has been stripped from the current directory name.

Signed-off-by: Arnaud Patard <[email protected]>

* src/ansiblelint/prerun.py: split _install_galaxy_role

Flake8 is complaining that the function is now too complex, so
split it into several ones.

Signed-off-by: Arnaud Patard <[email protected]>

* src/ansiblelint/prerun.py: Make _get_galaxy_role_* return empty string

Instead of using None for value not found and sometime return
an empty string make both functions always return a string and
make it empty is something went wrong.

Signed-off-by: Arnaud Patard <[email protected]>

* src/ansiblelint/prerun.py: Revert "Fix role name from SCM"

As it may lead to breakages, drop the check on .git or .hg
presence to get role name.

Signed-off-by: Arnaud Patard <[email protected]>

Co-authored-by: Sorin Sbarnea <[email protected]>
  • Loading branch information
apatard and ssbarnea authored Apr 7, 2021
1 parent 4779e5f commit 38a5dea
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
5 changes: 5 additions & 0 deletions playbooks/eco.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
- name: ansible-role-mysql
url: https://github.com/geerlingguy/ansible-role-mysql.git
contact: geerlingguy
- name: geerlingguy.mysql
url: https://github.com/geerlingguy/ansible-role-mysql.git
contact: geerlingguy
# duplicates first one but covers for the case where clone is made in a
# folder that uses namespace.rolename pattern (installed galaxy role)
- name: zuul-jobs
url: https://opendev.org/zuul/zuul-jobs
contact: ssbarnea
Expand Down
51 changes: 40 additions & 11 deletions src/ansiblelint/prerun.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import subprocess
import sys
from functools import lru_cache
from typing import List, Optional, Tuple
from typing import Any, Dict, List, Optional, Tuple

import tenacity
from packaging import version
Expand Down Expand Up @@ -165,23 +165,47 @@ def prepare_environment() -> None:
_prepare_ansible_paths()


def _get_galaxy_role_ns(galaxy_infos: Dict[str, Any]) -> str:
"""Compute role namespace from meta/main.yml, including trailing dot."""
role_namespace = galaxy_infos.get('namespace', "")
if len(role_namespace) == 0:
role_namespace = galaxy_infos.get('author', "")
# if there's a space in the name space, it's likely author name
# and not the galaxy login, so act as if there was no namespace
if re.match(r"^\w+ \w+", role_namespace):
role_namespace = ""
else:
role_namespace = f"{role_namespace}."
return role_namespace


def _get_galaxy_role_name(galaxy_infos: Dict[str, Any]) -> str:
"""Compute role name from meta/main.yml."""
return galaxy_infos.get('role_name', "")


def _get_role_fqrn(galaxy_infos: Dict[str, Any]) -> str:
"""Compute role fqrn."""
role_namespace = _get_galaxy_role_ns(galaxy_infos)
role_name = _get_galaxy_role_name(galaxy_infos)
if len(role_name) == 0:
role_name = pathlib.Path(".").absolute().name
role_name = re.sub(r'(ansible-|ansible-role-)', '', role_name)

return f"{role_namespace}{role_name}"


def _install_galaxy_role() -> None:
"""Detect standalone galaxy role and installs it."""
if not os.path.exists("meta/main.yml"):
return
yaml = yaml_from_file("meta/main.yml")
if 'galaxy_info' not in yaml:
return
role_name = yaml['galaxy_info'].get('role_name', None)
role_namespace = yaml['galaxy_info'].get('namespace', None)
if not role_namespace:
role_namespace = yaml['galaxy_info'].get('author', None)
if not role_name:
role_name = pathlib.Path(".").absolute().name
role_name = re.sub(r'^{0}'.format(re.escape('ansible-role-')), '', role_name)

fqrn = _get_role_fqrn(yaml['galaxy_info'])

if 'role-name' not in options.skip_list:
fqrn = f"{role_namespace}.{role_name}"
if not re.match(r"[a-z0-9][a-z0-9_]+\.[a-z][a-z0-9_]+$", fqrn):
msg = (
"""\
Expand All @@ -206,10 +230,15 @@ def _install_galaxy_role() -> None:
sys.exit(INVALID_PREREQUISITES_RC)
else:
# when 'role-name' is in skip_list, we stick to plain role names
fqrn = role_name
if 'role_name' in yaml['galaxy_info']:
role_namespace = _get_galaxy_role_ns(yaml['galaxy_info'])
role_name = _get_galaxy_role_name(yaml['galaxy_info'])
fqrn = f"{role_namespace}{role_name}"
else:
fqrn = pathlib.Path(".").absolute().name
p = pathlib.Path(f"{options.project_dir}/.cache/roles")
p.mkdir(parents=True, exist_ok=True)
link_path = p / f"{role_namespace}.{role_name}"
link_path = p / fqrn
# despite documentation stating that is_file() reports true for symlinks,
# it appears that is_dir() reports true instead, so we rely on exits().
if not link_path.exists():
Expand Down

0 comments on commit 38a5dea

Please sign in to comment.