Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 50b4bde

Browse files
author
fred-labs
authored
support regex in pod_exec (#158)
1 parent 3cdb085 commit 50b4bde

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

docs/libraries.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,10 @@ Execute a command within a running pod
509509
- ``list of string``
510510
-
511511
- Command to execute
512+
* - ``regex``
513+
- ``bool``
514+
- ``false``
515+
- Is the specified target a regular expression
512516

513517

514518
``kubernetes_wait_for_network_policy_status()``

libs/scenario_execution_kubernetes/scenario_execution_kubernetes/kubernetes_pod_exec.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,32 @@
2020
import threading
2121
from kubernetes import client, config, stream
2222
from enum import Enum
23+
import re
2324

2425

2526
class KubernetesPodExecState(Enum):
2627
IDLE = 1
27-
RUNNING = 2
28-
FAILURE = 3
28+
WAITING_FOR_LIST_RUNNING = 2
29+
POD_NAME_PRESENT = 3
30+
RUNNING = 4
31+
FAILURE = 5
2932

3033

3134
class KubernetesPodExec(BaseAction):
3235

33-
def __init__(self, target: str, command: list, namespace: str, within_cluster: bool):
36+
def __init__(self, target: str, command: list, regex: bool, namespace: str, within_cluster: bool):
3437
super().__init__()
3538
self.target = target
3639
self.namespace = namespace
40+
self.regex = regex
3741
self.command = command
3842
self.within_cluster = within_cluster
3943
self.client = None
4044
self.reponse_queue = queue.Queue()
4145
self.current_state = KubernetesPodExecState.IDLE
4246
self.output_queue = queue.Queue()
47+
self.pod_list_request = None
48+
self.pod_name = None
4349

4450
def setup(self, **kwargs):
4551
if self.within_cluster:
@@ -50,18 +56,57 @@ def setup(self, **kwargs):
5056

5157
self.exec_thread = threading.Thread(target=self.pod_exec, daemon=True)
5258

53-
def execute(self, target: str, command: list, namespace: str, within_cluster: bool):
59+
def execute(self, target: str, command: list, regex: bool, namespace: str, within_cluster: bool):
5460
if within_cluster != self.within_cluster:
5561
raise ValueError("parameter 'within_cluster' is not allowed to change since initialization.")
5662
self.target = target
5763
self.namespace = namespace
5864
self.command = command
65+
self.regex = regex
66+
if self.pod_list_request:
67+
self.pod_list_request.cancel()
68+
self.pod_name = None
5969
self.current_state = KubernetesPodExecState.IDLE
6070

61-
def update(self) -> py_trees.common.Status:
71+
def update(self) -> py_trees.common.Status: # pylint: disable=too-many-return-statements
6272
if self.current_state == KubernetesPodExecState.IDLE:
73+
if self.regex:
74+
self.current_state = KubernetesPodExecState.WAITING_FOR_LIST_RUNNING
75+
self.feedback_message = f"Requesting list of pods in namespace '{self.namespace}'" # pylint: disable= attribute-defined-outside-init
76+
self.pod_list_request = self.client.list_namespaced_pod(namespace=self.namespace, async_req=True)
77+
return py_trees.common.Status.RUNNING
78+
else:
79+
self.pod_name = self.target
80+
self.current_state = KubernetesPodExecState.POD_NAME_PRESENT
81+
82+
if self.current_state == KubernetesPodExecState.WAITING_FOR_LIST_RUNNING:
83+
if not self.pod_list_request.ready():
84+
return py_trees.common.Status.RUNNING
85+
current_elements = []
86+
for i in self.pod_list_request.get().items:
87+
current_elements.append(i.metadata.name)
88+
89+
found_element = None
90+
matched_elements = []
91+
for element in current_elements:
92+
if re.search(self.target, element):
93+
matched_elements.append(element)
94+
if matched_elements:
95+
if len(matched_elements) > 1:
96+
self.feedback_message = f"'{self.target}' regex identified more than one pod {', '.join(matched_elements)}. Only one element is supported!" # pylint: disable= attribute-defined-outside-init
97+
return py_trees.common.Status.FAILURE
98+
found_element = matched_elements[0]
99+
100+
if found_element:
101+
self.pod_name = found_element
102+
self.current_state = KubernetesPodExecState.POD_NAME_PRESENT
103+
else:
104+
self.feedback_message = f"'{self.target}' not found in list of available pods (namespace: '{self.namespace}'). Available: {', '.join(current_elements)}'" # pylint: disable= attribute-defined-outside-init
105+
return py_trees.common.Status.FAILURE
106+
107+
if self.current_state == KubernetesPodExecState.POD_NAME_PRESENT:
63108
self.current_state = KubernetesPodExecState.RUNNING
64-
self.feedback_message = f"Executing on pod '{self.target}': {self.command}..." # pylint: disable= attribute-defined-outside-init
109+
self.feedback_message = f"Executing on pod '{self.pod_name}': {self.command}..." # pylint: disable= attribute-defined-outside-init
65110
self.exec_thread.start()
66111
return py_trees.common.Status.RUNNING
67112
elif self.current_state == KubernetesPodExecState.RUNNING:
@@ -82,7 +127,7 @@ def update(self) -> py_trees.common.Status:
82127

83128
def pod_exec(self):
84129
resp = stream.stream(self.client.connect_get_namespaced_pod_exec,
85-
self.target,
130+
self.pod_name,
86131
self.namespace,
87132
command=self.command,
88133
stderr=True, stdin=False,

libs/scenario_execution_kubernetes/scenario_execution_kubernetes/lib_osc/kubernetes.osc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ action kubernetes_patch_pod inherits kubernetes_base_action:
4646

4747
action kubernetes_pod_exec inherits kubernetes_base_action:
4848
# execute a command within a running pod
49-
target: string # pod to patch
50-
command: list of string # command to execute
49+
target: string # pod to execute the command in
50+
command: list of string # command to execute
51+
regex: bool = false # is the specified target a regular expression
5152

5253
action kubernetes_wait_for_network_policy_status inherits kubernetes_base_action:
5354
# wait for a network-policy to reach the specified state

0 commit comments

Comments
 (0)