Port replicatedservice template to chart format

pull/486/head
jackgr 9 years ago
parent fb0e722ed9
commit e46a1eb752

@ -0,0 +1,7 @@
name: replicatedservice
description: Port of the replicatedservice template from kubernetes/charts
version: 3
expander:
name: Expandybird
entrypoint: templates/replicatedservice.py
schema: templates/replicatedservice.py.schema

@ -0,0 +1,195 @@
"""Defines a ReplicatedService type by creating both a Service and an RC.
This module creates a typical abstraction for running a service in a
Kubernetes cluster, namely a replication controller and a service packaged
together into a single unit.
"""
import yaml
SERVICE_TYPE_COLLECTION = 'Service'
RC_TYPE_COLLECTION = 'ReplicationController'
def GenerateConfig(context):
"""Generates a Replication Controller and a matching Service.
Args:
context: Template context. See schema for context properties
Returns:
A Container Manifest as a YAML string.
"""
# YAML config that we're going to create for both RC & Service
config = {'resources': []}
name = context.env['name']
container_name = context.properties.get('container_name', name)
namespace = context.properties.get('namespace', 'default')
# Define things that the Service cares about
service_name = context.properties.get('service_name', name + '-service')
service_type = SERVICE_TYPE_COLLECTION
# Define things that the Replication Controller (rc) cares about
rc_name = context.properties.get('rc_name', name + '-rc')
rc_type = RC_TYPE_COLLECTION
service = {
'name': service_name,
'type': service_type,
'properties': {
'apiVersion': 'v1',
'kind': 'Service',
'namespace': namespace,
'metadata': {
'name': service_name,
'labels': GenerateLabels(context, service_name),
},
'spec': {
'ports': [GenerateServicePorts(context, container_name)],
'selector': GenerateLabels(context, name)
}
}
}
set_up_external_lb = context.properties.get('external_service', None)
if set_up_external_lb:
service['properties']['spec']['type'] = 'LoadBalancer'
cluster_ip = context.properties.get('cluster_ip', None)
if cluster_ip:
service['properties']['spec']['clusterIP'] = cluster_ip
config['resources'].append(service)
rc = {
'name': rc_name,
'type': rc_type,
'properties': {
'apiVersion': 'v1',
'kind': 'ReplicationController',
'namespace': namespace,
'metadata': {
'name': rc_name,
'labels': GenerateLabels(context, rc_name),
},
'spec': {
'replicas': context.properties['replicas'],
'selector': GenerateLabels(context, name),
'template': {
'metadata': {
'labels': GenerateLabels(context, name),
},
'spec': {
'containers': [
{
'env': GenerateEnv(context),
'name': container_name,
'image': context.properties['image'],
'ports': [
{
'name': container_name,
'containerPort': context.properties['container_port'],
}
],
}
],
}
}
}
}
}
# Set up volume mounts
if context.properties.get('volumes', None):
rc['properties']['spec']['template']['spec']['containers'][0]['volumeMounts'] = []
rc['properties']['spec']['template']['spec']['volumes'] = []
for volume in context.properties['volumes']:
# mountPath should be unique
volume_name = volume['mount_path'].replace('/', '-').lstrip('-') + '-storage'
rc['properties']['spec']['template']['spec']['containers'][0]['volumeMounts'].append(
{
'name': volume_name,
'mountPath': volume['mount_path']
}
)
del volume['mount_path']
volume['name'] = volume_name
rc['properties']['spec']['template']['spec']['volumes'].append(volume)
if context.properties.get('privileged', False):
rc['properties']['spec']['template']['spec']['containers'][0]['securityContext'] = {
'privileged': True
}
config['resources'].append(rc)
return yaml.dump(config)
# Generates labels either from the context.properties['labels'] or generates
# a default label 'name':name
def GenerateLabels(context, name):
"""Generates labels from context.properties['labels'] or creates default.
We make a deep copy of the context.properties['labels'] section to avoid
linking in the yaml document, which I believe reduces readability of the
expanded template. If no labels are given, generate a default 'name':name.
Args:
context: Template context, which can contain the following properties:
labels - Labels to generate
Returns:
A dict containing labels in a name:value format
"""
tmp_labels = context.properties.get('labels', None)
ret_labels = {'name': name}
if isinstance(tmp_labels, dict):
for key, value in tmp_labels.iteritems():
ret_labels[key] = value
return ret_labels
def GenerateServicePorts(context, name):
"""Generates a ports section for a service.
Args:
context: Template context, which can contain the following properties:
service_port - Port to use for the service
target_port - Target port for the service
protocol - Protocol to use.
Returns:
A dict containing a port definition
"""
container_port = context.properties['container_port']
target_port = context.properties.get('target_port', container_port)
service_port = context.properties.get('service_port', target_port)
protocol = context.properties.get('protocol')
ports = {}
if name:
ports['name'] = name
if service_port:
ports['port'] = service_port
if target_port:
ports['targetPort'] = target_port
if protocol:
ports['protocol'] = protocol
return ports
def GenerateEnv(context):
"""Generates environmental variables for a pod.
Args:
context: Template context, which can contain the following properties:
env - Environment variables to set.
Returns:
A list containing env variables in dict format {name: 'name', value: 'value'}
"""
env = []
tmp_env = context.properties.get('env', [])
for entry in tmp_env:
if isinstance(entry, dict):
env.append({'name': entry.get('name'), 'value': entry.get('value')})
return env

@ -0,0 +1,91 @@
info:
title: Replicated Service
description: |
Defines a ReplicatedService type by creating both a Service and an RC.
This module creates a typical abstraction for running a service in a
Kubernetes cluster, namely a replication controller and a service packaged
together into a single unit.
required:
- image
properties:
container_name:
type: string
description: Name to use for container. If omitted, name is used.
service_name:
type: string
description: Name to use for service. If omitted, name-service is used.
namespace:
type: string
description: Namespace to create resources in. If omitted, 'default' is
used.
default: default
protocol:
type: string
description: Protocol to use for the service.
service_port:
type: int
description: Port to use for the service.
target_port:
type: int
description: Target port to use for the service.
container_port:
type: int
description: Port to use for the container.
replicas:
type: int
description: Number of replicas to create in RC.
image:
type: string
description: Docker image to use for replicas.
labels:
type: object
description: Labels to apply.
env:
type: array
description: Environment variables to apply.
properties:
name:
type: string
value:
type: string
external_service:
type: boolean
description: If set to true, enable external load balancer.
cluster_ip:
type: string
description: IP to use for the service
privileged:
type: boolean
description: If set to true, enable privileged container
volumes:
type: array
description: Volumes to mount.
items:
type: object
properties:
mounth_path:
type: string
description: Path to mount volume
# See https://cloud.google.com/container-engine/docs/spec-schema?hl=en for possible volumes. Since we only use gcePersistentDisk and NFS in our examples we have only added these ones.
oneOf:
gcePersistentDisk:
pdName:
type: string
description: Persistent's disk name
fsType:
type: string
description: Filesystem type of the persistent disk
nfs:
server:
type: string
description: The hostname or IP address of the NFS server
path:
type: string
description: The path that is exported by the NFS server
readOnly:
type: boolean
description: Forces the NFS export to be mounted with read-only permissions
Loading…
Cancel
Save