diff --git a/coriolis/api/v1/diagnostics.py b/coriolis/api/v1/diagnostics.py index 4f7b3e0b4..6ba735d7e 100644 --- a/coriolis/api/v1/diagnostics.py +++ b/coriolis/api/v1/diagnostics.py @@ -23,7 +23,7 @@ def index(self, req): diagnostics.get_diagnostics_policy_label("get")) return diagnostic_view.collection( - req, self._diag_api.get(context)) + self._diag_api.get(context)) def create_resource(): diff --git a/coriolis/api/v1/endpoint_destination_minion_pool_options.py b/coriolis/api/v1/endpoint_destination_minion_pool_options.py index 39b990e52..c8f07227c 100644 --- a/coriolis/api/v1/endpoint_destination_minion_pool_options.py +++ b/coriolis/api/v1/endpoint_destination_minion_pool_options.py @@ -37,7 +37,6 @@ def index(self, req, endpoint_id): return (endpoint_options_view. destination_minion_pool_options_collection)( - req, (self._minion_pool_options_api. get_endpoint_destination_minion_pool_options)( context, endpoint_id, env=env, option_names=options)) diff --git a/coriolis/api/v1/endpoint_destination_options.py b/coriolis/api/v1/endpoint_destination_options.py index 3082eee03..fef035b86 100644 --- a/coriolis/api/v1/endpoint_destination_options.py +++ b/coriolis/api/v1/endpoint_destination_options.py @@ -36,7 +36,6 @@ def index(self, req, endpoint_id): options = {} return endpoint_options_view.destination_options_collection( - req, self._destination_options_api.get_endpoint_destination_options( context, endpoint_id, env=env, option_names=options)) diff --git a/coriolis/api/v1/endpoint_instances.py b/coriolis/api/v1/endpoint_instances.py index a16db3cf2..c70622e72 100644 --- a/coriolis/api/v1/endpoint_instances.py +++ b/coriolis/api/v1/endpoint_instances.py @@ -32,7 +32,7 @@ def index(self, req, endpoint_id): env = {} return endpoint_resources_view.instances_collection( - req, self._instance_api.get_endpoint_instances( + self._instance_api.get_endpoint_instances( context, endpoint_id, env, marker, limit, instance_name_pattern)) @@ -52,7 +52,7 @@ def show(self, req, endpoint_id, id): env = {} return endpoint_resources_view.instance_single( - req, self._instance_api.get_endpoint_instance( + self._instance_api.get_endpoint_instance( req.environ['coriolis.context'], endpoint_id, env, id)) diff --git a/coriolis/api/v1/endpoint_networks.py b/coriolis/api/v1/endpoint_networks.py index 7cd2b5e8f..f34f14bed 100644 --- a/coriolis/api/v1/endpoint_networks.py +++ b/coriolis/api/v1/endpoint_networks.py @@ -28,7 +28,7 @@ def index(self, req, endpoint_id): env = {} return endpoint_resources_view.networks_collection( - req, self._network_api.get_endpoint_networks( + self._network_api.get_endpoint_networks( context, endpoint_id, env)) diff --git a/coriolis/api/v1/endpoint_source_minion_pool_options.py b/coriolis/api/v1/endpoint_source_minion_pool_options.py index 3aab73c87..2c526d9f9 100644 --- a/coriolis/api/v1/endpoint_source_minion_pool_options.py +++ b/coriolis/api/v1/endpoint_source_minion_pool_options.py @@ -36,7 +36,6 @@ def index(self, req, endpoint_id): options = {} return endpoint_options_view.source_minion_pool_options_collection( - req, (self._minion_pool_options_api. get_endpoint_source_minion_pool_options)( context, endpoint_id, env=env, option_names=options)) diff --git a/coriolis/api/v1/endpoint_source_options.py b/coriolis/api/v1/endpoint_source_options.py index 5e96f6e48..b3c7b4091 100644 --- a/coriolis/api/v1/endpoint_source_options.py +++ b/coriolis/api/v1/endpoint_source_options.py @@ -36,7 +36,6 @@ def index(self, req, endpoint_id): options = {} return endpoint_options_view.source_options_collection( - req, self._source_options_api.get_endpoint_source_options( context, endpoint_id, env=env, option_names=options)) diff --git a/coriolis/api/v1/endpoint_storage.py b/coriolis/api/v1/endpoint_storage.py index 5ddf1b446..3465fcc22 100644 --- a/coriolis/api/v1/endpoint_storage.py +++ b/coriolis/api/v1/endpoint_storage.py @@ -28,7 +28,7 @@ def index(self, req, endpoint_id): env = {} return endpoint_resources_view.storage_collection( - req, self._storage_api.get_endpoint_storage( + self._storage_api.get_endpoint_storage( context, endpoint_id, env)) diff --git a/coriolis/api/v1/endpoints.py b/coriolis/api/v1/endpoints.py index 2877d5335..a5fe63f03 100644 --- a/coriolis/api/v1/endpoints.py +++ b/coriolis/api/v1/endpoints.py @@ -27,13 +27,13 @@ def show(self, req, id): if not endpoint: raise exc.HTTPNotFound() - return endpoint_view.single(req, endpoint) + return endpoint_view.single(endpoint) def index(self, req): context = req.environ["coriolis.context"] context.can(endpoint_policies.get_endpoints_policy_label("list")) return endpoint_view.collection( - req, self._endpoint_api.get_endpoints(context)) + self._endpoint_api.get_endpoints(context)) @api_utils.format_keyerror_message(resource='endpoint', method='create') def _validate_create_body(self, body): @@ -52,7 +52,7 @@ def create(self, req, body): context.can(endpoint_policies.get_endpoints_policy_label("create")) (name, endpoint_type, description, connection_info, mapped_regions) = self._validate_create_body(body) - return endpoint_view.single(req, self._endpoint_api.create( + return endpoint_view.single(self._endpoint_api.create( context, name, endpoint_type, description, connection_info, mapped_regions)) @@ -69,7 +69,7 @@ def update(self, req, id, body): context = req.environ["coriolis.context"] context.can(endpoint_policies.get_endpoints_policy_label("update")) updated_values = self._validate_update_body(body) - return endpoint_view.single(req, self._endpoint_api.update( + return endpoint_view.single(self._endpoint_api.update( req.environ['coriolis.context'], id, updated_values)) def delete(self, req, id): diff --git a/coriolis/api/v1/migrations.py b/coriolis/api/v1/migrations.py index 20e0c5af6..403b843e8 100644 --- a/coriolis/api/v1/migrations.py +++ b/coriolis/api/v1/migrations.py @@ -41,7 +41,7 @@ def show(self, req, id): if not migration: raise exc.HTTPNotFound() - return migration_view.single(req, migration) + return migration_view.single(migration) def _list(self, req): show_deleted = api_utils._get_show_deleted( @@ -50,7 +50,7 @@ def _list(self, req): context.show_deleted = show_deleted context.can(migration_policies.get_migrations_policy_label("list")) return migration_view.collection( - req, self._migration_api.get_migrations( + self._migration_api.get_migrations( context, include_tasks=CONF.api.include_task_info_in_migrations_api, include_task_info=CONF.api.include_task_info_in_migrations_api @@ -173,7 +173,7 @@ def create(self, req, body): skip_os_morphing=skip_os_morphing, user_scripts=user_scripts) - return migration_view.single(req, migration) + return migration_view.single(migration) def delete(self, req, id): context = req.environ['coriolis.context'] diff --git a/coriolis/api/v1/minion_pool_actions.py b/coriolis/api/v1/minion_pool_actions.py index e617e6089..75e45bb80 100644 --- a/coriolis/api/v1/minion_pool_actions.py +++ b/coriolis/api/v1/minion_pool_actions.py @@ -23,7 +23,7 @@ def _allocate_pool(self, req, id, body): "allocate")) try: return minion_pool_view.single( - req, self.minion_pool_api.allocate_minion_pool( + self.minion_pool_api.allocate_minion_pool( context, id)) except exception.NotFound as ex: raise exc.HTTPNotFound(explanation=ex.msg) @@ -38,7 +38,7 @@ def _refresh_pool(self, req, id, body): "refresh")) try: return minion_pool_view.single( - req, self.minion_pool_api.refresh_minion_pool( + self.minion_pool_api.refresh_minion_pool( context, id)) except exception.NotFound as ex: raise exc.HTTPNotFound(explanation=ex.msg) @@ -54,7 +54,7 @@ def _deallocate_pool(self, req, id, body): force = (body["deallocate"] or {}).get("force", False) try: return minion_pool_view.single( - req, self.minion_pool_api.deallocate_minion_pool( + self.minion_pool_api.deallocate_minion_pool( context, id, force=force)) except exception.NotFound as ex: raise exc.HTTPNotFound(explanation=ex.msg) diff --git a/coriolis/api/v1/minion_pools.py b/coriolis/api/v1/minion_pools.py index b40013678..8f10d096d 100644 --- a/coriolis/api/v1/minion_pools.py +++ b/coriolis/api/v1/minion_pools.py @@ -29,13 +29,13 @@ def show(self, req, id): if not minion_pool: raise exc.HTTPNotFound() - return minion_pool_view.single(req, minion_pool) + return minion_pool_view.single(minion_pool) def index(self, req): context = req.environ["coriolis.context"] context.can(pools_policies.get_minion_pools_policy_label("list")) return minion_pool_view.collection( - req, self._minion_pool_api.get_minion_pools(context)) + self._minion_pool_api.get_minion_pools(context)) def _check_pool_retention_strategy(self, pool_retention_strategy): if not pool_retention_strategy: @@ -137,7 +137,7 @@ def create(self, req, body): minimum_minions, maximum_minions, minion_max_idle_time, minion_retention_strategy, notes, skip_allocation) = ( self._validate_create_body(context, body)) - return minion_pool_view.single(req, self._minion_pool_api.create( + return minion_pool_view.single(self._minion_pool_api.create( context, name, endpoint_id, pool_platform, pool_os_type, environment_options, minimum_minions, maximum_minions, minion_max_idle_time, minion_retention_strategy, notes=notes, @@ -197,7 +197,7 @@ def update(self, req, id, body): context.can(pools_policies.get_minion_pools_policy_label("update")) updated_values = self._validate_update_body(id, context, body) return minion_pool_view.single( - req, self._minion_pool_api.update( + self._minion_pool_api.update( req.environ['coriolis.context'], id, updated_values)) def delete(self, req, id): diff --git a/coriolis/api/v1/regions.py b/coriolis/api/v1/regions.py index 1cb6f4166..4cadb4c67 100644 --- a/coriolis/api/v1/regions.py +++ b/coriolis/api/v1/regions.py @@ -26,13 +26,13 @@ def show(self, req, id): if not region: raise exc.HTTPNotFound() - return region_view.single(req, region) + return region_view.single(region) def index(self, req): context = req.environ["coriolis.context"] context.can(region_policies.get_regions_policy_label("list")) return region_view.collection( - req, self._region_api.get_regions(context)) + self._region_api.get_regions(context)) @api_utils.format_keyerror_message(resource='region', method='create') def _validate_create_body(self, body): @@ -46,7 +46,7 @@ def create(self, req, body): context = req.environ["coriolis.context"] context.can(region_policies.get_regions_policy_label("create")) (name, description, enabled) = self._validate_create_body(body) - return region_view.single(req, self._region_api.create( + return region_view.single(self._region_api.create( context, region_name=name, description=description, enabled=enabled)) @@ -60,7 +60,7 @@ def update(self, req, id, body): context = req.environ["coriolis.context"] context.can(region_policies.get_regions_policy_label("update")) updated_values = self._validate_update_body(body) - return region_view.single(req, self._region_api.update( + return region_view.single(self._region_api.update( req.environ['coriolis.context'], id, updated_values)) def delete(self, req, id): diff --git a/coriolis/api/v1/replica_actions.py b/coriolis/api/v1/replica_actions.py index be092af58..adb82a26f 100644 --- a/coriolis/api/v1/replica_actions.py +++ b/coriolis/api/v1/replica_actions.py @@ -22,7 +22,7 @@ def _delete_disks(self, req, id, body): replica_policies.get_replicas_policy_label("delete_disks")) try: return replica_tasks_execution_view.single( - req, self._replica_api.delete_disks(context, id)) + self._replica_api.delete_disks(context, id)) except exception.NotFound as ex: raise exc.HTTPNotFound(explanation=ex.msg) except exception.InvalidParameterValue as ex: diff --git a/coriolis/api/v1/replica_schedules.py b/coriolis/api/v1/replica_schedules.py index 70aa41b7a..32a3e1d02 100644 --- a/coriolis/api/v1/replica_schedules.py +++ b/coriolis/api/v1/replica_schedules.py @@ -31,7 +31,7 @@ def show(self, req, replica_id, id): if not schedule: raise exc.HTTPNotFound() - return replica_schedule_view.single(req, schedule) + return replica_schedule_view.single(schedule) def index(self, req, replica_id): context = req.environ["coriolis.context"] @@ -41,7 +41,7 @@ def index(self, req, replica_id): show_expired = strutils.bool_from_string( req.GET.get("show_expired", True), strict=True) return replica_schedule_view.collection( - req, self._schedule_api.get_schedules( + self._schedule_api.get_schedules( context, replica_id, expired=show_expired)) def _validate_schedule(self, schedule): @@ -112,7 +112,7 @@ def create(self, req, replica_id, body): except Exception as err: raise exception.InvalidInput(err) - return replica_schedule_view.single(req, self._schedule_api.create( + return replica_schedule_view.single(self._schedule_api.create( context, replica_id, schedule, enabled, exp_date, shutdown)) def update(self, req, replica_id, id, body): @@ -128,7 +128,7 @@ def update(self, req, replica_id, id, body): except Exception as err: raise exception.InvalidInput(err) - return replica_schedule_view.single(req, self._schedule_api.update( + return replica_schedule_view.single(self._schedule_api.update( context, replica_id, id, update_values)) def delete(self, req, replica_id, id): diff --git a/coriolis/api/v1/replica_tasks_executions.py b/coriolis/api/v1/replica_tasks_executions.py index ddb377702..b755e4866 100644 --- a/coriolis/api/v1/replica_tasks_executions.py +++ b/coriolis/api/v1/replica_tasks_executions.py @@ -24,7 +24,7 @@ def show(self, req, replica_id, id): if not execution: raise exc.HTTPNotFound() - return replica_tasks_execution_view.single(req, execution) + return replica_tasks_execution_view.single(execution) def index(self, req, replica_id): context = req.environ["coriolis.context"] @@ -32,7 +32,7 @@ def index(self, req, replica_id): executions_policies.get_replica_executions_policy_label("list")) return replica_tasks_execution_view.collection( - req, self._replica_tasks_execution_api.get_executions( + self._replica_tasks_execution_api.get_executions( context, replica_id, include_tasks=False)) def detail(self, req, replica_id): @@ -41,7 +41,7 @@ def detail(self, req, replica_id): executions_policies.get_replica_executions_policy_label("show")) return replica_tasks_execution_view.collection( - req, self._replica_tasks_execution_api.get_executions( + self._replica_tasks_execution_api.get_executions( context, replica_id, include_tasks=True)) def create(self, req, replica_id, body): @@ -55,7 +55,7 @@ def create(self, req, replica_id, body): shutdown_instances = execution_body.get("shutdown_instances", False) return replica_tasks_execution_view.single( - req, self._replica_tasks_execution_api.create( + self._replica_tasks_execution_api.create( context, replica_id, shutdown_instances)) def delete(self, req, replica_id, id): diff --git a/coriolis/api/v1/replicas.py b/coriolis/api/v1/replicas.py index 6d9a734b2..bf5c6570c 100644 --- a/coriolis/api/v1/replicas.py +++ b/coriolis/api/v1/replicas.py @@ -41,7 +41,7 @@ def show(self, req, id): if not replica: raise exc.HTTPNotFound() - return replica_view.single(req, replica) + return replica_view.single(replica) def _list(self, req): show_deleted = api_utils._get_show_deleted( @@ -51,7 +51,7 @@ def _list(self, req): context.can(replica_policies.get_replicas_policy_label("list")) include_task_info = CONF.api.include_task_info_in_replicas_api return replica_view.collection( - req, self._replica_api.get_replicas( + self._replica_api.get_replicas( context, include_tasks_executions=include_task_info, include_task_info=include_task_info)) @@ -135,7 +135,7 @@ def create(self, req, body): instance_osmorphing_minion_pool_mappings, user_scripts) = ( self._validate_create_body(context, body)) - return replica_view.single(req, self._replica_api.create( + return replica_view.single(self._replica_api.create( context, origin_endpoint_id, destination_endpoint_id, origin_minion_pool_id, destination_minion_pool_id, instance_osmorphing_minion_pool_mappings, source_environment, @@ -342,8 +342,8 @@ def update(self, req, id, body): updated_values = self._validate_update_body(id, context, body) try: return replica_tasks_execution_view.single( - req, self._replica_api.update(req.environ['coriolis.context'], - id, updated_values)) + self._replica_api.update(req.environ['coriolis.context'], + id, updated_values)) except exception.NotFound as ex: raise exc.HTTPNotFound(explanation=ex.msg) except exception.InvalidParameterValue as ex: diff --git a/coriolis/api/v1/services.py b/coriolis/api/v1/services.py index c8667dc0e..b2bd267b6 100644 --- a/coriolis/api/v1/services.py +++ b/coriolis/api/v1/services.py @@ -26,13 +26,13 @@ def show(self, req, id): if not service: raise exc.HTTPNotFound() - return service_view.single(req, service) + return service_view.single(service) def index(self, req): context = req.environ["coriolis.context"] context.can(service_policies.get_services_policy_label("list")) return service_view.collection( - req, self._service_api.get_services(context)) + self._service_api.get_services(context)) @api_utils.format_keyerror_message(resource='service', method='create') def _validate_create_body(self, body): @@ -49,7 +49,7 @@ def create(self, req, body): context.can(service_policies.get_services_policy_label("create")) (host, binary, topic, mapped_regions, enabled) = ( self._validate_create_body(body)) - return service_view.single(req, self._service_api.create( + return service_view.single(self._service_api.create( context, host=host, binary=binary, topic=topic, mapped_regions=mapped_regions, enabled=enabled)) @@ -63,7 +63,7 @@ def update(self, req, id, body): context = req.environ["coriolis.context"] context.can(service_policies.get_services_policy_label("update")) updated_values = self._validate_update_body(body) - return service_view.single(req, self._service_api.update( + return service_view.single(self._service_api.update( req.environ['coriolis.context'], id, updated_values)) def delete(self, req, id): diff --git a/coriolis/api/v1/views/diagnostic_view.py b/coriolis/api/v1/views/diagnostic_view.py index 871b7f64c..60f7c0240 100644 --- a/coriolis/api/v1/views/diagnostic_view.py +++ b/coriolis/api/v1/views/diagnostic_view.py @@ -2,9 +2,9 @@ # All Rights Reserved. -def single(req, diag): +def single(diag): return {"diagnostic": diag} -def collection(req, diag): +def collection(diag): return {'diagnostics': diag} diff --git a/coriolis/api/v1/views/endpoint_options_view.py b/coriolis/api/v1/views/endpoint_options_view.py index 4d23a878e..5fc76f78c 100644 --- a/coriolis/api/v1/views/endpoint_options_view.py +++ b/coriolis/api/v1/views/endpoint_options_view.py @@ -1,38 +1,28 @@ # Copyright 2020 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def _format_opt(req, option, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - return dict(itertools.chain.from_iterable( - transform(k, v) for k, v in option.items())) - - -def destination_minion_pool_options_collection(req, destination_pool_options): +def destination_minion_pool_options_collection(destination_pool_options): formatted_opts = [ - _format_opt(req, opt) for opt in destination_pool_options] + view_utils._format_opt(opt) for opt in destination_pool_options] return {'destination_minion_pool_options': formatted_opts} -def destination_options_collection(req, destination_options): +def destination_options_collection(destination_options): formatted_opts = [ - _format_opt(req, opt) for opt in destination_options] + view_utils._format_opt(opt) for opt in destination_options] return {'destination_options': formatted_opts} -def source_minion_pool_options_collection(req, source_pool_options): +def source_minion_pool_options_collection(source_pool_options): formatted_opts = [ - _format_opt(req, opt) for opt in source_pool_options] + view_utils._format_opt(opt) for opt in source_pool_options] return {'source_minion_pool_options': formatted_opts} -def source_options_collection(req, source_options): +def source_options_collection(source_options): formatted_opts = [ - _format_opt(req, opt) for opt in source_options] + view_utils._format_opt(opt) for opt in source_options] return {'source_options': formatted_opts} diff --git a/coriolis/api/v1/views/endpoint_resources_view.py b/coriolis/api/v1/views/endpoint_resources_view.py index 188fe6025..782b901d2 100644 --- a/coriolis/api/v1/views/endpoint_resources_view.py +++ b/coriolis/api/v1/views/endpoint_resources_view.py @@ -1,38 +1,29 @@ # Copyright 2020 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def _format_resource(req, resource, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) +def instance_single(instance): + return {"instance": view_utils._format_opt(instance)} - return dict(itertools.chain.from_iterable( - transform(k, v) for k, v in resource.items())) - -def instance_single(req, instance): - return {"instance": _format_resource(req, instance)} - - -def instances_collection(req, instances): - formatted_instances = [_format_resource(req, m) +def instances_collection(instances): + formatted_instances = [view_utils._format_opt(m) for m in instances] return {'instances': formatted_instances} -def network_single(req, network): - return {"network": _format_resource(req, network)} +def network_single(network): + return {"network": view_utils._format_opt(network)} -def networks_collection(req, networks): - formatted_networks = [_format_resource(req, m) for m in networks] +def networks_collection(networks): + formatted_networks = [view_utils._format_opt(m) + for m in networks] return {'networks': formatted_networks} -def storage_collection(req, storage): - formatted_storages = _format_resource(req, storage) +def storage_collection(storage): + formatted_storages = view_utils._format_opt(storage) return {'storage': formatted_storages} diff --git a/coriolis/api/v1/views/endpoint_view.py b/coriolis/api/v1/views/endpoint_view.py index bb4b3b49e..b211dad24 100644 --- a/coriolis/api/v1/views/endpoint_view.py +++ b/coriolis/api/v1/views/endpoint_view.py @@ -1,17 +1,11 @@ # Copyright 2016 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def _format_endpoint(req, endpoint, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - endpoint_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in endpoint.items())) +def _format_endpoint(endpoint, keys=None): + endpoint_dict = view_utils._format_opt(endpoint) mapped_regions = endpoint_dict.get('mapped_regions', []) endpoint_dict['mapped_regions'] = [ reg['id'] for reg in mapped_regions] @@ -19,11 +13,11 @@ def transform(key, value): return endpoint_dict -def single(req, endpoint): - return {"endpoint": _format_endpoint(req, endpoint)} +def single(endpoint): + return {"endpoint": _format_endpoint(endpoint)} -def collection(req, endpoints): - formatted_endpoints = [_format_endpoint(req, m) +def collection(endpoints): + formatted_endpoints = [_format_endpoint(m) for m in endpoints] return {'endpoints': formatted_endpoints} diff --git a/coriolis/api/v1/views/migration_view.py b/coriolis/api/v1/views/migration_view.py index 1b4abc33e..1e1cc485a 100644 --- a/coriolis/api/v1/views/migration_view.py +++ b/coriolis/api/v1/views/migration_view.py @@ -1,23 +1,16 @@ # Copyright 2016 Cloudbase Solutions Srl # All Rights Reserved. -import itertools - from coriolis.api.v1.views import replica_tasks_execution_view as view +from coriolis.api.v1.views import utils as view_utils -def _format_migration(req, migration, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - migration_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in migration.items())) +def _format_migration(migration, keys=None): + migration_dict = view_utils._format_opt(migration) if len(migration_dict.get("executions", [])): execution = view.format_replica_tasks_execution( - req, migration_dict["executions"][0]) + migration_dict["executions"][0]) del migration_dict["executions"] else: execution = {} @@ -29,11 +22,11 @@ def transform(key, value): return migration_dict -def single(req, migration): - return {"migration": _format_migration(req, migration)} +def single(migration): + return {"migration": _format_migration(migration)} -def collection(req, migrations): - formatted_migrations = [_format_migration(req, m) +def collection(migrations): + formatted_migrations = [_format_migration(m) for m in migrations] return {'migrations': formatted_migrations} diff --git a/coriolis/api/v1/views/minion_pool_view.py b/coriolis/api/v1/views/minion_pool_view.py index e76051682..38e66acc8 100644 --- a/coriolis/api/v1/views/minion_pool_view.py +++ b/coriolis/api/v1/views/minion_pool_view.py @@ -1,17 +1,11 @@ # Copyright 2020 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def _format_minion_pool(req, minion_pool, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - minion_pool_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in minion_pool.items())) +def _format_minion_pool(minion_pool, keys=None): + minion_pool_dict = view_utils._format_opt(minion_pool) def _hide_minion_creds(minion_conn): if not minion_conn: @@ -38,11 +32,11 @@ def _hide_minion_creds(minion_conn): return minion_pool_dict -def single(req, minion_pool): - return {"minion_pool": _format_minion_pool(req, minion_pool)} +def single(minion_pool): + return {"minion_pool": _format_minion_pool(minion_pool)} -def collection(req, minion_pools): +def collection(minion_pools): formatted_minion_pools = [ - _format_minion_pool(req, r) for r in minion_pools] + _format_minion_pool(r) for r in minion_pools] return {'minion_pools': formatted_minion_pools} diff --git a/coriolis/api/v1/views/region_view.py b/coriolis/api/v1/views/region_view.py index 3914759e9..ce8d505b1 100644 --- a/coriolis/api/v1/views/region_view.py +++ b/coriolis/api/v1/views/region_view.py @@ -1,17 +1,11 @@ # Copyright 2020 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def _format_region(req, region, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - region_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in region.items())) +def _format_region(region, keys=None): + region_dict = view_utils._format_opt(region) mapped_endpoints = region_dict.get('mapped_endpoints', []) region_dict['mapped_endpoints'] = [ @@ -24,11 +18,11 @@ def transform(key, value): return region_dict -def single(req, region): - return {"region": _format_region(req, region)} +def single(region): + return {"region": _format_region(region)} -def collection(req, regions): +def collection(regions): formatted_regions = [ - _format_region(req, r) for r in regions] + _format_region(r) for r in regions] return {'regions': formatted_regions} diff --git a/coriolis/api/v1/views/replica_schedule_view.py b/coriolis/api/v1/views/replica_schedule_view.py index a4e51f64c..1a29c7bc7 100644 --- a/coriolis/api/v1/views/replica_schedule_view.py +++ b/coriolis/api/v1/views/replica_schedule_view.py @@ -1,24 +1,14 @@ # Copyright 2017 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def format_schedule(req, schedule, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) +def single(schedule): + return {"schedule": view_utils._format_opt(schedule)} - return dict(itertools.chain.from_iterable( - transform(k, v) for k, v in schedule.items())) - -def single(req, schedule): - return {"schedule": format_schedule(req, schedule)} - - -def collection(req, schedules): - formatted_schedules = [format_schedule(req, m) +def collection(schedules): + formatted_schedules = [view_utils._format_opt(m) for m in schedules] return {'schedules': formatted_schedules} diff --git a/coriolis/api/v1/views/replica_tasks_execution_view.py b/coriolis/api/v1/views/replica_tasks_execution_view.py index 933b0bb79..543fd25d9 100644 --- a/coriolis/api/v1/views/replica_tasks_execution_view.py +++ b/coriolis/api/v1/views/replica_tasks_execution_view.py @@ -1,7 +1,7 @@ # Copyright 2016 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils from oslo_log import log as logging @@ -12,7 +12,8 @@ def _sort_tasks(tasks, filter_error_only_tasks=True): - """ Sorts the given list of dicts representing tasks. + """Sorts the given list of dicts representing tasks. + Tasks are sorted primarily based on their index. """ if filter_error_only_tasks: @@ -24,26 +25,20 @@ def _sort_tasks(tasks, filter_error_only_tasks=True): tasks, key=lambda t: t.get('index', 0)) -def format_replica_tasks_execution(req, execution, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - +def format_replica_tasks_execution(execution, keys=None): if "tasks" in execution: execution["tasks"] = _sort_tasks(execution["tasks"]) - execution_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in execution.items())) + execution_dict = view_utils._format_opt(execution) return execution_dict -def single(req, execution): - return {"execution": format_replica_tasks_execution(req, execution)} +def single(execution): + return {"execution": format_replica_tasks_execution(execution)} -def collection(req, executions): - formatted_executions = [format_replica_tasks_execution(req, m) +def collection(executions): + formatted_executions = [format_replica_tasks_execution(m) for m in executions] return {'executions': formatted_executions} diff --git a/coriolis/api/v1/views/replica_view.py b/coriolis/api/v1/views/replica_view.py index b3bedeb27..24e7edee2 100644 --- a/coriolis/api/v1/views/replica_view.py +++ b/coriolis/api/v1/views/replica_view.py @@ -1,33 +1,26 @@ # Copyright 2016 Cloudbase Solutions Srl # All Rights Reserved. -import itertools - from coriolis.api.v1.views import replica_tasks_execution_view as view +from coriolis.api.v1.views import utils as view_utils -def _format_replica(req, replica, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - replica_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in replica.items())) +def _format_replica(replica, keys=None): + replica_dict = view_utils._format_opt(replica) executions = replica_dict.get('executions', []) replica_dict['executions'] = [ - view.format_replica_tasks_execution(req, ex) + view.format_replica_tasks_execution(ex) for ex in executions] return replica_dict -def single(req, replica): - return {"replica": _format_replica(req, replica)} +def single(replica): + return {"replica": _format_replica(replica)} -def collection(req, replicas): - formatted_replicas = [_format_replica(req, m) +def collection(replicas): + formatted_replicas = [_format_replica(m) for m in replicas] return {'replicas': formatted_replicas} diff --git a/coriolis/api/v1/views/service_view.py b/coriolis/api/v1/views/service_view.py index b1946b757..2a0728f2d 100644 --- a/coriolis/api/v1/views/service_view.py +++ b/coriolis/api/v1/views/service_view.py @@ -1,17 +1,11 @@ # Copyright 2020 Cloudbase Solutions Srl # All Rights Reserved. -import itertools +from coriolis.api.v1.views import utils as view_utils -def _format_service(req, service, keys=None): - def transform(key, value): - if keys and key not in keys: - return - yield (key, value) - - service_dict = dict(itertools.chain.from_iterable( - transform(k, v) for k, v in service.items())) +def _format_service(service, keys=None): + service_dict = view_utils._format_opt(service) mapped_regions = service_dict.get('mapped_regions', []) service_dict['mapped_regions'] = [ @@ -20,11 +14,11 @@ def transform(key, value): return service_dict -def single(req, service): - return {"service": _format_service(req, service)} +def single(service): + return {"service": _format_service(service)} -def collection(req, services): +def collection(services): formatted_services = [ - _format_service(req, r) for r in services] + _format_service(r) for r in services] return {'services': formatted_services} diff --git a/coriolis/api/v1/views/utils.py b/coriolis/api/v1/views/utils.py new file mode 100644 index 000000000..ba0ac752b --- /dev/null +++ b/coriolis/api/v1/views/utils.py @@ -0,0 +1,14 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +import itertools + + +def _format_opt(option, keys=None): + def transform(key, value): + if keys and key not in keys: + return + yield (key, value) + + return dict(itertools.chain.from_iterable( + transform(k, v) for k, v in option.items())) diff --git a/coriolis/tests/api/__init__.py b/coriolis/tests/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/coriolis/tests/api/v1/__init__.py b/coriolis/tests/api/v1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/coriolis/tests/api/v1/views/__init__.py b/coriolis/tests/api/v1/views/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/coriolis/tests/api/v1/views/test_diagnostic_view.py b/coriolis/tests/api/v1/views/test_diagnostic_view.py new file mode 100644 index 000000000..67bc11de6 --- /dev/null +++ b/coriolis/tests/api/v1/views/test_diagnostic_view.py @@ -0,0 +1,53 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from coriolis.api.v1.views import diagnostic_view +from coriolis.tests import test_base + + +class DiagnosticViewTestCase(test_base.CoriolisBaseTestCase): + "Test suite for the Coriolis api v1 views.""" + + def test_single(self): + mock_single = "mock_single" + expected_result = {'diagnostic': mock_single} + + result = diagnostic_view.single(mock_single) + + self.assertEqual( + expected_result, + result + ) + + def test_single_none(self): + mock_single = None + expected_result = {'diagnostic': mock_single} + + result = diagnostic_view.single(mock_single) + + self.assertEqual( + expected_result, + result + ) + + def test_collection(self): + mock_collection = {"mock_key_1": "value_1", "mock_key_2": "value_2"} + expected_result = {'diagnostics': mock_collection} + + result = diagnostic_view.collection(mock_collection) + + self.assertEqual( + expected_result, + result + ) + + def test_collection_none(self): + mock_collection = {} + expected_result = {'diagnostics': mock_collection} + + result = diagnostic_view.collection(mock_collection) + + self.assertEqual( + expected_result, + result + ) diff --git a/coriolis/tests/api/v1/views/test_endpoint_options_view.py b/coriolis/tests/api/v1/views/test_endpoint_options_view.py new file mode 100644 index 000000000..8258106ec --- /dev/null +++ b/coriolis/tests/api/v1/views/test_endpoint_options_view.py @@ -0,0 +1,12 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from coriolis.api.v1.views import endpoint_options_view +from coriolis.tests import test_base + + +class EndpointOptionsViewTestCase(test_base.CoriolisApiViewsTestCase): + + def test_source_options_collection(self): + fun = getattr(endpoint_options_view, 'source_options_collection') + self._collection_view_test(fun, "source_options") diff --git a/coriolis/tests/api/v1/views/test_endpoint_view.py b/coriolis/tests/api/v1/views/test_endpoint_view.py new file mode 100644 index 000000000..7cac9c4cb --- /dev/null +++ b/coriolis/tests/api/v1/views/test_endpoint_view.py @@ -0,0 +1,60 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from unittest import mock + +from coriolis.api.v1.views import endpoint_view +from coriolis.api.v1.views import utils as view_utils +from coriolis.tests import test_base + + +class EndpointViewTestCase(test_base.CoriolisApiViewsTestCase): + """Test suite for the Coriolis api v1 views.""" + + def setUp(self): + super(EndpointViewTestCase, self).setUp() + self._format_fun = endpoint_view._format_endpoint + + @mock.patch.object(view_utils, '_format_opt') + def test_format_endpoint(self, mock__format_opt): + mock__format_opt.return_value = { + "mapped_regions": [{'id': 'mock_id1'}, {'id': 'mock_id2'}], + "mock_key": "mock_value" + } + + expected_result = { + 'mapped_regions': ['mock_id1', 'mock_id2'], + 'mock_key': 'mock_value' + } + + result = endpoint_view._format_endpoint("") + + self.assertEqual( + expected_result, + result + ) + + @mock.patch.object(view_utils, '_format_opt') + def test_format_endpoint_no_keys(self, mock__format_opt): + mock__format_opt.return_value = { + "mapped_regions": [{'id': 'mock_id1'}, {'id': 'mock_id2'}], + } + + expected_result = { + 'mapped_regions': ['mock_id1', 'mock_id2'], + } + + result = endpoint_view._format_endpoint("") + + self.assertEqual( + expected_result, + result + ) + + def test_single(self): + fun = getattr(endpoint_view, 'single') + self._single_view_test(fun, 'endpoint') + + def test_collection(self): + fun = getattr(endpoint_view, 'collection') + self._collection_view_test(fun, 'endpoints') diff --git a/coriolis/tests/api/v1/views/test_migration_view.py b/coriolis/tests/api/v1/views/test_migration_view.py new file mode 100644 index 000000000..1066b1c6a --- /dev/null +++ b/coriolis/tests/api/v1/views/test_migration_view.py @@ -0,0 +1,74 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from unittest import mock + +from coriolis.api.v1.views import migration_view +from coriolis.api.v1.views import replica_tasks_execution_view as view +from coriolis.api.v1.views import utils as view_utils +from coriolis.tests import test_base + + +class MigrationViewTestCase(test_base.CoriolisBaseTestCase): + """Test suite for the Coriolis api v1 views.""" + + @mock.patch.object(view, 'format_replica_tasks_execution') + @mock.patch.object(view_utils, '_format_opt') + def test_format_migration( + self, + mock__format_opt, + mock_format_replica_tasks_execution + ): + mock__format_opt.return_value = { + "executions": [{'tasks': 'mock_id1'}], + 'tasks': 'mock_id2', + 'mock_key': 'mock_value' + } + mock_format_replica_tasks_execution.return_value = { + 'tasks': 'mock_id1' + } + + expected_result = { + 'tasks': 'mock_id1', + 'mock_key': 'mock_value' + } + + result = migration_view._format_migration("") + + self.assertEqual( + expected_result, + result + ) + + @mock.patch.object(view_utils, '_format_opt') + def test_format_migration_no_tasks( + self, + mock__format_opt, + ): + mock__format_opt.return_value = { + 'mock_key': 'mock_value' + } + + result = migration_view._format_migration("") + + self.assertEqual( + mock__format_opt.return_value, + result + ) + + @mock.patch.object(view_utils, '_format_opt') + def test_format_migration_migration_dict_has_tasks( + self, + mock__format_opt, + ): + mock__format_opt.return_value = { + 'tasks': 'mock_id1', + 'mock_key': 'mock_value' + } + + result = migration_view._format_migration("") + + self.assertEqual( + mock__format_opt.return_value, + result + ) diff --git a/coriolis/tests/api/v1/views/test_minion_pool_view.py b/coriolis/tests/api/v1/views/test_minion_pool_view.py new file mode 100644 index 000000000..4d43e4984 --- /dev/null +++ b/coriolis/tests/api/v1/views/test_minion_pool_view.py @@ -0,0 +1,57 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from unittest import mock + +from coriolis.api.v1.views import minion_pool_view as view +from coriolis.api.v1.views import utils as view_utils +from coriolis.tests import test_base + + +class MinionPoolViewTestCase(test_base.CoriolisBaseTestCase): + """Test suite for the Coriolis api v1 views.""" + + @mock.patch.object(view_utils, '_format_opt') + def test_format_minion_pool( + self, + mock__format_opt, + ): + mock_minion_pool_dict = { + 'minion_machines': [{ + 'connection_info': { + 'pkey': 'mock_key', + 'password': 'mock_key', + 'certificates': {'key': 'mock_key'} + }, + 'backup_writer_connection_info': { + 'connection_details': { + 'pkey': 'mock_key', + 'password': 'mock_key', + 'certificates': {'key': 'mock_key'} + }, + } + }], + } + expected_result = { + 'minion_machines': [{ + 'connection_info': { + 'pkey': '***', + 'password': '***', + 'certificates': {'key': '***'} + }, + 'backup_writer_connection_info': { + 'connection_details': { + 'pkey': '***', + 'password': '***', + 'certificates': {'key': '***'} + }, + } + }], + } + mock__format_opt.return_value = mock_minion_pool_dict + + result = view._format_minion_pool("") + self.assertEqual( + expected_result, + result + ) diff --git a/coriolis/tests/api/v1/views/test_replica_task_execution_view.py b/coriolis/tests/api/v1/views/test_replica_task_execution_view.py new file mode 100644 index 000000000..cb95037a1 --- /dev/null +++ b/coriolis/tests/api/v1/views/test_replica_task_execution_view.py @@ -0,0 +1,101 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from unittest import mock + +from coriolis.api.v1.views import replica_tasks_execution_view as view +from coriolis.api.v1.views import utils as view_utils +from coriolis import constants +from coriolis.tests import test_base + + +class ReplicaTaskExecutionViewTestCase(test_base.CoriolisBaseTestCase): + """Test suite for the Coriolis api v1 views.""" + + @mock.patch.object(view, '_sort_tasks') + @mock.patch.object(view_utils, '_format_opt') + def test_format_replica_tasks_execution( + self, + mock__format_opt, + mock_sort_tasks + ): + mock_tasks = ['mock_task1', 'mock_task2'] + mock_execution = { + 'tasks': mock_tasks, + 'mock_key': 'mock_value' + } + mock_sort_tasks.return_value = mock_execution + + result = view.format_replica_tasks_execution(mock_execution) + + mock_sort_tasks.assert_called_once_with(mock_tasks) + self.assertEqual( + mock__format_opt.return_value, + result + ) + + @mock.patch.object(view, '_sort_tasks') + @mock.patch.object(view_utils, '_format_opt') + def test_format_replica_tasks_execution_no_tasks( + self, + mock__format_opt, + mock_sort_tasks + ): + mock_execution = { + 'mock_key': 'mock_value' + } + + result = view.format_replica_tasks_execution(mock_execution) + + mock_sort_tasks.assert_not_called() + self.assertEqual( + mock__format_opt.return_value, + result + ) + + def test_sort_tasks(self): + mock_tasks = [ + {'index': 2, 'status': 'mock_status1'}, + {'index': 3, 'status': constants.TASK_STATUS_ON_ERROR_ONLY}, + {'index': 1, 'status': 'mock_status2'}, + ] + expected_result = [ + {'index': 1, 'status': 'mock_status2'}, + {'index': 2, 'status': 'mock_status1'}, + ] + + result = view._sort_tasks(mock_tasks) + + self.assertEqual( + expected_result, + result + ) + + def test_sort_tasks_no_filter(self): + mock_tasks = [ + {'index': 2, 'status': 'mock_status1'}, + {'index': 3, 'status': constants.TASK_STATUS_ON_ERROR_ONLY}, + {'index': 1, 'status': 'mock_status2'}, + ] + expected_result = [ + {'index': 1, 'status': 'mock_status2'}, + {'index': 2, 'status': 'mock_status1'}, + {'index': 3, 'status': constants.TASK_STATUS_ON_ERROR_ONLY}, + ] + + result = view._sort_tasks(mock_tasks, False) + + self.assertEqual( + expected_result, + result + ) + + def test_sort_tasks_no_tasks(self): + expected_result = [] + + result = view._sort_tasks(expected_result) + + self.assertEqual( + expected_result, + result + ) diff --git a/coriolis/tests/api/v1/views/test_utils.py b/coriolis/tests/api/v1/views/test_utils.py new file mode 100644 index 000000000..be1b8a5bb --- /dev/null +++ b/coriolis/tests/api/v1/views/test_utils.py @@ -0,0 +1,48 @@ +# Copyright 2022 Cloudbase Solutions Srl +# All Rights Reserved. + +from coriolis.api.v1.views import utils as view_utils +from coriolis.tests import test_base + + +class ViewUtilsTestCase(test_base.CoriolisBaseTestCase): + """Test suite for the Coriolis api v1 views.""" + + def test_format_opt(self): + mock_option = {"mock_key_1": "value_1", "mock_key_2": "value_2"} + mock_keys = {"mock_key_1"} + + expected_result = {"mock_key_1": "value_1"} + + result = view_utils._format_opt(mock_option, mock_keys) + + self.assertEqual( + expected_result, + result + ) + + def test_format_opt_key_not_in_options(self): + mock_option = {"mock_key_1": "value_1", "mock_key_2": "value_2"} + mock_keys = {"mock_key_3"} + + expected_result = {} + + result = view_utils._format_opt(mock_option, mock_keys) + + self.assertEqual( + expected_result, + result + ) + + def test_format_opt_keys_none(self): + mock_option = {"mock_key_1": "value_1", "mock_key_2": "value_2"} + mock_keys = None + + expected_result = mock_option + + result = view_utils._format_opt(mock_option, mock_keys) + + self.assertEqual( + expected_result, + result + ) diff --git a/coriolis/tests/test_base.py b/coriolis/tests/test_base.py index 93fc25e1d..4c6c2a0d3 100644 --- a/coriolis/tests/test_base.py +++ b/coriolis/tests/test_base.py @@ -3,10 +3,46 @@ """Defines base class for all tests.""" +from unittest import mock + from oslotest import base +from coriolis.api.v1.views import utils as views_utils + class CoriolisBaseTestCase(base.BaseTestCase): def setUp(self): super(CoriolisBaseTestCase, self).setUp() + + +class CoriolisApiViewsTestCase(CoriolisBaseTestCase): + + def setUp(self): + super(CoriolisApiViewsTestCase, self).setUp() + self._single_response = {"key1": "value1", "key2": "value2"} + self._collection_response = [ + self._single_response, self._single_response] + self._format_fun = views_utils._format_opt + + def _single_view_test(self, fun, expected_result_key): + format_fun = '%s.%s' % ( + self._format_fun.__module__, self._format_fun.__name__) + with mock.patch(format_fun) as format_mock: + result = fun(self._single_response) + format_mock.assert_called_once_with(self._single_response) + expected_result = {expected_result_key: format_mock.return_value} + self.assertEqual(expected_result, result) + + def _collection_view_test( + self, fun, expected_result_key): + format_fun = '%s.%s' % ( + self._format_fun.__module__, self._format_fun.__name__) + with mock.patch(format_fun) as format_mock: + f_opts = [] + result = fun(self._collection_response) + for c in self._collection_response: + format_mock.assert_has_calls([mock.call(c)]) + f_opts.append(format_mock.return_value) + expected_result = {expected_result_key: f_opts} + self.assertEqual(expected_result, result)