mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-17 13:00:56 +00:00
This commit is contained in:
parent
45370c773f
commit
c5e7a63fbb
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package org.openmetadata.service;
|
package org.openmetadata.service;
|
||||||
|
|
||||||
|
import static org.openmetadata.common.utils.CommonUtil.listOf;
|
||||||
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||||
@ -30,7 +31,9 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.openmetadata.schema.EntityInterface;
|
import org.openmetadata.schema.EntityInterface;
|
||||||
import org.openmetadata.schema.entity.services.ServiceType;
|
import org.openmetadata.schema.entity.services.ServiceType;
|
||||||
@ -41,6 +44,7 @@ import org.openmetadata.schema.type.TagLabel;
|
|||||||
import org.openmetadata.service.exception.CatalogExceptionMessage;
|
import org.openmetadata.service.exception.CatalogExceptionMessage;
|
||||||
import org.openmetadata.service.exception.EntityNotFoundException;
|
import org.openmetadata.service.exception.EntityNotFoundException;
|
||||||
import org.openmetadata.service.jdbi3.EntityRepository;
|
import org.openmetadata.service.jdbi3.EntityRepository;
|
||||||
|
import org.openmetadata.service.jdbi3.FeedRepository;
|
||||||
import org.openmetadata.service.resources.feeds.MessageParser.EntityLink;
|
import org.openmetadata.service.resources.feeds.MessageParser.EntityLink;
|
||||||
import org.openmetadata.service.util.EntityUtil.Fields;
|
import org.openmetadata.service.util.EntityUtil.Fields;
|
||||||
|
|
||||||
@ -52,6 +56,8 @@ public final class Entity {
|
|||||||
// Canonical entity name to corresponding EntityRepository map
|
// Canonical entity name to corresponding EntityRepository map
|
||||||
private static final Map<String, EntityRepository<? extends EntityInterface>> ENTITY_REPOSITORY_MAP = new HashMap<>();
|
private static final Map<String, EntityRepository<? extends EntityInterface>> ENTITY_REPOSITORY_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
@Getter @Setter private static FeedRepository feedRepository;
|
||||||
|
|
||||||
// List of all the entities
|
// List of all the entities
|
||||||
private static final List<String> ENTITY_LIST = new ArrayList<>();
|
private static final List<String> ENTITY_LIST = new ArrayList<>();
|
||||||
|
|
||||||
@ -89,15 +95,13 @@ public final class Entity {
|
|||||||
public static final String DATABASE_SCHEMA = "databaseSchema";
|
public static final String DATABASE_SCHEMA = "databaseSchema";
|
||||||
public static final String METRICS = "metrics";
|
public static final String METRICS = "metrics";
|
||||||
public static final String DASHBOARD = "dashboard";
|
public static final String DASHBOARD = "dashboard";
|
||||||
|
public static final String DASHBOARD_DATA_MODEL = "dashboardDataModel";
|
||||||
public static final String PIPELINE = "pipeline";
|
public static final String PIPELINE = "pipeline";
|
||||||
public static final String CHART = "chart";
|
public static final String CHART = "chart";
|
||||||
public static final String REPORT = "report";
|
public static final String REPORT = "report";
|
||||||
public static final String TOPIC = "topic";
|
public static final String TOPIC = "topic";
|
||||||
public static final String MLMODEL = "mlmodel";
|
public static final String MLMODEL = "mlmodel";
|
||||||
public static final String CONTAINER = "container";
|
public static final String CONTAINER = "container";
|
||||||
public static final String BOT = "bot";
|
|
||||||
public static final String EVENT_SUBSCRIPTION = "eventsubscription";
|
|
||||||
public static final String THREAD = "THREAD";
|
|
||||||
public static final String QUERY = "query";
|
public static final String QUERY = "query";
|
||||||
|
|
||||||
public static final String GLOSSARY = "glossary";
|
public static final String GLOSSARY = "glossary";
|
||||||
@ -107,15 +111,12 @@ public final class Entity {
|
|||||||
public static final String TYPE = "type";
|
public static final String TYPE = "type";
|
||||||
public static final String TEST_DEFINITION = "testDefinition";
|
public static final String TEST_DEFINITION = "testDefinition";
|
||||||
public static final String TEST_CONNECTION_DEFINITION = "testConnectionDefinition";
|
public static final String TEST_CONNECTION_DEFINITION = "testConnectionDefinition";
|
||||||
public static final String WORKFLOW = "workflow";
|
|
||||||
public static final String TEST_SUITE = "testSuite";
|
public static final String TEST_SUITE = "testSuite";
|
||||||
public static final String KPI = "kpi";
|
public static final String KPI = "kpi";
|
||||||
public static final String TEST_CASE = "testCase";
|
public static final String TEST_CASE = "testCase";
|
||||||
public static final String WEB_ANALYTIC_EVENT = "webAnalyticEvent";
|
public static final String WEB_ANALYTIC_EVENT = "webAnalyticEvent";
|
||||||
public static final String DATA_INSIGHT_CHART = "dataInsightChart";
|
public static final String DATA_INSIGHT_CHART = "dataInsightChart";
|
||||||
|
|
||||||
public static final String DASHBOARD_DATA_MODEL = "dashboardDataModel";
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Policy entity
|
// Policy entity
|
||||||
//
|
//
|
||||||
@ -128,6 +129,7 @@ public final class Entity {
|
|||||||
public static final String ROLE = "role";
|
public static final String ROLE = "role";
|
||||||
public static final String USER = "user";
|
public static final String USER = "user";
|
||||||
public static final String TEAM = "team";
|
public static final String TEAM = "team";
|
||||||
|
public static final String BOT = "bot";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Operation related entities
|
// Operation related entities
|
||||||
@ -140,6 +142,12 @@ public final class Entity {
|
|||||||
public static final String DOMAIN = "domain";
|
public static final String DOMAIN = "domain";
|
||||||
public static final String DATA_PRODUCT = "dataProduct";
|
public static final String DATA_PRODUCT = "dataProduct";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Other entities
|
||||||
|
public static final String EVENT_SUBSCRIPTION = "eventsubscription";
|
||||||
|
public static final String THREAD = "THREAD";
|
||||||
|
public static final String WORKFLOW = "workflow";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reserved names in OpenMetadata
|
// Reserved names in OpenMetadata
|
||||||
//
|
//
|
||||||
@ -357,6 +365,29 @@ public final class Entity {
|
|||||||
return new HashSet<>(Arrays.asList(propertyOrder.value()));
|
return new HashSet<>(Arrays.asList(propertyOrder.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true if the entity supports activity feeds, announcement, and tasks */
|
||||||
|
public static boolean supportsFeed(String entityType) {
|
||||||
|
return listOf(
|
||||||
|
TABLE,
|
||||||
|
DATABASE,
|
||||||
|
DATABASE_SCHEMA,
|
||||||
|
METRICS,
|
||||||
|
DASHBOARD,
|
||||||
|
DASHBOARD_DATA_MODEL,
|
||||||
|
PIPELINE,
|
||||||
|
CHART,
|
||||||
|
REPORT,
|
||||||
|
TOPIC,
|
||||||
|
MLMODEL,
|
||||||
|
CONTAINER,
|
||||||
|
QUERY,
|
||||||
|
GLOSSARY,
|
||||||
|
GLOSSARY_TERM,
|
||||||
|
TAG,
|
||||||
|
CLASSIFICATION)
|
||||||
|
.contains(entityType);
|
||||||
|
}
|
||||||
|
|
||||||
/** Class for getting validated entity list from a queryParam with list of entities. */
|
/** Class for getting validated entity list from a queryParam with list of entities. */
|
||||||
public static class EntityList {
|
public static class EntityList {
|
||||||
private EntityList() {}
|
private EntityList() {}
|
||||||
|
@ -42,6 +42,7 @@ public class CatalogGenericExceptionMapper implements ExceptionMapper<Throwable>
|
|||||||
@Override
|
@Override
|
||||||
public Response toResponse(Throwable ex) {
|
public Response toResponse(Throwable ex) {
|
||||||
LOG.debug(ex.getMessage());
|
LOG.debug(ex.getMessage());
|
||||||
|
ex.printStackTrace();
|
||||||
if (ex instanceof ProcessingException
|
if (ex instanceof ProcessingException
|
||||||
|| ex instanceof IllegalArgumentException
|
|| ex instanceof IllegalArgumentException
|
||||||
|| ex instanceof javax.ws.rs.BadRequestException) {
|
|| ex instanceof javax.ws.rs.BadRequestException) {
|
||||||
|
@ -850,6 +850,9 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
// Delete the extension data storing custom properties
|
// Delete the extension data storing custom properties
|
||||||
removeExtension(entityInterface);
|
removeExtension(entityInterface);
|
||||||
|
|
||||||
|
// Delete all the threads that are about this entity
|
||||||
|
Entity.getFeedRepository().deleteByAbout(entityInterface.getId());
|
||||||
|
|
||||||
// Finally, delete the entity
|
// Finally, delete the entity
|
||||||
dao.delete(id);
|
dao.delete(id);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,15 @@ import org.openmetadata.service.util.RestUtil.DeleteResponse;
|
|||||||
import org.openmetadata.service.util.RestUtil.PatchResponse;
|
import org.openmetadata.service.util.RestUtil.PatchResponse;
|
||||||
import org.openmetadata.service.util.ResultList;
|
import org.openmetadata.service.util.ResultList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feed relationships:
|
||||||
|
* - 'user' --- createdBy ---> 'thread' in entity_relationship
|
||||||
|
* - 'user' --- repliedTo ---> 'thread' in entity_relationship
|
||||||
|
* - 'user' --- mentionedIn ---> 'thread' in entity_relationship
|
||||||
|
* - 'user' --- reactedTo ---> 'thread' in entity_relationship
|
||||||
|
* - 'thread' --- addressedTo ---> 'user' in field_relationship
|
||||||
|
* - 'thread' --- isAbout ---> 'entity' in entity_relationship
|
||||||
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FeedRepository {
|
public class FeedRepository {
|
||||||
private final CollectionDAO dao;
|
private final CollectionDAO dao;
|
||||||
@ -369,19 +378,32 @@ public class FeedRepository {
|
|||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
public DeleteResponse<Thread> deleteThread(Thread thread, String deletedByUser) {
|
public DeleteResponse<Thread> deleteThread(Thread thread, String deletedByUser) {
|
||||||
String id = thread.getId().toString();
|
deleteThreadInternal(thread.getId().toString());
|
||||||
|
LOG.info("{} deleted thread with id {}", deletedByUser, thread.getId());
|
||||||
|
return new DeleteResponse<>(thread, RestUtil.ENTITY_DELETED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteThreadInternal(String id) {
|
||||||
// Delete all the relationships to other entities
|
// Delete all the relationships to other entities
|
||||||
dao.relationshipDAO().deleteAll(id, Entity.THREAD);
|
dao.relationshipDAO().deleteAll(id, Entity.THREAD);
|
||||||
|
|
||||||
// Delete all the field relationships to other entities
|
// Delete all the field relationships to other entities
|
||||||
dao.fieldRelationshipDAO().deleteAllByPrefix(id);
|
dao.fieldRelationshipDAO().deleteAllByPrefix(id);
|
||||||
|
|
||||||
// Finally, delete the entity
|
// Finally, delete the thread
|
||||||
dao.feedDAO().delete(id);
|
dao.feedDAO().delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
LOG.info("{} deleted thread with id {}", deletedByUser, thread.getId());
|
@Transaction
|
||||||
return new DeleteResponse<>(thread, RestUtil.ENTITY_DELETED);
|
public void deleteByAbout(UUID entityId) {
|
||||||
|
List<String> threadIds = listOrEmpty(dao.feedDAO().findByEntityId(entityId.toString()));
|
||||||
|
for (String threadId : threadIds) {
|
||||||
|
try {
|
||||||
|
deleteThreadInternal(threadId);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// Continue deletion
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
|
@ -100,6 +100,7 @@ public class FeedResource {
|
|||||||
public FeedResource(CollectionDAO dao, Authorizer authorizer) {
|
public FeedResource(CollectionDAO dao, Authorizer authorizer) {
|
||||||
Objects.requireNonNull(dao, "FeedRepository must not be null");
|
Objects.requireNonNull(dao, "FeedRepository must not be null");
|
||||||
this.dao = new FeedRepository(dao);
|
this.dao = new FeedRepository(dao);
|
||||||
|
Entity.setFeedRepository(this.dao);
|
||||||
this.authorizer = authorizer;
|
this.authorizer = authorizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ public class FeedResource {
|
|||||||
@QueryParam("after")
|
@QueryParam("after")
|
||||||
String after,
|
String after,
|
||||||
@Parameter(
|
@Parameter(
|
||||||
description = "Filter threads by entity link",
|
description = "Filter threads by entity link of entity about which this thread is created",
|
||||||
schema = @Schema(type = "string", example = "<E#/{entityType}/{entityFQN}/{fieldName}>"))
|
schema = @Schema(type = "string", example = "<E#/{entityType}/{entityFQN}/{fieldName}>"))
|
||||||
@QueryParam("entityLink")
|
@QueryParam("entityLink")
|
||||||
String entityLink,
|
String entityLink,
|
||||||
@ -354,8 +355,7 @@ public class FeedResource {
|
|||||||
@Parameter(description = "Filter threads by whether it is active or resolved", schema = @Schema(type = "boolean"))
|
@Parameter(description = "Filter threads by whether it is active or resolved", schema = @Schema(type = "boolean"))
|
||||||
@DefaultValue("false")
|
@DefaultValue("false")
|
||||||
@QueryParam("isResolved")
|
@QueryParam("isResolved")
|
||||||
Boolean isResolved)
|
Boolean isResolved) {
|
||||||
throws IOException {
|
|
||||||
FeedFilter filter = FeedFilter.builder().threadType(threadType).taskStatus(taskStatus).resolved(isResolved).build();
|
FeedFilter filter = FeedFilter.builder().threadType(threadType).taskStatus(taskStatus).resolved(isResolved).build();
|
||||||
return dao.getThreadsCount(filter, entityLink);
|
return dao.getThreadsCount(filter, entityLink);
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@ public final class MessageParser {
|
|||||||
|
|
||||||
private static final String ENTITY_LINK_SEPARATOR = "::";
|
private static final String ENTITY_LINK_SEPARATOR = "::";
|
||||||
// Pattern to match the following markdown entity links:
|
// Pattern to match the following markdown entity links:
|
||||||
// <#E::{entityType}::{entityFQN}> -- <#E::table::bigquery_gcp.shopify.raw_product_catalog>
|
// <#E::{entityType}::{entityFQN}> -- <#E::table::bigquery_gcp.shopify.product>
|
||||||
// <#E::{entityType}::{entityFQN}::{fieldName}> -- <#E::table::bigquery_gcp.shopify.raw_product_catalog::description>
|
// <#E::{entityType}::{entityFQN}::{fieldName}> -- <#E::table::bigquery_gcp.shopify.product::description>
|
||||||
// <#E::{entityType}::{entityFQN}::{fieldName}::{arrayFieldName}>
|
// <#E::{entityType}::{entityFQN}::{fieldName}::{arrayFieldName}>
|
||||||
// -- <#E::table::bigquery_gcp.shopify.raw_product_catalog::columns::comment>
|
// -- <#E::table::bigquery_gcp.shopify.product::columns::product_id>
|
||||||
// <#E::{entityType}::{entityFQN}::{fieldName}::{arrayFieldName}::{arrayFieldValue}>
|
// <#E::{entityType}::{entityFQN}::{fieldName}::{arrayFieldName}::{arrayFieldValue}>
|
||||||
// -- <#E::table::bigquery_gcp.shopify.raw_product_catalog::columns::comment::description>
|
// -- <#E::table::bigquery_gcp.shopify.product::columns::product_id::description>
|
||||||
private static final Pattern ENTITY_LINK_PATTERN =
|
private static final Pattern ENTITY_LINK_PATTERN =
|
||||||
Pattern.compile(
|
Pattern.compile(
|
||||||
"<#E"
|
"<#E"
|
||||||
@ -77,6 +77,10 @@ public final class MessageParser {
|
|||||||
ENTITY_ARRAY_FIELD
|
ENTITY_ARRAY_FIELD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntityLink(String entityType, String entityFqn) {
|
||||||
|
this(entityType, entityFqn, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
public EntityLink(
|
public EntityLink(
|
||||||
String entityType, String entityFqn, String fieldName, String arrayFieldName, String arrayFieldValue) {
|
String entityType, String entityFqn, String fieldName, String arrayFieldName, String arrayFieldValue) {
|
||||||
if (entityType == null || entityFqn == null) {
|
if (entityType == null || entityFqn == null) {
|
||||||
@ -92,18 +96,30 @@ public final class MessageParser {
|
|||||||
if (arrayFieldName == null) {
|
if (arrayFieldName == null) {
|
||||||
throw new IllegalArgumentException(INVALID_ENTITY_LINK);
|
throw new IllegalArgumentException(INVALID_ENTITY_LINK);
|
||||||
}
|
}
|
||||||
|
// Entity link example: <#E::table::bigquery_gcp.shopify.product::columns::product_id::description>
|
||||||
|
// FullyQualifiedFieldType: table.columns.member
|
||||||
|
// FullyQualifiedFieldValue: bigQuery_gcp.shopify.product.product_id.description
|
||||||
this.linkType = LinkType.ENTITY_ARRAY_FIELD;
|
this.linkType = LinkType.ENTITY_ARRAY_FIELD;
|
||||||
this.fullyQualifiedFieldType = String.format("%s.%s.member", entityType, fieldName);
|
this.fullyQualifiedFieldType = String.format("%s.%s.member", entityType, fieldName);
|
||||||
this.fullyQualifiedFieldValue = String.format("%s.%s.%s", entityFqn, arrayFieldName, arrayFieldValue);
|
this.fullyQualifiedFieldValue = String.format("%s.%s.%s", entityFqn, arrayFieldName, arrayFieldValue);
|
||||||
} else if (arrayFieldName != null) {
|
} else if (arrayFieldName != null) {
|
||||||
|
// Entity link example: <#E::table::bigquery_gcp.shopify.product::columns::product_id>
|
||||||
|
// FullyQualifiedFieldType: table.columns.member
|
||||||
|
// FullyQualifiedFieldValue: bigQuery_gcp.shopify.product.product_id
|
||||||
this.linkType = LinkType.ENTITY_ARRAY_FIELD;
|
this.linkType = LinkType.ENTITY_ARRAY_FIELD;
|
||||||
this.fullyQualifiedFieldType = String.format("%s.%s.member", entityType, fieldName);
|
this.fullyQualifiedFieldType = String.format("%s.%s.member", entityType, fieldName);
|
||||||
this.fullyQualifiedFieldValue = String.format("%s.%s", entityFqn, arrayFieldName);
|
this.fullyQualifiedFieldValue = String.format("%s.%s", entityFqn, arrayFieldName);
|
||||||
} else if (fieldName != null) {
|
} else if (fieldName != null) {
|
||||||
this.fullyQualifiedFieldType = String.format("%s.%s", entityType, fieldName);
|
// Entity link example: <#E::table::bigquery_gcp.shopify.product::description>
|
||||||
|
// FullyQualifiedFieldType: table.description
|
||||||
|
// FullyQualifiedFieldValue: bigQuery_gcp.shopify.product.description
|
||||||
this.linkType = LinkType.ENTITY_REGULAR_FIELD;
|
this.linkType = LinkType.ENTITY_REGULAR_FIELD;
|
||||||
|
this.fullyQualifiedFieldType = String.format("%s.%s", entityType, fieldName);
|
||||||
this.fullyQualifiedFieldValue = String.format("%s.%s", entityFqn, fieldName);
|
this.fullyQualifiedFieldValue = String.format("%s.%s", entityFqn, fieldName);
|
||||||
} else {
|
} else {
|
||||||
|
// Entity link example: <#E::table::bigquery_gcp.shopify.product>
|
||||||
|
// FullyQualifiedFieldType: table
|
||||||
|
// FullyQualifiedFieldValue: bigQuery_gcp.shopify.product
|
||||||
this.linkType = LinkType.ENTITY;
|
this.linkType = LinkType.ENTITY;
|
||||||
this.fullyQualifiedFieldType = entityType;
|
this.fullyQualifiedFieldType = entityType;
|
||||||
this.fullyQualifiedFieldValue = entityFqn;
|
this.fullyQualifiedFieldValue = entityFqn;
|
||||||
@ -111,13 +127,8 @@ public final class MessageParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getLinkString() {
|
public String getLinkString() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder("<#E");
|
||||||
builder
|
builder.append(ENTITY_LINK_SEPARATOR).append(entityType).append(ENTITY_LINK_SEPARATOR).append(entityFQN);
|
||||||
.append("<#E")
|
|
||||||
.append(ENTITY_LINK_SEPARATOR)
|
|
||||||
.append(entityType)
|
|
||||||
.append(ENTITY_LINK_SEPARATOR)
|
|
||||||
.append(entityFQN);
|
|
||||||
if (linkType == LinkType.ENTITY_REGULAR_FIELD || linkType == LinkType.ENTITY_ARRAY_FIELD) {
|
if (linkType == LinkType.ENTITY_REGULAR_FIELD || linkType == LinkType.ENTITY_ARRAY_FIELD) {
|
||||||
builder.append(ENTITY_LINK_SEPARATOR).append(fieldName);
|
builder.append(ENTITY_LINK_SEPARATOR).append(fieldName);
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,13 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
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.common.utils.CommonUtil.listOf;
|
||||||
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
||||||
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
|
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
|
||||||
import static org.openmetadata.csv.EntityCsvTest.assertSummary;
|
import static org.openmetadata.csv.EntityCsvTest.assertSummary;
|
||||||
import static org.openmetadata.schema.type.MetadataOperation.EDIT_ALL;
|
import static org.openmetadata.schema.type.MetadataOperation.EDIT_ALL;
|
||||||
import static org.openmetadata.schema.type.MetadataOperation.EDIT_TESTS;
|
import static org.openmetadata.schema.type.MetadataOperation.EDIT_TESTS;
|
||||||
|
import static org.openmetadata.schema.type.TaskType.RequestDescription;
|
||||||
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
|
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
|
||||||
import static org.openmetadata.service.Entity.FIELD_DELETED;
|
import static org.openmetadata.service.Entity.FIELD_DELETED;
|
||||||
import static org.openmetadata.service.Entity.FIELD_EXTENSION;
|
import static org.openmetadata.service.Entity.FIELD_EXTENSION;
|
||||||
@ -129,6 +131,7 @@ import org.openmetadata.schema.CreateEntity;
|
|||||||
import org.openmetadata.schema.EntityInterface;
|
import org.openmetadata.schema.EntityInterface;
|
||||||
import org.openmetadata.schema.api.data.RestoreEntity;
|
import org.openmetadata.schema.api.data.RestoreEntity;
|
||||||
import org.openmetadata.schema.api.data.TermReference;
|
import org.openmetadata.schema.api.data.TermReference;
|
||||||
|
import org.openmetadata.schema.api.feed.CreateThread;
|
||||||
import org.openmetadata.schema.api.teams.CreateTeam;
|
import org.openmetadata.schema.api.teams.CreateTeam;
|
||||||
import org.openmetadata.schema.api.teams.CreateTeam.TeamType;
|
import org.openmetadata.schema.api.teams.CreateTeam.TeamType;
|
||||||
import org.openmetadata.schema.api.tests.CreateTestSuite;
|
import org.openmetadata.schema.api.tests.CreateTestSuite;
|
||||||
@ -144,6 +147,7 @@ import org.openmetadata.schema.entity.data.GlossaryTerm;
|
|||||||
import org.openmetadata.schema.entity.data.Table;
|
import org.openmetadata.schema.entity.data.Table;
|
||||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||||
import org.openmetadata.schema.entity.domains.Domain;
|
import org.openmetadata.schema.entity.domains.Domain;
|
||||||
|
import org.openmetadata.schema.entity.feed.Thread;
|
||||||
import org.openmetadata.schema.entity.policies.Policy;
|
import org.openmetadata.schema.entity.policies.Policy;
|
||||||
import org.openmetadata.schema.entity.policies.accessControl.Rule;
|
import org.openmetadata.schema.entity.policies.accessControl.Rule;
|
||||||
import org.openmetadata.schema.entity.services.connections.TestConnectionResult;
|
import org.openmetadata.schema.entity.services.connections.TestConnectionResult;
|
||||||
@ -156,6 +160,7 @@ import org.openmetadata.schema.entity.type.Category;
|
|||||||
import org.openmetadata.schema.entity.type.CustomProperty;
|
import org.openmetadata.schema.entity.type.CustomProperty;
|
||||||
import org.openmetadata.schema.tests.TestDefinition;
|
import org.openmetadata.schema.tests.TestDefinition;
|
||||||
import org.openmetadata.schema.tests.TestSuite;
|
import org.openmetadata.schema.tests.TestSuite;
|
||||||
|
import org.openmetadata.schema.type.AnnouncementDetails;
|
||||||
import org.openmetadata.schema.type.ChangeDescription;
|
import org.openmetadata.schema.type.ChangeDescription;
|
||||||
import org.openmetadata.schema.type.ChangeEvent;
|
import org.openmetadata.schema.type.ChangeEvent;
|
||||||
import org.openmetadata.schema.type.Column;
|
import org.openmetadata.schema.type.Column;
|
||||||
@ -182,6 +187,7 @@ import org.openmetadata.service.resources.dqtests.TestDefinitionResourceTest;
|
|||||||
import org.openmetadata.service.resources.dqtests.TestSuiteResourceTest;
|
import org.openmetadata.service.resources.dqtests.TestSuiteResourceTest;
|
||||||
import org.openmetadata.service.resources.events.EventResource.EventList;
|
import org.openmetadata.service.resources.events.EventResource.EventList;
|
||||||
import org.openmetadata.service.resources.events.EventSubscriptionResourceTest;
|
import org.openmetadata.service.resources.events.EventSubscriptionResourceTest;
|
||||||
|
import org.openmetadata.service.resources.feeds.FeedResourceTest;
|
||||||
import org.openmetadata.service.resources.glossary.GlossaryResourceTest;
|
import org.openmetadata.service.resources.glossary.GlossaryResourceTest;
|
||||||
import org.openmetadata.service.resources.kpi.KpiResourceTest;
|
import org.openmetadata.service.resources.kpi.KpiResourceTest;
|
||||||
import org.openmetadata.service.resources.metadata.TypeResourceTest;
|
import org.openmetadata.service.resources.metadata.TypeResourceTest;
|
||||||
@ -1837,6 +1843,48 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Execution(ExecutionMode.CONCURRENT)
|
||||||
|
void test_cleanupConversations(TestInfo test) throws HttpResponseException {
|
||||||
|
if (!Entity.supportsFeed(entityType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
K request = createRequest(getEntityName(test), "", "", null);
|
||||||
|
T entity = createEntity(request, ADMIN_AUTH_HEADERS);
|
||||||
|
|
||||||
|
// Add a conversation thread for the entity
|
||||||
|
FeedResourceTest feedTest = new FeedResourceTest();
|
||||||
|
String about = String.format("<#E::%s::%s>", entityType, entity.getFullyQualifiedName());
|
||||||
|
CreateThread createThread = new CreateThread().withFrom(USER1.getName()).withMessage("message").withAbout(about);
|
||||||
|
Thread thread = feedTest.createAndCheck(createThread, ADMIN_AUTH_HEADERS);
|
||||||
|
|
||||||
|
// Add task thread for the entity from user1 to user2
|
||||||
|
Thread taskThread =
|
||||||
|
feedTest.createTaskThread(
|
||||||
|
USER1.getName(),
|
||||||
|
about,
|
||||||
|
USER2.getEntityReference(),
|
||||||
|
"old",
|
||||||
|
"new",
|
||||||
|
RequestDescription,
|
||||||
|
authHeaders(USER1.getName()));
|
||||||
|
|
||||||
|
// Add announcement thread for the entity from user1 to user2
|
||||||
|
AnnouncementDetails announcementDetails = feedTest.getAnnouncementDetails("Announcement", 10, 11);
|
||||||
|
Thread announcementThread =
|
||||||
|
feedTest.createAnnouncement(
|
||||||
|
USER1.getName(), about, "message", announcementDetails, authHeaders(USER1.getName()));
|
||||||
|
|
||||||
|
// When the entity is deleted, all the threads also should be deleted
|
||||||
|
deleteEntity(entity.getId(), true, true, ADMIN_AUTH_HEADERS);
|
||||||
|
for (UUID id : listOf(thread.getId(), taskThread.getId(), announcementThread.getId())) {
|
||||||
|
assertResponseContains(
|
||||||
|
() -> feedTest.getThread(id, ADMIN_AUTH_HEADERS),
|
||||||
|
NOT_FOUND,
|
||||||
|
CatalogExceptionMessage.entityNotFound("Thread", id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Common entity functionality for tests
|
// Common entity functionality for tests
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -2710,7 +2758,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T assertDomainInheritanceOverride(T entity, K updateRequest, EntityReference newDomain)
|
public void assertDomainInheritanceOverride(T entity, K updateRequest, EntityReference newDomain)
|
||||||
throws JsonProcessingException, HttpResponseException {
|
throws JsonProcessingException, HttpResponseException {
|
||||||
// When an entity has domain set, it does not inherit domain from the parent
|
// When an entity has domain set, it does not inherit domain from the parent
|
||||||
String json = JsonUtils.pojoToJson(entity);
|
String json = JsonUtils.pojoToJson(entity);
|
||||||
@ -2721,6 +2769,5 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
assertReference(newDomain, entity.getDomain()); // Domain remains the same
|
assertReference(newDomain, entity.getDomain()); // Domain remains the same
|
||||||
entity = getEntity(entity.getId(), "domain", ADMIN_AUTH_HEADERS);
|
entity = getEntity(entity.getId(), "domain", ADMIN_AUTH_HEADERS);
|
||||||
assertReference(newDomain, entity.getDomain()); // Domain remains the same
|
assertReference(newDomain, entity.getDomain()); // Domain remains the same
|
||||||
return entity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,50 +394,23 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
|
|
||||||
// create two announcements with start time in the future
|
// create two announcements with start time in the future
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
AnnouncementDetails announcementDetails =
|
String about = String.format("<#E::%s::%s>", Entity.TABLE, TABLE.getFullyQualifiedName());
|
||||||
new AnnouncementDetails()
|
|
||||||
.withDescription("First announcement")
|
|
||||||
.withStartTime(now.plusDays(10L).toEpochSecond(ZoneOffset.UTC))
|
|
||||||
.withEndTime(now.plusDays(11L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement One")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
announcementDetails
|
// Create announcement 1
|
||||||
.withStartTime(now.plusDays(12L).toEpochSecond(ZoneOffset.UTC))
|
AnnouncementDetails announcementDetails = getAnnouncementDetails("First announcement", 10, 11);
|
||||||
.withEndTime(now.plusDays(13L).toEpochSecond(ZoneOffset.UTC));
|
createAnnouncement(USER.getName(), about, "Announcement One", announcementDetails, USER_AUTH_HEADERS);
|
||||||
create =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement Two")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
// create one expired announcement
|
// Create announcement 2
|
||||||
announcementDetails
|
announcementDetails = getAnnouncementDetails("Second announcement", 12, 13);
|
||||||
.withStartTime(now.minusDays(30L).toEpochSecond(ZoneOffset.UTC))
|
createAnnouncement(USER.getName(), about, "Announcement Two", announcementDetails, USER_AUTH_HEADERS);
|
||||||
.withEndTime(now.minusDays(20L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
create =
|
// create an expired announcement
|
||||||
create()
|
announcementDetails = getAnnouncementDetails("Expired", -30, -20);
|
||||||
.withMessage("Announcement Three")
|
createAnnouncement(USER.getName(), about, "Announcement Three", announcementDetails, USER_AUTH_HEADERS);
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
// create one active announcement
|
// create one active announcement
|
||||||
announcementDetails
|
announcementDetails = getAnnouncementDetails("Active", -1, 1);
|
||||||
.withDescription("Active Announcement")
|
createAnnouncement(USER.getName(), about, "Announcement Four", announcementDetails, USER_AUTH_HEADERS);
|
||||||
.withStartTime(now.minusDays(1L).toEpochSecond(ZoneOffset.UTC))
|
|
||||||
.withEndTime(now.plusDays(1L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
create =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement Four")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
ThreadList announcements = listAnnouncements(null, null, null, ADMIN_AUTH_HEADERS);
|
ThreadList announcements = listAnnouncements(null, null, null, ADMIN_AUTH_HEADERS);
|
||||||
int announcementCount = announcements.getPaging().getTotal();
|
int announcementCount = announcements.getPaging().getTotal();
|
||||||
@ -445,7 +418,7 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
assertEquals(totalAnnouncementCount + 4, announcementCount);
|
assertEquals(totalAnnouncementCount + 4, announcementCount);
|
||||||
assertEquals(totalAnnouncementCount + 4, announcements.getData().size());
|
assertEquals(totalAnnouncementCount + 4, announcements.getData().size());
|
||||||
|
|
||||||
announcements = listAnnouncements(create.getAbout(), null, null, ADMIN_AUTH_HEADERS);
|
announcements = listAnnouncements(about, null, null, ADMIN_AUTH_HEADERS);
|
||||||
assertEquals(announcementCount, announcements.getPaging().getTotal());
|
assertEquals(announcementCount, announcements.getPaging().getTotal());
|
||||||
assertEquals(announcementCount, announcements.getData().size());
|
assertEquals(announcementCount, announcements.getData().size());
|
||||||
|
|
||||||
@ -454,9 +427,9 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
|
|
||||||
assertEquals(1, activeAnnouncementCount);
|
assertEquals(1, activeAnnouncementCount);
|
||||||
assertEquals(1, announcements.getData().size());
|
assertEquals(1, announcements.getData().size());
|
||||||
assertEquals("Active Announcement", announcements.getData().get(0).getAnnouncement().getDescription());
|
assertEquals("Active", announcements.getData().get(0).getAnnouncement().getDescription());
|
||||||
|
|
||||||
announcements = listAnnouncements(create.getAbout(), null, true, ADMIN_AUTH_HEADERS);
|
announcements = listAnnouncements(about, null, true, ADMIN_AUTH_HEADERS);
|
||||||
assertEquals(activeAnnouncementCount, announcements.getPaging().getTotal());
|
assertEquals(activeAnnouncementCount, announcements.getPaging().getTotal());
|
||||||
assertEquals(activeAnnouncementCount, announcements.getData().size());
|
assertEquals(activeAnnouncementCount, announcements.getData().size());
|
||||||
|
|
||||||
@ -465,7 +438,7 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
assertEquals(totalAnnouncementCount + 3, announcements.getPaging().getTotal());
|
assertEquals(totalAnnouncementCount + 3, announcements.getPaging().getTotal());
|
||||||
assertEquals(totalAnnouncementCount + 3, announcements.getData().size());
|
assertEquals(totalAnnouncementCount + 3, announcements.getData().size());
|
||||||
|
|
||||||
announcements = listAnnouncements(create.getAbout(), null, false, ADMIN_AUTH_HEADERS);
|
announcements = listAnnouncements(about, null, false, ADMIN_AUTH_HEADERS);
|
||||||
assertEquals(totalAnnouncementCount + 3, announcements.getPaging().getTotal());
|
assertEquals(totalAnnouncementCount + 3, announcements.getPaging().getTotal());
|
||||||
assertEquals(totalAnnouncementCount + 3, announcements.getData().size());
|
assertEquals(totalAnnouncementCount + 3, announcements.getData().size());
|
||||||
}
|
}
|
||||||
@ -474,58 +447,31 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
void post_invalidAnnouncement_400() throws IOException {
|
void post_invalidAnnouncement_400() throws IOException {
|
||||||
// create two announcements with same start time in the future
|
// create two announcements with same start time in the future
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
AnnouncementDetails announcementDetails =
|
String about = String.format("<#E::%s::%s>", Entity.TABLE, TABLE.getFullyQualifiedName());
|
||||||
new AnnouncementDetails()
|
AnnouncementDetails announcementDetails = getAnnouncementDetails("1", 3, 5);
|
||||||
.withDescription("First announcement")
|
createAnnouncement(USER.getName(), about, "Announcement One", announcementDetails, USER_AUTH_HEADERS);
|
||||||
.withStartTime(now.plusDays(3L).toEpochSecond(ZoneOffset.UTC))
|
|
||||||
.withEndTime(now.plusDays(5L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement One")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
CreateThread create2 =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement Two")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
|
|
||||||
// create announcement with same start and end time
|
// create announcement with same start and end time
|
||||||
assertResponse(() -> createThread(create2, USER_AUTH_HEADERS), BAD_REQUEST, ANNOUNCEMENT_OVERLAP);
|
assertResponse(
|
||||||
|
() -> createAnnouncement(USER.getName(), about, "Announcement Two", announcementDetails, USER_AUTH_HEADERS),
|
||||||
|
BAD_REQUEST,
|
||||||
|
ANNOUNCEMENT_OVERLAP);
|
||||||
|
|
||||||
// create announcement with start time > end time
|
// create announcement with start time > end time
|
||||||
announcementDetails
|
assertResponse(
|
||||||
.withStartTime(now.plusDays(3L).toEpochSecond(ZoneOffset.UTC))
|
() ->
|
||||||
.withEndTime(now.plusDays(2L).toEpochSecond(ZoneOffset.UTC));
|
createAnnouncement(
|
||||||
CreateThread create3 = create2.withAnnouncementDetails(announcementDetails);
|
USER.getName(), about, "Announcement Three", getAnnouncementDetails("2", 3, 2), USER_AUTH_HEADERS),
|
||||||
assertResponse(() -> createThread(create3, USER_AUTH_HEADERS), BAD_REQUEST, ANNOUNCEMENT_INVALID_START_TIME);
|
BAD_REQUEST,
|
||||||
|
ANNOUNCEMENT_INVALID_START_TIME);
|
||||||
|
|
||||||
// create announcement with overlaps
|
// create announcement with overlap
|
||||||
announcementDetails
|
assertResponse(
|
||||||
.withStartTime(now.plusDays(2L).toEpochSecond(ZoneOffset.UTC))
|
() ->
|
||||||
.withEndTime(now.plusDays(6L).toEpochSecond(ZoneOffset.UTC));
|
createAnnouncement(
|
||||||
CreateThread create4 = create2.withAnnouncementDetails(announcementDetails);
|
USER.getName(), about, "Announcement Four", getAnnouncementDetails("3", 2, 6), USER_AUTH_HEADERS),
|
||||||
assertResponse(() -> createThread(create4, USER_AUTH_HEADERS), BAD_REQUEST, ANNOUNCEMENT_OVERLAP);
|
BAD_REQUEST,
|
||||||
|
ANNOUNCEMENT_OVERLAP);
|
||||||
announcementDetails
|
|
||||||
.withStartTime(now.plusDays(3L).plusHours(2L).toEpochSecond(ZoneOffset.UTC))
|
|
||||||
.withEndTime(now.plusDays(4L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create5 = create2.withAnnouncementDetails(announcementDetails);
|
|
||||||
assertResponse(() -> createThread(create5, USER_AUTH_HEADERS), BAD_REQUEST, ANNOUNCEMENT_OVERLAP);
|
|
||||||
|
|
||||||
announcementDetails
|
|
||||||
.withStartTime(now.plusDays(2L).plusHours(12L).toEpochSecond(ZoneOffset.UTC))
|
|
||||||
.withEndTime(now.plusDays(4L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create6 = create2.withAnnouncementDetails(announcementDetails);
|
|
||||||
assertResponse(() -> createThread(create6, USER_AUTH_HEADERS), BAD_REQUEST, ANNOUNCEMENT_OVERLAP);
|
|
||||||
|
|
||||||
announcementDetails
|
|
||||||
.withStartTime(now.plusDays(4L).plusHours(12L).toEpochSecond(ZoneOffset.UTC))
|
|
||||||
.withEndTime(now.plusDays(6L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create7 = create2.withAnnouncementDetails(announcementDetails);
|
|
||||||
assertResponse(() -> createThread(create7, USER_AUTH_HEADERS), BAD_REQUEST, ANNOUNCEMENT_OVERLAP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -856,18 +802,10 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
@Test
|
@Test
|
||||||
void patch_announcement_200() throws IOException {
|
void patch_announcement_200() throws IOException {
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
AnnouncementDetails announcementDetails =
|
AnnouncementDetails announcementDetails = getAnnouncementDetails("First announcement", 5, 6);
|
||||||
new AnnouncementDetails()
|
String about = String.format("<#E::%s::%s>", Entity.TABLE, TABLE.getFullyQualifiedName());
|
||||||
.withDescription("First announcement")
|
Thread thread =
|
||||||
.withStartTime(now.plusDays(5L).toEpochSecond(ZoneOffset.UTC))
|
createAnnouncement(USER.getName(), about, "Announcement One", announcementDetails, USER_AUTH_HEADERS);
|
||||||
.withEndTime(now.plusDays(6L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement One")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
Thread thread = createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
String originalJson = JsonUtils.pojoToJson(thread);
|
String originalJson = JsonUtils.pojoToJson(thread);
|
||||||
|
|
||||||
long startTs = now.plusDays(6L).toEpochSecond(ZoneOffset.UTC);
|
long startTs = now.plusDays(6L).toEpochSecond(ZoneOffset.UTC);
|
||||||
@ -900,27 +838,14 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
@Test
|
@Test
|
||||||
void patch_invalidAnnouncement_400() throws IOException {
|
void patch_invalidAnnouncement_400() throws IOException {
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
AnnouncementDetails announcementDetails =
|
String about = String.format("<#E::%s::%s>", Entity.TABLE, TABLE.getFullyQualifiedName());
|
||||||
new AnnouncementDetails()
|
AnnouncementDetails announcementDetails = getAnnouncementDetails("First announcement", 53, 55);
|
||||||
.withDescription("First announcement")
|
Thread thread1 =
|
||||||
.withStartTime(now.plusDays(53L).toEpochSecond(ZoneOffset.UTC))
|
createAnnouncement(USER.getName(), about, "Announcement One", announcementDetails, USER_AUTH_HEADERS);
|
||||||
.withEndTime(now.plusDays(55L).toEpochSecond(ZoneOffset.UTC));
|
|
||||||
CreateThread create =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement One")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
Thread thread1 = createAndCheck(create, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
announcementDetails
|
announcementDetails = getAnnouncementDetails("Second announcement", 57, 59);
|
||||||
.withStartTime(now.plusDays(57L).toEpochSecond(ZoneOffset.UTC))
|
Thread thread2 =
|
||||||
.withEndTime(now.plusDays(59L).toEpochSecond(ZoneOffset.UTC));
|
createAnnouncement(USER.getName(), about, "Announcement Two", announcementDetails, USER_AUTH_HEADERS);
|
||||||
CreateThread create2 =
|
|
||||||
create()
|
|
||||||
.withMessage("Announcement Two")
|
|
||||||
.withType(ThreadType.Announcement)
|
|
||||||
.withAnnouncementDetails(announcementDetails);
|
|
||||||
Thread thread2 = createAndCheck(create2, USER_AUTH_HEADERS);
|
|
||||||
|
|
||||||
String originalJson = JsonUtils.pojoToJson(thread2);
|
String originalJson = JsonUtils.pojoToJson(thread2);
|
||||||
|
|
||||||
@ -1573,7 +1498,7 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Thread createTaskThread(
|
public Thread createTaskThread(
|
||||||
String fromUser,
|
String fromUser,
|
||||||
String about,
|
String about,
|
||||||
EntityReference assignee,
|
EntityReference assignee,
|
||||||
@ -1598,6 +1523,23 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
return createAndCheck(create, authHeaders);
|
return createAndCheck(create, authHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Thread createAnnouncement(
|
||||||
|
String fromUser,
|
||||||
|
String about,
|
||||||
|
String message,
|
||||||
|
AnnouncementDetails announcementDetails,
|
||||||
|
Map<String, String> authHeaders)
|
||||||
|
throws HttpResponseException {
|
||||||
|
CreateThread create =
|
||||||
|
new CreateThread()
|
||||||
|
.withFrom(fromUser)
|
||||||
|
.withMessage(message)
|
||||||
|
.withAbout(about)
|
||||||
|
.withType(ThreadType.Announcement)
|
||||||
|
.withAnnouncementDetails(announcementDetails);
|
||||||
|
return createAndCheck(create, authHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
public void validateTaskList(
|
public void validateTaskList(
|
||||||
UUID expectedAssignee,
|
UUID expectedAssignee,
|
||||||
String expectedSuggestion,
|
String expectedSuggestion,
|
||||||
@ -1623,4 +1565,12 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
|
|||||||
assertEquals(expected.getSuggestion(), actual.getSuggestion());
|
assertEquals(expected.getSuggestion(), actual.getSuggestion());
|
||||||
assertEquals(expected.getStatus(), actual.getStatus());
|
assertEquals(expected.getStatus(), actual.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AnnouncementDetails getAnnouncementDetails(String description, long start, long end) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
return new AnnouncementDetails()
|
||||||
|
.withDescription(description)
|
||||||
|
.withStartTime(now.plusDays(start).toEpochSecond(ZoneOffset.UTC))
|
||||||
|
.withEndTime(now.plusDays(end).toEpochSecond(ZoneOffset.UTC));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,10 @@ server:
|
|||||||
|
|
||||||
# Logging settings.
|
# Logging settings.
|
||||||
logging:
|
logging:
|
||||||
level: OFF
|
level: INFO
|
||||||
appenders: []
|
appenders:
|
||||||
|
- type: console
|
||||||
|
logFormat: "%level %logger{5} - %msg%n"
|
||||||
|
|
||||||
database:
|
database:
|
||||||
# the name of the JDBC driver, h2 is used for testing
|
# the name of the JDBC driver, h2 is used for testing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user