This is an automated email from the ASF dual-hosted git repository.

abhi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new fb4f8d9ea RANGER-5251: dedupTags() doesn’t remove duplicate tag IDs 
within a single resource’s resourceToTagIds list (#608)
fb4f8d9ea is described below

commit fb4f8d9ea395f72b3cfe2c7936aeb67ff4ee7c16
Author: Vyom Mani Tiwari <[email protected]>
AuthorDate: Wed Jul 16 20:59:18 2025 +0530

    RANGER-5251: dedupTags() doesn’t remove duplicate tag IDs within a single 
resource’s resourceToTagIds list (#608)
---
 .../org/apache/ranger/plugin/util/ServiceTags.java |  8 ++++
 .../apache/ranger/plugin/util/TestServiceTags.java | 51 ++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
index 74b2464a8..56ac3a0d3 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
@@ -33,10 +33,12 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.Set;
 
 @JsonAutoDetect(fieldVisibility = Visibility.ANY)
 @JsonInclude(JsonInclude.Include.NON_EMPTY)
@@ -280,6 +282,7 @@ public int dedupTags() {
         final int finalTagsCount = tags.size();
 
         for (Map.Entry<Long, List<Long>> resourceEntry : 
resourceToTagIds.entrySet()) {
+            Set<Long> uniqueTagIds = new 
HashSet<>(resourceEntry.getValue().size());
             for (ListIterator<Long> listIter = 
resourceEntry.getValue().listIterator(); listIter.hasNext(); ) {
                 final Long tagId       = listIter.next();
                 Long       mappedTagId = null;
@@ -292,6 +295,11 @@ public int dedupTags() {
                     continue;
                 }
 
+                if (!uniqueTagIds.add(mappedTagId)) {
+                    listIter.remove();
+                    continue;
+                }
+
                 listIter.set(mappedTagId);
 
                 RangerTag tag = tags.get(mappedTagId);
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
index a2d52427f..7e1720518 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
@@ -23,9 +23,12 @@
 import org.junit.Test;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -205,6 +208,54 @@ public void testDedupTags_HigherIdTagAfterLowerIdRemoval() 
{
         assertFalse(svcTags1.getTags().containsKey(newTagId));
     }
 
+    @Test
+    public void testDedupTags_DuplicateResourceToTagIds() {
+        RangerTag[] tags = {
+                new RangerTag("PII", Collections.singletonMap("type", 
"email")),
+                new RangerTag("PII", Collections.singletonMap("type", 
"email")),
+                new RangerTag("PCI", Collections.emptyMap()),
+                new RangerTag("PCI", Collections.emptyMap()),
+                new RangerTag("PII", Collections.singletonMap("type", "email"))
+        };
+        ServiceTags svcTags = createServiceTags(tags, RESOURCES);
+        assertEquals(5, svcTags.getTags().size());
+
+        int dedupCount = svcTags.dedupTags();
+        assertEquals(3, dedupCount);
+        assertEquals(2, svcTags.getTags().size());
+
+        ServiceTags svcTags1 = new ServiceTags(svcTags);
+        // Simulate resource1 deletion (like delete table_1)
+        svcTags1.getResourceToTagIds().remove(0L);
+        // Clear tags to simulate new sync
+        svcTags1.getTags().clear();
+
+        RangerTag tag1 = new RangerTag("PII", Collections.singletonMap("type", 
"email"));
+        RangerTag tag2 = new RangerTag("PII", Collections.singletonMap("type", 
"email"));
+        tag1.setId(200L);
+        tag2.setId(201L);
+        svcTags1.getTags().put(200L, tag1);
+        svcTags1.getTags().put(201L, tag2);
+
+        // Set resource mappings with duplicate tag IDs
+        svcTags1.getResourceToTagIds().put(0L, new 
ArrayList<>(Arrays.asList(200L, 200L, 201L)));
+        svcTags1.getResourceToTagIds().put(1L, new 
ArrayList<>(Arrays.asList(200L, 200L, 201L, 201L)));
+
+        dedupCount = svcTags1.dedupTags();
+        assertEquals(1, dedupCount);
+        assertEquals(1, svcTags1.getTags().size());
+
+        // Verify resource1 has no duplicate tag IDs
+        List<Long> resource1Tags = svcTags1.getResourceToTagIds().get(0L);
+        Set<Long> uniqueTags = new HashSet<>(resource1Tags);
+        assertEquals("Duplicate tag IDs should be removed from resource1", 
uniqueTags.size(), resource1Tags.size());
+
+        // Verify resource2 has no duplicate tag IDs
+        List<Long> resource2Tags = svcTags1.getResourceToTagIds().get(1L);
+        uniqueTags = new HashSet<>(resource2Tags);
+        assertEquals("Duplicate tag IDs should be removed from resource2", 
uniqueTags.size(), resource2Tags.size());
+    }
+
     private ServiceTags createServiceTags(RangerTag[] tags, 
RangerServiceResource[] resources) {
         ServiceTags ret = new ServiceTags();
 

Reply via email to