Merge "Initial AppController integration"
This commit is contained in:
commit
92b827ba0b
|
@ -10,6 +10,9 @@ DEFAULTS = {
|
|||
'password': None,
|
||||
'cluster_domain': 'cluster.local',
|
||||
'image_pull_policy': None,
|
||||
'appcontroller': {
|
||||
"enabled": False
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -33,6 +36,13 @@ SCHEMA = {
|
|||
{'type': 'null'},
|
||||
{'enum': ['Always', 'IfNotPresent', 'Never']},
|
||||
]},
|
||||
'appcontroller': {
|
||||
'type': 'object',
|
||||
'additionalProperties': False,
|
||||
'properties': {
|
||||
"enabled": {'type': 'boolean'},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ def _process_secrets(secrets):
|
|||
type, data)
|
||||
|
||||
|
||||
def parse_role(component, topology, configmaps):
|
||||
def parse_role(component, topology, configmaps, components_map):
|
||||
service_dir = component["service_dir"]
|
||||
role = component["service_content"]
|
||||
component_name = component["component_name"]
|
||||
|
@ -115,6 +115,8 @@ def parse_role(component, topology, configmaps):
|
|||
yield _process_secrets(role.get("secrets"))
|
||||
|
||||
workflows = _parse_workflows(service)
|
||||
if CONF.kubernetes.appcontroller['enabled']:
|
||||
yield create_dependencies(workflows, components_map)
|
||||
serialize_workflows(workflows)
|
||||
workflow_cm = _create_workflow(workflows, service_name)
|
||||
configmaps = configmaps + (files_cm, meta_cm, workflow_cm)
|
||||
|
@ -643,6 +645,27 @@ def _create_registry_secret():
|
|||
kubernetes.process_object(secret)
|
||||
|
||||
|
||||
def _format_dependency(dep, components_map):
|
||||
service_name, _, dep_name = dep.partition('/')
|
||||
# FIXME in general this is not correct...
|
||||
if dep_name in components_map:
|
||||
kind = components_map[dep_name]['service_content']['service'].get(
|
||||
'kind', "deployment")
|
||||
return "%s/%s" % (kind.lower(), service_name)
|
||||
return "job/%s-%s" % (service_name, dep_name)
|
||||
|
||||
|
||||
def create_dependencies(workflows, components_map):
|
||||
for name, wf in six.iteritems(workflows):
|
||||
child = _format_dependency(wf['workflow']['name'], components_map)
|
||||
for dep in wf['workflow']['dependencies']:
|
||||
parent = _format_dependency(dep, components_map)
|
||||
dep_name = "-".join((child.partition("/")[-1],
|
||||
parent.partition("/")[-1]))[:63].rstrip("-")
|
||||
template = templates.serialize_dependency(dep_name, parent, child)
|
||||
yield template
|
||||
|
||||
|
||||
def deploy_components(components_map, components):
|
||||
|
||||
topology = _make_topology(CONF.nodes, CONF.roles, CONF.replicas)
|
||||
|
@ -679,7 +702,7 @@ def deploy_components(components_map, components):
|
|||
for service_name in components:
|
||||
service = components_map[service_name]
|
||||
service["service_content"]['service']['exports_ctx'] = exports_ctx
|
||||
objects_gen = parse_role(service, topology, configmaps)
|
||||
objects_gen = parse_role(service, topology, configmaps, components_map)
|
||||
objects = list(itertools.chain.from_iterable(objects_gen))
|
||||
component_name = service['component_name']
|
||||
do_upgrade = component_name in upgrading_components
|
||||
|
|
|
@ -2,6 +2,7 @@ import logging
|
|||
import os
|
||||
|
||||
import pykube.exceptions
|
||||
import pykube.objects
|
||||
import yaml
|
||||
|
||||
from fuel_ccp import config
|
||||
|
@ -95,8 +96,8 @@ def get_pykube_object(object_dict, namespace=None, client=None):
|
|||
namespace = CONF.kubernetes.namespace
|
||||
if client is None:
|
||||
client = get_client()
|
||||
|
||||
obj_class = getattr(pykube, object_dict["kind"], None)
|
||||
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'])
|
||||
|
@ -128,7 +129,6 @@ def process_object(object_dict, namespace=None, client=None):
|
|||
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():
|
||||
|
@ -227,3 +227,27 @@ def get_configmap(name):
|
|||
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)
|
||||
|
|
|
@ -30,6 +30,18 @@ def _get_readiness_cmd(role_name):
|
|||
return [PYTHON_PATH, ENTRYPOINT_PATH, "status", role_name]
|
||||
|
||||
|
||||
def _wrap_with_definition(name, obj):
|
||||
kind = obj['kind'].lower()
|
||||
return {
|
||||
"apiVersion": "appcontroller.k8s/v1alpha1",
|
||||
"kind": "Definition",
|
||||
"metadata": {
|
||||
"name": "%s-%s" % (kind, name)
|
||||
},
|
||||
kind: obj
|
||||
}
|
||||
|
||||
|
||||
def serialize_namespace(name):
|
||||
return {
|
||||
"apiVersion": "v1",
|
||||
|
@ -389,7 +401,7 @@ def serialize_volumes(service, for_job=None):
|
|||
|
||||
|
||||
def serialize_job(name, spec, component_name, app_name):
|
||||
return {
|
||||
job = {
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
|
@ -404,6 +416,9 @@ def serialize_job(name, spec, component_name, app_name):
|
|||
"template": spec
|
||||
}
|
||||
}
|
||||
if CONF.kubernetes.appcontroller["enabled"]:
|
||||
job = _wrap_with_definition(name, job)
|
||||
return job
|
||||
|
||||
|
||||
def serialize_deployment(name, spec, annotations, replicas, component_name,
|
||||
|
@ -436,12 +451,14 @@ def serialize_deployment(name, spec, annotations, replicas, component_name,
|
|||
}
|
||||
}
|
||||
}
|
||||
if CONF.kubernetes.appcontroller["enabled"]:
|
||||
deployment = _wrap_with_definition(name, deployment)
|
||||
|
||||
return deployment
|
||||
|
||||
|
||||
def serialize_statefulset(name, spec, annotations, replicas, component_name):
|
||||
return {
|
||||
obj = {
|
||||
"apiVersion": "apps/v1beta1",
|
||||
"kind": "StatefulSet",
|
||||
"metadata": {
|
||||
|
@ -464,6 +481,10 @@ def serialize_statefulset(name, spec, annotations, replicas, component_name):
|
|||
}
|
||||
}
|
||||
|
||||
if CONF.kubernetes.appcontroller["enabled"]:
|
||||
obj = _wrap_with_definition(name, obj)
|
||||
return obj
|
||||
|
||||
|
||||
def serialize_affinity(service, topology):
|
||||
policy = {
|
||||
|
@ -545,6 +566,9 @@ def serialize_service(name, ports, headless=False, annotations=None):
|
|||
else:
|
||||
obj["spec"]["clusterIP"] = "None"
|
||||
|
||||
if CONF.kubernetes.appcontroller["enabled"]:
|
||||
obj = _wrap_with_definition(name, obj)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
|
@ -589,3 +613,15 @@ def serialize_secret(name, type="Opaque", data={}):
|
|||
"type": type,
|
||||
"data": data
|
||||
}
|
||||
|
||||
|
||||
def serialize_dependency(name, parent, child):
|
||||
return {
|
||||
"apiVersion": "appcontroller.k8s/v1alpha1",
|
||||
"kind": "Dependency",
|
||||
"metadata": {
|
||||
"name": name
|
||||
},
|
||||
"parent": parent,
|
||||
"child": child
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue