Skip to content

Commit fa50155

Browse files
committed
Discover and extract data from YAML files in manfifest
1 parent b7fde36 commit fa50155

File tree

1 file changed

+105
-5
lines changed

1 file changed

+105
-5
lines changed

src/pyatsimagebuilder/utils.py

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,11 @@ def to_image_path(path, search_path, workspace_dir):
283283
workspace_dir = str(workspace_dir)
284284

285285
if path.startswith('${WORKSPACE}'):
286-
path = path.replace('${WORKSPACE}', workspace_dir)
286+
path = path.replace('${WORKSPACE}', workspace_dir, 1)
287287
elif path.startswith('$WORKSPACE'):
288-
path = path.replace('$WORKSPACE', workspace_dir)
288+
path = path.replace('$WORKSPACE', workspace_dir, 1)
289289
elif path.startswith(search_path):
290-
path = path.replace(search_path, workspace_dir)
290+
path = path.replace(search_path, workspace_dir, 1)
291291

292292
return path
293293

@@ -471,14 +471,114 @@ def discover_manifests(search_path, ignore_folders=None, relative_path=None,
471471
jobs.append(manifest_data)
472472

473473
except Exception as e:
474-
logger.error('Error processing manifest file {}\n{}'.format(
475-
manifest, str(e)))
474+
logger.exception('Error processing manifest file {}'.format(
475+
manifest))
476476
continue
477477

478478
logger.info('Number of discovered manifest files: %s' % \
479479
len(discovered_manifests))
480480

481+
482+
481483
if jobs:
484+
discover_yamls(jobs, search_path=search_path, relative_path=relative_path)
482485
return {'version': MANIFEST_VERSION, 'jobs': jobs}
483486
else:
484487
return {}
488+
489+
490+
def _process_testbed_file(profile, yaml_contents):
491+
# Extract specific device information from each device
492+
# in the testbed and attach to the profile
493+
testbed_info = profile.setdefault('testbed_info', {})
494+
for dev_name, dev in yaml_contents['devices'].items():
495+
if isinstance(dev, dict):
496+
testbed_info[dev_name] = {}
497+
for key in ('os', 'platform', 'model', 'pid', 'type', 'logical'):
498+
if key in dev:
499+
testbed_info[dev_name][key] = dev[key]
500+
501+
def _process_clean_file(profile, yaml_contents):
502+
# Extract bringup information from the clean file and
503+
# attach to the profile
504+
clean_info = profile.setdefault('clean_info', {})
505+
bringup_module = yaml_contents.get('bringup', {}).get('BringUpWorker', {}).get('module')
506+
clean_info['bringup_module'] = bringup_module
507+
508+
509+
yaml_processors = {
510+
'testbed-file': _process_testbed_file,
511+
'logical-testbed-file': _process_testbed_file,
512+
'clean-file': _process_clean_file
513+
}
514+
515+
def discover_yamls(manifests, search_path, relative_path=None):
516+
""" Discover yaml files referenced in manifest files and extract key
517+
information
518+
519+
Arguments:
520+
manifests (list): list of contents of discovered manifests
521+
search_path (Path): pathlib Path object with the directory to start discovery from
522+
relative_path (str): String with the directory search results will be relative to
523+
"""
524+
logger.info('Discovering YAML files from manifests')
525+
for manifest in manifests:
526+
manifest_dir = os.path.dirname(manifest['file'])
527+
for profile in manifest['profiles']:
528+
profile['yaml_files'] = []
529+
if isinstance(profile.get('arguments'), dict):
530+
for argument, value in profile['arguments'].items():
531+
if argument not in yaml_processors:
532+
# Filter for only testbed and clean files. No need to
533+
# load other yaml files
534+
continue
535+
536+
if isinstance(value, str) and value.endswith('.yaml'):
537+
# Do not process any files that start with a variable
538+
# or some inaccessible absolute path. If the yaml file
539+
# starts with the relative path, it should be
540+
# accessible in the image, and still valid
541+
if value.startswith('$'):
542+
continue
543+
elif value.startswith('/'):
544+
if not relative_path or not value.startswith(relative_path):
545+
continue
546+
547+
# Construct an absolute path using the dir of the manifest
548+
# This will be the relative path to the image root once
549+
# built, not the actual path of the file in the build
550+
# environment
551+
yaml_file = os.path.abspath(os.path.join(manifest_dir, value))
552+
# Convert to a real path so we can find the file in our
553+
# build environment
554+
if relative_path:
555+
yaml_file = to_image_path(yaml_file, relative_path, search_path)
556+
if os.path.isfile(yaml_file):
557+
try:
558+
with open(yaml_file) as f:
559+
# load yaml contents with handling for an
560+
# empty file
561+
yaml_contents = yaml.safe_load(f.read()) or {}
562+
except Exception as e:
563+
msg = f'Error loading YAML file {value} from ' \
564+
f'manifest {manifest["file"]}'
565+
logger.exception(msg)
566+
continue
567+
else:
568+
# YAML file relative path from manifest does not
569+
# exist.
570+
msg = f'Could not find YAML file {value} from ' \
571+
f'manifest {manifest["file"]}'
572+
logger.warning(msg)
573+
574+
processor = yaml_processors.get(argument)
575+
if processor:
576+
try:
577+
processor(profile, yaml_contents)
578+
except Exception as e:
579+
# Problem processing the specific type of YAML file
580+
msg = f'Error processing {argument} {value} from ' \
581+
f'manifest {manifest["file"]}'
582+
logger.exception(msg)
583+
584+
return manifests

0 commit comments

Comments
 (0)