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