azext_edge/edge/providers/check/base/deployment.py (107 lines of code) (raw):
# 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.
# ----------------------------------------------------------------------------------------------
from functools import partial
from typing import Any, Callable, Dict, List, Optional
from knack.log import get_logger
from kubernetes.client.exceptions import ApiException
from rich.padding import Padding
from ....common import CheckTaskStatus, ListableEnum
from ....providers.edge_api import EdgeResourceApi
from ...base import client
from ..common import CoreServiceResourceKinds, ResourceOutputDetailLevel
from .check_manager import CheckManager
from .node import check_nodes
from .resource import enumerate_ops_service_resources
from .user_strings import UNABLE_TO_DETERMINE_VERSION_MSG
logger = get_logger(__name__)
# TODO: unit test
def check_pre_deployment(
result: Dict[str, Any],
as_list: bool = False,
) -> None:
result["preDeployment"] = []
desired_checks = {}
desired_checks.update(
{
"checkK8sVersion": partial(_check_k8s_version, as_list=as_list),
"checkNodes": partial(check_nodes, as_list=as_list),
}
)
for c in desired_checks:
output = desired_checks[c]()
result["preDeployment"].append(output)
def check_post_deployment(
evaluate_funcs: Dict[ListableEnum, Callable],
as_list: bool = False,
detail_level: int = ResourceOutputDetailLevel.summary.value,
api_info: Optional[EdgeResourceApi] = None,
check_name: Optional[str] = None,
check_desc: Optional[str] = None,
resource_kinds: Optional[List[str]] = None,
resource_name: str = None,
excluded_resources: Optional[List[str]] = None,
) -> List[dict]:
results = []
lowercase_api_resources = {}
if api_info:
resource_enumeration, api_resources = enumerate_ops_service_resources(
api_info, check_name, check_desc, as_list, excluded_resources
)
results = [resource_enumeration]
lowercase_api_resources = {k.lower(): v for k, v in api_resources.items()}
for resource, evaluate_func in evaluate_funcs.items():
should_check_resource = not resource_kinds or resource.value in resource_kinds
append_resource = False
# only add core service evaluation if there is no resource filter
if resource == CoreServiceResourceKinds.RUNTIME_RESOURCE and not resource_kinds:
append_resource = True
elif (
resource
and lowercase_api_resources
and resource.value in lowercase_api_resources
and should_check_resource
):
append_resource = True
if append_resource:
results.append(evaluate_func(detail_level=detail_level, as_list=as_list, resource_name=resource_name))
return results
def _check_k8s_version(as_list: bool = False) -> Dict[str, Any]:
from kubernetes.client.models import VersionInfo
from ..common import MIN_K8S_VERSION
version_client = client.VersionApi()
target_k8s_version = "k8s"
check_manager = CheckManager(check_name="evalK8sVers", check_desc="Evaluate Kubernetes server")
check_manager.add_target(
target_name=target_k8s_version,
conditions=[f"(k8s version)>={MIN_K8S_VERSION}"],
)
try:
from packaging import version
version_details: VersionInfo = version_client.get_code()
except (ApiException, ImportError) as ae:
logger.debug(str(ae))
api_error_text = UNABLE_TO_DETERMINE_VERSION_MSG
check_manager.add_target_eval(
target_name=target_k8s_version,
status=CheckTaskStatus.error.value,
value=api_error_text,
)
check_manager.add_display(
target_name=target_k8s_version,
display=Padding(api_error_text, (0, 0, 0, 8)),
)
else:
major_version = version_details.major
minor_version = version_details.minor
semver = f"{major_version}.{minor_version}"
if version.parse(semver) >= version.parse(MIN_K8S_VERSION):
semver_status = CheckTaskStatus.success.value
semver_colored = f"[green]v{semver}[/green]"
else:
semver_status = CheckTaskStatus.error.value
semver_colored = f"[red]v{semver}[/red]"
k8s_semver_text = (
f"Require [bright_blue]k8s[/bright_blue] >=[cyan]{MIN_K8S_VERSION}[/cyan] detected {semver_colored}."
)
check_manager.add_target_eval(target_name=target_k8s_version, status=semver_status, value=semver)
check_manager.add_display(
target_name=target_k8s_version,
display=Padding(k8s_semver_text, (0, 0, 0, 8)),
)
return check_manager.as_dict(as_list)