Juan Hernandez has uploaded a new change for review.

Change subject: restapi: Move Assigned Tag remove from collection to entity
......................................................................

restapi: Move Assigned Tag remove from collection to entity

This patch moves the method that implements the DELETE operation from
the collection interface to the entity interface. This is needed to
avoid issues with newer versions of Resteasy.

Change-Id: Ib725ccb39a7fdcf6c418e3187b21d8e4521dfabc
Related: https://gerrit.ovirt.org/41783
Signed-off-by: Juan Hernandez <[email protected]>
---
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagResource.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagsResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResource.java
D 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAssignedTagResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResource.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResourceTest.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResourceTest.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResourceTest.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResourceTest.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResourceTest.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResourceTest.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResourceTest.java
26 files changed, 908 insertions(+), 216 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/82/41982/1

diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagResource.java
index c760f80..b3b4e43 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagResource.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagResource.java
@@ -16,14 +16,18 @@
 
 package org.ovirt.engine.api.resource;
 
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
 
 import org.ovirt.engine.api.model.Tag;
 
 @Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
 public interface AssignedTagResource {
-
     @GET
-    public Tag get();
+    Tag get();
+
+    @DELETE
+    Response remove();
 }
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagsResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagsResource.java
index 7555ac3..048caed 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagsResource.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AssignedTagsResource.java
@@ -17,7 +17,6 @@
 package org.ovirt.engine.api.resource;
 
 import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -30,18 +29,13 @@
 
 @Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
 public interface AssignedTagsResource {
-
     @GET
-    public Tags list();
+    Tags list();
 
     @POST
     @Consumes({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
-    public Response add(Tag network);
-
-    @DELETE
-    @Path("{id}")
-    public Response remove(@PathParam("id") String id);
+    Response add(Tag network);
 
     @Path("{id}")
-    public AssignedTagResource getAssignedTagSubResource(@PathParam("id") 
String id);
+    AssignedTagResource getAssignedTagSubResource(@PathParam("id") String id);
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResource.java
index ed10bd2..648b4ef 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResource.java
@@ -8,7 +8,8 @@
 
 import org.ovirt.engine.api.model.BaseResource;
 import org.ovirt.engine.api.model.Tag;
-import org.ovirt.engine.api.resource.AssignedTagResource;
+import org.ovirt.engine.api.resource.AssignedTagsResource;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
 import org.ovirt.engine.core.common.action.TagsActionParametersBase;
 import org.ovirt.engine.core.common.action.VdcActionType;
 import org.ovirt.engine.core.common.businessentities.Tags;
@@ -18,39 +19,31 @@
 import org.ovirt.engine.core.compat.Guid;
 
 public abstract class AbstractBackendAssignedTagsResource
-    extends AbstractBackendCollectionResource<Tag, Tags> {
+    extends AbstractBackendCollectionResource<Tag, Tags>
+    implements AssignedTagsResource {
 
     protected Class<? extends BaseResource> parentType;
     protected String parentId;
     protected VdcActionType attachAction;
-    protected VdcActionType detachAction;
 
     public AbstractBackendAssignedTagsResource(Class<? extends BaseResource> 
parentType,
                                                String parentId,
-                                               VdcActionType attachAction,
-                                               VdcActionType detachAction) {
+                                               VdcActionType attachAction) {
         super(Tag.class, Tags.class);
         this.parentType = parentType;
         this.parentId = parentId;
         this.attachAction = attachAction;
-        this.detachAction = detachAction;
     }
 
     public String getParentId() {
         return parentId;
     }
 
-    public VdcActionType getAttachAction() {
-        return attachAction;
-    }
-
-    public VdcActionType getDetachAction() {
-        return detachAction;
-    }
-
     protected abstract List<Tags> getCollection();
 
-    protected abstract TagsActionParametersBase getAttachParams(String id);
+    private TagsActionParametersBase getAttachParams(String id) {
+        return new AttachEntityToTagParameters(asGuid(id), 
asList(asGuid(parentId)));
+    }
 
     public org.ovirt.engine.api.model.Tags list() {
         org.ovirt.engine.api.model.Tags ret = new 
org.ovirt.engine.api.model.Tags();
@@ -67,19 +60,13 @@
             tag = lookupTagByName(tag.getName());
         }
 
-        return performCreate(attachAction,
-                               getAttachParams(tag.getId()),
-                               new TagIdResolver(asGuid(tag.getId())));
+        return performCreate(attachAction, getAttachParams(tag.getId()), new 
TagIdResolver(asGuid(tag.getId())));
     }
+
 
     @Override
-    public Response performRemove(String id) {
-        return performAction(detachAction, getAttachParams(id));
-    }
-
-    @SingleEntityResource
-    public AssignedTagResource getAssignedTagSubResource(String id) {
-        return inject(new BackendAssignedTagResource(id, this));
+    protected Tag doPopulate(Tag model, Tags entity) {
+        return model;
     }
 
     @Override
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAssignedTagResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAssignedTagResource.java
deleted file mode 100644
index 662ee53..0000000
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAssignedTagResource.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.ovirt.engine.api.restapi.resource;
-
-import org.ovirt.engine.api.model.Tag;
-import org.ovirt.engine.api.resource.AssignedTagResource;
-import org.ovirt.engine.core.common.businessentities.Tags;
-
-public class BackendAssignedTagResource
-    extends AbstractBackendSubResource<Tag, Tags>
-    implements AssignedTagResource {
-
-    private AbstractBackendAssignedTagsResource parent;
-
-    public BackendAssignedTagResource(String id, 
AbstractBackendAssignedTagsResource parent) {
-        super(id, Tag.class, Tags.class);
-        this.parent = parent;
-    }
-
-    public AbstractBackendAssignedTagsResource getParent() {
-        return parent;
-    }
-
-    @Override
-    public Tag get() {
-        return addLinks(map(parent.lookupTagById(guid)));
-    }
-
-    @Override
-    protected Tag addParents(Tag tag) {
-        return parent.addParents(tag);
-    }
-
-    @Override
-    protected Tag doPopulate(Tag model, Tags entity) {
-        return model;
-    }
-}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResource.java
new file mode 100644
index 0000000..cd34572
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResource.java
@@ -0,0 +1,60 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.Group;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.api.resource.AssignedTagResource;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByUserGroupIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class BackendGroupTagResource extends AbstractBackendSubResource<Tag, 
Tags> implements AssignedTagResource {
+    private Guid groupId;
+
+    public BackendGroupTagResource(Guid groupId, String tagId) {
+        super(tagId, Tag.class, Tags.class);
+        this.groupId = groupId;
+    }
+
+    @Override
+    public Tag get() {
+        List<Tags> tags = getBackendCollection(
+            Tags.class,
+            VdcQueryType.GetTagsByUserGroupId,
+            new GetTagsByUserGroupIdParameters(groupId.toString())
+        );
+        for (Tags tag : tags) {
+            if (tag.gettag_id().equals(guid)) {
+                return addLinks(populate(map(tag, null), tag));
+            }
+        }
+        return notFound();
+    }
+
+    @Override
+    protected Tag doPopulate(Tag model, Tags entity) {
+        return model;
+    }
+
+    @Override
+    protected Tag addParents(Tag tag) {
+        Group group = new Group();
+        group.setId(groupId.toString());
+        tag.setGroup(group);
+        return tag;
+    }
+
+    @Override
+    public Response remove() {
+        get();
+        return performAction(
+            VdcActionType.DetachUserGroupFromTag,
+            new AttachEntityToTagParameters(guid, asList(groupId))
+        );
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResource.java
index 686f644..60e300f 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResource.java
@@ -3,33 +3,25 @@
 import java.util.List;
 
 import org.ovirt.engine.api.model.Group;
-import org.ovirt.engine.api.model.Tag;
-import org.ovirt.engine.api.resource.AssignedTagsResource;
-import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
-import org.ovirt.engine.core.common.action.TagsActionParametersBase;
+import org.ovirt.engine.api.resource.AssignedTagResource;
 import org.ovirt.engine.core.common.action.VdcActionType;
 import org.ovirt.engine.core.common.businessentities.Tags;
 import org.ovirt.engine.core.common.queries.GetTagsByUserGroupIdParameters;
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 
-public class BackendGroupTagsResource
-    extends AbstractBackendAssignedTagsResource
-    implements AssignedTagsResource {
+import javax.ws.rs.PathParam;
 
+public class BackendGroupTagsResource extends 
AbstractBackendAssignedTagsResource {
     public BackendGroupTagsResource(String parentId) {
-        super(Group.class, parentId, VdcActionType.AttachUserGroupToTag, 
VdcActionType.DetachUserGroupFromTag);
+        super(Group.class, parentId, VdcActionType.AttachUserGroupToTag);
     }
 
     public List<Tags> getCollection() {
         return getBackendCollection(VdcQueryType.GetTagsByUserGroupId, new 
GetTagsByUserGroupIdParameters(parentId));
     }
 
-    protected TagsActionParametersBase getAttachParams(String id) {
-        return new AttachEntityToTagParameters(asGuid(id), 
asList(asGuid(parentId)));
-    }
-
     @Override
-    protected Tag doPopulate(Tag model, Tags entity) {
-        return model;
+    public AssignedTagResource getAssignedTagSubResource(@PathParam("id") 
String id) {
+        return inject(new BackendGroupTagResource(asGuid(parentId), id));
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResource.java
new file mode 100644
index 0000000..ceb80ee
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResource.java
@@ -0,0 +1,58 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.Host;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.api.resource.AssignedTagResource;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByVdsIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class BackendHostTagResource extends AbstractBackendSubResource<Tag, 
Tags> implements AssignedTagResource {
+    private Guid hostId;
+
+    public BackendHostTagResource(Guid hostId, String tagId) {
+        super(tagId, Tag.class, Tags.class);
+        this.hostId = hostId;
+    }
+
+    @Override
+    public Tag get() {
+        List<Tags> tags = getBackendCollection(
+            Tags.class,
+            VdcQueryType.GetTagsByVdsId,
+            new GetTagsByVdsIdParameters(hostId.toString())
+        );
+        for (Tags tag : tags) {
+            if (tag.gettag_id().equals(guid)) {
+                return addLinks(populate(map(tag, null), tag));
+            }
+        }
+        return notFound();
+    }
+
+    @Override
+    protected Tag doPopulate(Tag model, Tags entity) {
+        return model;
+    }
+
+
+    @Override
+    protected Tag addParents(Tag tag) {
+        Host host = new Host();
+        host.setId(hostId.toString());
+        tag.setHost(host);
+        return tag;
+    }
+
+    @Override
+    public Response remove() {
+        get();
+        return performAction(VdcActionType.DetachVdsFromTag, new 
AttachEntityToTagParameters(guid, asList(hostId)));
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResource.java
index 6f488eb..a1bead5 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResource.java
@@ -3,33 +3,25 @@
 import java.util.List;
 
 import org.ovirt.engine.api.model.Host;
-import org.ovirt.engine.api.model.Tag;
-import org.ovirt.engine.api.resource.AssignedTagsResource;
+import org.ovirt.engine.api.resource.AssignedTagResource;
 import org.ovirt.engine.core.common.businessentities.Tags;
-import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
-import org.ovirt.engine.core.common.action.TagsActionParametersBase;
 import org.ovirt.engine.core.common.action.VdcActionType;
 import org.ovirt.engine.core.common.queries.GetTagsByVdsIdParameters;
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 
-public class BackendHostTagsResource
-    extends AbstractBackendAssignedTagsResource
-    implements AssignedTagsResource {
+import javax.ws.rs.PathParam;
 
+public class BackendHostTagsResource extends 
AbstractBackendAssignedTagsResource {
     public BackendHostTagsResource(String parentId) {
-        super(Host.class, parentId, VdcActionType.AttachVdsToTag, 
VdcActionType.DetachVdsFromTag);
+        super(Host.class, parentId, VdcActionType.AttachVdsToTag);
     }
 
     public List<Tags> getCollection() {
         return getBackendCollection(VdcQueryType.GetTagsByVdsId, new 
GetTagsByVdsIdParameters(parentId));
     }
 
-    protected TagsActionParametersBase getAttachParams(String id) {
-        return new AttachEntityToTagParameters(asGuid(id), 
asList(asGuid(parentId)));
-    }
-
     @Override
-    protected Tag doPopulate(Tag model, Tags entity) {
-        return model;
+    public AssignedTagResource getAssignedTagSubResource(@PathParam("id") 
String id) {
+        return inject(new BackendHostTagResource(asGuid(parentId), id));
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResource.java
new file mode 100644
index 0000000..9de16e6
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResource.java
@@ -0,0 +1,57 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.api.model.Template;
+import org.ovirt.engine.api.resource.AssignedTagResource;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByTemplateIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class BackendTemplateTagResource extends 
AbstractBackendSubResource<Tag, Tags> implements AssignedTagResource {
+    private Guid templateId;
+
+    public BackendTemplateTagResource(Guid templateId, String tagId) {
+        super(tagId, Tag.class, Tags.class);
+        this.templateId = templateId;
+    }
+
+    @Override
+    public Tag get() {
+        List<Tags> tags = getBackendCollection(
+            Tags.class,
+            VdcQueryType.GetTagsByTemplateId,
+            new GetTagsByTemplateIdParameters(templateId.toString())
+        );
+        for (Tags tag : tags) {
+            if (tag.gettag_id().equals(guid)) {
+                return addLinks(populate(map(tag, null), tag));
+            }
+        }
+        return notFound();
+    }
+
+    @Override
+    protected Tag doPopulate(Tag model, Tags entity) {
+        return model;
+    }
+
+    @Override
+    protected Tag addParents(Tag tag) {
+        Template template = new Template();
+        template.setId(templateId.toString());
+        tag.setTemplate(template);
+        return tag;
+    }
+
+    @Override
+    public Response remove() {
+        get();
+        return performAction(VdcActionType.DetachTemplateFromTag, new 
AttachEntityToTagParameters(guid, asList(templateId)));
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResource.java
index 9ed139b..e0b50ce 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResource.java
@@ -1,35 +1,27 @@
 package org.ovirt.engine.api.restapi.resource;
 
-import org.ovirt.engine.api.model.Tag;
 import org.ovirt.engine.api.model.Template;
-import org.ovirt.engine.api.resource.AssignedTagsResource;
-import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
-import org.ovirt.engine.core.common.action.TagsActionParametersBase;
+import org.ovirt.engine.api.resource.AssignedTagResource;
 import org.ovirt.engine.core.common.action.VdcActionType;
 import org.ovirt.engine.core.common.businessentities.Tags;
 import org.ovirt.engine.core.common.queries.GetTagsByTemplateIdParameters;
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 
+import javax.ws.rs.PathParam;
 import java.util.List;
 
-public class BackendTemplateTagsResource
-    extends AbstractBackendAssignedTagsResource
-    implements AssignedTagsResource {
+public class BackendTemplateTagsResource extends 
AbstractBackendAssignedTagsResource {
 
     public BackendTemplateTagsResource(String parentId) {
-        super(Template.class, parentId, VdcActionType.AttachTemplatesToTag, 
VdcActionType.DetachTemplateFromTag);
+        super(Template.class, parentId, VdcActionType.AttachTemplatesToTag);
     }
 
     public List<Tags> getCollection() {
         return getBackendCollection(VdcQueryType.GetTagsByTemplateId, new 
GetTagsByTemplateIdParameters(parentId));
     }
 
-    protected TagsActionParametersBase getAttachParams(String id) {
-        return new AttachEntityToTagParameters(asGuid(id), 
asList(asGuid(parentId)));
-    }
-
     @Override
-    protected Tag doPopulate(Tag model, Tags entity) {
-        return model;
+    public AssignedTagResource getAssignedTagSubResource(@PathParam("id") 
String id) {
+        return inject(new BackendTemplateTagResource(asGuid(parentId), id));
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResource.java
new file mode 100644
index 0000000..4d5870f
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResource.java
@@ -0,0 +1,57 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.api.model.User;
+import org.ovirt.engine.api.resource.AssignedTagResource;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByUserIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class BackendUserTagResource extends AbstractBackendSubResource<Tag, 
Tags> implements AssignedTagResource {
+    private Guid userId;
+
+    public BackendUserTagResource(Guid userId, String tagId) {
+        super(tagId, Tag.class, Tags.class);
+        this.userId = userId;
+    }
+
+    @Override
+    public Tag get() {
+        List<Tags> tags = getBackendCollection(
+            Tags.class,
+            VdcQueryType.GetTagsByUserId,
+            new GetTagsByUserIdParameters(userId.toString())
+        );
+        for (Tags tag : tags) {
+            if (tag.gettag_id().equals(guid)) {
+                return addLinks(populate(map(tag, null), tag));
+            }
+        }
+        return notFound();
+    }
+
+    @Override
+    protected Tag doPopulate(Tag model, Tags entity) {
+        return model;
+    }
+
+    @Override
+    protected Tag addParents(Tag tag) {
+        User user = new User();
+        user.setId(userId.toString());
+        tag.setUser(user);
+        return tag;
+    }
+
+    @Override
+    public Response remove() {
+        get();
+        return performAction(VdcActionType.DetachUserFromTag, new 
AttachEntityToTagParameters(guid, asList(userId)));
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResource.java
index b79538f..946e3a1 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResource.java
@@ -2,34 +2,26 @@
 
 import java.util.List;
 
-import org.ovirt.engine.api.model.Tag;
 import org.ovirt.engine.api.model.User;
-import org.ovirt.engine.api.resource.AssignedTagsResource;
-import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
-import org.ovirt.engine.core.common.action.TagsActionParametersBase;
+import org.ovirt.engine.api.resource.AssignedTagResource;
 import org.ovirt.engine.core.common.action.VdcActionType;
 import org.ovirt.engine.core.common.businessentities.Tags;
 import org.ovirt.engine.core.common.queries.GetTagsByUserIdParameters;
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 
-public class BackendUserTagsResource
-    extends AbstractBackendAssignedTagsResource
-    implements AssignedTagsResource {
+import javax.ws.rs.PathParam;
 
+public class BackendUserTagsResource extends 
AbstractBackendAssignedTagsResource {
     public BackendUserTagsResource(String parentId) {
-        super(User.class, parentId, VdcActionType.AttachUserToTag, 
VdcActionType.DetachUserFromTag);
+        super(User.class, parentId, VdcActionType.AttachUserToTag);
     }
 
     public List<Tags> getCollection() {
         return getBackendCollection(VdcQueryType.GetTagsByUserId, new 
GetTagsByUserIdParameters(parentId));
     }
 
-    protected TagsActionParametersBase getAttachParams(String id) {
-        return new AttachEntityToTagParameters(asGuid(id), 
asList(asGuid(parentId)));
-    }
-
     @Override
-    protected Tag doPopulate(Tag model, Tags entity) {
-        return model;
+    public AssignedTagResource getAssignedTagSubResource(@PathParam("id") 
String id) {
+        return inject(new BackendUserTagResource(asGuid(parentId), id));
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResource.java
new file mode 100644
index 0000000..d903595
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResource.java
@@ -0,0 +1,57 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.api.model.VM;
+import org.ovirt.engine.api.resource.AssignedTagResource;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByVmIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class BackendVmTagResource extends AbstractBackendSubResource<Tag, 
Tags> implements AssignedTagResource {
+    private Guid vmId;
+
+    public BackendVmTagResource(Guid vmId, String tagId) {
+        super(tagId, Tag.class, Tags.class);
+        this.vmId = vmId;
+    }
+
+    @Override
+    public Tag get() {
+        List<Tags> tags = getBackendCollection(
+            Tags.class,
+            VdcQueryType.GetTagsByVmId,
+            new GetTagsByVmIdParameters(vmId.toString())
+        );
+        for (Tags tag : tags) {
+            if (tag.gettag_id().equals(guid)) {
+                return addLinks(populate(map(tag, null), tag));
+            }
+        }
+        return notFound();
+    }
+
+    @Override
+    protected Tag doPopulate(Tag model, Tags entity) {
+        return model;
+    }
+
+    @Override
+    protected Tag addParents(Tag tag) {
+        VM vm = new VM();
+        vm.setId(vmId.toString());
+        tag.setVm(vm);
+        return tag;
+    }
+
+    @Override
+    public Response remove() {
+        get();
+        return performAction(VdcActionType.DetachVmFromTag, new 
AttachEntityToTagParameters(guid, asList(vmId)));
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResource.java
index 1818ee0..a0ce25b 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResource.java
@@ -2,34 +2,26 @@
 
 import java.util.List;
 
-import org.ovirt.engine.api.model.Tag;
 import org.ovirt.engine.api.model.VM;
-import org.ovirt.engine.api.resource.AssignedTagsResource;
+import org.ovirt.engine.api.resource.AssignedTagResource;
 import org.ovirt.engine.core.common.businessentities.Tags;
-import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
-import org.ovirt.engine.core.common.action.TagsActionParametersBase;
 import org.ovirt.engine.core.common.action.VdcActionType;
 import org.ovirt.engine.core.common.queries.GetTagsByVmIdParameters;
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 
-public class BackendVmTagsResource
-    extends AbstractBackendAssignedTagsResource
-    implements AssignedTagsResource {
+import javax.ws.rs.PathParam;
 
+public class BackendVmTagsResource extends AbstractBackendAssignedTagsResource 
{
     public BackendVmTagsResource(String parentId) {
-        super(VM.class, parentId, VdcActionType.AttachVmsToTag, 
VdcActionType.DetachVmFromTag);
+        super(VM.class, parentId, VdcActionType.AttachVmsToTag);
     }
 
     public List<Tags> getCollection() {
         return getBackendCollection(VdcQueryType.GetTagsByVmId, new 
GetTagsByVmIdParameters(parentId));
     }
 
-    protected TagsActionParametersBase getAttachParams(String id) {
-        return new AttachEntityToTagParameters(asGuid(id), 
asList(asGuid(parentId)));
-    }
-
     @Override
-    protected Tag doPopulate(Tag model, Tags entity) {
-        return model;
+    public AssignedTagResource getAssignedTagSubResource(@PathParam("id") 
String id) {
+        return inject(new BackendVmTagResource(asGuid(parentId), id));
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResourceTest.java
index cb110b5..3848b1b 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendAssignedTagsResourceTest.java
@@ -26,7 +26,6 @@
     protected static VdcQueryType queryType;
     protected static Class<? extends VdcQueryParametersBase> queryParams;
     protected static VdcActionType attachAction;
-    protected static VdcActionType detachAction;
     protected static Class<? extends TagsActionParametersBase> attachParams;
 
     public AbstractBackendAssignedTagsResourceTest(C collection) {
@@ -43,76 +42,10 @@
     public void testBadGuid() throws Exception {
         control.replay();
         try {
-            new BackendAssignedTagResource("foo", null);
+            collection.getAssignedTagSubResource("foo");
             fail("expected WebApplicationException");
         } catch (WebApplicationException wae) {
             verifyNotFoundException(wae);
-        }
-    }
-
-    @Test
-    public void testRemove() throws Exception {
-        setUpGetEntityExpectations(GUIDS[0]);
-        setUriInfo(setUpActionExpectations(detachAction,
-                                           attachParams,
-                                           new String[] { "TagId", 
"EntitiesId" },
-                                           new Object[] { GUIDS[0], 
asList(PARENT_GUID) },
-                                           true,
-                                           true));
-        verifyRemove(collection.remove(GUIDS[0].toString()));
-    }
-
-    private void setUpGetEntityExpectations(Guid guid) throws Exception {
-        setUpGetEntityExpectations(guid, false);
-    }
-
-    private void setUpGetEntityExpectations(Guid entityId, boolean returnNull) 
throws Exception {
-        String[] names = {"Id"};
-        Object[] values = {entityId};
-        Tags tag = null;
-        if (!returnNull) {
-            tag = new Tags();
-            tag.settag_id(entityId);
-        }
-        setUpGetEntityExpectations(VdcQueryType.GetTagByTagId, 
IdQueryParameters.class, names, values, tag);
-    }
-
-    @Test
-    public void testRemoveCantDo() throws Exception {
-        doTestBadRemove(false, true, CANT_DO);
-    }
-
-    @Test
-    public void testRemoveFailed() throws Exception {
-        doTestBadRemove(true, false, FAILURE);
-    }
-
-    protected void doTestBadRemove(boolean canDo, boolean success, String 
detail) throws Exception {
-        setUpGetEntityExpectations(GUIDS[0]);
-        setUriInfo(setUpActionExpectations(detachAction,
-                                           attachParams,
-                                           new String[] { "TagId", 
"EntitiesId" },
-                                           new Object[] { GUIDS[0], 
asList(PARENT_GUID) },
-                                           canDo,
-                                           success));
-        try {
-            collection.remove(GUIDS[0].toString());
-            fail("expected WebApplicationException");
-        } catch (WebApplicationException wae) {
-            verifyFault(wae, detail);
-        }
-    }
-
-    @Test
-    public void testRemoveNonExistant() throws Exception{
-        setUpGetEntityExpectations(NON_EXISTANT_GUID, true);
-        control.replay();
-        try {
-            collection.remove(NON_EXISTANT_GUID.toString());
-            fail("expected WebApplicationException");
-        } catch (WebApplicationException wae) {
-            assertNotNull(wae.getResponse());
-            assertEquals(wae.getResponse().getStatus(), 404);
         }
     }
 
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendResourceTest.java
index 735e337..c0e1b61 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendResourceTest.java
@@ -10,7 +10,9 @@
         initBackendResource(resource);
     }
 
-    protected abstract Q getEntity(int index);
+    protected Q getEntity(int index) {
+        throw new UnsupportedOperationException();
+    }
 
     protected void verifyModel(R model, int index) {
         assertEquals(GUIDS[index].toString(), model.getId());
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResourceTest.java
new file mode 100644
index 0000000..21d0283
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagResourceTest.java
@@ -0,0 +1,112 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.junit.Test;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByUserGroupIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendGroupTagResourceTest extends 
AbstractBackendSubResourceTest<Tag, Tags, BackendGroupTagResource> {
+    private static final Guid GROUP_ID = GUIDS[0];
+    private static final Guid TAG_ID = GUIDS[1];
+
+    public BackendGroupTagResourceTest() {
+        super(new BackendGroupTagResource(GROUP_ID, TAG_ID.toString()));
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        setUpGetTagExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachUserGroupFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(GROUP_ID) },
+                true,
+                true
+            )
+        );
+        verifyRemove(resource.remove());
+    }
+
+    @Test
+    public void testRemoveCantDo() throws Exception {
+        doTestBadRemove(false, true, CANT_DO);
+    }
+
+    @Test
+    public void testRemoveFailed() throws Exception {
+        doTestBadRemove(true, false, FAILURE);
+    }
+
+    private void doTestBadRemove(boolean canDo, boolean success, String 
detail) throws Exception {
+        setUpGetTagExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachUserGroupFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(GROUP_ID) },
+                canDo,
+                success));
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyFault(wae, detail);
+        }
+    }
+
+    @Test
+    public void testRemoveNonExistant() throws Exception{
+        setUpGetTagExpectations(false);
+        control.replay();
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            assertNotNull(wae.getResponse());
+            assertEquals(wae.getResponse().getStatus(), 404);
+        }
+    }
+
+    private void setUpGetTagExpectations(boolean succeed) throws Exception {
+        setUpGetEntityExpectations(
+            VdcQueryType.GetTagsByUserGroupId,
+            GetTagsByUserGroupIdParameters.class,
+            new String[] { "GroupId" },
+            new Object[] { GROUP_ID.toString() },
+            succeed? setUpTagsExpectations(): Collections.emptyList()
+        );
+    }
+
+    private List<Tags> setUpTagsExpectations() {
+        List<Tags> tags = new ArrayList<>();
+        for (int i = 0; i < GUIDS.length; i++) {
+            Tags tag = setUpTagExpectations(GUIDS[i]);
+            tags.add(tag);
+        }
+        return tags;
+    }
+
+    private Tags setUpTagExpectations(Guid tagId) {
+        Tags mock = control.createMock(Tags.class);
+        expect(mock.gettag_id()).andReturn(tagId).anyTimes();
+        expect(mock.getparent_id()).andReturn(GROUP_ID).anyTimes();
+        return mock;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResourceTest.java
index d4ddc39..e5dd8e1 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendGroupTagsResourceTest.java
@@ -12,7 +12,6 @@
         queryType = VdcQueryType.GetTagsByUserGroupId;
         queryParams = GetTagsByUserGroupIdParameters.class;
         attachAction = VdcActionType.AttachUserGroupToTag;
-        detachAction = VdcActionType.DetachUserGroupFromTag;
         attachParams = AttachEntityToTagParameters.class;
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResourceTest.java
new file mode 100644
index 0000000..a514377
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagResourceTest.java
@@ -0,0 +1,112 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.junit.Test;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByVdsIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendHostTagResourceTest extends 
AbstractBackendSubResourceTest<Tag, Tags, BackendHostTagResource> {
+    private static final Guid HOST_ID = GUIDS[0];
+    private static final Guid TAG_ID = GUIDS[1];
+
+    public BackendHostTagResourceTest() {
+        super(new BackendHostTagResource(HOST_ID, TAG_ID.toString()));
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        setUpGetTagExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachVdsFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(HOST_ID) },
+                true,
+                true
+            )
+        );
+        verifyRemove(resource.remove());
+    }
+
+    @Test
+    public void testRemoveCantDo() throws Exception {
+        doTestBadRemove(false, true, CANT_DO);
+    }
+
+    @Test
+    public void testRemoveFailed() throws Exception {
+        doTestBadRemove(true, false, FAILURE);
+    }
+
+    private void doTestBadRemove(boolean canDo, boolean success, String 
detail) throws Exception {
+        setUpGetTagExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachVdsFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(HOST_ID) },
+                canDo,
+                success));
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyFault(wae, detail);
+        }
+    }
+
+    @Test
+    public void testRemoveNonExistant() throws Exception{
+        setUpGetTagExpectations(false);
+        control.replay();
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            assertNotNull(wae.getResponse());
+            assertEquals(wae.getResponse().getStatus(), 404);
+        }
+    }
+
+    private void setUpGetTagExpectations(boolean succeed) throws Exception {
+        setUpGetEntityExpectations(
+            VdcQueryType.GetTagsByVdsId,
+            GetTagsByVdsIdParameters.class,
+            new String[] { "VdsId" },
+            new Object[] { HOST_ID.toString() },
+            succeed? setUpTagsExpectations(): Collections.emptyList()
+        );
+    }
+
+    private List<Tags> setUpTagsExpectations() {
+        List<Tags> tags = new ArrayList<>();
+        for (int i = 0; i < GUIDS.length; i++) {
+            Tags tag = setUpTagExpectations(GUIDS[i]);
+            tags.add(tag);
+        }
+        return tags;
+    }
+
+    private Tags setUpTagExpectations(Guid tagId) {
+        Tags mock = control.createMock(Tags.class);
+        expect(mock.gettag_id()).andReturn(tagId).anyTimes();
+        expect(mock.getparent_id()).andReturn(HOST_ID).anyTimes();
+        return mock;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResourceTest.java
index f8b2772..29c9aba 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostTagsResourceTest.java
@@ -12,7 +12,6 @@
         queryType = VdcQueryType.GetTagsByVdsId;
         queryParams = GetTagsByVdsIdParameters.class;
         attachAction = VdcActionType.AttachVdsToTag;
-        detachAction = VdcActionType.DetachVdsFromTag;
         attachParams = AttachEntityToTagParameters.class;
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResourceTest.java
new file mode 100644
index 0000000..d7a8051
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagResourceTest.java
@@ -0,0 +1,114 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.junit.Test;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByTemplateIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendTemplateTagResourceTest
+    extends AbstractBackendSubResourceTest<Tag, Tags, 
BackendTemplateTagResource> {
+
+    private static final Guid TEMPLATE_ID = GUIDS[0];
+    private static final Guid TAG_ID = GUIDS[1];
+
+    public BackendTemplateTagResourceTest() {
+        super(new BackendTemplateTagResource(TEMPLATE_ID, TAG_ID.toString()));
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        setUpGetTagsExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachTemplateFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(TEMPLATE_ID) },
+                true,
+                true
+            )
+        );
+        verifyRemove(resource.remove());
+    }
+
+    @Test
+    public void testRemoveCantDo() throws Exception {
+        doTestBadRemove(false, true, CANT_DO);
+    }
+
+    @Test
+    public void testRemoveFailed() throws Exception {
+        doTestBadRemove(true, false, FAILURE);
+    }
+
+    private void doTestBadRemove(boolean canDo, boolean success, String 
detail) throws Exception {
+        setUpGetTagsExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachTemplateFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(TEMPLATE_ID) },
+                canDo,
+                success));
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyFault(wae, detail);
+        }
+    }
+
+    @Test
+    public void testRemoveNonExistant() throws Exception{
+        setUpGetTagsExpectations(false);
+        control.replay();
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            assertNotNull(wae.getResponse());
+            assertEquals(wae.getResponse().getStatus(), 404);
+        }
+    }
+
+    private void setUpGetTagsExpectations(boolean succeed) throws Exception {
+        setUpGetEntityExpectations(
+            VdcQueryType.GetTagsByTemplateId,
+            GetTagsByTemplateIdParameters.class,
+            new String[] { "TemplateId" },
+            new Object[] { TEMPLATE_ID.toString() },
+            succeed? setUpTagsExpectations(): Collections.emptyList()
+        );
+    }
+
+    private List<Tags> setUpTagsExpectations() {
+        List<Tags> tags = new ArrayList<>();
+        for (int i = 0; i < GUIDS.length; i++) {
+            Tags tag = setUpTagExpectations(GUIDS[i]);
+            tags.add(tag);
+        }
+        return tags;
+    }
+
+    private Tags setUpTagExpectations(Guid tagId) {
+        Tags mock = control.createMock(Tags.class);
+        expect(mock.gettag_id()).andReturn(tagId).anyTimes();
+        expect(mock.getparent_id()).andReturn(TEMPLATE_ID).anyTimes();
+        return mock;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResourceTest.java
index c939baf..b2a00cc 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplateTagsResourceTest.java
@@ -12,7 +12,6 @@
         queryType = VdcQueryType.GetTagsByTemplateId;
         queryParams = GetTagsByTemplateIdParameters.class;
         attachAction = VdcActionType.AttachTemplatesToTag;
-        detachAction = VdcActionType.DetachTemplateFromTag;
         attachParams = AttachEntityToTagParameters.class;
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResourceTest.java
new file mode 100644
index 0000000..e14e027
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagResourceTest.java
@@ -0,0 +1,112 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.junit.Test;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByUserIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendUserTagResourceTest extends 
AbstractBackendSubResourceTest<Tag, Tags, BackendUserTagResource> {
+    private static final Guid USER_ID = GUIDS[0];
+    private static final Guid TAG_ID = GUIDS[1];
+
+    public BackendUserTagResourceTest() {
+        super(new BackendUserTagResource(USER_ID, TAG_ID.toString()));
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        setUpGetTagExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachUserFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(USER_ID) },
+                true,
+                true
+            )
+        );
+        verifyRemove(resource.remove());
+    }
+
+    @Test
+    public void testRemoveCantDo() throws Exception {
+        doTestBadRemove(false, true, CANT_DO);
+    }
+
+    @Test
+    public void testRemoveFailed() throws Exception {
+        doTestBadRemove(true, false, FAILURE);
+    }
+
+    private void doTestBadRemove(boolean canDo, boolean success, String 
detail) throws Exception {
+        setUpGetTagExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachUserFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(USER_ID) },
+                canDo,
+                success));
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyFault(wae, detail);
+        }
+    }
+
+    @Test
+    public void testRemoveNonExistant() throws Exception{
+        setUpGetTagExpectations(false);
+        control.replay();
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            assertNotNull(wae.getResponse());
+            assertEquals(wae.getResponse().getStatus(), 404);
+        }
+    }
+
+    private void setUpGetTagExpectations(boolean succeed) throws Exception {
+        setUpGetEntityExpectations(
+            VdcQueryType.GetTagsByUserId,
+            GetTagsByUserIdParameters.class,
+            new String[] { "UserId" },
+            new Object[] { USER_ID.toString() },
+            succeed? setUpTagsExpectations(): Collections.emptyList()
+        );
+    }
+
+    private List<Tags> setUpTagsExpectations() {
+        List<Tags> tags = new ArrayList<>();
+        for (int i = 0; i < GUIDS.length; i++) {
+            Tags tag = setUpTagExpectations(GUIDS[i]);
+            tags.add(tag);
+        }
+        return tags;
+    }
+
+    private Tags setUpTagExpectations(Guid tagId) {
+        Tags mock = control.createMock(Tags.class);
+        expect(mock.gettag_id()).andReturn(tagId).anyTimes();
+        expect(mock.getparent_id()).andReturn(USER_ID).anyTimes();
+        return mock;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResourceTest.java
index f3be71b..89de428 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendUserTagsResourceTest.java
@@ -12,7 +12,6 @@
         queryType = VdcQueryType.GetTagsByUserId;
         queryParams = GetTagsByUserIdParameters.class;
         attachAction = VdcActionType.AttachUserToTag;
-        detachAction = VdcActionType.DetachUserFromTag;
         attachParams = AttachEntityToTagParameters.class;
     }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResourceTest.java
new file mode 100644
index 0000000..48f2e41
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagResourceTest.java
@@ -0,0 +1,114 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.junit.Test;
+import org.ovirt.engine.api.model.Tag;
+import org.ovirt.engine.core.common.action.AttachEntityToTagParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Tags;
+import org.ovirt.engine.core.common.queries.GetTagsByVmIdParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendVmTagResourceTest extends 
AbstractBackendSubResourceTest<Tag, Tags, BackendVmTagResource> {
+    private static final Guid VM_ID = GUIDS[0];
+    private static final Guid TAG_ID = GUIDS[1];
+
+    public BackendVmTagResourceTest() {
+        super(new BackendVmTagResource(VM_ID, TAG_ID.toString()));
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        setUpGetTagsExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachVmFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(VM_ID) },
+                true,
+                true
+            )
+        );
+        verifyRemove(resource.remove());
+    }
+
+    @Test
+    public void testRemoveCantDo() throws Exception {
+        doTestBadRemove(false, true, CANT_DO);
+    }
+
+    @Test
+    public void testRemoveFailed() throws Exception {
+        doTestBadRemove(true, false, FAILURE);
+    }
+
+    private void doTestBadRemove(boolean canDo, boolean success, String 
detail) throws Exception {
+        setUpGetTagsExpectations(true);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.DetachVmFromTag,
+                AttachEntityToTagParameters.class,
+                new String[] { "TagId", "EntitiesId" },
+                new Object[] { TAG_ID, asList(VM_ID) },
+                canDo,
+                success
+            )
+        );
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyFault(wae, detail);
+        }
+    }
+
+    @Test
+    public void testRemoveNonExistant() throws Exception{
+        setUpGetTagsExpectations(false);
+        control.replay();
+        try {
+            resource.remove();
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            assertNotNull(wae.getResponse());
+            assertEquals(wae.getResponse().getStatus(), 404);
+        }
+    }
+
+    private void setUpGetTagsExpectations(boolean succeed) throws Exception {
+        setUpGetEntityExpectations(
+            VdcQueryType.GetTagsByVmId,
+            GetTagsByVmIdParameters.class,
+            new String[] { "VmId" },
+            new Object[] { VM_ID.toString() },
+            succeed? setUpTagsExpectations(): Collections.emptyList()
+        );
+    }
+
+    private List<Tags> setUpTagsExpectations() {
+        List<Tags> tags = new ArrayList<>();
+        for (int i = 0; i < GUIDS.length; i++) {
+            Tags tag = setUpTagExpectations(GUIDS[i]);
+            tags.add(tag);
+        }
+        return tags;
+    }
+
+    private Tags setUpTagExpectations(Guid tagId) {
+        Tags mock = control.createMock(Tags.class);
+        expect(mock.gettag_id()).andReturn(tagId).anyTimes();
+        expect(mock.getparent_id()).andReturn(VM_ID).anyTimes();
+        return mock;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResourceTest.java
index 7b836be..6ceb11e 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendVmTagsResourceTest.java
@@ -12,7 +12,6 @@
         queryType = VdcQueryType.GetTagsByVmId;
         queryParams = GetTagsByVmIdParameters.class;
         attachAction = VdcActionType.AttachVmsToTag;
-        detachAction = VdcActionType.DetachVmFromTag;
         attachParams = AttachEntityToTagParameters.class;
     }
 }


-- 
To view, visit https://gerrit.ovirt.org/41982
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib725ccb39a7fdcf6c418e3187b21d8e4521dfabc
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Juan Hernandez <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to