murano-apps/Docker/Kubernetes/KubernetesPod/package/Classes/KubernetesPod.yaml

356 lines
11 KiB
YAML

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
Namespaces:
=: com.mirantis.docker.kubernetes
docker: com.mirantis.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)
Usage: InOut
Methods:
.init:
Body:
- $._environment: $.find(std:Environment).require()
- $._podDefinition: null
# this is a workaround for early initialization. If docker application was deleted
# its destroy method will call deleteContainer method that will change _podDefinition
# on KubernetesPod loaded from ObjectsCopy
# but ininitialize method on a KubernetesPod from Objects is called before destruction
# and because we have 2 different KubernetesPod objects that share attributes but
# not private variables _podDefinition of real object will still contain outdated data
_loadCurrentPodDefinition:
Body:
- If: $._podDefinition = null
Then:
- $podName: $._getPodName()
- $podDefinition: $.getAttr(lastPodDeployed, null)
- If: $podDefinition = null
Then:
- $podDefinition:
apiVersion: v1
kind: Pod
metadata:
name: $podName
labels: $._getPodLabels($podName)
spec:
containers: []
volumes: []
- $.setAttr(lastPodDeployed, $podDefinition)
- $._podDefinition: $podDefinition
- Return: $._podDefinition
_getPodName:
Body:
- Return: $.name.toLower()
_getPodLabels:
Arguments:
- podName:
Contract: $.string().notNull()
Body:
Return: $.labels2Map($.labels.toLower()).mergeWith(dict(id => $podName))
hostContainer:
Arguments:
- container:
Contract: $.class(docker:DockerContainer)
Body:
- $._loadCurrentPodDefinition()
- $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: $container.name.toLower()
image: $container.image
args: $container.commands
ports: $container.ports.select($this._getPortDefinition($))
volumeMounts: $container.volumes.keys().select(
dict(
name => $this._generateVolumeName($container.name, $container.volumes.get($)),
mountPath => $
))
env: $container.env.keys().select(dict(name => $, value => $container.env.get($)))
securityContext:
privileged: $container.privileged
- $newVolumes: $container.volumes.values().select(
$this._buildVolumeEntry($container.name, $))
- $diff:
spec:
containers: [$containerDef]
volumes: $newVolumes
- $._podDefinition: $._podDefinition.mergeWith($diff)
- $.deploy()
- $._environment.reporter.report($, 'Creating services for Pod {0}'.format($.name))
- $.kubernetesCluster.createService(
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
and $.podId = $this._getPodName()
)
_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:
- name:
Contract: $.string().notNull()
- volume:
Contract: $.class(docker:DockerVolume).notNull()
Body:
- $type: $volume.getType()
- Value: $type
Match:
HostPath:
- $spec:
hostPath:
path: $volume.getParameters()
TempVolume:
- $spec:
emptyDir: {}
Default:
- Throw: UnknownDockerVolumeType
Message: format('Unknown docker volume type {0}', $type)
- $result:
name: $._generateVolumeName($name, $volume)
- Return: $result.mergeWith($spec)
_deleteContainer:
Arguments:
- name:
Contract: $.string().notNull()
Body:
- $lenBefore: len($._podDefinition.spec.containers) + len($._podDefinition.spec.volumes)
- $containerName: $name.toLower()
- $newContainers: $._podDefinition.spec.containers.where($.name != $containerName)
- $volumeNameMap: $.getAttr(volumeNameMap, dict())
- $newVolumeNameMap: {}
- $volumesToDelete: []
- $prefix: format('{0}/'.format($name))
- For: key
In: $volumeNameMap.keys()
Do:
- $volumeName: $volumeNameMap.get($key)
- If: $key.startsWith($prefix)
Then:
- $volumesToDelete: $volumesToDelete + list($volumeName)
Else:
- $newVolumeNameMap[$key]: $volumeName
- $.setAttr(volumeNameMap, $newVolumeNameMap)
- $newVolumes: $._podDefinition.spec.volumes.where(
not ($.name in $volumesToDelete))
- If: len($newContainers) + len($newVolumes) != $lenBefore
Then:
- $._podDefinition.spec.containers: $newContainers
- $._podDefinition.spec.volumes: $newVolumes
deleteContainer:
Arguments:
- name:
Contract: $.string().notNull()
Body:
- If: $.kubernetesCluster.isAvailable()
Then:
- $._loadCurrentPodDefinition()
- $._deleteContainer($name)
- $.kubernetesCluster.deleteServices(
applicationName => $name,
podId => $._getPodName())
- $.deploy()
_generateVolumeName:
Arguments:
- name:
Contract: $.string().notNull()
- volume:
Contract: $.class(docker:DockerVolume).notNull()
Body:
- $key: format('{0}/{1}', $name, $volume.name)
- $map: $.getAttr(volumeNameMap, dict())
- $volumeName: $map.get($key)
- If: $volumeName = null
Then:
- $volumeName: randomName()
- $map[$key]: $volumeName
- $.setAttr(volumeNameMap, $map)
- Return: $volumeName
deploy:
Body:
- $._loadCurrentPodDefinition()
- $prevPod: $.getAttr(lastPodDeployed, null)
- $prevReplicas: $.getAttr(lastReplicas, 0)
- $podDefinition: $._podDefinition
- $replicas: $.replicas
- If: len($podDefinition.spec.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 and len($prevPod.spec.containers) > 0
Then:
- $.kubernetesCluster.deletePods(dict(id => $._getPodName()))
- If: $.replicas = 0 and len($podDefinition.spec.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:
apiVersion: v1
kind: ReplicationController
metadata:
name: $._getReplicationControllerId()
labels: $podDefinition.metadata.labels
spec:
replicas: $.replicas
selector:
id: $._getPodName()
template:
metadata:
labels: $podDefinition.metadata.labels
spec: $podDefinition.spec
_getReplicationControllerId:
Body:
- Return: $._getPodName()
getInternalScopeId:
Body:
Return: id($.kubernetesCluster)
scalePodDown:
Usage: Action
Body:
- If: $.replicas > 1
Then:
- $._environment.reporter.report($this, 'Scaling Pod down')
- $.replicas: $.replicas - 1
- $.kubernetesCluster.scaleRc(rcName => $._getReplicationControllerId(), newSize => $.replicas)
Else:
- $._environment.reporter.report($this, 'Cannot scale Pod down')
scalePodUp:
Usage: Action
Body:
- If: $.replicas > 0
Then:
- $._environment.reporter.report($this, 'Scaling Pod up')
- $.replicas: $.replicas + 1
- $.kubernetesCluster.scaleRc(rcName => $._getReplicationControllerId(), newSize => $.replicas)
Else:
- $._environment.reporter.report($this, 'Cannot scale Pod up')
recreatePod:
Usage: Action
Body:
- $._environment.reporter.report($this, 'Recreating Pod {0}'.format($.name))
- $.kubernetesCluster.deletePods(dict(id => $._getPodName()))
- If: $.replicas = 0
Then:
- $._loadCurrentPodDefinition()
- $.kubernetesCluster.createPod(definition => $._podDefinition, isNew => true)
- $._environment.reporter.report($this, 'Pod {0} recreated'.format($.name))
restartContainers:
Usage: Action
Body:
- $.kubernetesCluster.restartContainers(podName => $._getPodName())