def version_requirement_validation(service_requirement, requirement_key_list,
                                   manifest_versions, current_validation):
    """
    Validates version matches the requirement for a specific service

    Args:
    service_requirement: service name and its version requirement
    requirement_key_list: list of service name which need validation
    manifest_versions: versions block from manifest
    current_validation (str): service name and version that are currently being validated

    Return:
        ok(bool): whether the validation succeeded.
    """
    ok = True

    for required_service in requirement_key_list:
        actual_version = get_manifest_version(manifest_versions,
                                              required_service)
        if not actual_version:
            logger.error(
                'Service "{}" not in manifest but required to validate "{}" with "{}"'
                .format(required_service, current_validation,
                        service_requirement))
            ok = False
            continue

        if version_is_branch(actual_version):
            # ignoring service on branch - user was already informed of this
            # by the log in `manifest_version()`
            continue

        if ("min" not in service_requirement[required_service]
                and "max" not in service_requirement[required_service]):
            ok = (assert_and_log(
                version.parse(
                    service_requirement[required_service]) <= actual_version,
                'Service "{}" version "{}" does not respect requirement "{}" for "{}"'
                .format(
                    required_service,
                    actual_version,
                    service_requirement,
                    current_validation,
                ),
            ) and ok)
        elif ("min" in service_requirement[required_service]
              and "max" in service_requirement[required_service]):
            ok = (assert_and_log(
                version.parse(service_requirement[required_service]["min"]) <=
                actual_version < version.parse(
                    service_requirement[required_service]["max"]),
                'Service "{}" version "{}" does not respect requirement "{}" for "{}"'
                .format(
                    required_service,
                    actual_version,
                    service_requirement,
                    current_validation,
                ),
            ) and ok)
    return ok
Exemple #2
0
def validate_against_dictionary(gitops, data_dictionary):
    """
    Validates gitops.json configuration against a data dictionary
    Args:
        gitops (dict): gitops.json config
        data_dictionary (str): url of data dictionary

    Returns:
        ok(bool): whether the validation succeeded.

    """

    _, model = init_dictionary(data_dictionary)
    schema = model.dictionary.schema

    ok = True
    graphql = gitops["graphql"]
    for item in graphql["boardCounts"]:
        node_count = item["graphql"]
        # assumes form _{node}_count
        idx = node_count.rfind("_")
        node = node_count[1:idx]

        ok = ok and assert_and_log(
            schema.get(node) is not None,
            "Node: {} in graphql.boardCounts not found in dictionary".format(
                node),
        )

    for item in graphql["chartCounts"]:
        node_count = item["graphql"]
        # assumes form _{node}_count
        idx = node_count.rfind("_")
        node = node_count[1:idx]
        ok = ok and assert_and_log(
            schema.get(node) is not None,
            "Node: {} in graphql.chartCounts not found in dictionary".format(
                node),
        )

    for item in graphql.get("homepageChartNodes", []):
        node = item["node"]
        ok = ok and assert_and_log(
            schema.get(node) is not None,
            "Node: {} in graphql.homepageChartNodes not found in dictionary".
            format(node),
        )

    return ok
def versions_validation(manifest_versions, versions_requirements):
    """
    Validates versions in cdis-manifest

    Arg:
        manifest_versions: manifest.json "versions" section
        versions_requirements: the "versions" requirement under validation_config.yaml

    Return:
        ok(bool): whether the validation succeeded.
    """
    ok = True

    for versions_requirement in versions_requirements:

        requirement_list = versions_requirement["needs"]
        requirement_key_list = list(requirement_list.keys())
        requirement_key = list(versions_requirement)[0]
        actual_version = get_manifest_version(manifest_versions,
                                              requirement_key)

        if requirement_key in manifest_versions and not version_is_branch(
                actual_version):

            required_version = versions_requirement[requirement_key]

            # If the first service set to * under validation_config versions, other services should be in the manifest
            # The second condition is ignoring branch on sevice. WHICH IS NOT GOO. Added a warning in the log
            if required_version == "*":
                for required_service in requirement_key_list:
                    ok = (assert_and_log(
                        required_service in manifest_versions,
                        required_service + " is missing in manifest.json",
                    ) and ok)

            elif ("min" not in required_version
                  and "max" not in required_version
                  and version.parse(required_version) <= actual_version):
                # If the first service set to a specific version in validation_config, other services should matches the version requirements
                ok = (version_requirement_validation(
                    requirement_list,
                    requirement_key_list,
                    manifest_versions,
                    "{} {}".format(requirement_key, actual_version),
                ) and ok)
            elif ("min" in required_version and "max" in required_version
                  and version.parse(required_version["min"]) <= actual_version
                  < version.parse(required_version["max"])):
                # if service is min_requirement <= service_version < max_requirement, other services should matches the version requirements
                ok = (version_requirement_validation(
                    requirement_list,
                    requirement_key_list,
                    manifest_versions,
                    "{} {}".format(requirement_key, actual_version),
                ) and ok)

    return ok
