Merge "Remove Image and ZunService class from controllers"

This commit is contained in:
Jenkins 2017-01-18 18:22:49 +00:00 committed by Gerrit Code Review
commit 44da21a8f4
4 changed files with 52 additions and 176 deletions

View File

@ -12,15 +12,13 @@
from oslo_log import log as logging
from oslo_utils import strutils
from oslo_utils import timeutils
import pecan
from pecan import rest
from zun.api.controllers import base
from zun.api.controllers import link
from zun.api.controllers import types
from zun.api.controllers.v1 import collection
from zun.api.controllers.v1.schemas import images as schema
from zun.api.controllers.v1.views import images_view as view
from zun.api import utils as api_utils
from zun.common import exception
from zun.common.i18n import _LE
@ -32,84 +30,11 @@ from zun import objects
LOG = logging.getLogger(__name__)
class Image(base.APIBase):
"""API representation of an image.
This class enforces type checking and value constraints, and converts
between the internal object model and the API representation of
an image.
"""
fields = {
'uuid': {
'validate': types.Uuid.validate,
},
'image_id': {
'validate': types.NameType.validate,
'validate_args': {
'pattern': types.image_name_pattern
},
},
'repo': {
'validate': types.NameType.validate,
'validate_args': {
'pattern': types.image_name_pattern
},
'mandatory': True
},
'tag': {
'validate': types.NameType.validate,
'validate_args': {
'pattern': types.image_name_pattern
},
},
'size': {
'validate': types.ImageSize.validate,
},
}
def __init__(self, **kwargs):
super(Image, self).__init__(**kwargs)
@staticmethod
def _convert_with_links(image, url, expand=True):
if not expand:
image.unset_fields_except([
'uuid', 'image_id', 'repo', 'tag', 'size'])
image.links = [link.Link.make_link(
'self', url,
'images', image.uuid),
link.Link.make_link(
'bookmark', url,
'images', image.uuid,
bookmark=True)]
return image
@classmethod
def convert_with_links(cls, rpc_image, expand=True):
image = Image(**rpc_image)
return cls._convert_with_links(image, pecan.request.host_url,
expand)
@classmethod
def sample(cls, expand=True):
sample = cls(uuid='27e3153e-d5bf-4b7e-b517-fb518e17f35c',
repo='ubuntu',
tag='latest',
size='700m',
created_at=timeutils.utcnow(),
updated_at=timeutils.utcnow())
return cls._convert_with_links(sample, 'http://localhost:9517', expand)
class ImageCollection(collection.Collection):
"""API representation of a collection of images."""
fields = {
'images': {
'validate': types.List(types.Custom(Image)).validate,
},
'images'
}
"""A list containing images objects"""
@ -121,20 +46,10 @@ class ImageCollection(collection.Collection):
def convert_with_links(rpc_images, limit, url=None,
expand=False, **kwargs):
collection = ImageCollection()
# TODO(sbiswas7): This is the ugly part of the deal.
# We need to convert this p thing below as dict for now
# Removal of dict-compat lead to this change.
collection.images = [Image.convert_with_links(p.as_dict(), expand)
for p in rpc_images]
collection.images = [view.format_image(url, p) for p in rpc_images]
collection.next = collection.get_next(limit, url=url, **kwargs)
return collection
@classmethod
def sample(cls):
sample = cls()
sample.images = [Image.sample(expand=False)]
return sample
class ImagesController(rest.RestController):
'''Controller for Images'''
@ -206,9 +121,7 @@ class ImagesController(rest.RestController):
# Set the HTTP Location Header
pecan.response.location = link.build_url('images', new_image.uuid)
pecan.response.status = 202
# TODO(sbiswas7): Schema validation is a better approach than
# back n forth conversion into dicts and objects.
return Image.convert_with_links(new_image.as_dict())
return view.format_image(pecan.request.host_url, new_image)
@pecan.expose('json')
@exception.wrap_pecan_controller_exception

