Skip to content

Commit

Permalink
Merge pull request #273 from rpitonak/k8s-pod-improvements
Browse files Browse the repository at this point in the history
K8s pod improvements
  • Loading branch information
TomasTomecek authored Sep 13, 2018
2 parents efdfefc + 42c422c commit c492dfc
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
76 changes: 74 additions & 2 deletions conu/backend/k8s/pod.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ def get_ip(self):

return self.get_status().pod_ip

def get_logs(self):
"""
print logs from pod
:return: str or None
"""
try:
api_response = self.core_api.read_namespaced_pod_log(self.name, self.namespace)
logger.info("Logs from pod: %s in namespace: %s", self.name, self.namespace)
for line in api_response.split('\n'):
logger.info(line)
return api_response
except ApiException as e:
# no reason to throw exception when logs cannot be obtain, just notify user
logger.info("Cannot get pod logs because of "
"exception during calling Kubernetes API %s\n", e)

return None

def get_phase(self):
"""
get phase of the pod
Expand All @@ -105,14 +123,34 @@ def get_phase(self):

return self.phase

def get_conditions(self):
"""
get conditions through which the pod has passed
:return: list of PodCondition enum or empty list
"""

# filter just values that are true (means that pod has that condition right now)
return [PodCondition.get_from_string(c.type) for c in self.get_status().conditions
if c.status == 'True']

def is_ready(self):
"""
Check if pod is in READY condition
:return: bool
"""
if PodCondition.READY in self.get_conditions():
logger.info("Pod: %s in namespace: %s is ready!", self.name, self.namespace)
return True
return False

def wait(self, timeout=15):
"""
block until pod is not running, raises an exc ProbeTimeout if timeout is reached
block until pod is not ready, raises an exc ProbeTimeout if timeout is reached
:param timeout: int or float (seconds), time to wait for pod to run
:return: None
"""

Probe(timeout=timeout, fnc=self.get_phase, expected_retval=PodPhase.RUNNING).run()
Probe(timeout=timeout, fnc=self.is_ready, expected_retval=True).run()

@staticmethod
def create(image_data):
Expand Down Expand Up @@ -193,3 +231,37 @@ def get_from_string(cls, string_phase):
return cls.UNKNOWN

return cls.UNKNOWN


class PodCondition(enum.Enum):
"""
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions
"""

SCHEDULED = 0
READY = 1
INITIALIZED = 2
UNSCHEDULABLE = 3
CONTAINERS_READY = 4
UNKNOWN = 5

@classmethod
def get_from_string(cls, string_condition):
"""
Convert string value obtained from k8s API to PodCondition enum value
:param string_condition: str, condition value from Kubernetes API
:return: PodCondition
"""

if string_condition == 'PodScheduled':
return cls.SCHEDULED
elif string_condition == 'Ready':
return cls.READY
elif string_condition == 'Initialized':
return cls.INITIALIZED
elif string_condition == 'Unschedulable':
return cls.UNSCHEDULABLE
elif string_condition == 'ContainersReady':
return cls.CONTAINERS_READY

return cls.UNKNOWN
25 changes: 25 additions & 0 deletions docs/source/examples/k8s_pod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from conu.backend.k8s.backend import K8sBackend
from conu.backend.docker.backend import DockerBackend
from conu.backend.k8s.pod import PodPhase

import logging

# insert your API key
API_KEY = "M0XufKHjTsl87t1A4y7Vp0qAYSiKq8n7QauYI3sAHcU"
with K8sBackend(api_key=API_KEY, logging_level=logging.DEBUG) as k8s_backend:

namespace = k8s_backend.create_namespace()

with DockerBackend(logging_level=logging.DEBUG) as backend:
image = backend.ImageClass('nginx')

pod = image.run_in_pod(namespace=namespace)
try:
pod.get_logs()
pod.wait(200)
assert pod.is_ready()
finally:
pod.get_logs()
pod.delete()
assert pod.get_phase() == PodPhase.TERMINATING
k8s_backend.delete_namespace(namespace)
6 changes: 3 additions & 3 deletions tests/integration/test_k8s.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from conu.backend.k8s.deployment import Deployment
from conu.backend.k8s.client import get_core_api

from ..constants import FEDORA_MINIMAL_REPOSITORY, FEDORA_MINIMAL_REPOSITORY_TAG

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

Expand All @@ -39,12 +38,13 @@ def test_pod():
namespace = k8s_backend.create_namespace()

with DockerBackend() as backend:
image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG)
image = backend.ImageClass('nginx')

pod = image.run_in_pod(namespace=namespace)

try:
pod.wait(200)
assert pod.is_ready()
assert pod.get_phase() == PodPhase.RUNNING
finally:
pod.delete()
Expand Down Expand Up @@ -95,7 +95,7 @@ def test_list_pods():

with DockerBackend() as backend:

image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG)
image = backend.ImageClass('nginx')

pod = image.run_in_pod(namespace=namespace)

Expand Down

0 comments on commit c492dfc

Please sign in to comment.