From 385d8fa83f376f1237b8afccf21c5dc2b7a67d5a Mon Sep 17 00:00:00 2001 From: vaikas-google <vaikas@google.com> Date: Thu, 3 Dec 2015 15:38:48 -0500 Subject: [PATCH] Reintroduce replicatedservice.py as it is used by tests. --- expandybird/expander/expander_test.go | 2 +- expandybird/service/service_test.go | 2 +- expandybird/test/replicatedservice.py | 182 ++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 expandybird/test/replicatedservice.py diff --git a/expandybird/expander/expander_test.go b/expandybird/expander/expander_test.go index 26efc634d..485ed197e 100644 --- a/expandybird/expander/expander_test.go +++ b/expandybird/expander/expander_test.go @@ -26,7 +26,7 @@ import ( const invalidFileName = "afilethatdoesnotexist" var importFileNames = []string{ - "../../templates/replicatedservice/v1/replicatedservice.py", + "../test/replicatedservice.py", } var outputFileName = "../test/ExpectedOutput.yaml" diff --git a/expandybird/service/service_test.go b/expandybird/service/service_test.go index 01d636941..989dbb2cc 100644 --- a/expandybird/service/service_test.go +++ b/expandybird/service/service_test.go @@ -66,7 +66,7 @@ const ( ) var importFileNames = []string{ - "../../templates/replicatedservice/v1/replicatedservice.py", + "../test/replicatedservice.py", } type ServiceWrapperTestCase struct { diff --git a/expandybird/test/replicatedservice.py b/expandybird/test/replicatedservice.py new file mode 100644 index 000000000..231fb2640 --- /dev/null +++ b/expandybird/test/replicatedservice.py @@ -0,0 +1,182 @@ + +###################################################################### +# Copyright 2015 The Kubernetes Authors All rights reserved. +# 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. +###################################################################### + +"""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 = name + '-rc' + rc_type = RC_TYPE_COLLECTION + + service = { + 'name': service_name, + 'type': service_type, + 'properties': { + 'apiVersion': 'v1', + 'kind': 'Service', + 'metadata': { + 'name': service_name, + 'namespace': namespace, + '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' + config['resources'].append(service) + + rc = { + 'name': rc_name, + 'type': rc_type, + 'properties': { + 'apiVersion': 'v1', + 'kind': 'ReplicationController', + 'metadata': { + 'name': rc_name, + 'namespace': namespace, + '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'], + } + ] + } + ] + } + } + } + } + } + + config['resources'].append(rc) + return yaml.dump(config) + + +def GenerateLabels(context, name): + """Generates labels either from the context.properties['labels'] or + generates a default label 'app':name + + 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 'app':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 = {'app': 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 + """ + service_port = context.properties.get('service_port', None) + target_port = context.properties.get('target_port', None) + 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