Add "ports" parameters in Kubernetes context 37/57537/15
authorJohn O'Loughlin <john.oloughlin@intel.com>
Thu, 17 May 2018 15:06:53 +0000 (15:06 +0000)
committerRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Tue, 10 Jul 2018 09:31:30 +0000 (10:31 +0100)
This new parameter, "ports", will allow the user to
automatically to add port variables in a pod definition:
context:
  type: Kubernetes
    servers:
        host:
            image: ...
            commands: ...
            ports:
                - containerPort: <port value>    # Mandatory
                  hostIP: <host IP>              # Optional
                  hostPort: <host port>          # Optional
                  name: <port name>              # Optional
                  protocol: <protocol name>      # Optional

The port type and the definition must be one of the supported ones
in Kubernetes [1].

Container port definition, V1 API, Kubernetes Python library v6.0.0 [2]

[1] https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/
[2] https://github.com/kubernetes-client/python/blob/6.0.0/kubernetes/client/models/v1_container_port.py

JIRA: YARDSTICK-1183

Change-Id: I3673dbeec8d380cb2f8b1dacf6c25c7cdbc37e28
Signed-off-by: John O Loughlin <john.oloughlin@intel.com>
yardstick/common/exceptions.py
yardstick/orchestrator/kubernetes.py
yardstick/tests/unit/orchestrator/test_kubernetes.py

index 018654a..641c4e1 100644 (file)
@@ -241,6 +241,10 @@ class KubernetesWrongRestartPolicy(YardstickException):
     message = 'Restart policy "%(rpolicy)s" is not valid'
 
 
+class KubernetesContainerPortNotDefined(YardstickException):
+    message = 'Container port not defined in "%(port)s"'
+
+
 class ScenarioCreateNetworkError(YardstickException):
     message = 'Create Neutron Network Scenario failed'
 
index 2c401fc..6fd3fa6 100644 (file)
@@ -22,7 +22,8 @@ class ContainerObject(object):
     SSH_MOUNT_PATH = '/tmp/.ssh/'
     IMAGE_DEFAULT = 'openretriever/yardstick'
     COMMAND_DEFAULT = '/bin/bash'
-    RESOURCES = ['requests', 'limits']
+    RESOURCES = ('requests', 'limits')
+    PORT_OPTIONS = ('containerPort', 'hostIP', 'hostPort', 'name', 'protocol')
 
     def __init__(self, name, ssh_key, **kwargs):
         self._name = name
@@ -34,6 +35,7 @@ class ContainerObject(object):
         self._security_context = kwargs.get('securityContext')
         self._env = kwargs.get('env', [])
         self._resources = kwargs.get('resources', {})
+        self._ports = kwargs.get('ports', [])
 
     def _create_volume_mounts(self):
         """Return all "volumeMounts" items per container"""
@@ -66,6 +68,15 @@ class ContainerObject(object):
             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
index e9c3c97..afadf74 100644 (file)
@@ -311,6 +311,44 @@ class ContainerObjectTestCase(base.BaseUnitTestCase):
                              'value': 'fake_var_value'}]}
         self.assertEqual(expected, container_obj.get_container_item())
 
+    def test_get_container_item_with_ports_multi_parameter(self):
+        volume_mount = {'name': 'fake_name',
+                        'mountPath': 'fake_path'}
+        args = ['arg1', 'arg2']
+        container_obj = kubernetes.ContainerObject(
+            'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+            args=args, ports=[{'containerPort': 'fake_port_name',
+                               'hostPort': 'fake_host_port',
+                               'name': 'fake_name',
+                               'protocol': 'fake_protocol',
+                               'invalid_varible': 'fakeinvalid_varible',
+                               'hostIP': 'fake_port_number'}])
+        expected = {'args': args,
+                    'command': [
+                        kubernetes.ContainerObject.COMMAND_DEFAULT],
+                    'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+                    'name': 'cname-container',
+                    'volumeMounts': container_obj._create_volume_mounts(),
+                    'ports': [{'containerPort': 'fake_port_name',
+                               'hostPort': 'fake_host_port',
+                               'name': 'fake_name',
+                               'protocol': 'fake_protocol',
+                               'hostIP': 'fake_port_number'}]}
+        self.assertEqual(expected, container_obj.get_container_item())
+
+    def test_get_container_item_with_ports_no_container_port(self):
+        with self.assertRaises(exceptions.KubernetesContainerPortNotDefined):
+            volume_mount = {'name': 'fake_name',
+                            'mountPath': 'fake_path'}
+            args = ['arg1', 'arg2']
+            container_obj = kubernetes.ContainerObject(
+                    'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+                    args=args, ports=[{'hostPort': 'fake_host_port',
+                                       'name': 'fake_name',
+                                       'protocol': 'fake_protocol',
+                                       'hostIP': 'fake_port_number'}])
+            container_obj.get_container_item()
+
     def test_get_container_item_with_resources(self):
         volume_mount = {'name': 'fake_name',
                         'mountPath': 'fake_path'}