Skip to content
7 changes: 7 additions & 0 deletions core/src/main/java/org/apache/gravitino/audit/AuditLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@
import org.apache.gravitino.listener.api.event.PurgeTableFailureEvent;
import org.apache.gravitino.listener.api.event.RemovePolicyFromTagEvent;
import org.apache.gravitino.listener.api.event.RemovePolicyFromTagFailureEvent;
import org.apache.gravitino.listener.api.event.TestConnectionEvent;
import org.apache.gravitino.listener.api.event.TestConnectionFailureEvent;
import org.apache.gravitino.listener.api.event.semantic.AlterSemanticModelEvent;
import org.apache.gravitino.listener.api.event.semantic.AlterSemanticModelFailureEvent;
import org.apache.gravitino.listener.api.event.semantic.CreateSemanticModelEvent;
Expand Down Expand Up @@ -256,6 +258,8 @@ enum Operation {

DISABLE_CATALOG,

TEST_CONNECTION_CATALOG,

CREATE_SCHEMA,

ALTER_SCHEMA,
Expand Down Expand Up @@ -587,6 +591,9 @@ public static Operation fromEvent(Event event) {
} else if (event instanceof DisableCatalogEvent
|| event instanceof DisableCatalogFailureEvent) {
return DISABLE_CATALOG;
} else if (event instanceof TestConnectionEvent
|| event instanceof TestConnectionFailureEvent) {
return TEST_CONNECTION_CATALOG;
} else if (event instanceof CreateSchemaEvent || event instanceof CreateSchemaFailureEvent) {
return CREATE_SCHEMA;
} else if (event instanceof AlterSchemaEvent || event instanceof AlterSchemaFailureEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class CompatibilityUtils {
.put(OperationType.LIST_CATALOG, Operation.LIST_CATALOG)
.put(OperationType.ENABLE_CATALOG, Operation.ENABLE_CATALOG)
.put(OperationType.DISABLE_CATALOG, Operation.DISABLE_CATALOG)
.put(OperationType.TEST_CONNECTION_CATALOG, Operation.TEST_CONNECTION_CATALOG)
.put(OperationType.CREATE_SCHEMA, Operation.CREATE_SCHEMA)
.put(OperationType.DROP_SCHEMA, Operation.DROP_SCHEMA)
.put(OperationType.ALTER_SCHEMA, Operation.ALTER_SCHEMA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.Collections;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.gravitino.Catalog;
import org.apache.gravitino.CatalogChange;
import org.apache.gravitino.NameIdentifier;
Expand Down Expand Up @@ -53,6 +54,9 @@
import org.apache.gravitino.listener.api.event.LoadCatalogEvent;
import org.apache.gravitino.listener.api.event.LoadCatalogFailureEvent;
import org.apache.gravitino.listener.api.event.LoadCatalogPreEvent;
import org.apache.gravitino.listener.api.event.TestConnectionEvent;
import org.apache.gravitino.listener.api.event.TestConnectionFailureEvent;
import org.apache.gravitino.listener.api.event.TestConnectionPreEvent;
import org.apache.gravitino.listener.api.info.CatalogInfo;
import org.apache.gravitino.secret.SecretBinding;
import org.apache.gravitino.secret.SecretReference;
Expand Down Expand Up @@ -218,20 +222,23 @@ public void testConnection(
String comment,
Map<String, String> properties)
throws Exception {
// TODO(#12566): Support event dispatching for testConnection
dispatcher.testConnection(ident, type, provider, comment, properties);
CatalogInfo catalogInfo =
new CatalogInfo(ident.name(), type, provider, comment, properties, null);
dispatchTestConnection(
ident,
catalogInfo,
null,
() -> dispatcher.testConnection(ident, type, provider, comment, properties));
}

@Override
public void testConnection(NameIdentifier ident) throws Exception {
// TODO(#12566): Support event dispatching for testConnection
dispatcher.testConnection(ident);
dispatchTestConnection(ident, null, null, () -> dispatcher.testConnection(ident));
}

@Override
public void testConnection(NameIdentifier ident, CatalogChange... changes) throws Exception {
// TODO(#12566): Support event dispatching for testConnection
dispatcher.testConnection(ident, changes);
dispatchTestConnection(ident, null, changes, () -> dispatcher.testConnection(ident, changes));
}

@Override
Expand Down Expand Up @@ -260,4 +267,26 @@ public void disableCatalog(NameIdentifier ident) throws NoSuchCatalogException {
throw e;
}
}

private void dispatchTestConnection(
NameIdentifier ident,
@Nullable CatalogInfo catalogInfo,
@Nullable CatalogChange[] changes,
ConnectionTestAction action)
throws Exception {
String user = PrincipalUtils.getCurrentUserName();
eventBus.dispatchEvent(new TestConnectionPreEvent(user, ident, catalogInfo, changes));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-event veto works in CatalogEventDispatcher, but both test-connection REST methods (CatalogOperations.java:226 and :273) pass the thrown ForbiddenException to handleTestConnectionException (ExceptionHandlers.java:245), which has no forbidden branch and returns HTTP 500 via Utils.internalError. Other catalog handlers map this to Utils.forbidden (403). Please handle ForbiddenException there and add a REST test for both endpoints so a synchronous pre-listener veto stays a 403 and does not run the connection test.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mapped ForbiddenException to HTTP 403 in the shared handler. Added REST tests for both endpoints, covering stored configuration, proposed changes, and empty changes. They verify that a synchronous pre-listener veto never reaches the delegate and preserves the existing stack-trace behavior.

try {
action.run();
eventBus.dispatchEvent(new TestConnectionEvent(user, ident, catalogInfo, changes));
} catch (Exception e) {
eventBus.dispatchEvent(new TestConnectionFailureEvent(user, ident, e, catalogInfo, changes));
throw e;
}
}

@FunctionalInterface
private interface ConnectionTestAction {
void run() throws Exception;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public enum OperationType {
LIST_CATALOG,
ENABLE_CATALOG,
DISABLE_CATALOG,
TEST_CONNECTION_CATALOG,
Comment thread
VedantMadane marked this conversation as resolved.

// Partition event
ADD_PARTITION,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.gravitino.listener.api.event;

import javax.annotation.Nullable;
import org.apache.gravitino.CatalogChange;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
import org.apache.gravitino.listener.api.info.CatalogInfo;

/**
* Represents an event that is triggered upon a successful catalog connection test.
*
* <p>Request parameters are available without redaction, consistent with other catalog events.
* Listeners are responsible for redacting sensitive values before forwarding or logging them.
*/
@DeveloperApi
public final class TestConnectionEvent extends CatalogEvent {
@Nullable private final CatalogInfo catalogInfo;
@Nullable private final CatalogChange[] catalogChanges;

/**
* Constructs an instance of {@code TestConnectionEvent}.
*
* @param user The username of the individual who initiated the connection test.
* @param identifier The identifier of the catalog whose connection was tested.
*/
public TestConnectionEvent(String user, NameIdentifier identifier) {
this(user, identifier, null, null);
}

/**
* Constructs a success event with the parameters supplied for the connection test.
*
* @param user The username of the individual who initiated the connection test.
* @param identifier The identifier of the catalog whose connection was tested.
* @param catalogInfo The parameters of a pre-create test, or null for an existing catalog.
* @param catalogChanges The proposed changes, or null when no changes were supplied.
*/
public TestConnectionEvent(
String user,
NameIdentifier identifier,
@Nullable CatalogInfo catalogInfo,
@Nullable CatalogChange[] catalogChanges) {
super(user, identifier);
this.catalogInfo = catalogInfo;
this.catalogChanges = catalogChanges == null ? null : catalogChanges.clone();
}

/**
* Returns the catalog parameters supplied for a pre-create connection test.
*
* @return The catalog parameters, or null for an existing-catalog test.
*/
@Nullable
public CatalogInfo catalogInfo() {
return catalogInfo;
}

/**
* Returns the proposed changes supplied for an existing-catalog connection test.
*
* @return The proposed changes, or null when no changes were supplied.
*/
@Nullable
public CatalogChange[] catalogChanges() {
return catalogChanges;
}

@Override
public OperationType operationType() {
return OperationType.TEST_CONNECTION_CATALOG;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.gravitino.listener.api.event;

import javax.annotation.Nullable;
import org.apache.gravitino.CatalogChange;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
import org.apache.gravitino.listener.api.info.CatalogInfo;

/**
* Represents an event that is triggered when a catalog connection test fails.
*
* <p>Request parameters and the original exception are available without redaction, consistent with
* other catalog events. Listeners are responsible for redacting sensitive values before forwarding
* or logging them.
*/
@DeveloperApi
public final class TestConnectionFailureEvent extends CatalogFailureEvent {
@Nullable private final CatalogInfo catalogInfo;
@Nullable private final CatalogChange[] catalogChanges;

/**
* Constructs an instance of {@code TestConnectionFailureEvent}.
*
* @param user The username of the individual who initiated the connection test.
* @param identifier The identifier of the catalog whose connection test failed.
* @param exception The original exception encountered during the connection test.
*/
public TestConnectionFailureEvent(String user, NameIdentifier identifier, Exception exception) {
this(user, identifier, exception, null, null);
}

/**
* Constructs a failure event with the parameters supplied for the connection test.
*
* @param user The username of the individual who initiated the connection test.
* @param identifier The identifier of the catalog whose connection test failed.
* @param exception The original exception encountered during the connection test.
* @param catalogInfo The parameters of a pre-create test, or null for an existing catalog.
* @param catalogChanges The proposed changes, or null when no changes were supplied.
*/
public TestConnectionFailureEvent(
String user,
NameIdentifier identifier,
Exception exception,
@Nullable CatalogInfo catalogInfo,
@Nullable CatalogChange[] catalogChanges) {
super(user, identifier, exception);
this.catalogInfo = catalogInfo;
this.catalogChanges = catalogChanges == null ? null : catalogChanges.clone();
}

/**
* Returns the catalog parameters supplied for a pre-create connection test.
*
* @return The catalog parameters, or null for an existing-catalog test.
*/
@Nullable
public CatalogInfo catalogInfo() {
return catalogInfo;
}

/**
* Returns the proposed changes supplied for an existing-catalog connection test.
*
* @return The proposed changes, or null when no changes were supplied.
*/
@Nullable
public CatalogChange[] catalogChanges() {
return catalogChanges;
}

@Override
public OperationType operationType() {
return OperationType.TEST_CONNECTION_CATALOG;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.gravitino.listener.api.event;

import javax.annotation.Nullable;
import org.apache.gravitino.CatalogChange;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
import org.apache.gravitino.listener.api.info.CatalogInfo;

/**
* Represents an event that is generated before a catalog connection test.
*
* <p>Request parameters are available without redaction, consistent with other catalog events.
* Listeners are responsible for redacting sensitive values before forwarding or logging them.
*/
@DeveloperApi
public final class TestConnectionPreEvent extends CatalogPreEvent {
@Nullable private final CatalogInfo catalogInfo;
@Nullable private final CatalogChange[] catalogChanges;

/**
* Constructs an instance of {@code TestConnectionPreEvent}.
*
* @param user The username of the individual who initiated the connection test.
* @param identifier The identifier of the catalog whose connection is being tested.
*/
public TestConnectionPreEvent(String user, NameIdentifier identifier) {
this(user, identifier, null, null);
}

/**
* Constructs a pre-event with the parameters supplied for the connection test.
*
* @param user The username of the individual who initiated the connection test.
* @param identifier The identifier of the catalog whose connection is being tested.
* @param catalogInfo The parameters of a pre-create test, or null for an existing catalog.
* @param catalogChanges The proposed changes, or null when no changes were supplied.
*/
public TestConnectionPreEvent(
String user,
NameIdentifier identifier,
@Nullable CatalogInfo catalogInfo,
@Nullable CatalogChange[] catalogChanges) {
super(user, identifier);
this.catalogInfo = catalogInfo;
this.catalogChanges = catalogChanges == null ? null : catalogChanges.clone();
}

/**
* Returns the catalog parameters supplied for a pre-create connection test.
*
* @return The catalog parameters, or null for an existing-catalog test.
*/
@Nullable
public CatalogInfo catalogInfo() {
return catalogInfo;
}

/**
* Returns the proposed changes supplied for an existing-catalog connection test.
*
* @return The proposed changes, or null when no changes were supplied.
*/
@Nullable
public CatalogChange[] catalogChanges() {
return catalogChanges;
}

@Override
public OperationType operationType() {
return OperationType.TEST_CONNECTION_CATALOG;
}
}
Loading
Loading