Split cases for nova and neutron networks.
Added simlest network tests. Change-Id: Ifc3f951a29d85fad61869376bcbe602ae209f6c6
This commit is contained in:
parent
3ecaef77b7
commit
93aabba2ff
@ -207,6 +207,14 @@ class API(object):
|
||||
self._delete_db_item(context, item)
|
||||
return only_os_items
|
||||
|
||||
@staticmethod
|
||||
def _from_gce(name):
|
||||
return name.replace("-", ".")
|
||||
|
||||
@staticmethod
|
||||
def _to_gce(name):
|
||||
return name.replace(".", "-")
|
||||
|
||||
|
||||
class _CallbackReasons(object):
|
||||
check_delete = 1
|
||||
|
@ -119,7 +119,7 @@ def keystone(context):
|
||||
# Ver2 doesn't create session and performs
|
||||
# authentication automatically, but Ver3 does create session
|
||||
# if it's not provided and doesn't perform authentication.
|
||||
# TODO(use sessions)
|
||||
# TODO(alexey-mr): use sessions
|
||||
c.authenticate()
|
||||
return c
|
||||
|
||||
|
@ -51,7 +51,7 @@ class Controller(object):
|
||||
# Ver2 doesn't create session and performs
|
||||
# authentication automatically, but Ver3 does create session
|
||||
# if it's not provided and doesn't perform authentication.
|
||||
# TODO(use sessions)
|
||||
# TODO(alexey-mr): use sessions
|
||||
keystone.authenticate()
|
||||
catalog = keystone.service_catalog.get_data()
|
||||
public_url = clients.get_url_from_catalog(catalog, "gceapi")
|
||||
|
@ -60,9 +60,3 @@ class API(base_api.API):
|
||||
def _prepare_item(self, item):
|
||||
item["name"] = self._to_gce(item["name"])
|
||||
return item
|
||||
|
||||
def _from_gce(self, name):
|
||||
return name.replace("-", ".")
|
||||
|
||||
def _to_gce(self, name):
|
||||
return name.replace(".", "-")
|
||||
|
@ -154,7 +154,7 @@ class Controller(object):
|
||||
# Ver2 doesn't create session and performs
|
||||
# authentication automatically, but Ver3 does create session
|
||||
# if it's not provided and doesn't perform authentication.
|
||||
# TODO(use sessions)
|
||||
# TODO(alexy-mr): use sessions
|
||||
keystone.authenticate()
|
||||
client.auth_token = keystone.auth_token
|
||||
s = keystone.auth_ref.issued
|
||||
@ -223,7 +223,7 @@ class AuthProtocol(object):
|
||||
# Ver2 doesn't create session and performs
|
||||
# authentication automatically, but Ver3 does create session
|
||||
# if it's not provided and doesn't perform authentication.
|
||||
# TODO(use sessions)
|
||||
# TODO(alexey-mr): use sessions
|
||||
keystone.authenticate()
|
||||
scoped_token = keystone.auth_token
|
||||
env["HTTP_X_AUTH_TOKEN"] = scoped_token
|
||||
|
@ -20,6 +20,19 @@ from gceapi import exception
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
# OS usual region names are in PascalCase - e.g. RegionOne,
|
||||
# GCE region name should matche the regexp [a-z](?:[-a-z0-9]{0,61}[a-z0-9])?
|
||||
_OS_GCE_MAP = {
|
||||
'RegionOne': 'region-one',
|
||||
'RegionTwo': 'region-two',
|
||||
'RegionThree': 'region-three',
|
||||
'RegionFour': 'region-four',
|
||||
}
|
||||
|
||||
|
||||
def _map_region_name(name):
|
||||
return _OS_GCE_MAP.get(name, name)
|
||||
|
||||
|
||||
class API(base_api.API):
|
||||
"""GCE Regions API
|
||||
@ -33,7 +46,7 @@ class API(base_api.API):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(API, self).__init__(*args, **kwargs)
|
||||
self._REGIONS = [CONF.get("region").strip()]
|
||||
self._REGIONS = [_map_region_name(CONF.get("region").strip())]
|
||||
|
||||
def _get_type(self):
|
||||
return self.KIND
|
||||
|
@ -58,11 +58,13 @@ if [[ ! -f $TEST_CONFIG_DIR/$TEST_CONFIG ]]; then
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to prepare flavor"; exit 1; }
|
||||
fi
|
||||
|
||||
# create network
|
||||
# create default network
|
||||
if [[ -n $(openstack service list | grep neutron) ]]; then
|
||||
net_id=$(neutron net-create --tenant-id $project_id "private" | grep ' id ' | awk '{print $4}')
|
||||
# neutron networking
|
||||
networking="neutron"
|
||||
net_id=$(neutron net-create --tenant-id $project_id "default" | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$net_id" ]] || { echo "net-create failed"; exit 1; }
|
||||
subnet_id=$(neutron subnet-create --tenant-id $project_id --ip_version 4 --gateway 10.0.0.1 --name "private_subnet" $net_id 10.0.0.0/24 | grep ' id ' | awk '{print $4}')
|
||||
subnet_id=$(neutron subnet-create --tenant-id $project_id --ip_version 4 --gateway 10.240.0.1 --name "private_subnet" $net_id 10.240.0.0/24 | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$subnet_id" ]] || { echo "subnet-create failed"; exit 1; }
|
||||
router_id=$(neutron router-create --tenant-id $project_id "private_router" | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$router_id" ]] || { echo "router-create failed"; exit 1; }
|
||||
@ -72,6 +74,10 @@ if [[ ! -f $TEST_CONFIG_DIR/$TEST_CONFIG ]]; then
|
||||
[[ -n "$public_net_id" ]] || { echo "can't find public network"; exit 1; }
|
||||
neutron router-gateway-set $router_id $public_net_id
|
||||
[[ "$?" -eq 0 ]] || { echo "router-gateway-set failed"; exit 1; }
|
||||
else
|
||||
# nova networking
|
||||
networking="nova-network"
|
||||
nova network-create "default" --fixed-range-v4 10.240.0.0/24 --gateway 10.240.0.1
|
||||
fi
|
||||
|
||||
#create image in raw format
|
||||
@ -117,7 +123,8 @@ discovery_url=${GCE_DISCOVERY_URL:-'/discovery/v1/apis/{api}/{apiVersion}/rest'}
|
||||
# GCE resource IDs for testing
|
||||
project_id=${OS_PROJECT_NAME}
|
||||
zone=${ZONE:-'nova'}
|
||||
region=${REGION:-'RegionOne'}
|
||||
networking=${networking}
|
||||
region=${REGION:-'region-one'}
|
||||
# convert flavor name: becase GCE dowsn't allows '.' and converts '-' into '.'
|
||||
machine_type=${flavor_name//\./-}
|
||||
image=${os_image_name}
|
||||
|
129
gceapi/tests/functional/api/test_addresses.py
Normal file
129
gceapi/tests/functional/api/test_addresses.py
Normal file
@ -0,0 +1,129 @@
|
||||
# Copyright 2015 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 gceapi.tests.functional import test_base
|
||||
|
||||
|
||||
CREATE_ADDRESS_TEMPLATE = {
|
||||
"name": "${name}",
|
||||
}
|
||||
|
||||
|
||||
def _prepare_address_create_parameters(**kwargs):
|
||||
return test_base.insert_json_parameters(CREATE_ADDRESS_TEMPLATE, **kwargs)
|
||||
|
||||
|
||||
class TestAddressesBase(test_base.GCETestCase):
|
||||
@property
|
||||
def addresses(self):
|
||||
res = self.api.compute.addresses()
|
||||
self.assertIsNotNone(
|
||||
res,
|
||||
'Null addresses object, api is not built properly')
|
||||
return res
|
||||
|
||||
def _create_address(self, options):
|
||||
self._add_cleanup(self._delete_address, options['name'])
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
region = cfg.region
|
||||
config = _prepare_address_create_parameters(**options)
|
||||
self.trace('Crete address with options {}'.format(config))
|
||||
request = self.addresses.insert(
|
||||
project=project_id,
|
||||
region=region,
|
||||
body=config)
|
||||
self._execute_async_request(request, project_id, region=region)
|
||||
|
||||
def _delete_address(self, name):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
region = cfg.region
|
||||
self.trace('Delete address: project_id={} region={} name={}'.
|
||||
format(project_id, region, name))
|
||||
request = self.addresses.delete(
|
||||
project=project_id,
|
||||
region=region,
|
||||
address=name)
|
||||
self._remove_cleanup(self._delete_address, name)
|
||||
self._execute_async_request(request, project_id, region=region)
|
||||
|
||||
def _list_addresses(self):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
region = cfg.region
|
||||
self.trace('List addresses: project_id={} region={}'.
|
||||
format(project_id, region))
|
||||
request = self.addresses.list(
|
||||
project=project_id,
|
||||
region=region)
|
||||
result = request.execute()
|
||||
self.trace('Addresses: {}'.format(result))
|
||||
self.api.validate_schema(value=result, schema_name='AddressList')
|
||||
return result
|
||||
|
||||
def _get_address(self, name):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
region = cfg.region
|
||||
self.trace('Get address: project_id={} region={} name={}'.
|
||||
format(project_id, region, name))
|
||||
request = self.addresses.get(
|
||||
project=project_id,
|
||||
region=region,
|
||||
address=name)
|
||||
result = request.execute()
|
||||
self.trace('Addresses: {}'.format(result))
|
||||
self.api.validate_schema(value=result, schema_name='Address')
|
||||
return result
|
||||
|
||||
|
||||
class TestAddressesCRUD(TestAddressesBase):
|
||||
@property
|
||||
def addresses(self):
|
||||
res = self.api.compute.addresses()
|
||||
self.assertIsNotNone(
|
||||
res,
|
||||
'Null addresses object, api is not built properly')
|
||||
return res
|
||||
|
||||
def setUp(self):
|
||||
super(TestAddressesCRUD, self).setUp()
|
||||
self._address_name = self._rand_name('testaddr')
|
||||
|
||||
def _create(self):
|
||||
options = {
|
||||
'name': self._address_name
|
||||
}
|
||||
self._create_address(options)
|
||||
|
||||
def _read(self):
|
||||
result = self._get_address(self._address_name)
|
||||
self.assertEqual(self._address_name, result['name'])
|
||||
result = self._list_addresses()
|
||||
self.assertFind(self._address_name, result)
|
||||
|
||||
def _update(self):
|
||||
pass
|
||||
|
||||
def _delete(self):
|
||||
self._delete_address(self._address_name)
|
||||
|
||||
def test_crud(self):
|
||||
self._create()
|
||||
self._read()
|
||||
self._update()
|
||||
self._delete()
|
@ -15,17 +15,11 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
from string import Template
|
||||
|
||||
from json import dumps
|
||||
from json import loads
|
||||
|
||||
from gceapi.tests.functional import test_base
|
||||
|
||||
|
||||
BASE_COMPUTE_URL = '{address}/compute/v1'
|
||||
CREATE_INSTANCE_TEMPLATE = {
|
||||
"name": "${instance}",
|
||||
"name": "${name}",
|
||||
"description": "Testing instance",
|
||||
"machineType": "zones/${zone}/machineTypes/${machine_type}",
|
||||
"disks": [
|
||||
@ -66,30 +60,13 @@ CREATE_INSTANCE_TEMPLATE = {
|
||||
}
|
||||
]
|
||||
}
|
||||
CREATE_NETWORK_TEMPLATE = {
|
||||
"name": "${name}",
|
||||
"IPv4Range": "10.240.0.0/16",
|
||||
"description": "testing network ${name}",
|
||||
"gatewayIPv4": "10.240.0.1"
|
||||
}
|
||||
|
||||
|
||||
def _insert_json_parameters(obj, **kwargs):
|
||||
s = dumps(obj)
|
||||
t = Template(s)
|
||||
s = t.substitute(**kwargs)
|
||||
return loads(s)
|
||||
def _prepare_instance_insert_parameters(**kwargs):
|
||||
return test_base.insert_json_parameters(CREATE_INSTANCE_TEMPLATE, **kwargs)
|
||||
|
||||
|
||||
def _prepare_instace_insert_parameters(**kwargs):
|
||||
return _insert_json_parameters(CREATE_INSTANCE_TEMPLATE, **kwargs)
|
||||
|
||||
|
||||
def _prepare_network_create_parameters(**kwargs):
|
||||
return _insert_json_parameters(CREATE_NETWORK_TEMPLATE, **kwargs)
|
||||
|
||||
|
||||
class TestIntancesBase(test_base.GCETestCase):
|
||||
class TestInstancesBase(test_base.GCETestCase):
|
||||
@property
|
||||
def instances(self):
|
||||
res = self.api.compute.instances()
|
||||
@ -98,132 +75,87 @@ class TestIntancesBase(test_base.GCETestCase):
|
||||
'Null instances object, api is not built properly')
|
||||
return res
|
||||
|
||||
@property
|
||||
def networks(self):
|
||||
res = self.api.compute.networks()
|
||||
self.assertIsNotNone(
|
||||
res,
|
||||
'Null networks object, api is not built properly')
|
||||
return res
|
||||
|
||||
def setUp(self):
|
||||
super(TestIntancesBase, self).setUp()
|
||||
self._instance_name = self.getUniqueString('testinst')
|
||||
self._network_name = self.getUniqueString('testnet')
|
||||
|
||||
def _create_network(self):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
network = self._network_name
|
||||
kw = {
|
||||
'name': network,
|
||||
}
|
||||
config = _prepare_network_create_parameters(**kw)
|
||||
self.trace('Crete network with options {}'.format(config))
|
||||
request = self.networks.insert(
|
||||
project=project_id,
|
||||
body=config)
|
||||
result = self._execute_async_request(request, project_id)
|
||||
self.api.validate_schema(value=result, schema_name='Operation')
|
||||
return result
|
||||
|
||||
def _delete_network(self):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
network = self._network_name
|
||||
self.trace(
|
||||
'Delete network: project_id={} network={}'.
|
||||
format(project_id, network))
|
||||
request = self.networks.delete(
|
||||
project=project_id,
|
||||
network=network)
|
||||
result = self._execute_async_request(request, project_id)
|
||||
self.api.validate_schema(value=result, schema_name='Operation')
|
||||
return result
|
||||
|
||||
def _create_instance(self):
|
||||
def _create_instance(self, options):
|
||||
self._add_cleanup(self._delete_instance, options['name'])
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
zone = cfg.zone
|
||||
kw = {
|
||||
'zone': zone,
|
||||
'instance': self._instance_name,
|
||||
'machine_type': cfg.machine_type,
|
||||
'image': cfg.image,
|
||||
'network': self._network_name,
|
||||
}
|
||||
config = _prepare_instace_insert_parameters(**kw)
|
||||
config = _prepare_instance_insert_parameters(**options)
|
||||
self.trace('Crete instance with options {}'.format(config))
|
||||
request = self.instances.insert(
|
||||
project=project_id,
|
||||
zone=zone,
|
||||
body=config)
|
||||
result = self._execute_async_request(request, project_id, zone=zone)
|
||||
self.api.validate_schema(value=result, schema_name='Operation')
|
||||
return result
|
||||
self._execute_async_request(request, project_id, zone=zone)
|
||||
|
||||
def _delete_instance(self):
|
||||
def _delete_instance(self, name):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
zone = cfg.zone
|
||||
instance = self._instance_name
|
||||
self.trace(
|
||||
'Delete instance: project_id={} zone={} instance {}'.
|
||||
format(project_id, zone, instance))
|
||||
self.trace('Delete instance: project_id={} zone={} instance {}'.
|
||||
format(project_id, zone, name))
|
||||
request = self.instances.delete(
|
||||
project=project_id,
|
||||
zone=zone,
|
||||
instance=instance)
|
||||
result = self._execute_async_request(request, project_id, zone=zone)
|
||||
self.api.validate_schema(value=result, schema_name='Operation')
|
||||
return result
|
||||
instance=name)
|
||||
self._remove_cleanup(self._delete_instance, name)
|
||||
self._execute_async_request(request, project_id, zone=zone)
|
||||
|
||||
def _list(self):
|
||||
def _list_instances(self):
|
||||
project_id = self.cfg.project_id
|
||||
zone = self.cfg.zone
|
||||
self.trace(
|
||||
'List instances: project_id={} zone={}'.format(project_id, zone))
|
||||
self.trace('List instances: project_id={} zone={}'.
|
||||
format(project_id, zone))
|
||||
request = self.instances.list(project=project_id, zone=zone)
|
||||
self._trace_request(request)
|
||||
self.trace_request(request)
|
||||
result = request.execute()
|
||||
self.trace('Instances: {}'.format(result))
|
||||
self.api.validate_schema(value=result, schema_name='InstanceList')
|
||||
self.assertFind(self._instance_name, result)
|
||||
return result
|
||||
|
||||
def _get(self):
|
||||
def _get_instance(self, name):
|
||||
project_id = self.cfg.project_id
|
||||
zone = self.cfg.zone
|
||||
instance = self._instance_name
|
||||
self.trace(
|
||||
'Get instance: project_id={} zone={} instance={}'.
|
||||
format(project_id, zone, instance))
|
||||
self.trace('Get instance: project_id={} zone={} instance={}'.
|
||||
format(project_id, zone, name))
|
||||
request = self.instances.get(
|
||||
project=project_id,
|
||||
zone=zone,
|
||||
instance=instance)
|
||||
instance=name)
|
||||
result = request.execute()
|
||||
self.trace('Instance: {}'.format(result))
|
||||
self.api.validate_schema(value=result, schema_name='Instance')
|
||||
return result
|
||||
|
||||
|
||||
class TestIntancesCRUD(TestIntancesBase):
|
||||
class TestInstancesCRUD(TestInstancesBase):
|
||||
def setUp(self):
|
||||
super(TestInstancesCRUD, self).setUp()
|
||||
self._instance_name = self._rand_name('testinst')
|
||||
|
||||
def _create(self):
|
||||
self._create_network()
|
||||
self._create_instance()
|
||||
cfg = self.cfg
|
||||
options = {
|
||||
'zone': cfg.zone,
|
||||
'name': self._instance_name,
|
||||
'machine_type': cfg.machine_type,
|
||||
'image': cfg.image,
|
||||
'network': 'default',
|
||||
}
|
||||
self._create_instance(options)
|
||||
|
||||
def _read(self):
|
||||
self._get()
|
||||
self._list()
|
||||
result = self._get_instance(self._instance_name)
|
||||
self.assertEqual(self._instance_name, result['name'])
|
||||
result = self._list_instances()
|
||||
self.assertFind(self._instance_name, result)
|
||||
|
||||
def _update(self):
|
||||
#TODO(to impl simple update cases)
|
||||
# TODO(alexey-mr): to impl simple update cases
|
||||
pass
|
||||
|
||||
def _delete(self):
|
||||
self._delete_instance()
|
||||
self._delete_network()
|
||||
self._delete_instance(self._instance_name)
|
||||
|
||||
def test_crud(self):
|
||||
self._create()
|
||||
|
132
gceapi/tests/functional/api/test_networks.py
Normal file
132
gceapi/tests/functional/api/test_networks.py
Normal file
@ -0,0 +1,132 @@
|
||||
# Copyright 2015 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 gceapi.tests.functional import test_base
|
||||
|
||||
|
||||
CREATE_NETWORK_TEMPLATE = {
|
||||
"name": "${name}",
|
||||
"IPv4Range": "${ip_range}",
|
||||
"description": "testing network ${name}",
|
||||
"gatewayIPv4": "${gateway}"
|
||||
}
|
||||
|
||||
|
||||
def _prepare_network_create_parameters(**kwargs):
|
||||
return test_base.insert_json_parameters(CREATE_NETWORK_TEMPLATE, **kwargs)
|
||||
|
||||
|
||||
class TestNetworksBase(test_base.GCETestCase):
|
||||
@property
|
||||
def networks(self):
|
||||
res = self.api.compute.networks()
|
||||
self.assertIsNotNone(
|
||||
res,
|
||||
'Null networks object, api is not built properly')
|
||||
return res
|
||||
|
||||
def _create_network(self, options):
|
||||
self._add_cleanup(self._delete_network, options['name'])
|
||||
project_id = self.cfg.project_id
|
||||
config = _prepare_network_create_parameters(**options)
|
||||
self.trace('Crete network with options {}'.format(config))
|
||||
request = self.networks.insert(
|
||||
project=project_id,
|
||||
body=config)
|
||||
self._execute_async_request(request, project_id)
|
||||
|
||||
def _delete_network(self, name):
|
||||
cfg = self.cfg
|
||||
project_id = cfg.project_id
|
||||
self.trace('Delete network: project_id={} network={}'.
|
||||
format(project_id, name))
|
||||
request = self.networks.delete(
|
||||
project=project_id,
|
||||
network=name)
|
||||
self._remove_cleanup(self._delete_network, name)
|
||||
self._execute_async_request(request, project_id)
|
||||
|
||||
def _list_networks(self):
|
||||
project_id = self.cfg.project_id
|
||||
self.trace('List networks: project_id={}'.format(project_id))
|
||||
request = self.networks.list(project=project_id)
|
||||
self.trace_request(request)
|
||||
result = request.execute()
|
||||
self.trace('Networks: {}'.format(result))
|
||||
self.api.validate_schema(value=result, schema_name='NetworkList')
|
||||
return result
|
||||
|
||||
def _get_network(self, name):
|
||||
project_id = self.cfg.project_id
|
||||
self.trace('Get network: project_id={} network={}'.
|
||||
format(project_id, name))
|
||||
request = self.networks.get(
|
||||
project=project_id,
|
||||
network=name)
|
||||
result = request.execute()
|
||||
self.trace('Network: {}'.format(result))
|
||||
self.api.validate_schema(value=result, schema_name='Network')
|
||||
return result
|
||||
|
||||
|
||||
class TestReadDefaultNetwork(TestNetworksBase):
|
||||
def setUp(self):
|
||||
super(TestReadDefaultNetwork, self).setUp()
|
||||
self._network_name = 'default'
|
||||
|
||||
def test_get(self):
|
||||
self._get_network(self._network_name)
|
||||
|
||||
def test_list(self):
|
||||
result = self._list_networks()
|
||||
self.assertFind(self._network_name, result)
|
||||
|
||||
|
||||
class TestNetworksCRUD(TestNetworksBase):
|
||||
def setUp(self):
|
||||
if self.cfg.networking == 'nova-network':
|
||||
self.skipTest('Skip network because of nova-network')
|
||||
return
|
||||
super(TestNetworksCRUD, self).setUp()
|
||||
self._network_name = self._rand_name('network')
|
||||
|
||||
def _create(self):
|
||||
options = {
|
||||
'name': self._network_name,
|
||||
'ip_range': '10.240.0.0/16',
|
||||
'gateway': '10.240.0.1'
|
||||
}
|
||||
# TODO(alexey-mr): gateway is optional, so add case with absent one
|
||||
self._create_network(options)
|
||||
|
||||
def _read(self):
|
||||
result = self._get_network(self._network_name)
|
||||
self.assertEqual(self._network_name, result['name'])
|
||||
result = self._list_networks()
|
||||
self.assertFind(self._network_name, result)
|
||||
|
||||
def _update(self):
|
||||
# TODO(alexey-mr): to be implemented
|
||||
pass
|
||||
|
||||
def _delete(self):
|
||||
self._delete_network(self._network_name)
|
||||
|
||||
def test_crud(self):
|
||||
self._create()
|
||||
self._read()
|
||||
self._update()
|
||||
self._delete()
|
@ -14,8 +14,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import unittest
|
||||
|
||||
from gceapi.tests.functional import test_base
|
||||
|
||||
|
||||
@ -34,8 +32,6 @@ class TestRegions(test_base.GCETestCase):
|
||||
'Null regions object, api is not built properly')
|
||||
return res
|
||||
|
||||
# TODO(alexey-mr): Google allows [a-z](?:[-a-z0-9]{0,61}[a-z0-9])?
|
||||
@unittest.skip("Skip test for now: google dosnt't allow name RegionOne")
|
||||
def test_describe(self):
|
||||
project_id = self.cfg.project_id
|
||||
region = self.cfg.region
|
||||
|
@ -31,13 +31,14 @@ import tempest.test
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = logging.getLogger("tempest.thirdparty.gce")
|
||||
REGION_NAME = 'region-one'
|
||||
|
||||
|
||||
class GCEConnection(rest_client.RestClient):
|
||||
|
||||
def __init__(self, auth_provider):
|
||||
super(GCEConnection, self).__init__(auth_provider,
|
||||
"gceapi", "RegionOne")
|
||||
"gceapi", REGION_NAME)
|
||||
self.service = CONF.gceapi.catalog_type
|
||||
|
||||
def set_zone(self, zone):
|
||||
|
@ -79,8 +79,11 @@ OPTIONS = [
|
||||
default='nova',
|
||||
help='GCE Zone for testing'),
|
||||
cfg.StrOpt('region',
|
||||
default='RegionOne',
|
||||
default='us-central1',
|
||||
help='GCE Region for testing'),
|
||||
cfg.StrOpt('networking',
|
||||
default='neutron',
|
||||
help='Types of OS networking: neutron or nova-network'),
|
||||
|
||||
cfg.StrOpt('machine_type',
|
||||
default='n1-standard-1',
|
||||
|
@ -15,39 +15,34 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
from keystoneclient.client import Client as KeystoneClient
|
||||
from oauth2client.client import AccessTokenCredentials
|
||||
from oauth2client.client import GoogleCredentials
|
||||
from keystoneclient import client as keystone_client
|
||||
from oauth2client import client as oauth_client
|
||||
|
||||
|
||||
class CredentialsProvider(object):
|
||||
def __init__(self, supp):
|
||||
self._supp = supp
|
||||
def __init__(self, cfg):
|
||||
self.cfg = cfg
|
||||
|
||||
def _trace(self, msg):
|
||||
self._supp.trace(msg)
|
||||
@staticmethod
|
||||
def _get_app_credentials():
|
||||
return oauth_client.GoogleCredentials.get_application_default()
|
||||
|
||||
def _get_app_credentials(self):
|
||||
self._trace('Create GoogleCredentials from default app file')
|
||||
return GoogleCredentials.get_application_default()
|
||||
|
||||
def _get_token_crenetials(self):
|
||||
def _get_token_credentials(self):
|
||||
client = self._create_keystone_client()
|
||||
token = client.auth_token
|
||||
self._trace('Created token {}'.format(token))
|
||||
return AccessTokenCredentials(access_token=token,
|
||||
return oauth_client.AccessTokenCredentials(
|
||||
access_token=token,
|
||||
user_agent='GCE test')
|
||||
|
||||
def _create_keystone_client(self):
|
||||
cfg = self._supp.cfg
|
||||
cfg = self.cfg
|
||||
auth_data = {
|
||||
'username': cfg.username,
|
||||
'password': cfg.password,
|
||||
'tenant_name': cfg.project_id,
|
||||
'auth_url': cfg.auth_url
|
||||
}
|
||||
self._trace('Create keystone client, auth_data={}'.format(auth_data))
|
||||
client = KeystoneClient(**auth_data)
|
||||
client = keystone_client.Client(**auth_data)
|
||||
if not client.authenticate():
|
||||
raise Exception('Failed to authenticate user')
|
||||
return client
|
||||
@ -58,9 +53,9 @@ class CredentialsProvider(object):
|
||||
|
||||
@property
|
||||
def credentials(self):
|
||||
cred_type = self._supp.cfg.cred_type
|
||||
cred_type = self.cfg.cred_type
|
||||
if cred_type == 'os_token':
|
||||
return self._get_token_crenetials()
|
||||
return self._get_token_credentials()
|
||||
elif cred_type == 'gcloud_auth':
|
||||
return self._get_app_credentials()
|
||||
else:
|
||||
|
@ -14,33 +14,43 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import string
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from googleapiclient.discovery import build
|
||||
from googleapiclient.schema import Schemas
|
||||
from jsonschema import RefResolver
|
||||
from jsonschema import validate
|
||||
from googleapiclient import discovery
|
||||
from googleapiclient import schema
|
||||
import jsonschema
|
||||
from oslo_log import log as logging
|
||||
from tempest_lib import base
|
||||
from tempest_lib.common.utils import data_utils
|
||||
|
||||
from gceapi.tests.functional import config
|
||||
from gceapi.tests.functional.credentials import CredentialsProvider
|
||||
from gceapi.tests.functional import credentials
|
||||
|
||||
|
||||
class TestSupp(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._cfg = config.CONF.gce
|
||||
from oslo_log import log as logging
|
||||
self._log = logging.getLogger("gceapi")
|
||||
|
||||
@property
|
||||
def cfg(self):
|
||||
return self._cfg
|
||||
|
||||
def trace(self, *args, **kwargs):
|
||||
self._log.debug(*args, **kwargs)
|
||||
CONF = config.CONF.gce
|
||||
LOG = logging.getLogger("gceapi")
|
||||
|
||||
|
||||
class LocalRefResolver(RefResolver):
|
||||
def trace(msg):
|
||||
LOG.debug(msg)
|
||||
|
||||
|
||||
def safe_call(method):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return method(self, *args, **kwargs)
|
||||
except Exception as err:
|
||||
trace('Exception {}'.format(err))
|
||||
bt = traceback.format_exc()
|
||||
trace('Exception back trace {}'.format(bt))
|
||||
return None
|
||||
return wrapper
|
||||
|
||||
|
||||
class LocalRefResolver(jsonschema.RefResolver):
|
||||
def __init__(
|
||||
self,
|
||||
base_uri,
|
||||
@ -66,15 +76,14 @@ class LocalRefResolver(RefResolver):
|
||||
|
||||
|
||||
class GCEApi(object):
|
||||
def __init__(self, supp, cred_provider):
|
||||
def __init__(self, cred_provider):
|
||||
self._compute = None
|
||||
self._cred_provider = cred_provider
|
||||
self._schema = None
|
||||
self._scheme_ref_resolver = 0
|
||||
self._supp = supp
|
||||
|
||||
def init(self):
|
||||
self._schema = Schemas(self._supp.cfg.schema)
|
||||
self._schema = schema.Schemas(CONF.schema)
|
||||
self._scheme_ref_resolver = LocalRefResolver.from_schema(
|
||||
self._schema.schemas)
|
||||
self._build_api()
|
||||
@ -82,9 +91,8 @@ class GCEApi(object):
|
||||
def _build_api(self):
|
||||
credentials = self._cred_provider.credentials
|
||||
url = self._discovery_url
|
||||
self._trace(
|
||||
'Build Google compute api with discovery url {}'.format(url))
|
||||
self._compute = build(
|
||||
trace('Build Google compute api with discovery url {}'.format(url))
|
||||
self._compute = discovery.build(
|
||||
'compute', 'v1',
|
||||
credentials=credentials,
|
||||
discoveryServiceUrl=url
|
||||
@ -92,7 +100,7 @@ class GCEApi(object):
|
||||
|
||||
@property
|
||||
def _discovery_url(self):
|
||||
cfg = self._supp.cfg
|
||||
cfg = CONF
|
||||
return '{}://{}:{}{}'.format(
|
||||
cfg.protocol,
|
||||
cfg.host,
|
||||
@ -100,9 +108,6 @@ class GCEApi(object):
|
||||
cfg.discovery_url
|
||||
)
|
||||
|
||||
def _trace(self, msg):
|
||||
self._supp.trace(msg)
|
||||
|
||||
@property
|
||||
def compute(self):
|
||||
assert(self._compute is not None)
|
||||
@ -110,7 +115,7 @@ class GCEApi(object):
|
||||
|
||||
@property
|
||||
def base_url(self):
|
||||
cfg = self._supp.cfg
|
||||
cfg = CONF
|
||||
return '{}://{}:{}'.format(
|
||||
cfg.protocol,
|
||||
cfg.host,
|
||||
@ -119,27 +124,31 @@ class GCEApi(object):
|
||||
|
||||
def validate_schema(self, value, schema_name):
|
||||
schema = self._schema.get(schema_name)
|
||||
validate(value, schema, resolver=self._scheme_ref_resolver)
|
||||
jsonschema.validate(value, schema, resolver=self._scheme_ref_resolver)
|
||||
|
||||
|
||||
class GCETestCase(base.BaseTestCase):
|
||||
@property
|
||||
def cfg(self):
|
||||
assert(self._supp.cfg is not None)
|
||||
return self._supp.cfg
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
assert(self._api is not None)
|
||||
return self._api
|
||||
|
||||
def trace(self, *args, **kwargs):
|
||||
self._supp.trace(*args, **kwargs)
|
||||
@property
|
||||
def cfg(self):
|
||||
return CONF
|
||||
|
||||
@staticmethod
|
||||
def trace(msg):
|
||||
trace(msg)
|
||||
|
||||
@staticmethod
|
||||
def trace_request(request):
|
||||
trace('Request: {}'.format(request.to_json()))
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls._supp = TestSupp()
|
||||
cls._api = GCEApi(cls._supp, CredentialsProvider(cls._supp))
|
||||
cp = credentials.CredentialsProvider(CONF)
|
||||
cls._api = GCEApi(cp)
|
||||
cls._api.init()
|
||||
super(GCETestCase, cls).setUpClass()
|
||||
|
||||
@ -154,49 +163,60 @@ class GCETestCase(base.BaseTestCase):
|
||||
self.fail(
|
||||
'There is no required item {} in the list {}'.format(item, items))
|
||||
|
||||
def _trace_request(self, r):
|
||||
self.trace('Request: {}'.format(r.to_json()))
|
||||
|
||||
def _get_operations_request(self, name, project, zone):
|
||||
def _get_operations_request(self, name, project, zone, region):
|
||||
if zone is not None:
|
||||
return self.api.compute.zoneOperations().get(
|
||||
project=project,
|
||||
zone=zone,
|
||||
operation=name)
|
||||
if region is not None:
|
||||
return self.api.compute.regionOperations().get(
|
||||
project=project,
|
||||
region=region,
|
||||
operation=name)
|
||||
return self.api.compute.globalOperations().get(
|
||||
project=project,
|
||||
operation=name)
|
||||
|
||||
def _execute_async_request(self, request, project, zone=None):
|
||||
self._trace_request(request)
|
||||
@staticmethod
|
||||
def _rand_name(prefix='n-'):
|
||||
return data_utils.rand_name(prefix)
|
||||
|
||||
def _add_cleanup(self, method, *args, **kwargs):
|
||||
self.addCleanup(method, *args, **kwargs)
|
||||
|
||||
@safe_call
|
||||
def _remove_cleanup(self, method, *args, **kwargs):
|
||||
v = (method, args, kwargs)
|
||||
self._cleanups.remove(v)
|
||||
|
||||
def _execute_async_request(self, request, project, zone=None, region=None):
|
||||
self.trace_request(request)
|
||||
operation = request.execute()
|
||||
name = operation['name']
|
||||
self.trace('Waiting for operation {} to finish...'.format(name))
|
||||
begin = time.time()
|
||||
timeout = self._supp.cfg.build_timeout
|
||||
timeout = self.cfg.build_timeout
|
||||
result = None
|
||||
while time.time() - begin < timeout:
|
||||
result = self._get_operations_request(
|
||||
name, project, zone).execute()
|
||||
name, project, zone, region).execute()
|
||||
self.api.validate_schema(value=result, schema_name='Operation')
|
||||
if result['status'] == 'DONE':
|
||||
if 'error' in result:
|
||||
self.fail('Request {} failed with error {}'. format(
|
||||
name, result['error']))
|
||||
else:
|
||||
self.trace("Request {} done successfully".format(name))
|
||||
return result
|
||||
return
|
||||
time.sleep(1)
|
||||
|
||||
self.fail('Request {} failed with timeout {}'.format(name, timeout))
|
||||
self.fail('Request {} failed with timeout {},'
|
||||
' latest operation status {}'.format(name, timeout, result))
|
||||
|
||||
|
||||
def safe_call(method):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return method(self, *args, **kwargs)
|
||||
except Exception as err:
|
||||
self.trace('Exception {}'.format(err))
|
||||
import traceback
|
||||
bt = traceback.format_exc()
|
||||
self.trace('Exception back trace {}'.format(bt))
|
||||
return None
|
||||
return wrapper
|
||||
def insert_json_parameters(obj, **kwargs):
|
||||
s = json.dumps(obj)
|
||||
t = string.Template(s)
|
||||
s = t.substitute(**kwargs)
|
||||
return json.loads(s)
|
||||
|
@ -58,13 +58,14 @@ COMMON_PENDING_OPERATION = {
|
||||
}
|
||||
COMMON_PENDING_OPERATION.update(COMMON_OPERATION)
|
||||
|
||||
REGION = fake_request.REGION
|
||||
REGION_OPERATION_SPECIFIC = {
|
||||
u'id': u'6294142421306477203',
|
||||
u'id': u'5036531165588500177',
|
||||
u'selfLink': u'http://localhost/compute/v1beta15/projects/'
|
||||
'fake_project/regions/RegionOne/operations/'
|
||||
'operation-735d48a5-284e-4fb4-a10c-a465ac0b8888',
|
||||
'fake_project/regions/%s/operations/'
|
||||
'operation-735d48a5-284e-4fb4-a10c-a465ac0b8888' % REGION,
|
||||
u'region': u'http://localhost/compute/v1beta15/projects/'
|
||||
'fake_project/regions/RegionOne',
|
||||
'fake_project/regions/%s' % REGION,
|
||||
}
|
||||
|
||||
COMMON_REGION_FINISHED_OPERATION = copy.copy(COMMON_FINISHED_OPERATION)
|
||||
|
@ -17,12 +17,12 @@ from gceapi import wsgi_ext as os_wsgi
|
||||
|
||||
|
||||
PROJECT_ID = "4a5cc7d8893544a9babb3b890227d75e"
|
||||
|
||||
REGION = u'region-one'
|
||||
|
||||
FAKE_SERVICE_CATALOG = [{
|
||||
u'endpoints': [{
|
||||
u'adminURL': u'http://192.168.137.21:8774/v2/' + PROJECT_ID,
|
||||
u'region': u'RegionOne',
|
||||
u'region': REGION,
|
||||
u'id': u'81a8b36abc5f4945bbd1269be0423012',
|
||||
u'internalURL': u'http://192.168.137.21:8774/v2/' + PROJECT_ID,
|
||||
u'publicURL': u'http://192.168.137.21:8774/v2/' + PROJECT_ID}],
|
||||
@ -32,7 +32,7 @@ FAKE_SERVICE_CATALOG = [{
|
||||
}, {
|
||||
u'endpoints': [{
|
||||
u'adminURL': u'http://192.168.137.21:9696/',
|
||||
u'region': u'RegionOne',
|
||||
u'region': REGION,
|
||||
u'id': u'10a0fc598a5741c390f0d6560a89fced',
|
||||
u'internalURL': u'http://192.168.137.21:9696/',
|
||||
u'publicURL': u'http://192.168.137.21:9696/'}],
|
||||
@ -42,7 +42,7 @@ FAKE_SERVICE_CATALOG = [{
|
||||
}, {
|
||||
u'endpoints': [{
|
||||
u'adminURL': u'http://192.168.137.21:9292',
|
||||
u'region': u'RegionOne',
|
||||
u'region': REGION,
|
||||
u'id': u'39643060448c4c089535fce07f2d2aa4',
|
||||
u'internalURL': u'http://192.168.137.21:9292',
|
||||
u'publicURL': u'http://192.168.137.21:9292'}],
|
||||
@ -52,7 +52,7 @@ FAKE_SERVICE_CATALOG = [{
|
||||
}, {
|
||||
u'endpoints': [{
|
||||
u'adminURL': u'http://192.168.137.21:8776/v1/' + PROJECT_ID,
|
||||
u'region': u'RegionOne',
|
||||
u'region': REGION,
|
||||
u'id': u'494bd5333aed467092316e03b1163139',
|
||||
u'internalURL': u'http://192.168.137.21:8776/v1/' + PROJECT_ID,
|
||||
u'publicURL': u'http://192.168.137.21:8776/v1/' + PROJECT_ID}],
|
||||
|
@ -13,20 +13,25 @@
|
||||
# limitations under the License.
|
||||
|
||||
from gceapi.api import addresses
|
||||
from gceapi.tests.unit.api import common
|
||||
|
||||
from gceapi.tests.unit.api import common
|
||||
from gceapi.tests.unit.api import fake_request
|
||||
|
||||
|
||||
REGION = fake_request.REGION
|
||||
EXPECTED_ADDRESSES = [{
|
||||
"kind": "compute#address",
|
||||
"id": "4065623605586261056",
|
||||
"id": "1870839154859306350",
|
||||
"creationTimestamp": "",
|
||||
"status": "IN USE",
|
||||
"region": "http://localhost/compute/v1beta15/projects/"
|
||||
"fake_project/regions/RegionOne",
|
||||
"fake_project/regions/%s" % REGION,
|
||||
"name": "address-172-24-4-227",
|
||||
"description": "",
|
||||
"address": "172.24.4.227",
|
||||
"selfLink": "http://localhost/compute/v1beta15/projects/"
|
||||
"fake_project/regions/RegionOne/addresses/address-172-24-4-227",
|
||||
"fake_project/regions/%s/"
|
||||
"addresses/address-172-24-4-227" % REGION,
|
||||
"users": ["http://localhost/compute/v1beta15/projects/"
|
||||
"fake_project/zones/nova/instances/i1"]
|
||||
}]
|
||||
@ -40,37 +45,38 @@ class AddressesTest(common.GCEControllerTest):
|
||||
|
||||
def test_get_address_by_invalid_name(self):
|
||||
response = self.request_gce("/fake_project/regions/"
|
||||
"RegionOne/addresses/fake")
|
||||
"%s/addresses/fake" % REGION)
|
||||
self.assertEqual(404, response.status_int)
|
||||
|
||||
def test_get_address_by_name(self):
|
||||
response = self.request_gce("/fake_project/regions/"
|
||||
"RegionOne/addresses/address-172-24-4-227")
|
||||
response = self.request_gce(
|
||||
"/fake_project/regions/%s/addresses/address-172-24-4-227" % REGION)
|
||||
|
||||
self.assertEqual(200, response.status_int)
|
||||
self.assertEqual(response.json_body, EXPECTED_ADDRESSES[0])
|
||||
|
||||
def test_get_address_list_filtered(self):
|
||||
response = self.request_gce("/fake_project/regions/RegionOne/addresses"
|
||||
"?filter=name+eq+address-172-24-4-227")
|
||||
response = self.request_gce("/fake_project/regions/%s/addresses"
|
||||
"?filter=name+eq+address-172-24-4-227" %
|
||||
REGION)
|
||||
expected = {
|
||||
"kind": "compute#addressList",
|
||||
"id": "projects/fake_project/regions/RegionOne/addresses",
|
||||
"id": "projects/fake_project/regions/%s/addresses" % REGION,
|
||||
"selfLink": "http://localhost/compute/v1beta15/projects"
|
||||
"/fake_project/regions/RegionOne/addresses",
|
||||
"/fake_project/regions/%s/addresses" % REGION,
|
||||
"items": [EXPECTED_ADDRESSES[0]]
|
||||
}
|
||||
|
||||
self.assertEqual(response.json_body, expected)
|
||||
|
||||
def test_get_address_list(self):
|
||||
response = self.request_gce("/fake_project/regions/RegionOne"
|
||||
"/addresses")
|
||||
response = self.request_gce("/fake_project/regions/%s"
|
||||
"/addresses" % REGION)
|
||||
expected = {
|
||||
"kind": "compute#addressList",
|
||||
"id": "projects/fake_project/regions/RegionOne/addresses",
|
||||
"id": "projects/fake_project/regions/%s/addresses" % REGION,
|
||||
"selfLink": "http://localhost/compute/v1beta15/projects"
|
||||
"/fake_project/regions/RegionOne/addresses",
|
||||
"/fake_project/regions/%s/addresses" % REGION,
|
||||
"items": EXPECTED_ADDRESSES
|
||||
}
|
||||
|
||||
@ -86,7 +92,7 @@ class AddressesTest(common.GCEControllerTest):
|
||||
"selfLink": "http://localhost/compute/v1beta15/projects"
|
||||
"/fake_project/aggregated/addresses",
|
||||
"items": {
|
||||
"regions/RegionOne": {
|
||||
"regions/%s" % REGION: {
|
||||
"addresses": [EXPECTED_ADDRESSES[0]]
|
||||
},
|
||||
}
|
||||
@ -103,7 +109,7 @@ class AddressesTest(common.GCEControllerTest):
|
||||
"selfLink": "http://localhost/compute/v1beta15/projects"
|
||||
"/fake_project/aggregated/addresses",
|
||||
"items": {
|
||||
"regions/RegionOne": {
|
||||
"regions/%s" % REGION: {
|
||||
"addresses": EXPECTED_ADDRESSES
|
||||
},
|
||||
}
|
||||
@ -112,21 +118,21 @@ class AddressesTest(common.GCEControllerTest):
|
||||
self.assertEqual(response.json_body, expected)
|
||||
|
||||
def test_delete_address_with_invalid_name(self):
|
||||
response = self.request_gce("/fake_project/regions/RegionOne"
|
||||
"/addresses/fake-address", method="DELETE")
|
||||
response = self.request_gce(
|
||||
"/fake_project/regions/%s/addresses/fake-address" % REGION,
|
||||
method="DELETE")
|
||||
self.assertEqual(404, response.status_int)
|
||||
|
||||
def test_delete_address(self):
|
||||
response = self.request_gce(
|
||||
"/fake_project/regions/RegionOne/"
|
||||
"addresses/address-172-24-4-227",
|
||||
"/fake_project/regions/%s/addresses/address-172-24-4-227" % REGION,
|
||||
method="DELETE")
|
||||
expected = {
|
||||
"operationType": "delete",
|
||||
"targetId": "4065623605586261056",
|
||||
"targetId": "1870839154859306350",
|
||||
"targetLink": "http://localhost/compute/v1beta15/projects/"
|
||||
"fake_project/regions/RegionOne/"
|
||||
"addresses/address-172-24-4-227",
|
||||
"fake_project/regions/%s/"
|
||||
"addresses/address-172-24-4-227" % REGION,
|
||||
}
|
||||
expected.update(common.COMMON_REGION_FINISHED_OPERATION)
|
||||
self.assertEqual(200, response.status_int)
|
||||
@ -136,16 +142,17 @@ class AddressesTest(common.GCEControllerTest):
|
||||
request_body = {
|
||||
"name": "fake-address",
|
||||
}
|
||||
response = self.request_gce("/fake_project/regions/RegionOne/"
|
||||
"addresses",
|
||||
response = self.request_gce("/fake_project/regions/%s/"
|
||||
"addresses" % REGION,
|
||||
method="POST",
|
||||
body=request_body)
|
||||
self.assertEqual(200, response.status_int)
|
||||
expected = {
|
||||
"operationType": "insert",
|
||||
"targetId": "4570437344333712421",
|
||||
"targetId": "8754519975833457287",
|
||||
"targetLink": "http://localhost/compute/v1beta15/projects/"
|
||||
"fake_project/regions/RegionOne/addresses/fake-address",
|
||||
"fake_project/regions/%s/addresses/fake-address" %
|
||||
REGION,
|
||||
}
|
||||
expected.update(common.COMMON_REGION_FINISHED_OPERATION)
|
||||
self.assertDictEqual(expected, response.json_body)
|
||||
|
@ -14,19 +14,22 @@
|
||||
|
||||
from gceapi.api import regions
|
||||
from gceapi.tests.unit.api import common
|
||||
from gceapi.tests.unit.api import fake_request
|
||||
|
||||
|
||||
REGION = fake_request.REGION
|
||||
EXPECTED_REGIONS = [
|
||||
{
|
||||
"id": "1905250285734383880",
|
||||
"id": "8220497844553564918",
|
||||
"kind": "compute#region",
|
||||
"selfLink": "http://localhost/compute/v1beta15/projects/fake_project"
|
||||
"/regions/RegionOne",
|
||||
"name": "RegionOne",
|
||||
"/regions/%s" % REGION,
|
||||
"name": REGION,
|
||||
"status": "UP",
|
||||
"zones": [
|
||||
"http://localhost/compute/v1beta15/projects/fake_project"
|
||||
"/zones/nova"]
|
||||
"/zones/nova"
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
@ -46,14 +49,14 @@ class RegionsTest(common.GCEControllerTest):
|
||||
self.assertEqual(404, response.status_int)
|
||||
|
||||
def test_get_region(self):
|
||||
response = self.request_gce('/fake_project/regions/RegionOne')
|
||||
response = self.request_gce('/fake_project/regions/%s' % REGION)
|
||||
expected = EXPECTED_REGIONS[0]
|
||||
|
||||
self.assertEqual(response.json_body, expected)
|
||||
|
||||
def test_get_region_list_filtered(self):
|
||||
response = self.request_gce("/fake_project/regions"
|
||||
"?filter=name+eq+RegionOne")
|
||||
"?filter=name+eq+%s" % REGION)
|
||||
expected = {
|
||||
"kind": "compute#regionList",
|
||||
"id": "projects/fake_project/regions",
|
||||
|
@ -14,8 +14,10 @@
|
||||
|
||||
from gceapi.api import zones
|
||||
from gceapi.tests.unit.api import common
|
||||
from gceapi.tests.unit.api import fake_request
|
||||
|
||||
|
||||
REGION = fake_request.REGION
|
||||
EXPECTED_ZONES = [{
|
||||
"id": "3924463100986466035",
|
||||
"kind": "compute#zone",
|
||||
@ -23,7 +25,7 @@ EXPECTED_ZONES = [{
|
||||
"/zones/nova",
|
||||
"name": "nova",
|
||||
"status": "UP",
|
||||
"region": "RegionOne",
|
||||
"region": REGION,
|
||||
}]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user