: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``
++++++++++++++++
"""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)
("/%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.
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):
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.
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"]]):