Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/kubernetes-pod-status #216

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,19 @@
from kubernetes import client, config, watch
from kubernetes.client.rest import ApiException
import re
from enum import Enum


class KubernetesWaitForPodStatusState(Enum):
IDLE = 1
MONITORING = 2
FAILURE = 3


class KubernetesWaitForPodStatus(BaseAction):

def __init__(self, within_cluster: bool):
super().__init__()
self.target = None
self.namespace = None
self.expected_status = None
self.within_cluster = within_cluster
self.regex = None
self.client = None
self.update_queue = queue.Queue()
self.current_state = KubernetesWaitForPodStatusState.IDLE
self.is_pod = False
Nikhil-Singhal-06 marked this conversation as resolved.
Show resolved Hide resolved

def setup(self, **kwargs):
if self.within_cluster:
Expand All @@ -50,35 +42,37 @@ def setup(self, **kwargs):
config.load_kube_config()
self.client = client.CoreV1Api()

self.monitoring_thread = threading.Thread(target=self.watch_pods, daemon=True)
self.monitoring_thread.start()

def execute(self, target: str, regex: bool, status: tuple, namespace: str):
self.target = target
self.namespace = namespace
self.target = target
if not isinstance(status, tuple) or not isinstance(status[0], str):
raise ValueError("Status expected to be enum.")
self.expected_status = status[0]
self.regex = regex
self.current_state = KubernetesWaitForPodStatusState.MONITORING
self.is_pod = False
self.monitoring_thread = threading.Thread(target=self.watch_pods, daemon=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this creates a new thread for every execution. Instead please rework the previous solution
--> in update() when getting the last element from update_queue (line 58) , store the item in a member variable (e.g. self.current_state). This allows you to keep the state for another execution. Then you can rework the update() function:

  1. move the check within update() into a separate function.
  2. update() should look something like that afterwards:
if self.update_queue().empty():
  if self.current_state is not None and check(self.current_state):
    return  SUCCESS
  return RUNNING
else:
  while not self.update_queue.empty():
    self.current_state = self.update_queue.get()
    if check(self.current_state):
      return SUCCESS
  return RUNNING

self.monitoring_thread.start()

def update(self) -> py_trees.common.Status:
while not self.update_queue.empty():
item = self.update_queue.get()
if len(item) != 2:
return py_trees.common.Status.FAILURE

self.feedback_message = f"waiting for status of pod '{self.target}'." # pylint: disable= attribute-defined-outside-init
if not self.is_pod:
self.feedback_message = f"waiting for status of pod '{self.target}'." # pylint: disable= attribute-defined-outside-init
if not self.regex:
if item[0] != self.target:
continue
else:
if not re.search(self.target, item[0]):
continue
# self.feedback_message = f"The pod '{self.target}' is currently in '{item[1].lower()}' status." # pylint: disable= attribute-defined-outside-init
Nikhil-Singhal-06 marked this conversation as resolved.
Show resolved Hide resolved
if item[1].lower() == self.expected_status:
self.is_pod = True
self.feedback_message = f"Pod '{item[0]}' changed to expected status '{item[1].lower()}'." # pylint: disable= attribute-defined-outside-init
return py_trees.common.Status.SUCCESS
else:
self.is_pod = True
self.feedback_message = f"Pod '{item[0]}' changed to status '{item[1].lower()}', expected '{self.expected_status}'." # pylint: disable= attribute-defined-outside-init
return py_trees.common.Status.RUNNING

Expand All @@ -89,8 +83,7 @@ def watch_pods(self):
for event in w.stream(self.client.list_namespaced_pod, namespace=self.namespace):
pod_name = event['object'].metadata.name
pod_status = event['object'].status.phase
if self.current_state == KubernetesWaitForPodStatusState.MONITORING:
self.update_queue.put((pod_name, pod_status))
self.update_queue.put((pod_name, pod_status))
except ApiException as e:
self.logger.error(f"Error accessing kubernetes: {e}")
self.update_queue.put(())