Added beginning of API layer required for PoC, plus unit tests
Change-Id: Ifb6586c97f5388471b4eb5012f729fdeab9cb174
This commit is contained in:
parent
31d937a62c
commit
ba6696b111
|
@ -20,9 +20,24 @@ from wsmeext.pecan import wsexpose
|
|||
|
||||
from graffiti.api.model.v1.resource import Resource
|
||||
|
||||
from graffiti.api.model.v1.resource_controller import LocalResourceController
|
||||
|
||||
from graffiti.common.utils import _
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
import six
|
||||
|
||||
resources = []
|
||||
|
||||
resource_controller_group = cfg.OptGroup('resource_controller')
|
||||
resource_controller_opts = [
|
||||
cfg.StrOpt('type',
|
||||
help=_("The resource controller plugin"))
|
||||
]
|
||||
|
||||
cfg.CONF.register_group(resource_controller_group)
|
||||
cfg.CONF.register_opts(resource_controller_opts,
|
||||
group=resource_controller_group)
|
||||
|
||||
|
||||
class ResourceController(RestController):
|
||||
|
@ -31,29 +46,49 @@ class ResourceController(RestController):
|
|||
|
||||
self.status = 200
|
||||
|
||||
self._controller = self._load_controller('Local')
|
||||
|
||||
def _load_controller(self, which_one):
|
||||
controller_type = cfg.CONF.resource_controller.type
|
||||
controller_type = controller_type if controller_type else 'Local'
|
||||
|
||||
# TODO(lakshmi): Load the controller here
|
||||
_controller = LocalResourceController()
|
||||
|
||||
return _controller
|
||||
|
||||
@wsexpose()
|
||||
def options():
|
||||
pass
|
||||
|
||||
@wsexpose(Resource, six.text_type)
|
||||
def get_one(self, id):
|
||||
global resources
|
||||
|
||||
for res in resources:
|
||||
if res.id.lower() == id.lower():
|
||||
return res
|
||||
res = self._controller.get_resource(id)
|
||||
if res:
|
||||
return res
|
||||
|
||||
res = Response(Resource(), status_code=404, error="Resource Not Found")
|
||||
return res
|
||||
|
||||
@wsexpose([Resource])
|
||||
def get_all(self):
|
||||
global resources
|
||||
@wsexpose([Resource], six.text_type)
|
||||
def get_all(self, query_string=None):
|
||||
|
||||
return resources
|
||||
res_list = self._controller.find_resources(query_string)
|
||||
if res_list:
|
||||
return res_list
|
||||
|
||||
return []
|
||||
|
||||
@wsexpose(Resource, six.text_type, Resource)
|
||||
def put(self, id, resource):
|
||||
|
||||
self._controller.set_resource(id, resource_definition=resource)
|
||||
|
||||
return resource
|
||||
|
||||
@wsexpose(Resource, Resource)
|
||||
def post(self, resource):
|
||||
global resources
|
||||
|
||||
resources.append(resource)
|
||||
self._controller.set_resource(resource_definition=resource)
|
||||
|
||||
return resource
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
#import json
|
||||
|
||||
from pecan.hooks import PecanHook
|
||||
|
||||
|
@ -30,7 +30,8 @@ class CorsHook(PecanHook):
|
|||
state.response.headers['Content-Length'] = \
|
||||
str(len(state.response.body))
|
||||
|
||||
if state.response.headers['Content-Type'].find('json') != -1:
|
||||
# TODO(lakshmi): this fails in Python 3.3, don't know why
|
||||
# if state.response.headers['Content-Type'].find('json') != -1:
|
||||
# Sort the Response Body's JSON
|
||||
json_str = json.loads(state.response.body)
|
||||
state.response.body = json.dumps(json_str, sort_keys=True)
|
||||
# json_str = json.loads(state.response.body)
|
||||
# state.response.body = json.dumps(json_str, sort_keys=True)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
class ResourceControllerBase(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(ResourceControllerBase, self).__init__(**kwargs)
|
||||
|
||||
self._type = 'None'
|
||||
|
||||
def get_resource(self, id):
|
||||
return None
|
||||
|
||||
def find_resources(self, query_string):
|
||||
return []
|
||||
|
||||
def set_resource(self, id=None, resource_definition=None):
|
||||
pass
|
||||
|
||||
|
||||
class LocalResourceController(ResourceControllerBase):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(LocalResourceController, self).__init__(**kwargs)
|
||||
|
||||
self._type = 'LocalResourceController'
|
||||
|
||||
self._resources = dict()
|
||||
self._last_id = 0
|
||||
|
||||
def get_resource(self, id):
|
||||
return self._resources[id]
|
||||
|
||||
def find_resources(self, query_string):
|
||||
return self._resources
|
||||
|
||||
def set_resource(self, id=None, resource_definition=None):
|
||||
if not id:
|
||||
id = self._generate_id()
|
||||
|
||||
self._resources[id] = resource_definition
|
||||
|
||||
def _generate_id(self):
|
||||
return_value = self._last_id
|
||||
self._last_id += 1
|
||||
|
||||
return return_value
|
|
@ -22,4 +22,10 @@ def prepare_service(argv=None):
|
|||
if argv is None:
|
||||
argv = sys.argv
|
||||
|
||||
cfg.CONF(argv[3:], project='graffiti')
|
||||
# when running unit tests, argv is inaccessible for some unknown
|
||||
# reason; need to revisit this logic again running under Apache2
|
||||
# TODO(lakshmi): figure this out
|
||||
try:
|
||||
cfg.CONF(argv[3:], project='graffiti')
|
||||
except BaseException:
|
||||
pass
|
||||
|
|
|
@ -31,9 +31,7 @@ class TestControllerV1(base.TestCase):
|
|||
def test_v1_exists(self):
|
||||
root = RootController()
|
||||
self.assertIn(hasattr(root, 'v1'), [True])
|
||||
pass
|
||||
|
||||
def test_v1_resource_exists(self):
|
||||
v1 = V1Controller()
|
||||
self.assertIn(hasattr(v1, 'resource'), [True])
|
||||
pass
|
||||
|
|
|
@ -19,11 +19,78 @@ test_graffiti
|
|||
|
||||
Tests for `graffiti` module.
|
||||
"""
|
||||
import os
|
||||
|
||||
import pecan
|
||||
import pecan.testing
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from graffiti.api.tests import base
|
||||
|
||||
|
||||
class TestGraffiti(base.TestCase):
|
||||
|
||||
def test_something(self):
|
||||
pass
|
||||
PATH_PREFIX = '/v1'
|
||||
|
||||
def setUp(self):
|
||||
super(TestGraffiti, self).setUp()
|
||||
self.app = self._make_app()
|
||||
cfg.CONF.set_override(name='type', override='Local',
|
||||
group='resource_controller')
|
||||
|
||||
def _make_app(self):
|
||||
root_dir = self.path_get()
|
||||
self.config = {
|
||||
'app': {
|
||||
'root': 'graffiti.api.controllers.root.RootController',
|
||||
'modules': ['graffiti.api'],
|
||||
'template_path': '%s/graffiti/templates' % root_dir,
|
||||
},
|
||||
}
|
||||
|
||||
return pecan.testing.load_test_app(self.config)
|
||||
|
||||
def tearDown(self):
|
||||
super(TestGraffiti, self).tearDown()
|
||||
pecan.set_config({}, overwrite=True)
|
||||
|
||||
def path_get(self, project_file=None):
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..',
|
||||
'..', ))
|
||||
if project_file:
|
||||
return os.path.join(root, project_file)
|
||||
else:
|
||||
return root
|
||||
|
||||
def get_json(self, path, expect_errors=False, headers=None,
|
||||
extra_environ=None, q=[], **params):
|
||||
full_path = self.PATH_PREFIX + path
|
||||
query_params = {'q.field': [],
|
||||
'q.value': [],
|
||||
'q.op': [], }
|
||||
for query in q:
|
||||
for name in ['field', 'op', 'value']:
|
||||
query_params['q.%s' % name].append(query.get(name, ''))
|
||||
|
||||
all_params = {}
|
||||
all_params.update(params)
|
||||
if q:
|
||||
all_params.update(query_params)
|
||||
|
||||
response = self.app.get(full_path,
|
||||
params=all_params,
|
||||
headers=headers,
|
||||
extra_environ=extra_environ,
|
||||
expect_errors=expect_errors)
|
||||
|
||||
if not expect_errors:
|
||||
response = response
|
||||
|
||||
return response
|
||||
|
||||
def test_get_all(self):
|
||||
response = self.get_json('/resource')
|
||||
self.assertEqual(response.status_int, 200)
|
||||
self.assertEqual(response.content_type, 'application/json')
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# look at heat/openstack/common/gettextutils.py when we actually need
|
||||
# to implement this method
|
||||
|
||||
|
||||
# TODO(travis): need localization strategy
|
||||
def _(msg):
|
||||
return msg
|
|
@ -2,3 +2,4 @@ pbr>=0.5.21,<1.0
|
|||
Babel>=0.9.6
|
||||
pecan>=0.4.4
|
||||
WSME>=0.6
|
||||
oslo.config
|
||||
|
|
Loading…
Reference in New Issue