def load() -> Dict[str, "Composition"]: """Load all demos in the repo""" compositions = {} compose_files = itertools.chain( Path("demo").glob("*/mzcompose.yml"), Path("play").glob("*/mzcompose.yml"), Path("test").glob("*/mzcompose.yml"), Path("test/performance").glob("*/mzcompose.yml"), ) for mzcompose in compose_files: with mzcompose.open() as fh: mzcomp = yaml.safe_load(fh) name = mzcompose.parent.name raw_comp = mzcomp.get("mzconduct") workflows = {} if raw_comp is not None: # TODO: move this into the workflow so that it can use env vars that are # manually defined. raw_comp = _substitute_env_vars(raw_comp) name = raw_comp.get("name", name) for workflow_name, raw_w in raw_comp["workflows"].items(): built_steps = [] for raw_step in raw_w["steps"]: step_name = raw_step.pop("step") step_ty = Steps.named(step_name) munged = { k.replace("-", "_"): v for k, v in raw_step.items() } try: step = step_ty(path=mzcompose, **munged) except TypeError as e: a = " ".join( [f"{k}={v}" for k, v in munged.items()]) raise BadSpec( f"Unable to construct {step_name} with args {a}: {e}" ) built_steps.append(step) env = raw_w.get("env") if not isinstance(env, dict) and env is not None: raise BadSpec( f"Workflow {workflow_name} has wrong type for env: " f"expected mapping, got {type(env).__name__}: {env}", ) # ensure that integers (e.g. ports) are treated as env vars if isinstance(env, dict): env = {k: str(v) for k, v in env.items()} workflows[workflow_name] = Workflow( workflow_name, built_steps, env=env, include_compose=raw_w.get("include_compose"), compose_file=str(mzcompose), ) compositions[name] = Composition(name, mzcompose, Workflows(workflows)) return compositions
def __init__( self, service: str, other_service: str, duration: int, run_cmd: str, stop_cmd: str, run_time: int, stop_time: int, ): if ( other_service == "" and duration < 0 or other_service != "" and duration >= 0 ): raise BadSpec( f"Need to specify either 'other_service' or 'duration' to run chaos Docker workflow step" ) self._service = service self._other_service = other_service self._duration = duration self._run_cmd = run_cmd self._stop_cmd = stop_cmd self._run_time = run_time self._stop_time = stop_time
def __init__(self, path: Path, *, services: Optional[List[str]] = None) -> None: super().__init__(path) self._services = services if services is not None else [] if not isinstance(self._services, list): raise BadSpec(f"services should be a list, got: {self._services}")
def _subst(match: Match) -> str: var = match.group("var") if var is None: raise BadSpec(f"Unable to parse environment variable {match.group(0)}") # https://github.com/python/typeshed/issues/3902 default = cast(Optional[str], match.group("default")) env_val = os.getenv(var) if env_val is None and default is None: say(f"WARNING: unknown env var {var!r}") return cast(str, match.group(0)) elif env_val is None and default is not None: # strip the leading ":-" env_val = default[2:] assert env_val is not None, "should be replaced correctly" return env_val
def load() -> Dict[str, "Composition"]: """Load all demos in the repo""" compositions = {} compose_files = itertools.chain( Path("demo").glob("*/mzcompose.yml"), Path("test").glob("*/mzcompose.yml")) for mzcompose in compose_files: with mzcompose.open() as fh: mzcomp = yaml.safe_load(fh) name = mzcompose.parent.name raw_comp = mzcomp.get("mzconduct") workflows = {} if raw_comp is not None: raw_comp = _substitute_env_vars(raw_comp) name = raw_comp.get("name", name) for workflow_name, raw_w in raw_comp["workflows"].items(): built_steps = [] for raw_step in raw_w["steps"]: step_name = raw_step.pop("step") step_ty = Steps.named(step_name) munged = { k.replace("-", "_"): v for k, v in raw_step.items() } try: step = step_ty(**munged) except TypeError as e: a = " ".join( [f"{k}={v}" for k, v in munged.items()]) raise BadSpec( f"Unable to construct {step_name} with args {a}: {e}" ) built_steps.append(step) workflows[workflow_name] = Workflow( workflow_name, built_steps, raw_w.get("include_compose")) compositions[name] = Composition(name, mzcompose.parent, Workflows(workflows)) return compositions