krkn-lib 5.0.1__tar.gz → 5.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/PKG-INFO +1 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/pyproject.toml +1 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/krkn_kubernetes.py +226 -93
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/pods_monitor_pool.py +14 -3
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/templates/node_exec_pod.j2 +6 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/k8s/models.py +9 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/prometheus/krkn_prometheus.py +1 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/telemetry/k8s/krkn_telemetry_kubernetes.py +0 -2
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/base_test.py +7 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_check.py +2 -3
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_create.py +3 -5
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_delete.py +2 -3
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_get.py +104 -5
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_list.py +13 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_monitor.py +168 -137
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_pods_monitor_pool.py +7 -3
- krkn_lib-5.1.0/src/krkn_lib/tests/test_krkn_prometheus.py +234 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_telemetry_kubernetes.py +57 -51
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_version.py +1 -1
- krkn_lib-5.0.1/src/krkn_lib/tests/test_krkn_prometheus.py +0 -229
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/LICENSE +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/README.md +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/elastic/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/elastic/krkn_elastic.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/templates/hog_pod.j2 +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/templates/service_hijacking_config_map.j2 +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/templates/service_hijacking_pod.j2 +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/k8s/templates/syn_flood_pod.j2 +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/elastic/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/elastic/models.py +1 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/k8s/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/krkn/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/krkn/models.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/telemetry/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/models/telemetry/models.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/ocp/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/ocp/krkn_openshift.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/prometheus/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/telemetry/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/telemetry/k8s/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/telemetry/ocp/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/telemetry/ocp/krkn_telemetry_openshift.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_elastic.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_elastic_models.py +1 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_exec.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_misc.py +2 -2
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_kubernetes_models.py +1 -1
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_openshift.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_telemetry_models.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_krkn_telemetry_openshift.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/tests/test_utils.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/utils/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/utils/functions.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/utils/safe_logger.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/version/__init__.py +0 -0
- {krkn_lib-5.0.1 → krkn_lib-5.1.0}/src/krkn_lib/version/version.py +0 -0
|
@@ -529,7 +529,10 @@ class KrknKubernetes:
|
|
|
529
529
|
return managedclusters
|
|
530
530
|
|
|
531
531
|
def list_pods(
|
|
532
|
-
self,
|
|
532
|
+
self,
|
|
533
|
+
namespace: str,
|
|
534
|
+
label_selector: str = None,
|
|
535
|
+
field_selector: str = None,
|
|
533
536
|
) -> list[str]:
|
|
534
537
|
"""
|
|
535
538
|
List pods in the given namespace
|
|
@@ -537,11 +540,15 @@ class KrknKubernetes:
|
|
|
537
540
|
:param namespace: namespace to search for pods
|
|
538
541
|
:param label_selector: filter by label selector
|
|
539
542
|
(optional default `None`)
|
|
543
|
+
:param field_selector: filter results by config details
|
|
544
|
+
select only running pods by setting "status.phase=Running"
|
|
540
545
|
:return: a list of pod names
|
|
541
546
|
"""
|
|
542
547
|
pods = []
|
|
543
548
|
try:
|
|
544
|
-
ret = self.get_all_pod_info(
|
|
549
|
+
ret = self.get_all_pod_info(
|
|
550
|
+
namespace, label_selector, field_selector
|
|
551
|
+
)
|
|
545
552
|
except ApiException as e:
|
|
546
553
|
logging.error(
|
|
547
554
|
"Exception when calling list_pods: %s\n",
|
|
@@ -734,12 +741,16 @@ class KrknKubernetes:
|
|
|
734
741
|
logging.error("Failed to get deployment data %s", str(e))
|
|
735
742
|
raise e
|
|
736
743
|
|
|
737
|
-
def get_all_pods(
|
|
744
|
+
def get_all_pods(
|
|
745
|
+
self, label_selector: str = None, field_selector: str = None
|
|
746
|
+
) -> list[[str, str]]:
|
|
738
747
|
"""
|
|
739
748
|
Return a list of tuples containing pod name [0] and namespace [1]
|
|
740
749
|
|
|
741
750
|
:param label_selector: filter by label_selector
|
|
742
751
|
(optional default `None`)
|
|
752
|
+
:param field_selector: filter results by config details
|
|
753
|
+
select only running pods by setting "status.phase=Running"
|
|
743
754
|
:return: list of tuples pod,namespace
|
|
744
755
|
"""
|
|
745
756
|
pods = []
|
|
@@ -749,12 +760,14 @@ class KrknKubernetes:
|
|
|
749
760
|
pretty=True,
|
|
750
761
|
label_selector=label_selector,
|
|
751
762
|
limit=self.request_chunk_size,
|
|
763
|
+
field_selector=field_selector,
|
|
752
764
|
)
|
|
753
765
|
else:
|
|
754
766
|
ret = self.list_continue_helper(
|
|
755
767
|
self.cli.list_pod_for_all_namespaces,
|
|
756
768
|
pretty=True,
|
|
757
769
|
limit=self.request_chunk_size,
|
|
770
|
+
field_selector=field_selector,
|
|
758
771
|
)
|
|
759
772
|
for ret_list in ret:
|
|
760
773
|
for pod in ret_list.items:
|
|
@@ -851,12 +864,18 @@ class KrknKubernetes:
|
|
|
851
864
|
|
|
852
865
|
# Outputs a json blob with informataion about all pods in a given namespace
|
|
853
866
|
def get_all_pod_info(
|
|
854
|
-
self,
|
|
867
|
+
self,
|
|
868
|
+
namespace: str = "default",
|
|
869
|
+
label_selector: str = None,
|
|
870
|
+
field_selector: str = None,
|
|
855
871
|
) -> list[str]:
|
|
856
872
|
"""
|
|
857
873
|
Get details of all pods in a namespace
|
|
858
874
|
|
|
859
875
|
:param namespace: namespace (optional default `default`)
|
|
876
|
+
:param field_selector: filter results by config details
|
|
877
|
+
select only running pods by setting "status.phase=Running"
|
|
878
|
+
|
|
860
879
|
:return list of pod details
|
|
861
880
|
"""
|
|
862
881
|
try:
|
|
@@ -867,12 +886,14 @@ class KrknKubernetes:
|
|
|
867
886
|
pretty=True,
|
|
868
887
|
label_selector=label_selector,
|
|
869
888
|
limit=self.request_chunk_size,
|
|
889
|
+
field_selector=field_selector,
|
|
870
890
|
)
|
|
871
891
|
else:
|
|
872
892
|
ret = self.list_continue_helper(
|
|
873
893
|
self.cli.list_namespaced_pod,
|
|
874
894
|
namespace,
|
|
875
895
|
limit=self.request_chunk_size,
|
|
896
|
+
field_selector=field_selector,
|
|
876
897
|
)
|
|
877
898
|
except ApiException as e:
|
|
878
899
|
logging.error(
|
|
@@ -1137,8 +1158,18 @@ class KrknKubernetes:
|
|
|
1137
1158
|
:param namespace: namespace (optional default `default`)
|
|
1138
1159
|
"""
|
|
1139
1160
|
try:
|
|
1161
|
+
starting_creation_timestamp = self.cli.read_namespaced_pod(
|
|
1162
|
+
name=name, namespace=namespace
|
|
1163
|
+
).metadata.creation_timestamp
|
|
1140
1164
|
self.cli.delete_namespaced_pod(name=name, namespace=namespace)
|
|
1165
|
+
|
|
1141
1166
|
while self.cli.read_namespaced_pod(name=name, namespace=namespace):
|
|
1167
|
+
|
|
1168
|
+
ending_creation_timestamp = self.cli.read_namespaced_pod(
|
|
1169
|
+
name=name, namespace=namespace
|
|
1170
|
+
).metadata.creation_timestamp
|
|
1171
|
+
if starting_creation_timestamp != ending_creation_timestamp:
|
|
1172
|
+
break
|
|
1142
1173
|
time.sleep(1)
|
|
1143
1174
|
except ApiException as e:
|
|
1144
1175
|
if e.status == 404:
|
|
@@ -1481,7 +1512,9 @@ class KrknKubernetes:
|
|
|
1481
1512
|
except Exception as e:
|
|
1482
1513
|
logging.error("Error trying to apply_yaml" + str(e))
|
|
1483
1514
|
|
|
1484
|
-
def get_pod_info(
|
|
1515
|
+
def get_pod_info(
|
|
1516
|
+
self, name: str, namespace: str = "default"
|
|
1517
|
+
) -> Optional[Pod]:
|
|
1485
1518
|
"""
|
|
1486
1519
|
Retrieve information about a specific pod
|
|
1487
1520
|
|
|
@@ -1491,62 +1524,70 @@ class KrknKubernetes:
|
|
|
1491
1524
|
kubectl command in the given format if the pod exists.
|
|
1492
1525
|
Returns None if the pod doesn't exist
|
|
1493
1526
|
"""
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
if pod_exists:
|
|
1527
|
+
try:
|
|
1528
|
+
pod_info = None
|
|
1497
1529
|
response = self.cli.read_namespaced_pod(
|
|
1498
1530
|
name=name, namespace=namespace, pretty="true"
|
|
1499
1531
|
)
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1532
|
+
if response:
|
|
1533
|
+
container_list = []
|
|
1534
|
+
|
|
1535
|
+
# Create a list of containers present in the pod
|
|
1536
|
+
for container in response.spec.containers:
|
|
1537
|
+
volume_mount_list = []
|
|
1538
|
+
for volume_mount in container.volume_mounts:
|
|
1539
|
+
volume_mount_list.append(
|
|
1540
|
+
VolumeMount(
|
|
1541
|
+
name=volume_mount.name,
|
|
1542
|
+
mountPath=volume_mount.mount_path,
|
|
1543
|
+
)
|
|
1544
|
+
)
|
|
1545
|
+
container_list.append(
|
|
1546
|
+
Container(
|
|
1547
|
+
name=container.name,
|
|
1548
|
+
image=container.image,
|
|
1549
|
+
volumeMounts=volume_mount_list,
|
|
1510
1550
|
)
|
|
1511
1551
|
)
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1552
|
+
|
|
1553
|
+
for i, container in enumerate(
|
|
1554
|
+
response.status.container_statuses
|
|
1555
|
+
):
|
|
1556
|
+
container_list[i].ready = container.ready
|
|
1557
|
+
container_list[i].containerId = (
|
|
1558
|
+
response.status.container_statuses[i].container_id
|
|
1517
1559
|
)
|
|
1518
|
-
)
|
|
1519
1560
|
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1561
|
+
# Create a list of volumes associated with the pod
|
|
1562
|
+
volume_list = []
|
|
1563
|
+
for volume in response.spec.volumes:
|
|
1564
|
+
volume_name = volume.name
|
|
1565
|
+
pvc_name = (
|
|
1566
|
+
volume.persistent_volume_claim.claim_name
|
|
1567
|
+
if volume.persistent_volume_claim is not None
|
|
1568
|
+
else None
|
|
1569
|
+
)
|
|
1570
|
+
volume_list.append(
|
|
1571
|
+
Volume(name=volume_name, pvcName=pvc_name)
|
|
1572
|
+
)
|
|
1573
|
+
|
|
1574
|
+
# Create the Pod data class object
|
|
1575
|
+
pod_info = Pod(
|
|
1576
|
+
name=response.metadata.name,
|
|
1577
|
+
podIP=response.status.pod_ip,
|
|
1578
|
+
namespace=response.metadata.namespace,
|
|
1579
|
+
containers=container_list,
|
|
1580
|
+
nodeName=response.spec.node_name,
|
|
1581
|
+
volumes=volume_list,
|
|
1582
|
+
status=response.status.phase,
|
|
1583
|
+
creation_timestamp=response.metadata.creation_timestamp,
|
|
1531
1584
|
)
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
# Create the Pod data class object
|
|
1535
|
-
pod_info = Pod(
|
|
1536
|
-
name=response.metadata.name,
|
|
1537
|
-
podIP=response.status.pod_ip,
|
|
1538
|
-
namespace=response.metadata.namespace,
|
|
1539
|
-
containers=container_list,
|
|
1540
|
-
nodeName=response.spec.node_name,
|
|
1541
|
-
volumes=volume_list,
|
|
1542
|
-
status=response.status.phase,
|
|
1543
|
-
)
|
|
1544
|
-
return pod_info
|
|
1545
|
-
else:
|
|
1585
|
+
except Exception:
|
|
1546
1586
|
logging.error(
|
|
1547
1587
|
"Pod '%s' doesn't exist in namespace '%s'", name, namespace
|
|
1548
1588
|
)
|
|
1549
1589
|
return None
|
|
1590
|
+
return pod_info
|
|
1550
1591
|
|
|
1551
1592
|
def check_if_namespace_exists(self, name: str) -> bool:
|
|
1552
1593
|
"""
|
|
@@ -2599,24 +2640,21 @@ class KrknKubernetes:
|
|
|
2599
2640
|
)
|
|
2600
2641
|
return None
|
|
2601
2642
|
|
|
2602
|
-
def select_pods_by_label(
|
|
2643
|
+
def select_pods_by_label(
|
|
2644
|
+
self, label_selector: str, field_selector: str = None
|
|
2645
|
+
) -> list[(str, str)]:
|
|
2603
2646
|
"""
|
|
2604
2647
|
Selects the pods identified by a label_selector
|
|
2605
2648
|
|
|
2606
2649
|
:param label_selector: a label selector string
|
|
2607
2650
|
in the format "key=value"
|
|
2608
|
-
:param
|
|
2609
|
-
|
|
2651
|
+
:param field_selector: filter results by config details
|
|
2652
|
+
select only running pods by setting "status.phase=Running"
|
|
2610
2653
|
:return: a list of pod_name and namespace tuples
|
|
2611
2654
|
"""
|
|
2612
|
-
pods_and_namespaces = self.get_all_pods(label_selector)
|
|
2655
|
+
pods_and_namespaces = self.get_all_pods(label_selector, field_selector)
|
|
2613
2656
|
pods_and_namespaces = [(pod[0], pod[1]) for pod in pods_and_namespaces]
|
|
2614
|
-
|
|
2615
|
-
pods_and_namespaces = [
|
|
2616
|
-
pod
|
|
2617
|
-
for pod in pods_and_namespaces
|
|
2618
|
-
if not self.is_pod_terminating(pod[0], pod[1])
|
|
2619
|
-
]
|
|
2657
|
+
|
|
2620
2658
|
return pods_and_namespaces
|
|
2621
2659
|
|
|
2622
2660
|
def select_service_by_label(
|
|
@@ -2648,7 +2686,10 @@ class KrknKubernetes:
|
|
|
2648
2686
|
return selected_services
|
|
2649
2687
|
|
|
2650
2688
|
def select_pods_by_name_pattern_and_namespace_pattern(
|
|
2651
|
-
self,
|
|
2689
|
+
self,
|
|
2690
|
+
pod_name_pattern: str,
|
|
2691
|
+
namespace_pattern: str,
|
|
2692
|
+
field_selector: str = None,
|
|
2652
2693
|
) -> list[(str, str)]:
|
|
2653
2694
|
"""
|
|
2654
2695
|
Selects the pods identified by a namespace_pattern
|
|
@@ -2658,6 +2699,8 @@ class KrknKubernetes:
|
|
|
2658
2699
|
:param namespace_pattern: a namespace pattern to match
|
|
2659
2700
|
:param max_timeout: the maximum time in seconds to wait
|
|
2660
2701
|
before considering the pod "not recovered" after the Chaos
|
|
2702
|
+
:param field_selector: filter results by config details
|
|
2703
|
+
select only running pods by setting "status.phase=Running"
|
|
2661
2704
|
:return: a list of pod_name and namespace tuples
|
|
2662
2705
|
"""
|
|
2663
2706
|
namespace_re = re.compile(namespace_pattern)
|
|
@@ -2666,20 +2709,18 @@ class KrknKubernetes:
|
|
|
2666
2709
|
pods_and_namespaces = []
|
|
2667
2710
|
for namespace in namespaces:
|
|
2668
2711
|
if namespace_re.match(namespace):
|
|
2669
|
-
pods = self.list_pods(namespace)
|
|
2712
|
+
pods = self.list_pods(namespace, field_selector=field_selector)
|
|
2670
2713
|
for pod in pods:
|
|
2671
2714
|
if podname_re.match(pod):
|
|
2672
2715
|
pods_and_namespaces.append((pod, namespace))
|
|
2673
|
-
|
|
2674
|
-
pods_and_namespaces = [
|
|
2675
|
-
(pod[0], pod[1])
|
|
2676
|
-
for pod in pods_and_namespaces
|
|
2677
|
-
if not self.is_pod_terminating(pod[0], pod[1])
|
|
2678
|
-
]
|
|
2716
|
+
|
|
2679
2717
|
return pods_and_namespaces
|
|
2680
2718
|
|
|
2681
2719
|
def select_pods_by_namespace_pattern_and_label(
|
|
2682
|
-
self,
|
|
2720
|
+
self,
|
|
2721
|
+
namespace_pattern: str,
|
|
2722
|
+
label_selector: str,
|
|
2723
|
+
field_selector: str = None,
|
|
2683
2724
|
) -> list[(str, str)]:
|
|
2684
2725
|
"""
|
|
2685
2726
|
Selects the pods identified by a label_selector
|
|
@@ -2688,20 +2729,16 @@ class KrknKubernetes:
|
|
|
2688
2729
|
:param namespace_pattern: a namespace pattern to match
|
|
2689
2730
|
:param label_selector: a label selector string
|
|
2690
2731
|
in the format "key=value"
|
|
2691
|
-
:param
|
|
2692
|
-
|
|
2732
|
+
:param field_selector: filter results by config details
|
|
2733
|
+
select only running pods by setting "status.phase=Running"
|
|
2693
2734
|
:return: a list of pod_name and namespace tuples
|
|
2694
2735
|
"""
|
|
2695
2736
|
namespace_re = re.compile(namespace_pattern)
|
|
2696
|
-
pods_and_namespaces = self.get_all_pods(label_selector)
|
|
2697
|
-
pods_and_namespaces = [
|
|
2698
|
-
pod for pod in pods_and_namespaces if namespace_re.match(pod[1])
|
|
2699
|
-
]
|
|
2700
|
-
# select only running pods
|
|
2737
|
+
pods_and_namespaces = self.get_all_pods(label_selector, field_selector)
|
|
2701
2738
|
pods_and_namespaces = [
|
|
2702
2739
|
(pod[0], pod[1])
|
|
2703
2740
|
for pod in pods_and_namespaces
|
|
2704
|
-
if
|
|
2741
|
+
if namespace_re.match(pod[1])
|
|
2705
2742
|
]
|
|
2706
2743
|
return pods_and_namespaces
|
|
2707
2744
|
|
|
@@ -2709,6 +2746,7 @@ class KrknKubernetes:
|
|
|
2709
2746
|
self,
|
|
2710
2747
|
label_selector: str,
|
|
2711
2748
|
pods_and_namespaces: list[(str, str)],
|
|
2749
|
+
field_selector: str = None,
|
|
2712
2750
|
max_timeout: int = 30,
|
|
2713
2751
|
event: threading.Event = None,
|
|
2714
2752
|
) -> PodsMonitorThread:
|
|
@@ -2726,6 +2764,8 @@ class KrknKubernetes:
|
|
|
2726
2764
|
:param pods_and_namespaces: the list of pods collected
|
|
2727
2765
|
by `select_pods_by_label` against which the changes
|
|
2728
2766
|
in the pods state is monitored
|
|
2767
|
+
:param field_selector: filter results by config details
|
|
2768
|
+
select only running pods by setting "status.phase=Running"
|
|
2729
2769
|
:param max_timeout: the expected time the pods should take
|
|
2730
2770
|
to recover. If the killed pods are replaced in this time frame,
|
|
2731
2771
|
but they didn't reach the Ready State, they will be marked as
|
|
@@ -2747,6 +2787,7 @@ class KrknKubernetes:
|
|
|
2747
2787
|
max_timeout=max_timeout,
|
|
2748
2788
|
pods_status=pods_status,
|
|
2749
2789
|
label_selector=label_selector,
|
|
2790
|
+
field_selector=field_selector,
|
|
2750
2791
|
event=event,
|
|
2751
2792
|
)
|
|
2752
2793
|
|
|
@@ -2755,6 +2796,7 @@ class KrknKubernetes:
|
|
|
2755
2796
|
pod_name_pattern: str,
|
|
2756
2797
|
namespace_pattern: str,
|
|
2757
2798
|
pods_and_namespaces: list[(str, str)],
|
|
2799
|
+
field_selector: str = None,
|
|
2758
2800
|
max_timeout=30,
|
|
2759
2801
|
event: threading.Event = None,
|
|
2760
2802
|
) -> PodsMonitorThread:
|
|
@@ -2778,6 +2820,8 @@ class KrknKubernetes:
|
|
|
2778
2820
|
:param pods_and_namespaces: the list of pods collected by
|
|
2779
2821
|
`select_pods_by_name_pattern_and_namespace_pattern` against
|
|
2780
2822
|
which the changes in the pods state is monitored
|
|
2823
|
+
:param field_selector: filter results by config details
|
|
2824
|
+
select only running pods by setting "status.phase=Running"
|
|
2781
2825
|
:param max_timeout: the expected time the pods should take to
|
|
2782
2826
|
recover. If the killed pods are replaced in this time frame,
|
|
2783
2827
|
but they didn't reach the Ready State, they will be marked as
|
|
@@ -2798,6 +2842,7 @@ class KrknKubernetes:
|
|
|
2798
2842
|
pods_and_namespaces=pods_and_namespaces,
|
|
2799
2843
|
max_timeout=max_timeout,
|
|
2800
2844
|
pods_status=pods_status,
|
|
2845
|
+
field_selector=field_selector,
|
|
2801
2846
|
name_pattern=pod_name_pattern,
|
|
2802
2847
|
namespace_pattern=namespace_pattern,
|
|
2803
2848
|
event=event,
|
|
@@ -2808,6 +2853,7 @@ class KrknKubernetes:
|
|
|
2808
2853
|
namespace_pattern: str,
|
|
2809
2854
|
label_selector: str,
|
|
2810
2855
|
pods_and_namespaces: list[(str, str)],
|
|
2856
|
+
field_selector: str = None,
|
|
2811
2857
|
max_timeout=30,
|
|
2812
2858
|
event: threading.Event = None,
|
|
2813
2859
|
) -> PodsMonitorThread:
|
|
@@ -2830,6 +2876,8 @@ class KrknKubernetes:
|
|
|
2830
2876
|
:param pods_and_namespaces: the list of pods collected by
|
|
2831
2877
|
`select_pods_by_name_pattern_and_namespace_pattern` against
|
|
2832
2878
|
which the changes in the pods state is monitored
|
|
2879
|
+
:param field_selector: filter results by config details
|
|
2880
|
+
select only running pods by setting "status.phase=Running"
|
|
2833
2881
|
:param max_timeout: the expected time the pods should take to recover.
|
|
2834
2882
|
If the killed pods are replaced in this time frame, but they
|
|
2835
2883
|
didn't reach the Ready State, they will be marked as unrecovered.
|
|
@@ -2851,6 +2899,7 @@ class KrknKubernetes:
|
|
|
2851
2899
|
max_timeout=max_timeout,
|
|
2852
2900
|
pods_status=pods_status,
|
|
2853
2901
|
label_selector=label_selector,
|
|
2902
|
+
field_selector=field_selector,
|
|
2854
2903
|
namespace_pattern=namespace_pattern,
|
|
2855
2904
|
event=event,
|
|
2856
2905
|
)
|
|
@@ -2861,6 +2910,7 @@ class KrknKubernetes:
|
|
|
2861
2910
|
pods_status: PodsStatus,
|
|
2862
2911
|
max_timeout: int,
|
|
2863
2912
|
label_selector: str = None,
|
|
2913
|
+
field_selector: str = None,
|
|
2864
2914
|
pod_name: str = None,
|
|
2865
2915
|
namespace_pattern: str = None,
|
|
2866
2916
|
name_pattern: str = None,
|
|
@@ -2873,6 +2923,7 @@ class KrknKubernetes:
|
|
|
2873
2923
|
pods_status=pods_status,
|
|
2874
2924
|
max_timeout=max_timeout,
|
|
2875
2925
|
label_selector=label_selector,
|
|
2926
|
+
field_selector=field_selector,
|
|
2876
2927
|
pod_name=pod_name,
|
|
2877
2928
|
namespace_pattern=namespace_pattern,
|
|
2878
2929
|
name_pattern=name_pattern,
|
|
@@ -2887,6 +2938,7 @@ class KrknKubernetes:
|
|
|
2887
2938
|
pods_status: PodsStatus,
|
|
2888
2939
|
max_timeout: int,
|
|
2889
2940
|
label_selector: str = None,
|
|
2941
|
+
field_selector: str = None,
|
|
2890
2942
|
pod_name: str = None,
|
|
2891
2943
|
namespace_pattern: str = None,
|
|
2892
2944
|
name_pattern: str = None,
|
|
@@ -2906,6 +2958,7 @@ class KrknKubernetes:
|
|
|
2906
2958
|
select_method = partial(
|
|
2907
2959
|
self.select_pods_by_label,
|
|
2908
2960
|
label_selector=label_selector,
|
|
2961
|
+
field_selector=field_selector,
|
|
2909
2962
|
)
|
|
2910
2963
|
elif (
|
|
2911
2964
|
name_pattern
|
|
@@ -2917,6 +2970,7 @@ class KrknKubernetes:
|
|
|
2917
2970
|
self.select_pods_by_name_pattern_and_namespace_pattern,
|
|
2918
2971
|
pod_name_pattern=name_pattern,
|
|
2919
2972
|
namespace_pattern=namespace_pattern,
|
|
2973
|
+
field_selector=field_selector,
|
|
2920
2974
|
)
|
|
2921
2975
|
elif (
|
|
2922
2976
|
namespace_pattern
|
|
@@ -2928,6 +2982,7 @@ class KrknKubernetes:
|
|
|
2928
2982
|
self.select_pods_by_namespace_pattern_and_label,
|
|
2929
2983
|
namespace_pattern=namespace_pattern,
|
|
2930
2984
|
label_selector=label_selector,
|
|
2985
|
+
field_selector=field_selector,
|
|
2931
2986
|
)
|
|
2932
2987
|
else:
|
|
2933
2988
|
pods_status.error = (
|
|
@@ -2944,17 +2999,19 @@ class KrknKubernetes:
|
|
|
2944
2999
|
time_offset = time.time() - start_time
|
|
2945
3000
|
remaining_time = max_timeout - time_offset
|
|
2946
3001
|
current_pods_and_namespaces = select_method()
|
|
2947
|
-
|
|
2948
3002
|
# no pods have been killed or pods have been killed and
|
|
2949
3003
|
# respawned with the same names
|
|
2950
3004
|
if set(pods_and_namespaces) == set(current_pods_and_namespaces):
|
|
2951
3005
|
for pod in current_pods_and_namespaces:
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
3006
|
+
|
|
3007
|
+
pod_info = self.get_pod_info(pod[0], pod[1])
|
|
3008
|
+
# for pod_info in pod_list_info:
|
|
3009
|
+
if pod_info:
|
|
3010
|
+
pod_creation_timestamp = (
|
|
3011
|
+
pod_info.creation_timestamp.timestamp()
|
|
3012
|
+
)
|
|
3013
|
+
if start_time < pod_creation_timestamp:
|
|
3014
|
+
missing_pods.add(pod)
|
|
2958
3015
|
pods_to_wait.update(missing_pods)
|
|
2959
3016
|
|
|
2960
3017
|
# pods have been killed but respawned with different names
|
|
@@ -2984,12 +3041,12 @@ class KrknKubernetes:
|
|
|
2984
3041
|
# inject the chaos, let's see the next iteration.
|
|
2985
3042
|
if len(pods_to_wait) == 0:
|
|
2986
3043
|
continue
|
|
2987
|
-
|
|
2988
3044
|
futures = []
|
|
2989
|
-
|
|
2990
3045
|
with ThreadPoolExecutor() as executor:
|
|
2991
3046
|
for pod_and_namespace in pods_to_wait:
|
|
2992
3047
|
if pod_and_namespace not in pods_already_watching:
|
|
3048
|
+
|
|
3049
|
+
# need name of new pod
|
|
2993
3050
|
future = executor.submit(
|
|
2994
3051
|
self.__wait_until_pod_is_ready_worker,
|
|
2995
3052
|
pod_name=pod_and_namespace[0],
|
|
@@ -3008,20 +3065,24 @@ class KrknKubernetes:
|
|
|
3008
3065
|
# sum the time elapsed waiting before the pod
|
|
3009
3066
|
# has been rescheduled (rescheduling time)
|
|
3010
3067
|
# to the effective recovery time of the pod
|
|
3011
|
-
result.
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3068
|
+
if result.pod_readiness_time:
|
|
3069
|
+
result.pod_rescheduling_time = (
|
|
3070
|
+
time.time()
|
|
3071
|
+
- start_time
|
|
3072
|
+
- result.pod_readiness_time
|
|
3073
|
+
)
|
|
3074
|
+
result.total_recovery_time = (
|
|
3075
|
+
result.pod_readiness_time
|
|
3076
|
+
+ result.pod_rescheduling_time
|
|
3077
|
+
)
|
|
3018
3078
|
|
|
3019
|
-
|
|
3079
|
+
pods_status.recovered.append(result)
|
|
3020
3080
|
for future in undone:
|
|
3021
3081
|
result = future.result()
|
|
3022
3082
|
pods_status.unrecovered.append(result)
|
|
3023
3083
|
|
|
3024
3084
|
missing_pods.clear()
|
|
3085
|
+
|
|
3025
3086
|
# if there are missing pods, pods affected
|
|
3026
3087
|
# by the chaos did not restart after the chaos
|
|
3027
3088
|
# an exception will be set in the PodsStatus
|
|
@@ -3361,3 +3422,75 @@ class KrknKubernetes:
|
|
|
3361
3422
|
resources.memory = json_obj["node"]["memory"]["availableBytes"]
|
|
3362
3423
|
resources.disk_space = json_obj["node"]["fs"]["availableBytes"]
|
|
3363
3424
|
return resources
|
|
3425
|
+
|
|
3426
|
+
def get_container_ids(self, pod_name: str, namespace: str) -> list[str]:
|
|
3427
|
+
"""
|
|
3428
|
+
Gets the container ids of the selected pod
|
|
3429
|
+
:param pod_name: name of the pod
|
|
3430
|
+
:param namespace: namespace of the pod
|
|
3431
|
+
|
|
3432
|
+
:return: a list of container id
|
|
3433
|
+
"""
|
|
3434
|
+
|
|
3435
|
+
container_ids: list[str] = []
|
|
3436
|
+
|
|
3437
|
+
pod = self.get_pod_info(pod_name, namespace)
|
|
3438
|
+
if pod:
|
|
3439
|
+
for container in pod.containers:
|
|
3440
|
+
container_ids.append(
|
|
3441
|
+
re.sub(r".*://", "", container.containerId)
|
|
3442
|
+
)
|
|
3443
|
+
return container_ids
|
|
3444
|
+
|
|
3445
|
+
def get_pod_pids(
|
|
3446
|
+
self,
|
|
3447
|
+
base_pod_name: str,
|
|
3448
|
+
base_pod_namespace: str,
|
|
3449
|
+
base_pod_container_name: str,
|
|
3450
|
+
pod_name: str,
|
|
3451
|
+
pod_namespace: str,
|
|
3452
|
+
pod_container_id: str,
|
|
3453
|
+
) -> Optional[list[str]]:
|
|
3454
|
+
"""
|
|
3455
|
+
Retrieves the PIDs assigned to the pod in the node. The command
|
|
3456
|
+
must be executed inside a privileged Pod with `hostPID` set to true
|
|
3457
|
+
|
|
3458
|
+
:param base_pod_name: name of the pod where the command is run
|
|
3459
|
+
:param base_pod_namespace: namespace of the pod
|
|
3460
|
+
where the command is run
|
|
3461
|
+
:param base_pod_container_name: container name of the pod
|
|
3462
|
+
where the command is run
|
|
3463
|
+
:param pod_name: Pod name associated with the PID
|
|
3464
|
+
:param pod_namespace: namespace of the Pod associated with the PID
|
|
3465
|
+
:param pod_container_id: container id of Pod associated with the PID
|
|
3466
|
+
|
|
3467
|
+
:return: list of pids None.
|
|
3468
|
+
"""
|
|
3469
|
+
|
|
3470
|
+
if not self.check_if_pod_exists(base_pod_name, base_pod_namespace):
|
|
3471
|
+
raise Exception(
|
|
3472
|
+
f"base pod {base_pod_name} does not exist in "
|
|
3473
|
+
f"namespace {base_pod_namespace}"
|
|
3474
|
+
)
|
|
3475
|
+
if not self.check_if_pod_exists(pod_name, pod_namespace):
|
|
3476
|
+
raise Exception(
|
|
3477
|
+
f"target pod {pod_name} does not exist in "
|
|
3478
|
+
f"namespace {pod_namespace}"
|
|
3479
|
+
)
|
|
3480
|
+
|
|
3481
|
+
cmd = (
|
|
3482
|
+
"for dir in /proc/[0-9]*; do [ $(cat $dir/cgroup | grep %s) ] && "
|
|
3483
|
+
"echo ${dir/\/proc\//}; done" % pod_container_id # noqa
|
|
3484
|
+
)
|
|
3485
|
+
|
|
3486
|
+
pids = self.exec_cmd_in_pod(
|
|
3487
|
+
[cmd],
|
|
3488
|
+
base_pod_name,
|
|
3489
|
+
base_pod_namespace,
|
|
3490
|
+
base_pod_container_name,
|
|
3491
|
+
)
|
|
3492
|
+
if pids:
|
|
3493
|
+
pids_list = pids.split("\n")
|
|
3494
|
+
pids_list = list(filter(None, pids_list))
|
|
3495
|
+
return pids_list
|
|
3496
|
+
return None
|