Fix #5508 Backend: Add API support to resolve a task related to tags (#5595)

This commit is contained in:
Vivek Ratnavel Subramanian 2022-06-23 10:30:18 -07:00 committed by GitHub
parent ce49247011
commit 9403b146fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 191 additions and 118 deletions

View File

@ -34,6 +34,7 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.json.JsonPatch; import javax.json.JsonPatch;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
@ -64,9 +65,11 @@ import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.type.Post; import org.openmetadata.catalog.type.Post;
import org.openmetadata.catalog.type.Reaction; import org.openmetadata.catalog.type.Reaction;
import org.openmetadata.catalog.type.Relationship; import org.openmetadata.catalog.type.Relationship;
import org.openmetadata.catalog.type.TagLabel;
import org.openmetadata.catalog.type.Task; import org.openmetadata.catalog.type.Task;
import org.openmetadata.catalog.type.TaskDetails; import org.openmetadata.catalog.type.TaskDetails;
import org.openmetadata.catalog.type.TaskStatus; import org.openmetadata.catalog.type.TaskStatus;
import org.openmetadata.catalog.type.TaskType;
import org.openmetadata.catalog.type.ThreadType; import org.openmetadata.catalog.type.ThreadType;
import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil;
import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.JsonUtils;
@ -177,15 +180,16 @@ public class FeedRepository {
return new PatchResponse<>(Status.OK, updatedHref, RestUtil.ENTITY_UPDATED); return new PatchResponse<>(Status.OK, updatedHref, RestUtil.ENTITY_UPDATED);
} }
public PatchResponse<Thread> resolveTask(UriInfo uriInfo, Thread thread, String user, ResolveTask resolveTask) private void performTask(
TaskDetails task, EntityLink entityLink, EntityReference reference, UriInfo uriInfo, String newValue, String user)
throws IOException { throws IOException {
// perform the task TaskType taskType = task.getType();
TaskDetails task = thread.getTask(); List<TaskType> descriptionTasks = List.of(TaskType.RequestDescription, TaskType.UpdateDescription);
EntityLink entityLink = EntityLink.parse(thread.getAbout()); List<TaskType> tagTasks = List.of(TaskType.RequestTag, TaskType.UpdateTag);
EntityReference reference = EntityUtil.validateEntityLink(entityLink); List<TaskType> supportedTasks =
switch (task.getType()) { Stream.concat(descriptionTasks.stream(), tagTasks.stream()).collect(Collectors.toList());
case RequestDescription: // task needs to be completed only for Request or update description or tags.
case UpdateDescription: if (supportedTasks.contains(taskType)) {
EntityRepository<?> repository = getEntityRepository(reference.getType()); EntityRepository<?> repository = getEntityRepository(reference.getType());
String json = repository.dao.findJsonByFqn(entityLink.getEntityFQN(), Include.ALL); String json = repository.dao.findJsonByFqn(entityLink.getEntityFQN(), Include.ALL);
switch (entityLink.getEntityType()) { switch (entityLink.getEntityType()) {
@ -194,19 +198,25 @@ public class FeedRepository {
String oldJson = JsonUtils.pojoToJson(table); String oldJson = JsonUtils.pojoToJson(table);
if (entityLink.getFieldName().equals("columns")) { if (entityLink.getFieldName().equals("columns")) {
Optional<Column> col = Optional<Column> col =
table.getColumns().stream() table.getColumns().stream().filter(c -> c.getName().equals(entityLink.getArrayFieldName())).findFirst();
.filter(c -> c.getName().equals(entityLink.getArrayFieldName()))
.findFirst();
if (col.isPresent()) { if (col.isPresent()) {
Column column = col.get(); Column column = col.get();
column.setDescription(resolveTask.getNewValue()); if (descriptionTasks.contains(taskType)) {
column.setDescription(newValue);
} else if (tagTasks.contains(taskType)) {
List<TagLabel> tags = JsonUtils.readObjects(newValue, TagLabel.class);
column.setTags(tags);
}
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format( String.format(
"The Column with name '%s' is not found in the table.", entityLink.getArrayFieldName())); "The Column with name '%s' is not found in the table.", entityLink.getArrayFieldName()));
} }
} else if (entityLink.getFieldName().equals("description")) { } else if (descriptionTasks.contains(taskType) && entityLink.getFieldName().equals("description")) {
table.setDescription(resolveTask.getNewValue()); table.setDescription(newValue);
} else if (tagTasks.contains(taskType) && entityLink.getFieldName().equals("tags")) {
List<TagLabel> tags = JsonUtils.readObjects(newValue, TagLabel.class);
table.setTags(tags);
} else { } else {
// Not supported // Not supported
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -220,8 +230,11 @@ public class FeedRepository {
case TOPIC: case TOPIC:
Topic topic = JsonUtils.readValue(json, Topic.class); Topic topic = JsonUtils.readValue(json, Topic.class);
oldJson = JsonUtils.pojoToJson(topic); oldJson = JsonUtils.pojoToJson(topic);
if (entityLink.getFieldName().equals("description")) { if (descriptionTasks.contains(taskType) && entityLink.getFieldName().equals("description")) {
topic.setDescription(resolveTask.getNewValue()); topic.setDescription(newValue);
} else if (tagTasks.contains(taskType) && entityLink.getFieldName().equals("tags")) {
List<TagLabel> tags = JsonUtils.readObjects(newValue, TagLabel.class);
topic.setTags(tags);
} else { } else {
// Not supported // Not supported
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -235,8 +248,8 @@ public class FeedRepository {
case DASHBOARD: case DASHBOARD:
Dashboard dashboard = JsonUtils.readValue(json, Dashboard.class); Dashboard dashboard = JsonUtils.readValue(json, Dashboard.class);
oldJson = JsonUtils.pojoToJson(dashboard); oldJson = JsonUtils.pojoToJson(dashboard);
if (entityLink.getFieldName().equals("description")) { if (descriptionTasks.contains(taskType) && entityLink.getFieldName().equals("description")) {
dashboard.setDescription(resolveTask.getNewValue()); dashboard.setDescription(newValue);
} else if (entityLink.getFieldName().equals("charts")) { } else if (entityLink.getFieldName().equals("charts")) {
Optional<EntityReference> ch = Optional<EntityReference> ch =
dashboard.getCharts().stream() dashboard.getCharts().stream()
@ -244,7 +257,9 @@ public class FeedRepository {
.findFirst(); .findFirst();
if (ch.isPresent()) { if (ch.isPresent()) {
EntityReference chart = ch.get(); EntityReference chart = ch.get();
chart.setDescription(resolveTask.getNewValue()); if (descriptionTasks.contains(taskType)) {
chart.setDescription(newValue);
}
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format( String.format(
@ -263,8 +278,8 @@ public class FeedRepository {
case PIPELINE: case PIPELINE:
Pipeline pipeline = JsonUtils.readValue(json, Pipeline.class); Pipeline pipeline = JsonUtils.readValue(json, Pipeline.class);
oldJson = JsonUtils.pojoToJson(pipeline); oldJson = JsonUtils.pojoToJson(pipeline);
if (entityLink.getFieldName().equals("description")) { if (descriptionTasks.contains(taskType) && entityLink.getFieldName().equals("description")) {
pipeline.setDescription(resolveTask.getNewValue()); pipeline.setDescription(newValue);
} else if (entityLink.getFieldName().equals("tasks")) { } else if (entityLink.getFieldName().equals("tasks")) {
Optional<Task> tsk = Optional<Task> tsk =
pipeline.getTasks().stream() pipeline.getTasks().stream()
@ -272,7 +287,12 @@ public class FeedRepository {
.findFirst(); .findFirst();
if (tsk.isPresent()) { if (tsk.isPresent()) {
Task pipelineTask = tsk.get(); Task pipelineTask = tsk.get();
pipelineTask.setDescription(resolveTask.getNewValue()); if (descriptionTasks.contains(taskType)) {
pipelineTask.setDescription(newValue);
} else if (tagTasks.contains(taskType)) {
List<TagLabel> tags = JsonUtils.readObjects(newValue, TagLabel.class);
pipelineTask.setTags(tags);
}
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format( String.format(
@ -291,15 +311,17 @@ public class FeedRepository {
default: default:
break; break;
} }
break;
case RequestTag:
case UpdateTag:
break;
case Generic:
default:
// no action to be taken. Just close the task
break;
} }
}
public PatchResponse<Thread> resolveTask(UriInfo uriInfo, Thread thread, String user, ResolveTask resolveTask)
throws IOException {
// perform the task
TaskDetails task = thread.getTask();
EntityLink entityLink = EntityLink.parse(thread.getAbout());
EntityReference reference = EntityUtil.validateEntityLink(entityLink);
performTask(task, entityLink, reference, uriInfo, resolveTask.getNewValue(), user);
// Update the attributes // Update the attributes
task.withNewValue(resolveTask.getNewValue()); task.withNewValue(resolveTask.getNewValue());
closeTask(thread, user); closeTask(thread, user);

View File

@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.entityNotFound; import static org.openmetadata.catalog.exception.CatalogExceptionMessage.entityNotFound;
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.noPermission; import static org.openmetadata.catalog.exception.CatalogExceptionMessage.noPermission;
import static org.openmetadata.catalog.resources.EntityResourceTest.USER_ADDRESS_TAG_LABEL;
import static org.openmetadata.catalog.security.SecurityUtil.authHeaders; import static org.openmetadata.catalog.security.SecurityUtil.authHeaders;
import static org.openmetadata.catalog.security.SecurityUtil.getPrincipalName; import static org.openmetadata.catalog.security.SecurityUtil.getPrincipalName;
import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS; import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS;
@ -43,6 +44,7 @@ import java.net.URISyntaxException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -91,6 +93,7 @@ import org.openmetadata.catalog.type.EntityReference;
import org.openmetadata.catalog.type.Post; import org.openmetadata.catalog.type.Post;
import org.openmetadata.catalog.type.Reaction; import org.openmetadata.catalog.type.Reaction;
import org.openmetadata.catalog.type.ReactionType; import org.openmetadata.catalog.type.ReactionType;
import org.openmetadata.catalog.type.TagLabel;
import org.openmetadata.catalog.type.TaskDetails; import org.openmetadata.catalog.type.TaskDetails;
import org.openmetadata.catalog.type.TaskStatus; import org.openmetadata.catalog.type.TaskStatus;
import org.openmetadata.catalog.type.TaskType; import org.openmetadata.catalog.type.TaskType;
@ -388,7 +391,7 @@ public class FeedResourceTest extends CatalogApplicationTest {
} }
@Test @Test
void post_resolveTask_200() throws IOException { void post_resolveTask_description_200() throws IOException {
CreateTaskDetails taskDetails = CreateTaskDetails taskDetails =
new CreateTaskDetails() new CreateTaskDetails()
.withOldValue("old description") .withOldValue("old description")
@ -432,6 +435,54 @@ public class FeedResourceTest extends CatalogApplicationTest {
assertEquals(TaskStatus.Closed, task.getStatus()); assertEquals(TaskStatus.Closed, task.getStatus());
} }
@Test
void post_resolveTask_tags_200() throws IOException {
String newValue = "[" + JsonUtils.pojoToJson(USER_ADDRESS_TAG_LABEL) + "]";
CreateTaskDetails taskDetails =
new CreateTaskDetails()
.withOldValue(null)
.withAssignees(List.of(USER2.getEntityReference()))
.withType(TaskType.RequestTag)
.withSuggestion(newValue);
String about = create().getAbout();
about = about.substring(0, about.length() - 1) + "::columns::c1::tags>";
CreateThread create =
create()
.withMessage("Request Tags for column")
.withTaskDetails(taskDetails)
.withType(ThreadType.Task)
.withAbout(about);
Map<String, String> userAuthHeaders = authHeaders(USER.getEmail());
createAndCheck(create, userAuthHeaders);
ThreadList tasks = listTasks(null, null, null, null, userAuthHeaders);
TaskDetails task = tasks.getData().get(0).getTask();
assertNotNull(task.getId());
int taskId = task.getId();
ResolveTask resolveTask = new ResolveTask().withNewValue(newValue);
resolveTask(taskId, resolveTask, userAuthHeaders);
Map<String, String> params = new HashMap<>();
params.put("fields", "tags");
ResultList<Table> tables = TABLE_RESOURCE_TEST.listEntities(params, userAuthHeaders);
Optional<Table> table =
tables.getData().stream()
.filter(t -> t.getFullyQualifiedName().equals(TABLE.getFullyQualifiedName()))
.findFirst();
assertTrue(table.isPresent());
List<TagLabel> tags =
table.get().getColumns().stream().filter(c -> c.getName().equals("c1")).findFirst().get().getTags();
assertEquals(USER_ADDRESS_TAG_LABEL.getTagFQN(), tags.get(0).getTagFQN());
Thread taskThread = getTask(taskId, userAuthHeaders);
task = taskThread.getTask();
assertEquals(taskId, task.getId());
assertEquals(newValue, task.getNewValue());
assertEquals(TaskStatus.Closed, task.getStatus());
}
private static Stream<Arguments> provideStringsForListThreads() { private static Stream<Arguments> provideStringsForListThreads() {
return Stream.of( return Stream.of(
Arguments.of(String.format("<#E::%s::%s>", Entity.USER, USER.getName())), Arguments.of(String.format("<#E::%s::%s>", Entity.USER, USER.getName())),