in security-admin/src/main/java/org/apache/ranger/rest/ServiceTagsProcessor.java [83:409]
private void addOrUpdate(ServiceTags serviceTags) throws Exception {
LOG.debug("==> ServiceTagsProcessor.createOrUpdate()");
RangerPerfTracer perfTotal = null;
RangerPerfTracer perf = null;
Map<Long, RangerTagDef> tagDefsInStore = new HashMap<>();
Map<Long, RangerServiceResource> resourcesInStore = new HashMap<>();
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perfTotal = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.addOrUpdate()");
}
if (MapUtils.isNotEmpty(serviceTags.getTagDefinitions())) {
RangerTagDef tagDef = null;
try {
for (Map.Entry<Long, RangerTagDef> entry : serviceTags.getTagDefinitions().entrySet()) {
tagDef = entry.getValue();
RangerTagDef existing = null;
if (StringUtils.isNotEmpty(tagDef.getGuid())) {
existing = tagStore.getTagDefByGuid(tagDef.getGuid());
}
if (existing == null && StringUtils.isNotEmpty(tagDef.getName())) {
existing = tagStore.getTagDefByName(tagDef.getName());
}
RangerTagDef tagDefInStore;
if (existing == null) {
tagDefInStore = tagStore.createTagDef(tagDef);
} else {
LOG.debug("tagDef for name: {} exists, will not update it", tagDef.getName());
tagDefInStore = existing;
}
tagDefsInStore.put(entry.getKey(), tagDefInStore);
}
} catch (Exception exception) {
LOG.error("createTagDef failed, tagDef={}", tagDef, exception);
throw exception;
}
}
List<RangerServiceResource> resources = serviceTags.getServiceResources();
if (CollectionUtils.isNotEmpty(resources)) {
RangerServiceResource resource = null;
try {
for (RangerServiceResource rangerServiceResource : resources) {
resource = rangerServiceResource;
if (StringUtils.isBlank(resource.getServiceName())) {
resource.setServiceName(serviceTags.getServiceName());
}
RangerServiceResource existing = null;
Long resourceId = resource.getId();
if (StringUtils.isNotEmpty(resource.getGuid())) {
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.search_service_resource_by_guid(" + resourceId + ")");
}
existing = tagStore.getServiceResourceByGuid(resource.getGuid());
RangerPerfTracer.logAlways(perf);
}
if (existing == null) {
if (MapUtils.isNotEmpty(resource.getResourceElements())) {
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.search_service_resource_by_signature(" + resourceId + ")");
}
RangerServiceResourceSignature serializer = new RangerServiceResourceSignature(resource);
String resourceSignature = serializer.getSignature();
resource.setResourceSignature(resourceSignature);
existing = tagStore.getServiceResourceByServiceAndResourceSignature(resource.getServiceName(), resourceSignature);
RangerPerfTracer.logAlways(perf);
}
}
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.createOrUpdate_service_resource(" + resourceId + ")");
}
RangerServiceResource resourceInStore;
if (existing == null) {
resourceInStore = tagStore.createServiceResource(resource);
} else if (StringUtils.isEmpty(resource.getServiceName()) || MapUtils.isEmpty(resource.getResourceElements())) {
resourceInStore = existing;
} else {
resource.setId(existing.getId());
resource.setGuid(existing.getGuid());
resourceInStore = tagStore.updateServiceResource(resource);
}
resourcesInStore.put(resourceId, resourceInStore);
RangerPerfTracer.logAlways(perf);
}
} catch (Exception exception) {
LOG.error("createServiceResource failed, resource={}", resource, exception);
throw exception;
}
}
if (MapUtils.isNotEmpty(serviceTags.getResourceToTagIds())) {
for (Map.Entry<Long, List<Long>> entry : serviceTags.getResourceToTagIds().entrySet()) {
Long resourceId = entry.getKey();
RangerServiceResource resourceInStore = resourcesInStore.get(resourceId);
if (resourceInStore == null) {
LOG.error("Resource (id={}) not found. Skipping tags update", resourceId);
continue;
}
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.get_tags_for_service_resource(" + resourceInStore.getId() + ")");
}
// Get all tags associated with this resourceId
List<RangerTag> associatedTags;
try {
associatedTags = tagStore.getTagsForResourceId(resourceInStore.getId());
} catch (Exception exception) {
LOG.error("RangerTags cannot be retrieved for resource with guid={}", resourceInStore.getGuid());
throw exception;
} finally {
RangerPerfTracer.logAlways(perf);
}
List<RangerTag> tagsToRetain = new ArrayList<>();
boolean isAnyTagUpdated = false;
List<Long> tagIds = entry.getValue();
try {
for (Long tagId : tagIds) {
RangerTag incomingTag = MapUtils.isNotEmpty(serviceTags.getTags()) ? serviceTags.getTags().get(tagId) : null;
if (incomingTag == null) {
LOG.error("Tag (id={}) not found. Skipping addition of this tag for resource (id={})", tagId, resourceId);
continue;
}
RangerTag matchingTag = findMatchingTag(incomingTag, associatedTags);
if (matchingTag == null) {
LOG.debug("Did not find matching tag for tagId={}", tagId);
// create new tag from incoming tag and associate it with service-resource
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.create_tag(" + tagId + ")");
}
RangerTag newTag = tagStore.createTag(incomingTag);
RangerPerfTracer.logAlways(perf);
RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();
tagResourceMap.setTagId(newTag.getId());
tagResourceMap.setResourceId(resourceInStore.getId());
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.create_tagResourceMap(" + tagId + ")");
}
tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);
RangerPerfTracer.logAlways(perf);
associatedTags.add(newTag);
tagsToRetain.add(newTag);
} else {
LOG.debug("Found matching tag for tagId={}, matchingTag={}", tagId, matchingTag);
if (isResourcePrivateTag(incomingTag)) {
if (!isResourcePrivateTag(matchingTag)) {
// create new tag from incoming tag and associate it with service-resource
RangerTag newTag = tagStore.createTag(incomingTag);
RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();
tagResourceMap.setTagId(newTag.getId());
tagResourceMap.setResourceId(resourceInStore.getId());
tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);
associatedTags.add(newTag);
tagsToRetain.add(newTag);
} else {
tagsToRetain.add(matchingTag);
boolean isTagUpdateNeeded = false;
// Note that as there is no easy way to check validityPeriods for equality, an easy way to rule out the possibility of validityPeriods
// not matching is to check if both old and new tags have empty validityPeriods
if (matchingTag.getGuid() != null && matchingTag.getGuid().equals(incomingTag.getGuid())) {
if (isMatch(incomingTag, matchingTag) && CollectionUtils.isEmpty(incomingTag.getValidityPeriods()) && CollectionUtils.isEmpty(matchingTag.getValidityPeriods())) {
LOG.debug("No need to update existing-tag:[{}] with incoming-tag:[{}]", matchingTag, incomingTag);
} else {
isTagUpdateNeeded = true;
}
} else {
if (CollectionUtils.isEmpty(incomingTag.getValidityPeriods()) && CollectionUtils.isEmpty(matchingTag.getValidityPeriods())) {
// Completely matched tags. No need to update
LOG.debug("No need to update existing-tag:[{}] with incoming-tag:[{}]", matchingTag, incomingTag);
} else {
isTagUpdateNeeded = true;
}
}
if (isTagUpdateNeeded) {
// Keep this tag, and update it with attribute-values and validity schedules from incoming tag
LOG.debug("Updating existing private tag with id={}", matchingTag.getId());
incomingTag.setId(matchingTag.getId());
tagStore.updateTag(incomingTag);
isAnyTagUpdated = true;
}
}
} else { // shared model
if (isResourcePrivateTag(matchingTag)) {
// create new tag from incoming tag and associate it with service-resource
RangerTag newTag = tagStore.createTag(incomingTag);
RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();
tagResourceMap.setTagId(newTag.getId());
tagResourceMap.setResourceId(resourceInStore.getId());
tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);
associatedTags.add(newTag);
tagsToRetain.add(newTag);
} else {
// Keep this tag, but update it with attribute-values from incoming tag
tagsToRetain.add(matchingTag);
// Update shared tag with new values
incomingTag.setId(matchingTag.getId());
tagStore.updateTag(incomingTag);
// associate with service-resource if not already associated
if (findTagInList(matchingTag, associatedTags) == null) {
RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();
tagResourceMap.setTagId(matchingTag.getId());
tagResourceMap.setResourceId(resourceInStore.getId());
tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);
} else {
isAnyTagUpdated = true;
}
}
}
}
}
} catch (Exception exception) {
LOG.error("createRangerTagResourceMap failed", exception);
throw exception;
}
if (CollectionUtils.isNotEmpty(associatedTags)) {
Long tagId = null;
try {
for (RangerTag associatedTag : associatedTags) {
if (findTagInList(associatedTag, tagsToRetain) == null) {
tagId = associatedTag.getId();
RangerTagResourceMap tagResourceMap = tagStore.getTagResourceMapForTagAndResourceId(tagId, resourceInStore.getId());
if (tagResourceMap != null) {
tagStore.deleteTagResourceMap(tagResourceMap.getId());
}
LOG.debug("Deleted tagResourceMap(tagId={}, resourceId={}", tagId, resourceInStore.getId());
}
}
} catch (Exception exception) {
LOG.error("deleteTagResourceMap failed, tagId={}, resourceId={}", tagId, resourceInStore.getId());
throw exception;
}
}
if (isAnyTagUpdated) {
if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.refreshServiceResource(" + resourceInStore.getId() + ")");
}
tagStore.refreshServiceResource(resourceInStore.getId());
RangerPerfTracer.logAlways(perf);
} else {
if (CollectionUtils.isEmpty(tagIds)) {
// No tags associated with the resource - delete the resource too
tagStore.deleteServiceResource(resourceInStore.getId());
}
}
}
}
RangerPerfTracer.logAlways(perfTotal);
LOG.debug("<== ServiceTagsProcessor.createOrUpdate()");
}