From 6c4d254b4af14a4884efae9220619392c465dddb Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Thu, 23 Nov 2017 20:21:10 +0000 Subject: [PATCH] Refactor swap_filter in instance views Previously we check if a fake_field is contained in search_opts before calling swap_filter, but we can move it into the inside of swap_filter. This commit is split from https://review.openstack.org/#/c/507388/ to avoid doing a fix and refactoring in a single commit. Co-Authored-By: Huan Xiong Change-Id: I3069c6c9e66f32f53a64124f1d9d191d6aa703a3 --- .../dashboards/admin/instances/views.py | 25 +++------ .../dashboards/project/instances/views.py | 54 +++++++++++++------ 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/openstack_dashboard/dashboards/admin/instances/views.py b/openstack_dashboard/dashboards/admin/instances/views.py index 2d3e53c08b..53ae88a05f 100644 --- a/openstack_dashboard/dashboards/admin/instances/views.py +++ b/openstack_dashboard/dashboards/admin/instances/views.py @@ -66,11 +66,6 @@ def mks(args, **kvargs): return views.mks(args, **kvargs) -# re-use get_resource_id_by_name from project.instances.views -def swap_filter(resources, filters, fake_field, real_field): - return views.swap_filter(resources, filters, fake_field, real_field) - - class AdminUpdateView(views.UpdateView): workflow_class = update_instance.AdminUpdateInstance success_url = reverse_lazy("horizon:admin:instances:index") @@ -172,18 +167,14 @@ class AdminIndexView(tables.DataTableView): e.submit(fn=_task_get_images) e.submit(fn=_task_get_flavors) - if 'project' in search_opts and \ - not swap_filter(tenants, search_opts, 'project', 'tenant_id'): - self._more = False - return instances - elif 'image_name' in search_opts and \ - not swap_filter(images, search_opts, 'image_name', 'image'): - self._more = False - return instances - elif "flavor_name" in search_opts and \ - not swap_filter(flavors, search_opts, 'flavor_name', 'flavor'): - self._more = False - return instances + non_api_filter_info = ( + ('project', 'tenant_id', tenants), + ('image_name', 'image', images), + ('flavor_name', 'flavor', flavors), + ) + if not views.process_non_api_filters(search_opts, non_api_filter_info): + self._more = False + return [] _task_get_instances() diff --git a/openstack_dashboard/dashboards/project/instances/views.py b/openstack_dashboard/dashboards/project/instances/views.py index 39a7b401aa..45b3a6cd6e 100644 --- a/openstack_dashboard/dashboards/project/instances/views.py +++ b/openstack_dashboard/dashboards/project/instances/views.py @@ -123,14 +123,13 @@ class IndexView(tables.DataTableView): e.submit(fn=_task_get_flavors) e.submit(fn=_task_get_images) - if 'image_name' in search_opts and \ - not swap_filter(images, search_opts, 'image_name', 'image'): + non_api_filter_info = ( + ('image_name', 'image', images), + ('flavor_name', 'flavor', flavors), + ) + if not process_non_api_filters(search_opts, non_api_filter_info): self._more = False - return instances - elif 'flavor_name' in search_opts and \ - not swap_filter(flavors, search_opts, 'flavor_name', 'flavor'): - self._more = False - return instances + return [] _task_get_instances() @@ -160,14 +159,39 @@ class IndexView(tables.DataTableView): return instances -def swap_filter(resources, filters, fake_field, real_field): - if fake_field in filters: - filter_string = filters[fake_field] - for resource in resources: - if resource.name.lower() == filter_string.lower(): - filters[real_field] = resource.id - del filters[fake_field] - return True +def process_non_api_filters(search_opts, non_api_filter_info): + """Process filters by non-API fields + + There are cases where it is useful to provide a filter field + which does not exist in a resource in a backend service. + For example, nova server list provides 'image' field with image ID + but 'image name' is more useful for GUI users. + This function replaces fake fields into corresponding real fields. + + The format of non_api_filter_info is a tuple/list of + (fake_field, real_field, resources). + + This returns True if further lookup is required. + It returns False if there are no matching resources, + for example, if no corresponding real field exists. + """ + for fake_field, real_field, resources in non_api_filter_info: + if not _swap_filter(resources, search_opts, fake_field, real_field): + return False + return True + + +def _swap_filter(resources, search_opts, fake_field, real_field): + if fake_field not in search_opts: + return True + filter_string = search_opts[fake_field] + matched = [resource for resource in resources + if resource.name.lower() == filter_string.lower()] + if not matched: + return False + search_opts[real_field] = matched[0].id + del search_opts[fake_field] + return True class LaunchInstanceView(workflows.WorkflowView):