From beb481ccb8aabbad592df837d4430373331eafa9 Mon Sep 17 00:00:00 2001 From: satish-nubo Date: Thu, 18 Feb 2021 10:50:07 +0000 Subject: [PATCH 01/10] Added healthcheck robot files --- src/KubeLibrary/KubeLibrary.py | 84 +++++++++++++++++----- testcases/healthcheck/healthcheck.robot | 8 +++ testcases/healthcheck/healthcheck_kw.robot | 15 ++++ 3 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 testcases/healthcheck/healthcheck.robot create mode 100644 testcases/healthcheck/healthcheck_kw.robot diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index 9685c64d..d203faf0 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -4,6 +4,7 @@ import urllib3 from kubernetes import client, config from robot.api import logger +import requests # supressing SSL warnings when using self-signed certs urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -231,23 +232,6 @@ def get_jobs_in_namespace(self, name_pattern, namespace, label_selector=""): jobs = [item for item in ret.items if r.match(item.metadata.name)] return jobs - def get_secrets_in_namespace(self, name_pattern, namespace, label_selector=""): - """Gets secrets matching pattern in given namespace. - - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - - Returns list of secrets. - - - ``name_pattern``: - secret name pattern to check - - ``namespace``: - Namespace to check - """ - ret = self.v1.list_namespaced_secret(namespace, watch=False, label_selector=label_selector) - r = re.compile(name_pattern) - secrets = [item for item in ret.items if r.match(item.metadata.name)] - return secrets - def filter_pods_names(self, pods): """Filter pod names for list of pods. @@ -517,3 +501,69 @@ def delete_service_account_in_namespace(self, name, namespace): """ ret = self.v1.delete_namespaced_service_account(name=name, namespace=namespace) return ret + + + def get_healthcheck(self): + """check cluster leverl healthcheck + Can be used to verify the readiness/current status of the API server +" """ + output = requests.get('https://localhost:6443/readyz?verbose=', verify = False) + logger.debug(output) + return output + + def get_ingresses_in_namespace(self, namespace, label_selector=""): + """Gets ingresses in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of strings. + - ``namespace``: + Namespace to check + """ + ret = self.v1.list_namespaced_ingress(namespace, watch=False, label_selector=label_selector) + return [item.metadata.name for item in ret.items] + + + + def get_ingress_details_in_namespace(self, name, namespace): + """Gets ingress details in given namespace. + Returns Ingress object representation. Can be accessed using + | Should Be Equal As integers | ${service_details.spec.ports[0].port} | 8080 | + - ``name``: + Name of ingress. + - ``namespace``: + Namespace to check + """ + ret = self.v1.read_namespaced_ingress(name, namespace) + return ret + + def get_k8objects(self): + output = subprocess.check_output("kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -n default",shell=True) + logger.debug(output) + return output + + def get_cronjobs_in_namespace(self, name_pattern, namespace, label_selector=""): + """Gets cronjobs matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of cronjobs. + - ``name_pattern``: + cronjobs name pattern to check + - ``namespace``: + Namespace to check + """ + ret = self.v1.list_namespaced_cronjobs(namespace, watch=False, label_selector=label_selector) + r = re.compile(name_pattern) + cronjobs = [item for item in ret.items if r.match(item.metadata.name)] + return cronjobs + + def get_replicasets_in_namespace(self, name_pattern, namespace, label_selector=""): + """Gets replicasets matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of replicasets. + - ``name_pattern``: + replicasets name pattern to check + - ``namespace``: + Namespace to check + """ + ret = self.v1.list_namespaced_replicasets(namespace, watch=False, label_selector=label_selector) + r = re.compile(name_pattern) + replicasets = [item for item in ret.items if r.match(item.metadata.name)] + return replicasets diff --git a/testcases/healthcheck/healthcheck.robot b/testcases/healthcheck/healthcheck.robot new file mode 100644 index 00000000..5c0d5f3b --- /dev/null +++ b/testcases/healthcheck/healthcheck.robot @@ -0,0 +1,8 @@ +*** Settings *** +Resource ./healthcheck_kw.robot + +*** Test Cases *** +Healthcheck + [Tags] other + Healthcheck + diff --git a/testcases/healthcheck/healthcheck_kw.robot b/testcases/healthcheck/healthcheck_kw.robot new file mode 100644 index 00000000..08cf8ebc --- /dev/null +++ b/testcases/healthcheck/healthcheck_kw.robot @@ -0,0 +1,15 @@ +*** Settings *** +Library Collections +Library RequestsLibrary +Library String +# For regular execution +Library KubeLibrary +# For incluster execution +#Library KubeLibrary None True False +# For development +#Library ../../src/KubeLibrary/KubeLibrary.py ~/.kube/k3d + +*** Keywords *** +Healthcheck + ${output}= Get Healthcheck + Log \nHealthcheck ${output}: console=True From 53bbdd1edc1266a88e41fdc573288972776dd5e9 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 19 Feb 2021 03:19:46 +0000 Subject: [PATCH 02/10] Added cluster healthcheck --- src/KubeLibrary/KubeLibrary.py | 149 ++++----------------------------- 1 file changed, 15 insertions(+), 134 deletions(-) diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index d203faf0..af2d9301 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -4,7 +4,6 @@ import urllib3 from kubernetes import client, config from robot.api import logger -import requests # supressing SSL warnings when using self-signed certs urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -12,27 +11,19 @@ class KubeLibrary(object): """KubeLibrary is a Robot Framework test library for Kubernetes. - The approach taken by this library is to provide easy to access kubernetes objects representation that can be then accessed to define highlevel keywords for tests. - = Kubeconfigs = - By default ~/.kube/config is used. Kubeconfig location can also be passed by setting KUBECONFIG environment variable or as Library argument. - | ***** Settings ***** | Library KubeLibrary /path/to/kubeconfig - = In cluster execution = - If tests are supposed to be executed from within cluster, KubeLibrary can be configured to use standard token authentication. Just set incluster parameter to True. If True then kubeconfigs are not used, even if provided. - | ***** Settings ***** | Library KubeLibrary None True - """ def __init__(self, kube_config=None, incluster=False, cert_validation=True): """KubeLibrary can be configured with several optional arguments. @@ -74,7 +65,6 @@ def reload_config(self, kube_config=None, incluster=False, cert_validation=True) def k8s_api_ping(self): """Performs GET on /api/v1/ for simple check of API availability. - Returns tuple of (response data, response status, response headers). Can be used as prerequisite in tests. """ path_params = {} @@ -93,9 +83,7 @@ def k8s_api_ping(self): def get_namespaces(self, label_selector=""): """Gets a list of available namespaces. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of namespaces. """ ret = self.v1.list_namespace(watch=False, label_selector=label_selector) @@ -103,9 +91,7 @@ def get_namespaces(self, label_selector=""): def get_healthy_nodes_count(self, label_selector=""): """Counts node with KubeletReady and status True. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Can be used to check number of healthy nodes. Can be used as prerequisite in tests. """ ret = self.v1.list_node(watch=False, label_selector=label_selector) @@ -118,11 +104,8 @@ def get_healthy_nodes_count(self, label_selector=""): def get_pod_names_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets pod name matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of strings. - - ``name_pattern``: Pod name pattern to check - ``namespace``: @@ -134,11 +117,8 @@ def get_pod_names_in_namespace(self, name_pattern, namespace, label_selector="") def get_pods_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets pods matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of pods. - - ``name_pattern``: Pod name pattern to check - ``namespace``: @@ -151,9 +131,7 @@ def get_pods_in_namespace(self, name_pattern, namespace, label_selector=""): def get_pod_logs(self, name, namespace, container): """Gets container logs of given pod in given namespace. - Returns logs. - - ``name``: Pod name to check - ``namespace``: @@ -166,11 +144,8 @@ def get_pod_logs(self, name, namespace, container): def get_configmaps_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets configmaps matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of configmaps. - - ``name_pattern``: configmap name pattern to check - ``namespace``: @@ -183,11 +158,8 @@ def get_configmaps_in_namespace(self, name_pattern, namespace, label_selector="" def get_service_accounts_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets service accounts matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of service accounts. - - ``name_pattern``: Service Account name pattern to check - ``namespace``: @@ -200,11 +172,8 @@ def get_service_accounts_in_namespace(self, name_pattern, namespace, label_selec def get_deployments_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets deployments matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of deployments. - - ``name_pattern``: deployment name pattern to check - ``namespace``: @@ -217,11 +186,8 @@ def get_deployments_in_namespace(self, name_pattern, namespace, label_selector=" def get_jobs_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets jobs matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of jobs. - - ``name_pattern``: job name pattern to check - ``namespace``: @@ -232,11 +198,23 @@ def get_jobs_in_namespace(self, name_pattern, namespace, label_selector=""): jobs = [item for item in ret.items if r.match(item.metadata.name)] return jobs + def get_secrets_in_namespace(self, name_pattern, namespace, label_selector=""): + """Gets secrets matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of secrets. + - ``name_pattern``: + secret name pattern to check + - ``namespace``: + Namespace to check + """ + ret = self.v1.list_namespaced_secret(namespace, watch=False, label_selector=label_selector) + r = re.compile(name_pattern) + secrets = [item for item in ret.items if r.match(item.metadata.name)] + return secrets + def filter_pods_names(self, pods): """Filter pod names for list of pods. - Returns list of strings. - - ``pods``: List of pods objects """ @@ -244,9 +222,7 @@ def filter_pods_names(self, pods): def filter_service_accounts_names(self, service_accounts): """Filter service accounts names for list of service accounts. - Returns list of strings. - - ``service_accounts``: List of service accounts objects """ @@ -254,9 +230,7 @@ def filter_service_accounts_names(self, service_accounts): def filter_pods_containers_by_name(self, pods, name_pattern): """Filters pods containers by name for given list of pods. - Returns lists of containers (flattens). - - ``pods``: List of pods objects """ @@ -270,9 +244,7 @@ def filter_pods_containers_by_name(self, pods, name_pattern): def filter_containers_images(self, containers): """Filters container images for given lists of containers. - Returns list of images. - - ``containers``: List of containers """ @@ -280,9 +252,7 @@ def filter_containers_images(self, containers): def filter_containers_resources(self, containers): """Filters container resources for given lists of containers. - Returns list of resources. - - ``containers``: List of containers """ @@ -290,9 +260,7 @@ def filter_containers_resources(self, containers): def filter_pods_containers_statuses_by_name(self, pods, name_pattern): """Filters pods containers statuses by container name for given list of pods. - Returns lists of containers statuses. - - ``pods``: List of pods objects """ @@ -306,7 +274,6 @@ def filter_pods_containers_statuses_by_name(self, pods, name_pattern): def get_pod_status_in_namespace(self, name, namespace): """Gets pod status in given namespace. - - ``name``: Name of pod. - ``namespace``: @@ -317,9 +284,7 @@ def get_pod_status_in_namespace(self, name, namespace): def assert_pod_has_labels(self, pod, labels_json): """Assert pod has labels. - Returns True/False - - ``pod``: Pod object. - ``labels_json``: @@ -342,9 +307,7 @@ def assert_pod_has_labels(self, pod, labels_json): def assert_pod_has_annotations(self, pod, annotations_json): """Assert pod has annotations. - Returns True/False - - ``pod``: Pod object. - ``annotations_json``: @@ -367,9 +330,7 @@ def assert_pod_has_annotations(self, pod, annotations_json): def assert_container_has_env_vars(self, container, env_vars_json): """Assert container has env vars. - Returns True/False - - ``container``: Container object. - ``env_var_json``: @@ -396,11 +357,8 @@ def assert_container_has_env_vars(self, container, env_vars_json): def get_services_in_namespace(self, namespace, label_selector=""): """Gets services in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of strings. - - ``namespace``: Namespace to check """ @@ -409,11 +367,8 @@ def get_services_in_namespace(self, namespace, label_selector=""): def get_service_details_in_namespace(self, name, namespace): """Gets service details in given namespace. - Returns Service object representation. Can be accessed using - | Should Be Equal As integers | ${service_details.spec.ports[0].port} | 8080 | - - ``name``: Name of service. - ``namespace``: @@ -424,11 +379,8 @@ def get_service_details_in_namespace(self, name, namespace): def get_endpoints_in_namespace(self, name, namespace): """Gets endpoint details in given namespace. - Returns Endpoint object representation. Can be accessed using - | Should Match | ${endpoint_details.subsets[0].addresses[0].target_ref.name} | pod-name-123456 | - - ``name``: Name of endpoint. - ``namespace``: @@ -439,11 +391,8 @@ def get_endpoints_in_namespace(self, name, namespace): def get_pvc_in_namespace(self, namespace, label_selector=""): """Gets pvcs in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of strings. - - ``namespace``: Namespace to check """ @@ -452,11 +401,8 @@ def get_pvc_in_namespace(self, namespace, label_selector=""): def get_pvc_capacity(self, name, namespace): """Gets PVC details in given namespace. - Returns PVC object representation. Can be accessed using - | Should Be Equal As strings | ${pvc.status.capacity.storage} | 1Gi | - - ``name``: Name of PVC. - ``namespace``: @@ -467,9 +413,7 @@ def get_pvc_capacity(self, name, namespace): def get_kubelet_version(self, label_selector=""): """Gets list of kubelet versions on each node. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of strings. """ ret = self.v1.list_node(watch=False, label_selector=label_selector) @@ -477,9 +421,7 @@ def get_kubelet_version(self, label_selector=""): def create_service_account_in_namespace(self, namespace, body): """Creates service account in a namespace - Returns created service account - - ``body``: Service Account object. - ``namespace``: @@ -490,10 +432,7 @@ def create_service_account_in_namespace(self, namespace, body): def delete_service_account_in_namespace(self, name, namespace): """Deletes service account in a namespace - Returns V1status - - - ``name``: Service Account name - ``namespace``: @@ -502,68 +441,10 @@ def delete_service_account_in_namespace(self, name, namespace): ret = self.v1.delete_namespaced_service_account(name=name, namespace=namespace) return ret - def get_healthcheck(self): """check cluster leverl healthcheck Can be used to verify the readiness/current status of the API server -" """ + """ output = requests.get('https://localhost:6443/readyz?verbose=', verify = False) logger.debug(output) return output - - def get_ingresses_in_namespace(self, namespace, label_selector=""): - """Gets ingresses in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of strings. - - ``namespace``: - Namespace to check - """ - ret = self.v1.list_namespaced_ingress(namespace, watch=False, label_selector=label_selector) - return [item.metadata.name for item in ret.items] - - - - def get_ingress_details_in_namespace(self, name, namespace): - """Gets ingress details in given namespace. - Returns Ingress object representation. Can be accessed using - | Should Be Equal As integers | ${service_details.spec.ports[0].port} | 8080 | - - ``name``: - Name of ingress. - - ``namespace``: - Namespace to check - """ - ret = self.v1.read_namespaced_ingress(name, namespace) - return ret - - def get_k8objects(self): - output = subprocess.check_output("kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -n default",shell=True) - logger.debug(output) - return output - - def get_cronjobs_in_namespace(self, name_pattern, namespace, label_selector=""): - """Gets cronjobs matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of cronjobs. - - ``name_pattern``: - cronjobs name pattern to check - - ``namespace``: - Namespace to check - """ - ret = self.v1.list_namespaced_cronjobs(namespace, watch=False, label_selector=label_selector) - r = re.compile(name_pattern) - cronjobs = [item for item in ret.items if r.match(item.metadata.name)] - return cronjobs - - def get_replicasets_in_namespace(self, name_pattern, namespace, label_selector=""): - """Gets replicasets matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of replicasets. - - ``name_pattern``: - replicasets name pattern to check - - ``namespace``: - Namespace to check - """ - ret = self.v1.list_namespaced_replicasets(namespace, watch=False, label_selector=label_selector) - r = re.compile(name_pattern) - replicasets = [item for item in ret.items if r.match(item.metadata.name)] - return replicasets From a13813490a2071eb6ea7f13dbc08597a2baeaba3 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 19 Feb 2021 03:23:01 +0000 Subject: [PATCH 03/10] Added cluster healthcheck --- src/KubeLibrary/KubeLibrary.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index af2d9301..a47ee950 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -3,6 +3,8 @@ import ssl import urllib3 from kubernetes import client, config +import subprocess + from robot.api import logger # supressing SSL warnings when using self-signed certs From 2591c70e890cef1da91605974c7b0123bb808ce9 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 19 Feb 2021 04:59:56 +0000 Subject: [PATCH 04/10] fix for cluster health check --- src/KubeLibrary/KubeLibrary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index a47ee950..f3532621 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -3,7 +3,7 @@ import ssl import urllib3 from kubernetes import client, config -import subprocess +import requests from robot.api import logger From 793f8b92ea9d94506caec83c5fd75f0970eaa2ba Mon Sep 17 00:00:00 2001 From: root Date: Sun, 21 Feb 2021 14:15:41 +0000 Subject: [PATCH 05/10] updated as per comments --- testcases/healthcheck/healthcheck_kw.robot | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/testcases/healthcheck/healthcheck_kw.robot b/testcases/healthcheck/healthcheck_kw.robot index 08cf8ebc..9d71b665 100644 --- a/testcases/healthcheck/healthcheck_kw.robot +++ b/testcases/healthcheck/healthcheck_kw.robot @@ -11,5 +11,11 @@ Library KubeLibrary *** Keywords *** Healthcheck - ${output}= Get Healthcheck - Log \nHealthcheck ${output}: console=True + @{RESPONSE}= Get Healthcheck + Remove from List ${RESPONSE} -1 + Remove from List ${RESPONSE} -1 + FOR ${ELEMENT} IN @{RESPONSE} + Should Be True "ok" in """${ELEMENT}""" + log to console \n ${ELEMENT} + END + From c8da163d5deaa7e608f0342307723917422c27ef Mon Sep 17 00:00:00 2001 From: root Date: Sun, 21 Feb 2021 14:16:26 +0000 Subject: [PATCH 06/10] updated as per comments --- src/KubeLibrary/KubeLibrary.py | 109 ++++++++++++++++++++++++++------- 1 file changed, 87 insertions(+), 22 deletions(-) diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index f3532621..b9318983 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -3,8 +3,6 @@ import ssl import urllib3 from kubernetes import client, config -import requests - from robot.api import logger # supressing SSL warnings when using self-signed certs @@ -13,19 +11,27 @@ class KubeLibrary(object): """KubeLibrary is a Robot Framework test library for Kubernetes. + The approach taken by this library is to provide easy to access kubernetes objects representation that can be then accessed to define highlevel keywords for tests. + = Kubeconfigs = + By default ~/.kube/config is used. Kubeconfig location can also be passed by setting KUBECONFIG environment variable or as Library argument. + | ***** Settings ***** | Library KubeLibrary /path/to/kubeconfig + = In cluster execution = + If tests are supposed to be executed from within cluster, KubeLibrary can be configured to use standard token authentication. Just set incluster parameter to True. If True then kubeconfigs are not used, even if provided. + | ***** Settings ***** | Library KubeLibrary None True + """ def __init__(self, kube_config=None, incluster=False, cert_validation=True): """KubeLibrary can be configured with several optional arguments. @@ -67,6 +73,7 @@ def reload_config(self, kube_config=None, incluster=False, cert_validation=True) def k8s_api_ping(self): """Performs GET on /api/v1/ for simple check of API availability. + Returns tuple of (response data, response status, response headers). Can be used as prerequisite in tests. """ path_params = {} @@ -85,7 +92,9 @@ def k8s_api_ping(self): def get_namespaces(self, label_selector=""): """Gets a list of available namespaces. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of namespaces. """ ret = self.v1.list_namespace(watch=False, label_selector=label_selector) @@ -93,7 +102,9 @@ def get_namespaces(self, label_selector=""): def get_healthy_nodes_count(self, label_selector=""): """Counts node with KubeletReady and status True. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Can be used to check number of healthy nodes. Can be used as prerequisite in tests. """ ret = self.v1.list_node(watch=False, label_selector=label_selector) @@ -106,8 +117,11 @@ def get_healthy_nodes_count(self, label_selector=""): def get_pod_names_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets pod name matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of strings. + - ``name_pattern``: Pod name pattern to check - ``namespace``: @@ -119,8 +133,11 @@ def get_pod_names_in_namespace(self, name_pattern, namespace, label_selector="") def get_pods_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets pods matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of pods. + - ``name_pattern``: Pod name pattern to check - ``namespace``: @@ -133,7 +150,9 @@ def get_pods_in_namespace(self, name_pattern, namespace, label_selector=""): def get_pod_logs(self, name, namespace, container): """Gets container logs of given pod in given namespace. + Returns logs. + - ``name``: Pod name to check - ``namespace``: @@ -146,8 +165,11 @@ def get_pod_logs(self, name, namespace, container): def get_configmaps_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets configmaps matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of configmaps. + - ``name_pattern``: configmap name pattern to check - ``namespace``: @@ -160,8 +182,11 @@ def get_configmaps_in_namespace(self, name_pattern, namespace, label_selector="" def get_service_accounts_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets service accounts matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of service accounts. + - ``name_pattern``: Service Account name pattern to check - ``namespace``: @@ -174,8 +199,11 @@ def get_service_accounts_in_namespace(self, name_pattern, namespace, label_selec def get_deployments_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets deployments matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of deployments. + - ``name_pattern``: deployment name pattern to check - ``namespace``: @@ -188,8 +216,11 @@ def get_deployments_in_namespace(self, name_pattern, namespace, label_selector=" def get_jobs_in_namespace(self, name_pattern, namespace, label_selector=""): """Gets jobs matching pattern in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of jobs. + - ``name_pattern``: job name pattern to check - ``namespace``: @@ -200,23 +231,11 @@ def get_jobs_in_namespace(self, name_pattern, namespace, label_selector=""): jobs = [item for item in ret.items if r.match(item.metadata.name)] return jobs - def get_secrets_in_namespace(self, name_pattern, namespace, label_selector=""): - """Gets secrets matching pattern in given namespace. - Can be optionally filtered by label. e.g. label_selector=label_key=label_value - Returns list of secrets. - - ``name_pattern``: - secret name pattern to check - - ``namespace``: - Namespace to check - """ - ret = self.v1.list_namespaced_secret(namespace, watch=False, label_selector=label_selector) - r = re.compile(name_pattern) - secrets = [item for item in ret.items if r.match(item.metadata.name)] - return secrets - def filter_pods_names(self, pods): """Filter pod names for list of pods. + Returns list of strings. + - ``pods``: List of pods objects """ @@ -224,7 +243,9 @@ def filter_pods_names(self, pods): def filter_service_accounts_names(self, service_accounts): """Filter service accounts names for list of service accounts. + Returns list of strings. + - ``service_accounts``: List of service accounts objects """ @@ -232,7 +253,9 @@ def filter_service_accounts_names(self, service_accounts): def filter_pods_containers_by_name(self, pods, name_pattern): """Filters pods containers by name for given list of pods. + Returns lists of containers (flattens). + - ``pods``: List of pods objects """ @@ -246,7 +269,9 @@ def filter_pods_containers_by_name(self, pods, name_pattern): def filter_containers_images(self, containers): """Filters container images for given lists of containers. + Returns list of images. + - ``containers``: List of containers """ @@ -254,7 +279,9 @@ def filter_containers_images(self, containers): def filter_containers_resources(self, containers): """Filters container resources for given lists of containers. + Returns list of resources. + - ``containers``: List of containers """ @@ -262,7 +289,9 @@ def filter_containers_resources(self, containers): def filter_pods_containers_statuses_by_name(self, pods, name_pattern): """Filters pods containers statuses by container name for given list of pods. + Returns lists of containers statuses. + - ``pods``: List of pods objects """ @@ -276,6 +305,7 @@ def filter_pods_containers_statuses_by_name(self, pods, name_pattern): def get_pod_status_in_namespace(self, name, namespace): """Gets pod status in given namespace. + - ``name``: Name of pod. - ``namespace``: @@ -286,7 +316,9 @@ def get_pod_status_in_namespace(self, name, namespace): def assert_pod_has_labels(self, pod, labels_json): """Assert pod has labels. + Returns True/False + - ``pod``: Pod object. - ``labels_json``: @@ -309,7 +341,9 @@ def assert_pod_has_labels(self, pod, labels_json): def assert_pod_has_annotations(self, pod, annotations_json): """Assert pod has annotations. + Returns True/False + - ``pod``: Pod object. - ``annotations_json``: @@ -332,7 +366,9 @@ def assert_pod_has_annotations(self, pod, annotations_json): def assert_container_has_env_vars(self, container, env_vars_json): """Assert container has env vars. + Returns True/False + - ``container``: Container object. - ``env_var_json``: @@ -359,8 +395,11 @@ def assert_container_has_env_vars(self, container, env_vars_json): def get_services_in_namespace(self, namespace, label_selector=""): """Gets services in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of strings. + - ``namespace``: Namespace to check """ @@ -369,8 +408,11 @@ def get_services_in_namespace(self, namespace, label_selector=""): def get_service_details_in_namespace(self, name, namespace): """Gets service details in given namespace. + Returns Service object representation. Can be accessed using + | Should Be Equal As integers | ${service_details.spec.ports[0].port} | 8080 | + - ``name``: Name of service. - ``namespace``: @@ -381,8 +423,11 @@ def get_service_details_in_namespace(self, name, namespace): def get_endpoints_in_namespace(self, name, namespace): """Gets endpoint details in given namespace. + Returns Endpoint object representation. Can be accessed using + | Should Match | ${endpoint_details.subsets[0].addresses[0].target_ref.name} | pod-name-123456 | + - ``name``: Name of endpoint. - ``namespace``: @@ -393,8 +438,11 @@ def get_endpoints_in_namespace(self, name, namespace): def get_pvc_in_namespace(self, namespace, label_selector=""): """Gets pvcs in given namespace. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of strings. + - ``namespace``: Namespace to check """ @@ -403,8 +451,11 @@ def get_pvc_in_namespace(self, namespace, label_selector=""): def get_pvc_capacity(self, name, namespace): """Gets PVC details in given namespace. + Returns PVC object representation. Can be accessed using + | Should Be Equal As strings | ${pvc.status.capacity.storage} | 1Gi | + - ``name``: Name of PVC. - ``namespace``: @@ -415,7 +466,9 @@ def get_pvc_capacity(self, name, namespace): def get_kubelet_version(self, label_selector=""): """Gets list of kubelet versions on each node. + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + Returns list of strings. """ ret = self.v1.list_node(watch=False, label_selector=label_selector) @@ -423,7 +476,9 @@ def get_kubelet_version(self, label_selector=""): def create_service_account_in_namespace(self, namespace, body): """Creates service account in a namespace + Returns created service account + - ``body``: Service Account object. - ``namespace``: @@ -434,7 +489,10 @@ def create_service_account_in_namespace(self, namespace, body): def delete_service_account_in_namespace(self, name, namespace): """Deletes service account in a namespace + Returns V1status + + - ``name``: Service Account name - ``namespace``: @@ -444,9 +502,16 @@ def delete_service_account_in_namespace(self, name, namespace): return ret def get_healthcheck(self): - """check cluster leverl healthcheck - Can be used to verify the readiness/current status of the API server - """ - output = requests.get('https://localhost:6443/readyz?verbose=', verify = False) - logger.debug(output) - return output + path_params = {} + query_params = [] + header_params = {} + auth_settings = ['BearerToken'] + resp = self.v1.api_client.call_api('/readyz?verbose=', 'GET', + path_params, + query_params, + header_params, + response_type='str', + auth_settings=auth_settings, + async_req=False, + _return_http_data_only=False) + return resp From 61ead369168d3b04e6e538f118c0170217805988 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 22 Feb 2021 05:18:25 +0000 Subject: [PATCH 07/10] updated with FOR loop --- testcases/healthcheck/healthcheck_kw.robot | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/testcases/healthcheck/healthcheck_kw.robot b/testcases/healthcheck/healthcheck_kw.robot index 9d71b665..0808101c 100644 --- a/testcases/healthcheck/healthcheck_kw.robot +++ b/testcases/healthcheck/healthcheck_kw.robot @@ -12,10 +12,12 @@ Library KubeLibrary *** Keywords *** Healthcheck @{RESPONSE}= Get Healthcheck - Remove from List ${RESPONSE} -1 - Remove from List ${RESPONSE} -1 + FOR ${i} IN RANGE 2 + Remove from List ${RESPONSE} -1 + END + FOR ${ELEMENT} IN @{RESPONSE} Should Be True "ok" in """${ELEMENT}""" log to console \n ${ELEMENT} - END + END From c3ec9a499f34997d41f7e26971efbd8c06168b89 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 22 Feb 2021 08:21:15 +0000 Subject: [PATCH 08/10] updated comment section --- src/KubeLibrary/KubeLibrary.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index b9318983..d5f5f7bd 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -502,6 +502,11 @@ def delete_service_account_in_namespace(self, name, namespace): return ret def get_healthcheck(self): + """Checks cluster level healthcheck + Can be used to verify the readiness/current status of the API server + + Returns tuple of (response data, response status and response headers) + """ path_params = {} query_params = [] header_params = {} From 8ea428b524a64e36ca06a27e51ad7a57fe0a0550 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 22 Feb 2021 08:22:09 +0000 Subject: [PATCH 09/10] updated code --- testcases/healthcheck/healthcheck_kw.robot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testcases/healthcheck/healthcheck_kw.robot b/testcases/healthcheck/healthcheck_kw.robot index 0808101c..b34d023a 100644 --- a/testcases/healthcheck/healthcheck_kw.robot +++ b/testcases/healthcheck/healthcheck_kw.robot @@ -16,8 +16,8 @@ Healthcheck Remove from List ${RESPONSE} -1 END - FOR ${ELEMENT} IN @{RESPONSE} + @{ENDPOINTS} = Split String ${RESPONSE}[0] \n + FOR ${ELEMENT} IN @{ENDPOINTS} Should Be True "ok" in """${ELEMENT}""" - log to console \n ${ELEMENT} END From 81382af45c41acbfcb910073b3333e5007b9a0c1 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 22 Feb 2021 08:50:05 +0000 Subject: [PATCH 10/10] added secret --- src/KubeLibrary/KubeLibrary.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/KubeLibrary/KubeLibrary.py b/src/KubeLibrary/KubeLibrary.py index 20efd6bf..3c95bd0f 100755 --- a/src/KubeLibrary/KubeLibrary.py +++ b/src/KubeLibrary/KubeLibrary.py @@ -243,6 +243,23 @@ def get_jobs_in_namespace(self, name_pattern, namespace, label_selector=""): jobs = [item for item in ret.items if r.match(item.metadata.name)] return jobs + def get_secrets_in_namespace(self, name_pattern, namespace, label_selector=""): + """Gets secrets matching pattern in given namespace. + + Can be optionally filtered by label. e.g. label_selector=label_key=label_value + + Returns list of secrets. + + - ``name_pattern``: + secret name pattern to check + - ``namespace``: + Namespace to check + """ + ret = self.v1.list_namespaced_secret(namespace, watch=False, label_selector=label_selector) + r = re.compile(name_pattern) + secrets = [item for item in ret.items if r.match(item.metadata.name)] + return secrets + def filter_pods_names(self, pods): """Filter pod names for list of pods.