@Test public void testCreateOrUpdateSubscriptionConfig() throws IOException { String validYaml = IOUtils.toString(this.getClass().getResourceAsStream("subscription/subscription-config-2.yaml")); try { long id = this.yamlResource.createOrUpdateSubscriptionConfig(user, validYaml); DetectionAlertConfigDTO subscription = daoRegistry.getDetectionAlertConfigManager().findById(id); Assert.assertNotNull(subscription); Assert.assertEquals(subscription.getName(), "Subscription Group Name"); } catch (Exception e) { Assert.fail("Exception should not be thrown for valid yaml. Message: " + e + " Cause: " + e.getCause(), e); } String updatedYaml = IOUtils.toString(this.getClass().getResourceAsStream("subscription/subscription-config-4.yaml")); try { long id = this.yamlResource.createOrUpdateSubscriptionConfig(user, updatedYaml); DetectionAlertConfigDTO subscription = daoRegistry.getDetectionAlertConfigManager().findById(id); Assert.assertNotNull(subscription); Assert.assertEquals(subscription.getName(), "Subscription Group Name"); Assert.assertEquals(subscription.getApplication(), "test_application"); } catch (Exception e) { Assert.fail("Exception should not be thrown if subscription already exists. Message: " + e + " Cause: " + e.getCause()); } }
long createOrUpdateSubscriptionConfig(ThirdEyePrincipal user, @NotNull String payload) throws ConfigValidationException { long subscriptionId; DetectionAlertConfigDTO existingSubscriptionGroup = fetchExistingSubscriptionGroup(payload); if (existingSubscriptionGroup != null) { subscriptionId = existingSubscriptionGroup.getId(); updateSubscriptionGroup(user, subscriptionId, payload); } else { subscriptionId = createSubscriptionConfig(payload); } return subscriptionId; }
YamlResource { long createOrUpdateSubscriptionConfig(ThirdEyePrincipal user, @NotNull String payload) throws ConfigValidationException { long subscriptionId; DetectionAlertConfigDTO existingSubscriptionGroup = fetchExistingSubscriptionGroup(payload); if (existingSubscriptionGroup != null) { subscriptionId = existingSubscriptionGroup.getId(); updateSubscriptionGroup(user, subscriptionId, payload); } else { subscriptionId = createSubscriptionConfig(payload); } return subscriptionId; } }
YamlResource { long createOrUpdateSubscriptionConfig(ThirdEyePrincipal user, @NotNull String payload) throws ConfigValidationException { long subscriptionId; DetectionAlertConfigDTO existingSubscriptionGroup = fetchExistingSubscriptionGroup(payload); if (existingSubscriptionGroup != null) { subscriptionId = existingSubscriptionGroup.getId(); updateSubscriptionGroup(user, subscriptionId, payload); } else { subscriptionId = createSubscriptionConfig(payload); } return subscriptionId; } YamlResource(Map<String, Map<String, Object>> alerterConfig, DetectionPreviewConfiguration previewConfig,
      double alertOnboardingPermitPerSecond);  YamlResource(Map<String, Map<String, Object>> alerterConfig, DetectionPreviewConfiguration previewConfig); }
