From 99b0134f78431429ad48e119ed14800916fe5a45 Mon Sep 17 00:00:00 2001 From: Lukasz Rajewski Date: Mon, 12 Feb 2024 17:34:50 +0100 Subject: Enhanced SDNC status check and SDNC distribution check Enhanced SDNC status check and SDNC distribution check Issue-ID: TEST-404 Signed-off-by: Lukasz Rajewski Change-Id: I4ed88c73251c5569bc6bc0ea9a4a4737ca903d93 --- src/onaptests/steps/instantiate/sdnc_service.py | 17 +++++++-- src/onaptests/steps/onboard/service.py | 50 +++++++++++++++++++++++++ src/onaptests/utils/kubernetes.py | 50 +++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/onaptests/utils/kubernetes.py (limited to 'src/onaptests') diff --git a/src/onaptests/steps/instantiate/sdnc_service.py b/src/onaptests/steps/instantiate/sdnc_service.py index 6d88c64..9dce7e9 100644 --- a/src/onaptests/steps/instantiate/sdnc_service.py +++ b/src/onaptests/steps/instantiate/sdnc_service.py @@ -42,7 +42,8 @@ class BaseSdncStep(BaseStep): class CheckSdncDbStep(BaseSdncStep): """Check MariaDB connection status.""" - SDNC_QUERY = "SELECT * FROM svc_logic LIMIT 1;" + SDNC_QUERY_LOGIC = "SELECT * FROM svc_logic LIMIT 1;" + SDNC_QUERY_MODEL = "SELECT * FROM service_model LIMIT 1;" SDNC_DATABASE = "sdnctl" SDNC_DB_LOGIN = "login" SDNC_DB_PASSWORD = "password" @@ -85,6 +86,13 @@ class CheckSdncDbStep(BaseSdncStep): self.password = None raise EnvironmentPreparationException("Error accessing secret") from e + def _check_query(self, conn, query): + cursor = conn.cursor() + cursor.execute(query) + for _ in cursor: + pass + cursor.close() + @BaseStep.store_state def execute(self) -> None: """Check MariaDB connection.""" @@ -98,8 +106,11 @@ class CheckSdncDbStep(BaseSdncStep): port=settings.SDNC_DB_PORT, user=self.login, password=self.password) - cursor = conn.cursor() - cursor.execute(self.SDNC_QUERY) + self._check_query(conn, self.SDNC_QUERY_LOGIC) + self._check_query(conn, self.SDNC_QUERY_MODEL) + except (mysql.errors.ProgrammingError, + mysql.errors.DatabaseError) as e: + raise OnapTestException(e) from e except Exception as e: raise OnapTestException("Cannot connect to SDNC Database") from e finally: diff --git a/src/onaptests/steps/onboard/service.py b/src/onaptests/steps/onboard/service.py index d8a627e..77456ff 100644 --- a/src/onaptests/steps/onboard/service.py +++ b/src/onaptests/steps/onboard/service.py @@ -2,6 +2,7 @@ import time from typing import Any, Dict, Iterator from urllib.parse import urlencode +import mysql.connector as mysql from onapsdk.aai.service_design_and_creation import Model from onapsdk.configuration import settings from onapsdk.exceptions import InvalidResponse, ResourceNotFound @@ -17,6 +18,7 @@ from yaml import SafeLoader, load import onaptests.utils.exceptions as onap_test_exceptions from onaptests.scenario.scenario_base import BaseScenarioStep +from onaptests.utils.kubernetes import KubernetesHelper from ..base import BaseStep, YamlTemplateBaseStep from .pnf import YamlTemplatePnfOnboardStep @@ -203,6 +205,7 @@ class VerifyServiceDistributionStep(BaseScenarioStep): notified_module=notified_module)) self.add_step(VerifyServiceDistributionInSoStep()) self.add_step(VerifyServiceDistributionInAaiStep()) + self.add_step(VerifyServiceDistributionInSdncStep()) @property def description(self) -> str: @@ -392,3 +395,50 @@ class VerifyServiceDistributionInAaiStep(BaseServiceDistributionComponentCheckSt msg = f"Service {self.service.name} is missing in AAI." self._logger.error(msg) raise onap_test_exceptions.ServiceDistributionException(msg) from e + + +class VerifyServiceDistributionInSdncStep(BaseServiceDistributionComponentCheckStep): + """Check service distribution in SDNC step.""" + + SDNC_DATABASE = "sdnctl" + SDNC_DB_LOGIN = "login" + SDNC_DB_PASSWORD = "password" + + def __init__(self): + """Initialize step.""" + BaseServiceDistributionComponentCheckStep.__init__( + self, component_name="SDNC") + + @BaseStep.store_state + def execute(self): + """Check service distribution status.""" + super().execute() + login, password = KubernetesHelper.get_credentials_from_secret( + settings.SDNC_SECRET_NAME, self.SDNC_DB_LOGIN, self.SDNC_DB_PASSWORD) + conn = None + try: + conn = mysql.connect( + database=self.SDNC_DATABASE, + host=settings.SDNC_DB_PRIMARY_HOST, + port=settings.SDNC_DB_PORT, + user=login, + password=password) + cursor = conn.cursor() + cursor.execute( + f"SELECT * FROM service_model WHERE service_uuid = '{self.service.uuid}'") + for _ in cursor: + pass + if cursor.rowcount == 0: + msg = f"Service {self.service.name} is missing in SDNC." + self._logger.error(msg) + raise onap_test_exceptions.ServiceDistributionException(msg) + cursor.close() + except Exception as e: + msg = f"Service {self.service.name} is missing in SDNC." + raise onap_test_exceptions.ServiceDistributionException(msg) from e + finally: + if conn: + try: + conn.close() + except Exception: + pass diff --git a/src/onaptests/utils/kubernetes.py b/src/onaptests/utils/kubernetes.py new file mode 100644 index 0000000..05728ca --- /dev/null +++ b/src/onaptests/utils/kubernetes.py @@ -0,0 +1,50 @@ +import base64 + +from kubernetes import client, config +from onapsdk.configuration import settings + +from onaptests.utils.exceptions import EnvironmentPreparationException + + +class KubernetesHelper: + """Helper class to perform operations on kubernetes cluster""" + + @classmethod + def load_config(cls): + """Load kubernetes client configuration""" + if settings.IN_CLUSTER: + config.load_incluster_config() + else: + config.load_kube_config(config_file=settings.K8S_CONFIG) + + @classmethod + def get_credentials_from_secret(cls, + secret_name: str, + login_key: str, + password_key: str, + namespace: str = settings.K8S_ONAP_NAMESPACE): + """Resolve SDNC datbase credentials from k8s secret. + + Args: + secret_name (str): name of the secret to load + login_key (str): key of the login in secret + password_key (str): key of the password in secret + namespace (str): k8s namespace to load key from + """ + + cls.load_config() + api_instance = client.CoreV1Api() + try: + secret = api_instance.read_namespaced_secret(secret_name, namespace) + if secret.data: + if (login_key in secret.data and password_key in secret.data): + login_base64 = secret.data[login_key] + login = base64.b64decode(login_base64).decode("utf-8") + password_base64 = secret.data[password_key] + password = base64.b64decode(password_base64).decode("utf-8") + return login, password + raise EnvironmentPreparationException( + "Login key or password key not found in secret") + raise EnvironmentPreparationException("Secret data not found in secret") + except client.rest.ApiException as e: + raise EnvironmentPreparationException("Error accessing secret") from e -- cgit 1.2.3-korg