Source:
<code>public boolean deleteTags(List<String> resourceIds, ResourceObjectType resourceType, Map<String, String> tags) { Account caller = CallContext.current().getCallingAccount(); if(s_logger.isDebugEnabled()) { s_logger.debug("ResourceIds to Find " + String.join(", ", resourceIds)); } List<? extends ResourceTag> resourceTags = searchResourceTags(resourceIds, resourceType); final List<ResourceTag> tagsToDelete = new ArrayList<>(); for (ResourceTag resourceTag : resourceTags) { if(s_logger.isDebugEnabled()) { s_logger.debug("Resource Tag Id: " + resourceTag.getResourceId()); s_logger.debug("Resource Tag AccountId: " + resourceTag.getAccountId()); } Account owner = _accountMgr.getAccount(resourceTag.getAccountId()); if(s_logger.isDebugEnabled()) { s_logger.debug("Resource Owner: " + owner); } _accountMgr.checkAccess(caller, null, false, owner); if (tags != null && !tags.isEmpty()) { for (String key : tags.keySet()) { boolean deleteTag = false; if (resourceTag.getKey().equalsIgnoreCase(key)) { String value = tags.get(key); if (value != null) { if (resourceTag.getValue().equalsIgnoreCase(value)) { deleteTag = true; } } else { deleteTag = true; } <START> if (deleteTag) { <END> tagsToDelete.add(resourceTag); break; } } } } else { tagsToDelete.add(resourceTag); } } if (tagsToDelete.isEmpty()) { throw new InvalidParameterValueException("Unable to find any tags which conform to specified delete parameters."); } Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { for (ResourceTag tagToRemove : tagsToDelete) { _resourceTagDao.remove(tagToRemove.getId()); s_logger.debug("Removed the tag '" + tagToRemove + "' for resources (" + String.join(", ", resourceIds) + ")"); } } }); return true; }</code><technical_language>changing lines 343- 349 this: deleteTag = == null || resourceTag.getValue().equalsIgnoreCase(value)</technical_language>

Target:
public boolean deleteTags(List<String> resourceIds, ResourceObjectType resourceType, Map<String, String> tags) { Account caller = CallContext.current().getCallingAccount(); if(s_logger.isDebugEnabled()) { s_logger.debug("ResourceIds to Find " + String.join(", ", resourceIds)); } List<? extends ResourceTag> resourceTags = searchResourceTags(resourceIds, resourceType); final List<ResourceTag> tagsToDelete = new ArrayList<>(); for (ResourceTag resourceTag : resourceTags) { if(s_logger.isDebugEnabled()) { s_logger.debug("Resource Tag Id: " + resourceTag.getResourceId()); s_logger.debug("Resource Tag AccountId: " + resourceTag.getAccountId()); } Account owner = _accountMgr.getAccount(resourceTag.getAccountId()); if(s_logger.isDebugEnabled()) { s_logger.debug("Resource Owner: " + owner); } _accountMgr.checkAccess(caller, null, false, owner); if (MapUtils.isEmpty(tags)) { tagsToDelete.add(resourceTag); } else { for (String key : tags.keySet()) { boolean deleteTag = false; if (resourceTag.getKey().equalsIgnoreCase(key)) { String value = tags.get(key); if (value != null) { if (resourceTag.getValue().equalsIgnoreCase(value)) { deleteTag = true; } } else { deleteTag = true; } if (deleteTag) { tagsToDelete.add(resourceTag); break; } } } } } if (tagsToDelete.isEmpty()) { throw new InvalidParameterValueException("Unable to find any tags which conform to specified delete parameters."); } Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { for (ResourceTag tagToRemove : tagsToDelete) { _resourceTagDao.remove(tagToRemove.getId()); s_logger.debug("Removed the tag '" + tagToRemove + "' for resources (" + String.join(", ", resourceIds) + ")"); } } }); return true; }