diff options
author | Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> | 2018-07-16 14:38:26 +0100 |
---|---|---|
committer | Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> | 2018-07-19 08:07:23 +0000 |
commit | d3ee90f9dd7335a3e13d1c4d71cad2b3b5c825fd (patch) | |
tree | fbb564084361fd37748efcdc28345d97759c3736 | |
parent | 3eb7c80aa614456b05e08651a55f7450e6864c79 (diff) |
Kubernetes NodePort must have 'name' if multiple created
In Kubernetes context, service NodePort can contain more than one port
defined. Actually, by default port SSH (22) is always created. If more
than one port is defined in the service template, 'name' parameter is
mandatory.
Names must be lowercase, containing alphanumeric characters or '-'.
Verification regex used by Kubernetes: [a-z0-9]([-a-z0-9]*[a-z0-9])?
JIRA: YARDSTICK-1324
Change-Id: I82791761d8eae24196c2f16aee9900af28d44c57
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
-rw-r--r-- | yardstick/common/exceptions.py | 10 | ||||
-rw-r--r-- | yardstick/orchestrator/kubernetes.py | 24 | ||||
-rw-r--r-- | yardstick/tests/unit/orchestrator/test_kubernetes.py | 44 |
3 files changed, 64 insertions, 14 deletions
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py index c25acbaf8..9397d4772 100644 --- a/yardstick/common/exceptions.py +++ b/yardstick/common/exceptions.py @@ -231,6 +231,16 @@ class KubernetesServiceObjectNotDefined(YardstickException): message = 'ServiceObject is not defined' +class KubernetesServiceObjectDefinitionError(YardstickException): + message = ('Kubernetes Service object definition error, missing ' + 'parameters: %(missing_parameters)s') + + +class KubernetesServiceObjectNameError(YardstickException): + message = ('Kubernetes Service object name "%(name)s" does not comply' + 'naming convention') + + class KubernetesCRDObjectDefinitionError(YardstickException): message = ('Kubernetes Custom Resource Definition Object error, missing ' 'parameters: %(missing_parameters)s') diff --git a/yardstick/orchestrator/kubernetes.py b/yardstick/orchestrator/kubernetes.py index 98832908c..1da177945 100644 --- a/yardstick/orchestrator/kubernetes.py +++ b/yardstick/orchestrator/kubernetes.py @@ -8,6 +8,7 @@ ############################################################################## import copy +import re from oslo_serialization import jsonutils @@ -234,6 +235,9 @@ class ReplicationControllerObject(object): 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 @@ -251,19 +255,27 @@ class ServiceNodePortObject(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: diff --git a/yardstick/tests/unit/orchestrator/test_kubernetes.py b/yardstick/tests/unit/orchestrator/test_kubernetes.py index 8d351e419..9da421a4a 100644 --- a/yardstick/tests/unit/orchestrator/test_kubernetes.py +++ b/yardstick/tests/unit/orchestrator/test_kubernetes.py @@ -513,24 +513,52 @@ class ServiceNodePortObjectTestCase(base.BaseUnitTestCase): def test__init(self): with mock.patch.object(kubernetes.ServiceNodePortObject, '_add_port') \ as mock_add_port: - kubernetes.ServiceNodePortObject('fake_name', - node_ports=[{'port': 80}]) + kubernetes.ServiceNodePortObject( + 'fake_name', node_ports=[{'port': 80, 'name': 'web'}]) - mock_add_port.assert_has_calls([mock.call(22, protocol='TCP'), - mock.call(80)]) + mock_add_port.assert_has_calls([mock.call(22, 'ssh', protocol='TCP'), + mock.call(80, 'web')]) + + @mock.patch.object(kubernetes.ServiceNodePortObject, '_add_port') + def test__init_missing_mandatory_parameters(self, *args): + with self.assertRaises( + exceptions.KubernetesServiceObjectDefinitionError): + kubernetes.ServiceNodePortObject( + 'fake_name', node_ports=[{'port': 80}]) + with self.assertRaises( + exceptions.KubernetesServiceObjectDefinitionError): + kubernetes.ServiceNodePortObject( + 'fake_name', node_ports=[{'name': 'web'}]) + + @mock.patch.object(kubernetes.ServiceNodePortObject, '_add_port') + def test__init_missing_bad_name(self, *args): + with self.assertRaises( + exceptions.KubernetesServiceObjectNameError): + kubernetes.ServiceNodePortObject( + 'fake_name', node_ports=[{'port': 80, 'name': '-web'}]) + with self.assertRaises( + exceptions.KubernetesServiceObjectNameError): + kubernetes.ServiceNodePortObject( + 'fake_name', node_ports=[{'port': 80, 'name': 'Web'}]) + with self.assertRaises( + exceptions.KubernetesServiceObjectNameError): + kubernetes.ServiceNodePortObject( + 'fake_name', node_ports=[{'port': 80, 'name': 'web-'}]) def test__add_port(self): nodeport_object = kubernetes.ServiceNodePortObject('fake_name') - port_ssh = {'port': 22, - 'protocol': 'TCP',} + port_ssh = {'name': 'ssh', + 'port': 22, + 'protocol': 'TCP'} port_definition = {'port': 80, 'protocol': 'TCP', 'name': 'web', 'targetPort': 10080, 'nodePort': 30080} port = copy.deepcopy(port_definition) - port.pop('port') - nodeport_object._add_port(80, **port) + _port = port.pop('port') + name = port.pop('name') + nodeport_object._add_port(_port, name, **port) self.assertEqual([port_ssh, port_definition], nodeport_object.template['spec']['ports']) |