mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-11 16:58:38 +00:00
MINOR: feat(apps): support event subscriptions (#19338)
* feat(apps): support event subscriptions - added support for apps with event subscriptions. - added support for custom consumers on event subscriptions. - use native application methods instead of reflection in ApplicationHandler * removed runMethodFromApplication reflection and use concrete methods from AbstractNativeApplication * format
This commit is contained in:
parent
00a37c6180
commit
3abae45403
@ -1,5 +1,6 @@
|
|||||||
package org.openmetadata.service.apps;
|
package org.openmetadata.service.apps;
|
||||||
|
|
||||||
|
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
||||||
import static org.openmetadata.service.apps.scheduler.AppScheduler.APPS_JOB_GROUP;
|
import static org.openmetadata.service.apps.scheduler.AppScheduler.APPS_JOB_GROUP;
|
||||||
import static org.openmetadata.service.apps.scheduler.AppScheduler.APP_INFO_KEY;
|
import static org.openmetadata.service.apps.scheduler.AppScheduler.APP_INFO_KEY;
|
||||||
import static org.openmetadata.service.apps.scheduler.AppScheduler.APP_NAME;
|
import static org.openmetadata.service.apps.scheduler.AppScheduler.APP_NAME;
|
||||||
@ -7,18 +8,29 @@ import static org.openmetadata.service.apps.scheduler.AppScheduler.APP_NAME;
|
|||||||
import io.dropwizard.configuration.ConfigurationException;
|
import io.dropwizard.configuration.ConfigurationException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.openmetadata.schema.api.configuration.apps.AppPrivateConfig;
|
import org.openmetadata.schema.api.configuration.apps.AppPrivateConfig;
|
||||||
import org.openmetadata.schema.entity.app.App;
|
import org.openmetadata.schema.entity.app.App;
|
||||||
|
import org.openmetadata.schema.entity.app.AppMarketPlaceDefinition;
|
||||||
|
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||||
|
import org.openmetadata.schema.type.EntityReference;
|
||||||
|
import org.openmetadata.schema.type.Include;
|
||||||
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
||||||
import org.openmetadata.service.apps.scheduler.AppScheduler;
|
import org.openmetadata.service.apps.scheduler.AppScheduler;
|
||||||
import org.openmetadata.service.exception.UnhandledServerException;
|
import org.openmetadata.service.events.scheduled.EventSubscriptionScheduler;
|
||||||
|
import org.openmetadata.service.exception.EntityNotFoundException;
|
||||||
|
import org.openmetadata.service.jdbi3.AppMarketPlaceRepository;
|
||||||
import org.openmetadata.service.jdbi3.AppRepository;
|
import org.openmetadata.service.jdbi3.AppRepository;
|
||||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
import org.openmetadata.service.jdbi3.EntityRepository;
|
import org.openmetadata.service.jdbi3.EntityRepository;
|
||||||
|
import org.openmetadata.service.jdbi3.EventSubscriptionRepository;
|
||||||
|
import org.openmetadata.service.resources.events.subscription.EventSubscriptionMapper;
|
||||||
import org.openmetadata.service.search.SearchRepository;
|
import org.openmetadata.service.search.SearchRepository;
|
||||||
import org.openmetadata.service.util.JsonUtils;
|
import org.openmetadata.service.util.JsonUtils;
|
||||||
import org.openmetadata.service.util.OpenMetadataConnectionBuilder;
|
import org.openmetadata.service.util.OpenMetadataConnectionBuilder;
|
||||||
@ -34,11 +46,15 @@ public class ApplicationHandler {
|
|||||||
@Getter private static ApplicationHandler instance;
|
@Getter private static ApplicationHandler instance;
|
||||||
private final OpenMetadataApplicationConfig config;
|
private final OpenMetadataApplicationConfig config;
|
||||||
private final AppRepository appRepository;
|
private final AppRepository appRepository;
|
||||||
|
private final AppMarketPlaceRepository appMarketPlaceRepository;
|
||||||
|
private final EventSubscriptionRepository eventSubscriptionRepository;
|
||||||
private final ConfigurationReader configReader = new ConfigurationReader();
|
private final ConfigurationReader configReader = new ConfigurationReader();
|
||||||
|
|
||||||
private ApplicationHandler(OpenMetadataApplicationConfig config) {
|
private ApplicationHandler(OpenMetadataApplicationConfig config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.appRepository = new AppRepository();
|
this.appRepository = new AppRepository();
|
||||||
|
this.appMarketPlaceRepository = new AppMarketPlaceRepository();
|
||||||
|
this.eventSubscriptionRepository = new EventSubscriptionRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initialize(OpenMetadataApplicationConfig config) {
|
public static void initialize(OpenMetadataApplicationConfig config) {
|
||||||
@ -80,25 +96,120 @@ public class ApplicationHandler {
|
|||||||
|
|
||||||
public void triggerApplicationOnDemand(
|
public void triggerApplicationOnDemand(
|
||||||
App app, CollectionDAO daoCollection, SearchRepository searchRepository) {
|
App app, CollectionDAO daoCollection, SearchRepository searchRepository) {
|
||||||
runMethodFromApplication(app, daoCollection, searchRepository, "triggerOnDemand");
|
try {
|
||||||
|
runAppInit(app, daoCollection, searchRepository).triggerOnDemand();
|
||||||
|
} catch (ClassNotFoundException
|
||||||
|
| NoSuchMethodException
|
||||||
|
| InvocationTargetException
|
||||||
|
| InstantiationException
|
||||||
|
| IllegalAccessException e) {
|
||||||
|
LOG.error("Failed to install application {}", app.getName(), e);
|
||||||
|
throw AppException.byMessage(
|
||||||
|
app.getName(), "triggerOnDemand", e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void installApplication(
|
public void installApplication(
|
||||||
App app, CollectionDAO daoCollection, SearchRepository searchRepository) {
|
App app, CollectionDAO daoCollection, SearchRepository searchRepository, String installedBy) {
|
||||||
runMethodFromApplication(app, daoCollection, searchRepository, "install");
|
try {
|
||||||
|
runAppInit(app, daoCollection, searchRepository).install();
|
||||||
|
installEventSubscriptions(app, installedBy);
|
||||||
|
} catch (ClassNotFoundException
|
||||||
|
| NoSuchMethodException
|
||||||
|
| InvocationTargetException
|
||||||
|
| InstantiationException
|
||||||
|
| IllegalAccessException e) {
|
||||||
|
LOG.error("Failed to install application {}", app.getName(), e);
|
||||||
|
throw AppException.byMessage(
|
||||||
|
app.getName(), "install", e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installEventSubscriptions(App app, String installedBy) {
|
||||||
|
AppMarketPlaceDefinition definition = appMarketPlaceRepository.getDefinition(app);
|
||||||
|
Map<String, EntityReference> eventSubscriptionsReferences =
|
||||||
|
listOrEmpty(app.getEventSubscriptions()).stream()
|
||||||
|
.collect(Collectors.toMap(EntityReference::getName, e -> e));
|
||||||
|
definition.getEventSubscriptions().stream()
|
||||||
|
.map(
|
||||||
|
request ->
|
||||||
|
Optional.ofNullable(eventSubscriptionsReferences.get(request.getName()))
|
||||||
|
.flatMap(
|
||||||
|
sub ->
|
||||||
|
Optional.ofNullable(
|
||||||
|
eventSubscriptionRepository.findByNameOrNull(
|
||||||
|
sub.getName(), Include.ALL)))
|
||||||
|
.orElseGet(
|
||||||
|
() -> {
|
||||||
|
EventSubscription createdEventSub =
|
||||||
|
eventSubscriptionRepository.create(
|
||||||
|
null,
|
||||||
|
// TODO need to get the actual user
|
||||||
|
new EventSubscriptionMapper()
|
||||||
|
.createToEntity(request, installedBy));
|
||||||
|
appRepository.addEventSubscription(app, createdEventSub);
|
||||||
|
return createdEventSub;
|
||||||
|
}))
|
||||||
|
.forEach(
|
||||||
|
eventSub -> {
|
||||||
|
try {
|
||||||
|
EventSubscriptionScheduler.getInstance().addSubscriptionPublisher(eventSub, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void configureApplication(
|
public void configureApplication(
|
||||||
App app, CollectionDAO daoCollection, SearchRepository searchRepository) {
|
App app, CollectionDAO daoCollection, SearchRepository searchRepository) {
|
||||||
runMethodFromApplication(app, daoCollection, searchRepository, "configure");
|
try {
|
||||||
|
runAppInit(app, daoCollection, searchRepository).configure();
|
||||||
|
} catch (ClassNotFoundException
|
||||||
|
| NoSuchMethodException
|
||||||
|
| InvocationTargetException
|
||||||
|
| InstantiationException
|
||||||
|
| IllegalAccessException e) {
|
||||||
|
LOG.error("Failed to configure application {}", app.getName(), e);
|
||||||
|
throw AppException.byMessage(
|
||||||
|
app.getName(), "configure", e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performCleanup(
|
public void performCleanup(
|
||||||
App app, CollectionDAO daoCollection, SearchRepository searchRepository) {
|
App app, CollectionDAO daoCollection, SearchRepository searchRepository, String deletedBy) {
|
||||||
runMethodFromApplication(app, daoCollection, searchRepository, "cleanup");
|
try {
|
||||||
|
runAppInit(app, daoCollection, searchRepository).cleanup();
|
||||||
|
} catch (ClassNotFoundException
|
||||||
|
| NoSuchMethodException
|
||||||
|
| InvocationTargetException
|
||||||
|
| InstantiationException
|
||||||
|
| IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
deleteEventSubscriptions(app, deletedBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object runAppInit(App app, CollectionDAO daoCollection, SearchRepository searchRepository)
|
private void deleteEventSubscriptions(App app, String deletedBy) {
|
||||||
|
listOrEmpty(app.getEventSubscriptions())
|
||||||
|
.forEach(
|
||||||
|
eventSubscriptionReference -> {
|
||||||
|
try {
|
||||||
|
EventSubscription eventSub =
|
||||||
|
eventSubscriptionRepository.find(
|
||||||
|
eventSubscriptionReference.getId(), Include.ALL);
|
||||||
|
EventSubscriptionScheduler.getInstance().deleteEventSubscriptionPublisher(eventSub);
|
||||||
|
eventSubscriptionRepository.delete(deletedBy, eventSub.getId(), false, true);
|
||||||
|
|
||||||
|
} catch (EntityNotFoundException e) {
|
||||||
|
LOG.debug("Event subscription {} not found", eventSubscriptionReference.getId());
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractNativeApplication runAppInit(
|
||||||
|
App app, CollectionDAO daoCollection, SearchRepository searchRepository)
|
||||||
throws ClassNotFoundException,
|
throws ClassNotFoundException,
|
||||||
NoSuchMethodException,
|
NoSuchMethodException,
|
||||||
InvocationTargetException,
|
InvocationTargetException,
|
||||||
@ -106,47 +217,21 @@ public class ApplicationHandler {
|
|||||||
IllegalAccessException {
|
IllegalAccessException {
|
||||||
// add private runtime properties
|
// add private runtime properties
|
||||||
setAppRuntimeProperties(app);
|
setAppRuntimeProperties(app);
|
||||||
Class<?> clz = Class.forName(app.getClassName());
|
Class<? extends AbstractNativeApplication> clz =
|
||||||
Object resource =
|
Class.forName(app.getClassName()).asSubclass(AbstractNativeApplication.class);
|
||||||
|
AbstractNativeApplication resource =
|
||||||
clz.getDeclaredConstructor(CollectionDAO.class, SearchRepository.class)
|
clz.getDeclaredConstructor(CollectionDAO.class, SearchRepository.class)
|
||||||
.newInstance(daoCollection, searchRepository);
|
.newInstance(daoCollection, searchRepository);
|
||||||
|
|
||||||
// Raise preview message if the app is in Preview mode
|
// Raise preview message if the app is in Preview mode
|
||||||
if (Boolean.TRUE.equals(app.getPreview())) {
|
if (Boolean.TRUE.equals(app.getPreview())) {
|
||||||
Method preview = resource.getClass().getMethod("raisePreviewMessage", App.class);
|
resource.raisePreviewMessage(app);
|
||||||
preview.invoke(resource, app);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call init Method
|
resource.init(app);
|
||||||
Method initMethod = resource.getClass().getMethod("init", App.class);
|
|
||||||
initMethod.invoke(resource, app);
|
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load an App from its className and call its methods dynamically
|
|
||||||
*/
|
|
||||||
public void runMethodFromApplication(
|
|
||||||
App app, CollectionDAO daoCollection, SearchRepository searchRepository, String methodName) {
|
|
||||||
// Native Application
|
|
||||||
setAppRuntimeProperties(app);
|
|
||||||
try {
|
|
||||||
Object resource = runAppInit(app, daoCollection, searchRepository);
|
|
||||||
// Call method on demand
|
|
||||||
Method scheduleMethod = resource.getClass().getMethod(methodName);
|
|
||||||
scheduleMethod.invoke(resource);
|
|
||||||
|
|
||||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
|
|
||||||
LOG.error("Exception encountered", e);
|
|
||||||
throw new UnhandledServerException(e.getMessage());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new UnhandledServerException(e.getMessage());
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw AppException.byMessage(app.getName(), methodName, e.getTargetException().getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void migrateQuartzConfig(App application) throws SchedulerException {
|
public void migrateQuartzConfig(App application) throws SchedulerException {
|
||||||
JobDetail jobDetails =
|
JobDetail jobDetails =
|
||||||
AppScheduler.getInstance()
|
AppScheduler.getInstance()
|
||||||
|
@ -17,6 +17,7 @@ import static org.openmetadata.service.apps.bundles.changeEvent.AbstractEventCon
|
|||||||
import static org.openmetadata.service.apps.bundles.changeEvent.AbstractEventConsumer.ALERT_OFFSET_KEY;
|
import static org.openmetadata.service.apps.bundles.changeEvent.AbstractEventConsumer.ALERT_OFFSET_KEY;
|
||||||
import static org.openmetadata.service.events.subscription.AlertUtil.getStartingOffset;
|
import static org.openmetadata.service.events.subscription.AlertUtil.getStartingOffset;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -37,6 +38,7 @@ import org.openmetadata.schema.entity.events.SubscriptionDestination;
|
|||||||
import org.openmetadata.schema.entity.events.SubscriptionStatus;
|
import org.openmetadata.schema.entity.events.SubscriptionStatus;
|
||||||
import org.openmetadata.schema.type.ChangeEvent;
|
import org.openmetadata.schema.type.ChangeEvent;
|
||||||
import org.openmetadata.service.Entity;
|
import org.openmetadata.service.Entity;
|
||||||
|
import org.openmetadata.service.apps.bundles.changeEvent.AbstractEventConsumer;
|
||||||
import org.openmetadata.service.apps.bundles.changeEvent.AlertPublisher;
|
import org.openmetadata.service.apps.bundles.changeEvent.AlertPublisher;
|
||||||
import org.openmetadata.service.events.subscription.AlertUtil;
|
import org.openmetadata.service.events.subscription.AlertUtil;
|
||||||
import org.openmetadata.service.jdbi3.EntityRepository;
|
import org.openmetadata.service.jdbi3.EntityRepository;
|
||||||
@ -87,9 +89,23 @@ public class EventSubscriptionScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
public void addSubscriptionPublisher(EventSubscription eventSubscription)
|
public void addSubscriptionPublisher(EventSubscription eventSubscription, boolean reinstall)
|
||||||
throws SchedulerException {
|
throws SchedulerException,
|
||||||
AlertPublisher alertPublisher = new AlertPublisher();
|
ClassNotFoundException,
|
||||||
|
NoSuchMethodException,
|
||||||
|
InvocationTargetException,
|
||||||
|
InstantiationException,
|
||||||
|
IllegalAccessException {
|
||||||
|
Class<? extends AbstractEventConsumer> defaultClass = AlertPublisher.class;
|
||||||
|
Class<? extends AbstractEventConsumer> clazz =
|
||||||
|
Class.forName(
|
||||||
|
Optional.ofNullable(eventSubscription.getClassName())
|
||||||
|
.orElse(defaultClass.getCanonicalName()))
|
||||||
|
.asSubclass(AbstractEventConsumer.class);
|
||||||
|
AbstractEventConsumer publisher = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
if (reinstall && isSubscriptionRegistered(eventSubscription)) {
|
||||||
|
deleteEventSubscriptionPublisher(eventSubscription);
|
||||||
|
}
|
||||||
if (Boolean.FALSE.equals(
|
if (Boolean.FALSE.equals(
|
||||||
eventSubscription.getEnabled())) { // Only add webhook that is enabled for publishing events
|
eventSubscription.getEnabled())) { // Only add webhook that is enabled for publishing events
|
||||||
eventSubscription
|
eventSubscription
|
||||||
@ -111,7 +127,7 @@ public class EventSubscriptionScheduler {
|
|||||||
getSubscriptionStatusAtCurrentTime(SubscriptionStatus.Status.ACTIVE)));
|
getSubscriptionStatusAtCurrentTime(SubscriptionStatus.Status.ACTIVE)));
|
||||||
JobDetail jobDetail =
|
JobDetail jobDetail =
|
||||||
jobBuilder(
|
jobBuilder(
|
||||||
alertPublisher,
|
publisher,
|
||||||
eventSubscription,
|
eventSubscription,
|
||||||
String.format("%s", eventSubscription.getId().toString()));
|
String.format("%s", eventSubscription.getId().toString()));
|
||||||
Trigger trigger = trigger(eventSubscription);
|
Trigger trigger = trigger(eventSubscription);
|
||||||
@ -127,8 +143,17 @@ public class EventSubscriptionScheduler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSubscriptionRegistered(EventSubscription eventSubscription) {
|
||||||
|
try {
|
||||||
|
return alertsScheduler.checkExists(getJobKey(eventSubscription));
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
LOG.error("Failed to check if subscription is registered: {}", eventSubscription.getId(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private JobDetail jobBuilder(
|
private JobDetail jobBuilder(
|
||||||
AlertPublisher publisher, EventSubscription eventSubscription, String jobIdentity) {
|
AbstractEventConsumer publisher, EventSubscription eventSubscription, String jobIdentity) {
|
||||||
JobDataMap dataMap = new JobDataMap();
|
JobDataMap dataMap = new JobDataMap();
|
||||||
dataMap.put(ALERT_INFO_KEY, eventSubscription);
|
dataMap.put(ALERT_INFO_KEY, eventSubscription);
|
||||||
dataMap.put(ALERT_OFFSET_KEY, getStartingOffset(eventSubscription.getId()));
|
dataMap.put(ALERT_OFFSET_KEY, getStartingOffset(eventSubscription.getId()));
|
||||||
@ -158,7 +183,7 @@ public class EventSubscriptionScheduler {
|
|||||||
// Remove Existing Subscription Publisher
|
// Remove Existing Subscription Publisher
|
||||||
deleteEventSubscriptionPublisher(eventSubscription);
|
deleteEventSubscriptionPublisher(eventSubscription);
|
||||||
if (Boolean.TRUE.equals(eventSubscription.getEnabled())) {
|
if (Boolean.TRUE.equals(eventSubscription.getEnabled())) {
|
||||||
addSubscriptionPublisher(eventSubscription);
|
addSubscriptionPublisher(eventSubscription, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,6 +561,14 @@ public class EventSubscriptionScheduler {
|
|||||||
return Entity.getCollectionDAO().changeEventDAO().recordExists(id.toString()) > 0;
|
return Entity.getCollectionDAO().changeEventDAO().recordExists(id.toString()) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JobKey getJobKey(EventSubscription eventSubscription) {
|
||||||
|
return getJobKey(eventSubscription.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JobKey getJobKey(UUID subscriptionId) {
|
||||||
|
return new JobKey(subscriptionId.toString(), ALERT_JOB_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
public static void shutDown() throws SchedulerException {
|
public static void shutDown() throws SchedulerException {
|
||||||
LOG.info("Shutting Down Event Subscription Scheduler");
|
LOG.info("Shutting Down Event Subscription Scheduler");
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.openmetadata.service.jdbi3;
|
package org.openmetadata.service.jdbi3;
|
||||||
|
|
||||||
|
import org.openmetadata.schema.entity.app.App;
|
||||||
import org.openmetadata.schema.entity.app.AppMarketPlaceDefinition;
|
import org.openmetadata.schema.entity.app.AppMarketPlaceDefinition;
|
||||||
|
import org.openmetadata.schema.type.Include;
|
||||||
import org.openmetadata.service.Entity;
|
import org.openmetadata.service.Entity;
|
||||||
import org.openmetadata.service.resources.apps.AppMarketPlaceResource;
|
import org.openmetadata.service.resources.apps.AppMarketPlaceResource;
|
||||||
import org.openmetadata.service.util.EntityUtil;
|
import org.openmetadata.service.util.EntityUtil;
|
||||||
@ -24,6 +26,10 @@ public class AppMarketPlaceRepository extends EntityRepository<AppMarketPlaceDef
|
|||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AppMarketPlaceDefinition getDefinition(App app) {
|
||||||
|
return findByName(app.getName(), Include.NON_DELETED);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearFields(AppMarketPlaceDefinition entity, EntityUtil.Fields fields) {
|
public void clearFields(AppMarketPlaceDefinition entity, EntityUtil.Fields fields) {
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.openmetadata.service.jdbi3;
|
package org.openmetadata.service.jdbi3;
|
||||||
|
|
||||||
|
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.service.util.UserUtil.getUser;
|
import static org.openmetadata.service.util.UserUtil.getUser;
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import org.openmetadata.schema.entity.Bot;
|
|||||||
import org.openmetadata.schema.entity.app.App;
|
import org.openmetadata.schema.entity.app.App;
|
||||||
import org.openmetadata.schema.entity.app.AppExtension;
|
import org.openmetadata.schema.entity.app.AppExtension;
|
||||||
import org.openmetadata.schema.entity.app.AppRunRecord;
|
import org.openmetadata.schema.entity.app.AppRunRecord;
|
||||||
|
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||||
import org.openmetadata.schema.entity.teams.AuthenticationMechanism;
|
import org.openmetadata.schema.entity.teams.AuthenticationMechanism;
|
||||||
import org.openmetadata.schema.entity.teams.User;
|
import org.openmetadata.schema.entity.teams.User;
|
||||||
import org.openmetadata.schema.type.EntityReference;
|
import org.openmetadata.schema.type.EntityReference;
|
||||||
@ -380,6 +382,20 @@ public class AppRepository extends EntityRepository<App> {
|
|||||||
return new AppRepository.AppUpdater(original, updated, operation);
|
return new AppRepository.AppUpdater(original, updated, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addEventSubscription(App app, EventSubscription eventSubscription) {
|
||||||
|
addRelationship(
|
||||||
|
app.getId(),
|
||||||
|
eventSubscription.getId(),
|
||||||
|
Entity.APPLICATION,
|
||||||
|
Entity.EVENT_SUBSCRIPTION,
|
||||||
|
Relationship.CONTAINS);
|
||||||
|
List<EntityReference> newSubs = new ArrayList<>(listOrEmpty(app.getEventSubscriptions()));
|
||||||
|
newSubs.add(eventSubscription.getEntityReference());
|
||||||
|
App updated = JsonUtils.deepCopy(app, App.class).withEventSubscriptions(newSubs);
|
||||||
|
updated.setOpenMetadataServerConnection(null);
|
||||||
|
getUpdater(app, updated, EntityRepository.Operation.PATCH).update();
|
||||||
|
}
|
||||||
|
|
||||||
public class AppUpdater extends EntityUpdater {
|
public class AppUpdater extends EntityUpdater {
|
||||||
public AppUpdater(App original, App updated, Operation operation) {
|
public AppUpdater(App original, App updated, Operation operation) {
|
||||||
super(original, updated, operation);
|
super(original, updated, operation);
|
||||||
@ -391,6 +407,8 @@ public class AppRepository extends EntityRepository<App> {
|
|||||||
"appConfiguration", original.getAppConfiguration(), updated.getAppConfiguration());
|
"appConfiguration", original.getAppConfiguration(), updated.getAppConfiguration());
|
||||||
recordChange("appSchedule", original.getAppSchedule(), updated.getAppSchedule());
|
recordChange("appSchedule", original.getAppSchedule(), updated.getAppSchedule());
|
||||||
recordChange("bot", original.getBot(), updated.getBot());
|
recordChange("bot", original.getBot(), updated.getBot());
|
||||||
|
recordChange(
|
||||||
|
"eventSubscriptions", original.getEventSubscriptions(), updated.getEventSubscriptions());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,8 @@ public class AppMapper implements EntityMapper<App, CreateApp> {
|
|||||||
.withSourcePythonClass(marketPlaceDefinition.getSourcePythonClass())
|
.withSourcePythonClass(marketPlaceDefinition.getSourcePythonClass())
|
||||||
.withAllowConfiguration(marketPlaceDefinition.getAllowConfiguration())
|
.withAllowConfiguration(marketPlaceDefinition.getAllowConfiguration())
|
||||||
.withSystem(marketPlaceDefinition.getSystem())
|
.withSystem(marketPlaceDefinition.getSystem())
|
||||||
.withSupportsInterrupt(marketPlaceDefinition.getSupportsInterrupt());
|
.withSupportsInterrupt(marketPlaceDefinition.getSupportsInterrupt())
|
||||||
|
.withFullyQualifiedName(marketPlaceDefinition.getFullyQualifiedName());
|
||||||
|
|
||||||
// validate Bot if provided
|
// validate Bot if provided
|
||||||
validateAndAddBot(app, createAppRequest.getBot());
|
validateAndAddBot(app, createAppRequest.getBot());
|
||||||
|
@ -38,7 +38,8 @@ public class AppMarketPlaceMapper
|
|||||||
.withSourcePythonClass(create.getSourcePythonClass())
|
.withSourcePythonClass(create.getSourcePythonClass())
|
||||||
.withAllowConfiguration(create.getAllowConfiguration())
|
.withAllowConfiguration(create.getAllowConfiguration())
|
||||||
.withSystem(create.getSystem())
|
.withSystem(create.getSystem())
|
||||||
.withSupportsInterrupt(create.getSupportsInterrupt());
|
.withSupportsInterrupt(create.getSupportsInterrupt())
|
||||||
|
.withEventSubscriptions(create.getEventSubscriptions());
|
||||||
|
|
||||||
// Validate App
|
// Validate App
|
||||||
validateApplication(app);
|
validateApplication(app);
|
||||||
|
@ -2,6 +2,7 @@ package org.openmetadata.service.resources.apps;
|
|||||||
|
|
||||||
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
|
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
|
||||||
import static org.openmetadata.schema.type.Include.ALL;
|
import static org.openmetadata.schema.type.Include.ALL;
|
||||||
|
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
|
||||||
import static org.openmetadata.service.Entity.APPLICATION;
|
import static org.openmetadata.service.Entity.APPLICATION;
|
||||||
import static org.openmetadata.service.Entity.FIELD_OWNERS;
|
import static org.openmetadata.service.Entity.FIELD_OWNERS;
|
||||||
import static org.openmetadata.service.jdbi3.EntityRepository.getEntitiesFromSeedData;
|
import static org.openmetadata.service.jdbi3.EntityRepository.getEntitiesFromSeedData;
|
||||||
@ -133,18 +134,19 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
try {
|
try {
|
||||||
App app = getAppForInit(createApp.getName());
|
App app = getAppForInit(createApp.getName());
|
||||||
if (app == null) {
|
if (app == null) {
|
||||||
app =
|
app = mapper.createToEntity(createApp, ADMIN_USER_NAME);
|
||||||
mapper.createToEntity(createApp, "admin").withFullyQualifiedName(createApp.getName());
|
|
||||||
repository.initializeEntity(app);
|
repository.initializeEntity(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule
|
// Schedule
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(app, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
|
app, Entity.getCollectionDAO(), searchRepository, ADMIN_USER_NAME);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.error("Failed in Creation/Initialization of Application : {}", createApp.getName(), ex);
|
LOG.error("Failed in Creation/Initialization of Application : {}", createApp.getName(), ex);
|
||||||
|
repository.deleteByName("admin", createApp.getName(), false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,9 +620,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
new OperationContext(Entity.APPLICATION, MetadataOperation.CREATE));
|
new OperationContext(Entity.APPLICATION, MetadataOperation.CREATE));
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(app, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
ApplicationHandler.getInstance()
|
app,
|
||||||
.configureApplication(app, Entity.getCollectionDAO(), searchRepository);
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
}
|
}
|
||||||
// We don't want to store this information
|
// We don't want to store this information
|
||||||
unsetAppRuntimeProperties(app);
|
unsetAppRuntimeProperties(app);
|
||||||
@ -663,7 +667,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
App updatedApp = (App) response.getEntity();
|
App updatedApp = (App) response.getEntity();
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(updatedApp, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
|
updatedApp,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
}
|
}
|
||||||
// We don't want to store this information
|
// We don't want to store this information
|
||||||
unsetAppRuntimeProperties(updatedApp);
|
unsetAppRuntimeProperties(updatedApp);
|
||||||
@ -707,7 +715,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
App updatedApp = (App) response.getEntity();
|
App updatedApp = (App) response.getEntity();
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(updatedApp, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
|
updatedApp,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
}
|
}
|
||||||
// We don't want to store this information
|
// We don't want to store this information
|
||||||
unsetAppRuntimeProperties(updatedApp);
|
unsetAppRuntimeProperties(updatedApp);
|
||||||
@ -735,7 +747,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
AppScheduler.getInstance().deleteScheduledApplication(app);
|
AppScheduler.getInstance().deleteScheduledApplication(app);
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(app, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
|
app,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
}
|
}
|
||||||
// We don't want to store this information
|
// We don't want to store this information
|
||||||
unsetAppRuntimeProperties(app);
|
unsetAppRuntimeProperties(app);
|
||||||
@ -773,7 +789,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.performCleanup(app, Entity.getCollectionDAO(), searchRepository);
|
.performCleanup(
|
||||||
|
app,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
|
|
||||||
limits.invalidateCache(entityType);
|
limits.invalidateCache(entityType);
|
||||||
// Remove from Pipeline Service
|
// Remove from Pipeline Service
|
||||||
@ -810,7 +830,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.performCleanup(app, Entity.getCollectionDAO(), searchRepository);
|
.performCleanup(
|
||||||
|
app,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
|
|
||||||
// Remove from Pipeline Service
|
// Remove from Pipeline Service
|
||||||
deleteApp(securityContext, app);
|
deleteApp(securityContext, app);
|
||||||
@ -842,7 +866,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
App app = (App) response.getEntity();
|
App app = (App) response.getEntity();
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(app, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
|
app,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
}
|
}
|
||||||
// We don't want to store this information
|
// We don't want to store this information
|
||||||
unsetAppRuntimeProperties(app);
|
unsetAppRuntimeProperties(app);
|
||||||
@ -878,7 +906,12 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
repository.getByName(uriInfo, name, new EntityUtil.Fields(repository.getAllowedFields()));
|
repository.getByName(uriInfo, name, new EntityUtil.Fields(repository.getAllowedFields()));
|
||||||
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
if (SCHEDULED_TYPES.contains(app.getScheduleType())) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(app, repository.getDaoCollection(), searchRepository);
|
.installApplication(
|
||||||
|
app,
|
||||||
|
repository.getDaoCollection(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
|
|
||||||
return Response.status(Response.Status.OK).entity("App is Scheduled.").build();
|
return Response.status(Response.Status.OK).entity("App is Scheduled.").build();
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("App is not of schedule type Scheduled.");
|
throw new IllegalArgumentException("App is not of schedule type Scheduled.");
|
||||||
@ -912,15 +945,9 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
repository.getByName(uriInfo, name, new EntityUtil.Fields(repository.getAllowedFields()));
|
repository.getByName(uriInfo, name, new EntityUtil.Fields(repository.getAllowedFields()));
|
||||||
// The application will have the updated appConfiguration we can use to run the `configure`
|
// The application will have the updated appConfiguration we can use to run the `configure`
|
||||||
// logic
|
// logic
|
||||||
try {
|
ApplicationHandler.getInstance()
|
||||||
ApplicationHandler.getInstance()
|
.configureApplication(app, repository.getDaoCollection(), searchRepository);
|
||||||
.configureApplication(app, repository.getDaoCollection(), searchRepository);
|
return Response.status(Response.Status.OK).entity("App has been configured.").build();
|
||||||
return Response.status(Response.Status.OK).entity("App has been configured.").build();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
|
||||||
.entity(String.format("Error configuring app [%s]", e.getMessage()))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@ -1029,7 +1056,11 @@ public class AppResource extends EntityResource<App, AppRepository> {
|
|||||||
App app = repository.getByName(uriInfo, name, fields);
|
App app = repository.getByName(uriInfo, name, fields);
|
||||||
if (app.getAppType().equals(AppType.Internal)) {
|
if (app.getAppType().equals(AppType.Internal)) {
|
||||||
ApplicationHandler.getInstance()
|
ApplicationHandler.getInstance()
|
||||||
.installApplication(app, Entity.getCollectionDAO(), searchRepository);
|
.installApplication(
|
||||||
|
app,
|
||||||
|
Entity.getCollectionDAO(),
|
||||||
|
searchRepository,
|
||||||
|
securityContext.getUserPrincipal().getName());
|
||||||
return Response.status(Response.Status.OK).entity("Application Deployed").build();
|
return Response.status(Response.Status.OK).entity("Application Deployed").build();
|
||||||
} else {
|
} else {
|
||||||
if (!app.getPipelines().isEmpty()) {
|
if (!app.getPipelines().isEmpty()) {
|
||||||
|
@ -6,10 +6,14 @@ import static org.openmetadata.service.fernet.Fernet.encryptWebhookSecretKey;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import javax.ws.rs.BadRequestException;
|
||||||
import org.openmetadata.schema.api.events.CreateEventSubscription;
|
import org.openmetadata.schema.api.events.CreateEventSubscription;
|
||||||
import org.openmetadata.schema.entity.events.EventSubscription;
|
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||||
import org.openmetadata.schema.entity.events.SubscriptionDestination;
|
import org.openmetadata.schema.entity.events.SubscriptionDestination;
|
||||||
|
import org.openmetadata.service.apps.bundles.changeEvent.AbstractEventConsumer;
|
||||||
|
import org.openmetadata.service.apps.bundles.changeEvent.AlertPublisher;
|
||||||
import org.openmetadata.service.mapper.EntityMapper;
|
import org.openmetadata.service.mapper.EntityMapper;
|
||||||
|
|
||||||
public class EventSubscriptionMapper
|
public class EventSubscriptionMapper
|
||||||
@ -28,7 +32,20 @@ public class EventSubscriptionMapper
|
|||||||
.withProvider(create.getProvider())
|
.withProvider(create.getProvider())
|
||||||
.withRetries(create.getRetries())
|
.withRetries(create.getRetries())
|
||||||
.withPollInterval(create.getPollInterval())
|
.withPollInterval(create.getPollInterval())
|
||||||
.withInput(create.getInput());
|
.withInput(create.getInput())
|
||||||
|
.withClassName(
|
||||||
|
validateConsumerClass(
|
||||||
|
Optional.ofNullable(create.getClassName())
|
||||||
|
.orElse(AlertPublisher.class.getCanonicalName())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String validateConsumerClass(String className) {
|
||||||
|
try {
|
||||||
|
Class.forName(className).asSubclass(AbstractEventConsumer.class);
|
||||||
|
return className;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new BadRequestException("Consumer class not found: " + className);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SubscriptionDestination> getSubscriptions(
|
private List<SubscriptionDestination> getSubscriptions(
|
||||||
|
@ -27,6 +27,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
|||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -143,19 +144,18 @@ public class EventSubscriptionResource
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeEventSubscriptions() {
|
private void initializeEventSubscriptions() {
|
||||||
try {
|
CollectionDAO daoCollection = repository.getDaoCollection();
|
||||||
CollectionDAO daoCollection = repository.getDaoCollection();
|
daoCollection.eventSubscriptionDAO().listAllEventsSubscriptions().stream()
|
||||||
List<String> listAllEventsSubscriptions =
|
.map(obj -> JsonUtils.readValue(obj, EventSubscription.class))
|
||||||
daoCollection.eventSubscriptionDAO().listAllEventsSubscriptions();
|
.forEach(
|
||||||
List<EventSubscription> eventSubList =
|
subscription -> {
|
||||||
JsonUtils.readObjects(listAllEventsSubscriptions, EventSubscription.class);
|
try {
|
||||||
for (EventSubscription subscription : eventSubList) {
|
EventSubscriptionScheduler.getInstance()
|
||||||
EventSubscriptionScheduler.getInstance().addSubscriptionPublisher(subscription);
|
.addSubscriptionPublisher(subscription, true);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
} catch (Exception ex) {
|
LOG.error("Failed to initialize subscription: {}", subscription.getId(), ex);
|
||||||
// Starting application should not fail
|
}
|
||||||
LOG.warn("Exception during initializeEventSubscriptions", ex);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ -293,12 +293,17 @@ public class EventSubscriptionResource
|
|||||||
@Context UriInfo uriInfo,
|
@Context UriInfo uriInfo,
|
||||||
@Context SecurityContext securityContext,
|
@Context SecurityContext securityContext,
|
||||||
@Valid CreateEventSubscription request)
|
@Valid CreateEventSubscription request)
|
||||||
throws SchedulerException {
|
throws SchedulerException,
|
||||||
|
ClassNotFoundException,
|
||||||
|
InvocationTargetException,
|
||||||
|
NoSuchMethodException,
|
||||||
|
InstantiationException,
|
||||||
|
IllegalAccessException {
|
||||||
EventSubscription eventSub =
|
EventSubscription eventSub =
|
||||||
mapper.createToEntity(request, securityContext.getUserPrincipal().getName());
|
mapper.createToEntity(request, securityContext.getUserPrincipal().getName());
|
||||||
// Only one Creation is allowed
|
// Only one Creation is allowed
|
||||||
Response response = create(uriInfo, securityContext, eventSub);
|
Response response = create(uriInfo, securityContext, eventSub);
|
||||||
EventSubscriptionScheduler.getInstance().addSubscriptionPublisher(eventSub);
|
EventSubscriptionScheduler.getInstance().addSubscriptionPublisher(eventSub, false);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.openmetadata.service.resources.apps;
|
package org.openmetadata.service.resources.apps;
|
||||||
|
|
||||||
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||||
|
import static javax.ws.rs.core.Response.Status.CREATED;
|
||||||
|
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
|
||||||
import static javax.ws.rs.core.Response.Status.OK;
|
import static javax.ws.rs.core.Response.Status.OK;
|
||||||
import static org.openmetadata.common.utils.CommonUtil.listOf;
|
import static org.openmetadata.common.utils.CommonUtil.listOf;
|
||||||
import static org.openmetadata.schema.type.ColumnDataType.INT;
|
import static org.openmetadata.schema.type.ColumnDataType.INT;
|
||||||
@ -18,6 +20,7 @@ import java.time.Duration;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -27,6 +30,8 @@ import lombok.SneakyThrows;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.http.client.HttpResponseException;
|
import org.apache.http.client.HttpResponseException;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.openmetadata.common.utils.CommonUtil;
|
import org.openmetadata.common.utils.CommonUtil;
|
||||||
import org.openmetadata.schema.analytics.PageViewData;
|
import org.openmetadata.schema.analytics.PageViewData;
|
||||||
@ -34,23 +39,33 @@ import org.openmetadata.schema.analytics.ReportData;
|
|||||||
import org.openmetadata.schema.analytics.WebAnalyticEventData;
|
import org.openmetadata.schema.analytics.WebAnalyticEventData;
|
||||||
import org.openmetadata.schema.analytics.type.WebAnalyticEventType;
|
import org.openmetadata.schema.analytics.type.WebAnalyticEventType;
|
||||||
import org.openmetadata.schema.api.data.CreateTableProfile;
|
import org.openmetadata.schema.api.data.CreateTableProfile;
|
||||||
|
import org.openmetadata.schema.api.events.CreateEventSubscription;
|
||||||
import org.openmetadata.schema.api.services.CreateDatabaseService;
|
import org.openmetadata.schema.api.services.CreateDatabaseService;
|
||||||
import org.openmetadata.schema.entity.app.App;
|
import org.openmetadata.schema.entity.app.App;
|
||||||
|
import org.openmetadata.schema.entity.app.AppConfiguration;
|
||||||
import org.openmetadata.schema.entity.app.AppExtension;
|
import org.openmetadata.schema.entity.app.AppExtension;
|
||||||
import org.openmetadata.schema.entity.app.AppMarketPlaceDefinition;
|
import org.openmetadata.schema.entity.app.AppMarketPlaceDefinition;
|
||||||
import org.openmetadata.schema.entity.app.AppRunRecord;
|
import org.openmetadata.schema.entity.app.AppRunRecord;
|
||||||
import org.openmetadata.schema.entity.app.AppSchedule;
|
import org.openmetadata.schema.entity.app.AppSchedule;
|
||||||
|
import org.openmetadata.schema.entity.app.AppType;
|
||||||
import org.openmetadata.schema.entity.app.CreateApp;
|
import org.openmetadata.schema.entity.app.CreateApp;
|
||||||
import org.openmetadata.schema.entity.app.CreateAppMarketPlaceDefinitionReq;
|
import org.openmetadata.schema.entity.app.CreateAppMarketPlaceDefinitionReq;
|
||||||
|
import org.openmetadata.schema.entity.app.NativeAppPermission;
|
||||||
import org.openmetadata.schema.entity.app.ScheduleTimeline;
|
import org.openmetadata.schema.entity.app.ScheduleTimeline;
|
||||||
|
import org.openmetadata.schema.entity.app.ScheduleType;
|
||||||
|
import org.openmetadata.schema.entity.app.ScheduledExecutionContext;
|
||||||
import org.openmetadata.schema.entity.data.Database;
|
import org.openmetadata.schema.entity.data.Database;
|
||||||
import org.openmetadata.schema.entity.data.DatabaseSchema;
|
import org.openmetadata.schema.entity.data.DatabaseSchema;
|
||||||
import org.openmetadata.schema.entity.data.Table;
|
import org.openmetadata.schema.entity.data.Table;
|
||||||
|
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||||
import org.openmetadata.schema.entity.services.DatabaseService;
|
import org.openmetadata.schema.entity.services.DatabaseService;
|
||||||
import org.openmetadata.schema.entity.teams.User;
|
import org.openmetadata.schema.entity.teams.User;
|
||||||
import org.openmetadata.schema.type.AccessDetails;
|
import org.openmetadata.schema.type.AccessDetails;
|
||||||
|
import org.openmetadata.schema.type.ChangeEvent;
|
||||||
import org.openmetadata.schema.type.Column;
|
import org.openmetadata.schema.type.Column;
|
||||||
|
import org.openmetadata.schema.type.EventType;
|
||||||
import org.openmetadata.schema.type.LifeCycle;
|
import org.openmetadata.schema.type.LifeCycle;
|
||||||
|
import org.openmetadata.schema.type.ProviderType;
|
||||||
import org.openmetadata.schema.type.TableProfile;
|
import org.openmetadata.schema.type.TableProfile;
|
||||||
import org.openmetadata.service.Entity;
|
import org.openmetadata.service.Entity;
|
||||||
import org.openmetadata.service.apps.bundles.insights.utils.TimestampUtils;
|
import org.openmetadata.service.apps.bundles.insights.utils.TimestampUtils;
|
||||||
@ -62,6 +77,8 @@ import org.openmetadata.service.resources.EntityResourceTest;
|
|||||||
import org.openmetadata.service.resources.databases.DatabaseResourceTest;
|
import org.openmetadata.service.resources.databases.DatabaseResourceTest;
|
||||||
import org.openmetadata.service.resources.databases.DatabaseSchemaResourceTest;
|
import org.openmetadata.service.resources.databases.DatabaseSchemaResourceTest;
|
||||||
import org.openmetadata.service.resources.databases.TableResourceTest;
|
import org.openmetadata.service.resources.databases.TableResourceTest;
|
||||||
|
import org.openmetadata.service.resources.events.BaseCallbackResource;
|
||||||
|
import org.openmetadata.service.resources.events.EventSubscriptionResourceTest;
|
||||||
import org.openmetadata.service.resources.services.DatabaseServiceResourceTest;
|
import org.openmetadata.service.resources.services.DatabaseServiceResourceTest;
|
||||||
import org.openmetadata.service.resources.teams.UserResourceTest;
|
import org.openmetadata.service.resources.teams.UserResourceTest;
|
||||||
import org.openmetadata.service.security.SecurityUtil;
|
import org.openmetadata.service.security.SecurityUtil;
|
||||||
@ -384,11 +401,119 @@ public class AppsResourceTest extends EntityResourceTest<App, CreateApp> {
|
|||||||
"App does not support manual trigger.");
|
"App does not support manual trigger.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Test
|
||||||
|
void app_with_event_subscription() {
|
||||||
|
String subscriptionName = "TestEventSubscription";
|
||||||
|
// register app in marketplace
|
||||||
|
EventSubscriptionResourceTest eventSubscriptionResourceTest =
|
||||||
|
new EventSubscriptionResourceTest();
|
||||||
|
CreateAppMarketPlaceDefinitionReq createRequest =
|
||||||
|
new CreateAppMarketPlaceDefinitionReq()
|
||||||
|
.withName("TestAppEventSubscription")
|
||||||
|
.withDisplayName("Test App Event Subscription")
|
||||||
|
.withDescription("A Test application with event subscriptions.")
|
||||||
|
.withFeatures("nothing really")
|
||||||
|
.withDeveloper("Collate Inc.")
|
||||||
|
.withDeveloperUrl("https://www.example.com")
|
||||||
|
.withPrivacyPolicyUrl("https://www.example.com/privacy")
|
||||||
|
.withSupportEmail("support@example.com")
|
||||||
|
.withClassName("org.openmetadata.service.resources.apps.TestApp")
|
||||||
|
.withAppType(AppType.Internal)
|
||||||
|
.withScheduleType(ScheduleType.Scheduled)
|
||||||
|
.withRuntime(new ScheduledExecutionContext().withEnabled(true))
|
||||||
|
.withAppConfiguration(new AppConfiguration())
|
||||||
|
.withPermission(NativeAppPermission.All)
|
||||||
|
.withEventSubscriptions(
|
||||||
|
List.of(
|
||||||
|
new CreateEventSubscription()
|
||||||
|
.withName(subscriptionName)
|
||||||
|
.withDisplayName("Test Event Subscription")
|
||||||
|
.withDescription(
|
||||||
|
"Consume EntityChange Events in order to trigger reverse metadata changes.")
|
||||||
|
.withAlertType(CreateEventSubscription.AlertType.NOTIFICATION)
|
||||||
|
.withResources(List.of("all"))
|
||||||
|
.withProvider(ProviderType.USER)
|
||||||
|
.withPollInterval(5)
|
||||||
|
.withEnabled(true)));
|
||||||
|
String endpoint =
|
||||||
|
"http://localhost:" + APP.getLocalPort() + "/api/v1/test/webhook/" + subscriptionName;
|
||||||
|
createRequest
|
||||||
|
.getEventSubscriptions()
|
||||||
|
.get(0)
|
||||||
|
.setDestinations(eventSubscriptionResourceTest.getWebhook(endpoint));
|
||||||
|
createAppMarketPlaceDefinition(createRequest, ADMIN_AUTH_HEADERS);
|
||||||
|
|
||||||
|
// install app
|
||||||
|
CreateApp installApp =
|
||||||
|
new CreateApp()
|
||||||
|
.withName(createRequest.getName())
|
||||||
|
.withAppConfiguration(new AppConfiguration());
|
||||||
|
createEntity(installApp, ADMIN_AUTH_HEADERS);
|
||||||
|
TestUtils.get(
|
||||||
|
getResource(String.format("events/subscriptions/name/%s", subscriptionName)),
|
||||||
|
EventSubscription.class,
|
||||||
|
ADMIN_AUTH_HEADERS);
|
||||||
|
|
||||||
|
// make change in the system
|
||||||
|
TableResourceTest tableResourceTest = new TableResourceTest();
|
||||||
|
Table table =
|
||||||
|
tableResourceTest.getEntityByName(TEST_TABLE1.getFullyQualifiedName(), ADMIN_AUTH_HEADERS);
|
||||||
|
Table updated = JsonUtils.deepCopy(table, Table.class);
|
||||||
|
updated.setDescription("Updated Description");
|
||||||
|
tableResourceTest.patchEntity(
|
||||||
|
table.getId(), JsonUtils.pojoToJson(table), updated, ADMIN_AUTH_HEADERS);
|
||||||
|
// assert webhook was called
|
||||||
|
Awaitility.await()
|
||||||
|
.timeout(
|
||||||
|
Duration.ofSeconds(createRequest.getEventSubscriptions().get(0).getPollInterval() + 10))
|
||||||
|
.untilAsserted(
|
||||||
|
() -> {
|
||||||
|
BaseCallbackResource.EventDetails<ChangeEvent> result =
|
||||||
|
webhookCallbackResource.getEventDetails(subscriptionName);
|
||||||
|
Assertions.assertNotNull(result);
|
||||||
|
Assertions.assertTrue(
|
||||||
|
result.getEvents().stream()
|
||||||
|
.anyMatch(
|
||||||
|
e ->
|
||||||
|
e.getEventType().equals(EventType.ENTITY_UPDATED)
|
||||||
|
&& e.getChangeDescription()
|
||||||
|
.getFieldsUpdated()
|
||||||
|
.get(0)
|
||||||
|
.getNewValue()
|
||||||
|
.equals("Updated Description")));
|
||||||
|
});
|
||||||
|
// uninstall app
|
||||||
|
deleteEntityByName(installApp.getName(), true, true, ADMIN_AUTH_HEADERS);
|
||||||
|
Table updated2 = JsonUtils.deepCopy(updated, Table.class);
|
||||||
|
updated2.setDescription("Updated Description 2");
|
||||||
|
tableResourceTest.patchEntity(
|
||||||
|
table.getId(), JsonUtils.pojoToJson(table), updated2, ADMIN_AUTH_HEADERS);
|
||||||
|
|
||||||
|
// assert event subscription was deleted
|
||||||
|
TestUtils.assertResponse(
|
||||||
|
() ->
|
||||||
|
TestUtils.get(
|
||||||
|
getResource(String.format("events/subscriptions/name/%s", subscriptionName)),
|
||||||
|
EventSubscription.class,
|
||||||
|
ADMIN_AUTH_HEADERS),
|
||||||
|
NOT_FOUND,
|
||||||
|
String.format("eventsubscription instance for %s not found", subscriptionName));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateCreatedEntity(
|
public void validateCreatedEntity(
|
||||||
App createdEntity, CreateApp request, Map<String, String> authHeaders)
|
App createdEntity, CreateApp request, Map<String, String> authHeaders)
|
||||||
throws HttpResponseException {}
|
throws HttpResponseException {}
|
||||||
|
|
||||||
|
public void createAppMarketPlaceDefinition(
|
||||||
|
CreateAppMarketPlaceDefinitionReq create, Map<String, String> authHeaders)
|
||||||
|
throws HttpResponseException {
|
||||||
|
WebTarget target = getResource("apps/marketplace");
|
||||||
|
TestUtils.post(
|
||||||
|
target, create, AppMarketPlaceDefinition.class, CREATED.getStatusCode(), authHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compareEntities(App expected, App updated, Map<String, String> authHeaders)
|
public void compareEntities(App expected, App updated, Map<String, String> authHeaders)
|
||||||
throws HttpResponseException {}
|
throws HttpResponseException {}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package org.openmetadata.service.resources.apps;
|
||||||
|
|
||||||
|
import org.openmetadata.service.apps.AbstractNativeApplication;
|
||||||
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
|
import org.openmetadata.service.search.SearchRepository;
|
||||||
|
|
||||||
|
public class TestApp extends AbstractNativeApplication {
|
||||||
|
public TestApp(CollectionDAO collectionDAO, SearchRepository searchRepository) {
|
||||||
|
super(collectionDAO, searchRepository);
|
||||||
|
}
|
||||||
|
}
|
@ -141,7 +141,7 @@ public abstract class BaseCallbackResource<T> {
|
|||||||
entityCallbackMap.clear();
|
entityCallbackMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EventDetails<T> {
|
public static class EventDetails<T> {
|
||||||
@Getter @Setter long firstEventTime;
|
@Getter @Setter long firstEventTime;
|
||||||
@Getter @Setter long latestEventTime;
|
@Getter @Setter long latestEventTime;
|
||||||
@Getter final ConcurrentLinkedQueue<T> events = new ConcurrentLinkedQueue<>();
|
@Getter final ConcurrentLinkedQueue<T> events = new ConcurrentLinkedQueue<>();
|
||||||
|
@ -255,6 +255,10 @@
|
|||||||
"description": "If the app run can be interrupted as part of the execution.",
|
"description": "If the app run can be interrupted as part of the execution.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"eventSubscriptions": {
|
||||||
|
"description": "Event Subscriptions for the Application.",
|
||||||
|
"$ref": "../../type/entityReferenceList.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -149,6 +149,14 @@
|
|||||||
"description": "If the app run can be interrupted as part of the execution.",
|
"description": "If the app run can be interrupted as part of the execution.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"eventSubscriptions": {
|
||||||
|
"description": "Event subscriptions that will be created when the application is installed.",
|
||||||
|
"type": "array",
|
||||||
|
"default": [],
|
||||||
|
"items": {
|
||||||
|
"$ref": "../../../events/api/createEventSubscription.json"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -111,6 +111,14 @@
|
|||||||
"description": "If the app run can be interrupted as part of the execution.",
|
"description": "If the app run can be interrupted as part of the execution.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"eventSubscriptions": {
|
||||||
|
"description": "Event subscriptions that will be created when the application is installed.",
|
||||||
|
"type": "array",
|
||||||
|
"default": [],
|
||||||
|
"items": {
|
||||||
|
"$ref": "../../../events/api/createEventSubscription.json"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
"description": "Name that uniquely identifies this Alert.",
|
"description": "Name that uniquely identifies this Alert.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityName"
|
"$ref": "../../type/basic.json#/definitions/entityName"
|
||||||
},
|
},
|
||||||
|
"className": {
|
||||||
|
"description": "Consumer Class for the Event Subscription. Will use 'AlertPublisher' if not provided.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"displayName": {
|
"displayName": {
|
||||||
"description": "Display name for this Alert.",
|
"description": "Display name for this Alert.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -155,6 +155,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "./emailAlertConfig.json"
|
"$ref": "./emailAlertConfig.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "../type/basic.json#/definitions/map"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -231,6 +234,10 @@
|
|||||||
"description": "Unique identifier that identifies this Event Subscription.",
|
"description": "Unique identifier that identifies this Event Subscription.",
|
||||||
"$ref": "../type/basic.json#/definitions/uuid"
|
"$ref": "../type/basic.json#/definitions/uuid"
|
||||||
},
|
},
|
||||||
|
"className": {
|
||||||
|
"description": "Java class for the Event Subscription.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"description": "Name that uniquely identifies this Event Subscription.",
|
"description": "Name that uniquely identifies this Event Subscription.",
|
||||||
"$ref": "../type/basic.json#/definitions/entityName"
|
"$ref": "../type/basic.json#/definitions/entityName"
|
||||||
|
@ -173,6 +173,12 @@
|
|||||||
".{1,}": { "type": "string" }
|
".{1,}": { "type": "string" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"map": {
|
||||||
|
"description": "A generic map that can be deserialized later.",
|
||||||
|
"existingJavaType" : "java.util.Map<String,Object>",
|
||||||
|
"type" : "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
"status" : {
|
"status" : {
|
||||||
"javaType": "org.openmetadata.schema.type.ApiStatus",
|
"javaType": "org.openmetadata.schema.type.ApiStatus",
|
||||||
"description": "State of an action over API.",
|
"description": "State of an action over API.",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024 Collate.
|
* Copyright 2025 Collate.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -10,9 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* This schema defines the applications for Open-Metadata.
|
* This schema defines the applications for Open-Metadata.
|
||||||
*/
|
*/
|
||||||
export interface App {
|
export interface App {
|
||||||
@ -78,6 +76,10 @@ export interface App {
|
|||||||
* it belongs to.
|
* it belongs to.
|
||||||
*/
|
*/
|
||||||
domain?: EntityReference;
|
domain?: EntityReference;
|
||||||
|
/**
|
||||||
|
* Event Subscriptions for the Application.
|
||||||
|
*/
|
||||||
|
eventSubscriptions?: EntityReference[];
|
||||||
/**
|
/**
|
||||||
* Features of the Application.
|
* Features of the Application.
|
||||||
*/
|
*/
|
||||||
@ -283,8 +285,12 @@ export interface CollateAIAppConfig {
|
|||||||
*
|
*
|
||||||
* Remove Owner Action Type
|
* Remove Owner Action Type
|
||||||
*
|
*
|
||||||
|
* Add a Custom Property to the selected assets.
|
||||||
|
*
|
||||||
* Add owners to the selected assets.
|
* Add owners to the selected assets.
|
||||||
*
|
*
|
||||||
|
* Remove Custom Properties Action Type
|
||||||
|
*
|
||||||
* Propagate description, tags and glossary terms via lineage
|
* Propagate description, tags and glossary terms via lineage
|
||||||
*
|
*
|
||||||
* ML Tagging action configuration for external automator.
|
* ML Tagging action configuration for external automator.
|
||||||
@ -314,6 +320,9 @@ export interface Action {
|
|||||||
* Update the description even if they are already defined in the asset. By default, we'll
|
* Update the description even if they are already defined in the asset. By default, we'll
|
||||||
* only add the descriptions to assets without the description set.
|
* only add the descriptions to assets without the description set.
|
||||||
*
|
*
|
||||||
|
* Update the Custom Property even if it is defined in the asset. By default, we will only
|
||||||
|
* apply the owners to assets without the given Custom Property informed.
|
||||||
|
*
|
||||||
* Update the tier even if it is defined in the asset. By default, we will only apply the
|
* Update the tier even if it is defined in the asset. By default, we will only apply the
|
||||||
* tier to assets without tier.
|
* tier to assets without tier.
|
||||||
*
|
*
|
||||||
@ -343,6 +352,12 @@ export interface Action {
|
|||||||
* Description to apply
|
* Description to apply
|
||||||
*/
|
*/
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Owners to apply
|
||||||
|
*
|
||||||
|
* Custom Properties keys to remove
|
||||||
|
*/
|
||||||
|
customProperties?: any;
|
||||||
/**
|
/**
|
||||||
* tier to apply
|
* tier to apply
|
||||||
*/
|
*/
|
||||||
@ -546,6 +561,8 @@ export interface Style {
|
|||||||
*
|
*
|
||||||
* Add Description Action Type.
|
* Add Description Action Type.
|
||||||
*
|
*
|
||||||
|
* Add Custom Properties Action Type.
|
||||||
|
*
|
||||||
* Remove Description Action Type
|
* Remove Description Action Type
|
||||||
*
|
*
|
||||||
* Add Tier Action Type.
|
* Add Tier Action Type.
|
||||||
@ -554,11 +571,14 @@ export interface Style {
|
|||||||
*
|
*
|
||||||
* Remove Owner Action Type
|
* Remove Owner Action Type
|
||||||
*
|
*
|
||||||
|
* Remove Custom Properties Action Type.
|
||||||
|
*
|
||||||
* Lineage propagation action type.
|
* Lineage propagation action type.
|
||||||
*
|
*
|
||||||
* ML PII Tagging action type.
|
* ML PII Tagging action type.
|
||||||
*/
|
*/
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
|
AddCustomPropertiesAction = "AddCustomPropertiesAction",
|
||||||
AddDescriptionAction = "AddDescriptionAction",
|
AddDescriptionAction = "AddDescriptionAction",
|
||||||
AddDomainAction = "AddDomainAction",
|
AddDomainAction = "AddDomainAction",
|
||||||
AddOwnerAction = "AddOwnerAction",
|
AddOwnerAction = "AddOwnerAction",
|
||||||
@ -566,6 +586,7 @@ export enum ActionType {
|
|||||||
AddTierAction = "AddTierAction",
|
AddTierAction = "AddTierAction",
|
||||||
LineagePropagationAction = "LineagePropagationAction",
|
LineagePropagationAction = "LineagePropagationAction",
|
||||||
MLTaggingAction = "MLTaggingAction",
|
MLTaggingAction = "MLTaggingAction",
|
||||||
|
RemoveCustomPropertiesAction = "RemoveCustomPropertiesAction",
|
||||||
RemoveDescriptionAction = "RemoveDescriptionAction",
|
RemoveDescriptionAction = "RemoveDescriptionAction",
|
||||||
RemoveDomainAction = "RemoveDomainAction",
|
RemoveDomainAction = "RemoveDomainAction",
|
||||||
RemoveOwnerAction = "RemoveOwnerAction",
|
RemoveOwnerAction = "RemoveOwnerAction",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024 Collate.
|
* Copyright 2025 Collate.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -10,9 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* This schema defines the applications for Open-Metadata.
|
* This schema defines the applications for Open-Metadata.
|
||||||
*/
|
*/
|
||||||
export interface AppMarketPlaceDefinition {
|
export interface AppMarketPlaceDefinition {
|
||||||
@ -70,6 +68,10 @@ export interface AppMarketPlaceDefinition {
|
|||||||
* it belongs to.
|
* it belongs to.
|
||||||
*/
|
*/
|
||||||
domain?: EntityReference;
|
domain?: EntityReference;
|
||||||
|
/**
|
||||||
|
* Event subscriptions that will be created when the application is installed.
|
||||||
|
*/
|
||||||
|
eventSubscriptions?: CreateEventSubscription[];
|
||||||
/**
|
/**
|
||||||
* Features of the Application.
|
* Features of the Application.
|
||||||
*/
|
*/
|
||||||
@ -268,8 +270,12 @@ export interface CollateAIAppConfig {
|
|||||||
*
|
*
|
||||||
* Remove Owner Action Type
|
* Remove Owner Action Type
|
||||||
*
|
*
|
||||||
|
* Add a Custom Property to the selected assets.
|
||||||
|
*
|
||||||
* Add owners to the selected assets.
|
* Add owners to the selected assets.
|
||||||
*
|
*
|
||||||
|
* Remove Custom Properties Action Type
|
||||||
|
*
|
||||||
* Propagate description, tags and glossary terms via lineage
|
* Propagate description, tags and glossary terms via lineage
|
||||||
*
|
*
|
||||||
* ML Tagging action configuration for external automator.
|
* ML Tagging action configuration for external automator.
|
||||||
@ -299,6 +305,9 @@ export interface Action {
|
|||||||
* Update the description even if they are already defined in the asset. By default, we'll
|
* Update the description even if they are already defined in the asset. By default, we'll
|
||||||
* only add the descriptions to assets without the description set.
|
* only add the descriptions to assets without the description set.
|
||||||
*
|
*
|
||||||
|
* Update the Custom Property even if it is defined in the asset. By default, we will only
|
||||||
|
* apply the owners to assets without the given Custom Property informed.
|
||||||
|
*
|
||||||
* Update the tier even if it is defined in the asset. By default, we will only apply the
|
* Update the tier even if it is defined in the asset. By default, we will only apply the
|
||||||
* tier to assets without tier.
|
* tier to assets without tier.
|
||||||
*
|
*
|
||||||
@ -328,6 +337,12 @@ export interface Action {
|
|||||||
* Description to apply
|
* Description to apply
|
||||||
*/
|
*/
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Owners to apply
|
||||||
|
*
|
||||||
|
* Custom Properties keys to remove
|
||||||
|
*/
|
||||||
|
customProperties?: any;
|
||||||
/**
|
/**
|
||||||
* tier to apply
|
* tier to apply
|
||||||
*/
|
*/
|
||||||
@ -529,6 +544,8 @@ export interface Style {
|
|||||||
*
|
*
|
||||||
* Add Description Action Type.
|
* Add Description Action Type.
|
||||||
*
|
*
|
||||||
|
* Add Custom Properties Action Type.
|
||||||
|
*
|
||||||
* Remove Description Action Type
|
* Remove Description Action Type
|
||||||
*
|
*
|
||||||
* Add Tier Action Type.
|
* Add Tier Action Type.
|
||||||
@ -537,11 +554,14 @@ export interface Style {
|
|||||||
*
|
*
|
||||||
* Remove Owner Action Type
|
* Remove Owner Action Type
|
||||||
*
|
*
|
||||||
|
* Remove Custom Properties Action Type.
|
||||||
|
*
|
||||||
* Lineage propagation action type.
|
* Lineage propagation action type.
|
||||||
*
|
*
|
||||||
* ML PII Tagging action type.
|
* ML PII Tagging action type.
|
||||||
*/
|
*/
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
|
AddCustomPropertiesAction = "AddCustomPropertiesAction",
|
||||||
AddDescriptionAction = "AddDescriptionAction",
|
AddDescriptionAction = "AddDescriptionAction",
|
||||||
AddDomainAction = "AddDomainAction",
|
AddDomainAction = "AddDomainAction",
|
||||||
AddOwnerAction = "AddOwnerAction",
|
AddOwnerAction = "AddOwnerAction",
|
||||||
@ -549,6 +569,7 @@ export enum ActionType {
|
|||||||
AddTierAction = "AddTierAction",
|
AddTierAction = "AddTierAction",
|
||||||
LineagePropagationAction = "LineagePropagationAction",
|
LineagePropagationAction = "LineagePropagationAction",
|
||||||
MLTaggingAction = "MLTaggingAction",
|
MLTaggingAction = "MLTaggingAction",
|
||||||
|
RemoveCustomPropertiesAction = "RemoveCustomPropertiesAction",
|
||||||
RemoveDescriptionAction = "RemoveDescriptionAction",
|
RemoveDescriptionAction = "RemoveDescriptionAction",
|
||||||
RemoveDomainAction = "RemoveDomainAction",
|
RemoveDomainAction = "RemoveDomainAction",
|
||||||
RemoveOwnerAction = "RemoveOwnerAction",
|
RemoveOwnerAction = "RemoveOwnerAction",
|
||||||
@ -665,6 +686,398 @@ export interface FieldChange {
|
|||||||
oldValue?: any;
|
oldValue?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This defines schema for sending alerts for OpenMetadata
|
||||||
|
*/
|
||||||
|
export interface CreateEventSubscription {
|
||||||
|
/**
|
||||||
|
* Type of Alert
|
||||||
|
*/
|
||||||
|
alertType: AlertType;
|
||||||
|
/**
|
||||||
|
* Maximum number of events sent in a batch (Default 10).
|
||||||
|
*/
|
||||||
|
batchSize?: number;
|
||||||
|
/**
|
||||||
|
* Consumer Class for the Event Subscription. Will use 'AlertPublisher' if not provided.
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
|
/**
|
||||||
|
* A short description of the Alert, comprehensible to regular users.
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Subscription Config.
|
||||||
|
*/
|
||||||
|
destinations?: Destination[];
|
||||||
|
/**
|
||||||
|
* Display name for this Alert.
|
||||||
|
*/
|
||||||
|
displayName?: string;
|
||||||
|
/**
|
||||||
|
* Fully qualified name of the domain the Table belongs to.
|
||||||
|
*/
|
||||||
|
domain?: string;
|
||||||
|
/**
|
||||||
|
* Is the alert enabled.
|
||||||
|
*/
|
||||||
|
enabled?: boolean;
|
||||||
|
/**
|
||||||
|
* Input for the Filters.
|
||||||
|
*/
|
||||||
|
input?: AlertFilteringInput;
|
||||||
|
/**
|
||||||
|
* Name that uniquely identifies this Alert.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Owners of this Alert.
|
||||||
|
*/
|
||||||
|
owners?: EntityReference[];
|
||||||
|
/**
|
||||||
|
* Poll Interval in seconds.
|
||||||
|
*/
|
||||||
|
pollInterval?: number;
|
||||||
|
provider?: ProviderType;
|
||||||
|
/**
|
||||||
|
* Defines a list of resources that triggers the Event Subscription, Eg All, User, Teams etc.
|
||||||
|
*/
|
||||||
|
resources?: string[];
|
||||||
|
/**
|
||||||
|
* Number of times to retry callback on failure. (Default 3).
|
||||||
|
*/
|
||||||
|
retries?: number;
|
||||||
|
trigger?: Trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of Alert
|
||||||
|
*
|
||||||
|
* Type of Alerts supported.
|
||||||
|
*/
|
||||||
|
export enum AlertType {
|
||||||
|
ActivityFeed = "ActivityFeed",
|
||||||
|
GovernanceWorkflowChangeEvent = "GovernanceWorkflowChangeEvent",
|
||||||
|
Notification = "Notification",
|
||||||
|
Observability = "Observability",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription which has a type and the config.
|
||||||
|
*/
|
||||||
|
export interface Destination {
|
||||||
|
category: SubscriptionCategory;
|
||||||
|
config?: Webhook;
|
||||||
|
/**
|
||||||
|
* Is the subscription enabled.
|
||||||
|
*/
|
||||||
|
enabled?: boolean;
|
||||||
|
/**
|
||||||
|
* Unique identifier that identifies this Event Subscription.
|
||||||
|
*/
|
||||||
|
id?: string;
|
||||||
|
/**
|
||||||
|
* Read timeout in seconds. (Default 12s).
|
||||||
|
*/
|
||||||
|
readTimeout?: number;
|
||||||
|
statusDetails?: TionStatus;
|
||||||
|
/**
|
||||||
|
* Connection timeout in seconds. (Default 10s).
|
||||||
|
*/
|
||||||
|
timeout?: number;
|
||||||
|
type: SubscriptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription Endpoint Type.
|
||||||
|
*/
|
||||||
|
export enum SubscriptionCategory {
|
||||||
|
Admins = "Admins",
|
||||||
|
Assignees = "Assignees",
|
||||||
|
External = "External",
|
||||||
|
Followers = "Followers",
|
||||||
|
Mentions = "Mentions",
|
||||||
|
Owners = "Owners",
|
||||||
|
Teams = "Teams",
|
||||||
|
Users = "Users",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This schema defines webhook for receiving events from OpenMetadata.
|
||||||
|
*
|
||||||
|
* This schema defines email config for receiving events from OpenMetadata.
|
||||||
|
*
|
||||||
|
* A generic map that can be deserialized later.
|
||||||
|
*/
|
||||||
|
export interface Webhook {
|
||||||
|
/**
|
||||||
|
* Endpoint to receive the webhook events over POST requests.
|
||||||
|
*/
|
||||||
|
endpoint?: string;
|
||||||
|
/**
|
||||||
|
* Custom headers to be sent with the webhook request.
|
||||||
|
*/
|
||||||
|
headers?: { [key: string]: any };
|
||||||
|
/**
|
||||||
|
* HTTP operation to send the webhook request. Supports POST or PUT.
|
||||||
|
*/
|
||||||
|
httpMethod?: HTTPMethod;
|
||||||
|
/**
|
||||||
|
* List of receivers to send mail to
|
||||||
|
*/
|
||||||
|
receivers?: string[];
|
||||||
|
/**
|
||||||
|
* Secret set by the webhook client used for computing HMAC SHA256 signature of webhook
|
||||||
|
* payload and sent in `X-OM-Signature` header in POST requests to publish the events.
|
||||||
|
*/
|
||||||
|
secretKey?: string;
|
||||||
|
/**
|
||||||
|
* Send the Event to Admins
|
||||||
|
*
|
||||||
|
* Send the Mails to Admins
|
||||||
|
*/
|
||||||
|
sendToAdmins?: boolean;
|
||||||
|
/**
|
||||||
|
* Send the Event to Followers
|
||||||
|
*
|
||||||
|
* Send the Mails to Followers
|
||||||
|
*/
|
||||||
|
sendToFollowers?: boolean;
|
||||||
|
/**
|
||||||
|
* Send the Event to Owners
|
||||||
|
*
|
||||||
|
* Send the Mails to Owners
|
||||||
|
*/
|
||||||
|
sendToOwners?: boolean;
|
||||||
|
[property: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP operation to send the webhook request. Supports POST or PUT.
|
||||||
|
*/
|
||||||
|
export enum HTTPMethod {
|
||||||
|
Post = "POST",
|
||||||
|
Put = "PUT",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current status of the subscription, including details on the last successful and failed
|
||||||
|
* attempts, and retry information.
|
||||||
|
*
|
||||||
|
* Detailed status of the destination during a test operation, including HTTP response
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
export interface TionStatus {
|
||||||
|
/**
|
||||||
|
* Timestamp of the last failed callback in UNIX UTC epoch time in milliseconds.
|
||||||
|
*/
|
||||||
|
lastFailedAt?: number;
|
||||||
|
/**
|
||||||
|
* Detailed reason for the last failure received during callback.
|
||||||
|
*/
|
||||||
|
lastFailedReason?: string;
|
||||||
|
/**
|
||||||
|
* HTTP status code received during the last failed callback attempt.
|
||||||
|
*/
|
||||||
|
lastFailedStatusCode?: number;
|
||||||
|
/**
|
||||||
|
* Timestamp of the last successful callback in UNIX UTC epoch time in milliseconds.
|
||||||
|
*/
|
||||||
|
lastSuccessfulAt?: number;
|
||||||
|
/**
|
||||||
|
* Timestamp for the next retry attempt in UNIX epoch time in milliseconds. Only valid if
|
||||||
|
* `status` is `awaitingRetry`.
|
||||||
|
*/
|
||||||
|
nextAttempt?: number;
|
||||||
|
/**
|
||||||
|
* Status is `disabled` when the event subscription was created with `enabled` set to false
|
||||||
|
* and it never started publishing events. Status is `active` when the event subscription is
|
||||||
|
* functioning normally and a 200 OK response was received for the callback notification.
|
||||||
|
* Status is `failed` when a bad callback URL, connection failures, or `1xx` or `3xx`
|
||||||
|
* response was received for the callback notification. Status is `awaitingRetry` when the
|
||||||
|
* previous attempt at callback timed out or received a `4xx` or `5xx` response. Status is
|
||||||
|
* `retryLimitReached` after all retries fail.
|
||||||
|
*
|
||||||
|
* Overall test status, indicating if the test operation succeeded or failed.
|
||||||
|
*/
|
||||||
|
status?: Status;
|
||||||
|
/**
|
||||||
|
* Current timestamp of this status in UNIX epoch time in milliseconds.
|
||||||
|
*
|
||||||
|
* Timestamp when the response was received, in UNIX epoch time milliseconds.
|
||||||
|
*/
|
||||||
|
timestamp?: number;
|
||||||
|
/**
|
||||||
|
* Body of the HTTP response, if any, returned by the server.
|
||||||
|
*/
|
||||||
|
entity?: string;
|
||||||
|
/**
|
||||||
|
* HTTP headers returned in the response as a map of header names to values.
|
||||||
|
*/
|
||||||
|
headers?: any;
|
||||||
|
/**
|
||||||
|
* URL location if the response indicates a redirect or newly created resource.
|
||||||
|
*/
|
||||||
|
location?: string;
|
||||||
|
/**
|
||||||
|
* Media type of the response entity, if specified (e.g., application/json).
|
||||||
|
*/
|
||||||
|
mediaType?: string;
|
||||||
|
/**
|
||||||
|
* Detailed reason for failure if the test did not succeed.
|
||||||
|
*/
|
||||||
|
reason?: string;
|
||||||
|
/**
|
||||||
|
* HTTP status code of the response (e.g., 200 for OK, 404 for Not Found).
|
||||||
|
*/
|
||||||
|
statusCode?: number;
|
||||||
|
/**
|
||||||
|
* HTTP status reason phrase associated with the status code (e.g., 'Not Found').
|
||||||
|
*/
|
||||||
|
statusInfo?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status is `disabled` when the event subscription was created with `enabled` set to false
|
||||||
|
* and it never started publishing events. Status is `active` when the event subscription is
|
||||||
|
* functioning normally and a 200 OK response was received for the callback notification.
|
||||||
|
* Status is `failed` when a bad callback URL, connection failures, or `1xx` or `3xx`
|
||||||
|
* response was received for the callback notification. Status is `awaitingRetry` when the
|
||||||
|
* previous attempt at callback timed out or received a `4xx` or `5xx` response. Status is
|
||||||
|
* `retryLimitReached` after all retries fail.
|
||||||
|
*
|
||||||
|
* Overall test status, indicating if the test operation succeeded or failed.
|
||||||
|
*/
|
||||||
|
export enum Status {
|
||||||
|
Active = "active",
|
||||||
|
AwaitingRetry = "awaitingRetry",
|
||||||
|
Disabled = "disabled",
|
||||||
|
Failed = "failed",
|
||||||
|
RetryLimitReached = "retryLimitReached",
|
||||||
|
StatusFailed = "Failed",
|
||||||
|
Success = "Success",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription Endpoint Type.
|
||||||
|
*/
|
||||||
|
export enum SubscriptionType {
|
||||||
|
ActivityFeed = "ActivityFeed",
|
||||||
|
Email = "Email",
|
||||||
|
GChat = "GChat",
|
||||||
|
GovernanceWorkflowChangeEvent = "GovernanceWorkflowChangeEvent",
|
||||||
|
MSTeams = "MsTeams",
|
||||||
|
Slack = "Slack",
|
||||||
|
Webhook = "Webhook",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input for the Filters.
|
||||||
|
*
|
||||||
|
* Observability of the event subscription.
|
||||||
|
*/
|
||||||
|
export interface AlertFilteringInput {
|
||||||
|
/**
|
||||||
|
* List of filters for the event subscription.
|
||||||
|
*/
|
||||||
|
actions?: ArgumentsInput[];
|
||||||
|
/**
|
||||||
|
* List of filters for the event subscription.
|
||||||
|
*/
|
||||||
|
filters?: ArgumentsInput[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observability Filters for Event Subscription.
|
||||||
|
*/
|
||||||
|
export interface ArgumentsInput {
|
||||||
|
/**
|
||||||
|
* Arguments List
|
||||||
|
*/
|
||||||
|
arguments?: Argument[];
|
||||||
|
effect?: Effect;
|
||||||
|
/**
|
||||||
|
* Name of the filter
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* Prefix Condition for the filter.
|
||||||
|
*/
|
||||||
|
prefixCondition?: PrefixCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Argument for the filter.
|
||||||
|
*/
|
||||||
|
export interface Argument {
|
||||||
|
/**
|
||||||
|
* Value of the Argument
|
||||||
|
*/
|
||||||
|
input?: string[];
|
||||||
|
/**
|
||||||
|
* Name of the Argument
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Effect {
|
||||||
|
Exclude = "exclude",
|
||||||
|
Include = "include",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix Condition for the filter.
|
||||||
|
*
|
||||||
|
* Prefix Condition to be applied to the Condition.
|
||||||
|
*/
|
||||||
|
export enum PrefixCondition {
|
||||||
|
And = "AND",
|
||||||
|
Or = "OR",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of provider of an entity. Some entities are provided by the `system`. Some are
|
||||||
|
* entities created and provided by the `user`. Typically `system` provide entities can't be
|
||||||
|
* deleted and can only be disabled.
|
||||||
|
*/
|
||||||
|
export enum ProviderType {
|
||||||
|
System = "system",
|
||||||
|
User = "user",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger Configuration for Alerts.
|
||||||
|
*/
|
||||||
|
export interface Trigger {
|
||||||
|
/**
|
||||||
|
* Cron Expression in case of Custom scheduled Trigger
|
||||||
|
*/
|
||||||
|
cronExpression?: string;
|
||||||
|
/**
|
||||||
|
* Schedule Info
|
||||||
|
*/
|
||||||
|
scheduleInfo?: ScheduleInfo;
|
||||||
|
triggerType: TriggerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule Info
|
||||||
|
*/
|
||||||
|
export enum ScheduleInfo {
|
||||||
|
Custom = "Custom",
|
||||||
|
Daily = "Daily",
|
||||||
|
Monthly = "Monthly",
|
||||||
|
Weekly = "Weekly",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger Configuration for Alerts.
|
||||||
|
*/
|
||||||
|
export enum TriggerType {
|
||||||
|
RealTime = "RealTime",
|
||||||
|
Scheduled = "Scheduled",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission used by Native Applications.
|
* Permission used by Native Applications.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024 Collate.
|
* Copyright 2025 Collate.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -10,9 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* This schema defines the applications for Open-Metadata.
|
* This schema defines the applications for Open-Metadata.
|
||||||
*/
|
*/
|
||||||
export interface CreateAppMarketPlaceDefinitionReq {
|
export interface CreateAppMarketPlaceDefinitionReq {
|
||||||
@ -61,6 +59,10 @@ export interface CreateAppMarketPlaceDefinitionReq {
|
|||||||
* Fully qualified name of the domain the Table belongs to.
|
* Fully qualified name of the domain the Table belongs to.
|
||||||
*/
|
*/
|
||||||
domain?: string;
|
domain?: string;
|
||||||
|
/**
|
||||||
|
* Event subscriptions that will be created when the application is installed.
|
||||||
|
*/
|
||||||
|
eventSubscriptions?: CreateEventSubscription[];
|
||||||
/**
|
/**
|
||||||
* Features of the Application.
|
* Features of the Application.
|
||||||
*/
|
*/
|
||||||
@ -229,8 +231,12 @@ export interface CollateAIAppConfig {
|
|||||||
*
|
*
|
||||||
* Remove Owner Action Type
|
* Remove Owner Action Type
|
||||||
*
|
*
|
||||||
|
* Add a Custom Property to the selected assets.
|
||||||
|
*
|
||||||
* Add owners to the selected assets.
|
* Add owners to the selected assets.
|
||||||
*
|
*
|
||||||
|
* Remove Custom Properties Action Type
|
||||||
|
*
|
||||||
* Propagate description, tags and glossary terms via lineage
|
* Propagate description, tags and glossary terms via lineage
|
||||||
*
|
*
|
||||||
* ML Tagging action configuration for external automator.
|
* ML Tagging action configuration for external automator.
|
||||||
@ -260,6 +266,9 @@ export interface Action {
|
|||||||
* Update the description even if they are already defined in the asset. By default, we'll
|
* Update the description even if they are already defined in the asset. By default, we'll
|
||||||
* only add the descriptions to assets without the description set.
|
* only add the descriptions to assets without the description set.
|
||||||
*
|
*
|
||||||
|
* Update the Custom Property even if it is defined in the asset. By default, we will only
|
||||||
|
* apply the owners to assets without the given Custom Property informed.
|
||||||
|
*
|
||||||
* Update the tier even if it is defined in the asset. By default, we will only apply the
|
* Update the tier even if it is defined in the asset. By default, we will only apply the
|
||||||
* tier to assets without tier.
|
* tier to assets without tier.
|
||||||
*
|
*
|
||||||
@ -289,6 +298,12 @@ export interface Action {
|
|||||||
* Description to apply
|
* Description to apply
|
||||||
*/
|
*/
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Owners to apply
|
||||||
|
*
|
||||||
|
* Custom Properties keys to remove
|
||||||
|
*/
|
||||||
|
customProperties?: any;
|
||||||
/**
|
/**
|
||||||
* tier to apply
|
* tier to apply
|
||||||
*/
|
*/
|
||||||
@ -487,6 +502,8 @@ export interface Style {
|
|||||||
*
|
*
|
||||||
* Add Description Action Type.
|
* Add Description Action Type.
|
||||||
*
|
*
|
||||||
|
* Add Custom Properties Action Type.
|
||||||
|
*
|
||||||
* Remove Description Action Type
|
* Remove Description Action Type
|
||||||
*
|
*
|
||||||
* Add Tier Action Type.
|
* Add Tier Action Type.
|
||||||
@ -495,11 +512,14 @@ export interface Style {
|
|||||||
*
|
*
|
||||||
* Remove Owner Action Type
|
* Remove Owner Action Type
|
||||||
*
|
*
|
||||||
|
* Remove Custom Properties Action Type.
|
||||||
|
*
|
||||||
* Lineage propagation action type.
|
* Lineage propagation action type.
|
||||||
*
|
*
|
||||||
* ML PII Tagging action type.
|
* ML PII Tagging action type.
|
||||||
*/
|
*/
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
|
AddCustomPropertiesAction = "AddCustomPropertiesAction",
|
||||||
AddDescriptionAction = "AddDescriptionAction",
|
AddDescriptionAction = "AddDescriptionAction",
|
||||||
AddDomainAction = "AddDomainAction",
|
AddDomainAction = "AddDomainAction",
|
||||||
AddOwnerAction = "AddOwnerAction",
|
AddOwnerAction = "AddOwnerAction",
|
||||||
@ -507,6 +527,7 @@ export enum ActionType {
|
|||||||
AddTierAction = "AddTierAction",
|
AddTierAction = "AddTierAction",
|
||||||
LineagePropagationAction = "LineagePropagationAction",
|
LineagePropagationAction = "LineagePropagationAction",
|
||||||
MLTaggingAction = "MLTaggingAction",
|
MLTaggingAction = "MLTaggingAction",
|
||||||
|
RemoveCustomPropertiesAction = "RemoveCustomPropertiesAction",
|
||||||
RemoveDescriptionAction = "RemoveDescriptionAction",
|
RemoveDescriptionAction = "RemoveDescriptionAction",
|
||||||
RemoveDomainAction = "RemoveDomainAction",
|
RemoveDomainAction = "RemoveDomainAction",
|
||||||
RemoveOwnerAction = "RemoveOwnerAction",
|
RemoveOwnerAction = "RemoveOwnerAction",
|
||||||
@ -582,6 +603,398 @@ export enum AppType {
|
|||||||
Internal = "internal",
|
Internal = "internal",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This defines schema for sending alerts for OpenMetadata
|
||||||
|
*/
|
||||||
|
export interface CreateEventSubscription {
|
||||||
|
/**
|
||||||
|
* Type of Alert
|
||||||
|
*/
|
||||||
|
alertType: AlertType;
|
||||||
|
/**
|
||||||
|
* Maximum number of events sent in a batch (Default 10).
|
||||||
|
*/
|
||||||
|
batchSize?: number;
|
||||||
|
/**
|
||||||
|
* Consumer Class for the Event Subscription. Will use 'AlertPublisher' if not provided.
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
|
/**
|
||||||
|
* A short description of the Alert, comprehensible to regular users.
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Subscription Config.
|
||||||
|
*/
|
||||||
|
destinations?: Destination[];
|
||||||
|
/**
|
||||||
|
* Display name for this Alert.
|
||||||
|
*/
|
||||||
|
displayName?: string;
|
||||||
|
/**
|
||||||
|
* Fully qualified name of the domain the Table belongs to.
|
||||||
|
*/
|
||||||
|
domain?: string;
|
||||||
|
/**
|
||||||
|
* Is the alert enabled.
|
||||||
|
*/
|
||||||
|
enabled?: boolean;
|
||||||
|
/**
|
||||||
|
* Input for the Filters.
|
||||||
|
*/
|
||||||
|
input?: AlertFilteringInput;
|
||||||
|
/**
|
||||||
|
* Name that uniquely identifies this Alert.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Owners of this Alert.
|
||||||
|
*/
|
||||||
|
owners?: EntityReference[];
|
||||||
|
/**
|
||||||
|
* Poll Interval in seconds.
|
||||||
|
*/
|
||||||
|
pollInterval?: number;
|
||||||
|
provider?: ProviderType;
|
||||||
|
/**
|
||||||
|
* Defines a list of resources that triggers the Event Subscription, Eg All, User, Teams etc.
|
||||||
|
*/
|
||||||
|
resources?: string[];
|
||||||
|
/**
|
||||||
|
* Number of times to retry callback on failure. (Default 3).
|
||||||
|
*/
|
||||||
|
retries?: number;
|
||||||
|
trigger?: Trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of Alert
|
||||||
|
*
|
||||||
|
* Type of Alerts supported.
|
||||||
|
*/
|
||||||
|
export enum AlertType {
|
||||||
|
ActivityFeed = "ActivityFeed",
|
||||||
|
GovernanceWorkflowChangeEvent = "GovernanceWorkflowChangeEvent",
|
||||||
|
Notification = "Notification",
|
||||||
|
Observability = "Observability",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription which has a type and the config.
|
||||||
|
*/
|
||||||
|
export interface Destination {
|
||||||
|
category: SubscriptionCategory;
|
||||||
|
config?: Webhook;
|
||||||
|
/**
|
||||||
|
* Is the subscription enabled.
|
||||||
|
*/
|
||||||
|
enabled?: boolean;
|
||||||
|
/**
|
||||||
|
* Unique identifier that identifies this Event Subscription.
|
||||||
|
*/
|
||||||
|
id?: string;
|
||||||
|
/**
|
||||||
|
* Read timeout in seconds. (Default 12s).
|
||||||
|
*/
|
||||||
|
readTimeout?: number;
|
||||||
|
statusDetails?: TionStatus;
|
||||||
|
/**
|
||||||
|
* Connection timeout in seconds. (Default 10s).
|
||||||
|
*/
|
||||||
|
timeout?: number;
|
||||||
|
type: SubscriptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription Endpoint Type.
|
||||||
|
*/
|
||||||
|
export enum SubscriptionCategory {
|
||||||
|
Admins = "Admins",
|
||||||
|
Assignees = "Assignees",
|
||||||
|
External = "External",
|
||||||
|
Followers = "Followers",
|
||||||
|
Mentions = "Mentions",
|
||||||
|
Owners = "Owners",
|
||||||
|
Teams = "Teams",
|
||||||
|
Users = "Users",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This schema defines webhook for receiving events from OpenMetadata.
|
||||||
|
*
|
||||||
|
* This schema defines email config for receiving events from OpenMetadata.
|
||||||
|
*
|
||||||
|
* A generic map that can be deserialized later.
|
||||||
|
*/
|
||||||
|
export interface Webhook {
|
||||||
|
/**
|
||||||
|
* Endpoint to receive the webhook events over POST requests.
|
||||||
|
*/
|
||||||
|
endpoint?: string;
|
||||||
|
/**
|
||||||
|
* Custom headers to be sent with the webhook request.
|
||||||
|
*/
|
||||||
|
headers?: { [key: string]: any };
|
||||||
|
/**
|
||||||
|
* HTTP operation to send the webhook request. Supports POST or PUT.
|
||||||
|
*/
|
||||||
|
httpMethod?: HTTPMethod;
|
||||||
|
/**
|
||||||
|
* List of receivers to send mail to
|
||||||
|
*/
|
||||||
|
receivers?: string[];
|
||||||
|
/**
|
||||||
|
* Secret set by the webhook client used for computing HMAC SHA256 signature of webhook
|
||||||
|
* payload and sent in `X-OM-Signature` header in POST requests to publish the events.
|
||||||
|
*/
|
||||||
|
secretKey?: string;
|
||||||
|
/**
|
||||||
|
* Send the Event to Admins
|
||||||
|
*
|
||||||
|
* Send the Mails to Admins
|
||||||
|
*/
|
||||||
|
sendToAdmins?: boolean;
|
||||||
|
/**
|
||||||
|
* Send the Event to Followers
|
||||||
|
*
|
||||||
|
* Send the Mails to Followers
|
||||||
|
*/
|
||||||
|
sendToFollowers?: boolean;
|
||||||
|
/**
|
||||||
|
* Send the Event to Owners
|
||||||
|
*
|
||||||
|
* Send the Mails to Owners
|
||||||
|
*/
|
||||||
|
sendToOwners?: boolean;
|
||||||
|
[property: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP operation to send the webhook request. Supports POST or PUT.
|
||||||
|
*/
|
||||||
|
export enum HTTPMethod {
|
||||||
|
Post = "POST",
|
||||||
|
Put = "PUT",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current status of the subscription, including details on the last successful and failed
|
||||||
|
* attempts, and retry information.
|
||||||
|
*
|
||||||
|
* Detailed status of the destination during a test operation, including HTTP response
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
export interface TionStatus {
|
||||||
|
/**
|
||||||
|
* Timestamp of the last failed callback in UNIX UTC epoch time in milliseconds.
|
||||||
|
*/
|
||||||
|
lastFailedAt?: number;
|
||||||
|
/**
|
||||||
|
* Detailed reason for the last failure received during callback.
|
||||||
|
*/
|
||||||
|
lastFailedReason?: string;
|
||||||
|
/**
|
||||||
|
* HTTP status code received during the last failed callback attempt.
|
||||||
|
*/
|
||||||
|
lastFailedStatusCode?: number;
|
||||||
|
/**
|
||||||
|
* Timestamp of the last successful callback in UNIX UTC epoch time in milliseconds.
|
||||||
|
*/
|
||||||
|
lastSuccessfulAt?: number;
|
||||||
|
/**
|
||||||
|
* Timestamp for the next retry attempt in UNIX epoch time in milliseconds. Only valid if
|
||||||
|
* `status` is `awaitingRetry`.
|
||||||
|
*/
|
||||||
|
nextAttempt?: number;
|
||||||
|
/**
|
||||||
|
* Status is `disabled` when the event subscription was created with `enabled` set to false
|
||||||
|
* and it never started publishing events. Status is `active` when the event subscription is
|
||||||
|
* functioning normally and a 200 OK response was received for the callback notification.
|
||||||
|
* Status is `failed` when a bad callback URL, connection failures, or `1xx` or `3xx`
|
||||||
|
* response was received for the callback notification. Status is `awaitingRetry` when the
|
||||||
|
* previous attempt at callback timed out or received a `4xx` or `5xx` response. Status is
|
||||||
|
* `retryLimitReached` after all retries fail.
|
||||||
|
*
|
||||||
|
* Overall test status, indicating if the test operation succeeded or failed.
|
||||||
|
*/
|
||||||
|
status?: Status;
|
||||||
|
/**
|
||||||
|
* Current timestamp of this status in UNIX epoch time in milliseconds.
|
||||||
|
*
|
||||||
|
* Timestamp when the response was received, in UNIX epoch time milliseconds.
|
||||||
|
*/
|
||||||
|
timestamp?: number;
|
||||||
|
/**
|
||||||
|
* Body of the HTTP response, if any, returned by the server.
|
||||||
|
*/
|
||||||
|
entity?: string;
|
||||||
|
/**
|
||||||
|
* HTTP headers returned in the response as a map of header names to values.
|
||||||
|
*/
|
||||||
|
headers?: any;
|
||||||
|
/**
|
||||||
|
* URL location if the response indicates a redirect or newly created resource.
|
||||||
|
*/
|
||||||
|
location?: string;
|
||||||
|
/**
|
||||||
|
* Media type of the response entity, if specified (e.g., application/json).
|
||||||
|
*/
|
||||||
|
mediaType?: string;
|
||||||
|
/**
|
||||||
|
* Detailed reason for failure if the test did not succeed.
|
||||||
|
*/
|
||||||
|
reason?: string;
|
||||||
|
/**
|
||||||
|
* HTTP status code of the response (e.g., 200 for OK, 404 for Not Found).
|
||||||
|
*/
|
||||||
|
statusCode?: number;
|
||||||
|
/**
|
||||||
|
* HTTP status reason phrase associated with the status code (e.g., 'Not Found').
|
||||||
|
*/
|
||||||
|
statusInfo?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status is `disabled` when the event subscription was created with `enabled` set to false
|
||||||
|
* and it never started publishing events. Status is `active` when the event subscription is
|
||||||
|
* functioning normally and a 200 OK response was received for the callback notification.
|
||||||
|
* Status is `failed` when a bad callback URL, connection failures, or `1xx` or `3xx`
|
||||||
|
* response was received for the callback notification. Status is `awaitingRetry` when the
|
||||||
|
* previous attempt at callback timed out or received a `4xx` or `5xx` response. Status is
|
||||||
|
* `retryLimitReached` after all retries fail.
|
||||||
|
*
|
||||||
|
* Overall test status, indicating if the test operation succeeded or failed.
|
||||||
|
*/
|
||||||
|
export enum Status {
|
||||||
|
Active = "active",
|
||||||
|
AwaitingRetry = "awaitingRetry",
|
||||||
|
Disabled = "disabled",
|
||||||
|
Failed = "failed",
|
||||||
|
RetryLimitReached = "retryLimitReached",
|
||||||
|
StatusFailed = "Failed",
|
||||||
|
Success = "Success",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription Endpoint Type.
|
||||||
|
*/
|
||||||
|
export enum SubscriptionType {
|
||||||
|
ActivityFeed = "ActivityFeed",
|
||||||
|
Email = "Email",
|
||||||
|
GChat = "GChat",
|
||||||
|
GovernanceWorkflowChangeEvent = "GovernanceWorkflowChangeEvent",
|
||||||
|
MSTeams = "MsTeams",
|
||||||
|
Slack = "Slack",
|
||||||
|
Webhook = "Webhook",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input for the Filters.
|
||||||
|
*
|
||||||
|
* Observability of the event subscription.
|
||||||
|
*/
|
||||||
|
export interface AlertFilteringInput {
|
||||||
|
/**
|
||||||
|
* List of filters for the event subscription.
|
||||||
|
*/
|
||||||
|
actions?: ArgumentsInput[];
|
||||||
|
/**
|
||||||
|
* List of filters for the event subscription.
|
||||||
|
*/
|
||||||
|
filters?: ArgumentsInput[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observability Filters for Event Subscription.
|
||||||
|
*/
|
||||||
|
export interface ArgumentsInput {
|
||||||
|
/**
|
||||||
|
* Arguments List
|
||||||
|
*/
|
||||||
|
arguments?: Argument[];
|
||||||
|
effect?: Effect;
|
||||||
|
/**
|
||||||
|
* Name of the filter
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* Prefix Condition for the filter.
|
||||||
|
*/
|
||||||
|
prefixCondition?: PrefixCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Argument for the filter.
|
||||||
|
*/
|
||||||
|
export interface Argument {
|
||||||
|
/**
|
||||||
|
* Value of the Argument
|
||||||
|
*/
|
||||||
|
input?: string[];
|
||||||
|
/**
|
||||||
|
* Name of the Argument
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Effect {
|
||||||
|
Exclude = "exclude",
|
||||||
|
Include = "include",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix Condition for the filter.
|
||||||
|
*
|
||||||
|
* Prefix Condition to be applied to the Condition.
|
||||||
|
*/
|
||||||
|
export enum PrefixCondition {
|
||||||
|
And = "AND",
|
||||||
|
Or = "OR",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of provider of an entity. Some entities are provided by the `system`. Some are
|
||||||
|
* entities created and provided by the `user`. Typically `system` provide entities can't be
|
||||||
|
* deleted and can only be disabled.
|
||||||
|
*/
|
||||||
|
export enum ProviderType {
|
||||||
|
System = "system",
|
||||||
|
User = "user",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger Configuration for Alerts.
|
||||||
|
*/
|
||||||
|
export interface Trigger {
|
||||||
|
/**
|
||||||
|
* Cron Expression in case of Custom scheduled Trigger
|
||||||
|
*/
|
||||||
|
cronExpression?: string;
|
||||||
|
/**
|
||||||
|
* Schedule Info
|
||||||
|
*/
|
||||||
|
scheduleInfo?: ScheduleInfo;
|
||||||
|
triggerType: TriggerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule Info
|
||||||
|
*/
|
||||||
|
export enum ScheduleInfo {
|
||||||
|
Custom = "Custom",
|
||||||
|
Daily = "Daily",
|
||||||
|
Monthly = "Monthly",
|
||||||
|
Weekly = "Weekly",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger Configuration for Alerts.
|
||||||
|
*/
|
||||||
|
export enum TriggerType {
|
||||||
|
RealTime = "RealTime",
|
||||||
|
Scheduled = "Scheduled",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission used by Native Applications.
|
* Permission used by Native Applications.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024 Collate.
|
* Copyright 2025 Collate.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -10,9 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* This defines schema for sending alerts for OpenMetadata
|
* This defines schema for sending alerts for OpenMetadata
|
||||||
*/
|
*/
|
||||||
export interface CreateEventSubscription {
|
export interface CreateEventSubscription {
|
||||||
@ -24,6 +22,10 @@ export interface CreateEventSubscription {
|
|||||||
* Maximum number of events sent in a batch (Default 10).
|
* Maximum number of events sent in a batch (Default 10).
|
||||||
*/
|
*/
|
||||||
batchSize?: number;
|
batchSize?: number;
|
||||||
|
/**
|
||||||
|
* Consumer Class for the Event Subscription. Will use 'AlertPublisher' if not provided.
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
/**
|
/**
|
||||||
* A short description of the Alert, comprehensible to regular users.
|
* A short description of the Alert, comprehensible to regular users.
|
||||||
*/
|
*/
|
||||||
@ -128,6 +130,8 @@ export enum SubscriptionCategory {
|
|||||||
* This schema defines webhook for receiving events from OpenMetadata.
|
* This schema defines webhook for receiving events from OpenMetadata.
|
||||||
*
|
*
|
||||||
* This schema defines email config for receiving events from OpenMetadata.
|
* This schema defines email config for receiving events from OpenMetadata.
|
||||||
|
*
|
||||||
|
* A generic map that can be deserialized later.
|
||||||
*/
|
*/
|
||||||
export interface Webhook {
|
export interface Webhook {
|
||||||
/**
|
/**
|
||||||
@ -169,6 +173,7 @@ export interface Webhook {
|
|||||||
* Send the Mails to Owners
|
* Send the Mails to Owners
|
||||||
*/
|
*/
|
||||||
sendToOwners?: boolean;
|
sendToOwners?: boolean;
|
||||||
|
[property: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024 Collate.
|
* Copyright 2025 Collate.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -10,9 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* This schema defines the EventSubscription entity. An Event Subscription has trigger,
|
* This schema defines the EventSubscription entity. An Event Subscription has trigger,
|
||||||
* filters and Subscription
|
* filters and Subscription
|
||||||
*/
|
*/
|
||||||
@ -29,6 +27,10 @@ export interface EventSubscription {
|
|||||||
* Change that led to this version of the Event Subscription.
|
* Change that led to this version of the Event Subscription.
|
||||||
*/
|
*/
|
||||||
changeDescription?: ChangeDescription;
|
changeDescription?: ChangeDescription;
|
||||||
|
/**
|
||||||
|
* Java class for the Event Subscription.
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
/**
|
/**
|
||||||
* A short description of the Event Subscription, comprehensible to regular users.
|
* A short description of the Event Subscription, comprehensible to regular users.
|
||||||
*/
|
*/
|
||||||
@ -204,6 +206,8 @@ export enum SubscriptionCategory {
|
|||||||
* This schema defines webhook for receiving events from OpenMetadata.
|
* This schema defines webhook for receiving events from OpenMetadata.
|
||||||
*
|
*
|
||||||
* This schema defines email config for receiving events from OpenMetadata.
|
* This schema defines email config for receiving events from OpenMetadata.
|
||||||
|
*
|
||||||
|
* A generic map that can be deserialized later.
|
||||||
*/
|
*/
|
||||||
export interface Webhook {
|
export interface Webhook {
|
||||||
/**
|
/**
|
||||||
@ -245,6 +249,7 @@ export interface Webhook {
|
|||||||
* Send the Mails to Owners
|
* Send the Mails to Owners
|
||||||
*/
|
*/
|
||||||
sendToOwners?: boolean;
|
sendToOwners?: boolean;
|
||||||
|
[property: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user