Merge "Implement purge list for tempest cleanup"
This commit is contained in:
commit
e838ec9fa8
11
releasenotes/notes/resource-list-cbf9779e8b434654.yaml
Normal file
11
releasenotes/notes/resource-list-cbf9779e8b434654.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
A new interface ``--resource-list`` has been introduced in the
|
||||||
|
``tempest cleanup`` command to remove the resources created by
|
||||||
|
Tempest. A new config option in the default section, ``record_resources``,
|
||||||
|
is added to allow the recording of all resources created by Tempest.
|
||||||
|
A list of these resources will be saved in ``resource_list.json`` file,
|
||||||
|
which will be appended in case of multiple Tempest runs. This file
|
||||||
|
is intended to be used with the ``tempest cleanup`` command if it is
|
||||||
|
used with the newly added option ``--resource-list``.
|
@ -13,8 +13,13 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from oslo_concurrency import lockutils
|
||||||
|
|
||||||
from tempest import config
|
from tempest import config
|
||||||
from tempest.lib import auth
|
from tempest.lib import auth
|
||||||
|
from tempest.lib.common.rest_client import RestClient
|
||||||
from tempest.lib import exceptions as lib_exc
|
from tempest.lib import exceptions as lib_exc
|
||||||
from tempest.lib.services import clients
|
from tempest.lib.services import clients
|
||||||
|
|
||||||
@ -35,6 +40,11 @@ class Manager(clients.ServiceClients):
|
|||||||
super(Manager, self).__init__(
|
super(Manager, self).__init__(
|
||||||
credentials=credentials, identity_uri=identity_uri, scope=scope,
|
credentials=credentials, identity_uri=identity_uri, scope=scope,
|
||||||
region=CONF.identity.region)
|
region=CONF.identity.region)
|
||||||
|
if CONF.record_resources:
|
||||||
|
RestClient.lock_dir = os.path.join(
|
||||||
|
lockutils.get_lock_path(CONF),
|
||||||
|
'tempest-rec-rw-lock')
|
||||||
|
RestClient.record_resources = True
|
||||||
# TODO(andreaf) When clients are initialised without the right
|
# TODO(andreaf) When clients are initialised without the right
|
||||||
# parameters available, the calls below will trigger a KeyError.
|
# parameters available, the calls below will trigger a KeyError.
|
||||||
# We should catch that and raise a better error.
|
# We should catch that and raise a better error.
|
||||||
|
@ -87,6 +87,23 @@ Runtime Arguments
|
|||||||
``saved_state.json`` file will be ignored and cleanup will be done based on
|
``saved_state.json`` file will be ignored and cleanup will be done based on
|
||||||
the passed prefix only.
|
the passed prefix only.
|
||||||
|
|
||||||
|
* ``--resource-list``: Allows the use of file ``./resource_list.json``, which
|
||||||
|
contains all resources created by Tempest during all Tempest runs, to
|
||||||
|
create another method for removing only resources created by Tempest.
|
||||||
|
List of these resources is created when config option ``record_resources``
|
||||||
|
in default section is set to true. After using this option for cleanup,
|
||||||
|
the existing ``./resource_list.json`` is cleared from deleted resources.
|
||||||
|
|
||||||
|
When this option is used, ``saved_state.json`` file is not needed (no
|
||||||
|
need to run with ``--init-saved-state`` first). If there is any
|
||||||
|
``saved_state.json`` file present and you run the tempest cleanup with
|
||||||
|
``--resource-list``, the ``saved_state.json`` file will be ignored and
|
||||||
|
cleanup will be done based on the ``resource_list.json`` only.
|
||||||
|
|
||||||
|
If you run tempest cleanup with both ``--prefix`` and ``--resource-list``,
|
||||||
|
the ``--resource-list`` option will be ignored and cleanup will be done
|
||||||
|
based on the ``--prefix`` option only.
|
||||||
|
|
||||||
* ``--help``: Print the help text for the command and parameters.
|
* ``--help``: Print the help text for the command and parameters.
|
||||||
|
|
||||||
.. [1] The ``_projects_to_clean`` dictionary in ``dry_run.json`` lists the
|
.. [1] The ``_projects_to_clean`` dictionary in ``dry_run.json`` lists the
|
||||||
@ -122,6 +139,7 @@ from tempest.lib import exceptions
|
|||||||
|
|
||||||
SAVED_STATE_JSON = "saved_state.json"
|
SAVED_STATE_JSON = "saved_state.json"
|
||||||
DRY_RUN_JSON = "dry_run.json"
|
DRY_RUN_JSON = "dry_run.json"
|
||||||
|
RESOURCE_LIST_JSON = "resource_list.json"
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
|
|
||||||
@ -164,6 +182,7 @@ class TempestCleanup(command.Command):
|
|||||||
self.admin_mgr = clients.Manager(
|
self.admin_mgr = clients.Manager(
|
||||||
credentials.get_configured_admin_credentials())
|
credentials.get_configured_admin_credentials())
|
||||||
self.dry_run_data = {}
|
self.dry_run_data = {}
|
||||||
|
self.resource_data = {}
|
||||||
self.json_data = {}
|
self.json_data = {}
|
||||||
|
|
||||||
# available services
|
# available services
|
||||||
@ -177,12 +196,20 @@ class TempestCleanup(command.Command):
|
|||||||
self._init_state()
|
self._init_state()
|
||||||
return
|
return
|
||||||
|
|
||||||
self._load_json()
|
if parsed_args.prefix:
|
||||||
|
return
|
||||||
|
|
||||||
|
if parsed_args.resource_list:
|
||||||
|
self._load_resource_list()
|
||||||
|
return
|
||||||
|
|
||||||
|
self._load_saved_state()
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
LOG.info("Begin cleanup")
|
LOG.info("Begin cleanup")
|
||||||
is_dry_run = self.options.dry_run
|
is_dry_run = self.options.dry_run
|
||||||
is_preserve = not self.options.delete_tempest_conf_objects
|
is_preserve = not self.options.delete_tempest_conf_objects
|
||||||
|
is_resource_list = self.options.resource_list
|
||||||
is_save_state = False
|
is_save_state = False
|
||||||
cleanup_prefix = self.options.prefix
|
cleanup_prefix = self.options.prefix
|
||||||
|
|
||||||
@ -194,8 +221,10 @@ class TempestCleanup(command.Command):
|
|||||||
# they are in saved state json. Therefore is_preserve is False
|
# they are in saved state json. Therefore is_preserve is False
|
||||||
kwargs = {'data': self.dry_run_data,
|
kwargs = {'data': self.dry_run_data,
|
||||||
'is_dry_run': is_dry_run,
|
'is_dry_run': is_dry_run,
|
||||||
|
'resource_list_json': self.resource_data,
|
||||||
'saved_state_json': self.json_data,
|
'saved_state_json': self.json_data,
|
||||||
'is_preserve': False,
|
'is_preserve': False,
|
||||||
|
'is_resource_list': is_resource_list,
|
||||||
'is_save_state': is_save_state,
|
'is_save_state': is_save_state,
|
||||||
'prefix': cleanup_prefix}
|
'prefix': cleanup_prefix}
|
||||||
project_service = cleanup_service.ProjectService(admin_mgr, **kwargs)
|
project_service = cleanup_service.ProjectService(admin_mgr, **kwargs)
|
||||||
@ -208,8 +237,10 @@ class TempestCleanup(command.Command):
|
|||||||
|
|
||||||
kwargs = {'data': self.dry_run_data,
|
kwargs = {'data': self.dry_run_data,
|
||||||
'is_dry_run': is_dry_run,
|
'is_dry_run': is_dry_run,
|
||||||
|
'resource_list_json': self.resource_data,
|
||||||
'saved_state_json': self.json_data,
|
'saved_state_json': self.json_data,
|
||||||
'is_preserve': is_preserve,
|
'is_preserve': is_preserve,
|
||||||
|
'is_resource_list': is_resource_list,
|
||||||
'is_save_state': is_save_state,
|
'is_save_state': is_save_state,
|
||||||
'prefix': cleanup_prefix,
|
'prefix': cleanup_prefix,
|
||||||
'got_exceptions': self.GOT_EXCEPTIONS}
|
'got_exceptions': self.GOT_EXCEPTIONS}
|
||||||
@ -228,11 +259,17 @@ class TempestCleanup(command.Command):
|
|||||||
f.write(json.dumps(self.dry_run_data, sort_keys=True,
|
f.write(json.dumps(self.dry_run_data, sort_keys=True,
|
||||||
indent=2, separators=(',', ': ')))
|
indent=2, separators=(',', ': ')))
|
||||||
|
|
||||||
|
if is_resource_list:
|
||||||
|
LOG.info("Clearing 'resource_list.json' file.")
|
||||||
|
with open(RESOURCE_LIST_JSON, 'w') as f:
|
||||||
|
f.write('{}')
|
||||||
|
|
||||||
def _clean_project(self, project):
|
def _clean_project(self, project):
|
||||||
LOG.debug("Cleaning project: %s ", project['name'])
|
LOG.debug("Cleaning project: %s ", project['name'])
|
||||||
is_dry_run = self.options.dry_run
|
is_dry_run = self.options.dry_run
|
||||||
dry_run_data = self.dry_run_data
|
dry_run_data = self.dry_run_data
|
||||||
is_preserve = not self.options.delete_tempest_conf_objects
|
is_preserve = not self.options.delete_tempest_conf_objects
|
||||||
|
is_resource_list = self.options.resource_list
|
||||||
project_id = project['id']
|
project_id = project['id']
|
||||||
project_name = project['name']
|
project_name = project['name']
|
||||||
project_data = None
|
project_data = None
|
||||||
@ -244,7 +281,9 @@ class TempestCleanup(command.Command):
|
|||||||
kwargs = {'data': project_data,
|
kwargs = {'data': project_data,
|
||||||
'is_dry_run': is_dry_run,
|
'is_dry_run': is_dry_run,
|
||||||
'saved_state_json': self.json_data,
|
'saved_state_json': self.json_data,
|
||||||
|
'resource_list_json': self.resource_data,
|
||||||
'is_preserve': is_preserve,
|
'is_preserve': is_preserve,
|
||||||
|
'is_resource_list': is_resource_list,
|
||||||
'is_save_state': False,
|
'is_save_state': False,
|
||||||
'project_id': project_id,
|
'project_id': project_id,
|
||||||
'prefix': cleanup_prefix,
|
'prefix': cleanup_prefix,
|
||||||
@ -287,6 +326,19 @@ class TempestCleanup(command.Command):
|
|||||||
"ignored when --init-saved-state is used so that "
|
"ignored when --init-saved-state is used so that "
|
||||||
"it can capture the true init state - all "
|
"it can capture the true init state - all "
|
||||||
"resources present at that moment.")
|
"resources present at that moment.")
|
||||||
|
parser.add_argument('--resource-list', action="store_true",
|
||||||
|
dest='resource_list', default=False,
|
||||||
|
help="Runs tempest cleanup with generated "
|
||||||
|
"JSON file: " + RESOURCE_LIST_JSON + " to "
|
||||||
|
"erase resources created during Tempest run. "
|
||||||
|
"NOTE: To create " + RESOURCE_LIST_JSON + " "
|
||||||
|
"set config option record_resources under default "
|
||||||
|
"section in tempest.conf file to true. This "
|
||||||
|
"option will be ignored when --init-saved-state "
|
||||||
|
"is used so that it can capture the true init "
|
||||||
|
"state - all resources present at that moment. "
|
||||||
|
"This option will be ignored if passed with "
|
||||||
|
"--prefix.")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
@ -304,6 +356,7 @@ class TempestCleanup(command.Command):
|
|||||||
'is_dry_run': False,
|
'is_dry_run': False,
|
||||||
'saved_state_json': data,
|
'saved_state_json': data,
|
||||||
'is_preserve': False,
|
'is_preserve': False,
|
||||||
|
'is_resource_list': False,
|
||||||
'is_save_state': True,
|
'is_save_state': True,
|
||||||
# must be None as we want to capture true init state
|
# must be None as we want to capture true init state
|
||||||
# (all resources present) thus no filtering based
|
# (all resources present) thus no filtering based
|
||||||
@ -326,15 +379,31 @@ class TempestCleanup(command.Command):
|
|||||||
f.write(json.dumps(data, sort_keys=True,
|
f.write(json.dumps(data, sort_keys=True,
|
||||||
indent=2, separators=(',', ': ')))
|
indent=2, separators=(',', ': ')))
|
||||||
|
|
||||||
def _load_json(self, saved_state_json=SAVED_STATE_JSON):
|
def _load_resource_list(self, resource_list_json=RESOURCE_LIST_JSON):
|
||||||
|
try:
|
||||||
|
with open(resource_list_json, 'rb') as json_file:
|
||||||
|
self.resource_data = json.load(json_file)
|
||||||
|
except IOError as ex:
|
||||||
|
LOG.exception(
|
||||||
|
"Failed loading 'resource_list.json', please "
|
||||||
|
"be sure you created this file by setting config "
|
||||||
|
"option record_resources in default section to true "
|
||||||
|
"prior to running tempest. Exception: %s", ex)
|
||||||
|
sys.exit(ex)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(
|
||||||
|
"Exception parsing 'resource_list.json' : %s", ex)
|
||||||
|
sys.exit(ex)
|
||||||
|
|
||||||
|
def _load_saved_state(self, saved_state_json=SAVED_STATE_JSON):
|
||||||
try:
|
try:
|
||||||
with open(saved_state_json, 'rb') as json_file:
|
with open(saved_state_json, 'rb') as json_file:
|
||||||
self.json_data = json.load(json_file)
|
self.json_data = json.load(json_file)
|
||||||
|
|
||||||
except IOError as ex:
|
except IOError as ex:
|
||||||
LOG.exception("Failed loading saved state, please be sure you"
|
LOG.exception(
|
||||||
" have first run cleanup with --init-saved-state "
|
"Failed loading saved state, please be sure you"
|
||||||
"flag prior to running tempest. Exception: %s", ex)
|
" have first run cleanup with --init-saved-state "
|
||||||
|
"flag prior to running tempest. Exception: %s", ex)
|
||||||
sys.exit(ex)
|
sys.exit(ex)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
LOG.exception("Exception parsing saved state json : %s", ex)
|
LOG.exception("Exception parsing saved state json : %s", ex)
|
||||||
|
@ -120,6 +120,13 @@ class BaseService(object):
|
|||||||
if item['name'].startswith(self.prefix)]
|
if item['name'].startswith(self.prefix)]
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
def _filter_by_resource_list(self, item_list, attr):
|
||||||
|
if attr not in self.resource_list_json:
|
||||||
|
return []
|
||||||
|
items = [item for item in item_list if item['id']
|
||||||
|
in self.resource_list_json[attr].keys()]
|
||||||
|
return items
|
||||||
|
|
||||||
def _filter_out_ids_from_saved(self, item_list, attr):
|
def _filter_out_ids_from_saved(self, item_list, attr):
|
||||||
items = [item for item in item_list if item['id']
|
items = [item for item in item_list if item['id']
|
||||||
not in self.saved_state_json[attr].keys()]
|
not in self.saved_state_json[attr].keys()]
|
||||||
@ -166,8 +173,11 @@ class SnapshotService(BaseService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
client = self.client
|
client = self.client
|
||||||
snaps = client.list_snapshots()['snapshots']
|
snaps = client.list_snapshots()['snapshots']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
snaps = self._filter_by_prefix(snaps)
|
snaps = self._filter_by_prefix(snaps)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
snaps = self._filter_by_resource_list(snaps, 'snapshots')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved snapshots
|
# recreate list removing saved snapshots
|
||||||
snaps = self._filter_out_ids_from_saved(snaps, 'snapshots')
|
snaps = self._filter_out_ids_from_saved(snaps, 'snapshots')
|
||||||
@ -205,8 +215,11 @@ class ServerService(BaseService):
|
|||||||
client = self.client
|
client = self.client
|
||||||
servers_body = client.list_servers()
|
servers_body = client.list_servers()
|
||||||
servers = servers_body['servers']
|
servers = servers_body['servers']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
servers = self._filter_by_prefix(servers)
|
servers = self._filter_by_prefix(servers)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
servers = self._filter_by_resource_list(servers, 'servers')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved servers
|
# recreate list removing saved servers
|
||||||
servers = self._filter_out_ids_from_saved(servers, 'servers')
|
servers = self._filter_out_ids_from_saved(servers, 'servers')
|
||||||
@ -238,9 +251,12 @@ class ServerGroupService(ServerService):
|
|||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
client = self.server_groups_client
|
client = self.server_groups_client
|
||||||
sgs = client.list_server_groups()['server_groups']
|
sgs = client.list_server_groups(all_projects=True)['server_groups']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
sgs = self._filter_by_prefix(sgs)
|
sgs = self._filter_by_prefix(sgs)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
sgs = self._filter_by_resource_list(sgs, 'server_groups')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved server_groups
|
# recreate list removing saved server_groups
|
||||||
sgs = self._filter_out_ids_from_saved(sgs, 'server_groups')
|
sgs = self._filter_out_ids_from_saved(sgs, 'server_groups')
|
||||||
@ -276,8 +292,13 @@ class KeyPairService(BaseService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
client = self.client
|
client = self.client
|
||||||
keypairs = client.list_keypairs()['keypairs']
|
keypairs = client.list_keypairs()['keypairs']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
keypairs = self._filter_by_prefix(keypairs)
|
keypairs = self._filter_by_prefix(keypairs)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
keypairs = [keypair for keypair in keypairs
|
||||||
|
if keypair['keypair']['name']
|
||||||
|
in self.resource_list_json['keypairs'].keys()]
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved keypairs
|
# recreate list removing saved keypairs
|
||||||
keypairs = [keypair for keypair in keypairs
|
keypairs = [keypair for keypair in keypairs
|
||||||
@ -317,8 +338,11 @@ class VolumeService(BaseService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
client = self.client
|
client = self.client
|
||||||
vols = client.list_volumes()['volumes']
|
vols = client.list_volumes()['volumes']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
vols = self._filter_by_prefix(vols)
|
vols = self._filter_by_prefix(vols)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
vols = self._filter_by_resource_list(vols, 'volumes')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved volumes
|
# recreate list removing saved volumes
|
||||||
vols = self._filter_out_ids_from_saved(vols, 'volumes')
|
vols = self._filter_out_ids_from_saved(vols, 'volumes')
|
||||||
@ -462,8 +486,11 @@ class NetworkService(BaseNetworkService):
|
|||||||
client = self.networks_client
|
client = self.networks_client
|
||||||
networks = client.list_networks(**self.tenant_filter)
|
networks = client.list_networks(**self.tenant_filter)
|
||||||
networks = networks['networks']
|
networks = networks['networks']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
networks = self._filter_by_prefix(networks)
|
networks = self._filter_by_prefix(networks)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
networks = self._filter_by_resource_list(networks, 'networks')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved networks
|
# recreate list removing saved networks
|
||||||
@ -500,15 +527,17 @@ class NetworkService(BaseNetworkService):
|
|||||||
class NetworkFloatingIpService(BaseNetworkService):
|
class NetworkFloatingIpService(BaseNetworkService):
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
if self.prefix:
|
|
||||||
# this means we're cleaning resources based on a certain prefix,
|
|
||||||
# this resource doesn't have a name, therefore return empty list
|
|
||||||
return []
|
|
||||||
client = self.floating_ips_client
|
client = self.floating_ips_client
|
||||||
flips = client.list_floatingips(**self.tenant_filter)
|
flips = client.list_floatingips(**self.tenant_filter)
|
||||||
flips = flips['floatingips']
|
flips = flips['floatingips']
|
||||||
|
|
||||||
if not self.is_save_state:
|
if self.prefix:
|
||||||
|
# this means we're cleaning resources based on a certain prefix,
|
||||||
|
# this resource doesn't have a name, therefore return empty list
|
||||||
|
return []
|
||||||
|
elif self.is_resource_list:
|
||||||
|
flips = self._filter_by_resource_list(flips, 'floatingips')
|
||||||
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved flips
|
# recreate list removing saved flips
|
||||||
flips = self._filter_out_ids_from_saved(flips, 'floatingips')
|
flips = self._filter_out_ids_from_saved(flips, 'floatingips')
|
||||||
LOG.debug("List count, %s Network Floating IPs", len(flips))
|
LOG.debug("List count, %s Network Floating IPs", len(flips))
|
||||||
@ -543,8 +572,11 @@ class NetworkRouterService(BaseNetworkService):
|
|||||||
client = self.routers_client
|
client = self.routers_client
|
||||||
routers = client.list_routers(**self.tenant_filter)
|
routers = client.list_routers(**self.tenant_filter)
|
||||||
routers = routers['routers']
|
routers = routers['routers']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
routers = self._filter_by_prefix(routers)
|
routers = self._filter_by_prefix(routers)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
routers = self._filter_by_resource_list(routers, 'routers')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved routers
|
# recreate list removing saved routers
|
||||||
@ -592,16 +624,19 @@ class NetworkRouterService(BaseNetworkService):
|
|||||||
class NetworkMeteringLabelRuleService(NetworkService):
|
class NetworkMeteringLabelRuleService(NetworkService):
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
if self.prefix:
|
|
||||||
# this means we're cleaning resources based on a certain prefix,
|
|
||||||
# this resource doesn't have a name, therefore return empty list
|
|
||||||
return []
|
|
||||||
client = self.metering_label_rules_client
|
client = self.metering_label_rules_client
|
||||||
rules = client.list_metering_label_rules()
|
rules = client.list_metering_label_rules()
|
||||||
rules = rules['metering_label_rules']
|
rules = rules['metering_label_rules']
|
||||||
rules = self._filter_by_tenant_id(rules)
|
rules = self._filter_by_tenant_id(rules)
|
||||||
|
|
||||||
if not self.is_save_state:
|
if self.prefix:
|
||||||
|
# this means we're cleaning resources based on a certain prefix,
|
||||||
|
# this resource doesn't have a name, therefore return empty list
|
||||||
|
return []
|
||||||
|
elif self.is_resource_list:
|
||||||
|
rules = self._filter_by_resource_list(
|
||||||
|
rules, 'metering_label_rules')
|
||||||
|
elif not self.is_save_state:
|
||||||
rules = self._filter_out_ids_from_saved(
|
rules = self._filter_out_ids_from_saved(
|
||||||
rules, 'metering_label_rules')
|
rules, 'metering_label_rules')
|
||||||
# recreate list removing saved rules
|
# recreate list removing saved rules
|
||||||
@ -638,8 +673,12 @@ class NetworkMeteringLabelService(BaseNetworkService):
|
|||||||
labels = client.list_metering_labels()
|
labels = client.list_metering_labels()
|
||||||
labels = labels['metering_labels']
|
labels = labels['metering_labels']
|
||||||
labels = self._filter_by_tenant_id(labels)
|
labels = self._filter_by_tenant_id(labels)
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
labels = self._filter_by_prefix(labels)
|
labels = self._filter_by_prefix(labels)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
labels = self._filter_by_resource_list(
|
||||||
|
labels, 'metering_labels')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# recreate list removing saved labels
|
# recreate list removing saved labels
|
||||||
labels = self._filter_out_ids_from_saved(
|
labels = self._filter_out_ids_from_saved(
|
||||||
@ -677,8 +716,11 @@ class NetworkPortService(BaseNetworkService):
|
|||||||
client.list_ports(**self.tenant_filter)['ports']
|
client.list_ports(**self.tenant_filter)['ports']
|
||||||
if port["device_owner"] == "" or
|
if port["device_owner"] == "" or
|
||||||
port["device_owner"].startswith("compute:")]
|
port["device_owner"].startswith("compute:")]
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
ports = self._filter_by_prefix(ports)
|
ports = self._filter_by_prefix(ports)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
ports = self._filter_by_resource_list(ports, 'ports')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved ports
|
# recreate list removing saved ports
|
||||||
@ -717,8 +759,12 @@ class NetworkSecGroupService(BaseNetworkService):
|
|||||||
secgroups = [secgroup for secgroup in
|
secgroups = [secgroup for secgroup in
|
||||||
client.list_security_groups(**filter)['security_groups']
|
client.list_security_groups(**filter)['security_groups']
|
||||||
if secgroup['name'] != 'default']
|
if secgroup['name'] != 'default']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
secgroups = self._filter_by_prefix(secgroups)
|
secgroups = self._filter_by_prefix(secgroups)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
secgroups = self._filter_by_resource_list(
|
||||||
|
secgroups, 'security_groups')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved security_groups
|
# recreate list removing saved security_groups
|
||||||
@ -760,8 +806,11 @@ class NetworkSubnetService(BaseNetworkService):
|
|||||||
client = self.subnets_client
|
client = self.subnets_client
|
||||||
subnets = client.list_subnets(**self.tenant_filter)
|
subnets = client.list_subnets(**self.tenant_filter)
|
||||||
subnets = subnets['subnets']
|
subnets = subnets['subnets']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
subnets = self._filter_by_prefix(subnets)
|
subnets = self._filter_by_prefix(subnets)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
subnets = self._filter_by_resource_list(subnets, 'subnets')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved subnets
|
# recreate list removing saved subnets
|
||||||
@ -797,8 +846,11 @@ class NetworkSubnetPoolsService(BaseNetworkService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
client = self.subnetpools_client
|
client = self.subnetpools_client
|
||||||
pools = client.list_subnetpools(**self.tenant_filter)['subnetpools']
|
pools = client.list_subnetpools(**self.tenant_filter)['subnetpools']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
pools = self._filter_by_prefix(pools)
|
pools = self._filter_by_prefix(pools)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
pools = self._filter_by_resource_list(pools, 'subnetpools')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved subnet pools
|
# recreate list removing saved subnet pools
|
||||||
@ -838,13 +890,18 @@ class RegionService(BaseService):
|
|||||||
self.client = manager.regions_client
|
self.client = manager.regions_client
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
|
client = self.client
|
||||||
|
regions = client.list_regions()
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
# this means we're cleaning resources based on a certain prefix,
|
# this means we're cleaning resources based on a certain prefix,
|
||||||
# this resource doesn't have a name, therefore return empty list
|
# this resource doesn't have a name, therefore return empty list
|
||||||
return []
|
return []
|
||||||
client = self.client
|
elif self.is_resource_list:
|
||||||
regions = client.list_regions()
|
regions = self._filter_by_resource_list(
|
||||||
if not self.is_save_state:
|
regions['regions'], 'regions')
|
||||||
|
return regions
|
||||||
|
elif not self.is_save_state:
|
||||||
regions = self._filter_out_ids_from_saved(
|
regions = self._filter_out_ids_from_saved(
|
||||||
regions['regions'], 'regions')
|
regions['regions'], 'regions')
|
||||||
LOG.debug("List count, %s Regions", len(regions))
|
LOG.debug("List count, %s Regions", len(regions))
|
||||||
@ -884,8 +941,11 @@ class FlavorService(BaseService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
client = self.client
|
client = self.client
|
||||||
flavors = client.list_flavors({"is_public": None})['flavors']
|
flavors = client.list_flavors({"is_public": None})['flavors']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
flavors = self._filter_by_prefix(flavors)
|
flavors = self._filter_by_prefix(flavors)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
flavors = self._filter_by_resource_list(flavors, 'flavors')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
# recreate list removing saved flavors
|
# recreate list removing saved flavors
|
||||||
@ -932,8 +992,11 @@ class ImageService(BaseService):
|
|||||||
marker = urllib.parse_qs(parsed.query)['marker'][0]
|
marker = urllib.parse_qs(parsed.query)['marker'][0]
|
||||||
response = client.list_images(params={"marker": marker})
|
response = client.list_images(params={"marker": marker})
|
||||||
images.extend(response['images'])
|
images.extend(response['images'])
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
images = self._filter_by_prefix(images)
|
images = self._filter_by_prefix(images)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
images = self._filter_by_resource_list(images, 'images')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
images = self._filter_out_ids_from_saved(images, 'images')
|
images = self._filter_out_ids_from_saved(images, 'images')
|
||||||
@ -974,6 +1037,8 @@ class UserService(BaseService):
|
|||||||
users = self.client.list_users()['users']
|
users = self.client.list_users()['users']
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
users = self._filter_by_prefix(users)
|
users = self._filter_by_prefix(users)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
users = self._filter_by_resource_list(users, 'users')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
users = self._filter_out_ids_from_saved(users, 'users')
|
users = self._filter_out_ids_from_saved(users, 'users')
|
||||||
@ -1015,8 +1080,11 @@ class RoleService(BaseService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
try:
|
try:
|
||||||
roles = self.client.list_roles()['roles']
|
roles = self.client.list_roles()['roles']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
roles = self._filter_by_prefix(roles)
|
roles = self._filter_by_prefix(roles)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
roles = self._filter_by_resource_list(roles, 'roles')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
# reconcile roles with saved state and never list admin role
|
# reconcile roles with saved state and never list admin role
|
||||||
roles = self._filter_out_ids_from_saved(roles, 'roles')
|
roles = self._filter_out_ids_from_saved(roles, 'roles')
|
||||||
@ -1056,8 +1124,11 @@ class ProjectService(BaseService):
|
|||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
projects = self.client.list_projects()['projects']
|
projects = self.client.list_projects()['projects']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
projects = self._filter_by_prefix(projects)
|
projects = self._filter_by_prefix(projects)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
projects = self._filter_by_resource_list(projects, 'projects')
|
||||||
else:
|
else:
|
||||||
if not self.is_save_state:
|
if not self.is_save_state:
|
||||||
projects = self._filter_out_ids_from_saved(
|
projects = self._filter_out_ids_from_saved(
|
||||||
@ -1099,8 +1170,11 @@ class DomainService(BaseService):
|
|||||||
def list(self):
|
def list(self):
|
||||||
client = self.client
|
client = self.client
|
||||||
domains = client.list_domains()['domains']
|
domains = client.list_domains()['domains']
|
||||||
|
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
domains = self._filter_by_prefix(domains)
|
domains = self._filter_by_prefix(domains)
|
||||||
|
elif self.is_resource_list:
|
||||||
|
domains = self._filter_by_resource_list(domains, 'domains')
|
||||||
elif not self.is_save_state:
|
elif not self.is_save_state:
|
||||||
domains = self._filter_out_ids_from_saved(domains, 'domains')
|
domains = self._filter_out_ids_from_saved(domains, 'domains')
|
||||||
LOG.debug("List count, %s Domains after reconcile", len(domains))
|
LOG.debug("List count, %s Domains after reconcile", len(domains))
|
||||||
|
@ -1309,6 +1309,15 @@ or
|
|||||||
"to cleanup only the resources that match the prefix. "
|
"to cleanup only the resources that match the prefix. "
|
||||||
"Make sure this prefix does not match with the resource "
|
"Make sure this prefix does not match with the resource "
|
||||||
"name you do not want Tempest cleanup CLI to delete."),
|
"name you do not want Tempest cleanup CLI to delete."),
|
||||||
|
cfg.BoolOpt('record_resources',
|
||||||
|
default=False,
|
||||||
|
help="Allows to record all resources created by Tempest. "
|
||||||
|
"These resources are stored in file resource_list.json, "
|
||||||
|
"which can be later used for resource deletion by "
|
||||||
|
"command tempest cleanup. The resource_list.json file "
|
||||||
|
"will be appended in case of multiple Tempest runs, "
|
||||||
|
"so the file will contain a list of resources created "
|
||||||
|
"during all Tempest runs."),
|
||||||
]
|
]
|
||||||
|
|
||||||
_opts = [
|
_opts = [
|
||||||
|
@ -21,6 +21,7 @@ import time
|
|||||||
import urllib
|
import urllib
|
||||||
import urllib3
|
import urllib3
|
||||||
|
|
||||||
|
from fasteners import process_lock
|
||||||
import jsonschema
|
import jsonschema
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_log import versionutils
|
from oslo_log import versionutils
|
||||||
@ -78,6 +79,17 @@ class RestClient(object):
|
|||||||
# The version of the API this client implements
|
# The version of the API this client implements
|
||||||
api_version = None
|
api_version = None
|
||||||
|
|
||||||
|
# Directory for storing read-write lock
|
||||||
|
lock_dir = None
|
||||||
|
|
||||||
|
# An interprocess lock used when the recording of all resources created by
|
||||||
|
# Tempest is allowed.
|
||||||
|
rec_rw_lock = None
|
||||||
|
|
||||||
|
# Variable mirrors value in config option 'record_resources' that allows
|
||||||
|
# the recording of all resources created by Tempest.
|
||||||
|
record_resources = False
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
def __init__(self, auth_provider, service, region,
|
def __init__(self, auth_provider, service, region,
|
||||||
@ -297,7 +309,13 @@ class RestClient(object):
|
|||||||
and the second the response body
|
and the second the response body
|
||||||
:rtype: tuple
|
:rtype: tuple
|
||||||
"""
|
"""
|
||||||
return self.request('POST', url, extra_headers, headers, body, chunked)
|
resp_header, resp_body = self.request(
|
||||||
|
'POST', url, extra_headers, headers, body, chunked)
|
||||||
|
|
||||||
|
if self.record_resources:
|
||||||
|
self.resource_record(resp_body)
|
||||||
|
|
||||||
|
return resp_header, resp_body
|
||||||
|
|
||||||
def get(self, url, headers=None, extra_headers=False, chunked=False):
|
def get(self, url, headers=None, extra_headers=False, chunked=False):
|
||||||
"""Send a HTTP GET request using keystone service catalog and auth
|
"""Send a HTTP GET request using keystone service catalog and auth
|
||||||
@ -1006,6 +1024,66 @@ class RestClient(object):
|
|||||||
"""Returns the primary type of resource this client works with."""
|
"""Returns the primary type of resource this client works with."""
|
||||||
return 'resource'
|
return 'resource'
|
||||||
|
|
||||||
|
def resource_update(self, data, res_type, res_dict):
|
||||||
|
"""Updates resource_list.json file with current resource."""
|
||||||
|
if not isinstance(res_dict, dict):
|
||||||
|
return
|
||||||
|
|
||||||
|
if not res_type.endswith('s'):
|
||||||
|
res_type += 's'
|
||||||
|
|
||||||
|
if res_type not in data:
|
||||||
|
data[res_type] = {}
|
||||||
|
|
||||||
|
if 'uuid' in res_dict:
|
||||||
|
data[res_type].update(
|
||||||
|
{res_dict.get('uuid'): res_dict.get('name')})
|
||||||
|
elif 'id' in res_dict:
|
||||||
|
data[res_type].update(
|
||||||
|
{res_dict.get('id'): res_dict.get('name')})
|
||||||
|
elif 'name' in res_dict:
|
||||||
|
data[res_type].update({res_dict.get('name'): ""})
|
||||||
|
|
||||||
|
self.rec_rw_lock.acquire_write_lock()
|
||||||
|
with open("resource_list.json", 'w+') as f:
|
||||||
|
f.write(json.dumps(data, indent=2, separators=(',', ': ')))
|
||||||
|
self.rec_rw_lock.release_write_lock()
|
||||||
|
|
||||||
|
def resource_record(self, resp_dict):
|
||||||
|
"""Records resources into resource_list.json file."""
|
||||||
|
if self.rec_rw_lock is None:
|
||||||
|
path = self.lock_dir
|
||||||
|
self.rec_rw_lock = (
|
||||||
|
process_lock.InterProcessReaderWriterLock(path)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.rec_rw_lock.acquire_read_lock()
|
||||||
|
try:
|
||||||
|
with open('resource_list.json', 'rb') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
except IOError:
|
||||||
|
data = {}
|
||||||
|
self.rec_rw_lock.release_read_lock()
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp_dict = json.loads(resp_dict.decode('utf-8'))
|
||||||
|
except (AttributeError, TypeError, ValueError):
|
||||||
|
return
|
||||||
|
|
||||||
|
# check if response has any keys
|
||||||
|
if not resp_dict.keys():
|
||||||
|
return
|
||||||
|
|
||||||
|
resource_type = list(resp_dict.keys())[0]
|
||||||
|
|
||||||
|
resource_dict = resp_dict[resource_type]
|
||||||
|
|
||||||
|
if isinstance(resource_dict, list):
|
||||||
|
for resource in resource_dict:
|
||||||
|
self.resource_update(data, resource_type, resource)
|
||||||
|
else:
|
||||||
|
self.resource_update(data, resource_type, resource_dict)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_response(cls, schema, resp, body):
|
def validate_response(cls, schema, resp, body):
|
||||||
# Only check the response if the status code is a success code
|
# Only check the response if the status code is a success code
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from urllib import parse as urllib
|
||||||
|
|
||||||
from oslo_serialization import jsonutils as json
|
from oslo_serialization import jsonutils as json
|
||||||
|
|
||||||
from tempest.lib.api_schema.response.compute.v2_1 import server_groups \
|
from tempest.lib.api_schema.response.compute.v2_1 import server_groups \
|
||||||
@ -55,9 +57,14 @@ class ServerGroupsClient(base_compute_client.BaseComputeClient):
|
|||||||
self.validate_response(schema.delete_server_group, resp, body)
|
self.validate_response(schema.delete_server_group, resp, body)
|
||||||
return rest_client.ResponseBody(resp, body)
|
return rest_client.ResponseBody(resp, body)
|
||||||
|
|
||||||
def list_server_groups(self):
|
def list_server_groups(self, **params):
|
||||||
"""List the server-groups."""
|
"""List the server-groups."""
|
||||||
resp, body = self.get("os-server-groups")
|
|
||||||
|
url = 'os-server-groups'
|
||||||
|
if params:
|
||||||
|
url += '?%s' % urllib.urlencode(params)
|
||||||
|
|
||||||
|
resp, body = self.get(url)
|
||||||
body = json.loads(body)
|
body = json.loads(body)
|
||||||
schema = self.get_schema(self.schema_versions_info)
|
schema = self.get_schema(self.schema_versions_info)
|
||||||
self.validate_response(schema.list_server_groups, resp, body)
|
self.validate_response(schema.list_server_groups, resp, body)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from tempest.cmd import cleanup
|
from tempest.cmd import cleanup
|
||||||
@ -20,12 +21,30 @@ from tempest.tests import base
|
|||||||
|
|
||||||
class TestTempestCleanup(base.TestCase):
|
class TestTempestCleanup(base.TestCase):
|
||||||
|
|
||||||
def test_load_json(self):
|
def test_load_json_saved_state(self):
|
||||||
# instantiate "empty" TempestCleanup
|
# instantiate "empty" TempestCleanup
|
||||||
c = cleanup.TempestCleanup(None, None, 'test')
|
c = cleanup.TempestCleanup(None, None, 'test')
|
||||||
test_saved_json = 'tempest/tests/cmd/test_saved_state_json.json'
|
test_saved_json = 'tempest/tests/cmd/test_saved_state_json.json'
|
||||||
|
with open(test_saved_json, 'r') as f:
|
||||||
|
test_saved_json_content = json.load(f)
|
||||||
# test if the file is loaded without any issues/exceptions
|
# test if the file is loaded without any issues/exceptions
|
||||||
c._load_json(test_saved_json)
|
c.options = mock.Mock()
|
||||||
|
c.options.init_saved_state = True
|
||||||
|
c._load_saved_state(test_saved_json)
|
||||||
|
self.assertEqual(c.json_data, test_saved_json_content)
|
||||||
|
|
||||||
|
def test_load_json_resource_list(self):
|
||||||
|
# instantiate "empty" TempestCleanup
|
||||||
|
c = cleanup.TempestCleanup(None, None, 'test')
|
||||||
|
test_resource_list = 'tempest/tests/cmd/test_resource_list.json'
|
||||||
|
with open(test_resource_list, 'r') as f:
|
||||||
|
test_resource_list_content = json.load(f)
|
||||||
|
# test if the file is loaded without any issues/exceptions
|
||||||
|
c.options = mock.Mock()
|
||||||
|
c.options.init_saved_state = False
|
||||||
|
c.options.resource_list = True
|
||||||
|
c._load_resource_list(test_resource_list)
|
||||||
|
self.assertEqual(c.resource_data, test_resource_list_content)
|
||||||
|
|
||||||
@mock.patch('tempest.cmd.cleanup.TempestCleanup.init')
|
@mock.patch('tempest.cmd.cleanup.TempestCleanup.init')
|
||||||
@mock.patch('tempest.cmd.cleanup.TempestCleanup._cleanup')
|
@mock.patch('tempest.cmd.cleanup.TempestCleanup._cleanup')
|
||||||
|
@ -41,8 +41,10 @@ class TestBaseService(base.TestCase):
|
|||||||
def test_base_service_init(self):
|
def test_base_service_init(self):
|
||||||
kwargs = {'data': {'data': 'test'},
|
kwargs = {'data': {'data': 'test'},
|
||||||
'is_dry_run': False,
|
'is_dry_run': False,
|
||||||
|
'resource_list_json': {'resp': 'data'},
|
||||||
'saved_state_json': {'saved': 'data'},
|
'saved_state_json': {'saved': 'data'},
|
||||||
'is_preserve': False,
|
'is_preserve': False,
|
||||||
|
'is_resource_list': False,
|
||||||
'is_save_state': True,
|
'is_save_state': True,
|
||||||
'prefix': 'tempest',
|
'prefix': 'tempest',
|
||||||
'tenant_id': 'project_id',
|
'tenant_id': 'project_id',
|
||||||
@ -50,8 +52,10 @@ class TestBaseService(base.TestCase):
|
|||||||
base = cleanup_service.BaseService(kwargs)
|
base = cleanup_service.BaseService(kwargs)
|
||||||
self.assertEqual(base.data, kwargs['data'])
|
self.assertEqual(base.data, kwargs['data'])
|
||||||
self.assertFalse(base.is_dry_run)
|
self.assertFalse(base.is_dry_run)
|
||||||
|
self.assertEqual(base.resource_list_json, kwargs['resource_list_json'])
|
||||||
self.assertEqual(base.saved_state_json, kwargs['saved_state_json'])
|
self.assertEqual(base.saved_state_json, kwargs['saved_state_json'])
|
||||||
self.assertFalse(base.is_preserve)
|
self.assertFalse(base.is_preserve)
|
||||||
|
self.assertFalse(base.is_resource_list)
|
||||||
self.assertTrue(base.is_save_state)
|
self.assertTrue(base.is_save_state)
|
||||||
self.assertEqual(base.tenant_filter['project_id'], kwargs['tenant_id'])
|
self.assertEqual(base.tenant_filter['project_id'], kwargs['tenant_id'])
|
||||||
self.assertEqual(base.got_exceptions, kwargs['got_exceptions'])
|
self.assertEqual(base.got_exceptions, kwargs['got_exceptions'])
|
||||||
@ -60,8 +64,10 @@ class TestBaseService(base.TestCase):
|
|||||||
def test_not_implemented_ex(self):
|
def test_not_implemented_ex(self):
|
||||||
kwargs = {'data': {'data': 'test'},
|
kwargs = {'data': {'data': 'test'},
|
||||||
'is_dry_run': False,
|
'is_dry_run': False,
|
||||||
|
'resource_list_json': {'resp': 'data'},
|
||||||
'saved_state_json': {'saved': 'data'},
|
'saved_state_json': {'saved': 'data'},
|
||||||
'is_preserve': False,
|
'is_preserve': False,
|
||||||
|
'is_resource_list': False,
|
||||||
'is_save_state': False,
|
'is_save_state': False,
|
||||||
'prefix': 'tempest',
|
'prefix': 'tempest',
|
||||||
'tenant_id': 'project_id',
|
'tenant_id': 'project_id',
|
||||||
@ -181,10 +187,20 @@ class BaseCmdServiceTests(MockFunctionsBase):
|
|||||||
"subnetpools": {'8acf64c1-43fc': 'saved-subnet-pool'},
|
"subnetpools": {'8acf64c1-43fc': 'saved-subnet-pool'},
|
||||||
"regions": {'RegionOne': {}}
|
"regions": {'RegionOne': {}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource_list = {
|
||||||
|
"keypairs": {'saved-key-pair': ""}
|
||||||
|
}
|
||||||
|
|
||||||
# Mocked methods
|
# Mocked methods
|
||||||
get_method = 'tempest.lib.common.rest_client.RestClient.get'
|
get_method = 'tempest.lib.common.rest_client.RestClient.get'
|
||||||
delete_method = 'tempest.lib.common.rest_client.RestClient.delete'
|
delete_method = 'tempest.lib.common.rest_client.RestClient.delete'
|
||||||
log_method = 'tempest.cmd.cleanup_service.LOG.exception'
|
log_method = 'tempest.cmd.cleanup_service.LOG.exception'
|
||||||
|
filter_saved_state = 'tempest.cmd.cleanup_service.' \
|
||||||
|
'BaseService._filter_out_ids_from_saved'
|
||||||
|
filter_resource_list = 'tempest.cmd.cleanup_service.' \
|
||||||
|
'BaseService._filter_by_resource_list'
|
||||||
|
filter_prefix = 'tempest.cmd.cleanup_service.BaseService._filter_by_prefix'
|
||||||
# Override parameters
|
# Override parameters
|
||||||
service_class = 'BaseService'
|
service_class = 'BaseService'
|
||||||
response = None
|
response = None
|
||||||
@ -192,17 +208,19 @@ class BaseCmdServiceTests(MockFunctionsBase):
|
|||||||
|
|
||||||
def _create_cmd_service(self, service_type, is_save_state=False,
|
def _create_cmd_service(self, service_type, is_save_state=False,
|
||||||
is_preserve=False, is_dry_run=False,
|
is_preserve=False, is_dry_run=False,
|
||||||
prefix=''):
|
prefix='', is_resource_list=False):
|
||||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||||
os = clients.Manager(creds)
|
os = clients.Manager(creds)
|
||||||
return getattr(cleanup_service, service_type)(
|
return getattr(cleanup_service, service_type)(
|
||||||
os,
|
os,
|
||||||
|
is_resource_list=is_resource_list,
|
||||||
is_save_state=is_save_state,
|
is_save_state=is_save_state,
|
||||||
is_preserve=is_preserve,
|
is_preserve=is_preserve,
|
||||||
is_dry_run=is_dry_run,
|
is_dry_run=is_dry_run,
|
||||||
prefix=prefix,
|
prefix=prefix,
|
||||||
project_id='b8e3ece07bb049138d224436756e3b57',
|
project_id='b8e3ece07bb049138d224436756e3b57',
|
||||||
data={},
|
data={},
|
||||||
|
resource_list_json=self.resource_list,
|
||||||
saved_state_json=self.saved_state
|
saved_state_json=self.saved_state
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -266,6 +284,38 @@ class BaseCmdServiceTests(MockFunctionsBase):
|
|||||||
self.assertNotIn(rsp['id'], self.conf_values.values())
|
self.assertNotIn(rsp['id'], self.conf_values.values())
|
||||||
self.assertNotIn(rsp['name'], self.conf_values.values())
|
self.assertNotIn(rsp['name'], self.conf_values.values())
|
||||||
|
|
||||||
|
def _test_prefix_opt_precedence(self, delete_mock):
|
||||||
|
serv = self._create_cmd_service(
|
||||||
|
self.service_class, is_resource_list=True, prefix='tempest')
|
||||||
|
_, fixtures = self.run_function_with_mocks(
|
||||||
|
serv.run,
|
||||||
|
delete_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that prefix was used for filtering
|
||||||
|
fixtures[2].mock.assert_called_once()
|
||||||
|
|
||||||
|
# Check that neither saved_state.json nor resource list was
|
||||||
|
# used for filtering
|
||||||
|
fixtures[0].mock.assert_not_called()
|
||||||
|
fixtures[1].mock.assert_not_called()
|
||||||
|
|
||||||
|
def _test_resource_list_opt_precedence(self, delete_mock):
|
||||||
|
serv = self._create_cmd_service(
|
||||||
|
self.service_class, is_resource_list=True)
|
||||||
|
_, fixtures = self.run_function_with_mocks(
|
||||||
|
serv.run,
|
||||||
|
delete_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that resource list was used for filtering
|
||||||
|
fixtures[1].mock.assert_called_once()
|
||||||
|
|
||||||
|
# Check that neither saved_state.json nor prefix was
|
||||||
|
# used for filtering
|
||||||
|
fixtures[0].mock.assert_not_called()
|
||||||
|
fixtures[2].mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
class TestSnapshotService(BaseCmdServiceTests):
|
class TestSnapshotService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -320,6 +370,24 @@ class TestSnapshotService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestServerService(BaseCmdServiceTests):
|
class TestServerService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -378,6 +446,24 @@ class TestServerService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestServerGroupService(BaseCmdServiceTests):
|
class TestServerGroupService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -429,6 +515,26 @@ class TestServerGroupService(BaseCmdServiceTests):
|
|||||||
(self.validate_response, 'validate', None)
|
(self.validate_response, 'validate', None)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.validate_response, 'validate', None),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.validate_response, 'validate', None),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestKeyPairService(BaseCmdServiceTests):
|
class TestKeyPairService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -493,6 +599,33 @@ class TestKeyPairService(BaseCmdServiceTests):
|
|||||||
(self.validate_response, 'validate', None)
|
(self.validate_response, 'validate', None)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.validate_response, 'validate', None),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.validate_response, 'validate', None),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
serv = self._create_cmd_service(
|
||||||
|
self.service_class, is_resource_list=True)
|
||||||
|
|
||||||
|
_, fixtures = self.run_function_with_mocks(
|
||||||
|
serv.delete,
|
||||||
|
delete_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that prefix was not used for filtering
|
||||||
|
fixtures[0].mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
class TestVolumeService(BaseCmdServiceTests):
|
class TestVolumeService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -542,6 +675,24 @@ class TestVolumeService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestVolumeQuotaService(BaseCmdServiceTests):
|
class TestVolumeQuotaService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -761,6 +912,24 @@ class TestNetworkService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkFloatingIpService(BaseCmdServiceTests):
|
class TestNetworkFloatingIpService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -823,6 +992,34 @@ class TestNetworkFloatingIpService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
serv = self._create_cmd_service(
|
||||||
|
self.service_class, is_resource_list=True, prefix='tempest')
|
||||||
|
_, fixtures = self.run_function_with_mocks(
|
||||||
|
serv.run,
|
||||||
|
delete_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
# cleanup returns []
|
||||||
|
fixtures[0].mock.assert_not_called()
|
||||||
|
fixtures[1].mock.assert_not_called()
|
||||||
|
fixtures[2].mock.assert_not_called()
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkRouterService(BaseCmdServiceTests):
|
class TestNetworkRouterService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -937,6 +1134,24 @@ class TestNetworkRouterService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkMeteringLabelRuleService(BaseCmdServiceTests):
|
class TestNetworkMeteringLabelRuleService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -978,6 +1193,34 @@ class TestNetworkMeteringLabelRuleService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
serv = self._create_cmd_service(
|
||||||
|
self.service_class, is_resource_list=True, prefix='tempest')
|
||||||
|
_, fixtures = self.run_function_with_mocks(
|
||||||
|
serv.run,
|
||||||
|
delete_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
# cleanup returns []
|
||||||
|
fixtures[0].mock.assert_not_called()
|
||||||
|
fixtures[1].mock.assert_not_called()
|
||||||
|
fixtures[2].mock.assert_not_called()
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkMeteringLabelService(BaseCmdServiceTests):
|
class TestNetworkMeteringLabelService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1020,6 +1263,24 @@ class TestNetworkMeteringLabelService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkPortService(BaseCmdServiceTests):
|
class TestNetworkPortService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1118,6 +1379,24 @@ class TestNetworkPortService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkSecGroupService(BaseCmdServiceTests):
|
class TestNetworkSecGroupService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1196,6 +1475,24 @@ class TestNetworkSecGroupService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkSubnetService(BaseCmdServiceTests):
|
class TestNetworkSubnetService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1272,6 +1569,24 @@ class TestNetworkSubnetService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkSubnetPoolsService(BaseCmdServiceTests):
|
class TestNetworkSubnetPoolsService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1340,6 +1655,24 @@ class TestNetworkSubnetPoolsService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
# begin global services
|
# begin global services
|
||||||
class TestRegionService(BaseCmdServiceTests):
|
class TestRegionService(BaseCmdServiceTests):
|
||||||
@ -1392,6 +1725,34 @@ class TestRegionService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
serv = self._create_cmd_service(
|
||||||
|
self.service_class, is_resource_list=True, prefix='tempest')
|
||||||
|
_, fixtures = self.run_function_with_mocks(
|
||||||
|
serv.run,
|
||||||
|
delete_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
# cleanup returns []
|
||||||
|
fixtures[0].mock.assert_not_called()
|
||||||
|
fixtures[1].mock.assert_not_called()
|
||||||
|
fixtures[2].mock.assert_not_called()
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestDomainService(BaseCmdServiceTests):
|
class TestDomainService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1445,6 +1806,26 @@ class TestDomainService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None),
|
||||||
|
(self.mock_update, 'update', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None),
|
||||||
|
(self.mock_update, 'update', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestProjectsService(BaseCmdServiceTests):
|
class TestProjectsService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1518,6 +1899,24 @@ class TestProjectsService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestImagesService(BaseCmdServiceTests):
|
class TestImagesService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1597,6 +1996,24 @@ class TestImagesService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestFlavorService(BaseCmdServiceTests):
|
class TestFlavorService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1670,6 +2087,24 @@ class TestFlavorService(BaseCmdServiceTests):
|
|||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestRoleService(BaseCmdServiceTests):
|
class TestRoleService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1716,6 +2151,24 @@ class TestRoleService(BaseCmdServiceTests):
|
|||||||
def test_save_state(self):
|
def test_save_state(self):
|
||||||
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
self._test_saved_state_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
|
||||||
class TestUserService(BaseCmdServiceTests):
|
class TestUserService(BaseCmdServiceTests):
|
||||||
|
|
||||||
@ -1782,3 +2235,21 @@ class TestUserService(BaseCmdServiceTests):
|
|||||||
"password_expires_at": "1893-11-06T15:32:17.000000",
|
"password_expires_at": "1893-11-06T15:32:17.000000",
|
||||||
})
|
})
|
||||||
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
self._test_is_preserve_true([(self.get_method, self.response, 200)])
|
||||||
|
|
||||||
|
def test_prefix_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_prefix_opt_precedence(delete_mock)
|
||||||
|
|
||||||
|
def test_resource_list_opt_precedence(self):
|
||||||
|
delete_mock = [(self.filter_saved_state, [], None),
|
||||||
|
(self.filter_resource_list, [], None),
|
||||||
|
(self.filter_prefix, [], None),
|
||||||
|
(self.get_method, self.response, 200),
|
||||||
|
(self.delete_method, 'error', None),
|
||||||
|
(self.log_method, 'exception', None)]
|
||||||
|
self._test_resource_list_opt_precedence(delete_mock)
|
||||||
|
11
tempest/tests/cmd/test_resource_list.json
Normal file
11
tempest/tests/cmd/test_resource_list.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"project": {
|
||||||
|
"ce4e7edf051c439d8b81c4bfe581c5ef": "test"
|
||||||
|
},
|
||||||
|
"keypairs": {
|
||||||
|
"tempest-keypair-1215039183": ""
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"74463c83f9d640fe84c4376527ceff26": "test"
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
import jsonschema
|
import jsonschema
|
||||||
@ -749,6 +750,110 @@ class TestExpectedSuccess(BaseRestClientTestClass):
|
|||||||
expected_code, read_code)
|
expected_code, read_code)
|
||||||
|
|
||||||
|
|
||||||
|
class TestRecordResources(BaseRestClientTestClass):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.fake_http = fake_http.fake_httplib2()
|
||||||
|
super(TestRecordResources, self).setUp()
|
||||||
|
|
||||||
|
def _cleanup_test_resource_record(self):
|
||||||
|
# clear resource_list.json file
|
||||||
|
with open('resource_list.json', 'w') as f:
|
||||||
|
f.write('{}')
|
||||||
|
|
||||||
|
def test_post_record_resources(self):
|
||||||
|
self.rest_client.record_resources = True
|
||||||
|
__, return_dict = self.rest_client.post(self.url, {}, {})
|
||||||
|
self.assertEqual({}, return_dict['headers'])
|
||||||
|
self.assertEqual({}, return_dict['body'])
|
||||||
|
|
||||||
|
def test_resource_record_no_top_key(self):
|
||||||
|
test_body_no_key = b'{}'
|
||||||
|
self.rest_client.resource_record(test_body_no_key)
|
||||||
|
|
||||||
|
def test_resource_record_dict(self):
|
||||||
|
test_dict_body = b'{"project": {"id": "test-id", "name": ""}}\n'
|
||||||
|
self.rest_client.resource_record(test_dict_body)
|
||||||
|
|
||||||
|
with open('resource_list.json', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
resource_list_content = json.loads(content)
|
||||||
|
|
||||||
|
test_resource_list = {
|
||||||
|
"projects": {"test-id": ""}
|
||||||
|
}
|
||||||
|
self.assertEqual(resource_list_content, test_resource_list)
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
self._cleanup_test_resource_record()
|
||||||
|
|
||||||
|
def test_resource_record_list(self):
|
||||||
|
test_list_body = '''{
|
||||||
|
"user": [
|
||||||
|
{
|
||||||
|
"id": "test-uuid",
|
||||||
|
"name": "test-name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "test-uuid2",
|
||||||
|
"name": "test-name2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'''
|
||||||
|
test_list_body = test_list_body.encode('utf-8')
|
||||||
|
self.rest_client.resource_record(test_list_body)
|
||||||
|
|
||||||
|
with open('resource_list.json', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
resource_list_content = json.loads(content)
|
||||||
|
|
||||||
|
test_resource_list = {
|
||||||
|
"users": {
|
||||||
|
"test-uuid": "test-name",
|
||||||
|
"test-uuid2": "test-name2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.assertEqual(resource_list_content, test_resource_list)
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
self._cleanup_test_resource_record()
|
||||||
|
|
||||||
|
def test_resource_update_id(self):
|
||||||
|
data = {}
|
||||||
|
res_dict = {'id': 'test-uuid', 'name': 'test-name'}
|
||||||
|
|
||||||
|
self.rest_client.rec_rw_lock = mock.MagicMock()
|
||||||
|
self.rest_client.resource_update(data, 'user', res_dict)
|
||||||
|
result = {'users': {'test-uuid': 'test-name'}}
|
||||||
|
self.assertEqual(data, result)
|
||||||
|
|
||||||
|
def test_resource_update_name(self):
|
||||||
|
data = {'keypairs': {}}
|
||||||
|
res_dict = {'name': 'test-keypair'}
|
||||||
|
|
||||||
|
self.rest_client.rec_rw_lock = mock.MagicMock()
|
||||||
|
self.rest_client.resource_update(data, 'keypair', res_dict)
|
||||||
|
result = {'keypairs': {'test-keypair': ""}}
|
||||||
|
self.assertEqual(data, result)
|
||||||
|
|
||||||
|
def test_resource_update_no_id(self):
|
||||||
|
data = {}
|
||||||
|
res_dict = {'type': 'test', 'description': 'example'}
|
||||||
|
|
||||||
|
self.rest_client.rec_rw_lock = mock.MagicMock()
|
||||||
|
self.rest_client.resource_update(data, 'projects', res_dict)
|
||||||
|
result = {'projects': {}}
|
||||||
|
self.assertEqual(data, result)
|
||||||
|
|
||||||
|
def test_resource_update_not_dict(self):
|
||||||
|
data = {}
|
||||||
|
res_dict = 'test-string'
|
||||||
|
|
||||||
|
self.rest_client.rec_rw_lock = mock.MagicMock()
|
||||||
|
self.rest_client.resource_update(data, 'user', res_dict)
|
||||||
|
self.assertEqual(data, {})
|
||||||
|
|
||||||
|
|
||||||
class TestResponseBody(base.TestCase):
|
class TestResponseBody(base.TestCase):
|
||||||
|
|
||||||
def test_str(self):
|
def test_str(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user