Revision 89ea97e1

b/kamaki/cli/commands/cyclades.py
33 33

  
34 34
from kamaki.cli import command
35 35
from kamaki.cli.command_tree import CommandTree
36
from kamaki.cli.utils import print_dict, remove_from_items
36
from kamaki.cli.utils import (
37
    print_dict, remove_from_items, filter_dicts_by_dict)
37 38
from kamaki.cli.errors import raiseCLIError, CLISyntaxError, CLIBaseUrlError
38 39
from kamaki.clients.cyclades import CycladesClient, ClientError
39 40
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
......
157 158
class server_list(_init_cyclades, _optional_json):
158 159
    """List Virtual Machines accessible by user"""
159 160

  
161
    PERMANENTS = ('id', 'name')
162

  
160 163
    __doc__ += about_authentication
161 164

  
162 165
    arguments = dict(
......
168 171
        more=FlagArgument(
169 172
            'output results in pages (-n to set items per page, default 10)',
170 173
            '--more'),
171
        enum=FlagArgument('Enumerate results', '--enumerate')
174
        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
        flavor_id=ValueArgument('filter by flavor id', ('--flavor-id')),
184
        image_id=ValueArgument('filter by image id', ('--image-id')),
185
        meta=KeyValueArgument('filter by metadata key=values', ('--metadata')),
186
        meta_like=KeyValueArgument(
187
            'print only if in key=value, the value is part of actual value',
188
            ('--metadata-like')),
172 189
    )
173 190

  
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
    def _filtered_by_image(self, servers):
201
        iid = self['image_id']
202
        new_servers = []
203
        for srv in servers:
204
            if srv['image']['id'] == iid:
205
                new_servers.append(srv)
206
        return new_servers
207

  
208
    def _filtered_by_flavor(self, servers):
209
        fid = self['flavor_id']
210
        new_servers = []
211
        for srv in servers:
212
            if '%s' % srv['flavor']['id'] == '%s' % fid:
213
                new_servers.append(srv)
214
        return new_servers
215

  
216
    def _filtered_by_metadata(self, servers):
217
        new_servers = []
218
        for srv in servers:
219
            if not 'metadata' in srv:
220
                continue
221
            meta = [dict(srv['metadata'])]
222
            if self['meta']:
223
                meta = filter_dicts_by_dict(meta, self['meta'])
224
            if meta and self['meta_like']:
225
                meta = filter_dicts_by_dict(
226
                    meta, self['meta_like'], exact_match=False)
227
            if meta:
228
                new_servers.append(srv)
229
        return new_servers
230

  
174 231
    @errors.generic.all
175 232
    @errors.cyclades.connection
176 233
    @errors.cyclades.date
177 234
    def _run(self):
178
        servers = self.client.list_servers(self['detail'], self['since'])
235
        withimage = bool(self['image_id'])
236
        withflavor = bool(self['flavor_id'])
237
        withmeta = bool(self['meta'] or self['meta_like'])
238
        detail = self['detail'] or withimage or withflavor or withmeta
239
        servers = self.client.list_servers(detail, self['since'])
240

  
241
        servers = self._filtered_by_name(servers)
242
        if withimage:
243
            servers = self._filtered_by_image(servers)
244
        if withflavor:
245
            servers = self._filtered_by_flavor(servers)
246
        if withmeta:
247
            servers = self._filtered_by_metadata(servers)
248

  
179 249
        if not (self['detail'] or self['json_output']):
180 250
            remove_from_items(servers, 'links')
181

  
251
        #if self['detail'] and not self['json_output']:
252
        #    servers = self._add_owner_name(servers)
253
        if detail and not self['detail']:
254
            for srv in servers:
255
                for key in set(srv).difference(self.PERMANENTS):
256
                    srv.pop(key)
182 257
        kwargs = dict(with_enumeration=self['enum'])
183 258
        if self['more']:
184 259
            kwargs['page_size'] = self['limit'] if self['limit'] else 10
b/kamaki/cli/commands/image.py
187 187
        disk_format=ValueArgument('filter by disk format', '--disk-format'),
188 188
        name=ValueArgument('filter by name', '--name'),
189 189
        name_pref=ValueArgument(
190
            'filter by name prefix (case insensitive)',
191
            '--name-prefix'),
190
            'filter by name prefix (case insensitive)', '--name-prefix'),
192 191
        name_suff=ValueArgument(
193
            'filter by name suffix (case insensitive)',
194
            '--name-suffix'),
192
            'filter by name suffix (case insensitive)', '--name-suffix'),
195 193
        name_like=ValueArgument(
196 194
            'print only if name contains this (case insensitive)',
197 195
            '--name-like'),
......
813 811
    def _run(self, image_id, keyvals):
814 812
        meta = dict()
815 813
        for keyval in keyvals:
816
            key, val = keyval.split('=')
814
            key, sep, val = keyval.partition('=')
817 815
            meta[key] = val
818 816
        self._print(
819 817
            self.client.update_image_metadata(image_id, **meta), print_dict)
820 818

  
821 819
    def main(self, image_id, *key_equals_value):
822 820
        super(self.__class__, self)._run()
821
        print key_equals_value
823 822
        self._run(image_id=image_id, keyvals=key_equals_value)
824 823

  
825 824

  
b/kamaki/cli/utils/__init__.py
73 73

  
74 74

  
75 75
def _readline():
76
    """stdout.readline wrapper is used to help unittests"""
77
    return stdout.readline()
76
    """raw_input wrapper is used to help unittests"""
77
    return raw_input()
78 78

  
79 79

  
80 80
def suggest_missing(miss=None, exclude=[]):
......
283 283
        _print('%s' % items)
284 284
        return
285 285

  
286
    page_size = int(page_size)
286
    page_size = int(page_size or 0)
287 287
    try:
288 288
        page_size = page_size if page_size > 0 else len(items)
289 289
    except:
b/kamaki/cli/utils/test.py
413 413
    def test_split_input(self):
414 414
        from kamaki.cli.utils import split_input
415 415
        for line, expected in (
416
                ('set key="v1"', ['set', 'key=v1']),
416 417
                ('unparsable', ['unparsable']),
417 418
                ('"parsable"', ['parsable']),
418 419
                ('"parse" out', ['parse', 'out']),

Also available in: Unified diff