Add bindings for overcloud API entrypoints

Add the entrypoint for the new overcloud type provided in the Tuskar API
after the domain model refactor.

Change-Id: I49b63905b5d657e63471bc3d02cc7cc2edd90caf
Implements: blueprint update-to-match-api-changes
This commit is contained in:
Dougal Matthews 2014-01-27 09:58:31 +00:00
parent 06d2a094a7
commit 3cc9879347
5 changed files with 189 additions and 4 deletions

View File

@ -56,16 +56,26 @@ class Manager(object):
path is returned. Otherwise the collection path is returned. path is returned. Otherwise the collection path is returned.
:param id: id of the resource (optional) :param id: id of the resource (optional)
:type id: string
:return: A string representing the API endpoint
:rtype: string
""" """
raise NotImplementedError("_path method not implemented.") raise NotImplementedError("_path method not implemented.")
def _single_path(self, id): def _single_path(self, id):
"""This is like the _path method, but it asserts that the rack_id """This is like the _path method, but it asserts that the id
parameter is not None. This is useful e.g. when you want to make sure parameter is not None. This is useful e.g. when you want to make sure
that you can't issue a DELETE request on a collection URL. that you can't issue a DELETE request on a collection URL.
:param id: id of the resource (not optional)
:type id: string
:return: A string representing the API endpoint
:rtype: string
""" """
if not id: if not id:
raise ValueError("{0} id for deletion must not be null." raise ValueError("{0} id is required."
.format(self.resource_class)) .format(self.resource_class))
return self._path(id) return self._path(id)

View File

@ -55,5 +55,5 @@ class ClientTest(tutils.TestCase):
self.client = client.Client(self.endpoint) self.client = client.Client(self.endpoint)
def test_managers_present(self): def test_managers_present(self):
#TODO(dmatthew): re-add tests for the managers with the new versions self.assertThat(self.client, HasManager('OvercloudManager',
pass 'overclouds'))

View File

@ -0,0 +1,78 @@
# 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 mock
import tuskarclient.tests.utils as tutils
from tuskarclient.v1 import overclouds
class OvercloudManagerTest(tutils.TestCase):
def setUp(self):
"""Create a mock API object and bind to the OvercloudManager manager.
"""
super(OvercloudManagerTest, self).setUp()
self.api = mock.Mock()
self.om = overclouds.OvercloudManager(self.api)
def test_get(self):
"""Test a standard GET operation to read/retrieve the overcloud."""
self.om._get = mock.Mock(return_value='fake_overcloud')
self.assertEqual(self.om.get('fake_overcloud'), 'fake_overcloud')
self.om._get.assert_called_with('/v1/overclouds/fake_overcloud')
def test_get_404(self):
"""Test a 404 response to a standard GET."""
self.om._get = mock.Mock(return_value=None)
self.assertEqual(self.om.get('fake_overcloud'), None)
self.om._get.assert_called_with('/v1/overclouds/fake_overcloud')
def test_list(self):
"""Test retrieving a list of overclouds via GET."""
self.om._list = mock.Mock(return_value=['fake_overcloud'])
self.assertEqual(self.om.list(), ['fake_overcloud'])
self.om._list.assert_called_with('/v1/overclouds')
def test_create(self):
"""Test creating a new overcloud via POST."""
self.om._create = mock.Mock(return_value=['fake_overcloud'])
self.assertEqual(
self.om.create(dummy='dummy overcloud data'),
['fake_overcloud'])
self.om._create.assert_called_with(
'/v1/overclouds',
{'dummy': 'dummy overcloud data'})
def test_update(self):
"""Test updating an overcloud via POST."""
self.om._update = mock.Mock(return_value=['fake_overcloud'])
self.assertEqual(
self.om.update(42, dummy='dummy overcloud data'),
['fake_overcloud'])
self.om._update.assert_called_with(
'/v1/overclouds/42',
{'dummy': 'dummy overcloud data'})
def test_delete(self):
"""Test deleting/removing an overcloud via DELETE."""
self.om._delete = mock.Mock(return_value=None)
self.assertEqual(self.om.delete(42), None)
self.om._delete.assert_called_with('/v1/overclouds/42')

View File

@ -11,6 +11,7 @@
# under the License. # under the License.
from tuskarclient.common import http from tuskarclient.common import http
from tuskarclient.v1 import overclouds
class Client(object): class Client(object):
@ -23,3 +24,4 @@ class Client(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.http_client = http.HTTPClient(*args, **kwargs) self.http_client = http.HTTPClient(*args, **kwargs)
self.overclouds = overclouds.OvercloudManager(self.http_client)

View File

@ -0,0 +1,95 @@
# 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.
from tuskarclient.common import base
class Overcloud(base.Resource):
"""Represents an instance of a Overcloud in the Tuskar API.
:param manager: Manager object
:param info: dictionary representing resource attributes
:param loaded: prevent lazy-loading if set to True
"""
class OvercloudManager(base.Manager):
"""OvercloudManager interacts with the Tuskar API and provides CRUD
operations for the Overcloud type.
"""
#: The class used to represent an Overcloud instance
resource_class = Overcloud
@staticmethod
def _path(overcloud_id=None):
if overcloud_id:
return '/v1/overclouds/%s' % overcloud_id
return '/v1/overclouds'
def list(self):
"""Get a list of the existing Overclouds
:return: A list of overclounds or an empty list if none are found.
:rtype: [tuskarclient.v1.overclouds.Overcloud] or []
"""
return self._list(self._path())
def get(self, overcloud_id):
"""Get the Overcloud by its ID.
:param overcloud_id: id of the Overcloud.
:type overcloud_id: string
:return: A Overcloud instance or None if its not found.
:rtype: tuskarclient.v1.overclouds.Overcloud or None
"""
return self._get(self._single_path(overcloud_id))
def create(self, **fields):
"""Create a new Overcloud.
:param fields: A set of key/value pairs representing a Overcloud.
:type fields: string
:return: A Overcloud instance or None if its not found.
:rtype: tuskarclient.v1.overclouds.Overcloud
"""
return self._create(self._path(), fields)
def update(self, overcloud_id, **fields):
"""Update an existing Overcloud.
:param overcloud_id: id of the Overcloud.
:type overcloud_id: string
:param fields: A set of key/value pairs representing the Overcloud.
:type fields: string
:return: A Overcloud instance or None if its not found.
:rtype: tuskarclient.v1.overclouds.Overcloud or None
"""
return self._update(self._single_path(overcloud_id), fields)
def delete(self, overcloud_id):
"""Delete an Overcloud.
:param overcloud_id: id of the Overcloud.
:type overcloud_id: string
:return: None
:rtype: None
"""
return self._delete(self._single_path(overcloud_id))