diff options
-rw-r--r-- | ansible/site.yml | 1 | ||||
-rw-r--r-- | docker/cnf/Dockerfile | 15 | ||||
-rw-r--r-- | docker/cnf/testcases.yaml | 13 | ||||
-rw-r--r-- | functest_kubernetes/cnf_conformance/__init__.py | 0 | ||||
-rw-r--r-- | functest_kubernetes/cnf_conformance/conformance.py | 104 | ||||
-rw-r--r-- | setup.cfg | 1 |
6 files changed, 134 insertions, 0 deletions
diff --git a/ansible/site.yml b/ansible/site.yml index 78b1c36a..5c6498b5 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -58,4 +58,5 @@ - xrally_kubernetes_full - container: functest-kubernetes-cnf tests: + - cnf_conformance - k8s_vims diff --git a/docker/cnf/Dockerfile b/docker/cnf/Dockerfile index 868a2c13..46c97c5b 100644 --- a/docker/cnf/Dockerfile +++ b/docker/cnf/Dockerfile @@ -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"] diff --git a/docker/cnf/testcases.yaml b/docker/cnf/testcases.yaml index 68d1788d..e0d8bcb2 100644 --- a/docker/cnf/testcases.yaml +++ b/docker/cnf/testcases.yaml @@ -7,6 +7,19 @@ tiers: 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 criteria: 100 diff --git a/functest_kubernetes/cnf_conformance/__init__.py b/functest_kubernetes/cnf_conformance/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/functest_kubernetes/cnf_conformance/__init__.py diff --git a/functest_kubernetes/cnf_conformance/conformance.py b/functest_kubernetes/cnf_conformance/conformance.py new file mode 100644 index 00000000..1f80f15c --- /dev/null +++ b/functest_kubernetes/cnf_conformance/conformance.py @@ -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) @@ -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 |