Skip to content

Commit

Permalink
fix: error when expected CRD is not deployed instead of skip (Azure#244)
Browse files Browse the repository at this point in the history
  • Loading branch information
Elsie4ever authored and Ryan Kelly committed Jul 3, 2024
1 parent b0f37eb commit 1b756bc
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 12 deletions.
3 changes: 1 addition & 2 deletions azext_edge/edge/providers/check/base/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ def enumerate_ops_service_resources(
)

if not api_resources:
check_manager.add_target_eval(target_name=target_api, status=CheckTaskStatus.skipped.value)
check_manager.add_target_eval(target_name=target_api, status=CheckTaskStatus.error.value)
missing_api_text = (
f"[bright_blue]{target_api}[/bright_blue] API resources [red]not[/red] detected."
"\n\n[bright_white]Skipping deployment evaluation[/bright_white]."
)
check_manager.add_display(target_name=target_api, display=Padding(missing_api_text, (0, 0, 0, 8)))
return check_manager.as_dict(as_list), resource_kind_map
Expand Down
7 changes: 4 additions & 3 deletions azext_edge/edge/providers/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from ..common import ListableEnum, OpsServiceType
from .check.base import check_pre_deployment, display_as_list
from .check.common import ResourceOutputDetailLevel
from .check.common import COLOR_STR_FORMAT, ResourceOutputDetailLevel
from .check.dataprocessor import check_dataprocessor_deployment
from .check.deviceregistry import check_deviceregistry_deployment
from .check.lnm import check_lnm_deployment
Expand Down Expand Up @@ -48,10 +48,11 @@ def run_checks(

sleep(0.5)

color = COLOR_STR_FORMAT.format(color="bright_blue", value="{text}") if as_list else "{text}"
title_subject = (
f"{{[bright_blue]{ops_service}[/bright_blue]}} service deployment"
f"{{{color.format(text=ops_service)}}} service deployment"
if post_deployment
else "[bright_blue]IoT Operations readiness[/bright_blue]"
else color.format(text="IoT Operations readiness")
)
result["title"] = f"Evaluation for {title_subject}"

Expand Down
148 changes: 148 additions & 0 deletions azext_edge/tests/edge/checks/base/test_resource_unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# coding=utf-8
# ----------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License file in the project root for license information.
# ----------------------------------------------------------------------------------------------

import pytest

from azext_edge.edge.common import CheckTaskStatus
from azext_edge.edge.providers.check.base.resource import enumerate_ops_service_resources
from azext_edge.edge.providers.check.common import ALL_NAMESPACES_TARGET
from azext_edge.edge.providers.edge_api import (
AKRI_API_V0,
AkriResourceKinds,
MQ_ACTIVE_API,
MqResourceKinds,
OPCUA_API_V1,
OpcuaResourceKinds,
)
from azext_edge.tests.edge.checks.conftest import generate_api_resource_list
# TODO: Add more test for resource.py


@pytest.mark.parametrize(
"api_info, resource_kinds, check_name, check_desc,\
excluded_resources, api_resources, expected_resource_map, status",
[
(MQ_ACTIVE_API, MqResourceKinds.list(), "mq", "MQ", None, [], {}, CheckTaskStatus.error.value),
(
AKRI_API_V0, AkriResourceKinds.list(), "akri", "AKRI", None,
generate_api_resource_list
(
api_version=AKRI_API_V0.version,
group_version=AKRI_API_V0.as_str(),
resources=[
{
'categories': None,
'group': None,
'kind': 'Instance',
'name': 'instances',
'namespaced': True,
'short_names': ['akrii'],
'singular_name': 'instance',
'verbs': [
'delete',
'deletecollection',
'get',
'list',
'patch',
'create',
'update',
'watch'
],
},
{
'categories': None,
'group': None,
'kind': 'Configuration',
'name': 'configurations',
'namespaced': True,
'short_names': ['akric'],
'singular_name': 'configuration',
'verbs': [
'delete',
'deletecollection',
'get',
'list',
'patch',
'create',
'update',
'watch'
],
}
]
),
{
AkriResourceKinds.INSTANCE.value.capitalize(): True,
AkriResourceKinds.CONFIGURATION.value.capitalize(): True
},
CheckTaskStatus.success.value
),
(
OPCUA_API_V1, OpcuaResourceKinds.list(), "opcua", "OPCUA", ["assettypes"],
generate_api_resource_list(
api_version=OPCUA_API_V1.version,
group_version=OPCUA_API_V1.as_str(),
resources=[
{
'categories': None,
'group': None,
'kind': 'AssetType',
'name': 'assettypes',
'namespaced': True,
'short_names': None,
'singular_name': 'assettype',
'storage_version_hash': 'FCPRUJA7s2I=',
'verbs': [
'delete',
'deletecollection',
'get',
'list',
'patch',
'create',
'update',
'watch'
],
'version': None
},
]
),
{},
CheckTaskStatus.success.value
),
]
)
def test_enumerate_ops_service_resources(
mock_get_cluster_custom_api,
api_info,
resource_kinds,
api_resources,
check_name,
check_desc,
excluded_resources,
expected_resource_map,
status,
):
mock_get_cluster_custom_api.return_value = api_resources
result, resource_map = enumerate_ops_service_resources(
api_info=api_info,
check_name=check_name,
check_desc=check_desc,
as_list=False,
excluded_resources=excluded_resources,
)
assert len(result["targets"][api_info.as_str()]) == 1
target_key = f"{api_info.group}/{api_info.version}"
assert target_key in result["targets"]
evaluation = result["targets"][api_info.as_str()][ALL_NAMESPACES_TARGET]
assert evaluation["conditions"] is None
assert evaluation["status"] == status
assert len(evaluation["evaluations"]) == 1
assert evaluation["evaluations"][0]["status"] == status
assert resource_map == expected_resource_map

if status == expected_resource_map:
assert len(evaluation["evaluations"][0]["value"]) == len(resource_kinds)
for kind in evaluation["evaluations"][0]["value"]:
assert kind.lower() in resource_kinds
17 changes: 16 additions & 1 deletion azext_edge/tests/edge/checks/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Licensed under the MIT License. See License file in the project root for license information.
# ----------------------------------------------------------------------------------------------
import pytest
from kubernetes.client import V1Pod, V1ObjectMeta, V1PodStatus, V1PodCondition
from kubernetes.client import V1Pod, V1ObjectMeta, V1PodStatus, V1PodCondition, V1APIResourceList, V1APIResource
from typing import List, Dict, Any
from azext_edge.edge.providers.checks import run_checks
from azext_edge.edge.providers.check.common import CoreServiceResourceKinds
Expand Down Expand Up @@ -99,6 +99,12 @@ def mock_opcua_get_namespaced_pods_by_prefix(mocker):
yield patched


@pytest.fixture
def mock_get_cluster_custom_api(mocker):
patched = mocker.patch("azext_edge.edge.providers.check.base.resource.get_cluster_custom_api")
yield patched


@pytest.fixture
def mock_resource_types(mocker, ops_service):
patched = mocker.patch("azext_edge.edge.providers.check.base.deployment.enumerate_ops_service_resources")
Expand Down Expand Up @@ -220,6 +226,15 @@ def generate_pod_stub(
return pod


def generate_api_resource_list(
api_version: str,
group_version: str,
resources: List[Dict[str, Any]],
):
resources = [V1APIResource(**resource) for resource in resources]
return V1APIResourceList(api_version=api_version, group_version=group_version, resources=resources)


def assert_check_by_resource_types(ops_service, mocker, resource_kinds, eval_lookup):
# Mock the functions
for key, value in eval_lookup.items():
Expand Down
10 changes: 6 additions & 4 deletions azext_edge/tests/edge/checks/int/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def assert_enumerate_resources(
present: bool = True
):
key = f"enumerate{key_name}Api"
status = "success" if present else "skipped"
status = "success" if present else "error"
assert post_deployment[key]
assert post_deployment[key]["status"] == status
assert post_deployment[key]["description"] == f"Enumerate {description_name} API resources"
Expand All @@ -38,9 +38,11 @@ def assert_enumerate_resources(
assert evaluation["status"] == status
assert len(evaluation["evaluations"]) == 1
assert evaluation["evaluations"][0]["status"] == status
assert len(evaluation["evaluations"][0]["value"]) == len(resource_kinds)
for kind in evaluation["evaluations"][0]["value"]:
assert kind.lower() in resource_kinds

if present:
assert len(evaluation["evaluations"][0]["value"]) == len(resource_kinds)
for kind in evaluation["evaluations"][0]["value"]:
assert kind.lower() in resource_kinds


# Used by Akri and OPCUA
Expand Down
4 changes: 2 additions & 2 deletions azext_edge/tests/edge/checks/int/test_pre_post_int.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def test_check_pre_post(init_setup, post, pre):
result = run(command)

# default service title
expected_title = "Evaluation for {[bright_blue]mq[/bright_blue]} service deployment"
expected_precheck_title = "[bright_blue]IoT Operations readiness[/bright_blue]"
expected_title = "Evaluation for {mq} service deployment"
expected_precheck_title = "IoT Operations readiness"
expected_pre = not post if pre is None else pre
expected_post = not pre if post is None else post
assert result["title"] == expected_title if expected_post else expected_precheck_title
Expand Down

0 comments on commit 1b756bc

Please sign in to comment.