| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 1 | import pytest |
| 2 | |
| 3 | from si_tests import settings |
| 4 | from si_tests.clients import k8s as k8s_client |
| 5 | from si_tests.fixtures.kubectl import kcm_manager |
| 6 | |
| 7 | |
| 8 | @pytest.fixture |
| 9 | def ready_child_cluster(request, kcm_manager): |
| 10 | namespace, name = request.param |
| 11 | return namespace, name |
| 12 | |
| 13 | |
| 14 | def pytest_generate_tests(metafunc): |
| 15 | if "ready_child_cluster" in metafunc.fixturenames: |
| 16 | clds = get_ready_cluster_deployments(kcm_manager()) |
| 17 | metafunc.parametrize("ready_child_cluster", |
| 18 | range(len(clds)), indirect=True) |
| 19 | |
| 20 | |
| 21 | def get_ready_cluster_deployments(kcm_manager): |
| 22 | ready_clds = [] |
| 23 | clds = kcm_manager.list_all_clusterdeployments() |
| 24 | |
| 25 | for cld in clds: |
| 26 | conditions = cld.data.get("status", {}).get("conditions", []) |
| 27 | for cond in conditions: |
| 28 | if cond["type"] == "Ready" and cond["status"] == "True": |
| 29 | ready_clds.append((cld.namespace, cld.name)) |
| 30 | break |
| 31 | return ready_clds |
| 32 | |
| 33 | |
| Ievgeniia Zadorozhna | 2c05d96 | 2025-11-25 16:09:12 +0100 | [diff] [blame^] | 34 | def get_all_cluster_deployments(kcm_manager): |
| 35 | all_clds = [] |
| 36 | clds = kcm_manager.list_all_clusterdeployments() |
| 37 | |
| 38 | for cld in clds: |
| 39 | all_clds.append((cld.namespace, cld.name)) |
| 40 | return all_clds |
| 41 | |
| 42 | |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 43 | def check_cluster_deployment_exists(kcm_manager, namespace, name) -> bool: |
| 44 | clds = kcm_manager.list_all_clusterdeployments() |
| 45 | return any(cld.namespace == namespace and cld.name == name for cld in clds) |
| 46 | |
| 47 | |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 48 | def is_kof_installed(kcm_manager) -> bool: |
| 49 | # Checks if 'kof' ns is present at mothership |
| 50 | all_ns = kcm_manager.api.namespaces.list() |
| 51 | # If yes, checks if there is any *kof* named cld deployed |
| 52 | if "kof" in [n.name for n in all_ns]: |
| 53 | ready_cld_names = [cluster[1] for cluster in |
| 54 | get_ready_cluster_deployments(kcm_manager)] |
| 55 | if any("kof" in name for name in ready_cld_names): |
| 56 | return True |
| 57 | return False |
| 58 | |
| 59 | |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 60 | @pytest.mark.sanity |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 61 | def test_k0rdent_mgmt_object_is_ready(kcm_manager): |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 62 | assert kcm_manager.mgmt.ready == True,\ |
| 63 | f"Management 'kcm' object is not ready" |
| 64 | |
| 65 | |
| 66 | @pytest.mark.sanity |
| 67 | def test_cluster_deployments_are_ready(kcm_manager): |
| 68 | not_ready_clds = [] |
| 69 | clds = kcm_manager.list_all_clusterdeployments() |
| 70 | for cld in clds: |
| 71 | conditions = cld.data.get("status", {}).get("conditions", []) |
| 72 | for cond in conditions: |
| 73 | if cond["type"] == "Ready" and cond["status"] != "True": |
| 74 | not_ready_clds.append((cld.namespace, cld.name)) |
| 75 | break |
| 76 | assert not_ready_clds == [],\ |
| 77 | f"There are some cluster deployments not ready: {not_ready_clds}" |
| 78 | |
| 79 | |
| 80 | @pytest.mark.sanity |
| 81 | def test_provider_templates_are_valid(kcm_manager): |
| 82 | k8s = k8s_client.K8sCluster(kubeconfig=settings.KUBECONFIG_PATH) |
| 83 | provider_templates = k8s.k0rdent_provider_templates.list_raw().items |
| 84 | invalid_res = [] |
| 85 | for pt in provider_templates: |
| 86 | if not pt.status['valid']: |
| 87 | invalid_res.append({"name": pt.metadata.name, |
| 88 | "valid": pt.status['valid']}) |
| 89 | assert not invalid_res, f"Invalid provider templates found: {invalid_res}" |
| 90 | |
| 91 | |
| 92 | @pytest.mark.sanity |
| 93 | def test_cluster_templates_are_valid(kcm_manager): |
| 94 | k8s = k8s_client.K8sCluster(kubeconfig=settings.KUBECONFIG_PATH) |
| 95 | cluster_templates = k8s.k0rdent_cluster_templates.list_raw().items |
| 96 | invalid_res = [] |
| 97 | for ct in cluster_templates: |
| 98 | if not ct.status['valid']: |
| 99 | invalid_res.append({"name": ct.metadata.name, |
| 100 | "valid": ct.status['valid']}) |
| 101 | assert not invalid_res, f"Invalid cluster templates found: {invalid_res}" |
| 102 | |
| 103 | |
| 104 | @pytest.mark.sanity |
| 105 | def test_service_templates_are_valid(kcm_manager): |
| 106 | k8s = k8s_client.K8sCluster(kubeconfig=settings.KUBECONFIG_PATH) |
| 107 | service_templates = k8s.k0rdent_service_templates.list_raw().items |
| 108 | invalid_res = [] |
| 109 | for st in service_templates: |
| 110 | if not st.status['valid']: |
| 111 | invalid_res.append({"name": st.metadata.name, |
| 112 | "valid": st.status['valid']}) |
| 113 | assert not invalid_res, f"Invalid service templates found: {invalid_res}" |
| 114 | |
| 115 | |
| 116 | @pytest.mark.sanity |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 117 | def test_k0rdent_mgmt_pods_are_ready( |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 118 | kcm_manager, namespaces=None, allowed_phases=None): |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 119 | if namespaces is None: |
| 120 | namespaces = ["kcm-system", "projectsveltos"] |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 121 | if is_kof_installed(kcm_manager): |
| 122 | namespaces.append("kof") |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 123 | if allowed_phases is None: |
| 124 | allowed_phases = ("Running", "Succeeded") |
| 125 | |
| 126 | for ns in namespaces: |
| 127 | pods = kcm_manager.api.pods.list(namespace=ns) |
| 128 | assert pods, f"No pods found in namespace '{ns}'" |
| 129 | |
| 130 | for pod in pods: |
| 131 | phase = pod.data["status"]["phase"] |
| 132 | assert phase in allowed_phases, ( |
| 133 | f"Pod '{pod.name}' in namespace '{ns}' is in phase '{phase}', " |
| 134 | f"expected one of {allowed_phases}" |
| 135 | ) |
| 136 | |
| 137 | |
| 138 | @pytest.mark.sanity |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 139 | def test_k0rdent_mgmt_nodes_are_ready(kcm_manager): |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 140 | nodes = kcm_manager.api.nodes.list() |
| 141 | assert nodes, "No nodes found in the cluster" |
| 142 | |
| 143 | for node in nodes: |
| 144 | conditions = node.data["status"]["conditions"] |
| 145 | ready_condition = next((c for c in conditions if c["type"] == "Ready"), |
| 146 | None) |
| 147 | assert ready_condition is not None,\ |
| 148 | f"Node '{node.name}' has no Ready condition" |
| 149 | assert ready_condition["status"] == "True",\ |
| 150 | f"Node '{node.name}' is not Ready" |
| 151 | |
| 152 | |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 153 | @pytest.mark.sanity |
| 154 | def test_certificates_are_ready(kcm_manager): |
| 155 | certs = kcm_manager.api.api_custom.list_cluster_custom_object( |
| 156 | group="cert-manager.io", |
| 157 | version="v1", |
| 158 | plural="certificates", |
| 159 | ).get("items", []) |
| 160 | assert certs, "No certificates found in the cluster" |
| 161 | |
| 162 | not_ready = [] |
| 163 | for cert in certs: |
| 164 | name = cert["metadata"]["name"] |
| 165 | namespace = cert["metadata"]["namespace"] |
| 166 | conditions = cert.get("status", {}).get("conditions", []) |
| 167 | ready_condition = next((c for c in conditions if c["type"] == "Ready"), |
| 168 | None) |
| 169 | |
| 170 | if not ready_condition or ready_condition.get("status") != "True": |
| 171 | not_ready.append(f"{namespace}/{name}") |
| 172 | |
| 173 | assert not not_ready, f"Some certificates are not Ready: {not_ready}" |
| 174 | |
| 175 | |
| 176 | @pytest.mark.sanity |
| 177 | def test_cluster_summaries_features_are_provisioned(kcm_manager): |
| 178 | cluster_summaries = kcm_manager.api.api_custom.list_cluster_custom_object( |
| 179 | group="config.projectsveltos.io", |
| 180 | version="v1beta1", |
| 181 | plural="clustersummaries", |
| 182 | ).get("items", []) |
| 183 | |
| 184 | not_provisioned = [] |
| 185 | for summary in cluster_summaries: |
| 186 | name = summary["metadata"]["name"] |
| 187 | namespace = summary["metadata"].get("namespace", "") |
| 188 | summaries = summary.get("status", {}).get("featureSummaries", []) |
| 189 | |
| 190 | for feature in summaries: |
| 191 | feature_id = feature.get("featureID") |
| 192 | status = feature.get("status") |
| Ievgeniia Zadorozhna | 234298e | 2025-11-24 15:38:42 +0100 | [diff] [blame] | 193 | failureMessage = feature.get("failureMessage") |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 194 | if status != "Provisioned": |
| 195 | not_provisioned.append( |
| Ievgeniia Zadorozhna | 234298e | 2025-11-24 15:38:42 +0100 | [diff] [blame] | 196 | f"{namespace}/{name} -> {feature_id}: {status}" |
| 197 | f" -> failureMessage: {failureMessage}") |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 198 | |
| 199 | assert not not_provisioned, ( |
| 200 | "Some ClusterSummaries have non-Provisioned features:\n" |
| 201 | + "\n".join(not_provisioned) |
| 202 | ) |
| 203 | |
| 204 | |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 205 | @pytest.mark.sanity_targeted |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 206 | def test_target_child_cluster_is_ready(kcm_manager): |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 207 | ns = kcm_manager.get_namespace(settings.TARGET_NAMESPACE) |
| 208 | cld = ns.get_cluster_deployment(settings.TARGET_CLD) |
| 209 | if not check_cluster_deployment_exists( |
| 210 | kcm_manager, settings.TARGET_NAMESPACE, settings.TARGET_CLD): |
| 211 | pytest.skip(f"Target cluster deployment '{cld.name}' is not found in " |
| 212 | f"namespace '{settings.TARGET_NAMESPACE}'. Please check " |
| 213 | f"TARGET_NAMESPACE and TARGET_CLD env vars.") |
| Ievgeniia Zadorozhna | 234298e | 2025-11-24 15:38:42 +0100 | [diff] [blame] | 214 | cld.check.check_cluster_readiness(timeout=30) |
| 215 | cld.check.check_k8s_pods(timeout=30) |
| 216 | cld.check.check_k8s_nodes(timeout=30) |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 217 | |
| 218 | |
| 219 | @pytest.mark.sanity |
| Ievgeniia Zadorozhna | 7dabab8 | 2025-10-24 18:37:18 +0200 | [diff] [blame] | 220 | def test_child_clusters_are_ready(kcm_manager, subtests): |
| Ievgeniia Zadorozhna | 2c05d96 | 2025-11-25 16:09:12 +0100 | [diff] [blame^] | 221 | all_clds = get_all_cluster_deployments(kcm_manager) |
| 222 | if not all_clds: |
| 223 | pytest.skip("No child cluster deployments found.") |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 224 | |
| Ievgeniia Zadorozhna | 2c05d96 | 2025-11-25 16:09:12 +0100 | [diff] [blame^] | 225 | for namespace, cld_name in all_clds: |
| Ievgeniia Zadorozhna | 86ab37a | 2025-09-11 12:58:49 +0200 | [diff] [blame] | 226 | label = f"{cld_name} ({namespace})" |
| 227 | with subtests.test(cluster=label): |
| 228 | ns = kcm_manager.get_namespace(namespace) |
| 229 | cld = ns.get_cluster_deployment(cld_name) |
| 230 | |
| Ievgeniia Zadorozhna | 234298e | 2025-11-24 15:38:42 +0100 | [diff] [blame] | 231 | cld.check.check_cluster_readiness(timeout=30) |
| 232 | cld.check.check_k8s_pods(timeout=30) |
| 233 | cld.check.check_k8s_nodes(timeout=30) |