Add tag support for Glare client
Change-Id: I08bdfe3260e68bff3955e6dc39941a90c262c112
This commit is contained in:
parent
6ed07b9320
commit
847615851c
@ -508,6 +508,92 @@ class PublishArtifact(command.Lister):
|
|||||||
return print_artifact(client, data, parsed_args.type_name)
|
return print_artifact(client, data, parsed_args.type_name)
|
||||||
|
|
||||||
|
|
||||||
|
class AddTag(command.Lister):
|
||||||
|
"""Add tag to artifact"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(AddTag, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'type_name',
|
||||||
|
metavar='<TYPE_NAME>',
|
||||||
|
action=TypeMapperAction,
|
||||||
|
help='Name of artifact type.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'name',
|
||||||
|
metavar='<NAME>',
|
||||||
|
help='Name or id of the artifact to publish.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'tag',
|
||||||
|
metavar='<TAG>',
|
||||||
|
help='Value of the tag to add to the artifact.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--artifact-version', '-V',
|
||||||
|
metavar='<VERSION>',
|
||||||
|
default='latest',
|
||||||
|
help='Version of the artifact.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--id', '-i',
|
||||||
|
action='store_true',
|
||||||
|
help='Flag indicates to use artifact id instead of its name.',
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
LOG.debug('take_action({0})'.format(parsed_args))
|
||||||
|
client = self.app.client_manager.artifact
|
||||||
|
af_id = get_artifact_id(client, parsed_args)
|
||||||
|
data = client.artifacts.add_tag(
|
||||||
|
af_id, tag_value=parsed_args.tag, type_name=parsed_args.type_name)
|
||||||
|
return print_artifact(client, data, parsed_args.type_name)
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveTag(command.Lister):
|
||||||
|
"""Remove tag from the artifact"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(RemoveTag, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'type_name',
|
||||||
|
metavar='<TYPE_NAME>',
|
||||||
|
action=TypeMapperAction,
|
||||||
|
help='Name of artifact type.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'name',
|
||||||
|
metavar='<NAME>',
|
||||||
|
help='Name or id of the artifact to publish.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'tag',
|
||||||
|
metavar='<TAG>',
|
||||||
|
help='Value of the tag to remove from the artifact.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--artifact-version', '-V',
|
||||||
|
metavar='<VERSION>',
|
||||||
|
default='latest',
|
||||||
|
help='Version of the artifact.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--id', '-i',
|
||||||
|
action='store_true',
|
||||||
|
help='Flag indicates to use artifact id instead of its name.',
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
LOG.debug('take_action({0})'.format(parsed_args))
|
||||||
|
client = self.app.client_manager.artifact
|
||||||
|
af_id = get_artifact_id(client, parsed_args)
|
||||||
|
data = client.artifacts.remove_tag(
|
||||||
|
af_id, tag_value=parsed_args.tag, type_name=parsed_args.type_name)
|
||||||
|
return print_artifact(client, data, parsed_args.type_name)
|
||||||
|
|
||||||
|
|
||||||
class TypeList(command.Lister):
|
class TypeList(command.Lister):
|
||||||
"""List of type names"""
|
"""List of type names"""
|
||||||
|
|
||||||
|
@ -89,6 +89,8 @@ class TestArtifacts(utils.TestCommand):
|
|||||||
self.app.client_manager.artifact.artifacts.list = mock_list
|
self.app.client_manager.artifact.artifacts.list = mock_list
|
||||||
self.app.client_manager.artifact.artifacts.get = mock_get
|
self.app.client_manager.artifact.artifacts.get = mock_get
|
||||||
self.app.client_manager.artifact.artifacts.get_by_name = mock_get
|
self.app.client_manager.artifact.artifacts.get_by_name = mock_get
|
||||||
|
self.app.client_manager.artifact.artifacts.add_tag = mock_g_servs
|
||||||
|
self.app.client_manager.artifact.artifacts.remove_tag = mock_g_servs
|
||||||
self.app.client_manager.artifact.artifacts.create = mock_g_servs
|
self.app.client_manager.artifact.artifacts.create = mock_g_servs
|
||||||
self.app.client_manager.artifact.artifacts.update = mock_g_servs
|
self.app.client_manager.artifact.artifacts.update = mock_g_servs
|
||||||
self.app.client_manager.artifact.artifacts.delete = mock_g_servs
|
self.app.client_manager.artifact.artifacts.delete = mock_g_servs
|
||||||
|
@ -423,6 +423,58 @@ class TestReactivateArtifacts(TestArtifacts):
|
|||||||
self.assertEqual(self.COLUMNS, name_fields)
|
self.assertEqual(self.COLUMNS, name_fields)
|
||||||
|
|
||||||
|
|
||||||
|
class TestAddTag(TestArtifacts):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestAddTag, self).setUp()
|
||||||
|
self.artifact_mock.call.return_value = \
|
||||||
|
api_art.Controller(self.http, type_name='images')
|
||||||
|
|
||||||
|
# Command to test
|
||||||
|
self.cmd = osc_art.AddTag(self.app, None)
|
||||||
|
|
||||||
|
def test_artifact_add_tag(self):
|
||||||
|
arglist = ['images',
|
||||||
|
'fc15c365-d4f9-4b8b-a090-d9e230f1f6ba', '--id',
|
||||||
|
'123']
|
||||||
|
verify = [('type_name', 'images'),
|
||||||
|
('name', 'fc15c365-d4f9-4b8b-a090-d9e230f1f6ba'),
|
||||||
|
('id', True),
|
||||||
|
('tag', '123')]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verify)
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
name_fields = set([column[0] for column in data])
|
||||||
|
# Check that columns are correct
|
||||||
|
self.assertEqual(self.COLUMNS, name_fields)
|
||||||
|
|
||||||
|
|
||||||
|
class TestRemoveTag(TestArtifacts):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestRemoveTag, self).setUp()
|
||||||
|
self.artifact_mock.call.return_value = \
|
||||||
|
api_art.Controller(self.http, type_name='images')
|
||||||
|
|
||||||
|
# Command to test
|
||||||
|
self.cmd = osc_art.RemoveTag(self.app, None)
|
||||||
|
|
||||||
|
def test_artifact_add_tag(self):
|
||||||
|
arglist = ['images',
|
||||||
|
'fc15c365-d4f9-4b8b-a090-d9e230f1f6ba', '--id',
|
||||||
|
'123']
|
||||||
|
verify = [('type_name', 'images'),
|
||||||
|
('name', 'fc15c365-d4f9-4b8b-a090-d9e230f1f6ba'),
|
||||||
|
('id', True),
|
||||||
|
('tag', '123')]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verify)
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
name_fields = set([column[0] for column in data])
|
||||||
|
# Check that columns are correct
|
||||||
|
self.assertEqual(self.COLUMNS, name_fields)
|
||||||
|
|
||||||
|
|
||||||
class TestPublishArtifacts(TestArtifacts):
|
class TestPublishArtifacts(TestArtifacts):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -243,4 +243,19 @@ data_fixtures = {
|
|||||||
]},
|
]},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
'/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c': {
|
||||||
|
'PATCH': (
|
||||||
|
{},
|
||||||
|
''
|
||||||
|
),
|
||||||
|
'GET': (
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
'name': 'art_1',
|
||||||
|
'id': '07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
'version': '0.0.0',
|
||||||
|
'tags': ["a", "b", "c"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -412,3 +412,55 @@ class TestController(testtools.TestCase):
|
|||||||
'http://fake_url')]
|
'http://fake_url')]
|
||||||
self.assertEqual(expect_call, self.api.calls)
|
self.assertEqual(expect_call, self.api.calls)
|
||||||
self.assertIsNone(data)
|
self.assertIsNone(data)
|
||||||
|
|
||||||
|
def test_add_tag(self):
|
||||||
|
art_id = '07a679d8-d0a8-45ff-8d6e-2f32f2097b7c'
|
||||||
|
data = self.controller.add_tag(
|
||||||
|
art_id, tag_value="123", type_name='images')
|
||||||
|
expect_call = [
|
||||||
|
('GET', '/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
{}, None),
|
||||||
|
('PATCH',
|
||||||
|
'/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
{'Content-Type': 'application/json-patch+json'},
|
||||||
|
[{'op': 'add',
|
||||||
|
'path': '/tags',
|
||||||
|
'value': ['a', 'b', 'c', '123']}])]
|
||||||
|
self.assertEqual(expect_call, self.api.calls)
|
||||||
|
self.assertIsNotNone(data)
|
||||||
|
|
||||||
|
def test_add_existing_tag(self):
|
||||||
|
art_id = '07a679d8-d0a8-45ff-8d6e-2f32f2097b7c'
|
||||||
|
data = self.controller.add_tag(
|
||||||
|
art_id, tag_value="a", type_name='images')
|
||||||
|
expect_call = [
|
||||||
|
('GET', '/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
{}, None)]
|
||||||
|
self.assertEqual(expect_call, self.api.calls)
|
||||||
|
self.assertIsNotNone(data)
|
||||||
|
|
||||||
|
def test_remove_tag(self):
|
||||||
|
art_id = '07a679d8-d0a8-45ff-8d6e-2f32f2097b7c'
|
||||||
|
data = self.controller.remove_tag(
|
||||||
|
art_id, tag_value="a", type_name='images')
|
||||||
|
expect_call = [
|
||||||
|
('GET', '/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
{}, None),
|
||||||
|
('PATCH',
|
||||||
|
'/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
{'Content-Type': 'application/json-patch+json'},
|
||||||
|
[{'op': 'add',
|
||||||
|
'path': '/tags',
|
||||||
|
'value': ['b', 'c']}])]
|
||||||
|
self.assertEqual(expect_call, self.api.calls)
|
||||||
|
self.assertIsNotNone(data)
|
||||||
|
|
||||||
|
def test_remove_nonexisting_tag(self):
|
||||||
|
art_id = '07a679d8-d0a8-45ff-8d6e-2f32f2097b7c'
|
||||||
|
data = self.controller.remove_tag(
|
||||||
|
art_id, tag_value="123", type_name='images')
|
||||||
|
expect_call = [
|
||||||
|
('GET', '/artifacts/images/07a679d8-d0a8-45ff-8d6e-2f32f2097b7c',
|
||||||
|
{}, None)]
|
||||||
|
self.assertEqual(expect_call, self.api.calls)
|
||||||
|
self.assertIsNotNone(data)
|
||||||
|
@ -274,3 +274,33 @@ class Controller(object):
|
|||||||
url = '/schemas/%s' % type_name
|
url = '/schemas/%s' % type_name
|
||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
return body['schemas'][type_name]
|
return body['schemas'][type_name]
|
||||||
|
|
||||||
|
def add_tag(self, artifact_id, tag_value, type_name=None):
|
||||||
|
"""Add tag to artifact.
|
||||||
|
|
||||||
|
:param artifact_id: ID of the artifact to add a tag
|
||||||
|
:param tag_value: value of the tag to add
|
||||||
|
"""
|
||||||
|
type_name = self._check_type_name(type_name)
|
||||||
|
url = '/artifacts/%s/%s' % (type_name, artifact_id)
|
||||||
|
resp, body = self.http_client.get(url)
|
||||||
|
tags = body['tags']
|
||||||
|
if tag_value in tags:
|
||||||
|
return body
|
||||||
|
tags.append(tag_value)
|
||||||
|
return self.update(artifact_id, type_name, tags=tags)
|
||||||
|
|
||||||
|
def remove_tag(self, artifact_id, tag_value, type_name=None):
|
||||||
|
"""Remove tag from artifact.
|
||||||
|
|
||||||
|
:param artifact_id: ID of the artifact to remove a tag
|
||||||
|
:param tag_value: value of the tag to remove
|
||||||
|
"""
|
||||||
|
type_name = self._check_type_name(type_name)
|
||||||
|
url = '/artifacts/%s/%s' % (type_name, artifact_id)
|
||||||
|
resp, body = self.http_client.get(url)
|
||||||
|
tags = body['tags']
|
||||||
|
if tag_value not in tags:
|
||||||
|
return body
|
||||||
|
tags.remove(tag_value)
|
||||||
|
return self.update(artifact_id, type_name, tags=tags)
|
||||||
|
@ -49,6 +49,8 @@ openstack.artifact.v1 =
|
|||||||
artifact_download = glareclient.osc.v1.blobs:DownloadBlob
|
artifact_download = glareclient.osc.v1.blobs:DownloadBlob
|
||||||
artifact_type-list = glareclient.osc.v1.artifacts:TypeList
|
artifact_type-list = glareclient.osc.v1.artifacts:TypeList
|
||||||
artifact_schema = glareclient.osc.v1.artifacts:TypeSchema
|
artifact_schema = glareclient.osc.v1.artifacts:TypeSchema
|
||||||
|
artifact_add_tag = glareclient.osc.v1.artifacts:AddTag
|
||||||
|
artifact_remove_tag = glareclient.osc.v1.artifacts:RemoveTag
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
|
Loading…
x
Reference in New Issue
Block a user