fuel-ccp-tests/fuel_ccp_tests/tests/component/k8s/test_appcontroller.py

212 lines
8.2 KiB
Python

# Copyright 2016 Mirantis, Inc.
#
# 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.
import pytest
from devops.helpers import helpers
from k8sclient.client import rest
import yaml
from fuel_ccp_tests import logger
from fuel_ccp_tests import settings
from fuel_ccp_tests.helpers import ext
LOG = logger.logger
class AppControllerResoucesStatus(object):
"""Helper class to check defined resources creation of AppController"""
resources = [
"dependency.appcontroller.k8s1",
"definition.appcontroller.k8s2"
]
def __init__(self, k8sclient, kube_ssh, expected_result=None):
"""
:param k8sclient: fuel_ccp_tests.managers.k8s.cluster.K8sCluster
:param kube_ssh: devops.helpers.ssh_client.SSHClient
:param expected_result: list of strings in 'type/object_name' format
"""
super(AppControllerResoucesStatus, self).__init__()
self.__k8s = k8sclient
self.__managers = {
"job": lambda: self.__k8s.jobs,
"pod": lambda: self.__k8s.pods,
"replicaset": lambda: self.__k8s.replicasets,
"service": lambda: self.__k8s.services,
}
self.__ssh = kube_ssh
self.__linear_order = []
self.register_linear_objects(expected_result)
def register_linear_objects(self, list_resources=None):
"""Method to register check actions for each type of resources
:param list_resources: list of strings "type/object"
:raises: TypeError, KeyError, ValueError
"""
# The following object will return function (checker) to run
def obj_exists(resource):
resource_type, resource_name = resource.split('/')
if resource_name is None:
raise ValueError("Resource '{}' has wrong format".format(
resource
))
return (
lambda: self.__managers[resource_type]().get(
name=resource_name) is not None)
if list_resources:
if not isinstance(list_resources, list):
raise TypeError("list_resources must be a list instance!")
result = []
for resource in list_resources:
try:
res_func = obj_exists(resource)
# To restore original name of object
setattr(res_func, '__resource_repr', resource)
except KeyError:
raise KeyError(
"Resource '{}' has unsupported type!".format(resource))
result.append(res_func)
self.__linear_order = result
def _linear_check(self, func):
"""Action to run check
:param func: function to run
"""
# Each function must be created with this attribute
resource_repr = getattr(func, '__resource_repr')
# Additional flag to detect if object has already created
must_created = getattr(func, '__to_be_created', None)
try:
result = func()
if must_created is None:
raise Exception("{} is already created!".format(resource_repr))
LOG.info("{} is created".format(resource_repr))
except rest.ApiException as err:
LOG.debug(err)
if must_created is None:
setattr(func, '__to_be_created', True)
LOG.info("{} should be created".format(resource_repr))
result = False
return result
def linear_check(self):
"""Action to wait until all checks are done
Each check has own timeout equals 300 secs"""
for item in self.__linear_order:
resource_repr = getattr(item, '__resource_repr')
helpers.wait(
lambda: self._linear_check(item), timeout=300, interval=2,
timeout_msg="{} creation timeout reached".format(resource_repr)
)
def thirdparty_resources(self):
result = yaml.load(
self.__ssh.check_call(
"kubectl get thirdpartyresources -o yaml").stdout_str
)
return [item['metadata']['name'] for item in result['items']]
@pytest.mark.AppController
@pytest.mark.component
class TestAppController(object):
kube_settings = {
"hyperkube_image_repo": settings.HYPERKUBE_IMAGE_REPO,
"hyperkube_image_tag": settings.HYPERKUBE_IMAGE_TAG,
"searchdomains": settings.SEARCH_DOMAINS,
"use_hyperkube_cni": str("true"),
}
@pytest.mark.ac_linear_test
@pytest.mark.revert_snapshot(ext.SNAPSHOT.k8s_deployed)
@pytest.mark.skipif(settings.AC_REPO == "",
reason="ApplicationController repo is not set!")
def test_linear(self, underlay, k8scluster):
"""Linear test of AppController work
Scenario:
1. Get AppController source on master node
2. Create AppController in k8s
3. Wait until pod with AppController is Running
4. Wait until required thirdparty resources are created
5. Create dependencies from test
6. Create definitions from test
7. Run AppController to create defined resources
8. Check if resources are created in expected order
"""
node_name = underlay.node_names()[0]
remote = underlay.remote(node_name=underlay.node_names()[0])
cmd_ac_run = "kubectl exec -i k8s-appcontroller ac-run"
# Install additional software if it's needed
underlay.sudo_check_call(
cmd="which unzip || apt-get install unzip",
node_name=node_name)
cmd = """wget -qO ac.zip {url} &&
unzip -qq ac && mv k8s-AppController-{commit} k8s-AppController &&
cd k8s-AppController && pwd""".format(
url=settings.AC_ZIP_URL, commit=settings.AC_COMMIT)
LOG.info("1. Get AppController source on master node")
ac_path = underlay.check_call(
cmd, node_name=node_name).stdout_str
LOG.info("2. Create AppController in k8s")
underlay.check_call(
"kubectl create -f {}/manifests/appcontroller.yaml".format(
ac_path),
node_name=node_name)
LOG.info("3. Wait until pod with AppController is Running")
k8scluster.wait_pod_phase(
pod_name="k8s-appcontroller", phase="Running", timeout=300)
# Load expected order to perform future checks
file_name = "{}/tests/linear/expected_order.yaml".format(ac_path)
with remote.open(file_name) as f:
expected_order = yaml.load(f.read())
acr = AppControllerResoucesStatus(k8scluster.api, remote,
expected_order)
LOG.info("4. Wait until required thirdparty resources are created")
helpers.wait(
lambda: set(acr.thirdparty_resources()).issubset(acr.resources),
timeout=120, interval=2, timeout_msg="Resources creation timeout"
)
LOG.info("5. Create dependencies from test")
cmd = "kubectl create -f {}/tests/linear/dependencies.yaml".format(
ac_path)
helpers.wait(
lambda: underlay.check_call(
cmd, node_name=node_name, expected=[0, 1]
).exit_code == 0,
timeout=30, interval=2, timeout_msg="Dependencies creation failed")
LOG.info("6. Create definitions from test")
underlay.check_call(
"kubectl create -f {}/tests/linear/definitions.yaml".format(
ac_path),
node_name=node_name)
LOG.info("7. Run AppController to create defined resources")
underlay.check_call(cmd_ac_run, node_name=node_name)
LOG.info("8. Check if resources are created in expected order")
acr.linear_check()