Stan Lagun a855e9a879 Adds support for several applications in single Pod
Kubernetes doesn't allow to add containers to a Pod that
is already deployed. With this change old pods will be deleted
and either new pod created which will include new container
or Replication Controller will be modified (before Pod delete
so that updated Pods be created instead)

Also now Pods are created only when replica number set to 0.
Otherwise Pods created by ReplicationController alone.

Change-Id: I8552793f39083de47ad07e7013dedb72e0550885
Closes-Bug: #1444208
2015-04-15 00:28:31 +00:00

245 lines
7.4 KiB
YAML

Namespaces:
=: io.murano.apps.docker.kubernetes
docker: io.murano.apps.docker
std: io.murano
sys: io.murano.system
Name: KubernetesPod
Extends:
- docker:DockerContainerHost
- docker:DockerHelpers
Properties:
name:
Contract: $.string().notNull()
kubernetesCluster:
Contract: $.class(KubernetesCluster).notNull()
labels:
Contract: $.string().notNull() # convert to key-value map as soon as it will be possible to input it in UI
Default: ''
replicas:
Contract: $.int().notNull().check($ >= 0)
Methods:
initialize:
Body:
- $._environment: $.find(std:Environment).require()
- $podName: $._getPodName()
- $podDefinition: $.getAttr(lastPodDeployed, null)
- If: $podDefinition = null
Then:
- $podDefinition:
id: $podName
kind: Pod
apiVersion: v1beta1
desiredState:
manifest:
version: v1beta1
id: $podName
containers: []
volumes: []
labels: $._getPodLabels($podName)
- $.setAttr(lastPodDeployed, $podDefinition)
- $._podDefinition: $podDefinition
_getPodName:
Body:
- Return: toLower($.name)
_getPodLabels:
Arguments:
- podName:
Contract: $.string().notNull()
Body:
Return: $.labels2Map(toLower($.labels)).mergeWith(dict(id => $podName))
hostContainer:
Arguments:
- container:
Contract: $.class(docker:DockerContainer)
Body:
- $podName: $._getPodName()
- For: port
In: $container.ports
Do:
- $endpoints: $.kubernetesCluster.serviceEndpoints.where(
$.containerPort = $port.port and $.protocol = $port.protocol and $.podId = $podName)
- If: len($endpoints) > 0
Then:
- $msg: format('Port {0} is already used in the Pod {1}', $port.port, $.name)
- Throw: PortConflictException
Message: $msg
- $._deleteContainer($container.name)
- $containerDef:
name: toLower($container.name)
image: $container.image
command: $container.commands
ports: $container.ports.select($this._getPortDefinition($))
volumeMounts: $container.volumes.keys().select(dict(name => $this._generateVolumeName($container.volumes.get($)), mountPath => $))
env: $container.env.keys().select(dict(key => $, value => $container.env.get($)))
- $newVolumes: $container.volumes.values().where(not $this._generateVolumeName($) in $this._podDefinition.desiredState.volumes.name).
select($this._buildVolumeEntry($))
- $diff:
desiredState:
manifest:
containers: [$containerDef]
volumes: $newVolumes
- $._podDefinition: $._podDefinition.mergeWith($diff)
- $.deploy()
- $._environment.reporter.report($, 'Creating services for Pod {0}'.format($.name))
- $.kubernetesCluster.createServices(
applicationName => $container.name,
applicationPorts => $container.ports,
podId => $podName)
- Return: $.getEndpoints($container.name)
getEndpoints:
Arguments:
- applicationName:
Contract: $.string().notNull()
Body:
- Return: $.kubernetesCluster.serviceEndpoints.where($.applicationName = $applicationName)
_getPortDefinition:
Arguments:
- port:
Contract: $.class(docker:ApplicationPort).notNull()
Body:
- $result:
containerPort: $port.port
- If: $port.scope = node
Then:
$result.hostPort: $port.port
- Return: $result
_buildVolumeEntry:
Arguments:
- volume:
Contract: $.class(docker:DockerVolume).notNull()
Body:
- $type: $volume.getType()
- Value: $type
Match:
HostDir:
- $spec:
hostDir:
path: $volume.getParameters()
TempVolume:
- $spec:
emptyDir: {}
Default:
- Throw: UnknownDockerVolumeType
Message: format('Unknown docker volume type {0}', $type)
- Return:
name: $._generateVolumeName($volume)
source: $spec
_deleteContainer:
Arguments:
- name:
Contract: $.string().notNull()
Body:
- $lenBefore: len($._podDefinition.desiredState.manifest.containers) + len($._podDefinition.desiredState.manifest.volumes)
- $newContainers: $._podDefinition.desiredState.manifest.containers.where($.name != $name)
- $newVolumes: $._podDefinition.desiredState.manifest.volumes.where(
$.name in $._podDefinition.desiredState.manifest.containers.volumeMounts.name)
- If: len($newContainers) + len($newVolumes) != $lenBefore
Then:
- $._podDefinition.desiredState.manifest.containers: $newContainers
- $._podDefinition.desiredState.manifest.volumes: $newVolumes
deleteContainer:
Arguments:
- name:
Contract: $.string().notNull()
Body:
- $._deleteContainer($name)
- $.kubernetesCluster.deleteService(
applicationName => $name,
podId => $._getPodName())
- $.deploy()
_generateVolumeName:
Arguments:
- volume:
Contract: $.class(docker:DockerVolume).notNull()
Body:
Return: toLower($volume.name)
deploy:
Body:
- $prevPod: $.getAttr(lastPodDeployed, null)
- $prevReplicas: $.getAttr(lastReplicas, 0)
- $podDefinition: $._podDefinition
- $replicas: $.replicas
- If: len($podDefinition.desiredState.manifest.containers) = 0
Then:
- $replicas: 0
- $.setAttr(lastReplicas, $replicas)
- If: $replicas != $prevReplicas or $prevPod != $podDefinition
Then:
- If: $replicas > 0
Then:
- $._environment.reporter.report($, 'Deploying Replication Controller for Pod {0}'.format($.name))
- $rcDefinition: $._buildReplicationControllerDefinition($podDefinition)
- $.kubernetesCluster.createReplicationController(
definition => $rcDefinition, isNew => $prevReplicas = 0)
- If: $replicas = 0 and $prevReplicas > 0
Then:
- $.kubernetesCluster.deleteReplicationController($._getReplicationControllerId())
- If: $prevPod != $podDefinition
Then:
- $.kubernetesCluster.deletePods(dict(id => $._getPodName()))
- If: $.replicas = 0 and len($podDefinition.desiredState.manifest.containers) > 0
Then:
- $.kubernetesCluster.createPod(definition => $podDefinition, isNew => true)
- $._environment.reporter.report($, 'Pod {0} is ready'.format($.name))
- $.setAttr(lastPodDeployed, $podDefinition)
_buildReplicationControllerDefinition:
Arguments:
- podDefinition:
Contract: {}
Body:
Return:
id: $._getReplicationControllerId()
kind: ReplicationController
apiVersion: v1beta1
desiredState:
replicas: $.replicas
replicaSelector:
id: $._getPodName()
podTemplate:
desiredState: $podDefinition.desiredState
labels: $podDefinition.labels
_getReplicationControllerId:
Body:
- Return: $._getPodName()
getInternalScopeId:
Body:
Return: $.kubernetesCluster.id()