CORD-2965 Kubernetes Synchronizer
Change-Id: Ie5c02b9ad1c65af686598bab0b36350ac1caef64
diff --git a/xos/synchronizer/steps/sync_kubernetesserviceinstance.py b/xos/synchronizer/steps/sync_kubernetesserviceinstance.py
index 400396d..27badfa 100644
--- a/xos/synchronizer/steps/sync_kubernetesserviceinstance.py
+++ b/xos/synchronizer/steps/sync_kubernetesserviceinstance.py
@@ -17,6 +17,10 @@
sync_kubernetesserviceinstance.py
Synchronize KubernetesServiceInstance. See also the related pull_step.
+
+ This sync_step is intended to handle the case where callers are creating pods directly, as opposed to using
+ a controller to manage pods for them. It makes some simplifying assumptions, such as each pod has one
+ container and uses one image.
"""
from synchronizers.new_base.syncstep import SyncStep
@@ -25,6 +29,7 @@
from xosconfig import Config
from multistructlog import create_logger
+from kubernetes.client.rest import ApiException
from kubernetes import client as kubernetes_client, config as kubernetes_config
log = create_logger(Config().get('logging'))
@@ -43,16 +48,62 @@
def __init__(self, *args, **kwargs):
super(SyncKubernetesServiceInstance, self).__init__(*args, **kwargs)
-
kubernetes_config.load_incluster_config()
self.v1 = kubernetes_client.CoreV1Api()
- def sync_record(self, o):
- # TODO(smbaker): implement sync step here
- pass
+ def get_pod(self, o):
+ """ Given a KubernetesServiceInstance, read the pod from Kubernetes.
+ Return None if the pod does not exist.
+ """
+ try:
+ pod = self.v1.read_namespaced_pod(o.name, o.slice.trust_domain.name)
+ except ApiException, e:
+ if e.status == 404:
+ return None
+ raise
+ return pod
+ def sync_record(self, o):
+ if o.xos_managed:
+ if (not o.slice) or (not o.slice.trust_domain):
+ raise Exception("No trust domain for service instance", o=o)
+
+ if (not o.name):
+ raise Exception("No name for service instance", o=o)
+
+ pod = self.get_pod(o)
+ if not pod:
+ # make a pod!
+ pod = kubernetes_client.V1Pod()
+ pod.metadata = kubernetes_client.V1ObjectMeta(name=o.name)
+
+ if o.slice.trust_domain:
+ pod.metadata.namespace = o.slice.trust_domain.name
+
+ if o.image.tag:
+ imageName = o.image.name + ":" + o.image.tag
+ else:
+ # TODO(smbaker): Is this case possible?
+ imageName = o.image.name
+
+ container=kubernetes_client.V1Container(name=o.name,
+ image=imageName)
+
+ spec = kubernetes_client.V1PodSpec(containers=[container])
+ pod.spec = spec
+
+ if o.slice.principal:
+ pod.spec.service_account = o.slice.principal.name
+
+ log.info("Creating pod", o=o, pod=pod)
+
+ pod = self.v1.create_namespaced_pod(o.slice.trust_domain.name, pod)
+
+ if (not o.backend_handle):
+ o.backend_handle = pod.metadata.self_link
+ o.save(update_fields=["backend_handle"])
def delete_record(self, port):
- # TODO(smbaker): implement delete sync step here
+ # TODO(smbaker): Implement delete step
pass