GEN 1931 - Fix entity link accepted chars (#18391)

This commit is contained in:
Aniket Katkar 2024-10-29 15:29:23 +05:30
parent eb6a959886
commit 46cf15c12e
8 changed files with 300 additions and 210 deletions

View File

@ -236,7 +236,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
protected final boolean supportsEmptyDescription; protected final boolean supportsEmptyDescription;
// Special characters supported in the entity name // Special characters supported in the entity name
protected String supportedNameCharacters = "_'-.&()" + RANDOM_STRING_GENERATOR.generate(1); protected String supportedNameCharacters = "_'-.&()[]" + RANDOM_STRING_GENERATOR.generate(1);
protected final boolean supportsCustomExtension; protected final boolean supportsCustomExtension;
@ -250,7 +250,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
public static final String DATA_CONSUMER_ROLE_NAME = "DataConsumer"; public static final String DATA_CONSUMER_ROLE_NAME = "DataConsumer";
public static final String ENTITY_LINK_MATCH_ERROR = public static final String ENTITY_LINK_MATCH_ERROR =
"[entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"]"; "[entityLink must match \"(?U)^<#E::\\w+::(?:[^:<>|]|:[^:<>|])+(?:::(?:[^:<>|]|:[^:<>|])+)*>$\"]";
// Random unicode string generator to test entity name accepts all the unicode characters // Random unicode string generator to test entity name accepts all the unicode characters
protected static final RandomStringGenerator RANDOM_STRING_GENERATOR = protected static final RandomStringGenerator RANDOM_STRING_GENERATOR =

View File

@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals; 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.assertThrows;
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.listOf;
import static org.openmetadata.schema.type.ColumnDataType.BIGINT; import static org.openmetadata.schema.type.ColumnDataType.BIGINT;
@ -2572,152 +2573,53 @@ public class TestCaseResourceTest extends EntityResourceTest<TestCase, CreateTes
} }
@Test @Test
void resolved_test_case_deletes_sample_data(TestInfo test) throws IOException, ParseException { void test_testCaseInvalidEntityLinkTest(TestInfo testInfo) throws IOException {
CreateTestCase create = // Invalid entity link as not parsable by antlr parser
createRequest(test) String entityLink = "<#E::table::special!@#$%^&*()_+[]{}|;:\\'\",./?>";
.withEntityLink(TABLE_LINK) CreateTestCase create = createRequest(testInfo);
.withTestSuite(TEST_SUITE1.getFullyQualifiedName()) create
.withTestDefinition(TEST_DEFINITION3.getFullyQualifiedName()) .withEntityLink(entityLink)
.withParameterValues( .withTestSuite(TEST_SUITE1.getFullyQualifiedName())
List.of( .withTestDefinition(TEST_DEFINITION3.getFullyQualifiedName())
new TestCaseParameterValue().withValue("100").withName("missingCountValue"))); .withParameterValues(
TestCase testCase = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); List.of(new TestCaseParameterValue().withValue("100").withName("missingCountValue")));
List<String> columns = Arrays.asList(C1, C2, C3);
// Add 3 rows of sample data for 3 columns assertThrows(
List<List<Object>> rows = HttpResponseException.class,
Arrays.asList( () -> createAndCheckEntity(create, ADMIN_AUTH_HEADERS),
Arrays.asList("c1Value1", 1, true), "entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"");
Arrays.asList("c1Value2", null, false),
Arrays.asList("c1Value3", 3, true));
putTestCaseResult( entityLink = "<#E::table::user<name>::column>";
testCase.getFullyQualifiedName(), create.setEntityLink(entityLink);
new TestCaseResult() assertThrows(
.withResult("result") HttpResponseException.class,
.withTestCaseStatus(TestCaseStatus.Failed) () -> createAndCheckEntity(create, ADMIN_AUTH_HEADERS),
.withTimestamp(TestUtils.dateToTimestamp("2024-01-01")), "entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"");
ADMIN_AUTH_HEADERS);
putFailedRowsSample(testCase, columns, rows, ADMIN_AUTH_HEADERS); entityLink = "<#E::table::user>name::column>";
create.setEntityLink(entityLink);
assertThrows(
HttpResponseException.class,
() -> createAndCheckEntity(create, ADMIN_AUTH_HEADERS),
"entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"");
// resolving test case deletes the sample data entityLink = "<#E::table::foo<>bar::baz>\");";
TestCaseResult testCaseResult = create.setEntityLink(entityLink);
new TestCaseResult() assertThrows(
.withResult("tested") HttpResponseException.class,
.withTestCaseStatus(TestCaseStatus.Success) () -> createAndCheckEntity(create, ADMIN_AUTH_HEADERS),
.withTimestamp(TestUtils.dateToTimestamp("2021-09-09")); "entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"");
putTestCaseResult(testCase.getFullyQualifiedName(), testCaseResult, ADMIN_AUTH_HEADERS);
assertResponse( entityLink = "<#E::table::::baz>";
() -> getSampleData(testCase.getId(), ADMIN_AUTH_HEADERS), create.setEntityLink(entityLink);
NOT_FOUND, assertThrows(
FAILED_ROWS_SAMPLE_EXTENSION + " instance for " + testCase.getId() + " not found"); HttpResponseException.class,
() -> createAndCheckEntity(create, ADMIN_AUTH_HEADERS),
"entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"");
} }
@Test private void putInspectionQuery(TestCase testCase, String sql) throws IOException {
void test_sensitivePIISampleData(TestInfo test) throws IOException, ParseException { TestCase putResponse = putInspectionQuery(testCase.getId(), sql, ADMIN_AUTH_HEADERS);
// Create table with owner and a column tagged with PII.Sensitive
TableResourceTest tableResourceTest = new TableResourceTest();
CreateTable tableReq = getSensitiveTableReq(test, tableResourceTest);
Table sensitiveTable = tableResourceTest.createAndCheckEntity(tableReq, ADMIN_AUTH_HEADERS);
String sensitiveColumnLink =
String.format("<#E::table::%s::columns::%s>", sensitiveTable.getFullyQualifiedName(), C1);
CreateTestCase create =
createRequest(test)
.withEntityLink(sensitiveColumnLink)
.withTestSuite(TEST_SUITE1.getFullyQualifiedName())
.withTestDefinition(TEST_DEFINITION3.getFullyQualifiedName())
.withParameterValues(
List.of(
new TestCaseParameterValue().withValue("100").withName("missingCountValue")));
TestCase testCase = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
putTestCaseResult(
testCase.getFullyQualifiedName(),
new TestCaseResult()
.withResult("result")
.withTestCaseStatus(TestCaseStatus.Failed)
.withTimestamp(TestUtils.dateToTimestamp("2024-01-01")),
ADMIN_AUTH_HEADERS);
List<String> columns = List.of(C1);
// Add 3 rows of sample data
List<List<Object>> rows =
Arrays.asList(List.of("c1Value1"), List.of("c1Value2"), List.of("c1Value3"));
// add sample data
putFailedRowsSample(testCase, columns, rows, ADMIN_AUTH_HEADERS);
// assert values are not masked for the table owner
TableData data = getSampleData(testCase.getId(), authHeaders(USER1.getName()));
assertFalse(
data.getRows().stream()
.flatMap(List::stream)
.map(r -> r == null ? "" : r)
.map(Object::toString)
.anyMatch(MASKED_VALUE::equals));
// assert values are masked when is not the table owner
data = getSampleData(testCase.getId(), authHeaders(USER2.getName()));
assertEquals(
3,
data.getRows().stream()
.flatMap(List::stream)
.map(r -> r == null ? "" : r)
.map(Object::toString)
.filter(MASKED_VALUE::equals)
.count());
}
@Test
void test_addInspectionQuery(TestInfo test) throws IOException {
CreateTestCase create =
createRequest(test)
.withEntityLink(TABLE_LINK)
.withTestSuite(TEST_SUITE1.getFullyQualifiedName())
.withTestDefinition(TEST_DEFINITION3.getFullyQualifiedName())
.withParameterValues(
List.of(
new TestCaseParameterValue().withValue("100").withName("missingCountValue")));
TestCase testCase = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
String inspectionQuery = "SELECT * FROM test_table WHERE column1 = 'value1'";
putInspectionQuery(testCase, inspectionQuery, ADMIN_AUTH_HEADERS);
TestCase updated = getTestCase(testCase.getFullyQualifiedName(), ADMIN_AUTH_HEADERS);
assertEquals(updated.getInspectionQuery(), inspectionQuery);
}
@Test
@Execution(ExecutionMode.CONCURRENT)
protected void post_entityCreateWithInvalidName_400() {
// Create an entity with mandatory name field null
final CreateTestCase request = createRequest(null, "description", "displayName", null);
assertResponseContains(
() -> createEntity(request, ADMIN_AUTH_HEADERS), BAD_REQUEST, "[name must not be null]");
// Create an entity with mandatory name field empty
final CreateTestCase request1 = createRequest("", "description", "displayName", null);
assertResponseContains(
() -> createEntity(request1, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
TestUtils.getEntityNameLengthError(entityClass));
// Any entity name that has EntityLink separator must fail
final CreateTestCase request3 =
createRequest("invalid::Name", "description", "displayName", null);
assertResponseContains(
() -> createEntity(request3, ADMIN_AUTH_HEADERS), BAD_REQUEST, "name must match");
}
@Test
void createUpdate_DynamicAssertionTests(TestInfo testInfo) throws IOException {
CreateTestCase create = createRequest(testInfo).withUseDynamicAssertion(true);
TestCase testCase = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
testCase = getTestCase(testCase.getFullyQualifiedName(), ADMIN_AUTH_HEADERS);
assertTrue(testCase.getUseDynamicAssertion());
CreateTestCase update = create.withUseDynamicAssertion(false);
updateEntity(update, OK, ADMIN_AUTH_HEADERS);
testCase = getTestCase(testCase.getFullyQualifiedName(), ADMIN_AUTH_HEADERS);
assertFalse(testCase.getUseDynamicAssertion());
}
private void putInspectionQuery(TestCase testCase, String sql, Map<String, String> authHeaders)
throws IOException {
TestCase putResponse = putInspectionQuery(testCase.getId(), sql, authHeaders);
assertEquals(sql, putResponse.getInspectionQuery()); assertEquals(sql, putResponse.getInspectionQuery());
} }

View File

@ -98,8 +98,9 @@ public class EventSubscriptionResourceTest
@Test @Test
void post_alertActionWithEnabledStateChange(TestInfo test) throws IOException { void post_alertActionWithEnabledStateChange(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
LOG.info("creating webhook in disabled state"); LOG.info("creating webhook in disabled state");
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + endpoint;
// Create a Disabled Generic Webhook // Create a Disabled Generic Webhook
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName).withEnabled(false).withDestinations(getWebhook(uri)); createRequest(webhookName).withEnabled(false).withDestinations(getWebhook(uri));
@ -108,7 +109,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(DISABLED, status.getStatus()); assertEquals(DISABLED, status.getStatus());
WebhookCallbackResource.EventDetails details = WebhookCallbackResource.EventDetails details =
webhookCallbackResource.getEventDetails(webhookName); webhookCallbackResource.getEventDetails(endpoint);
assertNull(details); assertNull(details);
// //
// Now enable the webhook // Now enable the webhook
@ -143,7 +144,7 @@ public class EventSubscriptionResourceTest
assertEquals(SubscriptionStatus.Status.ACTIVE, status2.getStatus()); assertEquals(SubscriptionStatus.Status.ACTIVE, status2.getStatus());
// Ensure the call back notification has started // Ensure the call back notification has started
details = waitForFirstEvent(alert.getId(), webhookName, 25); details = waitForFirstEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
SubscriptionStatus successDetails = SubscriptionStatus successDetails =
getStatus(alert.getId(), Response.Status.OK.getStatusCode()); getStatus(alert.getId(), Response.Status.OK.getStatusCode());
@ -454,7 +455,8 @@ public class EventSubscriptionResourceTest
@Test @Test
public void post_createAndValidateEventSubscription(TestInfo test) throws IOException { public void post_createAndValidateEventSubscription(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + endpoint;
CreateEventSubscription enabledWebhookRequest = CreateEventSubscription enabledWebhookRequest =
new CreateEventSubscription() new CreateEventSubscription()
@ -491,7 +493,8 @@ public class EventSubscriptionResourceTest
@Test @Test
public void post_duplicateAlertsAreNotAllowed(TestInfo test) throws IOException { public void post_duplicateAlertsAreNotAllowed(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + endpoint;
CreateEventSubscription genericWebhookRequest = CreateEventSubscription genericWebhookRequest =
new CreateEventSubscription() new CreateEventSubscription()
@ -599,7 +602,8 @@ public class EventSubscriptionResourceTest
@Test @Test
public void post_createAndValidateEventSubscription_SLACK(TestInfo test) throws IOException { public void post_createAndValidateEventSubscription_SLACK(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription enabledWebhookRequest = CreateEventSubscription enabledWebhookRequest =
new CreateEventSubscription() new CreateEventSubscription()
@ -614,7 +618,7 @@ public class EventSubscriptionResourceTest
EventSubscription alert = createEntity(enabledWebhookRequest, ADMIN_AUTH_HEADERS); EventSubscription alert = createEntity(enabledWebhookRequest, ADMIN_AUTH_HEADERS);
waitForAllEventToComplete(alert.getId()); waitForAllEventToComplete(alert.getId());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
ConcurrentLinkedQueue<SlackMessage> events = details.getEvents(); ConcurrentLinkedQueue<SlackMessage> events = details.getEvents();
for (SlackMessage event : events) { for (SlackMessage event : events) {
validateSlackMessage(alert, event); validateSlackMessage(alert, event);
@ -675,8 +679,9 @@ public class EventSubscriptionResourceTest
@Test @Test
void post_tableResource_filterByOwner_alertAction(TestInfo test) throws IOException { void post_tableResource_filterByOwner_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
TableResourceTest tableResourceTest = new TableResourceTest(); TableResourceTest tableResourceTest = new TableResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create the event subscription request with the Slack destination and table as the resource // Create the event subscription request with the Slack destination and table as the resource
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
@ -700,7 +705,7 @@ public class EventSubscriptionResourceTest
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
// Verify no Slack events triggered initially // Verify no Slack events triggered initially
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
assertNull(details); assertNull(details);
// Create a table with a different owner (USER2), expect no alert // Create a table with a different owner (USER2), expect no alert
@ -709,14 +714,14 @@ public class EventSubscriptionResourceTest
.createRequest(test.getClass().getName() + generateUniqueNumberAsString()) .createRequest(test.getClass().getName() + generateUniqueNumberAsString())
.withOwners(List.of(USER2.getEntityReference())); .withOwners(List.of(USER2.getEntityReference()));
tableResourceTest.createEntity(createTable1, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable1, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertNull(details); assertNull(details);
// Create another table with the owner that matches the filter (USER_TEAM21), expect an alert // Create another table with the owner that matches the filter (USER_TEAM21), expect an alert
CreateTable createTable = CreateTable createTable =
tableResourceTest.createRequest(test).withOwners(List.of(USER_TEAM21.getEntityReference())); tableResourceTest.createRequest(test).withOwners(List.of(USER_TEAM21.getEntityReference()));
Table table = tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS); Table table = tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
// Clean up: delete the event subscription and created tables // Clean up: delete the event subscription and created tables
@ -728,7 +733,8 @@ public class EventSubscriptionResourceTest
void post_tableResource_filterByDomain_alertAction(TestInfo test) throws IOException { void post_tableResource_filterByDomain_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
TableResourceTest tableResourceTest = new TableResourceTest(); TableResourceTest tableResourceTest = new TableResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create the event subscription request with the Slack destination and table resource with // Create the event subscription request with the Slack destination and table resource with
// filterByDomain // filterByDomain
@ -754,7 +760,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
assertNull(details); assertNull(details);
CreateDomain createDomain2 = domainResourceTest.createRequest("Engineering_2"); CreateDomain createDomain2 = domainResourceTest.createRequest("Engineering_2");
@ -762,7 +768,7 @@ public class EventSubscriptionResourceTest
CreateTable createTable = CreateTable createTable =
tableResourceTest.createRequest(test).withDomain(domainSecond.getName()); tableResourceTest.createRequest(test).withDomain(domainSecond.getName());
tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
// changeEvent on the table with correct domain will result in alerts // changeEvent on the table with correct domain will result in alerts
assertNull(details); assertNull(details);
@ -771,7 +777,7 @@ public class EventSubscriptionResourceTest
.createRequest(test.getClass().getName() + "_secondTable") .createRequest(test.getClass().getName() + "_secondTable")
.withDomain(domain.getName()); .withDomain(domain.getName());
tableResourceTest.createEntity(createTable2, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable2, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@ -779,7 +785,8 @@ public class EventSubscriptionResourceTest
void post_tableResource_fqnFilter_alertAction(TestInfo test) throws IOException { void post_tableResource_fqnFilter_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
TableResourceTest tableResourceTest = new TableResourceTest(); TableResourceTest tableResourceTest = new TableResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create the event subscription request with slack destination and table as the resource with // Create the event subscription request with slack destination and table as the resource with
// filterByFqn // filterByFqn
@ -798,20 +805,20 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// alerts will trigger on the changeEvent of table resource // alerts will trigger on the changeEvent of table resource
assertNull(details); assertNull(details);
CreateTable createTable = CreateTable createTable =
tableResourceTest.createRequest(test.getClass().getName() + generateUniqueNumberAsString()); tableResourceTest.createRequest(test.getClass().getName() + generateUniqueNumberAsString());
Table table1 = tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS); Table table1 = tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
// alerts will trigger on the changeEvent of table resource with correct fqn // alerts will trigger on the changeEvent of table resource with correct fqn
assertNull(details); assertNull(details);
CreateTable createTable2 = tableResourceTest.createRequest(test).withName("test"); CreateTable createTable2 = tableResourceTest.createRequest(test).withName("test");
Table table2 = tableResourceTest.createEntity(createTable2, ADMIN_AUTH_HEADERS); Table table2 = tableResourceTest.createEntity(createTable2, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
tableResourceTest.deleteEntity(table1.getId(), ADMIN_AUTH_HEADERS); tableResourceTest.deleteEntity(table1.getId(), ADMIN_AUTH_HEADERS);
@ -821,7 +828,8 @@ public class EventSubscriptionResourceTest
@Test @Test
void post_excluded_filters_alertAction(TestInfo test) throws IOException { void post_excluded_filters_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create the event subscription request with the Slack destination and table resource // Create the event subscription request with the Slack destination and table resource
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
@ -841,7 +849,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
assertNull(details); assertNull(details);
TableResourceTest tableResourceTest = new TableResourceTest(); TableResourceTest tableResourceTest = new TableResourceTest();
@ -851,7 +859,7 @@ public class EventSubscriptionResourceTest
tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
// Wait for the slack event and verify its details // Wait for the slack event and verify its details
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
// filters are EXCLUDED // filters are EXCLUDED
assertNull(details); assertNull(details);
@ -862,7 +870,8 @@ public class EventSubscriptionResourceTest
void post_tableResource_filterByOwner_AND_filterByDomain_Filter_alertAction(TestInfo test) void post_tableResource_filterByOwner_AND_filterByDomain_Filter_alertAction(TestInfo test)
throws IOException { throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create the event subscription request with the Slack destination and table resource with // Create the event subscription request with the Slack destination and table resource with
// filterByOwner AND filterByDomain // filterByOwner AND filterByDomain
@ -894,7 +903,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
assertNull(details); assertNull(details);
// wrong owner and correct domain -> no alerts // wrong owner and correct domain -> no alerts
@ -906,7 +915,7 @@ public class EventSubscriptionResourceTest
.withOwners(List.of(USER1.getEntityReference())) .withOwners(List.of(USER1.getEntityReference()))
.withDomain(domain.getName()); .withDomain(domain.getName());
tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertNull(details); assertNull(details);
// correct owner and wrong domain -> no alerts // correct owner and wrong domain -> no alerts
@ -920,7 +929,7 @@ public class EventSubscriptionResourceTest
.withOwners(List.of(USER1.getEntityReference())) .withOwners(List.of(USER1.getEntityReference()))
.withDomain(domain2.getName()); .withDomain(domain2.getName());
tableResourceTest.createEntity(createTable2, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable2, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertNull(details); assertNull(details);
// correcr owner and correct domain -> alerts // correcr owner and correct domain -> alerts
@ -933,7 +942,7 @@ public class EventSubscriptionResourceTest
Table table = tableResourceTest.createEntity(createTable3, ADMIN_AUTH_HEADERS); Table table = tableResourceTest.createEntity(createTable3, ADMIN_AUTH_HEADERS);
// Wait for the slack event and verify its details // Wait for the slack event and verify its details
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
tableResourceTest.deleteEntity(table.getId(), ADMIN_AUTH_HEADERS); tableResourceTest.deleteEntity(table.getId(), ADMIN_AUTH_HEADERS);
} }
@ -942,7 +951,8 @@ public class EventSubscriptionResourceTest
void post_tableResource_noFilters_alertAction(TestInfo test) throws IOException { void post_tableResource_noFilters_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
TableResourceTest tableResourceTest = new TableResourceTest(); TableResourceTest tableResourceTest = new TableResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create the event subscription request with the Slack destination and table as the resource // Create the event subscription request with the Slack destination and table as the resource
// without any filters // without any filters
@ -955,7 +965,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// alerts will trigger on the changeEvent of table resource // alerts will trigger on the changeEvent of table resource
assertNull(details); assertNull(details);
@ -964,14 +974,15 @@ public class EventSubscriptionResourceTest
tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS); tableResourceTest.createEntity(createTable, ADMIN_AUTH_HEADERS);
// Wait for the slack event and verify its details // Wait for the slack event and verify its details
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@Test @Test
void post_topicResource_noFilters_alertAction(TestInfo test) throws IOException { void post_topicResource_noFilters_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -981,7 +992,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by ChangeEvent occurrences related to resources as topic // Alerts are triggered only by ChangeEvent occurrences related to resources as topic
assertNull(details); assertNull(details);
@ -993,15 +1004,16 @@ public class EventSubscriptionResourceTest
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@Test @Test
void post_topicResource_filterByFqn_alertAction(TestInfo test) throws IOException { void post_topicResource_filterByFqn_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
TopicResourceTest topicResourceTest = new TopicResourceTest(); TopicResourceTest topicResourceTest = new TopicResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -1020,7 +1032,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by changeEvent occurrences related to resources as topic with // Alerts are triggered only by changeEvent occurrences related to resources as topic with
// filterByFqn // filterByFqn
@ -1031,7 +1043,7 @@ public class EventSubscriptionResourceTest
.createRequest(test) .createRequest(test)
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
// changeEvents associated with correct fqn will result in alerts // changeEvents associated with correct fqn will result in alerts
assertNull(details); assertNull(details);
@ -1041,15 +1053,16 @@ public class EventSubscriptionResourceTest
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest2, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest2, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@Test @Test
void post_topicResource_domain_alertAction(TestInfo test) throws IOException { void post_topicResource_domain_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
TopicResourceTest topicResourceTest = new TopicResourceTest(); TopicResourceTest topicResourceTest = new TopicResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -1072,7 +1085,7 @@ public class EventSubscriptionResourceTest
EventSubscription alert = createAndCheckEntity(genericWebhookActionRequest, ADMIN_AUTH_HEADERS); EventSubscription alert = createAndCheckEntity(genericWebhookActionRequest, ADMIN_AUTH_HEADERS);
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by ChangeEvent occurrences related to resources as topic by // Alerts are triggered only by ChangeEvent occurrences related to resources as topic by
// filterByDomain // filterByDomain
@ -1085,15 +1098,16 @@ public class EventSubscriptionResourceTest
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@Test @Test
void post_topicResource_owner_alertAction(TestInfo test) throws IOException { void post_topicResource_owner_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
TopicResourceTest topicResourceTest = new TopicResourceTest(); TopicResourceTest topicResourceTest = new TopicResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -1110,7 +1124,7 @@ public class EventSubscriptionResourceTest
EventSubscription alert = createAndCheckEntity(genericWebhookActionRequest, ADMIN_AUTH_HEADERS); EventSubscription alert = createAndCheckEntity(genericWebhookActionRequest, ADMIN_AUTH_HEADERS);
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by changeEvent occurrences related to resources as topic by // Alerts are triggered only by changeEvent occurrences related to resources as topic by
// filerByOwner // filerByOwner
@ -1123,7 +1137,7 @@ public class EventSubscriptionResourceTest
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@ -1131,8 +1145,9 @@ public class EventSubscriptionResourceTest
void post_topicResource_owner_AND_domain_alertAction(TestInfo test) throws IOException { void post_topicResource_owner_AND_domain_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
DomainResourceTest domainResourceTest = new DomainResourceTest(); DomainResourceTest domainResourceTest = new DomainResourceTest();
String endpoint = test.getDisplayName();
TopicResourceTest topicResourceTest = new TopicResourceTest(); TopicResourceTest topicResourceTest = new TopicResourceTest();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -1160,7 +1175,7 @@ public class EventSubscriptionResourceTest
EventSubscription alert = createAndCheckEntity(genericWebhookActionRequest, ADMIN_AUTH_HEADERS); EventSubscription alert = createAndCheckEntity(genericWebhookActionRequest, ADMIN_AUTH_HEADERS);
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by ChangeEvent occurrences related to resources as topic by // Alerts are triggered only by ChangeEvent occurrences related to resources as topic by
// filterByDomain // filterByDomain
@ -1175,7 +1190,7 @@ public class EventSubscriptionResourceTest
.withDomain(domain.getName()) .withDomain(domain.getName())
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertNull(details); assertNull(details);
// correct owner AND wrong domain -> no alerts // correct owner AND wrong domain -> no alerts
@ -1190,7 +1205,7 @@ public class EventSubscriptionResourceTest
.withDomain(domain2.getName()) .withDomain(domain2.getName())
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest2, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest2, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertNull(details); assertNull(details);
// correct owner AND correct domain -> alerts // correct owner AND correct domain -> alerts
@ -1202,14 +1217,15 @@ public class EventSubscriptionResourceTest
.withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields)); .withMessageSchema(TopicResourceTest.SCHEMA.withSchemaFields(TopicResourceTest.fields));
topicResourceTest.createEntity(topicRequest3, ADMIN_AUTH_HEADERS); topicResourceTest.createEntity(topicRequest3, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@Test @Test
void post_ingestionPiplelineResource_noFilter_alertAction(TestInfo test) throws IOException { void post_ingestionPiplelineResource_noFilter_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -1220,7 +1236,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by ChangeEvent occurrences related to resources as // Alerts are triggered only by ChangeEvent occurrences related to resources as
// ingestionPipeline by domain filter // ingestionPipeline by domain filter
@ -1244,15 +1260,16 @@ public class EventSubscriptionResourceTest
ingestionPipelineResourceTest.createEntity(request, ADMIN_AUTH_HEADERS); ingestionPipelineResourceTest.createEntity(request, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@Test @Test
void post_ingestionPiplelineResource_owner_alertAction(TestInfo test) throws IOException { void post_ingestionPiplelineResource_owner_alertAction(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
LOG.info("creating webhook in disabled state"); LOG.info("creating webhook in disabled state");
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
createRequest(webhookName) createRequest(webhookName)
@ -1272,7 +1289,7 @@ public class EventSubscriptionResourceTest
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(ACTIVE, status.getStatus()); assertEquals(ACTIVE, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
// Alerts are triggered only by ChangeEvent occurrences related to resources as // Alerts are triggered only by ChangeEvent occurrences related to resources as
// ingestionPipeline // ingestionPipeline
@ -1296,7 +1313,7 @@ public class EventSubscriptionResourceTest
ingestionPipelineResourceTest.createEntity(request, ADMIN_AUTH_HEADERS); ingestionPipelineResourceTest.createEntity(request, ADMIN_AUTH_HEADERS);
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
} }
@ -1307,8 +1324,9 @@ public class EventSubscriptionResourceTest
@Test @Test
void post_alertActionWithEnabledStateChange_SLACK(TestInfo test) throws IOException { void post_alertActionWithEnabledStateChange_SLACK(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
LOG.info("creating webhook in disabled state"); LOG.info("creating webhook in disabled state");
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/slack/" + endpoint;
// Create a Disabled Generic Webhook // Create a Disabled Generic Webhook
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
@ -1318,7 +1336,7 @@ public class EventSubscriptionResourceTest
// For the DISABLED Publisher are not available, so it will have no status // For the DISABLED Publisher are not available, so it will have no status
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(DISABLED, status.getStatus()); assertEquals(DISABLED, status.getStatus());
SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(webhookName); SlackCallbackResource.EventDetails details = slackCallbackResource.getEventDetails(endpoint);
assertNull(details); assertNull(details);
LOG.info("Enabling webhook Action"); LOG.info("Enabling webhook Action");
@ -1339,7 +1357,7 @@ public class EventSubscriptionResourceTest
assertEquals(SubscriptionStatus.Status.ACTIVE, status2.getStatus()); assertEquals(SubscriptionStatus.Status.ACTIVE, status2.getStatus());
// Ensure the call back notification has started // Ensure the call back notification has started
details = waitForFirstSlackEvent(alert.getId(), webhookName, 25); details = waitForFirstSlackEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
ConcurrentLinkedQueue<SlackMessage> messages = details.getEvents(); ConcurrentLinkedQueue<SlackMessage> messages = details.getEvents();
for (SlackMessage sm : messages) { for (SlackMessage sm : messages) {
@ -1451,7 +1469,8 @@ public class EventSubscriptionResourceTest
@Test @Test
public void post_createAndValidateEventSubscription_MSTEAMS(TestInfo test) throws IOException { public void post_createAndValidateEventSubscription_MSTEAMS(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/msteams/" + webhookName; String endpoint = test.getDisplayName();
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/msteams/" + endpoint;
CreateEventSubscription enabledWebhookRequest = CreateEventSubscription enabledWebhookRequest =
new CreateEventSubscription() new CreateEventSubscription()
@ -1466,8 +1485,7 @@ public class EventSubscriptionResourceTest
EventSubscription alert = createEntity(enabledWebhookRequest, ADMIN_AUTH_HEADERS); EventSubscription alert = createEntity(enabledWebhookRequest, ADMIN_AUTH_HEADERS);
waitForAllEventToComplete(alert.getId()); waitForAllEventToComplete(alert.getId());
MSTeamsCallbackResource.EventDetails details = MSTeamsCallbackResource.EventDetails details = teamsCallbackResource.getEventDetails(endpoint);
teamsCallbackResource.getEventDetails(webhookName);
Awaitility.await() Awaitility.await()
.pollInterval(Duration.ofMillis(100L)) .pollInterval(Duration.ofMillis(100L))
@ -1495,8 +1513,9 @@ public class EventSubscriptionResourceTest
@Test @Test
void post_alertActionWithEnabledStateChange_MSTeams(TestInfo test) throws IOException { void post_alertActionWithEnabledStateChange_MSTeams(TestInfo test) throws IOException {
String webhookName = getEntityName(test); String webhookName = getEntityName(test);
String endpoint = test.getDisplayName();
LOG.info("creating webhook in disabled state"); LOG.info("creating webhook in disabled state");
String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/msteams/" + webhookName; String uri = "http://localhost:" + APP.getLocalPort() + "/api/v1/test/msteams/" + endpoint;
// Create a Disabled Generic Webhook // Create a Disabled Generic Webhook
CreateEventSubscription genericWebhookActionRequest = CreateEventSubscription genericWebhookActionRequest =
@ -1506,8 +1525,7 @@ public class EventSubscriptionResourceTest
// For the DISABLED Publisher are not available, so it will have no status // For the DISABLED Publisher are not available, so it will have no status
SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode()); SubscriptionStatus status = getStatus(alert.getId(), Response.Status.OK.getStatusCode());
assertEquals(DISABLED, status.getStatus()); assertEquals(DISABLED, status.getStatus());
MSTeamsCallbackResource.EventDetails details = MSTeamsCallbackResource.EventDetails details = teamsCallbackResource.getEventDetails(endpoint);
teamsCallbackResource.getEventDetails(webhookName);
assertNull(details); assertNull(details);
LOG.info("Enabling webhook Action"); LOG.info("Enabling webhook Action");
@ -1528,7 +1546,7 @@ public class EventSubscriptionResourceTest
assertEquals(SubscriptionStatus.Status.ACTIVE, status2.getStatus()); assertEquals(SubscriptionStatus.Status.ACTIVE, status2.getStatus());
// Ensure the call back notification has started // Ensure the call back notification has started
details = waitForFirstMSTeamsEvent(alert.getId(), webhookName, 25); details = waitForFirstMSTeamsEvent(alert.getId(), endpoint, 25);
assertEquals(1, details.getEvents().size()); assertEquals(1, details.getEvents().size());
ConcurrentLinkedQueue<TeamsMessage> messages = details.getEvents(); ConcurrentLinkedQueue<TeamsMessage> messages = details.getEvents();
for (TeamsMessage teamsMessage : messages) { for (TeamsMessage teamsMessage : messages) {

View File

@ -219,7 +219,8 @@ public class FeedResourceTest extends OpenMetadataApplicationTest {
// Create thread without addressed to entity in the request // Create thread without addressed to entity in the request
CreateThread create = create().withFrom(USER.getName()).withAbout("<>"); // Invalid EntityLink CreateThread create = create().withFrom(USER.getName()).withAbout("<>"); // Invalid EntityLink
String failureReason = "[about must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"]"; String failureReason =
"[about must match \"(?U)^<#E::\\w+::(?:[^:<>|]|:[^:<>|])+(?:::(?:[^:<>|]|:[^:<>|])+)*>$\"]";
assertResponseContains( assertResponseContains(
() -> createThread(create, USER_AUTH_HEADERS), BAD_REQUEST, failureReason); () -> createThread(create, USER_AUTH_HEADERS), BAD_REQUEST, failureReason);

View File

@ -153,7 +153,7 @@ public class SuggestionsResourceTest extends OpenMetadataApplicationTest {
CreateSuggestion create = create().withEntityLink("<>"); // Invalid EntityLink CreateSuggestion create = create().withEntityLink("<>"); // Invalid EntityLink
String failureReason = String failureReason =
"[entityLink must match \"(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$\"]"; "[entityLink must match \"(?U)^<#E::\\w+::(?:[^:<>|]|:[^:<>|])+(?:::(?:[^:<>|]|:[^:<>|])+)*>$\"]";
assertResponseContains( assertResponseContains(
() -> createSuggestion(create, USER_AUTH_HEADERS), BAD_REQUEST, failureReason); () -> createSuggestion(create, USER_AUTH_HEADERS), BAD_REQUEST, failureReason);

View File

@ -2,9 +2,12 @@ package org.openmetadata.service.util;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openmetadata.schema.entity.data.GlossaryTerm; import org.openmetadata.schema.entity.data.GlossaryTerm;
import org.openmetadata.schema.entity.data.Table; import org.openmetadata.schema.entity.data.Table;
import org.openmetadata.service.resources.feeds.MessageParser;
class EntityUtilTest { class EntityUtilTest {
@Test @Test
@ -15,4 +18,167 @@ class EntityUtilTest {
EntityUtil.isDescriptionRequired( EntityUtil.isDescriptionRequired(
GlossaryTerm.class)); // GlossaryTerm entity requires description GlossaryTerm.class)); // GlossaryTerm entity requires description
} }
@Test
void test_entityLinkParser() {
// Valid entity links
Map<String, String> expected = new HashMap<>();
expected.put("entityLink", "<#E::table::users>");
expected.put("arrayFieldName", null);
expected.put("arrayFieldValue", null);
expected.put("fieldName", null);
expected.put("entityFQN", "users");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY");
expected.put("fullyQualifiedFieldType", "table");
expected.put("fullyQualifiedFieldValue", "users");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::table::users.foo.\"bar.baz\">");
expected.put("arrayFieldName", null);
expected.put("arrayFieldValue", null);
expected.put("fieldName", null);
expected.put("entityFQN", "users.foo.\"bar.baz\"");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY");
expected.put("fullyQualifiedFieldType", "table");
expected.put("fullyQualifiedFieldValue", "users.foo.\"bar.baz\"");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::db::customers>");
expected.put("arrayFieldName", null);
expected.put("arrayFieldValue", null);
expected.put("fieldName", null);
expected.put("entityFQN", "customers");
expected.put("entityType", "db");
expected.put("linkType", "ENTITY");
expected.put("fullyQualifiedFieldType", "db");
expected.put("fullyQualifiedFieldValue", "customers");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::table::users::column::id>");
expected.put("arrayFieldName", "id");
expected.put("arrayFieldValue", null);
expected.put("fieldName", "column");
expected.put("entityFQN", "users");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY_ARRAY_FIELD");
expected.put("fullyQualifiedFieldType", "table.column.member");
expected.put("fullyQualifiedFieldValue", "users.id");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::table::orders::column::status::type::enum>");
expected.put("arrayFieldName", "status");
expected.put("arrayFieldValue", "type::enum");
expected.put("fieldName", "column");
expected.put("entityFQN", "orders");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY_ARRAY_FIELD");
expected.put("fullyQualifiedFieldType", "table.column.member");
expected.put("fullyQualifiedFieldValue", "orders.status.type::enum");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::db::schema::table::view::column>");
expected.put("arrayFieldName", "view");
expected.put("arrayFieldValue", "column");
expected.put("fieldName", "table");
expected.put("entityFQN", "schema");
expected.put("entityType", "db");
expected.put("linkType", "ENTITY_ARRAY_FIELD");
expected.put("fullyQualifiedFieldType", "db.table.member");
expected.put("fullyQualifiedFieldValue", "schema.view.column");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::table::foo@bar>");
expected.put("arrayFieldName", null);
expected.put("arrayFieldValue", null);
expected.put("fieldName", null);
expected.put("entityFQN", "foo@bar");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY");
expected.put("fullyQualifiedFieldType", "table");
expected.put("fullyQualifiedFieldValue", "foo@bar");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::table::foo[bar]>");
expected.put("arrayFieldName", null);
expected.put("arrayFieldValue", null);
expected.put("fieldName", null);
expected.put("entityFQN", "foo[bar]");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY");
expected.put("fullyQualifiedFieldType", "table");
expected.put("fullyQualifiedFieldValue", "foo[bar]");
verifyEntityLinkParser(expected);
expected.clear();
expected.put("entityLink", "<#E::table::special!@#$%^&*()_+[]{};:\\'\",./?>");
expected.put("arrayFieldName", null);
expected.put("arrayFieldValue", null);
expected.put("fieldName", null);
expected.put("entityFQN", "special!@#$%^&*()_+[]{};:\\'\",./?");
expected.put("entityType", "table");
expected.put("linkType", "ENTITY");
expected.put("fullyQualifiedFieldType", "table");
expected.put("fullyQualifiedFieldValue", "special!@#$%^&*()_+[]{};:\\'\",./?");
verifyEntityLinkParser(expected);
// Invalid entity link
expected.clear();
expected.put("entityLink", "<#E::table::special!@#$%^&*()_+[]{}|;:\\'\",./?>");
// EntityLink with `|` character will not be parsed correctly and everything after `|` will be
// ignored
org.opentest4j.AssertionFailedError exception =
assertThrows(
org.opentest4j.AssertionFailedError.class, () -> verifyEntityLinkParser(expected));
assertEquals(
"expected: <<#E::table::special!@#$%^&*()_+[]{}|;:\\'\",./?>> but was: <<#E::table::special!@#$%^&*()_+[]{}>>",
exception.getMessage());
expected.clear();
expected.put("entityLink", "<#E::table::user<name>::column>");
IllegalArgumentException argException =
assertThrows(IllegalArgumentException.class, () -> verifyEntityLinkParser(expected));
assertEquals(
"Entity link was not found in <#E::table::user<name>::column>", argException.getMessage());
expected.clear();
expected.put("entityLink", "<#E::table::user>name::column>");
exception =
assertThrows(
org.opentest4j.AssertionFailedError.class, () -> verifyEntityLinkParser(expected));
assertEquals(
"expected: <<#E::table::user>name::column>> but was: <<#E::table::user>>",
exception.getMessage());
expected.clear();
expected.put("entityLink", "<#E::table::foo<>bar::baz>");
argException =
assertThrows(IllegalArgumentException.class, () -> verifyEntityLinkParser(expected));
assertEquals(
"Entity link was not found in <#E::table::foo<>bar::baz>", argException.getMessage());
}
void verifyEntityLinkParser(Map<String, String> expected) {
MessageParser.EntityLink entityLink =
MessageParser.EntityLink.parse(expected.get("entityLink"));
assertEquals(expected.get("entityLink"), entityLink.getLinkString());
assertEquals(expected.get("arrayFieldName"), entityLink.getArrayFieldName());
assertEquals(expected.get("arrayFieldValue"), entityLink.getArrayFieldValue());
assertEquals(expected.get("entityType"), entityLink.getEntityType());
assertEquals(expected.get("fieldName"), entityLink.getFieldName());
assertEquals(expected.get("entityFQN"), entityLink.getEntityFQN());
assertEquals(expected.get("linkType"), entityLink.getLinkType().toString());
assertEquals(expected.get("fullyQualifiedFieldType"), entityLink.getFullyQualifiedFieldType());
assertEquals(
expected.get("fullyQualifiedFieldValue"), entityLink.getFullyQualifiedFieldValue());
}
} }

View File

@ -113,7 +113,7 @@
"entityLink": { "entityLink": {
"description": "Link to an entity or field within an entity using this format `<#E::{entities}::{entityType}::{field}::{arrayFieldName}::{arrayFieldValue}`.", "description": "Link to an entity or field within an entity using this format `<#E::{entities}::{entityType}::{field}::{arrayFieldName}::{arrayFieldValue}`.",
"type": "string", "type": "string",
"pattern": "(?U)^<#E::\\w+::[\\w'\\- .&/:+\"\\\\()$#%]+>$" "pattern": "(?U)^<#E::\\w+::(?:[^:<>|]|:[^:<>|])+(?:::(?:[^:<>|]|:[^:<>|])+)*>$"
}, },
"entityName": { "entityName": {
"description": "Name that identifies an entity.", "description": "Name that identifies an entity.",

View File

@ -23,6 +23,7 @@ import {
FormItemLayout, FormItemLayout,
} from '../../../../interface/FormUtils.interface'; } from '../../../../interface/FormUtils.interface';
import { generateFormFields } from '../../../../utils/formUtils'; import { generateFormFields } from '../../../../utils/formUtils';
import { escapeESReservedCharacters } from '../../../../utils/StringsUtils';
import { AddTestCaseList } from '../../AddTestCaseList/AddTestCaseList.component'; import { AddTestCaseList } from '../../AddTestCaseList/AddTestCaseList.component';
import { AddTestSuitePipelineProps } from '../AddDataQualityTest.interface'; import { AddTestSuitePipelineProps } from '../AddDataQualityTest.interface';
import './add-test-suite-pipeline.style.less'; import './add-test-suite-pipeline.style.less';
@ -142,7 +143,9 @@ const AddTestSuitePipeline = ({
]} ]}
valuePropName="selectedTest"> valuePropName="selectedTest">
<AddTestCaseList <AddTestCaseList
filters={`testSuite.fullyQualifiedName:${testSuiteFQN ?? fqn}`} filters={`testSuite.fullyQualifiedName:${escapeESReservedCharacters(
testSuiteFQN ?? fqn
)}`}
showButton={false} showButton={false}
/> />
</Form.Item> </Form.Item>