Add test_k8s_dashboard test
Add 'cluster role binding' api wrapper
Add method in TestMCPK8sActions to read testdata yamls
Change-Id: I7b9f7a74ce74ea5e722cb4c958bd60b6a64b6a0c
Related-PROD: PROD-22249
diff --git a/tcp_tests/managers/k8s/cluster.py b/tcp_tests/managers/k8s/cluster.py
index 8ffb4d1..db7bb18 100644
--- a/tcp_tests/managers/k8s/cluster.py
+++ b/tcp_tests/managers/k8s/cluster.py
@@ -42,6 +42,8 @@
from tcp_tests.managers.k8s.services import K8sServiceManager
from tcp_tests.managers.k8s.replicasets import K8sReplicaSetManager
from tcp_tests.managers.k8s.networkpolicies import K8sNetworkPolicyManager
+from tcp_tests.managers.k8s.clusterrolebindings import \
+ K8sClusterRoleBindingManager
class K8sCluster(object):
@@ -89,6 +91,7 @@
self.api_extensions = client.ExtensionsV1beta1Api(api_client)
self.api_autoscaling = client.AutoscalingV1Api(api_client)
self.api_batch = client.BatchV1Api(api_client)
+ self.api_rbac_auth = client.RbacAuthorizationV1Api(api_client)
self.nodes = K8sNodeManager(self)
self.pods = K8sPodManager(self)
@@ -111,3 +114,4 @@
self.pvolumes = K8sPersistentVolumeManager(self)
self.replicasets = K8sReplicaSetManager(self)
self.networkpolicies = K8sNetworkPolicyManager(self)
+ self.clusterrolebindings = K8sClusterRoleBindingManager(self)
diff --git a/tcp_tests/managers/k8s/clusterrolebindings.py b/tcp_tests/managers/k8s/clusterrolebindings.py
new file mode 100644
index 0000000..d958817
--- /dev/null
+++ b/tcp_tests/managers/k8s/clusterrolebindings.py
@@ -0,0 +1,54 @@
+# Copyright 2017 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
+
+
+from kubernetes import client
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sClusterRoleBinding(K8sBaseResource):
+ resource_type = 'clusterrolebindings'
+
+ def _read(self, **kwargs):
+ return self._manager.api.read_cluster_role_binding(self.name, **kwargs)
+
+ def _create(self, body, **kwargs):
+ return self._manager.api.create_cluster_role_binding(body, **kwargs)
+
+ def _patch(self, body, **kwargs):
+ return self._manager.api.patch_cluster_role_binding(
+ self.name, body, **kwargs)
+
+ def _replace(self, body, **kwargs):
+ return self._manager.api.replace_cluster_role_binding(
+ self.name, body, **kwargs)
+
+ def _delete(self, **kwargs):
+ self._manager.api.delete_cluster_role_binding(
+ self.name, client.V1DeleteOptions(), **kwargs)
+
+
+class K8sClusterRoleBindingManager(K8sBaseManager):
+ resource_class = K8sClusterRoleBinding
+
+ @property
+ def api(self):
+ return self._cluster.api_rbac_auth
+
+ def _list(self, namespace, **kwargs):
+ return self.api.list_cluster_role_binding(**kwargs)
+
+ def _list_all(self, **kwargs):
+ return self._list(None, **kwargs)
diff --git a/tcp_tests/managers/k8s/serviceaccounts.py b/tcp_tests/managers/k8s/serviceaccounts.py
index 3b779eb..bc0db30 100644
--- a/tcp_tests/managers/k8s/serviceaccounts.py
+++ b/tcp_tests/managers/k8s/serviceaccounts.py
@@ -14,6 +14,8 @@
from kubernetes import client
+from devops.helpers import helpers
+
from tcp_tests.managers.k8s.base import K8sBaseResource
from tcp_tests.managers.k8s.base import K8sBaseManager
@@ -41,6 +43,13 @@
self._manager.api.delete_namespaced_service_account(
self.name, self.namespace, client.V1DeleteOptions(), **kwargs)
+ def wait_secret_generation(self, timeout=90, interval=2):
+ def is_secret_generated():
+ secrets = self.read().secrets
+ return secrets is not None and len(secrets) > 0
+ helpers.wait(lambda: is_secret_generated(),
+ timeout=timeout, interval=interval)
+
class K8sServiceAccountManager(K8sBaseManager):
resource_class = K8sServiceAccount
diff --git a/tcp_tests/managers/k8smanager.py b/tcp_tests/managers/k8smanager.py
index a72f2f1..748cb04 100644
--- a/tcp_tests/managers/k8smanager.py
+++ b/tcp_tests/managers/k8smanager.py
@@ -364,15 +364,19 @@
return self.controller_check_call("nslookup {0} {1}".format(host, src))
@retry(300, exception=DevopsCalledProcessError)
- def curl(self, url):
+ def curl(self, url, *args):
"""
Run curl on controller and return stdout
:param url: url to curl
- :return: response string
+ :return: list of strings (with /n at end of every line)
"""
- result = self.controller_check_call("curl -s -S \"{}\"".format(url))
- LOG.debug("curl \"{0}\" result: {1}".format(url, result['stdout']))
+ args = list(args)
+ args.append(url)
+ cmd = "curl -s -S {}".format(
+ " ".join(["'{}'".format(a.replace("'", "\\'")) for a in args]))
+ result = self.controller_check_call(cmd)
+ LOG.debug("{0}\nresult:\n{1}".format(cmd, result['stdout']))
return result['stdout']
diff --git a/tcp_tests/tests/system/test_k8s_actions.py b/tcp_tests/tests/system/test_k8s_actions.py
index 6510a67..364361c 100644
--- a/tcp_tests/tests/system/test_k8s_actions.py
+++ b/tcp_tests/tests/system/test_k8s_actions.py
@@ -15,6 +15,7 @@
import pytest
import netaddr
import os
+import json
from tcp_tests import logger
from tcp_tests import settings
@@ -27,6 +28,10 @@
class TestMCPK8sActions(object):
"""Test class for different k8s actions"""
+ def __read_testdata_yaml(self, name):
+ dir = os.path.join(os.path.dirname(__file__), 'testdata/k8s')
+ return read_yaml_file(dir, name)
+
@pytest.mark.grab_versions
@pytest.mark.fail_snapshot
@pytest.mark.cz8116
@@ -235,9 +240,8 @@
namespace="kube-system", name_prefix="kube-flannel-") > 0
show_step(3)
- data_dir = os.path.join(os.path.dirname(__file__), 'testdata/k8s')
flannel_pod = k8s_deployed.api.pods.create(
- body=read_yaml_file(data_dir, 'pod-sample-flannel.yaml'))
+ body=self.__read_testdata_yaml('pod-sample-flannel.yaml'))
flannel_pod.wait_running()
show_step(4)
@@ -247,7 +251,7 @@
show_step(5)
calico_pod = k8s_deployed.api.pods.create(
- body=read_yaml_file(data_dir, 'pod-sample-calico.yaml'))
+ body=self.__read_testdata_yaml('pod-sample-calico.yaml'))
calico_pod.wait_running()
show_step(6)
@@ -257,7 +261,7 @@
show_step(7)
multicni_pod = k8s_deployed.api.pods.create(
- body=read_yaml_file(data_dir, 'pod-sample-multicni.yaml'))
+ body=self.__read_testdata_yaml('pod-sample-multicni.yaml'))
multicni_pod.wait_running()
show_step(8)
@@ -270,7 +274,7 @@
show_step(9)
nocni_pod = k8s_deployed.api.pods.create(
- body=read_yaml_file(data_dir, 'pod-sample.yaml'))
+ body=self.__read_testdata_yaml('pod-sample.yaml'))
nocni_pod.wait_running()
show_step(10)
@@ -305,3 +309,78 @@
calico_pod.delete()
multicni_pod.delete()
nocni_pod.delete()
+
+ @pytest.mark.grap_versions
+ @pytest.mark.fail_snapshot
+ def test_k8s_dashboard(self, show_step, config,
+ salt_deployed, k8s_deployed):
+ """Test dashboard setup
+
+ Scenario:
+ 1. Setup Kubernetes cluster
+ 2. Try to curl login status api
+ 3. Create a test-admin-user account
+ 4. Try to login in dashboard using test-admin-user account
+ 5. Get and check list of namespaces using dashboard api
+ """
+ show_step(1)
+
+ show_step(2)
+ system_ns = 'kube-system'
+ dashboard_service = \
+ k8s_deployed.api.services.get('kubernetes-dashboard', system_ns)
+ dashboard_url = 'https://{}'.format(dashboard_service.get_ip())
+
+ def dashboard_curl(url, data=None, headers=None):
+ """ Using curl command on controller node. Alternatives:
+ - connect_{get,post}_namespaced_service_proxy_with_path -
+ k8s lib does not provide way to pass headers or POST data
+ - raw rest k8s api - need to auth somehow
+ - new load-balancer svc for dashboard + requests python lib -
+ requires working metallb or other load-balancer
+ """
+ args = ['--insecure']
+ for name in headers or {}:
+ args.append('--header')
+ args.append("{0}: {1}".format(name, headers[name]))
+ if data is not None:
+ args.append('--data')
+ args.append(data)
+ return ''.join(k8s_deployed.curl(dashboard_url + url, *args))
+
+ assert 'tokenPresent' in \
+ json.loads(dashboard_curl('/api/v1/login/status'))
+
+ show_step(3)
+ account = k8s_deployed.api.serviceaccounts.create(
+ namespace=system_ns,
+ body=self.__read_testdata_yaml('test-admin-user-account.yaml'))
+ account.wait_secret_generation()
+
+ k8s_deployed.api.clusterrolebindings.create(
+ body=self.__read_testdata_yaml(
+ 'test-admin-user-cluster-role-bind.yaml'))
+
+ account_secret = account.read().secrets[0]
+ account_token = k8s_deployed.api.secrets.get(
+ namespace=system_ns, name=account_secret.name).read().data['token']
+
+ show_step(4)
+ csrf_token = \
+ json.loads(dashboard_curl('/api/v1/csrftoken/login'))['token']
+ login_headers = {'X-CSRF-TOKEN': csrf_token,
+ 'Content-Type': 'application/json'}
+ jwe_token = json.loads(dashboard_curl(
+ '/api/v1/login', headers=login_headers,
+ data=json.dumps({'token': account_token.decode('base64')})
+ ))['jweToken']
+ headers = {'jweToken': jwe_token}
+
+ show_step(5)
+ dashboard_namespaces = json.loads(
+ dashboard_curl('/api/v1/namespace', headers=headers))['namespaces']
+
+ namespaces_names_list = \
+ [ns.name for ns in k8s_deployed.api.namespaces.list()]
+ for namespace in dashboard_namespaces:
+ assert namespace['objectMeta']['name'] in namespaces_names_list
diff --git a/tcp_tests/tests/system/testdata/k8s/test-admin-user-account.yaml b/tcp_tests/tests/system/testdata/k8s/test-admin-user-account.yaml
new file mode 100644
index 0000000..889fa48
--- /dev/null
+++ b/tcp_tests/tests/system/testdata/k8s/test-admin-user-account.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-admin-user
+ namespace: kube-system
diff --git a/tcp_tests/tests/system/testdata/k8s/test-admin-user-cluster-role-bind.yaml b/tcp_tests/tests/system/testdata/k8s/test-admin-user-cluster-role-bind.yaml
new file mode 100644
index 0000000..cad78ce
--- /dev/null
+++ b/tcp_tests/tests/system/testdata/k8s/test-admin-user-cluster-role-bind.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: test-admin-user
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+- kind: ServiceAccount
+ name: test-admin-user
+ namespace: kube-system