Update to Alpine 3.14
[functest-kubernetes.git] / functest_kubernetes / ims / ims.py
index 95aa1c6..18e8c0d 100644 (file)
 
 from __future__ import division
 
+import abc
 import logging
-import time
+import os
 import re
+import subprocess
+import time
 import yaml
 
+from jinja2 import Template
 from kubernetes import client
 from kubernetes import config
 from kubernetes import watch
 import pkg_resources
-
 from xtesting.core import testcase
 
 
@@ -32,10 +35,13 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
 
     See https://github.com/Metaswitch/clearwater-docker for more details
     """
-    watch_timeout = 1200
+    watch_timeout = 1800
     metadata_name = "env-vars"
     test_image_name = "ollivier/clearwater-live-test:hunter"
     test_container_name = "live-test"
+    ns_generate_name = "ims-"
+    dockerhub_repo = os.getenv("MIRROR_REPO", "docker.io")
+    quay_repo = os.getenv("MIRROR_REPO", "quay.io")
 
     __logger = logging.getLogger(__name__)
 
@@ -44,7 +50,7 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
         "homestead", "homestead-prov", "ralf", "sprout"]
 
     def __init__(self, **kwargs):
-        super(Vims, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         config.load_kube_config()
         self.corev1 = client.CoreV1Api()
         self.appsv1 = client.AppsV1Api()
@@ -53,48 +59,40 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
         self.namespace = ""
         self.zone = ""
 
-    def deploy_vnf(self):
-        """Deploy vIMS as proposed by clearwater-docker
+    def prepare_vnf(self):
+        """Prepare vIMS as proposed by clearwater-live-test
 
-        It leverages on unofficial Clearwater dockers as proposed in the
-        documentation.
+        It creates a dedicated namespace and the configmap needed.
 
-        See https://github.com/Metaswitch/clearwater-docker for more details
+        See https://github.com/Metaswitch/clearwater-live-test for more details
         """
         api_response = self.corev1.create_namespace(
             client.V1Namespace(metadata=client.V1ObjectMeta(
-                generate_name="ims-")))
+                generate_name=self.ns_generate_name)))
         self.namespace = api_response.metadata.name
         self.__logger.debug("create_namespace: %s", api_response)
+        self.zone = '{}.svc.cluster.local'.format(self.namespace)
         metadata = client.V1ObjectMeta(
             name=self.metadata_name, namespace=self.namespace)
-        self.zone = '{}.svc.cluster.local'.format(self.namespace)
         body = client.V1ConfigMap(
             metadata=metadata,
             data={"ADDITIONAL_SHARED_CONFIG": "", "ZONE": self.zone})
         api_response = self.corev1.create_namespaced_config_map(
             self.namespace, body=body)
         self.__logger.debug("create_namespaced_config_map: %s", api_response)
