1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""Searchlight v1 Search action implementations"""
import logging
from oslo_serialization import jsonutils
from osc_lib.command import command
from osc_lib import utils
class SearchResource(command.Lister):
"""Search Searchlight resource."""
log = logging.getLogger(__name__ + ".SearchResource")
def get_parser(self, prog_name):
parser = super(SearchResource, self).get_parser(prog_name)
parser.add_argument(
"query",
metavar="<query>",
help="Query resources by Elasticsearch query string or json "
"format DSL. Query string example: 'name: cirros AND "
"updated_at: [now-1y TO now]'. DSL example: "
"'{\"term\": {\"name\": \"cirros\"}}'. "
"See Elasticsearch DSL or Searchlight documentation for "
"more detail."
)
parser.add_argument(
"--json",
action='store_true',
default=False,
help="Treat the query argument as a JSON formatted DSL query."
)
parser.add_argument(
"--type",
nargs='*',
metavar="<resource-type>",
help="One or more types to search. Uniquely identifies resource "
"types. Example: --type OS::Glance::Image "
"OS::Nova::Server"
)
parser.add_argument(
"--all-projects",
action='store_true',
default=False,
help="By default searches are restricted to the current project "
"unless all_projects is set"
)
parser.add_argument(
"--source",
nargs='?',
const='all_sources',
metavar="[<field>,...]",
help="Whether to display the json source. If not specified, "
"it will not be displayed. If specified with no argument, "
"the full source will be displayed. Otherwise, specify the "
"fields combined with ',' to return the fields you want. "
"It is recommended that you use the --max-width argument "
"with this option."
)
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args)
search_client = self.app.client_manager.search
mapping = {"_score": "score", "_type": "type", "_id": "id",
"_index": "index", "_source": "source"}
params = {
"type": parsed_args.type,
"all_projects": parsed_args.all_projects
}
source = parsed_args.source
if source:
columns = ("ID", "Score", "Type", "Source")
if source != "all_sources":
params["_source"] = (["id"] +
[s for s in source.split(",") if s != 'id'])
else:
columns = ("ID", "Name", "Score", "Type", "Updated")
# Only return the required fields when source not specified.
params["_source"] = ["id", "name", "updated_at"]
if parsed_args.query:
if parsed_args.json:
query = jsonutils.loads(parsed_args.query)
else:
try:
jsonutils.loads(parsed_args.query)
print("You should use the --json flag when specifying "
"a JSON object.")
exit(1)
except Exception:
qs = self._modify_query_string(parsed_args.query)
query = {"query_string": {"query": qs}}
params['query'] = query
data = search_client.search.search(**params)
result = []
for r in data.hits['hits']:
converted = {}
extra = {}
# hit._id may include extra information appended after _,
# so use r['_source']['id'] for safe.
r['_id'] = r.get('_source', {}).get('id')
for k, v in r.items():
map_key = mapping.get(k)
if map_key is not None:
converted[map_key] = v
if k == "_source" and not parsed_args.source:
converted["name"] = v.get("name")
converted["updated"] = v.get("updated_at")
else:
extra[k] = v
if extra:
self.log.debug("extra info returned: %s", extra)
result.append(utils.get_dict_properties(converted, columns))
return (columns, result)
def _modify_query_string(self, query_string):
return query_string.replace(r'/', r'\/')
|