ansible-test - Validate collection ns and name.

Resolves https://github.com/ansible/ansible/issues/62079
pull/76871/head
Matt Clay 2 years ago
parent de5f60e374
commit 26b43f425f

@ -0,0 +1,2 @@
minor_changes:
- ansible-test - Stop early with an error if the current working directory contains an invalid collection namespace or name.

@ -9,6 +9,7 @@ from .util import (
ApplicationError,
import_plugins,
is_subdir,
is_valid_identifier,
ANSIBLE_LIB_ROOT,
ANSIBLE_TEST_ROOT,
ANSIBLE_SOURCE_ROOT,
@ -180,8 +181,7 @@ class DataContext:
if self.content.unsupported:
raise ApplicationError(self.explain_working_directory())
@staticmethod
def explain_working_directory() -> str:
def explain_working_directory(self) -> str:
"""Return a message explaining the working directory requirements."""
blocks = [
'The current working directory must be within the source tree being tested.',
@ -204,9 +204,16 @@ class DataContext:
blocks.append(f'Expected parent directory: {os.path.dirname(cwd)}/{{namespace}}/{{collection}}/')
elif os.path.basename(cwd) == 'ansible_collections':
blocks.append(f'Expected parent directory: {cwd}/{{namespace}}/{{collection}}/')
else:
elif 'ansible_collections' not in cwd.split(os.path.sep):
blocks.append('No "ansible_collections" parent directory was found.')
if self.content.collection:
if not is_valid_identifier(self.content.collection.namespace):
blocks.append(f'The namespace "{self.content.collection.namespace}" is an invalid identifier or a reserved keyword.')
if not is_valid_identifier(self.content.collection.name):
blocks.append(f'The name "{self.content.collection.name}" is an invalid identifier or a reserved keyword.')
message = '\n'.join(blocks)
return message

@ -11,6 +11,10 @@ from . import (
LayoutMessages,
)
from ...util import (
is_valid_identifier,
)
class CollectionLayout(LayoutProvider):
"""Layout provider for Ansible collections."""
@ -28,6 +32,10 @@ class CollectionLayout(LayoutProvider):
collection_root = os.path.dirname(os.path.dirname(root))
collection_dir = os.path.relpath(root, collection_root)
collection_namespace: str
collection_name: str
collection_namespace, collection_name = collection_dir.split(os.path.sep)
collection_root = os.path.dirname(collection_root)
@ -65,6 +73,7 @@ class CollectionLayout(LayoutProvider):
unit_module_path='tests/unit/plugins/modules',
unit_module_utils_path='tests/unit/plugins/module_utils',
unit_messages=unit_messages,
unsupported=not(is_valid_identifier(collection_namespace) and is_valid_identifier(collection_name)),
)
@staticmethod

@ -6,6 +6,7 @@ import errno
import fcntl
import importlib.util
import inspect
import keyword
import os
import pkgutil
import random
@ -98,6 +99,11 @@ MODE_DIRECTORY = MODE_READ | stat.S_IWUSR | stat.S_IXUSR | stat.S_IXGRP | stat.S
MODE_DIRECTORY_WRITE = MODE_DIRECTORY | stat.S_IWGRP | stat.S_IWOTH
def is_valid_identifier(value: str) -> bool:
"""Return True if the given value is a valid non-keyword Python identifier, otherwise return False."""
return value.isidentifier() and not keyword.iskeyword(value)
def cache(func): # type: (t.Callable[[], TValue]) -> t.Callable[[], TValue]
"""Enforce exclusive access on a decorated function and cache the result."""
storage = {} # type: t.Dict[None, TValue]

Loading…
Cancel
Save