Add cnf-conformance in functest-kubernetes-cnf 25/70925/1
authorCédric Ollivier <cedric.ollivier@orange.com>
Wed, 2 Sep 2020 17:46:25 +0000 (19:46 +0200)
committerCédric Ollivier <cedric.ollivier@orange.com>
Fri, 4 Sep 2020 20:47:41 +0000 (22:47 +0200)
It selects cnf-conformance v0.7.2-beta1 (current latest release) and
the default CNF as proposed by [1].

The end user is free to override the default yml files on purpose (e.g.
docker volumes). Tag (default: all) could be modified too via
testcases.yaml

[1] https://hackmd.io/@vulk/SkY54QnsU

Change-Id: Iec2a830c441e523e067f6eb114ecb205c49c6b93
Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com>
(cherry picked from commit 120daffd8d6d4be727d2ba52a76dbd8eacfe2628)

ansible/site.yml
docker/cnf/Dockerfile
docker/cnf/testcases.yaml
functest_kubernetes/cnf_conformance/__init__.py [new file with mode: 0644]
functest_kubernetes/cnf_conformance/conformance.py [new file with mode: 0644]
setup.cfg

index 78b1c36..5c6498b 100644 (file)
@@ -58,4 +58,5 @@
             - xrally_kubernetes_full
         - container: functest-kubernetes-cnf
           tests:
+            - cnf_conformance
             - k8s_vims
index 868a2c1..46c97c5 100644 (file)
@@ -1,4 +1,19 @@
 FROM opnfv/functest-kubernetes-core:hunter
 
+ARG CNF_CONFORMANCE_TAG=v0.7.2-beta1
+
+RUN apk --no-cache add --update wget curl libc6-compat && \
+    K8S_TAG=$(curl -s https://storage.googleapis.com/kubernetes-release/release/latest-1.19.txt)  && \
+    case $(uname -m) in armv7l) ARCH=arm;; aarch64) ARCH=arm64;; x86_64) ARCH=amd64;; esac && \
+    curl https://storage.googleapis.com/kubernetes-release/release/$K8S_TAG/bin/linux/$ARCH/kubectl \
+        -s --output /usr/local/bin/kubectl && \
+    curl https://github.com/cncf/cnf-conformance/releases/download/$CNF_CONFORMANCE_TAG/cnf-conformance-$(echo $CNF_CONFORMANCE_TAG |cut -d\- -f 1)-$ARCH-static \
+        -Ls --output /usr/local/bin/cnf-conformance && \
+    chmod +x /usr/local/bin/kubectl /usr/local/bin/cnf-conformance && \
+    mkdir -p /src/cnf-conformance && \
+    curl -Ls https://raw.githubusercontent.com/cncf/cnf-conformance/$CNF_CONFORMANCE_TAG/example-cnfs/coredns/cnf-conformance.yml \
+        -s --output /src/cnf-conformance/cnf-conformance.yml && \
+    curl -Ls https://raw.githubusercontent.com/cncf/cnf-conformance/$CNF_CONFORMANCE_TAG/points.yml \
+        -s --output /src/cnf-conformance/points.yml
 COPY testcases.yaml /usr/lib/python2.7/site-packages/xtesting/ci/testcases.yaml
 CMD ["run_tests", "-t", "all"]
index 68d1788..e0d8bcb 100644 (file)
@@ -6,6 +6,19 @@ tiers:
         description: >-
             Collection of VNF test cases.
         testcases:
+            -
+                case_name: cnf_conformance
+                project_name: functest
+                criteria: 90
+                blocking: false
+                description: >-
+                    Enable interoperability of Cloud native Network
+                    Functions (CNFs) as proposed by
+                    https://github.com/cncf/cnf-conformance
+                dependencies:
+                    - DEPLOY_SCENARIO: 'k8-*'
+                run:
+                    name: cnf_conformance
             -
                 case_name: k8s_vims
                 project_name: functest
