##############################################################################
import copy
+import re
from oslo_serialization import jsonutils
+import six
from yardstick.common import constants
from yardstick.common import exceptions
SSH_MOUNT_PATH = '/tmp/.ssh/'
IMAGE_DEFAULT = 'openretriever/yardstick'
- COMMAND_DEFAULT = '/bin/bash'
- RESOURCES = ['requests', 'limits']
+ COMMAND_DEFAULT = ['/bin/bash', '-c']
+ RESOURCES = ('requests', 'limits')
+ PORT_OPTIONS = ('containerPort', 'hostIP', 'hostPort', 'name', 'protocol')
+ IMAGE_PULL_POLICY = ('Always', 'IfNotPresent', 'Never')
def __init__(self, name, ssh_key, **kwargs):
self._name = name
self._ssh_key = ssh_key
self._image = kwargs.get('image', self.IMAGE_DEFAULT)
- self._command = [kwargs.get('command', self.COMMAND_DEFAULT)]
- self._args = kwargs.get('args', [])
+ self._command = self._parse_commands(
+ kwargs.get('command', self.COMMAND_DEFAULT))
+ self._args = self._parse_commands(kwargs.get('args', []))
self._volume_mounts = kwargs.get('volumeMounts', [])
self._security_context = kwargs.get('securityContext')
self._env = kwargs.get('env', [])
self._resources = kwargs.get('resources', {})
+ self._ports = kwargs.get('ports', [])
+ self._image_pull_policy = kwargs.get('imagePullPolicy')
+ self._tty = kwargs.get('tty')
+ self._stdin = kwargs.get('stdin')
+
+ @staticmethod
+ def _parse_commands(command):
+ if isinstance(command, six.string_types):
+ return [command]
+ elif isinstance(command, list):
+ return command
+ raise exceptions.KubernetesContainerCommandType()
def _create_volume_mounts(self):
"""Return all "volumeMounts" items per container"""
for env in self._env:
container['env'].append({'name': env['name'],
'value': env['value']})
+ if self._ports:
+ container['ports'] = []
+ for port in self._ports:
+ if 'containerPort' not in port.keys():
+ raise exceptions.KubernetesContainerPortNotDefined(
+ port=port)
+ _port = {port_option: value for port_option, value
+ in port.items() if port_option in self.PORT_OPTIONS}
+ container['ports'].append(_port)
if self._resources:
container['resources'] = {}
for res in (res for res in self._resources if
res in self.RESOURCES):
container['resources'][res] = self._resources[res]
+ if self._image_pull_policy:
+ if self._image_pull_policy not in self.IMAGE_PULL_POLICY:
+ raise exceptions.KubernetesContainerWrongImagePullPolicy()
+ container['imagePullPolicy'] = self._image_pull_policy
+ if self._stdin is not None:
+ container['stdin'] = self._stdin
+ if self._tty is not None:
+ container['tty'] = self._tty
return container
class ReplicationControllerObject(object):
SSHKEY_DEFAULT = 'yardstick_key'
+ RESTART_POLICY = ('Always', 'OnFailure', 'Never')
+ TOLERATIONS_KEYS = ('key', 'value', 'effect', 'operator')
def __init__(self, name, **kwargs):
super(ReplicationControllerObject, self).__init__()
self._volumes = parameters.pop('volumes', [])
self._security_context = parameters.pop('securityContext', None)
self._networks = parameters.pop('networks', [])
+ self._tolerations = parameters.pop('tolerations', [])
+ self._restart_policy = parameters.pop('restartPolicy', 'Always')
+ if self._restart_policy not in self.RESTART_POLICY:
+ raise exceptions.KubernetesWrongRestartPolicy(
+ rpolicy=self._restart_policy)
containers = parameters.pop('containers', None)
if containers:
"spec": {
"containers": [],
"volumes": [],
- "nodeSelector": {}
+ "nodeSelector": {},
+ "restartPolicy": self._restart_policy,
+ "tolerations": []
}
}
}
self._add_volumes()
self._add_security_context()
self._add_networks()
+ self._add_tolerations()
+
+ @property
+ def networks(self):
+ return self._networks
def get_template(self):
return self.template
'spec.template.metadata.annotations',
annotations)
+ def _add_tolerations(self):
+ tolerations = []
+ for tol in self._tolerations:
+ tolerations.append({k: tol[k] for k in tol
+ if k in self.TOLERATIONS_KEYS})
+
+ tolerations = ([{'operator': 'Exists'}] if not tolerations
+ else tolerations)
+ utils.set_dict_value(self.template,
+ 'spec.template.spec.tolerations',
+ tolerations)
+
class ServiceNodePortObject(object):
+ MANDATORY_PARAMETERS = {'port', 'name'}
+ NAME_REGEX = re.compile(r'^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')
+
def __init__(self, name, **kwargs):
"""Service kind "NodePort" object
}
}
- self._add_port(22, protocol='TCP')
+ self._add_port(22, 'ssh', protocol='TCP')
node_ports = copy.deepcopy(kwargs.get('node_ports', []))
for port in node_ports:
+ if not self.MANDATORY_PARAMETERS.issubset(port.keys()):
+ missing_parameters = ', '.join(
+ str(param) for param in
+ (self.MANDATORY_PARAMETERS - set(port.keys())))
+ raise exceptions.KubernetesServiceObjectDefinitionError(
+ missing_parameters=missing_parameters)
port_number = port.pop('port')
- self._add_port(port_number, **port)
+ name = port.pop('name')
+ if not self.NAME_REGEX.match(name):
+ raise exceptions.KubernetesServiceObjectNameError(name=name)
+ self._add_port(port_number, name, **port)
- def _add_port(self, port, protocol=None, name=None, targetPort=None,
+ def _add_port(self, port, name, protocol=None, targetPort=None,
nodePort=None):
- _port = {'port': port}
+ _port = {'port': port,
+ 'name': name}
if protocol:
_port['protocol'] = protocol
- if name:
- _port['name'] = name
if targetPort:
_port['targetPort'] = targetPort
if nodePort:
k8s_utils.create_service(self.template)
def delete(self):
- k8s_utils.delete_service(self._name)
+ k8s_utils.delete_service(self._name, skip_codes=[404])
class CustomResourceDefinitionObject(object):
k8s_utils.create_custom_resource_definition(self._template)
def delete(self):
- k8s_utils.delete_custom_resource_definition(self._name)
+ k8s_utils.delete_custom_resource_definition(self._name, skip_codes=[404])
class NetworkObject(object):
- MANDATORY_PARAMETERS = {'name', 'plugin', 'args'}
+ MANDATORY_PARAMETERS = {'plugin', 'args'}
KIND = 'Network'
- def __init__(self, **kwargs):
+ def __init__(self, name, **kwargs):
if not self.MANDATORY_PARAMETERS.issubset(kwargs):
missing_parameters = ', '.join(
str(param) for param in
raise exceptions.KubernetesNetworkObjectDefinitionError(
missing_parameters=missing_parameters)
- self._name = kwargs['name']
+ self._name = name
self._plugin = kwargs['plugin']
self._args = kwargs['args']
self._crd = None
def create(self):
k8s_utils.create_network(self.scope, self.group, self.version,
- self.plural, self.template)
+ self.plural, self.template, self._name)
def delete(self):
k8s_utils.delete_network(self.scope, self.group, self.version,
- self.plural, self._name)
+ self.plural, self._name, skip_codes=[404])
class KubernetesTemplate(object):
context_cfg = copy.deepcopy(context_cfg)
servers_cfg = context_cfg.pop('servers', {})
crd_cfg = context_cfg.pop('custom_resources', [])
- networks_cfg = context_cfg.pop('networks', [])
+ networks_cfg = context_cfg.pop('networks', {})
self.name = name
self.ssh_key = '{}-key'.format(name)
self.rcs = {self._get_rc_name(rc): cfg
for rc, cfg in servers_cfg.items()}
- self.k8s_objs = [ReplicationControllerObject(
+ self.rc_objs = [ReplicationControllerObject(
rc, ssh_key=self.ssh_key, **cfg) for rc, cfg in self.rcs.items()]
self.service_objs = [ServiceNodePortObject(rc, **cfg)
for rc, cfg in self.rcs.items()]
self.crd = [CustomResourceDefinitionObject(self.name, **crd)
for crd in crd_cfg]
- self.network_objs = [NetworkObject(**nobj) for nobj in networks_cfg]
+ self.network_objs = [NetworkObject(net_name, **net_data)
+ for net_name, net_data in networks_cfg.items()]
self.pods = []
def _get_rc_name(self, rc_name):
if p.metadata.name.startswith(s)]
return self.pods
+
+ def get_rc_by_name(self, rc_name):
+ """Returns a ``ReplicationControllerObject``, searching by name"""
+ for rc in (rc for rc in self.rc_objs if rc.name == rc_name):
+ return rc