This is an automated email from the ASF dual-hosted git repository.
mandarambawane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/master by this push:
new e61a24f75 ATLAS-5377: Remove duplicate NotificationREST endpoint from
webapp (#730)
e61a24f75 is described below
commit e61a24f75eea9cd7f320b5e415d90f21f22bafbb
Author: UmeshPatil-1 <[email protected]>
AuthorDate: Wed Sep 16 13:24:52 2026 +0530
ATLAS-5377: Remove duplicate NotificationREST endpoint from webapp (#730)
* ATLAS-5377: Remove duplicate NotificationREST endpoint from the main
webapp (port 21000) and require hooks to use rest-notification-webapp (port
41000/rest) only.
* ATLAS-5377: Updated NotificationRestIT to assert endpoint is removed from
webapp (expect error, not 204).
* ATLAS-5377: Updated assertion and shorter fail-fast message as per review.
---
.../main/java/org/apache/atlas/AtlasConstants.java | 3 +-
.../atlas/notification/rest/RestNotification.java | 10 +-
.../atlas/notification/RestNotificationTest.java | 44 ++++---
.../apache/atlas/web/rest/NotificationREST.java | 132 ---------------------
.../atlas/web/integration/NotificationRestIT.java | 32 +++--
5 files changed, 53 insertions(+), 168 deletions(-)
diff --git a/common/src/main/java/org/apache/atlas/AtlasConstants.java
b/common/src/main/java/org/apache/atlas/AtlasConstants.java
index cc0d50763..e2930062c 100644
--- a/common/src/main/java/org/apache/atlas/AtlasConstants.java
+++ b/common/src/main/java/org/apache/atlas/AtlasConstants.java
@@ -31,7 +31,8 @@ public final class AtlasConstants {
public static final String ATLAS_SERVICES_ENABLED =
"atlas.services.enabled";
public static final String CLUSTER_NAME_ATTRIBUTE = "clusterName";
public static final String DEFAULT_APP_PORT_STR = "21000";
- public static final String DEFAULT_ATLAS_REST_ADDRESS =
"http://localhost:21000";
+ public static final String DEFAULT_ATLAS_REST_ADDRESS =
"http://localhost:21000";
+ public static final String DEFAULT_REST_NOTIFICATION_ADDRESS =
"http://localhost:41000/rest";
public static final String DEFAULT_TYPE_VERSION = "1.0";
public static final int ATLAS_SHUTDOWN_HOOK_PRIORITY = 30;
diff --git
a/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java
b/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java
index e94afddc9..0743545ff 100644
---
a/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java
+++
b/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java
@@ -47,10 +47,9 @@ public class RestNotification extends AbstractNotification {
private static final Logger LOG =
LoggerFactory.getLogger(RestNotification.class);
private static final int BATCH_MAX_LENGTH_BYTES =
AtlasConfiguration.NOTIFICATION_REST_BODY_MAX_LENGTH_BYTES.getInt();
- private static final String ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT =
"atlas.hook.rest.notification.address";
+ private static final String ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT =
AtlasConfiguration.NOTIFICATION_HOOK_REST_ADDRESS.getPropertyName();
private static final String BASIC_AUTH_USERNAME =
"atlas.rest.basic.auth.username";
private static final String BASIC_AUTH_PASSWORD =
"atlas.rest.basic.auth.password";
- private static final String DEFAULT_ATLAS_URL =
"http://localhost:31000/";
private static final Map<NotificationType, String> PRODUCER_TOPIC_MAP =
new HashMap<>();
@@ -115,11 +114,8 @@ public class RestNotification extends AbstractNotification
{
String[] atlasEndPoint =
configuration.getStringArray(ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT);
if (isEndpointNotSpecified(atlasEndPoint)) {
- atlasEndPoint =
configuration.getStringArray(AtlasConstants.ATLAS_REST_ADDRESS_KEY);
- }
-
- if (isEndpointNotSpecified(atlasEndPoint)) {
- atlasEndPoint = new String[] {DEFAULT_ATLAS_URL};
+ throw new AtlasException(ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT
+ " is required for rest-notification-webapp (e.g. "
+ + AtlasConstants.DEFAULT_REST_NOTIFICATION_ADDRESS +
")");
}
if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
diff --git
a/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java
b/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java
index 417adc7df..5db77523b 100644
---
a/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java
+++
b/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java
@@ -25,6 +25,7 @@ import org.apache.atlas.AtlasBaseClient;
import org.apache.atlas.AtlasClientV2;
import org.apache.atlas.AtlasConfiguration;
import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
import org.apache.atlas.kafka.NotificationProvider;
import org.apache.atlas.notification.rest.RestNotification;
import org.apache.commons.configuration2.BaseConfiguration;
@@ -68,6 +69,7 @@ public class RestNotificationTest {
conf = ApplicationProperties.get();
conf.setProperty(AtlasConfiguration.NOTIFICATION_HOOK_REST_ENABLED.getPropertyName(),
true);
+
conf.setProperty(AtlasConfiguration.NOTIFICATION_HOOK_REST_ADDRESS.getPropertyName(),
"http://localhost:41000/rest");
conf.setProperty(NotificationProvider.CONF_ATLAS_HOOK_SPOOL_ENABLED,
false);
notifier = NotificationProvider.get();
@@ -150,23 +152,17 @@ public class RestNotificationTest {
assertEquals(configuredEndpoints[0],
"http://atlas-rest.example.com:41000/rest");
}
- @Test
- public void testRestNotificationEndpointFallsBackToAtlasRestAddress()
throws Exception {
+ @Test(expectedExceptions = AtlasException.class)
+ public void testRestNotificationFailsFastWhenHookAddressNotConfigured()
throws Exception {
Configuration localConf = new BaseConfiguration();
- localConf.setProperty("atlas.rest.address",
"http://atlas-main.example.com:21000");
localConf.setProperty("atlas.rest.basic.auth.username", "admin");
localConf.setProperty("atlas.rest.basic.auth.password", "admin123");
- RestNotification restNotification = new RestNotification(localConf);
-
- String[] configuredEndpoints =
getConfiguredBaseUrls(restNotification.atlasClientV2);
-
- assertEquals(configuredEndpoints.length, 1);
- assertEquals(configuredEndpoints[0],
"http://atlas-main.example.com:21000");
+ new RestNotification(localConf);
}
- @Test
- public void
testRestNotificationFallsBackToAtlasRestWhenNotificationAddressesAllBlank()
throws Exception {
+ @Test(expectedExceptions = AtlasException.class)
+ public void testRestNotificationFailsFastWhenHookAddressesAllBlank()
throws Exception {
Configuration localConf = new BaseConfiguration();
localConf.addProperty("atlas.hook.rest.notification.address", "");
localConf.addProperty("atlas.hook.rest.notification.address", " ");
@@ -174,12 +170,30 @@ public class RestNotificationTest {
localConf.setProperty("atlas.rest.basic.auth.username", "admin");
localConf.setProperty("atlas.rest.basic.auth.password", "admin123");
- RestNotification restNotification = new RestNotification(localConf);
+ new RestNotification(localConf);
+ }
- String[] configuredEndpoints =
getConfiguredBaseUrls(restNotification.atlasClientV2);
+ @Test(expectedExceptions = AtlasException.class)
+ public void
testRestNotificationFailsFastWhenOnlyAtlasRestAddressConfigured() throws
Exception {
+ Configuration localConf = new BaseConfiguration();
+ localConf.setProperty("atlas.rest.address",
"http://atlas-main.example.com:21000");
+ localConf.setProperty("atlas.rest.basic.auth.username", "admin");
+ localConf.setProperty("atlas.rest.basic.auth.password", "admin123");
- assertEquals(configuredEndpoints.length, 1);
- assertEquals(configuredEndpoints[0],
"http://atlas-main.example.com:21000");
+ new RestNotification(localConf);
+ }
+
+ @Test
+ public void testRestNotificationFailFastExceptionMessage() {
+ Configuration localConf = new BaseConfiguration();
+
+ try {
+ new RestNotification(localConf);
+ fail("Expected AtlasException when
atlas.hook.rest.notification.address is not configured");
+ } catch (AtlasException e) {
+
assertTrue(e.getMessage().contains("atlas.hook.rest.notification.address is
required"));
+ assertTrue(e.getMessage().contains("http://localhost:41000/rest"));
+ }
}
private String[] getConfiguredBaseUrls(AtlasClientV2 atlasClientV2) throws
Exception {
diff --git
a/webapp/src/main/java/org/apache/atlas/web/rest/NotificationREST.java
b/webapp/src/main/java/org/apache/atlas/web/rest/NotificationREST.java
deleted file mode 100644
index 6c437ea98..000000000
--- a/webapp/src/main/java/org/apache/atlas/web/rest/NotificationREST.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.atlas.web.rest;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import org.apache.atlas.AtlasConfiguration;
-import org.apache.atlas.AtlasErrorCode;
-import org.apache.atlas.authorize.AtlasAdminAccessRequest;
-import org.apache.atlas.authorize.AtlasAuthorizationUtils;
-import org.apache.atlas.authorize.AtlasPrivilege;
-import org.apache.atlas.exception.AtlasBaseException;
-import org.apache.atlas.hook.AtlasHook;
-import org.apache.atlas.kafka.KafkaNotification;
-import org.apache.atlas.notification.NotificationException;
-import org.apache.atlas.notification.NotificationInterface;
-import org.apache.atlas.server.common.util.Servlets;
-import org.apache.atlas.utils.AtlasJson;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-@Path("v2/notification")
-@Singleton
-@Service
-@Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
-@Produces({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
-public class NotificationREST {
- private static final Logger LOG =
LoggerFactory.getLogger(NotificationREST.class);
-
- public static final String ATLAS_HOOK_TOPIC =
AtlasConfiguration.NOTIFICATION_HOOK_TOPIC_NAME.getString();
- public static final String ATLAS_ENTITIES_TOPIC =
AtlasConfiguration.NOTIFICATION_ENTITIES_TOPIC_NAME.getString();
-
- private static final String[] ATLAS_HOOK_CONSUMER_TOPICS =
AtlasConfiguration.NOTIFICATION_HOOK_CONSUMER_TOPIC_NAMES.getStringArray(ATLAS_HOOK_TOPIC);
- private static final String[] ATLAS_ENTITIES_CONSUMER_TOPICS =
AtlasConfiguration.NOTIFICATION_ENTITIES_CONSUMER_TOPIC_NAMES.getStringArray(ATLAS_ENTITIES_TOPIC);
- private static final Set<String> TOPICS = new
HashSet<>();
-
- private final NotificationInterface notificationInterface;
-
- @Inject
- public NotificationREST(NotificationInterface notificationInterface) {
- this.notificationInterface = notificationInterface;
- }
-
- /**
- * Publish notifications on Kafka topic
- *
- * @param topicName - nameOfTheQueue
- * @throws AtlasBaseException
- */
- @POST
- @Path("/topic/{topicName}")
- @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
- public void handleNotifications(@PathParam("topicName") String topicName,
@Context HttpServletRequest request) throws AtlasBaseException, IOException {
- LOG.debug("Handling notifications for topic {}", topicName);
-
- AtlasAuthorizationUtils.verifyAccess(new
AtlasAdminAccessRequest(AtlasPrivilege.SERVICE_NOTIFICATION_POST), "post on
rest notification service");
-
- if (!TOPICS.contains(topicName)) {
- throw new AtlasBaseException(AtlasErrorCode.INVALID_TOPIC_NAME,
topicName);
- }
-
- String messagesAsJson = Servlets.getRequestPayload(request);
- List<String> messages = getMessagesToNotify(messagesAsJson);
-
- try {
- KafkaNotification notifier = (KafkaNotification)
notificationInterface;
-
- notifier.sendInternal(topicName, messages,
AtlasHook.isHookMsgsSortEnabled);
- } catch (NotificationException exception) {
- List<String> failedMessages = exception.getFailedMessages();
- String concatenatedMessage =
StringUtils.join(failedMessages, "\n");
-
- throw new
AtlasBaseException(AtlasErrorCode.NOTIFICATION_EXCEPTION, exception,
concatenatedMessage);
- }
- }
-
- private List<String> getMessagesToNotify(String messagesAsJson) {
- List<String> messages = new ArrayList<>();
-
- try {
- ArrayNode messageNodes =
AtlasJson.parseToV1ArrayNode(messagesAsJson);
-
- for (JsonNode messageNode : messageNodes) {
- messages.add(AtlasJson.toV1Json(messageNode));
- }
- } catch (IOException e) {
- messages.add(messagesAsJson);
- }
-
- return messages;
- }
-
- static {
- TOPICS.addAll(Arrays.asList(ATLAS_HOOK_CONSUMER_TOPICS));
- TOPICS.addAll(Arrays.asList(ATLAS_ENTITIES_CONSUMER_TOPICS));
- }
-}
diff --git
a/webapp/src/test/java/org/apache/atlas/web/integration/NotificationRestIT.java
b/webapp/src/test/java/org/apache/atlas/web/integration/NotificationRestIT.java
index 96df5d599..54c1a4bce 100644
---
a/webapp/src/test/java/org/apache/atlas/web/integration/NotificationRestIT.java
+++
b/webapp/src/test/java/org/apache/atlas/web/integration/NotificationRestIT.java
@@ -17,7 +17,7 @@
*/
package org.apache.atlas.web.integration;
-import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.sun.jersey.api.client.ClientResponse;
import org.apache.atlas.AtlasClientV2;
import org.apache.atlas.AtlasServiceException;
import org.apache.atlas.utils.TestResourceFileUtils;
@@ -30,40 +30,46 @@ import java.util.Date;
import static org.apache.atlas.kafka.KafkaNotification.ATLAS_HOOK_TOPIC;
import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+/**
+ * ATLAS-5377: hook notification REST ingress was removed from the main Atlas
webapp.
+ * Canonical endpoint is rest-notification-webapp only. These integration
tests verify
+ * that POST /api/atlas/v2/notification/topic/{topicName} is not served on
main webapp.
+ */
public class NotificationRestIT extends BaseResourceIT {
@Test
- public void unAuthPostNotification() throws IOException {
+ public void unAuthPostNotificationRejected() throws IOException {
AtlasClientV2 unAuthClient = new AtlasClientV2(atlasUrls, new String[]
{"admin", "wr0ng_pa55w0rd"});
try {
- unAuthClient.postNotificationToTopic(ATLAS_HOOK_TOPIC, new
ArrayList<String>(Collections.singletonList("Dummy")));
+ unAuthClient.postNotificationToTopic(ATLAS_HOOK_TOPIC, new
ArrayList<>(Collections.singletonList("Dummy")));
+
+ fail("Expected postNotificationToTopic to fail on main webapp");
} catch (AtlasServiceException e) {
assertNotNull(e.getStatus(), "expected server error code in the
status");
}
}
@Test
- public void postNotificationBasicTest() throws Exception {
+ public void notificationEndpointRemovedFromMainWebapp() throws Exception {
String dbName = "db_" + randomString();
String clusterName = "cl" + randomString();
- String qualifiedName = dbName + "@" + clusterName;
String notificationString =
TestResourceFileUtils.getJson("notifications/create-db")
.replaceAll("--name--", dbName).replaceAll("--clName--",
clusterName)
.replace("\"--ts--\"", String.valueOf((new Date()).getTime()));
try {
- atlasClientV2.postNotificationToTopic(ATLAS_HOOK_TOPIC, new
ArrayList<String>(Collections.singletonList(notificationString)));
+ atlasClientV2.postNotificationToTopic(ATLAS_HOOK_TOPIC, new
ArrayList<>(Collections.singletonList(notificationString)));
- waitFor(MAX_WAIT_TIME, () -> {
- ArrayNode results = searchByDSL(String.format("%s where
qualifiedName='%s'", DATABASE_TYPE_BUILTIN, qualifiedName));
-
- return results.size() == 1;
- });
+ fail("Expected notification POST to fail — endpoint removed from
main webapp (ATLAS-5377)");
} catch (AtlasServiceException e) {
- assertNull(e.getStatus(), "expected no server error code in the
status");
+ assertNotNull(e.getStatus(), "expected HTTP error when posting to
removed endpoint");
+
+ assertTrue(e.getStatus().getStatusCode() !=
ClientResponse.Status.NO_CONTENT.getStatusCode(),
+ "notification POST must not return 204 on main webapp");
}
}
}