YamlResource { long createOrUpdateSubscriptionConfig(ThirdEyePrincipal user, @NotNull String payload) throws ConfigValidationException { long subscriptionId; DetectionAlertConfigDTO existingSubscriptionGroup = fetchExistingSubscriptionGroup(payload); if (existingSubscriptionGroup != null) { subscriptionId = existingSubscriptionGroup.getId(); updateSubscriptionGroup(user, subscriptionId, payload); } else { subscriptionId = createSubscriptionConfig(payload); } return subscriptionId; } YamlResource(Map<String, Map<String, Object>> alerterConfig, DetectionPreviewConfiguration previewConfig,
      double alertOnboardingPermitPerSecond);  YamlResource(Map<String, Map<String, Object>> alerterConfig, DetectionPreviewConfiguration previewConfig); void validateCreateAlertYaml(Map<String, String> config); @POST @Path("/create-alert") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @PermitAll @ApiOperation("Use yaml to create both subscription and detection yaml. ") Response createYamlAlert(
      @Auth ThirdEyePrincipal user,
      @ApiParam(value =  "a json contains both subscription and detection yaml as string")  String payload,
      @ApiParam("tuning window start time for tunable components") @QueryParam("startTime") long tuningStartTime,
      @ApiParam("tuning window end time for tunable components") @QueryParam("endTime") long tuningEndTime); @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Set up a detection pipeline using a YAML config") Response createDetectionPipelineApi(
      @ApiParam("yaml config") String payload,
      @ApiParam("tuning window start time for tunable components") @QueryParam("startTime") long startTime,
      @ApiParam("tuning window end time for tunable components") @QueryParam("endTime") long endTime); @PUT @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Edit a detection pipeline using a YAML config") Response updateDetectionPipelineApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("yaml config") String payload,
      @ApiParam("the detection config id to edit") @PathParam("id") long id,
      @ApiParam("tuning window start time for tunable components")  @QueryParam("startTime") long startTime,
      @ApiParam("tuning window end time for tunable components") @QueryParam("endTime") long endTime); @POST @Path("/create-or-update") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Create a new detection config or update existing if one already exists") Response createOrUpdateDetectionConfigApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("yaml config") String payload); @POST @Path("/subscription/create-or-update") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Create a new subscription config or update existing if one already exists") Response createOrUpdateSubscriptionConfigApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("yaml config") String payload); long createSubscriptionConfig(@NotNull String payload); @POST @Path("/subscription") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Create a subscription group using a YAML config") @SuppressWarnings("unchecked") Response createSubscriptionConfigApi(
      @ApiParam("payload") String payload); @PUT @Path("/subscription/{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Edit a subscription group using a YAML config") Response updateSubscriptionGroupApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("payload") String payload,
      @ApiParam("the detection alert config id to edit") @PathParam("id") long id); @POST @Path("/preview") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Preview the anomaly detection result of a YAML configuration") Response yamlPreviewApi(
      @QueryParam("start") long start,
      @QueryParam("end") long end,
      @QueryParam("tuningStart") long tuningStart,
      @QueryParam("tuningEnd") long tuningEnd,
      @ApiParam("jsonPayload") String payload); @POST @Path("/preview/{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Preview the anomaly detection result of a YAML configuration, with an existing config and historical anomalies") Response yamlPreviewWithHistoricalAnomalies(
      @PathParam("id") long id,
      @QueryParam("start") long start,
      @QueryParam("end") long end,
      @QueryParam("tuningStart") long tuningStart,
      @QueryParam("tuningEnd") long tuningEnd,
      @ApiParam("jsonPayload") String payload); @POST @Path("/preview/baseline") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Get baseline from YAML configuration") /* TODO: Will return baseline from yamlPreviewApi together with detection in the future. */ Response yamlPreviewBaselineApi(
      @QueryParam("start") long start,
      @QueryParam("end") long end,
      @QueryParam("urn") @NotNull String urn,
      @QueryParam("tuningStart") long tuningStart,
      @QueryParam("tuningEnd") long tuningEnd,
      @ApiParam("jsonPayload") @NotNull String payload,
      @QueryParam("ruleName") String ruleName); @PUT @Path("/activation/{id}") @ApiOperation("Make detection active or inactive, given id") @Produces(MediaType.APPLICATION_JSON) Response toggleActivation(
      @ApiParam("Detection configuration id for the alert") @NotNull @PathParam("id") long detectionId,
      @ApiParam("Active status you want to set for the alert") @NotNull @QueryParam("active") boolean active); @GET @Path("/list") @ApiOperation( "Get the list of all detection YAML configurations as JSON enhanced with additional information, optionally filtered." + "IMPORTANT NOTE: This endpoint is deprecated because it is not scalable. Please use the /alerts endpoint instead. " + "For now, it is limited to list and filter the most recent 100 alerts only. ") @Produces(MediaType.APPLICATION_JSON) @Deprecated Response listYamls(
      @ApiParam("Dataset the detection configurations should be filtered by") @QueryParam("dataset") String dataset,
      @ApiParam("Metric the detection configurations should be filtered by") @QueryParam("metric") String metric); @PUT @Path("/notify/{id}") @ApiOperation("Send notification email for detection alert config") Response triggerNotification(
      @ApiParam("Subscription configuration id for the alert") @NotNull @PathParam("id") long subscriptionId); }
