fuel-ccp/fuel_ccp/kubernetes.py

254 lines
7.1 KiB
Python

import logging
import os
import pykube.exceptions
import pykube.objects
import yaml
from fuel_ccp import config
CONF = config.CONF
LOG = logging.getLogger(__name__)
UPDATABLE_OBJECTS = (
'ConfigMap',
'Deployment',
'Service',
'Ingress',
'StatefulSet',
'Secret',
)
def get_client(kube_apiserver=None, key_file=None, cert_file=None,
ca_cert=None, insecure=None, username=None, password=None):
kube_apiserver = kube_apiserver or CONF.kubernetes.server
key_file = key_file or CONF.kubernetes.key_file
cert_file = cert_file or CONF.kubernetes.cert_file
ca_cert = ca_cert or CONF.kubernetes.ca_cert
insecure = insecure or CONF.kubernetes.insecure
username = username or CONF.kubernetes.username
password = password or CONF.kubernetes.password
cluster = {"server": kube_apiserver}
if ca_cert:
cluster["certificate-authority"] = ca_cert
elif insecure:
cluster['insecure-skip-tls-verify'] = insecure
user = {}
if cert_file and key_file:
user["client-certificate"] = cert_file
user["client-key"] = key_file
if username:
user["username"] = username
if password:
user["password"] = password
config = {
"clusters": [
{
"name": "ccp",
"cluster": cluster
}
],
"users": [
{
"name": "ccp",
"user": user
}
],
"contexts": [
{
"name": "ccp",
"context": {
"cluster": "ccp",
"user": "ccp"
},
}
],
"current-context": "ccp"
}
return pykube.HTTPClient(pykube.KubeConfig(config))
def export_object(object_dict):
file_name = '%s-%s.yaml' % (
object_dict['metadata']['name'], object_dict['kind'].lower())
if object_dict['kind'] == 'ConfigMap':
file_path = os.path.join(
CONF.action.export_dir, 'configmaps', file_name)
else:
file_path = os.path.join(CONF.action.export_dir, file_name)
with open(file_path, 'w') as object_file:
object_file.write(yaml.dump(
object_dict, default_flow_style=False))
def _reload_obj(obj, updated_dict):
obj.reload()
obj.obj = updated_dict
def get_pykube_object(object_dict, namespace=None, client=None):
if namespace is None:
namespace = CONF.kubernetes.namespace
if client is None:
client = get_client()
obj_class = getattr(pykube, object_dict["kind"], None) or globals().get(
object_dict["kind"], None)
if obj_class is None:
raise RuntimeError('"%s" object is not supported, skipping.'
% object_dict['kind'])
if not object_dict['kind'] == 'Namespace':
object_dict['metadata']['namespace'] = namespace
return obj_class(client, object_dict)
def get_pykube_object_if_exists(object_dict, namespace=None, client=None):
obj = get_pykube_object(object_dict, namespace=namespace, client=client)
try:
obj.reload()
except pykube.exceptions.HTTPError as ex:
# pykube 0.13 doesn't provide simple way to get code, so...
if 'not found' in ex.args[0].lower():
return None
raise
return obj
def process_object(object_dict, namespace=None, client=None):
LOG.debug("Deploying %s: \"%s\"",
object_dict["kind"], object_dict["metadata"]["name"])
if not object_dict['kind'] == 'Namespace':
if CONF.action.export_dir:
export_object(object_dict)
if CONF.action.dry_run:
LOG.info(yaml.dump(object_dict, default_flow_style=False))
return
obj = get_pykube_object(object_dict, namespace=namespace, client=client)
if obj.exists():
LOG.debug('%s "%s" already exists', object_dict['kind'],
object_dict['metadata']['name'])
if object_dict['kind'] in UPDATABLE_OBJECTS:
if object_dict['kind'] == 'Service':
# Reload object and merge new and old fields
_reload_obj(obj, object_dict)
obj.update()
LOG.debug('%s "%s" has been updated', object_dict['kind'],
object_dict['metadata']['name'])
else:
obj.create()
LOG.debug('%s "%s" has been created', object_dict['kind'],
object_dict['metadata']['name'])
return obj
def list_k8s_nodes():
client = get_client()
return pykube.Node.objects(client).all()
def list_cluster_deployments(selector=None):
ccp_selector = "ccp=true"
if selector:
ccp_selector += "," + selector
client = get_client()
return pykube.Deployment.objects(client).filter(
namespace=CONF.kubernetes.namespace,
selector=ccp_selector)
def list_cluster_pods(service=None, selector=None, raw_selector=None,
name=None):
if raw_selector is not None:
ccp_selector = raw_selector
else:
ccp_selector = "ccp=true"
if service:
ccp_selector = ",".join((ccp_selector, "app=%s" % service))
if selector:
ccp_selector += "," + selector
client = get_client()
pods = pykube.Pod.objects(client).filter(
namespace=CONF.kubernetes.namespace,
selector=str(ccp_selector))
if name:
return pods.get_by_name(name)
return pods
def list_cluster_jobs(selector=None, name=None):
ccp_selector = "ccp=true"
if selector:
ccp_selector += "," + selector
client = get_client()
jobs = pykube.Job.objects(client).filter(
namespace=CONF.kubernetes.namespace,
selector=ccp_selector)
if name:
return jobs.get_by_name(name)
return jobs
def list_cluster_services():
client = get_client()
return pykube.Service.objects(client).filter(
namespace=CONF.kubernetes.namespace,
selector="ccp=true")
def list_cluster_ingress():
client = get_client()
return pykube.Ingress.objects(client).filter(
namespace=CONF.kubernetes.namespace)
def list_cluster_statefulsets():
client = get_client()
return pykube.StatefulSet.objects(client).filter(
namespace=CONF.kubernetes.namespace,
selector="ccp=true")
def get_object_names(items):
names = []
for item in items:
names.append(item.name)
return names
def get_configmap(name):
client = get_client()
return pykube.ConfigMap.objects(client).filter(
namespace=CONF.kubernetes.namespace,
selector="ccp=true").get_by_name(name)
class Dependency(pykube.objects.APIObject):
version = "appcontroller.k8s/v1alpha1"
endpoint = "dependencies"
kind = "Dependency"
def __init__(self, api, obj):
self.api = api
self.namespace = obj['metadata']['namespace']
self.set_obj(obj)
class Definition(pykube.objects.APIObject):
version = "appcontroller.k8s/v1alpha1"
endpoint = "definitions"
kind = "Definition"
def __init__(self, api, obj):
self.api = api
self.namespace = obj['metadata']['namespace']
self.set_obj(obj)