-        for deployment in self.deployment_list:
-            with open(pkg_resources.resource_filename(
-                    'functest_kubernetes',
-                    'ims/{}-depl.yaml'.format(deployment))) as yfile:
-                body = yaml.safe_load(yfile)
-                resp = self.appsv1.create_namespaced_deployment(
-                    body=body, namespace=self.namespace)
-                self.__logger.info("Deployment %s created", resp.metadata.name)
-                self.__logger.debug(
-                    "create_namespaced_deployment: %s", api_response)
-        for service in self.deployment_list:
-            with open(pkg_resources.resource_filename(
-                    'functest_kubernetes',
-                    'ims/{}-svc.yaml'.format(service))) as yfile:
-                body = yaml.safe_load(yfile)
-                resp = self.corev1.create_namespaced_service(
-                    body=body, namespace=self.namespace)
-                self.__logger.info("Service %s created", resp.metadata.name)
-                self.__logger.debug(
-                    "create_namespaced_service: %s", api_response)
+
+    @abc.abstractmethod
+    def deploy_vnf(self):
+        """Deploy vIMS as proposed by clearwater-docker
+
+        It must be overriden on purpose.
+
+        See https://github.com/Metaswitch/clearwater-docker for more details
+        """
+
+    def wait_vnf(self):
+        """Wait vIMS is up and running"""
+        assert self.namespace
         status = self.deployment_list.copy()
         watch_deployment = watch.Watch()
         for event in watch_deployment.stream(
@@ -119,12 +117,14 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
     def test_vnf(self):
         """Test vIMS as proposed by clearwater-live-test
 
-        It leverages on an unofficial Clearwater docker to allow testing from
+        It leverages an unofficial Clearwater docker to allow testing from
         the Kubernetes cluster.
 
         See https://github.com/Metaswitch/clearwater-live-test for more details
         """
         time.sleep(120)
+        assert self.namespace
+        assert self.zone
         container = client.V1Container(
             name=self.test_container_name, image=self.test_image_name,
             command=["rake", "test[{}]".format(self.zone),
@@ -171,13 +171,21 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
     def run(self, **kwargs):
         self.start_time = time.time()
         try:
-            if self.deploy_vnf():
+            self.prepare_vnf()
+            self.deploy_vnf()
+            if self.wait_vnf():
                 self.test_vnf()
         except client.rest.ApiException:
             self.__logger.exception("Cannot deploy and test vIms")
         self.stop_time = time.time()
 
     def clean(self):
+        try:
+            api_response = self.corev1.delete_namespaced_pod(
+                name=self.test_container_name, namespace=self.namespace)
+            self.__logger.debug("delete_namespaced_pod: %s", api_response)
+        except client.rest.ApiException:
+            pass
         try:
             api_response = self.corev1.delete_namespaced_config_map(
                 name=self.metadata_name, namespace=self.namespace)
@@ -186,11 +194,56 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
         except client.rest.ApiException:
             pass
         try:
-            api_response = self.corev1.delete_namespaced_pod(
-                name=self.test_container_name, namespace=self.namespace)
-            self.__logger.debug("delete_namespaced_pod: %s", api_response)
+            api_response = self.corev1.delete_namespace(self.namespace)
+            self.__logger.debug("delete_namespace: %s", self.namespace)
         except client.rest.ApiException:
             pass
+
+
+class K8sVims(Vims):
+    """Deploy vIMS via kubectl as proposed by clearwater-docker
+
+    It leverages unofficial Clearwater dockers as proposed in the
+    documentation.
+
+    See https://github.com/Metaswitch/clearwater-docker for more details
+    """
+
+    __logger = logging.getLogger(__name__)
+
+    def deploy_vnf(self):
+        """Deploy vIMS via kubectl as proposed by clearwater-docker
+
+        See https://github.com/Metaswitch/clearwater-docker for more details
+        """
+        assert self.namespace
+        for deployment in self.deployment_list:
+            with open(pkg_resources.resource_filename(
+                    'functest_kubernetes',
+                    'ims/{}-depl.yaml'.format(deployment))) as yfile:
+                template = Template(yfile.read())
+                body = yaml.safe_load(template.render(
+                    dockerhub_repo=os.getenv(
+                        "DOCKERHUB_REPO", self.dockerhub_repo),
+                    quay_repo=os.getenv(
+                        "QUAY_REPO", self.quay_repo)))
+                resp = self.appsv1.create_namespaced_deployment(
+                    body=body, namespace=self.namespace)
+                self.__logger.info("Deployment %s created", resp.metadata.name)
+                self.__logger.debug(
+                    "create_namespaced_deployment: %s", resp)
+        for service in self.deployment_list:
+            with open(pkg_resources.resource_filename(
+                    'functest_kubernetes',
+                    'ims/{}-svc.yaml'.format(service))) as yfile:
+                body = yaml.safe_load(yfile)
+                resp = self.corev1.create_namespaced_service(
+                    body=body, namespace=self.namespace)
+                self.__logger.info("Service %s created", resp.metadata.name)
+                self.__logger.debug(
+                    "create_namespaced_service: %s", resp)
+
+    def clean(self):
         for deployment in self.deployment_list:
             try:
                 api_response = self.appsv1.delete_namespaced_deployment(
@@ -206,8 +259,37 @@ class Vims(testcase.TestCase):  # pylint: disable=too-many-instance-attributes
                     "delete_namespaced_service: %s", api_response)
             except client.rest.ApiException:
                 pass
-        try:
-            api_response = self.corev1.delete_namespace(self.namespace)
-            self.__logger.debug("delete_namespace: %s", self.namespace)
-        except client.rest.ApiException:
-            pass
+        super().clean()
+
+
+class HelmVims(Vims):
+    """Deploy vIMS via Helm as proposed by clearwater-docker
+
+    It leverages unofficial Clearwater dockers as proposed in the
+    documentation.
+
+    See https://github.com/Metaswitch/clearwater-docker for more details
+    """
+
+    __logger = logging.getLogger(__name__)
+
+    def deploy_vnf(self):
+        """Deploy vIMS via Helm as proposed by clearwater-docker
+
+        See https://github.com/Metaswitch/clearwater-docker for more details
+        """
+        dockerhub_repo = os.getenv("DOCKERHUB_REPO", self.dockerhub_repo)
+        quay_repo = os.getenv("QUAY_REPO", self.quay_repo)
+        cmd = [
+            "helm", "install", "clearwater", "--set",
+            "repo.dockerHub={},repo.quay={}".format(dockerhub_repo, quay_repo),
+            pkg_resources.resource_filename("functest_kubernetes", "ims/helm"),
+            "-n", self.namespace]
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        self.__logger.debug(output.decode("utf-8"))
+
+    def clean(self):
+        cmd = ["helm", "uninstall", "clearwater", "-n", self.namespace]
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        self.__logger.debug(output.decode("utf-8"))
+        super().clean()