diff --git a/lib/schema_checker.py b/lib/schema_checker.py index 8eff447ee..a5d04e904 100644 --- a/lib/schema_checker.py +++ b/lib/schema_checker.py @@ -129,10 +129,11 @@ def check_usage_scenario(self, usage_scenario): if 'networks' in usage_scenario: self.validate_networks_no_invalid_chars(usage_scenario['networks']) - for service_name in usage_scenario.get('services'): - service = usage_scenario['services'][service_name] - if 'image' not in service and 'build' not in service: - raise SchemaError("The 'image' key under services is required when 'build' key is not present.") + if 'services' in usage_scenario: + for service_name in usage_scenario.get('services'): + service = usage_scenario['services'][service_name] + if 'image' not in service and 'build' not in service: + raise SchemaError("The 'image' key under services is required when 'build' key is not present.") usage_scenario_schema.validate(usage_scenario) diff --git a/runner.py b/runner.py index 4f4ebc14e..a07153874 100755 --- a/runner.py +++ b/runner.py @@ -338,8 +338,9 @@ def merge_dicts(dict1, dict2): # creating benchmarking scripts and you want to have all options in the compose but not in each benchmark. # The cleaner way would be to handle an empty service key throughout the code but would make it quite messy # so we chose to remove it right at the start. - for key in [sname for sname, content in yml_obj['services'].items() if content is None]: - del yml_obj['services'][key] + if 'services' in yml_obj: + for key in [sname for sname, content in yml_obj['services'].items() if content is None]: + del yml_obj['services'][key] self._usage_scenario = yml_obj @@ -379,7 +380,7 @@ def check_running_containers(self): raise PermissionError(f"Container '{container_name}' is already running on system. Please close it before running the tool.") def populate_image_names(self): - for service_name, service in self._usage_scenario.get('services', []).items(): + for service_name, service in self._usage_scenario.get('services', {}).items(): if not service.get('image', None): # image is a non essential field. But we need it, so we tmp it if self._dev_repeat_run: service['image'] = f"{service_name}" @@ -541,7 +542,7 @@ def build_docker_images(self): # technically the usage_scenario needs no services and can also operate on an empty list # This use case is when you have running containers on your host and want to benchmark some code running in them - for _, service in self._usage_scenario.get('services', []).items(): + for _, service in self._usage_scenario.get('services', {}).items(): # minimal protection from possible shell escapes. # since we use subprocess without shell we should be safe though if re.findall(r'(\.\.|\$|\'|"|`|!)', service['image']): @@ -640,7 +641,7 @@ def setup_networks(self): def setup_services(self): # technically the usage_scenario needs no services and can also operate on an empty list # This use case is when you have running containers on your host and want to benchmark some code running in them - for service_name in self._usage_scenario.get('services', []): + for service_name, service in self._usage_scenario.get('services', {}).items(): print(TerminalColors.HEADER, '\nSetting up containers', TerminalColors.ENDC) if 'container_name' in self._usage_scenario['services'][service_name]: @@ -648,8 +649,6 @@ def setup_services(self): else: container_name = service_name - service = self._usage_scenario['services'][service_name] - print('Resetting container') # By using the -f we return with 0 if no container is found # we always reset container without checking if something is running, as we expect that a user understands