Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/ansible_builder/_target_scripts/introspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class CollectionDefinition:
def __init__(self, collection_path):
self.reference_path = collection_path

# NOTE: Filenames should match constants.DEAFULT_EE_BASENAME and constants.YAML_FILENAME_EXTENSIONS.
# NOTE: Filenames should match constants.DEFAULT_EE_BASENAME and constants.YAML_FILENAME_EXTENSIONS.
meta_file_base = os.path.join(collection_path, 'meta', 'execution-environment')
ee_exists = False
for ext in ('yml', 'yaml'):
Expand All @@ -69,7 +69,7 @@ def target_dir(self):
)

def namespace_name(self):
"Returns 2-tuple of namespace and name"
"""Returns 2-tuple of namespace and name"""
path_parts = [p for p in self.reference_path.split(os.path.sep) if p]
return tuple(path_parts[-2:])

Expand Down Expand Up @@ -149,7 +149,7 @@ def process_collection(path):
if sys_file:
bindep_lines = bindep_file_data(os.path.join(path, sys_file))

return (pip_lines, bindep_lines)
return pip_lines, bindep_lines


def process(data_dir=BASE_COLLECTIONS_PATH,
Expand Down Expand Up @@ -231,6 +231,7 @@ def process(data_dir=BASE_COLLECTIONS_PATH,
if col_sys_exclude_lines:
sys_req['exclude'] = col_sys_exclude_lines

retval: dict[str, dict | list]
retval = {
'python': py_req,
'system': sys_req,
Expand Down Expand Up @@ -270,7 +271,7 @@ def strip_comments(reqs: dict[str, list]) -> dict[str, list]:
for collection, lines in reqs.items():
for line in lines:
# strip comments
if (base_line := COMMENT_RE.sub('', line.strip())):
if base_line := COMMENT_RE.sub('', line.strip()):
result.setdefault(collection, []).append(base_line)

return result
Expand Down Expand Up @@ -299,14 +300,15 @@ def should_be_excluded(value: str, exclusion_list: list[str]) -> bool:
def filter_requirements(reqs: dict[str, list],
exclude: list[str] | None = None,
exclude_collections: list[str] | None = None,
is_python: bool = True) -> list[str]:
is_python: bool = True,
warning_is_error: bool = False) -> list[str]:
"""
Given a dictionary of Python requirement lines keyed off collections,
return a list of cleaned up (no source comments) requirements
annotated with comments indicating the sources based off the collection keys.

Currently, non-pep508 compliant Python entries are passed through. We also no
longer attempt to normalize names (replace '_' with '-', etc), other than
longer attempt to normalize names (replace '_' with '-', etc.), other than
lowercasing it for exclusion matching, since we no longer are attempting
to combine similar entries.

Expand All @@ -315,6 +317,8 @@ def filter_requirements(reqs: dict[str, list],
:param list exclude_collections: A list of collection names from which to exclude all requirements.
:param bool is_python: This should be set to True for Python requirements, as each
will be tested for PEP508 compliance. This should be set to False for system requirements.
:param bool warning_is_error: If True, warnings are treated as errors. This currently affects
only Python requirements.

:return: A list of filtered and annotated requirements.
"""
Expand Down Expand Up @@ -342,6 +346,12 @@ def filter_requirements(reqs: dict[str, list],
parsed_req = Requirement(line)
name = parsed_req.name
except InvalidRequirement:
if warning_is_error:
logger.error(
"Error on non-PEP508 compliant line '%s' from collection '%s'",
line, collection)
sys.exit(1)

logger.warning(
"Passing through non-PEP508 compliant line '%s' from collection '%s'",
line, collection
Expand Down Expand Up @@ -389,6 +399,7 @@ def parse_args(args=None):


def run_introspect(args, log):
logger.debug("Requirements warnings are errors: %s", args.warning_is_error)
data = process(args.folder,
user_pip=args.user_pip,
user_bindep=args.user_bindep,
Expand All @@ -403,13 +414,14 @@ def run_introspect(args, log):
data['python'],
exclude=data['python'].pop('exclude', []),
exclude_collections=excluded_collections,
warning_is_error=args.warning_is_error,
)

data['system'] = filter_requirements(
data['system'],
exclude=data['system'].pop('exclude', []),
exclude_collections=excluded_collections,
is_python=False
is_python=False,
)

print('---')
Expand Down Expand Up @@ -472,6 +484,10 @@ def create_introspect_parser(parser):
'--write-bindep', dest='write_bindep',
help='Write the combined bindep requirements file to this location.'
)
introspect_parser.add_argument(
'--warning-is-error', action='store_true',
help='Exit with error if requirement parsing produces warnings.'
)

return introspect_parser

Expand Down
4 changes: 4 additions & 0 deletions src/ansible_builder/containerfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ def _insert_global_args(self, include_values: bool = False) -> None:
self.definition.build_arg_defaults['ANSIBLE_GALAXY_CLI_COLLECTION_OPTS'],
'ANSIBLE_GALAXY_CLI_ROLE_OPTS': self.definition.build_arg_defaults['ANSIBLE_GALAXY_CLI_ROLE_OPTS'],
'ANSIBLE_INSTALL_REFS': self.definition.ansible_ref_install_list,
'INTROSPECT_OPTS': self.definition.build_arg_defaults.get('INTROSPECT_OPTS'),
}

if self.definition.version >= 3:
Expand Down Expand Up @@ -491,6 +492,9 @@ def _prepare_introspect_assemble_steps(self) -> None:

introspect_cmd += " --write-bindep=/tmp/src/bindep.txt --write-pip=/tmp/src/requirements.txt"

if introspect_opts := self.definition.build_arg_defaults.get('INTROSPECT_OPTS'):
introspect_cmd += f" {introspect_opts}"

self.steps.append(introspect_cmd)
self.steps.append("RUN /output/scripts/assemble")

Expand Down
3 changes: 3 additions & 0 deletions src/ansible_builder/ee_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@
"PKGMGR_PRESERVE_CACHE": {
"type": "string",
},
"INTROSPECT_OPTS": {
"type": "string",
}
},
},

Expand Down