Commit 414ebaf1 authored by Michael Hanselmann's avatar Michael Hanselmann

RAPI: Add support for tagging node groups

Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent 819cbfe5
......@@ -497,6 +497,46 @@ Body parameters:
:exclude: group_name, force, dry_run
``/2/groups/[group_name]/tags``
+++++++++++++++++++++++++++++++
Manages per-nodegroup tags.
Supports the following commands: ``GET``, ``PUT``, ``DELETE``.
``GET``
~~~~~~~
Returns a list of tags.
Example::
["tag1", "tag2", "tag3"]
``PUT``
~~~~~~~
Add a set of tags.
The request as a list of strings should be ``PUT`` to this URI. The
result will be a job id.
It supports the ``dry-run`` argument.
``DELETE``
~~~~~~~~~~
Delete a tag.
In order to delete a set of tags, the DELETE request should be addressed
to URI like::
/tags?tag=[tag]&tag=[tag]
It supports the ``dry-run`` argument.
``/2/instances``
++++++++++++++++
......
......@@ -92,12 +92,16 @@ def _Tags_GET(kind, name):
"""Helper function to retrieve tags.
"""
if kind == constants.TAG_INSTANCE or kind == constants.TAG_NODE:
if kind in (constants.TAG_INSTANCE,
constants.TAG_NODEGROUP,
constants.TAG_NODE):
if not name:
raise http.HttpBadRequest("Missing name on tag request")
cl = GetClient()
if kind == constants.TAG_INSTANCE:
fn = cl.QueryInstances
elif kind == constants.TAG_NODEGROUP:
fn = cl.QueryGroups
else:
fn = cl.QueryNodes
result = fn(names=[name], fields=["tags"], use_locking=False)
......
......@@ -1620,6 +1620,63 @@ class GanetiRapiClient(object): # pylint: disable-msg=R0904
("/%s/groups/%s/assign-nodes" %
(GANETI_RAPI_VERSION, group)), query, body)
def GetGroupTags(self, group):
"""Gets tags for a node group.
@type group: string
@param group: Node group whose tags to return
@rtype: list of strings
@return: tags for the group
"""
return self._SendRequest(HTTP_GET,
("/%s/groups/%s/tags" %
(GANETI_RAPI_VERSION, group)), None, None)
def AddGroupTags(self, group, tags, dry_run=False):
"""Adds tags to a node group.
@type group: str
@param group: group to add tags to
@type tags: list of string
@param tags: tags to add to the group
@type dry_run: bool
@param dry_run: whether to perform a dry run
@rtype: string
@return: job id
"""
query = [("tag", t) for t in tags]
if dry_run:
query.append(("dry-run", 1))
return self._SendRequest(HTTP_PUT,
("/%s/groups/%s/tags" %
(GANETI_RAPI_VERSION, group)), query, None)
def DeleteGroupTags(self, group, tags, dry_run=False):
"""Deletes tags from a node group.
@type group: str
@param group: group to delete tags from
@type tags: list of string
@param tags: tags to delete
@type dry_run: bool
@param dry_run: whether to perform a dry run
@rtype: string
@return: job id
"""
query = [("tag", t) for t in tags]
if dry_run:
query.append(("dry-run", 1))
return self._SendRequest(HTTP_DELETE,
("/%s/groups/%s/tags" %
(GANETI_RAPI_VERSION, group)), query, None)
def Query(self, what, fields, filter_=None):
"""Retrieves information about resources.
......
......@@ -230,6 +230,8 @@ def GetHandlers(node_name_pattern, instance_name_pattern,
rlib2.R_2_groups_name_rename,
re.compile(r'^/2/groups/(%s)/assign-nodes$' % group_name_pattern):
rlib2.R_2_groups_name_assign_nodes,
re.compile(r'^/2/groups/(%s)/tags$' % group_name_pattern):
rlib2.R_2_groups_name_tags,
"/2/jobs": rlib2.R_2_jobs,
re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
......
......@@ -1375,6 +1375,15 @@ class R_2_nodes_name_tags(_R_Tags):
TAG_LEVEL = constants.TAG_NODE
class R_2_groups_name_tags(_R_Tags):
""" /2/groups/[group_name]/tags resource.
Manages per-nodegroup tags.
"""
TAG_LEVEL = constants.TAG_NODEGROUP
class R_2_tags(_R_Tags):
""" /2/tags resource.
......
......@@ -1087,6 +1087,30 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
self.assertEqual(data["amount"], amount)
self.assertEqual(self.rapi.CountPending(), 0)
def testGetGroupTags(self):
self.rapi.AddResponse("[]")
self.assertEqual([], self.client.GetGroupTags("fooGroup"))
self.assertHandler(rlib2.R_2_groups_name_tags)
self.assertItems(["fooGroup"])
def testAddGroupTags(self):
self.rapi.AddResponse("1234")
self.assertEqual(1234,
self.client.AddGroupTags("fooGroup", ["awesome"], dry_run=True))
self.assertHandler(rlib2.R_2_groups_name_tags)
self.assertItems(["fooGroup"])
self.assertDryRun()
self.assertQuery("tag", ["awesome"])
def testDeleteGroupTags(self):
self.rapi.AddResponse("25826")
self.assertEqual(25826, self.client.DeleteGroupTags("foo", ["awesome"],
dry_run=True))
self.assertHandler(rlib2.R_2_groups_name_tags)
self.assertItems(["foo"])
self.assertDryRun()
self.assertQuery("tag", ["awesome"])
def testQuery(self):
for idx, what in enumerate(constants.QR_VIA_RAPI):
for idx2, filter_ in enumerate([None, ["?", "name"]]):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment