diff options
author | mrichomme <morgan.richomme@orange.com> | 2019-12-10 08:47:28 +0100 |
---|---|---|
committer | mrichomme <morgan.richomme@orange.com> | 2019-12-11 12:00:31 +0100 |
commit | 1f997a66f658ff11809f44f4630fc678eb091b83 (patch) | |
tree | d29e08adfc2a5d193310d9dfc640175b0cf76fc6 /infra-healthcheck | |
parent | 78b4cdd2c5aa084ee6b8cc0f768187be907ae68c (diff) |
Move integration xtesting Dockerfile to ONAP
All the Dockerfiles and xtesting configurations were hosted in gitlab.com [1]
The goal of this patch is to host these assets in ONAP
A jenkins jjb shall be created to generated the docker and push them on the nexus
(today the built-in registry of ONAP was used)
These xtesting dockers are referencing integration categories [2] and integration
use cases [3]
These xtesting dockers shall also simplify the way to integrate new use cases in any
CI chain (jenkins or gitlab-ci based)
[1]: https://gitlab.com/Orange-OpenSource/lfn/onap/integration/xtesting
[2]: https://wiki.onap.org/pages/viewpage.action?pageId=71835330
[3]: http://testresults.opnfv.org/onap/api/v1/projects/integration/cases
Issue-ID: INT-1366
Signed-off-by: mrichomme <morgan.richomme@orange.com>
Change-Id: Iba0fc0b0415731a7a81ba0225a70ae16391dd129
Signed-off-by: mrichomme <morgan.richomme@orange.com>
Diffstat (limited to 'infra-healthcheck')
-rw-r--r-- | infra-healthcheck/README.md | 79 | ||||
-rw-r--r-- | infra-healthcheck/docker/Dockerfile | 31 | ||||
-rw-r--r-- | infra-healthcheck/docker/testcases.yaml | 29 | ||||
-rw-r--r-- | infra-healthcheck/infra_healthcheck/__init__.py | 0 | ||||
-rw-r--r-- | infra-healthcheck/infra_healthcheck/k8stest.py | 121 | ||||
-rw-r--r-- | infra-healthcheck/infra_healthcheck/test_k8stest.py | 41 | ||||
-rw-r--r-- | infra-healthcheck/requirements.txt | 11 | ||||
-rw-r--r-- | infra-healthcheck/scripts/check_onap_helm.sh | 36 | ||||
-rw-r--r-- | infra-healthcheck/scripts/check_onap_k8s.sh | 108 | ||||
-rw-r--r-- | infra-healthcheck/setup.cfg | 11 | ||||
-rw-r--r-- | infra-healthcheck/setup.py | 29 | ||||
-rw-r--r-- | infra-healthcheck/tox.ini | 49 |
12 files changed, 545 insertions, 0 deletions
diff --git a/infra-healthcheck/README.md b/infra-healthcheck/README.md new file mode 100644 index 0000000..ba873af --- /dev/null +++ b/infra-healthcheck/README.md @@ -0,0 +1,79 @@ +# infra-healthcheck + +## Goal + +This infra-healthcheck docker includes the test suites checking kubernetes and +healm charts of an ONAP deployment. + +It includes 2 tests: + +* onap-k8s: list pods, deployments, events, cm, ... For any faulty pod, it + collects the logs and the describe. The success criteria is 100% of the pods + are up&running +* onap-helm: list the helm charts. The success criteria is all the helm charts + are completed. + +## Usage + +### Configuration + +Mandatory: + +* The kubernetes configuration: usually hosted on the.kube/config of your + jumphost. It corresponds the kubernetes credentials and are needed to perform + the different operations. This file shall be copied in /config/.kube/config in + the docker. + +Optional: + +* The local result directory path: to store the results in your local + environement. It shall corresponds to the internal result docker path + /var/lib/xtesting/results + +### Command + +You can run this docker by typing: + +``` +docker run -v <the kube config>:/config/.kube/config -v +<result directory>:/var/lib/xtesting/results +registry.gitlab.com/orange-opensource/lfn/onap/integration/xtesting:latest +``` + +Options: + +* -r: by default the reporting to the Database is not enabled. You need to + specify the -r option in the command line. Please note that in this case, you + must precise some env variables. + +environement variables: + +* Mandatory: + * TEST_DB_URL: the url of the target Database with the env variable . + * NODE_NAME: the name of your test environement. It must be declared in the + test database (e.g. windriver-SB00) +* Optionnal + * INSTALLER_TYPE: precise how your ONAP has been installed (e.g. kubespray-oom, + rke-oom) + * BUILD_TAG: a unique tag of your CI system. It can be usefull to get all the + tests of one CI run. It uses the regex (dai|week)ly-(.+?)-[0-9]* to find the + version (e.g. daily-elalto-123456789). + +The command becomes: + +``` +docker run -v <the kube config>:/config/.kube/config -v +<result directory>:/var/lib/xtesting/results registry.gitlab.com/orange-opensour +ce/lfn/onap/integration/xtesting:latest /bin/bash -c "run_tests -r -t all +``` + +### Output + +``` ++------------+-------------+-------------------+----------+--------+ +| TEST CASE | PROJECT | TIER | DURATION | RESULT | ++------------+-------------+-------------------+----------+--------+ +| onap-k8s | integration | infra-healthcheck | 00:06 | PASS | +| onap-helm | integration | infra-healthcheck | 00:01 | PASS | ++------------+-------------+-------------------+----------+--------+ +``` diff --git a/infra-healthcheck/docker/Dockerfile b/infra-healthcheck/docker/Dockerfile new file mode 100644 index 0000000..de19a2a --- /dev/null +++ b/infra-healthcheck/docker/Dockerfile @@ -0,0 +1,31 @@ +FROM opnfv/xtesting + +ARG KUBERNETES_VERSION="v1.15.2" +ARG HELM_VERSION="v2.14.1" +ARG ONAP_TESTS_TAG=master + +# Install kubectl +# Note: Latest version may be found on: +# https://aur.archlinux.org/packages/kubectl-bin/ + +ADD https://storage.googleapis.com/kubernetes-release/release/${KUBERNETES_VERSION}/bin/linux/amd64/kubectl /usr/local/bin/kubectl + +COPY scripts/check_onap_k8s.sh /check_onap_k8s.sh +COPY scripts/check_onap_helm.sh /check_onap_helm.sh + +RUN set -x && \ + apk --no-cache add --update curl ca-certificates && \ + apk --no-cache add --virtual .build-deps --update \ + gcc python3-dev musl-dev && \ + chmod +x /usr/local/bin/kubectl && \ + adduser kubectl -Du 2342 -h /config && \ + wget https://storage.googleapis.com/kubernetes-helm/helm-${HELM_VERSION}-linux-amd64.tar.gz -O - | tar -xzO linux-amd64/helm > /usr/local/bin/helm && \ + chmod +x /usr/local/bin/helm && \ + chmod +x /check_onap_*.sh && \ + pip3 install --upgrade pip && \ + pip3 install --no-cache-dir \ + git+https://gitlab.com/Orange-OpenSource/lfn/onap/integration/xtesting.git@$ONAP_TESTS_TAG#subdirectory=infra-healthcheck && \ + apk del .build-deps + +COPY docker/testcases.yaml /usr/lib/python3.7/site-packages/xtesting/ci/testcases.yaml +CMD ["run_tests", "-t", "all"] diff --git a/infra-healthcheck/docker/testcases.yaml b/infra-healthcheck/docker/testcases.yaml new file mode 100644 index 0000000..fb30c85 --- /dev/null +++ b/infra-healthcheck/docker/testcases.yaml @@ -0,0 +1,29 @@ +--- +tiers: + - + name: infra-healthcheck + order: 1 + ci_loop: '(daily)|(weekly)!(gating)' + description: >- + Set of basic k8s Functional tests to validate the ONAP installation. + testcases: + - + case_name: onap-k8s + project_name: integration + criteria: 100 + blocking: false + description: >- + This test case verifies that the ONAP pods are all Running + and shows the pods, deployments, svc and events + run: + name: 'onap_k8s' + - + case_name: onap-helm + project_name: integration + criteria: 100 + blocking: false + description: >- + This test case verifies that the ONAP charts are in + DEPLOYED status + run: + name: 'onap_helm' diff --git a/infra-healthcheck/infra_healthcheck/__init__.py b/infra-healthcheck/infra_healthcheck/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/infra-healthcheck/infra_healthcheck/__init__.py diff --git a/infra-healthcheck/infra_healthcheck/k8stest.py b/infra-healthcheck/infra_healthcheck/k8stest.py new file mode 100644 index 0000000..8bb7dde --- /dev/null +++ b/infra-healthcheck/infra_healthcheck/k8stest.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Copyright (c) 2018 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 +# + +""" +Define the parent for Kubernetes testing. +""" + +from __future__ import division + +import logging +import subprocess +import time + +from xtesting.core import testcase + + +class K8sTesting(testcase.TestCase): + """Kubernetes test runner""" + + __logger = logging.getLogger(__name__) + + def __init__(self, **kwargs): + super(K8sTesting, self).__init__(**kwargs) + self.cmd = [] + self.result = 0 + self.details = {} + self.start_time = 0 + self.stop_time = 0 + self.criteria_string = "" + + def run_kubetest(self): # pylint: disable=too-many-branches + """Run the test suites""" + cmd_line = self.cmd + self.__logger.info("Starting k8s test: '%s'.", cmd_line) + + process = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + output = process.stdout.read().decode("utf-8") + if ('Error loading client' in output or + 'Unexpected error' in output): + raise Exception(output) + + # create a log file + file_name = "/var/lib/xtesting/results/" + self.case_name + ".log" + log_file = open(file_name, "w") + log_file.write(output) + log_file.close() + + remarks = [] + details = {} + lines = output.split('\n') + success = False + + for log in lines: + if log.startswith(">>>"): + remarks.append(log.replace('>', '')) + for remark in remarks: + if ':' in remark: + # 2 possible Results + # * numeric nb pods, failed, duration + # * list of pods, charts,... + if '[' in remark: + # it is a list + str1 = remark.split(":", 1)[1].strip().replace( + ']', '').replace('[', '') + details[remark.split(":", 1)[0].strip()] = str1.split(",") + else: + details[remark.split(":", 1)[0].strip()] = int( + remark.split(":", 1)[1].strip()) + + # if 1 pod/helm chart if Failed, the testcase is failed + if int(details[self.criteria_string]) < 1: + success = True + + self.details = details + self.__logger.info("details: %s", details) + + if success: + self.result = 100 + else: + self.result = 0 + + def run(self, **kwargs): + + self.start_time = time.time() + try: + self.run_kubetest() + res = self.EX_OK + except Exception: # pylint: disable=broad-except + self.__logger.exception("Error with running kubetest:") + res = self.EX_RUN_ERROR + + self.stop_time = time.time() + return res + + +class OnapK8sTest(K8sTesting): + """Kubernetes smoke test suite""" + def __init__(self, **kwargs): + if "case_name" not in kwargs: + kwargs.get("case_name", 'onap-k8s') + super(OnapK8sTest, self).__init__(**kwargs) + self.cmd = ['/check_onap_k8s.sh'] + self.criteria_string = "Nb Failed Pods" + + +class OnapHelmTest(K8sTesting): + """Kubernetes conformance test suite""" + def __init__(self, **kwargs): + if "case_name" not in kwargs: + kwargs.get("case_name", 'onap-helm') + super(OnapHelmTest, self).__init__(**kwargs) + self.cmd = ['/check_onap_helm.sh'] + self.criteria_string = "Nb Failed Helm Charts" diff --git a/infra-healthcheck/infra_healthcheck/test_k8stest.py b/infra-healthcheck/infra_healthcheck/test_k8stest.py new file mode 100644 index 0000000..4e91279 --- /dev/null +++ b/infra-healthcheck/infra_healthcheck/test_k8stest.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# +# Copyright (c) 2018 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 +# + +"""Define the classes required to fully cover k8s.""" + +import logging +import os +import unittest + + +from infra_healthcheck import k8stest + + +class K8sTests(unittest.TestCase): + + # pylint: disable=missing-docstring + + def setUp(self): + os.environ["DEPLOY_SCENARIO"] = "k8-test" + os.environ["KUBE_MASTER_IP"] = "127.0.0.1" + os.environ["KUBE_MASTER_URL"] = "https://127.0.0.1:6443" + os.environ["KUBERNETES_PROVIDER"] = "local" + + self.k8stesting = k8stest.K8sTesting() + + def test_run_kubetest_cmd_none(self): + self.k8stesting.cmd = None + with self.assertRaises(TypeError): + self.k8stesting.run_kubetest() + + +if __name__ == "__main__": + logging.disable(logging.CRITICAL) + unittest.main(verbosity=2) diff --git a/infra-healthcheck/requirements.txt b/infra-healthcheck/requirements.txt new file mode 100644 index 0000000..aed40a6 --- /dev/null +++ b/infra-healthcheck/requirements.txt @@ -0,0 +1,11 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. +coverage!=4.4 # Apache-2.0 +mock # BSD +nose # LGPL +flake8>=2.5.4 # MIT +pylint>=2.1 # GPLv2 +yamllint +bashate # Apache-2.0 +xtesting diff --git a/infra-healthcheck/scripts/check_onap_helm.sh b/infra-healthcheck/scripts/check_onap_helm.sh new file mode 100644 index 0000000..27f8094 --- /dev/null +++ b/infra-healthcheck/scripts/check_onap_helm.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +echo "------------------------------------------------------------------------" +echo "------------------- ONAP Check helm charts ----------------------------" +echo "------------------------------------------------------------------------" +code=0 +nb_charts=$(helm ls |awk {'print $1'}|grep -v NAME |wc -l) +nb_failed_charts=0 +list_failed_charts="[$(helm ls |grep -v DEPLOYED |grep -v NAME |awk '{print $1}')]" +nice_list=$(echo $list_failed_charts |sed -e "s/ /,/g") + +# List Helm chart and get their status +for i in $(helm ls |awk {'print $1'}|grep -v NAME);do + echo "Chart $i" + status=$(helm status $i |grep STATUS:) + echo ${status} + if [ "${status}" != "STATUS: DEPLOYED" ]; then + echo "Chart problem" + helm status $i -o yaml + code=1 + let "nb_failed_charts++" + fi + echo "--------------------------------------------------------------------" +done + +echo "------------------------------------------------" +echo "------- ONAP Helm tests ------------------------" +echo "------------------------------------------------" +echo ">>> Nb Helm Charts: ${nb_charts}" +echo ">>> Nb Failed Helm Charts: ${nb_failed_charts}" +echo ">>> List of Failed Helm Charts: ${nice_list}" +echo "------------------------------------------------" +echo "------------------------------------------------" +echo "------------------------------------------------" + +exit $code diff --git a/infra-healthcheck/scripts/check_onap_k8s.sh b/infra-healthcheck/scripts/check_onap_k8s.sh new file mode 100644 index 0000000..2dffd7e --- /dev/null +++ b/infra-healthcheck/scripts/check_onap_k8s.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +echo "------------------------------------------------------------------------" +echo "-------------------- ONAP Check kubernetes ----------------------------" +echo "------------------------------------------------------------------------" + +code=0 + +# get the pod list +echo "List of ONAP pods" +echo "*****************" +kubectl get pods -n onap + +# show deployments +echo "Show ONAP kubernetes deployments" +echo "********************************" +kubectl get deployments -n onap +echo "------------------------------------------------------------------------" + +# show SVC +echo "Show ONAP kubernetes SVC" +echo "************************" +kubectl get svc -n onap +echo "------------------------------------------------------------------------" + +# show ONAP events +echo "Show ONAP kubernetes events" +echo "***************************" +kubectl get events -n onap +echo "------------------------------------------------------------------------" + +# show ONAP config maps +echo "Show ONAP kubernetes config maps" +echo "***************************" +kubectl get cm -n onap +echo "------------------------------------------------------------------------" + +# show ONAP jobs +echo "Show ONAP kubernetes jobs" +echo "***************************" +kubectl get jobs -n onap +echo "------------------------------------------------------------------------" + +# show ONAP statefulsets +echo "Show ONAP kubernetes statefulset" +echo "***************************" +kubectl get sts -n onap +echo "------------------------------------------------------------------------" + +# if all pods in RUNNING state exit 0, else exit 1 +nb_pods=$((`kubectl get pods -n onap | grep Running | grep -v functest | wc -l` -1)) +list_failed_pods=$(kubectl get pods -n onap |grep -v Running |grep -v functest |grep -v NAME | grep -v Completed | awk '{print $1}') +list_filtered_failed_pods=() + +for i in $list_failed_pods;do + status=$(kubectl get pods -n onap $i | grep -v NAME | awk '{print $3'}) + # in case of Error or Init:Error + # we check that another instance is not already Completed or Running + if [ $status = "Error" ] || [ $status = "Init:Error" ];then + echo "$i in Status Error or Init Error found for the pods, is is really true...." + # By default pod naming is similar, keep only the root to check + root_name=${i::-6} + kubectl get pods -n onap | grep $root_name | grep Completed + if [ $? ];then + echo "Instance Completed found." + else + echo "No Completed instance found." + list_filtered_failed_pods+=$i, + fi + else + # Other status are not running/not completed pods + list_filtered_failed_pods+=$i, + fi +done + +nice_list=${list_filtered_failed_pods::-1} + +IFS=, +nb_pods_not_running=$(echo "$list_filtered_failed_pods" | tr -cd , | wc -c) + +if [ $nb_pods_not_running -ne 0 ]; then +echo "$nb_pods_not_running pods (on $nb_pods) are not in Running state" +echo "---------------------------------------------------------------------" + kubectl get pods -n onap | grep -v Running | grep -v functest | grep -v Completed + echo "--------------------------------------------------------------------" + echo "Describe non running pods" + echo "*************************" + for i in $nice_list;do + echo "****************************************************************" + kubectl describe pod $i -n onap + kubectl logs --all-containers=true -n onap $i + done + code=1 +else + echo "all pods ($nb_pods) are running well" +fi + +echo "------------------------------------------------" +echo "------- ONAP kubernetes tests ------------------" +echo "------------------------------------------------" +echo ">>> Nb Pods: $nb_pods" +echo ">>> Nb Failed Pods: $nb_pods_not_running" +echo ">>> List of Failed Pods: [$nice_list]" +echo "------------------------------------------------" +echo "------------------------------------------------" +echo "------------------------------------------------" + +exit $code diff --git a/infra-healthcheck/setup.cfg b/infra-healthcheck/setup.cfg new file mode 100644 index 0000000..2cccb82 --- /dev/null +++ b/infra-healthcheck/setup.cfg @@ -0,0 +1,11 @@ +[metadata] +name = infra_healthcheck +version = 1 + +[files] +packages = infra_healthcheck + +[entry_points] +xtesting.testcase = + onap_k8s = infra_healthcheck.k8stest:OnapK8sTest + onap_helm = infra_healthcheck.k8stest:OnapHelmTest diff --git a/infra-healthcheck/setup.py b/infra-healthcheck/setup.py new file mode 100644 index 0000000..566d844 --- /dev/null +++ b/infra-healthcheck/setup.py @@ -0,0 +1,29 @@ +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT +import setuptools + +# In python < 2.7.4, a lazy loading of package `pbr` will break +# setuptools if some other modules registered functions in `atexit`. +# solution from: http://bugs.python.org/issue15881#msg170215 +try: + import multiprocessing # noqa +except ImportError: + pass + +setuptools.setup( + setup_requires=['pbr>=2.0.0'], + pbr=True) diff --git a/infra-healthcheck/tox.ini b/infra-healthcheck/tox.ini new file mode 100644 index 0000000..0bd2e5a --- /dev/null +++ b/infra-healthcheck/tox.ini @@ -0,0 +1,49 @@ +[tox] +envlist = pylint,yamllint,bashate,py3 + +[testenv] +usedevelop = True +deps = + -chttps://git.opnfv.org/functest/plain/upper-constraints.txt + -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=master} + -r{toxinidir}/requirements.txt +install_command = pip install {opts} {packages} + +[testenv:pep8] +basepython = python3 +commands = flake8 + +[testenv:pylint] +basepython = python3 +whitelist_externals = pylint +modules = + infra_healthcheck +commands = + pylint --disable=locally-disabled --reports=n {[testenv:pylint]modules} + +[testenv:yamllint] +whitelist_externals = yamllint +basepython = python3 +files = + docker +commands = + yamllint {[testenv:yamllint]files} + +[testenv:py3] +whitelist_externals = nosetests +basepython = python3 +commands = nosetests --with-xunit \ + --with-coverage \ + --cover-tests \ + --cover-package=infra_healthcheck \ + --cover-xml \ + --cover-html \ + infra_healthcheck + +[testenv:bashate] +whitelist_externals = bashate +basepython = python3 +files = + scripts/check_onap_k8s.sh + scripts/check_onap_helm.sh +commands = bashate {[testenv:bashate]files} -i E006 |