def __init__(self, sources: list, uid: uuid.UUID): self.config = BaseConfig.from_dict(DEFAULTS) self.config.set_source("TASKCAT_DEFAULT") self.uid = uid for source in sources: config_dict: dict = source["config"] source_name: str = source["source"] source_config = BaseConfig.from_dict(config_dict) source_config.set_source(source_name) self.config = BaseConfig.merge(self.config, source_config)
def _dict_from_template(file_path: Path) -> dict: relative_path = str(file_path.relative_to(PROJECT_ROOT)) config_dict = ( BaseConfig() .from_dict( {"project": {"template": relative_path}, "tests": {"default": {}}} ) .to_dict() ) if not file_path.is_file(): raise TaskCatException(f"invalid template path {file_path}") try: template = Template( str(file_path), template_cache=tcat_template_cache ).template except Exception as e: LOG.warning(f"failed to load template from {file_path}") LOG.debug(str(e), exc_info=True) raise e if not template.get("Metadata"): return config_dict if not template["Metadata"].get("taskcat"): return config_dict template_config_dict = template["Metadata"]["taskcat"] if not template_config_dict.get("project"): template_config_dict["project"] = {} template_config_dict["project"]["template"] = relative_path if not template_config_dict.get("tests"): template_config_dict["tests"] = {"default": {}} return template_config_dict
def create( cls, template_file: Optional[Path] = None, args: Optional[dict] = None, global_config_path: Path = GENERAL, project_config_path: Path = PROJECT, overrides_path: Path = OVERRIDES, env_vars: Optional[dict] = None, project_root: Path = PROJECT_ROOT, uid: uuid.UUID = None, ) -> "Config": uid = uid if uid else uuid.uuid4() project_source = cls._get_project_source(cls, project_config_path, project_root, template_file) # general legacy_overrides( Path("~/.aws/taskcat_global_override.json").expanduser().resolve(), global_config_path, "global", ) sources = [{ "source": str(global_config_path), "config": cls._dict_from_file(global_config_path), }] # project config file if project_source: sources.append(project_source) # template file if isinstance(template_file, Path): sources.append({ "source": str(template_file), "config": cls._dict_from_template(template_file), }) # override file legacy_overrides(project_root / "ci/taskcat_project_override.json", overrides_path, "project") if overrides_path.is_file(): overrides = BaseConfig().to_dict() with open(str(overrides_path), "r") as file_handle: override_params = yaml.safe_load(file_handle) overrides["project"]["parameters"] = override_params sources.append({ "source": str(overrides_path), "config": overrides }) # environment variables sources.append({ "source": "EnvoronmentVariable", "config": cls._dict_from_env_vars(env_vars), }) # cli arguments if args: sources.append({"source": "CliArgument", "config": args}) return cls(sources=sources, uid=uid)
def parse_legacy_config(project_root: Path): config_file = (project_root / "ci/taskcat.yml").expanduser().resolve() if not config_file.is_file(): raise TaskCatException(f"No config_file at {config_file}") with open(str(config_file), "r") as file_handle: config_dict = yaml.safe_load(file_handle) # need to rename global key, as it's a python keyword config_dict["global_"] = config_dict.pop("global") legacy_config = LegacyConfig.from_dict(config_dict) tests = {} for test_name, test_data in legacy_config.tests.items(): parameters = {} parameter_file = project_root / "ci/" / test_data.parameter_input parameter_file = parameter_file.expanduser().resolve() with open(str(parameter_file), "r") as file_handle: for param in yaml.safe_load(file_handle): parameters[param["ParameterKey"]] = param["ParameterValue"] tests[test_name] = { "template": "templates/" + test_data.template_file, "parameters": parameters, "regions": test_data.regions, } if not tests[test_name]["regions"]: del tests[test_name]["regions"] new_config_dict = { "project": { "name": legacy_config.global_.qsname, "owner": legacy_config.global_.owner, "s3_bucket": legacy_config.global_.s3bucket, "package_lambda": legacy_config.global_.lambda_build, "regions": legacy_config.global_.regions, }, "tests": tests, } new_config = BaseConfig.from_dict(new_config_dict) LOG.warning( "config is in a legacy format, support for which will be dropped in a " "future version. a new format config (.taskcat.yml) will been placed " "in your project_root" ) new_config_path = project_root / ".taskcat.yml" if new_config_path.exists(): LOG.warning( f"skipping new config file creation, file already exits at " f"{new_config_path}" ) else: with open(str(new_config_path), "w") as file_handle: config_dict = new_config.to_dict() config_dict.pop("general") yaml.dump(config_dict, file_handle, default_flow_style=False) return new_config
def _dict_from_file(file_path: Path, fail_ok=True) -> dict: config_dict = BaseConfig().to_dict() if not file_path.is_file() and fail_ok: return config_dict try: with open(str(file_path), "r") as file_handle: config_dict = yaml.safe_load(file_handle) return config_dict except Exception as e: # pylint: disable=broad-except LOG.warning(f"failed to load config from {file_path}") LOG.debug(str(e), exc_info=True) if not fail_ok: raise e return config_dict
#!/usr/bin/env python import json from taskcat._dataclasses import BaseConfig if __name__ == "__main__": schema = BaseConfig.json_schema() with open("./taskcat/cfg/config_schema.json", "w") as f: f.write( json.dumps(schema, sort_keys=True, indent=4, separators=(",", ": "))) f.write("\n")