Update service manifest parsing according to v1beta3
Now that Kubernetes 0.15.0 release is supported and it has v1beta3, the manifest structure has changed from v1beta1 to v1beta3. This change implements the v1beta3 manifest parsing logic for service resource of Kubernetes. Change-Id: I1200473f91118eaa48b1cec386f30cf8a50708b5 Partially-Implements: blueprint python-k8sclient
This commit is contained in:
parent
2704710e28
commit
08a27f1c0f
|
@ -37,7 +37,7 @@ class ServicePatchType(v1_base.K8sPatchType):
|
|||
@staticmethod
|
||||
def internal_attrs():
|
||||
defaults = v1_base.K8sPatchType.internal_attrs()
|
||||
return defaults + ['/selector', '/port', '/ip']
|
||||
return defaults + ['/selector', '/ports', '/ip']
|
||||
|
||||
|
||||
class Service(v1_base.K8sResourceBase):
|
||||
|
@ -51,7 +51,7 @@ class Service(v1_base.K8sResourceBase):
|
|||
ip = wtypes.text
|
||||
"""IP of this service"""
|
||||
|
||||
port = wsme.wsattr(wtypes.IntegerType(), readonly=True)
|
||||
ports = wsme.wsattr([{wtypes.text: wtypes.IntegerType()}], readonly=True)
|
||||
"""Port of this service"""
|
||||
|
||||
links = wsme.wsattr([link.Link], readonly=True)
|
||||
|
@ -72,7 +72,7 @@ class Service(v1_base.K8sResourceBase):
|
|||
def _convert_with_links(service, url, expand=True):
|
||||
if not expand:
|
||||
service.unset_fields_except(['uuid', 'name', 'bay_uuid', 'labels',
|
||||
'selector', 'ip', 'port'])
|
||||
'selector', 'ip', 'ports'])
|
||||
|
||||
service.links = [link.Link.make_link('self', url,
|
||||
'services', service.uuid),
|
||||
|
@ -95,20 +95,34 @@ class Service(v1_base.K8sResourceBase):
|
|||
labels={'label1': 'foo'},
|
||||
selector={'label1': 'foo'},
|
||||
ip='172.17.2.2',
|
||||
port=80,
|
||||
ports=[
|
||||
{
|
||||
"port": 88,
|
||||
"targetPort": 6379,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
manifest_url='file:///tmp/rc.yaml',
|
||||
manifest='''{
|
||||
"id": "service_foo",
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1beta1",
|
||||
"port": 88,
|
||||
"selector": {
|
||||
"bar": "foo"
|
||||
"metadata": {
|
||||
"name": "test",
|
||||
"labels": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"bar": "foo"
|
||||
"spec": {
|
||||
"ports": [
|
||||
{
|
||||
"port": 88,
|
||||
"targetPort": 6379,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"selector": {
|
||||
"bar": "foo"
|
||||
}
|
||||
}
|
||||
}''',
|
||||
}''',
|
||||
created_at=datetime.datetime.utcnow(),
|
||||
updated_at=datetime.datetime.utcnow())
|
||||
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
|
||||
|
@ -119,16 +133,20 @@ class Service(v1_base.K8sResourceBase):
|
|||
except ValueError as e:
|
||||
raise exception.InvalidParameterValue(message=str(e))
|
||||
try:
|
||||
self.name = manifest["id"]
|
||||
except KeyError:
|
||||
self.name = manifest["metadata"]["name"]
|
||||
except (KeyError, TypeError):
|
||||
raise exception.InvalidParameterValue(
|
||||
"'id' can't be empty in manifest.")
|
||||
if "port" in manifest:
|
||||
self.port = manifest["port"]
|
||||
if "selector" in manifest:
|
||||
self.selector = manifest["selector"]
|
||||
if "labels" in manifest:
|
||||
self.labels = manifest["labels"]
|
||||
"Field metadata['name'] can't be empty in manifest.")
|
||||
try:
|
||||
self.ports = manifest["spec"]["ports"][:]
|
||||
except (KeyError, TypeError):
|
||||
raise exception.InvalidParameterValue(
|
||||
"Field spec['ports'] can't be empty in manifest.")
|
||||
|
||||
if "selector" in manifest["spec"]:
|
||||
self.selector = manifest["spec"]["selector"]
|
||||
if "labels" in manifest["metadata"]:
|
||||
self.labels = manifest["metadata"]["labels"]
|
||||
|
||||
|
||||
class ServiceCollection(collection.Collection):
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# 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.
|
||||
"""rename service port
|
||||
|
||||
Revision ID: 2b5f24dd95de
|
||||
Revises: 592131657ca1
|
||||
Create Date: 2015-04-29 05:52:52.204095
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2b5f24dd95de'
|
||||
down_revision = '3b6c4c42adb4'
|
||||
|
||||
from alembic import op
|
||||
|
||||
from magnum.db.sqlalchemy import models
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.alter_column('service', 'port',
|
||||
new_column_name='ports',
|
||||
existing_type=models.JSONEncodedList())
|
|
@ -704,8 +704,8 @@ class Connection(api.Connection):
|
|||
query = query.filter_by(name=filters['name'])
|
||||
if 'ip' in filters:
|
||||
query = query.filter_by(ip=filters['ip'])
|
||||
if 'port' in filters:
|
||||
query = query.filter_by(port=filters['port'])
|
||||
if 'ports' in filters:
|
||||
query = query.filter_by(ports=filters['ports'])
|
||||
|
||||
return query
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ class Service(Base):
|
|||
labels = Column(JSONEncodedDict)
|
||||
selector = Column(JSONEncodedDict)
|
||||
ip = Column(String(36))
|
||||
port = Column(Integer())
|
||||
ports = Column(JSONEncodedList)
|
||||
project_id = Column(String(255))
|
||||
user_id = Column(String(255))
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class Service(base.MagnumObject):
|
|||
'labels': obj_utils.dict_or_none,
|
||||
'selector': obj_utils.dict_or_none,
|
||||
'ip': obj_utils.str_or_none,
|
||||
'port': obj_utils.int_or_none,
|
||||
'ports': obj_utils.list_or_none,
|
||||
'manifest_url': obj_utils.str_or_none,
|
||||
'manifest': obj_utils.str_or_none,
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ class TestListService(api_base.FunctionalTest):
|
|||
|
||||
def _assert_service_fields(self, service):
|
||||
service_fields = ['name', 'bay_uuid', 'name', 'labels', 'selector',
|
||||
'ip', 'port']
|
||||
'ip', 'ports']
|
||||
for field in service_fields:
|
||||
self.assertIn(field, service)
|
||||
|
||||
|
|
|
@ -67,17 +67,25 @@ def service_post_data(**kw):
|
|||
service = utils.get_test_service(**kw)
|
||||
if 'manifest' not in service:
|
||||
service['manifest'] = '''{
|
||||
"id": "service_foo",
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1beta1",
|
||||
"port": 88,
|
||||
"selector": {
|
||||
"bar": "foo"
|
||||
"metadata": {
|
||||
"name": "test",
|
||||
"labels": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"bar": "foo"
|
||||
"spec": {
|
||||
"ports": [
|
||||
{
|
||||
"port": 88,
|
||||
"targetPort": 6379,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"selector": {
|
||||
"bar": "foo"
|
||||
}
|
||||
}
|
||||
}'''
|
||||
}'''
|
||||
internal = service_controller.ServicePatchType.internal_attrs()
|
||||
return remove_internal(service, internal)
|
||||
|
||||
|
|
|
@ -91,11 +91,11 @@ class DbServiceTestCase(base.DbTestCase):
|
|||
service1 = utils.create_test_service(name='service-one',
|
||||
uuid=magnum_utils.generate_uuid(),
|
||||
bay_uuid=bay1['uuid'],
|
||||
port=8000)
|
||||
ports=[{'port': 8000}])
|
||||
service2 = utils.create_test_service(name='service-two',
|
||||
uuid=magnum_utils.generate_uuid(),
|
||||
bay_uuid=bay2['uuid'],
|
||||
port=8001)
|
||||
ports=[{'port': 8001}])
|
||||
|
||||
res = self.dbapi.get_service_list(self.context,
|
||||
filters={'bay_uuid': bay1['uuid']})
|
||||
|
@ -114,11 +114,11 @@ class DbServiceTestCase(base.DbTestCase):
|
|||
self.assertEqual([], [r.id for r in res])
|
||||
|
||||
res = self.dbapi.get_service_list(self.context,
|
||||
filters={'port': 8000})
|
||||
filters={'ports': [{'port': 8000}]})
|
||||
self.assertEqual([service1.id], [r.id for r in res])
|
||||
|
||||
res = self.dbapi.get_service_list(self.context,
|
||||
filters={'port': 8001})
|
||||
filters={'ports': [{'port': 8001}]})
|
||||
self.assertEqual([service2.id], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_bay_not_exist(self):
|
||||
|
|
|
@ -126,7 +126,7 @@ def get_test_service(**kw):
|
|||
'labels': kw.get('labels', {'name': 'foo'}),
|
||||
'selector': kw.get('selector', {'name': 'foo'}),
|
||||
'ip': kw.get('ip', '172.17.2.2'),
|
||||
'port': kw.get('port', 80),
|
||||
'ports': kw.get('ports', [{'port': 80}]),
|
||||
'created_at': kw.get('created_at'),
|
||||
'updated_at': kw.get('updated_at'),
|
||||
}
|
||||
|
|
|
@ -95,12 +95,12 @@ class TestServiceObject(base.DbTestCase):
|
|||
with mock.patch.object(self.dbapi, 'update_service',
|
||||
autospec=True) as mock_update_service:
|
||||
service = objects.Service.get_by_uuid(self.context, uuid)
|
||||
service.port = 4567
|
||||
service.ports = [{'port': 4567}]
|
||||
service.save()
|
||||
|
||||
mock_get_service.assert_called_once_with(self.context, uuid)
|
||||
mock_update_service.assert_called_once_with(
|
||||
uuid, {'port': 4567})
|
||||
uuid, {'ports': [{'port': 4567}]})
|
||||
self.assertEqual(self.context, service._context)
|
||||
|
||||
def test_refresh(self):
|
||||
|
|
Loading…
Reference in New Issue