diff --git a/functest_kubernetes/cnf_conformance/__init__.py b/functest_kubernetes/cnf_conformance/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/functest_kubernetes/cnf_conformance/conformance.py b/functest_kubernetes/cnf_conformance/conformance.py
new file mode 100644 (file)
index 0000000..1f80f15
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2020 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""
+The CNF Conformance program enables interoperability of Cloud native Network
+Functions (CNFs) from multiple vendors running on top of Kubernetes supplied by
+different vendors [1].
+[1] https://github.com/cncf/cnf-conformance
+"""
+
+from __future__ import division
+
+import fnmatch
+import logging
+import os
+import re
+import shutil
+import subprocess
+import time
+import yaml
+
+import prettytable
+
+from xtesting.core import testcase
+
+
+class CNFConformance(testcase.TestCase):
+    """ Implement CNF Conformance driver.
+
+    https://hackmd.io/@vulk/SkY54QnsU
+    """
+
+    src_dir = '/src/cnf-conformance'
+    bin_dir = '/usr/local/bin'
+    default_tag = 'all'
+
+    __logger = logging.getLogger(__name__)
+
+    def setup(self):
+        """Implement initialization and pre-reqs steps"""
+        os.makedirs(self.res_dir, exist_ok=True)
+
+        shutil.copy2(os.path.join(self.src_dir, 'points.yml'), self.res_dir)
+        shutil.copy2(
+            os.path.join(self.src_dir, 'cnf-conformance.yml'), self.res_dir)
+        os.chdir(self.res_dir)
+        # cnf-conformance must be in the working dir
+        # https://github.com/cncf/cnf-conformance/issues/388
+        if not os.path.exists(os.path.join(self.res_dir, 'cnf-conformance')):
+            os.symlink(
+                os.path.join(self.bin_dir, 'cnf-conformance'),
+                os.path.join(self.res_dir, 'cnf-conformance'))
+        cmd = ['cnf-conformance', 'setup']
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+        cmd = ['cnf-conformance', 'cnf_setup',
+               'cnf-config=cnf-conformance.yml']
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+
+    def run_conformance(self, **kwargs):
+        """Run CNF Conformance"""
+        # a previous results.yml leads to interactive mode
+        if os.path.exists(os.path.join(self.res_dir, 'results.yml')):
+            os.remove(os.path.join(self.res_dir, 'results.yml'))
+        cmd = ['cnf-conformance', kwargs.get("tag", self.default_tag)]
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+        for lfile in os.listdir(self.res_dir):
+            if fnmatch.fnmatch(lfile, 'cnf-conformance-results-*.yml'):
+                with open(os.path.join(self.res_dir, lfile)) as yfile:
+                    self.details = yaml.safe_load(yfile)
+                    msg = prettytable.PrettyTable(
+                        header_style='upper', padding_width=5,
+                        field_names=['name', 'status'])
+                    for item in self.details['items']:
+                        msg.add_row([item['name'], item['status']])
+                    self.__logger.info("\n\n%s\n", msg.get_string())
+        grp = re.search(r'Final score: (\d+) of (\d+)', output.decode("utf-8"))
+        if grp:
+            self.result = int(grp.group(1)) / int(grp.group(2)) * 100
+
+    def run(self, **kwargs):
+        """"Running the test with example CNF"""
+        self.start_time = time.time()
+        try:
+            self.setup()
+            self.run_conformance(**kwargs)
+        except Exception:  # pylint: disable=broad-except
+            self.__logger.exception("Can not run CNF Conformance")
+        self.stop_time = time.time()
+
+    def clean(self):
+        cmd = ['cnf-conformance', 'cnf_cleanup',
+               'cnf-config=cnf-conformance.yml']
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+        shutil.rmtree(self.res_dir)
index e9b73f9..54a528b 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -13,3 +13,4 @@ xtesting.testcase =
     k8s_vims = functest_kubernetes.ims.ims:Vims
     kube_hunter = functest_kubernetes.security.security:KubeHunter
     kube_bench = functest_kubernetes.security.security:KubeBench
+    cnf_conformance = functest_kubernetes.cnf_conformance.conformance:CNFConformance