Merge "image: Add 'image task show' commands"
This commit is contained in:
commit
97af1b661e
@ -55,6 +55,6 @@ stores-delete,,Delete image from specific store.
|
|||||||
stores-info,,Print available backends from Glance.
|
stores-info,,Print available backends from Glance.
|
||||||
task-create,,Create a new task.
|
task-create,,Create a new task.
|
||||||
task-list,,List tasks you can access.
|
task-list,,List tasks you can access.
|
||||||
task-show,,Describe a specific task.
|
task-show,image task show,Describe a specific task.
|
||||||
bash-completion,complete,Prints arguments for bash_completion.
|
bash-completion,complete,Prints arguments for bash_completion.
|
||||||
help,help,Display help about this program or one of its subcommands.
|
help,help,Display help about this program or one of its subcommands.
|
||||||
|
|
78
openstackclient/image/v2/task.py
Normal file
78
openstackclient/image/v2/task.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from osc_lib.cli import format_columns
|
||||||
|
from osc_lib.command import command
|
||||||
|
|
||||||
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
def _format_task(task):
|
||||||
|
"""Format an task to make it more consistent with OSC operations."""
|
||||||
|
|
||||||
|
info = {}
|
||||||
|
properties = {}
|
||||||
|
|
||||||
|
# the only fields we're not including is "links", "tags" and the properties
|
||||||
|
fields_to_show = [
|
||||||
|
'created_at',
|
||||||
|
'expires_at',
|
||||||
|
'id',
|
||||||
|
'input',
|
||||||
|
'message',
|
||||||
|
'owner_id',
|
||||||
|
'result',
|
||||||
|
'status',
|
||||||
|
'type',
|
||||||
|
'updated_at',
|
||||||
|
]
|
||||||
|
|
||||||
|
# split out the usual key and the properties which are top-level
|
||||||
|
for field in fields_to_show:
|
||||||
|
info[field] = task.get(field)
|
||||||
|
|
||||||
|
for key in task:
|
||||||
|
if key in fields_to_show:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if key in {'location', 'name', 'schema'}:
|
||||||
|
continue
|
||||||
|
|
||||||
|
properties[key] = task.get(key)
|
||||||
|
|
||||||
|
# add properties back into the dictionary as a top-level key
|
||||||
|
info['properties'] = format_columns.DictColumn(properties)
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
class ShowTask(command.ShowOne):
|
||||||
|
_description = _('Display task details')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShowTask, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'task',
|
||||||
|
metavar='<Task ID>',
|
||||||
|
help=_('Task to display (ID)'),
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
image_client = self.app.client_manager.image
|
||||||
|
|
||||||
|
task = image_client.get_task(parsed_args.task)
|
||||||
|
info = _format_task(task)
|
||||||
|
|
||||||
|
return zip(*sorted(info.items()))
|
@ -18,6 +18,7 @@ import uuid
|
|||||||
|
|
||||||
from openstack.image.v2 import image
|
from openstack.image.v2 import image
|
||||||
from openstack.image.v2 import member
|
from openstack.image.v2 import member
|
||||||
|
from openstack.image.v2 import task
|
||||||
|
|
||||||
from openstackclient.tests.unit import fakes
|
from openstackclient.tests.unit import fakes
|
||||||
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
|
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
|
||||||
@ -44,6 +45,9 @@ class FakeImagev2Client:
|
|||||||
|
|
||||||
self.remove_tag = mock.Mock()
|
self.remove_tag = mock.Mock()
|
||||||
|
|
||||||
|
self.tasks = mock.Mock()
|
||||||
|
self.get_task = mock.Mock()
|
||||||
|
|
||||||
self.auth_token = kwargs['token']
|
self.auth_token = kwargs['token']
|
||||||
self.management_url = kwargs['endpoint']
|
self.management_url = kwargs['endpoint']
|
||||||
self.version = 2.0
|
self.version = 2.0
|
||||||
@ -129,3 +133,53 @@ def create_one_image_member(attrs=None):
|
|||||||
image_member_info.update(attrs)
|
image_member_info.update(attrs)
|
||||||
|
|
||||||
return member.Member(**image_member_info)
|
return member.Member(**image_member_info)
|
||||||
|
|
||||||
|
|
||||||
|
def create_one_task(attrs=None):
|
||||||
|
"""Create a fake task.
|
||||||
|
|
||||||
|
:param attrs: A dictionary with all attributes of task
|
||||||
|
:type attrs: dict
|
||||||
|
:return: A fake Task object.
|
||||||
|
:rtype: `openstack.image.v2.task.Task`
|
||||||
|
"""
|
||||||
|
attrs = attrs or {}
|
||||||
|
|
||||||
|
# Set default attribute
|
||||||
|
task_info = {
|
||||||
|
'created_at': '2016-06-29T16:13:07Z',
|
||||||
|
'expires_at': '2016-07-01T16:13:07Z',
|
||||||
|
'id': str(uuid.uuid4()),
|
||||||
|
'input': {
|
||||||
|
'image_properties': {
|
||||||
|
'container_format': 'ovf',
|
||||||
|
'disk_format': 'vhd'
|
||||||
|
},
|
||||||
|
'import_from': 'https://apps.openstack.org/excellent-image',
|
||||||
|
'import_from_format': 'qcow2'
|
||||||
|
},
|
||||||
|
'message': '',
|
||||||
|
'owner': str(uuid.uuid4()),
|
||||||
|
'result': {
|
||||||
|
'image_id': str(uuid.uuid4()),
|
||||||
|
},
|
||||||
|
'schema': '/v2/schemas/task',
|
||||||
|
'status': random.choice(
|
||||||
|
[
|
||||||
|
'pending',
|
||||||
|
'processing',
|
||||||
|
'success',
|
||||||
|
'failure',
|
||||||
|
]
|
||||||
|
),
|
||||||
|
# though not documented, the API only allows 'import'
|
||||||
|
# https://github.com/openstack/glance/blob/24.0.0/glance/api/v2/tasks.py#L186-L190
|
||||||
|
'type': 'import',
|
||||||
|
'updated_at': '2016-06-29T16:13:07Z',
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Overwrite default attributes if there are some attributes set
|
||||||
|
task_info.update(attrs)
|
||||||
|
|
||||||
|
return task.Task(**task_info)
|
||||||
|
80
openstackclient/tests/unit/image/v2/test_task.py
Normal file
80
openstackclient/tests/unit/image/v2/test_task.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from osc_lib.cli import format_columns
|
||||||
|
|
||||||
|
from openstackclient.image.v2 import task
|
||||||
|
from openstackclient.tests.unit.image.v2 import fakes as image_fakes
|
||||||
|
|
||||||
|
|
||||||
|
class TestTask(image_fakes.TestImagev2):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
# Get shortcuts to mocked image client
|
||||||
|
self.client = self.app.client_manager.image
|
||||||
|
|
||||||
|
|
||||||
|
class TestTaskShow(TestTask):
|
||||||
|
|
||||||
|
task = image_fakes.create_one_task()
|
||||||
|
|
||||||
|
columns = (
|
||||||
|
'created_at',
|
||||||
|
'expires_at',
|
||||||
|
'id',
|
||||||
|
'input',
|
||||||
|
'message',
|
||||||
|
'owner_id',
|
||||||
|
'properties',
|
||||||
|
'result',
|
||||||
|
'status',
|
||||||
|
'type',
|
||||||
|
'updated_at',
|
||||||
|
)
|
||||||
|
data = (
|
||||||
|
task.created_at,
|
||||||
|
task.expires_at,
|
||||||
|
task.id,
|
||||||
|
task.input,
|
||||||
|
task.message,
|
||||||
|
task.owner_id,
|
||||||
|
format_columns.DictColumn({}),
|
||||||
|
task.result,
|
||||||
|
task.status,
|
||||||
|
task.type,
|
||||||
|
task.updated_at,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.client.get_task.return_value = self.task
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = task.ShowTask(self.app, None)
|
||||||
|
|
||||||
|
def test_task_show(self):
|
||||||
|
arglist = [self.task.id]
|
||||||
|
verifylist = [
|
||||||
|
('task', self.task.id),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# In base command class ShowOne in cliff, abstract method take_action()
|
||||||
|
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||||
|
# data to be shown.
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
self.client.get_task.assert_called_with(self.task.id)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertCountEqual(self.data, data)
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ``image task show`` command to show a task for the image service.
|
@ -382,6 +382,7 @@ openstack.image.v2 =
|
|||||||
image_show = openstackclient.image.v2.image:ShowImage
|
image_show = openstackclient.image.v2.image:ShowImage
|
||||||
image_set = openstackclient.image.v2.image:SetImage
|
image_set = openstackclient.image.v2.image:SetImage
|
||||||
image_unset = openstackclient.image.v2.image:UnsetImage
|
image_unset = openstackclient.image.v2.image:UnsetImage
|
||||||
|
image_task_show = openstackclient.image.v2.task:ShowTask
|
||||||
|
|
||||||
openstack.network.v2 =
|
openstack.network.v2 =
|
||||||
address_group_create = openstackclient.network.v2.address_group:CreateAddressGroup
|
address_group_create = openstackclient.network.v2.address_group:CreateAddressGroup
|
||||||
|
Loading…
x
Reference in New Issue
Block a user