Beispiel #1
0
def test_exceptions():
    with pytest.raises(ValueError):
        parse_version("pr-2d")
    with pytest.raises(ValueError):
        parse_version("0-1")
Beispiel #2
0
def workflow_generator_cli(gordo_ctx, **ctx):
    """
    Machine Configuration to Argo Workflow
    """

    configure_once()

    context: Dict[Any, Any] = ctx.copy()
    yaml_content = wg.get_dict_from_yaml(context["machine_config"])

    try:
        log_level = yaml_content["globals"]["runtime"]["log_level"]
    except KeyError:
        log_level = os.getenv("GORDO_LOG_LEVEL", gordo_ctx.obj["log_level"])

    logging.getLogger("gordo").setLevel(log_level.upper())
    context["log_level"] = log_level.upper()

    validate_generate_context(context)

    context["resources_labels"] = prepare_resources_labels(context["resources_labels"])

    model_builder_env = None
    if context["custom_model_builder_envs"]:
        model_builder_env = json.loads(context["custom_model_builder_envs"])
    # Create normalized config
    config = NormalizedConfig(
        yaml_content,
        project_name=context["project_name"],
        model_builder_env=model_builder_env,
    )

    version = parse_version(context["gordo_version"])
    if "image_pull_policy" not in context or not context["image_pull_policy"]:
        context["image_pull_policy"] = wg.default_image_pull_policy(version)
    logger.info(
        "Generate config with gordo_version=%s and imagePullPolicy=%s",
        context["gordo_version"],
        context["image_pull_policy"],
    )

    context["max_server_replicas"] = (
        context.pop("n_servers") or len(config.machines) * 10
    )

    context["volumes"] = None
    if "volumes" in config.globals["runtime"]:
        context["volumes"] = config.globals["runtime"]["volumes"]

    builder_runtime = config.globals["runtime"]["builder"]
    # We know these exist since we set them in the default globals
    builder_resources = builder_runtime["resources"]
    context["model_builder_resources_requests_memory"] = builder_resources["requests"][
        "memory"
    ]
    context["model_builder_resources_requests_cpu"] = builder_resources["requests"][
        "cpu"
    ]
    context["model_builder_resources_limits_memory"] = builder_resources["limits"][
        "memory"
    ]
    context["model_builder_resources_limits_cpu"] = builder_resources["limits"]["cpu"]
    context["model_builder_image"] = config.globals["runtime"]["builder"]["image"]

    context["builder_runtime"] = builder_runtime

    context["server_resources"] = config.globals["runtime"]["server"]["resources"]
    context["server_image"] = config.globals["runtime"]["server"]["image"]

    context["prometheus_metrics_server_resources"] = config.globals["runtime"][
        "prometheus_metrics_server"
    ]["resources"]

    context["prometheus_metrics_server_image"] = config.globals["runtime"][
        "prometheus_metrics_server"
    ]["image"]

    context["deployer_image"] = config.globals["runtime"]["deployer"]["image"]

    # These are also set in the default globals, and guaranteed to exist
    client_resources = config.globals["runtime"]["client"]["resources"]
    context["client_resources_requests_memory"] = client_resources["requests"]["memory"]
    context["client_resources_requests_cpu"] = client_resources["requests"]["cpu"]
    context["client_resources_limits_memory"] = client_resources["limits"]["memory"]
    context["client_resources_limits_cpu"] = client_resources["limits"]["cpu"]

    context["client_image"] = config.globals["runtime"]["client"]["image"]

    context["client_max_instances"] = config.globals["runtime"]["client"][
        "max_instances"
    ]

    influx_resources = config.globals["runtime"]["influx"]["resources"]
    context["influx_resources_requests_memory"] = influx_resources["requests"]["memory"]
    context["influx_resources_requests_cpu"] = influx_resources["requests"]["cpu"]
    context["influx_resources_limits_memory"] = influx_resources["limits"]["memory"]
    context["influx_resources_limits_cpu"] = influx_resources["limits"]["cpu"]

    nr_of_models_with_clients = len(
        [
            machine
            for machine in config.machines
            if machine.runtime.get("influx", {}).get("enable", True)
        ]
    )
    context["client_total_instances"] = nr_of_models_with_clients

    # Should we start up influx/grafana at all, i.e. is there at least one request
    # for it?"
    enable_influx = nr_of_models_with_clients > 0
    context["enable_influx"] = enable_influx

    context["postgres_host"] = f"gordo-postgres-{config.project_name}"

    context["keda_prometheus_query"] = prepare_keda_prometheus_query(context)

    # If enabling influx, we setup a postgres reporter to send metadata
    # to allowing querying about the machine from grafana
    if enable_influx:
        pg_reporter = {
            "gordo.reporters.postgres.PostgresReporter": {
                "host": context["postgres_host"]
            }
        }
        for machine in config.machines:
            machine.runtime["reporters"].append(pg_reporter)

    # Determine if MlFlowReporter should be enabled per machine
    for machine in config.machines:
        try:
            enabled = machine.runtime["builder"]["remote_logging"]["enable"]
        except KeyError:
            continue
        else:
            if enabled:
                machine.runtime["reporters"].append(
                    "gordo.reporters.mlflow.MlFlowReporter"
                )

    context["machines"] = config.machines

    # Context requiring pre-processing
    context["target_names"] = [machine.name for machine in config.machines]

    # Json dump owner_references, if not None, otherwise pop it out of the context
    if context["owner_references"]:
        context["owner_references"] = json.dumps(context["owner_references"])
    else:
        context.pop("owner_references")

    builder_exceptions_report_level = get_builder_exceptions_report_level(config)
    context["builder_exceptions_report_level"] = builder_exceptions_report_level.name
    if builder_exceptions_report_level != ReportLevel.EXIT_CODE:
        context["builder_exceptions_report_file"] = "/tmp/exception.json"

    if context["workflow_template"]:
        template = wg.load_workflow_template(context["workflow_template"])
    else:
        workflow_template = pkg_resources.resource_filename(
            "gordo.workflow.workflow_generator.resources", "argo-workflow.yml.template"
        )
        template = wg.load_workflow_template(workflow_template)

    # Clear output file
    if context["output_file"]:
        open(context["output_file"], "w").close()  # type: ignore
    project_workflow = 0
    for i in range(0, len(config.machines), context["split_workflows"]):  # type: ignore
        logger.info(
            f"Generating workflow for machines {i} to {i + context['split_workflows']}"
        )
        context["machines"] = config.machines[i : i + context["split_workflows"]]
        context["project_workflow"] = str(project_workflow)

        if context["output_file"]:
            s = template.stream(**context)
            with open(context["output_file"], "a") as f:  # type: ignore
                if i != 0:
                    f.write("\n---\n")
                s.dump(f)
        else:
            output = template.render(**context)
            if i != 0:
                print("\n---\n")
            print(output)
        project_workflow += 1
Beispiel #3
0
def test_versions(gordo_version, expected):
    result = parse_version(gordo_version)
    assert result == expected
    assert result.get_version() == gordo_version