Transition nova flavor tests to requests_mock
We had added a betamax fixture for create_flavor, but the requests_mock approach is actually working out much better. Go ahead and replace it to simplify the test suite a little bit. Remove _by_flavor tests as they tested a behavior that's actually invalid but worked in the test by happenstance. Transition the rest of the file while we're in there. Change-Id: Ic2457d7380a8af41ed7bf6b264cbdc2240780ff3
This commit is contained in:
parent
16a058f16e
commit
32d53d58ce
@ -83,17 +83,6 @@ class BaseTestCase(base.TestCase):
|
|||||||
cloud_config=self.cloud_config,
|
cloud_config=self.cloud_config,
|
||||||
log_inner_exceptions=True)
|
log_inner_exceptions=True)
|
||||||
|
|
||||||
# Any unit tests using betamax directly need a ksa.Session with
|
|
||||||
# an auth dict. The cassette is currently written with v2 as well
|
|
||||||
self.full_cloud_config = self.config.get_one_cloud(
|
|
||||||
cloud='_test_cloud_v2_')
|
|
||||||
self.full_cloud = shade.OpenStackCloud(
|
|
||||||
cloud_config=self.full_cloud_config,
|
|
||||||
log_inner_exceptions=True)
|
|
||||||
self.full_op_cloud = shade.OperatorCloud(
|
|
||||||
cloud_config=self.full_cloud_config,
|
|
||||||
log_inner_exceptions=True)
|
|
||||||
|
|
||||||
|
|
||||||
class TestCase(BaseTestCase):
|
class TestCase(BaseTestCase):
|
||||||
|
|
||||||
@ -157,6 +146,9 @@ class RequestsMockTestCase(BaseTestCase):
|
|||||||
self.cloud = shade.OpenStackCloud(
|
self.cloud = shade.OpenStackCloud(
|
||||||
cloud_config=self.cloud_config,
|
cloud_config=self.cloud_config,
|
||||||
log_inner_exceptions=True)
|
log_inner_exceptions=True)
|
||||||
|
self.op_cloud = shade.OperatorCloud(
|
||||||
|
cloud_config=self.cloud_config,
|
||||||
|
log_inner_exceptions=True)
|
||||||
|
|
||||||
def use_glance(self, image_version_json='image-version.json'):
|
def use_glance(self, image_version_json='image-version.json'):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
@ -187,7 +179,6 @@ class RequestsMockTestCase(BaseTestCase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def assert_calls(self, stop_after=None):
|
def assert_calls(self, stop_after=None):
|
||||||
self.assertEqual(len(self.calls), len(self.adapter.request_history))
|
|
||||||
for (x, (call, history)) in enumerate(
|
for (x, (call, history)) in enumerate(
|
||||||
zip(self.calls, self.adapter.request_history)):
|
zip(self.calls, self.adapter.request_history)):
|
||||||
if stop_after and x > stop_after:
|
if stop_after and x > stop_after:
|
||||||
@ -210,3 +201,4 @@ class RequestsMockTestCase(BaseTestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
value, history.headers[key],
|
value, history.headers[key],
|
||||||
'header mismatch in call {index}'.format(index=x))
|
'header mismatch in call {index}'.format(index=x))
|
||||||
|
self.assertEqual(len(self.calls), len(self.adapter.request_history))
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,37 +11,115 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
import mock
|
|
||||||
from shade.tests.fakes import FakeFlavor, FakeProject
|
|
||||||
|
|
||||||
import shade
|
import shade
|
||||||
from keystoneauth1.fixture import keystoneauth_betamax
|
|
||||||
from keystoneauth1.fixture import serializer
|
|
||||||
from shade.tests import fakes
|
|
||||||
from shade.tests.unit import base
|
from shade.tests.unit import base
|
||||||
|
|
||||||
|
FLAVOR_ID = '0c1d9008-f546-4608-9e8f-f8bdaec8dddd'
|
||||||
|
ENDPOINT = 'https://compute.example.com/v2.1/1c36b64c840a42cd9e9b931a369337f0'
|
||||||
|
FAKE_FLAVOR = {
|
||||||
|
u'OS-FLV-DISABLED:disabled': False,
|
||||||
|
u'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||||
|
u'disk': 1600,
|
||||||
|
u'id': u'0c1d9008-f546-4608-9e8f-f8bdaec8dddd',
|
||||||
|
u'links': [{
|
||||||
|
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||||
|
endpoint=ENDPOINT, id=FLAVOR_ID),
|
||||||
|
u'rel': u'self'
|
||||||
|
}, {
|
||||||
|
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||||
|
endpoint=ENDPOINT, id=FLAVOR_ID),
|
||||||
|
u'rel': u'bookmark'
|
||||||
|
}],
|
||||||
|
u'name': u'vanilla',
|
||||||
|
u'os-flavor-access:is_public': True,
|
||||||
|
u'ram': 65536,
|
||||||
|
u'rxtx_factor': 1.0,
|
||||||
|
u'swap': u'',
|
||||||
|
u'vcpus': 24
|
||||||
|
}
|
||||||
|
FAKE_FLAVOR_LIST = [FAKE_FLAVOR]
|
||||||
|
|
||||||
class TestFlavorsBetamax(base.BaseTestCase):
|
|
||||||
|
class TestFlavors(base.RequestsMockTestCase):
|
||||||
|
|
||||||
def test_create_flavor(self):
|
def test_create_flavor(self):
|
||||||
self.useFixture(keystoneauth_betamax.BetamaxFixture(
|
|
||||||
cassette_name='test_create_flavor',
|
|
||||||
cassette_library_dir=self.fixtures_directory,
|
|
||||||
record=self.record_fixtures,
|
|
||||||
serializer=serializer.YamlJsonSerializer))
|
|
||||||
|
|
||||||
old_flavors = self.full_op_cloud.list_flavors()
|
self.register_uri(
|
||||||
self.full_op_cloud.create_flavor(
|
'POST', '{endpoint}/flavors'.format(
|
||||||
'vanilla', 12345, 4, 100
|
endpoint=ENDPOINT),
|
||||||
|
json={'flavor': FAKE_FLAVOR},
|
||||||
|
validate=dict(
|
||||||
|
json={'flavor': {
|
||||||
|
"name": "vanilla",
|
||||||
|
"ram": 65536,
|
||||||
|
"vcpus": 24,
|
||||||
|
"swap": 0,
|
||||||
|
"os-flavor-access:is_public": True,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||||
|
"disk": 1600,
|
||||||
|
"id": None
|
||||||
|
}}))
|
||||||
|
|
||||||
|
self.register_uri(
|
||||||
|
'GET', '{endpoint}/flavors/{id}'.format(
|
||||||
|
endpoint=ENDPOINT, id=FLAVOR_ID),
|
||||||
|
json={'flavor': FAKE_FLAVOR})
|
||||||
|
|
||||||
|
self.op_cloud.create_flavor(
|
||||||
|
'vanilla', ram=65536, disk=1600, vcpus=24,
|
||||||
)
|
)
|
||||||
|
self.assert_calls()
|
||||||
|
|
||||||
# test that we have a new flavor added
|
def test_delete_flavor(self):
|
||||||
new_flavors = self.full_op_cloud.list_flavors()
|
self.register_uri(
|
||||||
self.assertEqual(len(new_flavors) - len(old_flavors), 1)
|
'GET', '{endpoint}/flavors/detail?is_public=None'.format(
|
||||||
|
endpoint=ENDPOINT),
|
||||||
|
json={'flavors': FAKE_FLAVOR_LIST})
|
||||||
|
self.register_uri(
|
||||||
|
'DELETE', '{endpoint}/flavors/{id}'.format(
|
||||||
|
endpoint=ENDPOINT, id=FLAVOR_ID))
|
||||||
|
self.assertTrue(self.op_cloud.delete_flavor('vanilla'))
|
||||||
|
|
||||||
|
self.assert_calls()
|
||||||
|
|
||||||
|
def test_delete_flavor_not_found(self):
|
||||||
|
self.register_uri(
|
||||||
|
'GET', '{endpoint}/flavors/detail?is_public=None'.format(
|
||||||
|
endpoint=ENDPOINT),
|
||||||
|
json={'flavors': []})
|
||||||
|
|
||||||
|
self.assertFalse(self.op_cloud.delete_flavor('invalid'))
|
||||||
|
|
||||||
|
self.assert_calls()
|
||||||
|
|
||||||
|
def test_delete_flavor_exception(self):
|
||||||
|
self.register_uri(
|
||||||
|
'GET', '{endpoint}/flavors/detail?is_public=None'.format(
|
||||||
|
endpoint=ENDPOINT),
|
||||||
|
json={'flavors': FAKE_FLAVOR_LIST})
|
||||||
|
self.register_uri(
|
||||||
|
'DELETE', '{endpoint}/flavors/{id}'.format(
|
||||||
|
endpoint=ENDPOINT, id=FLAVOR_ID),
|
||||||
|
status_code=503)
|
||||||
|
self.assertRaises(shade.OpenStackCloudException,
|
||||||
|
self.op_cloud.delete_flavor, 'vanilla')
|
||||||
|
|
||||||
|
def test_list_flavors(self):
|
||||||
|
self.register_uri(
|
||||||
|
'GET', '{endpoint}/flavors/detail?is_public=None'.format(
|
||||||
|
endpoint=ENDPOINT),
|
||||||
|
json={'flavors': FAKE_FLAVOR_LIST})
|
||||||
|
self.register_uri(
|
||||||
|
'GET', '{endpoint}/flavors/{id}/os-extra_specs'.format(
|
||||||
|
endpoint=ENDPOINT, id=FLAVOR_ID),
|
||||||
|
json={'extra_specs': {}})
|
||||||
|
|
||||||
|
flavors = self.cloud.list_flavors()
|
||||||
|
|
||||||
# test that new flavor is created correctly
|
# test that new flavor is created correctly
|
||||||
found = False
|
found = False
|
||||||
for flavor in new_flavors:
|
for flavor in flavors:
|
||||||
if flavor['name'] == 'vanilla':
|
if flavor['name'] == 'vanilla':
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
@ -50,101 +128,69 @@ class TestFlavorsBetamax(base.BaseTestCase):
|
|||||||
if found:
|
if found:
|
||||||
# check flavor content
|
# check flavor content
|
||||||
self.assertTrue(needed_keys.issubset(flavor.keys()))
|
self.assertTrue(needed_keys.issubset(flavor.keys()))
|
||||||
|
self.assert_calls()
|
||||||
|
|
||||||
# delete created flavor
|
def test_set_flavor_specs(self):
|
||||||
self.full_op_cloud.delete_flavor('vanilla')
|
|
||||||
|
|
||||||
|
|
||||||
class TestFlavors(base.TestCase):
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, '_compute_client')
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
|
||||||
def test_delete_flavor(self, mock_nova, mock_compute):
|
|
||||||
mock_response = mock.Mock()
|
|
||||||
mock_response.json.return_value = dict(extra_specs=[])
|
|
||||||
mock_compute.get.return_value = mock_response
|
|
||||||
mock_nova.flavors.list.return_value = [
|
|
||||||
fakes.FakeFlavor('123', 'lemon', 100)
|
|
||||||
]
|
|
||||||
self.assertTrue(self.op_cloud.delete_flavor('lemon'))
|
|
||||||
mock_nova.flavors.delete.assert_called_once_with(flavor='123')
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
|
||||||
def test_delete_flavor_not_found(self, mock_nova):
|
|
||||||
mock_nova.flavors.list.return_value = []
|
|
||||||
self.assertFalse(self.op_cloud.delete_flavor('invalid'))
|
|
||||||
self.assertFalse(mock_nova.flavors.delete.called)
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
|
||||||
def test_delete_flavor_exception(self, mock_nova):
|
|
||||||
mock_nova.flavors.list.return_value = [
|
|
||||||
fakes.FakeFlavor('123', 'lemon', 100)
|
|
||||||
]
|
|
||||||
mock_nova.flavors.delete.side_effect = Exception()
|
|
||||||
self.assertRaises(shade.OpenStackCloudException,
|
|
||||||
self.op_cloud.delete_flavor, '')
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
|
||||||
def test_list_flavors(self, mock_nova):
|
|
||||||
self.op_cloud.list_flavors()
|
|
||||||
mock_nova.flavors.list.assert_called_once_with(is_public=None)
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, '_compute_client')
|
|
||||||
def test_set_flavor_specs(self, mock_compute):
|
|
||||||
extra_specs = dict(key1='value1')
|
extra_specs = dict(key1='value1')
|
||||||
self.op_cloud.set_flavor_specs(1, extra_specs)
|
self.register_uri(
|
||||||
mock_compute.post.assert_called_once_with(
|
'POST', '{endpoint}/flavors/{id}/os-extra_specs'.format(
|
||||||
'/flavors/{id}/os-extra_specs'.format(id=1),
|
endpoint=ENDPOINT, id=1),
|
||||||
json=dict(extra_specs=extra_specs))
|
json=dict(extra_specs=extra_specs))
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, '_compute_client')
|
self.op_cloud.set_flavor_specs(1, extra_specs)
|
||||||
def test_unset_flavor_specs(self, mock_compute):
|
self.assert_calls()
|
||||||
|
|
||||||
|
def test_unset_flavor_specs(self):
|
||||||
keys = ['key1', 'key2']
|
keys = ['key1', 'key2']
|
||||||
|
for key in keys:
|
||||||
|
self.register_uri(
|
||||||
|
'DELETE',
|
||||||
|
'{endpoint}/flavors/{id}/os-extra_specs/{key}'.format(
|
||||||
|
endpoint=ENDPOINT, id=1, key=key))
|
||||||
|
|
||||||
self.op_cloud.unset_flavor_specs(1, keys)
|
self.op_cloud.unset_flavor_specs(1, keys)
|
||||||
api_spec = '/flavors/{id}/os-extra_specs/{key}'
|
self.assert_calls()
|
||||||
self.assertEqual(
|
|
||||||
mock_compute.delete.call_args_list[0],
|
def test_add_flavor_access(self):
|
||||||
mock.call(api_spec.format(id=1, key='key1')))
|
self.register_uri(
|
||||||
self.assertEqual(
|
'POST', '{endpoint}/flavors/{id}/action'.format(
|
||||||
mock_compute.delete.call_args_list[1],
|
endpoint=ENDPOINT, id='flavor_id'),
|
||||||
mock.call(api_spec.format(id=1, key='key2')))
|
json={
|
||||||
|
'flavor_access': [{
|
||||||
|
'flavor_id': 'flavor_id',
|
||||||
|
'tenant_id': 'tenant_id',
|
||||||
|
}]},
|
||||||
|
validate=dict(
|
||||||
|
json={
|
||||||
|
'addTenantAccess': {
|
||||||
|
'tenant': 'tenant_id',
|
||||||
|
}}))
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
|
||||||
def test_add_flavor_access(self, mock_nova):
|
|
||||||
self.op_cloud.add_flavor_access('flavor_id', 'tenant_id')
|
self.op_cloud.add_flavor_access('flavor_id', 'tenant_id')
|
||||||
mock_nova.flavor_access.add_tenant_access.assert_called_once_with(
|
self.assert_calls()
|
||||||
flavor='flavor_id', tenant='tenant_id'
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
def test_remove_flavor_access(self):
|
||||||
def test_add_flavor_access_by_flavor(self, mock_nova):
|
self.register_uri(
|
||||||
flavor = FakeFlavor(id='flavor_id', name='flavor_name', ram=None)
|
'POST', '{endpoint}/flavors/{id}/action'.format(
|
||||||
tenant = FakeProject('tenant_id')
|
endpoint=ENDPOINT, id='flavor_id'),
|
||||||
self.op_cloud.add_flavor_access(flavor, tenant)
|
json={'flavor_access': []},
|
||||||
mock_nova.flavor_access.add_tenant_access.assert_called_once_with(
|
validate=dict(
|
||||||
flavor=flavor, tenant=tenant
|
json={
|
||||||
)
|
'removeTenantAccess': {
|
||||||
|
'tenant': 'tenant_id',
|
||||||
|
}}))
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
|
||||||
def test_remove_flavor_access(self, mock_nova):
|
|
||||||
self.op_cloud.remove_flavor_access('flavor_id', 'tenant_id')
|
self.op_cloud.remove_flavor_access('flavor_id', 'tenant_id')
|
||||||
mock_nova.flavor_access.remove_tenant_access.assert_called_once_with(
|
self.assert_calls()
|
||||||
flavor='flavor_id', tenant='tenant_id'
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
def test_list_flavor_access(self):
|
||||||
def test_list_flavor_access(self, mock_nova):
|
self.register_uri(
|
||||||
mock_nova.flavors.list.return_value = [FakeFlavor(
|
'GET', '{endpoint}/flavors/vanilla/os-flavor-access'.format(
|
||||||
id='flavor_id', name='flavor_name', ram=None)]
|
endpoint=ENDPOINT),
|
||||||
self.op_cloud.list_flavor_access('flavor_id')
|
json={
|
||||||
mock_nova.flavor_access.list.assert_called_once_with(
|
'flavor_access': [{
|
||||||
flavor='flavor_id'
|
'flavor_id': 'vanilla',
|
||||||
)
|
'tenant_id': 'tenant_id',
|
||||||
|
}]})
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
self.op_cloud.list_flavor_access('vanilla')
|
||||||
def test_list_flavor_access_by_flavor(self, mock_nova):
|
self.assert_calls()
|
||||||
flavor = FakeFlavor(id='flavor_id', name='flavor_name', ram=None)
|
|
||||||
self.op_cloud.list_flavor_access(flavor)
|
|
||||||
mock_nova.flavor_access.list.assert_called_once_with(
|
|
||||||
flavor=flavor
|
|
||||||
)
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
hacking>=0.11.0,<0.12 # Apache-2.0
|
hacking>=0.11.0,<0.12 # Apache-2.0
|
||||||
|
|
||||||
betamax-serializers>=0.1.1
|
|
||||||
coverage>=3.6
|
coverage>=3.6
|
||||||
fixtures>=0.3.14
|
fixtures>=0.3.14
|
||||||
mock>=1.0
|
mock>=1.0
|
||||||
python-openstackclient>=2.1.0
|
|
||||||
python-subunit
|
python-subunit
|
||||||
oslosphinx>=2.2.0 # Apache-2.0
|
oslosphinx>=2.2.0 # Apache-2.0
|
||||||
requests-mock
|
requests-mock
|
||||||
|
Loading…
Reference in New Issue
Block a user