View File

@ -0,0 +1,43 @@
#
# 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.
import itertools
from zun.api.controllers import link
_basic_keys = (
'uuid',
'repo',
'tag'
'size'
)
def format_image(url, image):
def transform(key, value):
if key not in _basic_keys:
return
if key == 'uuid':
yield ('uuid', value)
yield ('links', [link.Link.make_link(
'self', url, 'images', value),
link.Link.make_link(
'bookmark', url,
'images', value,
bookmark=True)])
else:
yield (key, value)
return dict(itertools.chain.from_iterable(
transform(k, v) for k, v in image.as_dict().items()))

View File

@ -13,8 +13,6 @@
import pecan
from pecan import rest
from zun.api.controllers import base
from zun.api.controllers import types
from zun.api.controllers.v1 import collection
from zun.api import servicegroup as svcgrp_api
from zun.common import exception
@ -22,74 +20,10 @@ from zun.common import policy
from zun import objects
class ZunService(base.APIBase):
fields = {
'host': {
'validate': types.String.validate,
'validate_args': {
'min_length': 1,
'max_length': 255,
},
},
'binary': {
'validate': types.String.validate,
'validate_args': {
'min_length': 1,
'max_length': 255,
},
},
'state': {
'validate': types.String.validate,
'validate_args': {
'min_length': 1,
'max_length': 255,
},
},
'id': {
'validate': types.Integer.validate,
'validate_args': {
'minimum': 1,
},
},
'report_count': {
'validate': types.Integer.validate,
'validate_args': {
'minimum': 0,
},
},
'disabled': {
'validate': types.Bool.validate,
'validate_args': {
'default': False,
},
},
'disabled_reason': {
'validate': types.String.validate,
'validate_args': {
'min_length': 0,
'max_length': 255,
},
},
'created_at': {
'validate': types.DateTime.validate,
},
'updated_at': {
'validate': types.DateTime.validate,
},
}
def __init__(self, state, **kwargs):
super(ZunService, self).__init__(**kwargs)
setattr(self, 'state', state)
class ZunServiceCollection(collection.Collection):
fields = {
'services': {
'validate': types.List(types.Custom(ZunService)).validate,
},
'services'
}
def __init__(self, **kwargs):
@ -102,9 +36,10 @@ class ZunServiceCollection(collection.Collection):
collection = ZunServiceCollection()
collection.services = []
for p in rpc_hsvcs:
hsvc = p.as_dict()
alive = servicegroup_api.service_is_up(p)
state = 'up' if alive else 'down'
hsvc = ZunService(state, **p.as_dict())
hsvc['state'] = state
collection.services.append(hsvc)
next = collection.get_next(limit=None, url=None, **kwargs)
if next is not None:

View File

@ -12,28 +12,13 @@
import mock
from zun.api.controllers.v1 import zun_services as zservice
from zun.api import servicegroup
from zun import objects
from zun.tests import base
from zun.tests.unit.api import base as api_base
from zun.tests.unit.api import utils as api_utils
class TestZunServiceObject(base.BaseTestCase):
def setUp(self):
super(TestZunServiceObject, self).setUp()
self.rpc_dict = api_utils.zservice_get_data()
def test_msvc_obj_fields_filtering(self):
"""Test that it does filtering fields """
self.rpc_dict['fake-key'] = 'fake-value'
msvco = zservice.ZunService("up", **self.rpc_dict)
self.assertNotIn('fake-key', msvco.fields)
class db_rec(object):
class DbRec(object):
def __init__(self, d):
self.rec_as_dict = d
@ -53,7 +38,7 @@ class TestZunServiceController(api_base.FunctionalTest):
for i in range(count):
elem = api_utils.zservice_get_data()
elem['id'] = i + 1
rec = db_rec(elem)
rec = DbRec(elem)
reclist.append(rec)
return reclist