@@ -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