From 9cfc60139d0fd30c2d2ca8d308077577b28bbeb8 Mon Sep 17 00:00:00 2001 From: lasiva <45047672+lasiva@users.noreply.github.com> Date: Tue, 1 Feb 2022 10:55:31 -0500 Subject: [PATCH] Issue 164: Pre_Install_Report : Update deprecated Kubernetes APIs in tool to be compatible with Viya supported range 1.20.x-1.22.x (#165) * (#issue_164) Initial push to branch * (issue_164) Fix pytest * (issue_164) Fix pytest * (issue_164) Fix Copyrights * (issue_164) Fix Review Comments * (issue_164) Fix Flake8 * (issue_164) Fix Log for K8s Version * (issue_164) Update/consolidate code to discover Kubernetes version. Use it on Worker Nodes. * (issue_164) Update Pytests * (issue_164) Update Ingress to k8s 1.22 * (issue_164) Fix Review comments from Kevin * (issue_164) Re-do Copyright Years * (issue_164) Re-do Copyright Years --- pre_install_report/README.md | 6 +- .../library/pre_install_check.py | 136 +++++++++++++----- .../library/pre_install_check_permissions.py | 55 +------ pre_install_report/library/utils/crdviya.yaml | 27 +++- pre_install_report/library/utils/crviya.yaml | 6 +- .../library/utils/hello-ingress-k8s-v118.yaml | 27 ---- .../library/utils/hello-ingress.yaml | 5 +- .../library/utils/viya_constants.py | 6 +- .../library/utils/viya_messages.py | 4 +- pre_install_report/pre_install_report.py | 2 +- .../report_template_viya_pre_install_check.j2 | 11 +- .../test/test_pre_install_report.py | 96 ++++++++----- 12 files changed, 218 insertions(+), 163 deletions(-) delete mode 100644 pre_install_report/library/utils/hello-ingress-k8s-v118.yaml diff --git a/pre_install_report/README.md b/pre_install_report/README.md index 4fd315f..86fcb85 100644 --- a/pre_install_report/README.md +++ b/pre_install_report/README.md @@ -9,6 +9,10 @@ deployment in a Kubernetes cluster. The tool cannot account for the dynamic res Kubernetes may orchestrate once Viya is deployed. The report and the information therein must be considered a snapshot in time. +The Kubernetes cluster for a SAS Viya deployment must meet the requirements documented in [SAS® Viya® Operations](https://go.documentation.sas.com/doc/en/itopscdc/default/itopssr/titlepage.htm) +Ensure that the Kubernetes version is within the documented range for the selected cloud provider. + + ### Memory and vCPU Check The tool calculates the aggregate Memory and aggregate vCPUs of your cluster. The aggregate Memory is the sum of the Memory capacity on all the active and running nodes. The aggregate CPU is calculated similarly. @@ -38,11 +42,9 @@ If calculated aggregate vCPUs is less than VIYA_MIN_AGGREGATE_WORKER_CPU_CORES t SAS recommends using the SAS Viya 4 Infrastructure as Code (IaC) tools to create a cluster. Refer to the following IaC repositories for [Microsoft Azure](https://github.com/sassoftware/viya4-iac-azure), [AWS](https://github.com/sassoftware/viya4-iac-aws]) or [GCP](https://github.com/sassoftware/viya4-iac-gcp). For OpenShift refer to the documentation in SAS® Viya® Operations [OpenShift](https://go.documentation.sas.com/doc/en/itopscdc/v_019/itopssr/n1ika6zxghgsoqn1mq4bck9dx695.htm#p1c8bxlbu0gzuvn1e75nck1yozcn) - **Example**: Setting for aggregate Memory and vCPU for deployment based on documentation in SAS Viya Operations under System Requirements in the Hardware and Resource Requirements section. See Sizing Recommendations for Microsoft Azure. - | Offering | CAS Node(s) | System Node | Nodes in User Node Pool(s) | | ------------------------- |------------- | --------- | -------------| | SAS Visual Analytics and SAS Data Preparation | Num of Node: Node 1, CPU: 16, Memory, 128 | Num. of Nodes: 1, CPU: 8, Memory: 64 | Num of Node: 1 per Node User Node Pool, CPU: 8 Memory 64 | diff --git a/pre_install_report/library/pre_install_check.py b/pre_install_report/library/pre_install_check.py index 47b8201..2cf15d5 100644 --- a/pre_install_report/library/pre_install_check.py +++ b/pre_install_report/library/pre_install_check.py @@ -5,7 +5,7 @@ # ### Author: SAS Institute Inc. ### #################################################################### # ### -# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. ### +# Copyright (c) 2021-2022, SAS Institute Inc., Cary, NC, USA. ### # All Rights Reserved. ### # SPDX-License-Identifier: Apache-2.0 ### # ### @@ -21,9 +21,10 @@ import subprocess import pint from subprocess import CalledProcessError -from typing import Text +from typing import Text, Dict # import pint to add, compare memory +import semantic_version from pint import UnitRegistry from pre_install_report.library.utils import viya_messages @@ -64,7 +65,6 @@ def __init__(self, sas_logger: ViyaARKLogger, viya_kubelet_version_min, self._kubectl: KubectlInterface = None self.sas_logger = sas_logger self.logger = self.sas_logger.get_logger() - self._min_kubelet_version: tuple = () self._viya_kubelet_version_min = viya_kubelet_version_min self._viya_min_aggregate_worker_CPU_cores: Text = viya_min_aggregate_worker_CPU_cores self._viya_min_aggregate_worker_memory: Text = viya_min_aggregate_worker_memory @@ -72,6 +72,7 @@ def __init__(self, sas_logger: ViyaARKLogger, viya_kubelet_version_min, self._workers = 0 self._aggregate_nodeStatus_failures = 0 self._ingress_controller = None + self._k8s_server_version = None def _parse_release_info(self, release_info): """ @@ -91,6 +92,65 @@ def _parse_release_info(self, release_info): print(viya_messages.KUBELET_VERSION_ERROR) sys.exit(viya_messages.BAD_OPT_RC_) + def _validate_k8s_server_version(self, version): + """ + Validate the major and minor parts of the kubernetes version. The 3rd part is not specified in the Kubernetes + cluster requirements + """ + version_parts_to_validate = 2 + version_lst = version.split('.') + if (len(version_lst) < version_parts_to_validate): + self.logger.error(viya_messages.KUBERNETES_VERSION_ERROR.format(version)) + print(viya_messages.KUBERNETES_VERSION_ERROR.format(version)) + sys.exit(viya_messages.INVALID_K8S_VERSION_RC_) + + for i in range(version_parts_to_validate): + if version_lst[i].startswith("0") or float(version_lst[i]) < 0: + self.logger.error(viya_messages.KUBERNETES_VERSION_ERROR.format(version)) + print(viya_messages.KUBERNETES_VERSION_ERROR.format(version)) + sys.exit(viya_messages.INVALID_K8S_VERSION_RC_) + i += 1 + return 0 + + def _retrieve_k8s_server_version(self, utils): + """ + Retrieve the Kubernetes server version and validate the git version + """ + try: + versions: Dict = utils.get_k8s_version() + server_version = versions.get('serverVersion') + git_version = str(server_version.get('gitVersion')) + self.logger.debug("git_version {} ".format(git_version)) + # check git_version is not empty + if git_version and git_version.startswith("v"): + git_version = git_version[1:] + self._validate_k8s_server_version(git_version) + + self.logger.info('Kubernetes Server version = {}'.format(git_version)) + return git_version + except CalledProcessError as cpe: + self.logger.exception('kubectl version command failed. Return code = {}'.format(str(cpe.returncode))) + sys.exit(viya_messages.RUNTIME_ERROR_RC_) + + def _k8s_server_version_min(self): + """ + Compare Kubernetes Version to the Minimum version expected. See + https://pypi.org/project/semantic_version/ 2.8.5 initial version + """ + try: + curr_version = semantic_version.Version(str(self._k8s_server_version)) + + if(curr_version in semantic_version.SimpleSpec(viya_constants.MIN_K8S_SERVER_VERSION)): + self.logger.error("This release of Kubernetes is not supported {}.{}.x" + .format(str(curr_version.major), + str(curr_version.minor))) + return False + else: + return True + except ValueError as cpe: + self.logger.exception(viya_messages.EXCEPTION_MESSAGE.format(str(cpe))) + sys.exit(viya_messages.RUNTIME_ERROR_RC_) + def check_details(self, kubectl, ingress_port, ingress_host, ingress_controller, output_dir): self._ingress_controller = ingress_controller @@ -110,6 +170,8 @@ def check_details(self, kubectl, ingress_port, ingress_host, ingress_controller, pre_check_utils_params["logger"] = self.sas_logger utils = PreCheckUtils(pre_check_utils_params) + self._k8s_server_version = self._retrieve_k8s_server_version(utils) + configs_data = self.get_config_info() cluster_info = self._get_master_json() master_data = self._check_master(cluster_info) @@ -130,11 +192,22 @@ def check_details(self, kubectl, ingress_port, ingress_host, ingress_controller, params[viya_constants.INGRESS_HOST] = str(ingress_host) params[viya_constants.INGRESS_PORT] = str(ingress_port) params[viya_constants.PERM_CLASS] = utils + params[viya_constants.SERVER_K8S_VERSION] = self._k8s_server_version params['logger'] = self.sas_logger permissions_check = PreCheckPermissions(params) self._check_permissions(permissions_check) + test_list = [viya_constants.INSUFFICIENT_PERMS, viya_constants.PERM_SKIPPING] + + # Log Summary of Permissions Issues found + if(any(ele in str(permissions_check.get_cluster_admin_permission_aggregate()) for ele in test_list)): + self.logger.warn("WARN: Review Cluster Aggregate Report") + if(any(ele in str(permissions_check.get_namespace_admin_permission_aggregate()) for ele in test_list)): + self.logger.warn("WARN: Review Namespace Aggregate Report") + if(any(ele in str(permissions_check.get_namespace_admin_permission_data()) for ele in test_list)): + self.logger.warn("WARN: Review Namespace Permissions") + self.generate_report(global_data, master_data, configs_data, storage_data, namespace_data, permissions_check.get_cluster_admin_permission_data(), permissions_check.get_namespace_admin_permission_data(), @@ -389,8 +462,6 @@ def _check_permissions(self, permissions_check: PreCheckPermissions): permissions_check: instance of PreCheckPermissions class """ namespace = self._kubectl.get_namespace() - permissions_check.get_server_git_version() - permissions_check.set_ingress_manifest_file() permissions_check.get_sc_resources() permissions_check.manage_pvc(viya_constants.KUBECTL_APPLY, False) @@ -520,6 +591,20 @@ def _set_time(self, global_data): self.logger.debug("global data{} time{}".format(pprint.pformat(global_data), time_string)) return global_data + def _update_k8s_version(self, global_data, git_version): + """Set the Cluster Kubernetes Version for the report in the global data list + + global_data: List to be updated + return: global_data list updated with Kubernetes Version to be added to the report + """ + global_nodes = {} + + global_nodes.update({'k8sVersion': str(git_version)}) + global_data.append(global_nodes) + + self.logger.debug("global data{} Kubernetes Version {}".format(pprint.pformat(global_data), git_version)) + return global_data + def _check_cpu_errors(self, global_data, total_capacity_cpu_cores: float, aggregate_cpu_failures): """ Check if the aggregate CPUs across all worker nodes meets SAS total cpu requirements @@ -708,8 +793,6 @@ def evaluate_nodes(self, nodes_data, global_data, cluster_info, quantity_): global_data: list of dictionary object with global data for nodes return: return ist of dictionary objects with updated information and status """ - self._min_kubelet_version = self._parse_release_info(self._viya_kubelet_version_min) - aggregate_cpu_failures = int(0) aggregate_memory_failures = int(0) aggregate_kubelet_failures = int(0) @@ -749,15 +832,18 @@ def evaluate_nodes(self, nodes_data, global_data, cluster_info, quantity_): self._set_status(0, node, 'capacityMemory') node['error']['capacityMemory'] = "See below." - if self._release_in_range(kubeletversion): + if (self._k8s_server_version_min()): self._set_status(0, node, 'kubeletversion') + self.logger.debug("node kubeletversion status 0 {} ".format(pprint.pformat(node))) else: self._set_status(1, node, 'kubeletversion') node['error']['kubeletversion'] = viya_constants.SET + ': ' + kubeletversion + ', ' + \ - str(viya_constants.EXPECTED) + ': ' + self._viya_kubelet_version_min + ' or later ' + str(viya_constants.EXPECTED) + ': ' + viya_constants.MIN_K8S_SERVER_VERSION[1:] + ' or later ' aggregate_kubelet_failures += 1 - self.logger.debug("node {} ".format(pprint.pformat(node))) + self.logger.debug("aggregate_kubelet_failures {} ".format(str(aggregate_kubelet_failures))) + self.logger.debug("node kubeletversion{} ".format(pprint.pformat(node))) + global_data = self._check_workers(global_data, nodes_data) global_data = self._set_time(global_data) global_data = self._check_cpu_errors(global_data, total_cpu_cores, aggregate_cpu_failures) @@ -767,6 +853,7 @@ def evaluate_nodes(self, nodes_data, global_data, cluster_info, quantity_): global_data = self._check_kubelet_errors(global_data, aggregate_kubelet_failures) global_data.append(nodes_data) + global_data = self._update_k8s_version(global_data, self._k8s_server_version) self.logger.debug("nodes_data {}".format(pprint.pformat(nodes_data))) return global_data @@ -904,32 +991,6 @@ def _get_config_json(self): self.logger.debug("config view JSON{} return_code{}".format(str(config_json), str(return_code))) return config_json, return_code - def _release_in_range(self, kubeletversion): - """ - Check if the current kublet version retrieved from the cluster nodes is equal to or greater - than the major/minor version specified in the viya_cluster_settings file - - :param kubeletversion - current version in cluster node - :return True if version is within range. If not return False - """ - - try: - current = tuple(kubeletversion.split(".")) - - if int(current[0][1:]) > int(self._min_kubelet_version[0][1:]): - return True - if int(current[0][1:]) < int(self._min_kubelet_version[0][1:]): - return False - if int(current[0][1:]) == int(self._min_kubelet_version[0][1:]) and \ - (int(current[1]) >= int(self._min_kubelet_version[1])): - return True - return False - except ValueError: - print(viya_messages.LIMIT_ERROR.format("VIYA_KUBELET_VERSION_MIN", str(self._min_kubelet_version))) - self.logger.exception(viya_messages.LIMIT_ERROR.format("VIYA_KUBELET_VERSION_MIN", - str(self._min_kubelet_version))) - sys.exit(viya_messages.BAD_OPT_RC_) - def _get_memory(self, limit, key, quantity_): """ Check that the memory specified in the viya_cluster_settings file is valid. Exit if @@ -991,6 +1052,9 @@ def get_config_info(self): def get_calculated_aggregate_memory(self): return self._calculated_aggregate_memory + def set_k8s_version(self, version: Text): + self._k8s_server_version = version + def generate_report(self, global_data, master_data, diff --git a/pre_install_report/library/pre_install_check_permissions.py b/pre_install_report/library/pre_install_check_permissions.py index a687dc6..9495372 100644 --- a/pre_install_report/library/pre_install_check_permissions.py +++ b/pre_install_report/library/pre_install_check_permissions.py @@ -5,21 +5,18 @@ # ### Author: SAS Institute Inc. ### #################################################################### # ### -# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. ### +# Copyright (c) 2021-2022, SAS Institute Inc., Cary, NC, USA. ### # All Rights Reserved. ### # SPDX-License-Identifier: Apache-2.0 ### # ### #################################################################### import os -from subprocess import CalledProcessError -from typing import List, Dict +from typing import List import requests -import sys import pprint -import semantic_version from requests.packages.urllib3.exceptions import InsecureRequestWarning -from pre_install_report.library.utils import viya_constants, viya_messages +from pre_install_report.library.utils import viya_constants from pre_install_report.library.pre_install_utils import PreCheckUtils from viya_ark_library.k8s.k8s_resource_type_values import KubernetesResourceTypeValues from viya_ark_library.logging import ViyaARKLogger @@ -46,8 +43,6 @@ PROVISIONER_AZURE_DISK = "kubernetes.io/azure-disk" PROVISIONER_AWS_EBS = "kubernetes.io/aws-ebs" -INGRESS_V1BETA1_REL_EQ = '==1.18' -INGRESS_UNSUPPORTED_REL_LT = '<1.18' OPS_ROUTE_NAME = "no-route-hello-world" OPS_ROUTE_KEY = "host" @@ -87,7 +82,7 @@ def __init__(self, params): self._storage_class_sc: List[KubernetesResource] = None self._sample_deployment = 0 self._sample_output = "" - self._k8s_git_version = None + self._k8s_git_version = params.get(viya_constants.SERVER_K8S_VERSION) self._openshift_host_port = viya_constants.NO_HOST_FOUND self._route_k8s_resource: KubernetesResource = None @@ -340,7 +335,6 @@ def get_storage_classes_details(self): str(k8s_resource.get_parameter_value('storageaccounttype')))) if str(k8s_resource.get_provisioner()) == PROVISIONER_AWS_EBS and \ - ("/storageclasses/gp2" in str(k8s_resource.get_self_link())) and \ str(k8s_resource.get_parameter_value('type')) == SC_TYPE_AWS_EBS: storage_classes.append((str(k8s_resource.get_name()), PVC_AWS_EBS, @@ -492,45 +486,6 @@ def check_sample_service(self): 'helloworld-svc.yaml') self._set_results_namespace_admin(viya_constants.PERM_SERVICE, rc) - def get_server_git_version(self): - """ - Retrieve the Kubernetes server version and validate the git version - """ - try: - versions: Dict = self.utils.get_k8s_version() - server_version = versions.get('serverVersion') - git_version = server_version.get('gitVersion') - self.logger.info("git_version {} ".format(str(git_version))) - - if git_version.startswith("v"): - git_version = git_version[1:] - self.set_k8s_git_version(git_version) - except CalledProcessError as cpe: - self.logger.exception('kubectl version command failed. Return code = {}'.format(str(cpe.returncode))) - sys.exit(viya_messages.RUNTIME_ERROR_RC_) - - def set_ingress_manifest_file(self): - """ - Retrieve the server Kubernetes gitVersion using and compare it using - https://pypi.org/project/semantic_version/ 2.8.5 initial version - """ - try: - curr_version = semantic_version.Version(str(self.get_k8s_git_version())) - - if(curr_version in semantic_version.SimpleSpec(INGRESS_V1BETA1_REL_EQ)): - self._ingress_file = "hello-ingress-k8s-v118.yaml" - self.logger.debug("hello-ingress file deployed {} major {} minor {}" - .format(str(self._ingress_file), str(curr_version.major), - str(curr_version.minor))) - if(curr_version in semantic_version.SimpleSpec(INGRESS_UNSUPPORTED_REL_LT)): - self._ingress_file = "hello-ingress-k8s-v118.yaml" - self.logger.error("This release of Kubernetes is not supported. major {} minor {}" - .format(str(curr_version.major), - str(curr_version.minor))) - except ValueError as cpe: - self.logger.exception(viya_messages.EXCEPTION_MESSAGE.format(str(cpe))) - sys.exit(viya_messages.RUNTIME_ERROR_RC_) - def check_sample_ingress(self): """ Deploy Kubernetes Ingress for hello-world appliction in the specified @@ -675,7 +630,7 @@ def check_rbac_role(self): """ found = self.utils.get_rbac_group_cmd() - self.logger.debug("get_rbace_group_cmd found = {}, sample_deployment = {}" + self.logger.debug("get_rbac_group_cmd found = {}, sample_deployment = {}" .format(str(found), str(self._sample_deployment))) if found: rc = self.utils.deploy_manifest_file(viya_constants.KUBECTL_APPLY, diff --git a/pre_install_report/library/utils/crdviya.yaml b/pre_install_report/library/utils/crdviya.yaml index 53264e7..6bac1bd 100644 --- a/pre_install_report/library/utils/crdviya.yaml +++ b/pre_install_report/library/utils/crdviya.yaml @@ -7,16 +7,37 @@ #################################################################### #################################################################### # -# Copyright (c) 2019-2020, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. +# Copyright (c) 2019-2022, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 metadata: name: viyas.company.com spec: group: company.com - version: v1 + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + company: + type: string + industry: + type: string + enum: + - software + replicas: + type: integer + minimum: 1 + required: ["company", "industry"] + required: ["spec"] scope: Namespaced names: plural: viyas diff --git a/pre_install_report/library/utils/crviya.yaml b/pre_install_report/library/utils/crviya.yaml index 27a3a1b..b840102 100644 --- a/pre_install_report/library/utils/crviya.yaml +++ b/pre_install_report/library/utils/crviya.yaml @@ -7,10 +7,14 @@ #################################################################### #################################################################### # -# Copyright (c) 2019-2020, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. +# Copyright (c) 2019-2022, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # apiVersion: company.com/v1 kind: Viya metadata: name: testcr +spec: + company: testcr + industry: software + replicas: 1 \ No newline at end of file diff --git a/pre_install_report/library/utils/hello-ingress-k8s-v118.yaml b/pre_install_report/library/utils/hello-ingress-k8s-v118.yaml deleted file mode 100644 index be4df26..0000000 --- a/pre_install_report/library/utils/hello-ingress-k8s-v118.yaml +++ /dev/null @@ -1,27 +0,0 @@ -#################################################################### -#### hello-ingress.yml #### -#################################################################### -#################################################################### -#### Author: SAS Institute Inc. #### -#### #### -#################################################################### -#################################################################### -# -# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -# ---- -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: hello-world - annotations: - kubernetes.io/ingress.class: "nginx" -spec: - rules: - - http: - paths: - - backend: - serviceName: hello-world - servicePort: 8080 - path: /hello-world diff --git a/pre_install_report/library/utils/hello-ingress.yaml b/pre_install_report/library/utils/hello-ingress.yaml index a4bbaa2..6d56f14 100644 --- a/pre_install_report/library/utils/hello-ingress.yaml +++ b/pre_install_report/library/utils/hello-ingress.yaml @@ -7,7 +7,7 @@ #################################################################### #################################################################### # -# Copyright (c) 2019-2021, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. +# Copyright (c) 2019-2022 SAS Institute Inc., Cary, NC, USA. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # --- @@ -15,9 +15,8 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hello-world - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / spec: + ingressClassName: nginx rules: - http: paths: diff --git a/pre_install_report/library/utils/viya_constants.py b/pre_install_report/library/utils/viya_constants.py index 63d82eb..74d8bfc 100644 --- a/pre_install_report/library/utils/viya_constants.py +++ b/pre_install_report/library/utils/viya_constants.py @@ -4,7 +4,7 @@ # ### Author: SAS Institute Inc. ### #################################################################### # ### -# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. ### +# Copyright (c) 2021-2022, SAS Institute Inc., Cary, NC, USA. ### # All Rights Reserved. ### # SPDX-License-Identifier: Apache-2.0 ### # ### @@ -60,3 +60,7 @@ # Check cluster capacity for Memory against Percentage of Memory set in the viya_deployment_settings.ini VIYA_PERCENTAGE_OF_INSTANCE = "85" MEMORY_WITHIN_RANGE = " Memory within Range" +SERVER_K8S_VERSION = "Server_k8s_version" + +# Any versions below this minimum are not supported +MIN_K8S_SERVER_VERSION = '<1.20' diff --git a/pre_install_report/library/utils/viya_messages.py b/pre_install_report/library/utils/viya_messages.py index c507d3f..fae9e32 100644 --- a/pre_install_report/library/utils/viya_messages.py +++ b/pre_install_report/library/utils/viya_messages.py @@ -4,7 +4,7 @@ # ### Author: SAS Institute Inc. ### #################################################################### # ### -# Copyright (c) 2020, SAS Institute Inc., Cary, NC, USA. ### +# Copyright (c) 2020-2022, SAS Institute Inc., Cary, NC, USA. ### # All Rights Reserved. ### # SPDX-License-Identifier: Apache-2.0 ### # ### @@ -29,6 +29,7 @@ EXCEPTION_MESSAGE = "ERROR: {}" KUBECONF_FILE_ERROR = "ERROR: The file specified in the KUBECONFIG environment does not exist. " \ "Check that file {} exists." +KUBERNETES_VERSION_ERROR = "Kubernetes version is missing or invalid: {}" # command line return codes # SUCCESS_RC_ = 0 @@ -40,3 +41,4 @@ NAMESPACE_NOT_FOUND_RC_ = 6 RUNTIME_ERROR_RC_ = 7 SET_LIMTS_ERROR_RC_ = 8 +INVALID_K8S_VERSION_RC_ = 9 diff --git a/pre_install_report/pre_install_report.py b/pre_install_report/pre_install_report.py index 7f03deb..f7467c7 100644 --- a/pre_install_report/pre_install_report.py +++ b/pre_install_report/pre_install_report.py @@ -5,7 +5,7 @@ # ### Author: SAS Institute Inc. ### #################################################################### # ### -# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. ### +# Copyright (c) 2021-2022, SAS Institute Inc., Cary, NC, USA. ### # All Rights Reserved. ### # SPDX-License-Identifier: Apache-2.0 ### # ### diff --git a/pre_install_report/templates/report_template_viya_pre_install_check.j2 b/pre_install_report/templates/report_template_viya_pre_install_check.j2 index 0645df1..8bcb8af 100644 --- a/pre_install_report/templates/report_template_viya_pre_install_check.j2 +++ b/pre_install_report/templates/report_template_viya_pre_install_check.j2 @@ -3,7 +3,7 @@ {# ----------------------------------------------------------- #} {# Author: SAS Institute Inc. #} {# ----------------------------------------------------------- #} -{# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. #} +{# Copyright (c) 2021-2022, SAS Institute Inc., Cary, NC, USA. #} {# All Rights Reserved. #} {# SPDX-License-Identifier: Apache-2.0 #} {# ----------------------------------------------------------- #} @@ -52,10 +52,17 @@ {% for global_nodes in global_data %} {% if loop.index == 1 %} -

Worker Nodes Detected - {{global_nodes.totalWorkers}}

+

Worker Nodes Detected: {{global_nodes.totalWorkers}}

{% endif %} {% endfor %} + +{% for global_nodes in global_data %} + {% if loop.index == 7 %} + +

Kubernetes Version: {{global_nodes.k8sVersion}}

+ {% endif %} +{% endfor %} {% for contexts in configs_data %} {% if loop.index == 2 %} diff --git a/pre_install_report/test/test_pre_install_report.py b/pre_install_report/test/test_pre_install_report.py index 514fa4a..415509d 100644 --- a/pre_install_report/test/test_pre_install_report.py +++ b/pre_install_report/test/test_pre_install_report.py @@ -5,7 +5,7 @@ # ### Author: SAS Institute Inc. ### #################################################################### # ### -# Copyright (c) 2021, SAS Institute Inc., Cary, NC, USA. ### +# Copyright (c) 2021-2022, SAS Institute Inc., Cary, NC, USA. ### # All Rights Reserved. ### # SPDX-License-Identifier: Apache-2.0 ### # ### @@ -39,6 +39,7 @@ _RUNTIME_ERROR_RC_ = 7 viya_kubelet_version_min = 'v1.14.0' +viya_kubenetes_version = "1.22.4" viya_min_aggregate_worker_CPU_cores = '12' viya_min_aggregate_worker_memory = '56G' @@ -149,6 +150,9 @@ def test_get_nested_nodes_info(): viya_min_aggregate_worker_CPU_cores, viya_min_aggregate_worker_memory) + # Unsupported version + vpc.set_k8s_version("1.16.1") + current_dir = os.path.dirname(os.path.abspath(__file__)) datafile = os.path.join(current_dir, 'test_data/json_data/nodes_info.json') # Register Python Package Pint definitions @@ -176,7 +180,8 @@ def test_get_nested_nodes_info(): total_aggregate_memoryG = vpc.get_calculated_aggregate_memory() # quantity_("62.3276481628418 Gi").to('G') assert str(round(total_aggregate_memoryG.to("G"), 2)) == '67.13 G' assert str(round(total_aggregate_memoryG.to("Gi"), 2)) == '62.52 Gi' - assert global_data[4]['aggregate_kubelet_failures'] in 'Check Kubelet Version on nodes. Issues Found: 1.' + assert global_data[4]['aggregate_kubelet_failures'] in 'Check Kubelet Version on nodes. Issues Found: 3.' + assert global_data[6]['k8sVersion'] in '1.16.1' template_render(global_data, configs_data, storage_data, 'nested_nodes_info.html') @@ -188,6 +193,8 @@ def test_get_nested_millicores_nodes_info(): vpc = createViyaPreInstallCheck(viya_kubelet_version_min, viya_min_aggregate_worker_CPU_cores, viya_min_aggregate_worker_memory) + + vpc.set_k8s_version("1.13.1") # Register Python Package Pint definitions quantity_ = register_pint() @@ -214,7 +221,8 @@ def test_get_nested_millicores_nodes_info(): ' Issues Found: 1' total_calc_memoryG = vpc.get_calculated_aggregate_memory() assert str(round(total_calc_memoryG.to("G"), 2)) == '68.16 G' # 68.16113098752 - assert global_data[4]['aggregate_kubelet_failures'] in 'Check Kubelet Version on nodes. Issues Found: 2.' + assert global_data[4]['aggregate_kubelet_failures'] in 'Check Kubelet Version on nodes. Issues Found: 3.' + assert global_data[6]['k8sVersion'] in '1.13.1' template_render(global_data, configs_data, storage_data, 'nested_millicores_nodes_info.html') @@ -501,10 +509,9 @@ def test_azure_worker_nodes(): assert global_data[3]['aggregate_memory_failures'] in 'Expected: 56G, Calculated: 802.28 G,' \ ' Memory within Range,' \ ' Issues Found: 0' - assert global_data[4]['aggregate_kubelet_failures'] in 'Check Kubelet Version on nodes. Issues Found: 10. ' \ - 'Check Node(s). All Nodes NOT in Ready Status. ' \ + assert global_data[4]['aggregate_kubelet_failures'] in ' Check Node(s). All Nodes NOT in Ready Status. ' \ 'Issues Found: ' + str(issues_found) - + assert global_data[6]['k8sVersion'] in '1.22.4' template_render(global_data, configs_data, storage_data, 'azure_nodes_no_master.html') @@ -540,6 +547,7 @@ def createViyaPreInstallCheck(viya_kubelet_version_min, viya_kubelet_version_min, viya_min_aggregate_worker_CPU_cores, viya_min_aggregate_worker_memory) + sas_pre_check_report.set_k8s_version(viya_kubenetes_version) return sas_pre_check_report @@ -582,6 +590,49 @@ def test_kubconfig_file(): os.environ['KUBECONFIG'] = str(old_kubeconfig) +def test_validated_k8s_server_version(): + + vpc = createViyaPreInstallCheck(viya_kubelet_version_min, + viya_min_aggregate_worker_CPU_cores, + viya_min_aggregate_worker_memory) + + rc = vpc._validate_k8s_server_version("1.21.6-gke.1500") + assert(rc == 0) + + try: + rc = vpc._validate_k8s_server_version("") + except SystemExit as exc: + assert exc.code == viya_messages.INVALID_K8S_VERSION_RC_ + + try: + vpc._validate_k8s_server_version("0.2.5") + except SystemExit as exc: + assert exc.code == viya_messages.INVALID_K8S_VERSION_RC_ + + try: + vpc._validate_k8s_server_version("025") + except SystemExit as exc: + assert exc.code == viya_messages.INVALID_K8S_VERSION_RC_ + + try: + vpc._validate_k8s_server_version("1.2.3.5") + except SystemExit as exc: + assert exc.code == viya_messages.INVALID_K8S_VERSION_RC_ + + try: + vpc._validate_k8s_server_version("") + except SystemExit as exc: + assert exc.code == viya_messages.INVALID_K8S_VERSION_RC_ + + rc = vpc._validate_k8s_server_version("1.21.5") + assert (rc == 0) + + try: + vpc._validate_k8s_server_version("1.-21.5") + except SystemExit as exc: + assert exc.code == viya_messages.INVALID_K8S_VERSION_RC_ + + def test_get_k8s_version(): """ Retrieve thhe server Kubernetes mjor and minor version using @@ -591,8 +642,6 @@ def test_get_k8s_version(): # versions: Dict = self.utils.get_k8s_version() version_string = "1.18.9-eks-d1db3c" version_string2 = "1.19.0" - version_string3 = '1.19.a' - version_string4 = '1.17.1' params = {} params[viya_constants.INGRESS_CONTROLLER] = 'nginx' @@ -603,40 +652,15 @@ def test_get_k8s_version(): # initialize the PreCheckPermissions object perms = PreCheckPermissions(params) perms.set_k8s_git_version(version_string) - perms.set_ingress_manifest_file() - # check for correct ingress manifest - assert(str(perms.get_ingress_file_name() in "hello-ingress-k8s-v118.yaml")) - - # initialize the PreCheckPermissions object - perms = PreCheckPermissions(params) - perms.set_k8s_git_version(version_string4) - perms.set_ingress_manifest_file() - # check for correct ingress manifest - assert(str(perms.get_ingress_file_name() in "hello-ingress-k8s-v118.yaml")) - - perms.set_k8s_git_version(version_string2) - perms.set_ingress_manifest_file() - # check for correct ingress manifest - assert(str(perms.get_ingress_file_name() in "hello-ingress.yaml")) # check curren version less than 1.20 curr_version = semantic_version.Version(str(version_string2)) assert (curr_version in semantic_version.SimpleSpec('<1.20')) assert (curr_version in semantic_version.SimpleSpec('==1.19')) - perms.set_k8s_git_version(version_string2) - perms.set_ingress_manifest_file() - # check for correct ingress manifest - assert(str(perms.get_ingress_file_name() not in "hello-ingress_invalid.yaml")) - - # initialize the PreCheckPermissions object - perms.set_k8s_git_version(version_string3) - # check for system exit rc 7 - try: - perms.set_ingress_manifest_file() - except SystemExit as exc: - assert exc.code == viya_messages.RUNTIME_ERROR_RC_ - pass + # current version is less then 1.19 + curr_version = semantic_version.Version(str(version_string)) + assert (curr_version in semantic_version.SimpleSpec(viya_constants.MIN_K8S_SERVER_VERSION)) def test_check_permissions():