Revision 6d190dd1
b/kamaki/cli/commands/__init__.py | ||
---|---|---|
32 | 32 |
# or implied, of GRNET S.A.command |
33 | 33 |
|
34 | 34 |
from kamaki.cli.logger import get_logger |
35 |
from kamaki.cli.utils import print_json, print_items |
|
36 |
from kamaki.cli.argument import FlagArgument |
|
35 |
from kamaki.cli.utils import print_json, print_items, filter_dicts_by_dict
|
|
36 |
from kamaki.cli.argument import FlagArgument, ValueArgument
|
|
37 | 37 |
|
38 | 38 |
log = get_logger(__name__) |
39 | 39 |
|
... | ... | |
66 | 66 |
arguments.update(self.oo_arguments) |
67 | 67 |
if isinstance(self, _optional_json): |
68 | 68 |
arguments.update(self.oj_arguments) |
69 |
if isinstance(self, _name_filter): |
|
70 |
arguments.update(self.nf_arguments) |
|
71 |
if isinstance(self, _id_filter): |
|
72 |
arguments.update(self.if_arguments) |
|
69 | 73 |
try: |
70 | 74 |
arguments.update(self.wait_arguments) |
71 | 75 |
except AttributeError: |
... | ... | |
209 | 213 |
print_json(output) |
210 | 214 |
else: |
211 | 215 |
print_method(output, **print_method_kwargs) |
216 |
|
|
217 |
|
|
218 |
class _name_filter(object): |
|
219 |
|
|
220 |
nf_arguments = dict( |
|
221 |
name=ValueArgument('filter by name', '--name'), |
|
222 |
name_pref=ValueArgument( |
|
223 |
'filter by name prefix (case insensitive)', '--name-prefix'), |
|
224 |
name_suff=ValueArgument( |
|
225 |
'filter by name suffix (case insensitive)', '--name-suffix'), |
|
226 |
name_like=ValueArgument( |
|
227 |
'print only if name contains this (case insensitive)', |
|
228 |
'--name-like') |
|
229 |
) |
|
230 |
|
|
231 |
def _non_exact_name_filter(self, items): |
|
232 |
np, ns, nl = self['name_pref'], self['name_suff'], self['name_like'] |
|
233 |
return [item for item in items if ( |
|
234 |
(not np) or item['name'].lower().startswith(np.lower())) and ( |
|
235 |
(not ns) or item['name'].lower().endswith(ns.lower())) and ( |
|
236 |
(not nl) or nl.lower() in item['name'].lower())] |
|
237 |
|
|
238 |
def _exact_name_filter(self, items): |
|
239 |
return filter_dicts_by_dict(items, dict(name=self['name'])) if ( |
|
240 |
self['name']) else items |
|
241 |
|
|
242 |
def _filter_by_name(self, items): |
|
243 |
return self._non_exact_name_filter(self._exact_name_filter(items)) |
|
244 |
|
|
245 |
|
|
246 |
class _id_filter(object): |
|
247 |
|
|
248 |
if_arguments = dict( |
|
249 |
id=ValueArgument('filter by id', '--id'), |
|
250 |
id_pref=ValueArgument( |
|
251 |
'filter by id prefix (case insensitive)', '--id-prefix'), |
|
252 |
id_suff=ValueArgument( |
|
253 |
'filter by id suffix (case insensitive)', '--id-suffix'), |
|
254 |
id_like=ValueArgument( |
|
255 |
'print only if id contains this (case insensitive)', |
|
256 |
'--id-like') |
|
257 |
) |
|
258 |
|
|
259 |
def _non_exact_id_filter(self, items): |
|
260 |
np, ns, nl = self['id_pref'], self['id_suff'], self['id_like'] |
|
261 |
return [item for item in items if ( |
|
262 |
(not np) or ( |
|
263 |
'%s' % item['id']).lower().startswith(np.lower())) and ( |
|
264 |
(not ns) or ('%s' % item['id']).lower().endswith(ns.lower())) and ( |
|
265 |
(not nl) or nl.lower() in ('%s' % item['id']).lower())] |
|
266 |
|
|
267 |
def _exact_id_filter(self, items): |
|
268 |
return filter_dicts_by_dict(items, dict(id=self['id'])) if ( |
|
269 |
self['id']) else items |
|
270 |
|
|
271 |
def _filter_by_id(self, items): |
|
272 |
return self._non_exact_id_filter(self._exact_id_filter(items)) |
b/kamaki/cli/commands/cyclades.py | ||
---|---|---|
40 | 40 |
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument |
41 | 41 |
from kamaki.cli.argument import ProgressBarArgument, DateArgument, IntArgument |
42 | 42 |
from kamaki.cli.commands import _command_init, errors, addLogSettings |
43 |
from kamaki.cli.commands import _optional_output_cmd, _optional_json |
|
43 |
from kamaki.cli.commands import ( |
|
44 |
_optional_output_cmd, _optional_json, _name_filter, _id_filter) |
|
44 | 45 |
|
45 | 46 |
from base64 import b64encode |
46 | 47 |
from os.path import exists |
... | ... | |
155 | 156 |
|
156 | 157 |
|
157 | 158 |
@command(server_cmds) |
158 |
class server_list(_init_cyclades, _optional_json): |
|
159 |
class server_list(_init_cyclades, _optional_json, _name_filter, _id_filter):
|
|
159 | 160 |
"""List Virtual Machines accessible by user""" |
160 | 161 |
|
161 | 162 |
PERMANENTS = ('id', 'name') |
... | ... | |
172 | 173 |
'output results in pages (-n to set items per page, default 10)', |
173 | 174 |
'--more'), |
174 | 175 |
enum=FlagArgument('Enumerate results', '--enumerate'), |
175 |
name=ValueArgument('filter by name', '--name'), |
|
176 |
name_pref=ValueArgument( |
|
177 |
'filter by name prefix (case insensitive)', '--name-prefix'), |
|
178 |
name_suff=ValueArgument( |
|
179 |
'filter by name suffix (case insensitive)', '--name-suffix'), |
|
180 |
name_like=ValueArgument( |
|
181 |
'print only if name contains this (case insensitive)', |
|
182 |
'--name-like'), |
|
183 | 176 |
flavor_id=ValueArgument('filter by flavor id', ('--flavor-id')), |
184 | 177 |
image_id=ValueArgument('filter by image id', ('--image-id')), |
185 | 178 |
meta=KeyValueArgument('filter by metadata key=values', ('--metadata')), |
... | ... | |
188 | 181 |
('--metadata-like')), |
189 | 182 |
) |
190 | 183 |
|
191 |
def _filtered_by_name(self, servers): |
|
192 |
if self['name']: |
|
193 |
servers = filter_dicts_by_dict(servers, dict(name=self['name'])) |
|
194 |
np, ns, nl = self['name_pref'], self['name_suff'], self['name_like'] |
|
195 |
return [img for img in servers if ( |
|
196 |
(not np) or img['name'].lower().startswith(np.lower())) and ( |
|
197 |
(not ns) or img['name'].lower().endswith(ns.lower())) and ( |
|
198 |
(not nl) or nl.lower() in img['name'].lower())] |
|
199 |
|
|
200 | 184 |
def _add_user_name(self, servers): |
201 | 185 |
uuids = self._uuids2usernames(list(set( |
202 | 186 |
[srv['user_id'] for srv in servers] + |
... | ... | |
206 | 190 |
srv['tenant_id'] += ' (%s)' % uuids[srv['tenant_id']] |
207 | 191 |
return servers |
208 | 192 |
|
209 |
def _filtered_by_image(self, servers):
|
|
193 |
def _filter_by_image(self, servers): |
|
210 | 194 |
iid = self['image_id'] |
211 | 195 |
new_servers = [] |
212 | 196 |
for srv in servers: |
... | ... | |
214 | 198 |
new_servers.append(srv) |
215 | 199 |
return new_servers |
216 | 200 |
|
217 |
def _filtered_by_flavor(self, servers):
|
|
201 |
def _filter_by_flavor(self, servers): |
|
218 | 202 |
fid = self['flavor_id'] |
219 | 203 |
new_servers = [] |
220 | 204 |
for srv in servers: |
... | ... | |
222 | 206 |
new_servers.append(srv) |
223 | 207 |
return new_servers |
224 | 208 |
|
225 |
def _filtered_by_metadata(self, servers):
|
|
209 |
def _filter_by_metadata(self, servers): |
|
226 | 210 |
new_servers = [] |
227 | 211 |
for srv in servers: |
228 | 212 |
if not 'metadata' in srv: |
... | ... | |
247 | 231 |
detail = self['detail'] or withimage or withflavor or withmeta |
248 | 232 |
servers = self.client.list_servers(detail, self['since']) |
249 | 233 |
|
250 |
servers = self._filtered_by_name(servers) |
|
234 |
servers = self._filter_by_name(servers) |
|
235 |
servers = self._filter_by_id(servers) |
|
251 | 236 |
if withimage: |
252 |
servers = self._filtered_by_image(servers)
|
|
237 |
servers = self._filter_by_image(servers) |
|
253 | 238 |
if withflavor: |
254 |
servers = self._filtered_by_flavor(servers)
|
|
239 |
servers = self._filter_by_flavor(servers) |
|
255 | 240 |
if withmeta: |
256 |
servers = self._filtered_by_metadata(servers)
|
|
241 |
servers = self._filter_by_metadata(servers) |
|
257 | 242 |
|
258 | 243 |
if self['detail'] and not self['json_output']: |
259 | 244 |
servers = self._add_user_name(servers) |
... | ... | |
700 | 685 |
|
701 | 686 |
|
702 | 687 |
@command(flavor_cmds) |
703 |
class flavor_list(_init_cyclades, _optional_json): |
|
688 |
class flavor_list(_init_cyclades, _optional_json, _name_filter, _id_filter):
|
|
704 | 689 |
"""List available hardware flavors""" |
705 | 690 |
|
706 | 691 |
arguments = dict( |
... | ... | |
716 | 701 |
@errors.cyclades.connection |
717 | 702 |
def _run(self): |
718 | 703 |
flavors = self.client.list_flavors(self['detail']) |
704 |
flavors = self._filter_by_name(flavors) |
|
705 |
flavors = self._filter_by_id(flavors) |
|
719 | 706 |
if not (self['detail'] or self['json_output']): |
720 | 707 |
remove_from_items(flavors, 'links') |
721 | 708 |
pg_size = 10 if self['more'] and not self['limit'] else self['limit'] |
... | ... | |
767 | 754 |
|
768 | 755 |
|
769 | 756 |
@command(network_cmds) |
770 |
class network_list(_init_cyclades, _optional_json): |
|
757 |
class network_list(_init_cyclades, _optional_json, _name_filter, _id_filter):
|
|
771 | 758 |
"""List networks""" |
772 | 759 |
|
773 | 760 |
arguments = dict( |
... | ... | |
783 | 770 |
@errors.cyclades.connection |
784 | 771 |
def _run(self): |
785 | 772 |
networks = self.client.list_networks(self['detail']) |
773 |
networks = self._filter_by_name(networks) |
|
774 |
networks = self._filter_by_id(networks) |
|
786 | 775 |
if not (self['detail'] or self['json_output']): |
787 | 776 |
remove_from_items(networks, 'links') |
788 | 777 |
kwargs = dict(with_enumeration=self['enum']) |
b/kamaki/cli/commands/image.py | ||
---|---|---|
47 | 47 |
from kamaki.cli.commands.cyclades import _init_cyclades |
48 | 48 |
from kamaki.cli.errors import raiseCLIError, CLIBaseUrlError |
49 | 49 |
from kamaki.cli.commands import _command_init, errors, addLogSettings |
50 |
from kamaki.cli.commands import _optional_output_cmd, _optional_json |
|
50 |
from kamaki.cli.commands import ( |
|
51 |
_optional_output_cmd, _optional_json, _name_filter, _id_filter) |
|
51 | 52 |
|
52 | 53 |
|
53 | 54 |
image_cmds = CommandTree( |
... | ... | |
172 | 173 |
|
173 | 174 |
|
174 | 175 |
@command(image_cmds) |
175 |
class image_list(_init_image, _optional_json): |
|
176 |
class image_list(_init_image, _optional_json, _name_filter, _id_filter):
|
|
176 | 177 |
"""List images accessible by user""" |
177 | 178 |
|
178 | 179 |
PERMANENTS = ( |
... | ... | |
185 | 186 |
'filter by container format', |
186 | 187 |
'--container-format'), |
187 | 188 |
disk_format=ValueArgument('filter by disk format', '--disk-format'), |
188 |
name=ValueArgument('filter by name', '--name'), |
|
189 |
name_pref=ValueArgument( |
|
190 |
'filter by name prefix (case insensitive)', '--name-prefix'), |
|
191 |
name_suff=ValueArgument( |
|
192 |
'filter by name suffix (case insensitive)', '--name-suffix'), |
|
193 |
name_like=ValueArgument( |
|
194 |
'print only if name contains this (case insensitive)', |
|
195 |
'--name-like'), |
|
196 | 189 |
size_min=IntArgument('filter by minimum size', '--size-min'), |
197 | 190 |
size_max=IntArgument('filter by maximum size', '--size-max'), |
198 | 191 |
status=ValueArgument('filter by status', '--status'), |
... | ... | |
213 | 206 |
('--property-like')), |
214 | 207 |
) |
215 | 208 |
|
216 |
def _filtered_by_owner(self, images):
|
|
209 |
def _filter_by_owner(self, images): |
|
217 | 210 |
ouuid = self['owner'] or self._username2uuid(self['owner_name']) |
218 | 211 |
return filter_dicts_by_dict(images, dict(owner=ouuid)) |
219 | 212 |
|
220 |
def _filtered_by_name(self, images): |
|
221 |
np, ns, nl = self['name_pref'], self['name_suff'], self['name_like'] |
|
222 |
return [img for img in images if ( |
|
223 |
(not np) or img['name'].lower().startswith(np.lower())) and ( |
|
224 |
(not ns) or img['name'].lower().endswith(ns.lower())) and ( |
|
225 |
(not nl) or nl.lower() in img['name'].lower())] |
|
226 |
|
|
227 | 213 |
def _add_owner_name(self, images): |
228 | 214 |
uuids = self._uuids2usernames( |
229 | 215 |
list(set([img['owner'] for img in images]))) |
... | ... | |
231 | 217 |
img['owner'] += ' (%s)' % uuids[img['owner']] |
232 | 218 |
return images |
233 | 219 |
|
234 |
def _filtered_by_properties(self, images):
|
|
220 |
def _filter_by_properties(self, images): |
|
235 | 221 |
new_images = [] |
236 | 222 |
for img in images: |
237 | 223 |
props = [dict(img['properties'])] |
... | ... | |
266 | 252 |
images = self.client.list_public(detail, filters, order) |
267 | 253 |
|
268 | 254 |
if self['owner'] or self['owner_name']: |
269 |
images = self._filtered_by_owner(images)
|
|
255 |
images = self._filter_by_owner(images) |
|
270 | 256 |
if self['prop'] or self['prop_like']: |
271 |
images = self._filtered_by_properties(images) |
|
272 |
images = self._filtered_by_name(images) |
|
257 |
images = self._filter_by_properties(images) |
|
258 |
images = self._filter_by_id(images) |
|
259 |
images = self._non_exact_name_filter(images) |
|
273 | 260 |
|
274 | 261 |
if self['detail'] and not self['json_output']: |
275 | 262 |
images = self._add_owner_name(images) |
... | ... | |
622 | 609 |
|
623 | 610 |
|
624 | 611 |
@command(image_cmds) |
625 |
class image_compute_list(_init_cyclades, _optional_json): |
|
612 |
class image_compute_list( |
|
613 |
_init_cyclades, _optional_json, _name_filter, _id_filter): |
|
626 | 614 |
"""List images""" |
627 | 615 |
|
628 | 616 |
PERMANENTS = ('id', 'name') |
... | ... | |
634 | 622 |
'output results in pages (-n to set items per page, default 10)', |
635 | 623 |
'--more'), |
636 | 624 |
enum=FlagArgument('Enumerate results', '--enumerate'), |
637 |
name=ValueArgument('filter by name', '--name'), |
|
638 |
name_pref=ValueArgument( |
|
639 |
'filter by name prefix (case insensitive)', |
|
640 |
'--name-prefix'), |
|
641 |
name_suff=ValueArgument( |
|
642 |
'filter by name suffix (case insensitive)', |
|
643 |
'--name-suffix'), |
|
644 |
name_like=ValueArgument( |
|
645 |
'print only if name contains this (case insensitive)', |
|
646 |
'--name-like'), |
|
647 | 625 |
user_id=ValueArgument('filter by user_id', '--user-id'), |
648 | 626 |
user_name=ValueArgument('filter by username', '--user-name'), |
649 | 627 |
meta=KeyValueArgument( |
... | ... | |
653 | 631 |
('--metadata-like')) |
654 | 632 |
) |
655 | 633 |
|
656 |
def _filtered_by_name(self, images): |
|
657 |
np, ns, nl = self['name_pref'], self['name_suff'], self['name_like'] |
|
658 |
return [img for img in images if ( |
|
659 |
(not np) or img['name'].lower().startswith(np.lower())) and ( |
|
660 |
(not ns) or img['name'].lower().endswith(ns.lower())) and ( |
|
661 |
(not nl) or nl.lower() in img['name'].lower())] |
|
662 |
|
|
663 | 634 |
def _filter_by_metadata(self, images): |
664 | 635 |
new_images = [] |
665 | 636 |
for img in images: |
... | ... | |
691 | 662 |
withuser = bool(self['user_id'] or self['user_name']) |
692 | 663 |
detail = self['detail'] or withmeta or withuser |
693 | 664 |
images = self.client.list_images(detail) |
694 |
images = self._filtered_by_name(images) |
|
665 |
images = self._filter_by_name(images) |
|
666 |
images = self._filter_by_id(images) |
|
695 | 667 |
if withuser: |
696 | 668 |
images = self._filter_by_user(images) |
697 | 669 |
if withmeta: |
b/kamaki/cli/commands/pithos.py | ||
---|---|---|
46 | 46 |
from kamaki.cli.argument import ProgressBarArgument |
47 | 47 |
from kamaki.cli.commands import _command_init, errors |
48 | 48 |
from kamaki.cli.commands import addLogSettings, DontRaiseKeyError |
49 |
from kamaki.cli.commands import _optional_output_cmd, _optional_json |
|
49 |
from kamaki.cli.commands import ( |
|
50 |
_optional_output_cmd, _optional_json, _name_filter) |
|
50 | 51 |
from kamaki.clients.pithos import PithosClient, ClientError |
51 | 52 |
from kamaki.clients.astakos import AstakosClient |
52 | 53 |
|
... | ... | |
326 | 327 |
|
327 | 328 |
|
328 | 329 |
@command(pithos_cmds) |
329 |
class file_list(_file_container_command, _optional_json): |
|
330 |
class file_list(_file_container_command, _optional_json, _name_filter):
|
|
330 | 331 |
"""List containers, object trees or objects in a directory |
331 | 332 |
Use with: |
332 | 333 |
1 no parameters : containers in current account |
... | ... | |
439 | 440 |
if_unmodified_since=self['if_unmodified_since'], |
440 | 441 |
until=self['until'], |
441 | 442 |
show_only_shared=self['shared']) |
442 |
self._print(r.json, self.print_containers) |
|
443 |
files = self._filter_by_name(r.json) |
|
444 |
self._print(files, self.print_containers) |
|
443 | 445 |
else: |
444 |
prefix = self.path or self['prefix'] |
|
446 |
prefix = self.path or self['prefix'] or self['name_prefix']
|
|
445 | 447 |
r = self.client.container_get( |
446 | 448 |
limit=False if self['more'] else self['limit'], |
447 | 449 |
marker=self['marker'], |
... | ... | |
453 | 455 |
until=self['until'], |
454 | 456 |
meta=self['meta'], |
455 | 457 |
show_only_shared=self['shared']) |
456 |
self._print(r.json, self.print_objects) |
|
458 |
files = self._filter_by_name(r.json) |
|
459 |
self._print(files, self.print_objects) |
|
457 | 460 |
|
458 | 461 |
def main(self, container____path__=None): |
459 | 462 |
super(self.__class__, self)._run(container____path__) |
Also available in: Unified diff