Merge changes Ib98e912a,Ib98e912a,Ib98e912a,Ib98e912a,Ib98e912a

* changes:
  Align print_dict to the left
  Convert v2 images list method to generator
  Replace static v2 Image model with warlock model
  Add support for viewing a single image through v2
  Rewrite link parsing for finding v2 schemas
This commit is contained in:
Jenkins
2012-07-18 01:02:07 +00:00
committed by Gerrit Code Review
8 changed files with 147 additions and 23 deletions

View File

@@ -14,6 +14,7 @@
# under the License.
import os
import sys
import uuid
import prettytable
@@ -47,7 +48,7 @@ def print_list(objs, fields, formatters={}):
row.append(formatters[field](o))
else:
field_name = field.lower().replace(' ', '_')
data = getattr(o, field_name, '')
data = getattr(o, field_name, None) or ''
row.append(data)
pt.add_row(row)
@@ -56,7 +57,7 @@ def print_list(objs, fields, formatters={}):
def print_dict(d):
pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
pt.aligns = ['l', 'l']
pt.align = 'l'
[pt.add_row(list(r)) for r in d.iteritems()]
print pt.get_string(sortby='Property')
@@ -123,3 +124,9 @@ def import_versioned_module(version, submodule=None):
if submodule:
module = '.'.join((module, submodule))
return importutils.import_module(module)
def exit(msg=''):
if msg:
print >> sys.stderr, msg
sys.exit(1)

View File

@@ -15,6 +15,8 @@
import logging
import warlock
from glanceclient.common import http
from glanceclient.v2 import images
from glanceclient.v2 import schemas
@@ -36,5 +38,10 @@ class Client(object):
def __init__(self, endpoint, token=None, timeout=600, **kwargs):
self.http_client = http.HTTPClient(
endpoint, token=token, timeout=timeout)
self.images = images.Controller(self.http_client)
self.schemas = schemas.Controller(self.http_client)
self.images = images.Controller(self.http_client,
self._get_image_model())
def _get_image_model(self):
schema = self.schemas.get('image')
return warlock.model_factory(schema.raw())

View File

@@ -14,16 +14,27 @@
# under the License.
class Image(object):
def __init__(self, id, name):
self.id = id
self.name = name
class Controller(object):
def __init__(self, http_client):
def __init__(self, http_client, model):
self.http_client = http_client
self.model = model
def list(self):
"""Retrieve a listing of Image objects
:returns generator over list of Images
"""
resp, body = self.http_client.json_request('GET', '/v2/images')
return [Image(i['id'], i['name']) for i in body['images']]
for image in body['images']:
#NOTE(bcwaldon): remove 'self' for now until we have an elegant
# way to pass it into the model constructor without conflict
image.pop('self', None)
yield self.model(**image)
def get(self, image_id):
url = '/v2/images/%s' % image_id
resp, body = self.http_client.json_request('GET', url)
#NOTE(bcwaldon): remove 'self' for now until we have an elegant
# way to pass it into the model constructor without conflict
body['image'].pop('self', None)
return self.model(**body['image'])

View File

@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from glanceclient import exc
@@ -40,6 +42,9 @@ class Schema(object):
raw_properties = raw_schema['properties']
self.properties = translate_schema_properties(raw_properties)
def raw(self):
return copy.deepcopy(self._raw_schema)
class Controller(object):
def __init__(self, http_client):
@@ -52,7 +57,7 @@ class Controller(object):
def _find_schema_uri(self, schema_name):
_, schema_index = self.http_client.json_request('GET', '/v2/schemas')
for link in schema_index['links']:
if link['rel'] == schema_name:
return link['href']
raise exc.SchemaNotFound(schema_name)
try:
return schema_index[schema_name]
except KeyError:
raise exc.SchemaNotFound(schema_name)

View File

@@ -14,6 +14,7 @@
# under the License.
from glanceclient.common import utils
from glanceclient import exc
def do_image_list(gc, args):
@@ -23,9 +24,21 @@ def do_image_list(gc, args):
utils.print_list(images, columns)
@utils.arg('name', metavar='<NAME>', help='Name of model to describe.')
@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.')
def do_image_show(gc, args):
"""Describe a specific image."""
image = gc.images.get(args.id)
utils.print_dict(image)
@utils.arg('model', metavar='<MODEL>', help='Name of model to describe.')
def do_explain(gc, args):
"""Describe a specific model."""
schema = gc.schemas.get(args.name)
columns = ['Name', 'Description']
utils.print_list(schema.properties, columns)
try:
schema = gc.schemas.get(args.model)
except exc.SchemaNotFound:
utils.exit('Unable to find requested model \'%s\'' % args.model)
else:
formatters = {'Attribute': lambda m: m.name}
columns = ['Attribute', 'Description']
utils.print_list(schema.properties, columns, formatters)

75
tests/v2/test_images.py Normal file
View File

@@ -0,0 +1,75 @@
# Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
# 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.
import unittest
import warlock
from glanceclient.v2 import images
from tests import utils
fixtures = {
'/v2/images': {
'GET': (
{},
{'images': [
{
'id': '3a4560a1-e585-443e-9b39-553b46ec92d1',
'name': 'image-1',
},
{
'id': '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810',
'name': 'image-2',
},
]},
),
},
'/v2/images/3a4560a1-e585-443e-9b39-553b46ec92d1': {
'GET': (
{},
{
'image': {
'id': '3a4560a1-e585-443e-9b39-553b46ec92d1',
'name': 'image-1',
},
},
),
},
}
fake_schema = {'name': 'image', 'properties': {'id': {}, 'name': {}}}
FakeModel = warlock.model_factory(fake_schema)
class TestController(unittest.TestCase):
def setUp(self):
super(TestController, self).setUp()
self.api = utils.FakeAPI(fixtures)
self.controller = images.Controller(self.api, FakeModel)
def test_list_images(self):
#NOTE(bcwaldon): cast to list since the controller returns a generator
images = list(self.controller.list())
self.assertEqual(images[0].id, '3a4560a1-e585-443e-9b39-553b46ec92d1')
self.assertEqual(images[0].name, 'image-1')
self.assertEqual(images[1].id, '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810')
self.assertEqual(images[1].name, 'image-2')
def test_get_image(self):
image = self.controller.get('3a4560a1-e585-443e-9b39-553b46ec92d1')
self.assertEqual(image.id, '3a4560a1-e585-443e-9b39-553b46ec92d1')
self.assertEqual(image.name, 'image-1')

View File

@@ -23,10 +23,10 @@ fixtures = {
'/v2/schemas': {
'GET': (
{},
{'links': [
{'rel': 'image', 'href': '/v2/schemas/image'},
{'rel': 'access', 'href': '/v2/schemas/image/access'},
]},
{
'image': '/v2/schemas/image',
'access': '/v2/schemas/image/access',
},
),
},
'/v2/schemas/image': {
@@ -67,6 +67,11 @@ class TestSchema(unittest.TestCase):
self.assertEqual(schema.name, 'Country')
self.assertEqual([p.name for p in schema.properties], ['size'])
def test_raw(self):
raw_schema = {'name': 'Country', 'properties': {}}
schema = schemas.Schema(raw_schema)
self.assertEqual(schema.raw(), raw_schema)
class TestController(unittest.TestCase):
def setUp(self):

View File

@@ -2,3 +2,4 @@ argparse
httplib2
prettytable==0.6
python-keystoneclient>=0.1,<0.2
warlock==0.1.0