YamlResource { long createOrUpdateSubscriptionConfig(ThirdEyePrincipal user, @NotNull String payload) throws ConfigValidationException { long subscriptionId; DetectionAlertConfigDTO existingSubscriptionGroup = fetchExistingSubscriptionGroup(payload); if (existingSubscriptionGroup != null) { subscriptionId = existingSubscriptionGroup.getId(); updateSubscriptionGroup(user, subscriptionId, payload); } else { subscriptionId = createSubscriptionConfig(payload); } return subscriptionId; } YamlResource(Map<String, Map<String, Object>> alerterConfig, DetectionPreviewConfiguration previewConfig,
      double alertOnboardingPermitPerSecond);  YamlResource(Map<String, Map<String, Object>> alerterConfig, DetectionPreviewConfiguration previewConfig); void validateCreateAlertYaml(Map<String, String> config); @POST @Path("/create-alert") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @PermitAll @ApiOperation("Use yaml to create both subscription and detection yaml. ") Response createYamlAlert(
      @Auth ThirdEyePrincipal user,
      @ApiParam(value =  "a json contains both subscription and detection yaml as string")  String payload,
      @ApiParam("tuning window start time for tunable components") @QueryParam("startTime") long tuningStartTime,
      @ApiParam("tuning window end time for tunable components") @QueryParam("endTime") long tuningEndTime); @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Set up a detection pipeline using a YAML config") Response createDetectionPipelineApi(
      @ApiParam("yaml config") String payload,
      @ApiParam("tuning window start time for tunable components") @QueryParam("startTime") long startTime,
      @ApiParam("tuning window end time for tunable components") @QueryParam("endTime") long endTime); @PUT @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Edit a detection pipeline using a YAML config") Response updateDetectionPipelineApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("yaml config") String payload,
      @ApiParam("the detection config id to edit") @PathParam("id") long id,
      @ApiParam("tuning window start time for tunable components")  @QueryParam("startTime") long startTime,
      @ApiParam("tuning window end time for tunable components") @QueryParam("endTime") long endTime); @POST @Path("/create-or-update") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Create a new detection config or update existing if one already exists") Response createOrUpdateDetectionConfigApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("yaml config") String payload); @POST @Path("/subscription/create-or-update") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Create a new subscription config or update existing if one already exists") Response createOrUpdateSubscriptionConfigApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("yaml config") String payload); long createSubscriptionConfig(@NotNull String payload); @POST @Path("/subscription") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Create a subscription group using a YAML config") @SuppressWarnings("unchecked") Response createSubscriptionConfigApi(
      @ApiParam("payload") String payload); @PUT @Path("/subscription/{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @PermitAll @ApiOperation("Edit a subscription group using a YAML config") Response updateSubscriptionGroupApi(
      @Auth ThirdEyePrincipal user,
      @ApiParam("payload") String payload,
      @ApiParam("the detection alert config id to edit") @PathParam("id") long id); @POST @Path("/preview") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Preview the anomaly detection result of a YAML configuration") Response yamlPreviewApi(
      @QueryParam("start") long start,
      @QueryParam("end") long end,
      @QueryParam("tuningStart") long tuningStart,
      @QueryParam("tuningEnd") long tuningEnd,
      @ApiParam("jsonPayload") String payload); @POST @Path("/preview/{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Preview the anomaly detection result of a YAML configuration, with an existing config and historical anomalies") Response yamlPreviewWithHistoricalAnomalies(
      @PathParam("id") long id,
      @QueryParam("start") long start,
      @QueryParam("end") long end,
      @QueryParam("tuningStart") long tuningStart,
      @QueryParam("tuningEnd") long tuningEnd,
      @ApiParam("jsonPayload") String payload); @POST @Path("/preview/baseline") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_PLAIN) @ApiOperation("Get baseline from YAML configuration") /* TODO: Will return baseline from yamlPreviewApi together with detection in the future. */ Response yamlPreviewBaselineApi(
      @QueryParam("start") long start,
      @QueryParam("end") long end,
      @QueryParam("urn") @NotNull String urn,
      @QueryParam("tuningStart") long tuningStart,
      @QueryParam("tuningEnd") long tuningEnd,
      @ApiParam("jsonPayload") @NotNull String payload,
      @QueryParam("ruleName") String ruleName); @PUT @Path("/activation/{id}") @ApiOperation("Make detection active or inactive, given id") @Produces(MediaType.APPLICATION_JSON) Response toggleActivation(
      @ApiParam("Detection configuration id for the alert") @NotNull @PathParam("id") long detectionId,
      @ApiParam("Active status you want to set for the alert") @NotNull @QueryParam("active") boolean active); @GET @Path("/list") @ApiOperation( "Get the list of all detection YAML configurations as JSON enhanced with additional information, optionally filtered." + "IMPORTANT NOTE: This endpoint is deprecated because it is not scalable. Please use the /alerts endpoint instead. " + "For now, it is limited to list and filter the most recent 100 alerts only. ") @Produces(MediaType.APPLICATION_JSON) @Deprecated Response listYamls(
      @ApiParam("Dataset the detection configurations should be filtered by") @QueryParam("dataset") String dataset,
      @ApiParam("Metric the detection configurations should be filtered by") @QueryParam("metric") String metric); @PUT @Path("/notify/{id}") @ApiOperation("Send notification email for detection alert config") Response triggerNotification(
      @ApiParam("Subscription configuration id for the alert") @NotNull @PathParam("id") long subscriptionId);  }