def validate_manifest_block(manifest, blocks_requirements):
    """
    Validates blocks in cdis-manifest.

    Args:
        manifest (dict): Contents of manifest.json file.
        blocks_requirements (dict): the "block" requirement under
            validation_config.yaml. The keys of the dict are the service names
            and the values are the requirements for the block associated to
            the service.

    Return:
        ok(bool): whether the validation succeeded.
    """
    ok = True

    for service_name, block in blocks_requirements.items():
        if service_name in manifest["versions"]:
            # Validation for all services has requirement in validation_config.
            block_requirement_version = get_manifest_version(
                manifest["versions"], service_name)
            is_branch = version_is_branch(block_requirement_version)
            should_check_has = type(
                block) == dict and "has" in block and not is_branch
            if type(block) == dict and "version" in block and not is_branch:
                # If we have version requirement for a service, min or max is required.
                # We are not validating branch or master branch
                # min: Version in manifest is equal or greater than the verson in validation_config
                # max: Version in manifest is smaller than the verson in validation_config

                min_version = block["version"].get("min")
                max_version = block["version"].get("max")
                if min_version:
                    min_version = version.parse(min_version)
                if max_version:
                    max_version = version.parse(max_version)

                if min_version and max_version:
                    should_check_has = (
                        min_version <= block_requirement_version < max_version)
                elif min_version:
                    should_check_has = block_requirement_version >= min_version
                elif max_version:
                    should_check_has = block_requirement_version < max_version

            if should_check_has:
                # Validation to check if a service has a specific key in its block in cdis-manfiest
                error_msg = "{} is missing in {} block or {} block is missing".format(
                    block["has"], service_name, service_name)

                ok = (assert_and_log(
                    service_name in manifest
                    and block["has"] in manifest[service_name]
                    or service_name not in manifest and block.get("optional"),
                    error_msg,
                ) and ok)

            if block is True:
                # Validation to check if a block exists in cdis-manifest
                ok = (assert_and_log(
                    service_name in manifest,
                    service_name + " block is missing in cdis-manifest",
                ) and ok)
    return ok
Exemple #5
0
def validate_gitops_syntax(gitops):
    """
    Validates the syntax of gitops.json by checking for required fields
    Args:
        gitops (dict): gitops.json config

    Returns:
        Error: Returns the error if it exists, else returns None.

    TODO
    Currently only checks syntax needed for etl mapping and dictionary validation.
    """
    graphql = gitops.get("graphql")
    ok = assert_and_log(graphql, FieldSyntaxError("graphql"))

    if graphql:
        ok = ok and assert_and_log("boardCounts" in graphql,
                                   FieldSyntaxError("graphql.boardCounts"))
        boardcounts = graphql.get("boardCounts", [])
        if boardcounts:
            for item in boardcounts:
                checks = ["graphql", "name", "plural"]
                ok = check_required_fields("graphql.boardCounts", checks, item,
                                           ok)

        ok = ok and assert_and_log("chartCounts" in graphql,
                                   FieldSyntaxError("graphql.chartCounts"))

    components = gitops.get("components")
    ok = ok and assert_and_log(components, FieldSyntaxError("components"))
    if components:
        index = components.get("index")
        ok = ok and assert_and_log(index, FieldSyntaxError("components.index"))
        if index:
            homepage = index.get("homepageChartNodes", [])
            ok = ok and assert_and_log(
                index, FieldSyntaxError("components.homepageChartNodes"))
            for item in homepage:
                checks = ["node", "name"]
                ok = check_required_fields("components.index.homepage", checks,
                                           item, ok)

        # footerLogos is optional, but when present, it must be an array (list)
        footerLogos = components.get("footerLogos", [])
        ok = ok and assert_and_log(
            isinstance(footerLogos, list),
            FieldError(
                "footerLogos must be an array if presents in the config"),
        )

    explorer_enabled = gitops.get("featureFlags", {}).get("explorer", True)
    explorerconfig = gitops.get("explorerConfig")
    configs = []
    if not explorerconfig:
        dataConfig = gitops.get("dataExplorerConfig")
        fileConfig = gitops.get("fileExplorerConfig")
        ok = ok and assert_and_log(dataConfig or not explorer_enabled,
                                   FieldSyntaxError("(data)explorerConfig"))
        if dataConfig:
            configs.append(dataConfig)
        if fileConfig:
            configs.append(fileConfig)
    else:
        configs = explorerconfig

    for exp_config in configs:
        filters = exp_config.get("filters")
        ok = ok and assert_and_log(filters,
                                   FieldSyntaxError("explorerConfig.filters"))
        if filters:
            tabs = filters.get("tabs", [])
            ok = ok and assert_and_log(
                tabs, FieldSyntaxError("explorerConfig.filters.tabs"))
            for tab in tabs:
                checks = ["title", "fields"]
                ok = check_required_fields("explorerConfig.filters.tab",
                                           checks, tab, ok)

        guppy = exp_config.get("guppyConfig")
        ok = ok and assert_and_log(
            guppy, FieldSyntaxError("explorerConfig.guppyConfig"))
        buttons = exp_config.get("buttons", [])
        manifest_mapping = None
        if guppy:
            ok = ok and assert_and_log(
                guppy.get("dataType"),
                FieldSyntaxError("explorerConfig.guppyConfig.dataType"),
            )
            manifest_mapping = guppy.get("manifestMapping")

        val_mapping = False
        for button in buttons:
            if button.get("enabled") and button.get("type") == "manifest":
                val_mapping = True
        if manifest_mapping and val_mapping:
            checks = [
                "resourceIndexType",
                "resourceIdField",
                "referenceIdFieldInResourceIndex",
                "referenceIdFieldInDataIndex",
            ]
            ok = check_required_fields(
                "explorerConfig.guppyConfig.manifestMapping",
                checks,
                manifest_mapping,
                ok,
            )

    study_viewer = gitops.get("studyViewerConfig")

    if study_viewer:
        checks = [
            "dataType",
            "listItemConfig",
            "rowAccessor",
        ]
        for viewer in study_viewer:
            ok = check_required_fields("studyViewerConfig", checks, viewer, ok)

    return ok
Exemple #6
0
def check_required_fields(path, checks, field, ok):
    for check in checks:
        ok = ok and assert_and_log(field.get(check),
                                   FieldSyntaxError(f"{path}.{check}"))
    return ok