This is an automated email from the ASF dual-hosted git repository.
sungwy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 2ae08b846 core: rename Resolvable.CATALOG_ROLES to
Resolvable.CALLER_CATALOG_ROLES (#3916)
2ae08b846 is described below
commit 2ae08b8469c512aa3d07a83f46b322b5301836c5
Author: Sung Yun <[email protected]>
AuthorDate: Mon Mar 2 18:35:30 2026 -0500
core: rename Resolvable.CATALOG_ROLES to Resolvable.CALLER_CATALOG_ROLES
(#3916)
* rename Resolvable.CALLER_CATALOG_ROLES and add special handling for
requested CATALOG_ROLES
* adopt feedback
---
.../resolver/PolarisResolutionManifest.java | 8 ++-
.../core/persistence/resolver/Resolvable.java | 13 ++--
.../core/persistence/resolver/Resolver.java | 72 ++++++++++++++--------
.../polaris/core/persistence/ResolverTest.java | 24 +++++++-
4 files changed, 82 insertions(+), 35 deletions(-)
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
index a3965bd4f..4954cdd48 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
@@ -96,7 +96,13 @@ public class PolarisResolutionManifest implements
PolarisResolutionManifestCatal
addTopLevelName(PolarisEntityConstants.getRootContainerName(),
PolarisEntityType.ROOT, true);
}
- /** Adds a name of a top-level entity (Catalog, Principal, PrincipalRole) to
be resolved. */
+ /**
+ * Adds a named entity to be resolved via the resolver's name-based
registration surface.
+ *
+ * <p>This includes top-level entities (Catalog, Principal, PrincipalRole),
and also {@code
+ * CATALOG_ROLE}. For {@code CATALOG_ROLE}, a reference catalog must be
present on the
+ * manifest/resolver context.
+ */
public void addTopLevelName(String entityName, PolarisEntityType entityType,
boolean isOptional) {
addedTopLevelNames.put(entityName, entityType);
if (isOptional) {
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
index 28f3f09b9..e1393bfaa 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
@@ -29,16 +29,19 @@ public enum Resolvable {
CALLER_PRINCIPAL,
/** Resolve the caller's activated principal-role entities. */
CALLER_PRINCIPAL_ROLES,
- /** Resolve catalog-role entities (e.g., roles attached in the reference
catalog). */
- CATALOG_ROLES,
+ /** Resolve caller-activated catalog-role entities in the reference catalog.
*/
+ CALLER_CATALOG_ROLES,
/** Resolve the reference catalog entity. */
REFERENCE_CATALOG,
/** Resolve explicitly registered paths (via addPath/addPassthroughPath). */
REQUESTED_PATHS,
/**
- * Resolve any additional top-level entities explicitly registered via
addTopLevelName, such as
- * catalog/principal/principal-role names used for authorization beyond the
caller and reference
- * catalog.
+ * Resolve any additional top-level entities explicitly registered via {@link
+ * PolarisResolutionManifest#addTopLevelName}, such as
catalog/principal/principal-role names used
+ * for authorization beyond the caller and reference catalog.
+ *
+ * <p>All entity types resolved here share the same {@link
+ * PolarisResolutionManifest#addTopLevelName} registration surface.
*/
REQUESTED_TOP_LEVEL_ENTITIES
}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
index 532e9aa69..c6f1a7e88 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
@@ -251,7 +251,8 @@ public class Resolver {
public ResolverStatus resolveSelections(@Nonnull Set<Resolvable> selections)
{
diagnostics.checkNotNull(selections, "resolver_selections_is_null");
diagnostics.check(!selections.isEmpty(), "resolver_selections_is_empty");
- return resolveWithPlan(ResolvePlan.fromSelections(selections,
referenceCatalogName));
+ return resolveWithPlan(
+ ResolvePlan.fromSelections(selections, referenceCatalogName,
hasRequestedCatalogRoles()));
}
private ResolverStatus resolveWithPlan(ResolvePlan plan) {
@@ -429,7 +430,8 @@ public class Resolver {
// first resolve the principal and determine the set of activated
principal roles
ResolverStatus status =
plan.resolveCallerPrincipal()
- ? this.resolveCallerPrincipalAndPrincipalRoles(toValidate,
plan.resolvePrincipalRoles())
+ ? this.resolveCallerPrincipalAndPrincipalRoles(
+ toValidate, plan.resolveCallerPrincipalRoles())
: new ResolverStatus(ResolverStatus.StatusEnum.SUCCESS);
// if success, continue resolving
@@ -439,18 +441,19 @@ public class Resolver {
this.diagnostics.checkNotNull(this.referenceCatalogName,
"reference_catalog_expected");
status =
this.resolveReferenceCatalog(
- toValidate, this.referenceCatalogName,
plan.resolveCatalogRoles());
+ toValidate, this.referenceCatalogName,
plan.resolveCallerCatalogRoles());
}
// if success, continue resolving
if (status.getStatus() == ResolverStatus.StatusEnum.SUCCESS) {
// then resolve all the additional entities we were asked to resolve
- if (plan.resolveTopLevelEntities()) {
+ if (plan.resolveRequestedTopLevelEntities()) {
status = this.resolveEntities(toValidate, this.entitiesToResolve);
}
// if success, continue resolving
- if (status.getStatus() == ResolverStatus.StatusEnum.SUCCESS &&
plan.resolvePaths()) {
+ if (status.getStatus() == ResolverStatus.StatusEnum.SUCCESS
+ && plan.resolveRequestedPaths()) {
// finally, resolve all paths we need to resolve
status = this.resolvePaths(toValidate, this.pathsToResolve);
}
@@ -472,6 +475,15 @@ public class Resolver {
return validationSuccess ? status : null;
}
+ private boolean hasRequestedCatalogRoles() {
+ for (ResolverEntityName entityName : this.entitiesToResolve) {
+ if (entityName.entityType() == PolarisEntityType.CATALOG_ROLE) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Update all entities which have been resolved since after validation, some
might have changed
*/
@@ -828,20 +840,21 @@ public class Resolver {
}
/**
- * Resolve the reference catalog and determine all activated role. The
principal and principal
- * roles should have already been resolved
+ * Resolve the reference catalog and optionally determine all
caller-activated catalog roles. The
+ * principal and principal roles should have already been resolved.
*
* @param toValidate all entities we have resolved incrementally, possibly
with some entries
* coming from cache, hence we will have to verify that these entities
have not changed in the
* backend
- * @param referenceCatalogName name of the reference catalog to resolve,
along with all catalog
- * roles which are activated
+ * @param referenceCatalogName name of the reference catalog to resolve
+ * @param resolveCallerCatalogRoles whether to resolve caller-activated
catalog roles for the
+ * reference catalog
* @return the status of resolution
*/
private ResolverStatus resolveReferenceCatalog(
@Nonnull List<ResolvedPolarisEntity> toValidate,
@Nonnull String referenceCatalogName,
- boolean resolveCatalogRoles) {
+ boolean resolveCallerCatalogRoles) {
// resolve the catalog
this.resolvedReferenceCatalog =
this.resolveByName(toValidate, PolarisEntityType.CATALOG,
referenceCatalogName);
@@ -852,7 +865,7 @@ public class Resolver {
return new ResolverStatus(PolarisEntityType.CATALOG,
this.referenceCatalogName);
}
- if (resolveCatalogRoles) {
+ if (resolveCallerCatalogRoles) {
// determine the set of catalog roles which have been activated
long catalogId = this.resolvedReferenceCatalog.getEntity().getId();
for (ResolvedPolarisEntity principalRole : resolvedCallerPrincipalRoles)
{
@@ -890,11 +903,11 @@ public class Resolver {
private static record ResolvePlan(
boolean resolveCallerPrincipal,
- boolean resolvePrincipalRoles,
+ boolean resolveCallerPrincipalRoles,
boolean resolveReferenceCatalog,
- boolean resolveCatalogRoles,
- boolean resolveTopLevelEntities,
- boolean resolvePaths) {
+ boolean resolveCallerCatalogRoles,
+ boolean resolveRequestedTopLevelEntities,
+ boolean resolveRequestedPaths) {
private static ResolvePlan all(@Nullable String referenceCatalogName) {
boolean hasReferenceCatalog = referenceCatalogName != null;
@@ -903,20 +916,25 @@ public class Resolver {
}
private static ResolvePlan fromSelections(
- Set<Resolvable> selections, @Nullable String referenceCatalogName) {
- boolean resolvePaths = selections.contains(Resolvable.REQUESTED_PATHS);
- boolean resolveTopLevelEntities =
+ Set<Resolvable> selections,
+ @Nullable String referenceCatalogName,
+ boolean hasRequestedCatalogRoles) {
+ boolean resolveRequestedPaths =
selections.contains(Resolvable.REQUESTED_PATHS);
+ boolean resolveRequestedTopLevelEntities =
selections.contains(Resolvable.REQUESTED_TOP_LEVEL_ENTITIES);
- boolean resolveCatalogRoles =
selections.contains(Resolvable.CATALOG_ROLES);
+ boolean resolveCallerCatalogRoles =
selections.contains(Resolvable.CALLER_CATALOG_ROLES);
// Principal roles depend on resolving the caller principal, and catalog
roles depend on
// principal roles. Only those selections require caller principal
resolution.
- boolean resolvePrincipalRoles =
- selections.contains(Resolvable.CALLER_PRINCIPAL_ROLES) ||
resolveCatalogRoles;
+ boolean resolveCallerPrincipalRoles =
+ selections.contains(Resolvable.CALLER_PRINCIPAL_ROLES) ||
resolveCallerCatalogRoles;
// Reference catalog is required for path resolution and catalog role
expansion.
boolean resolveReferenceCatalog =
- selections.contains(Resolvable.REFERENCE_CATALOG) || resolvePaths ||
resolveCatalogRoles;
+ selections.contains(Resolvable.REFERENCE_CATALOG)
+ || resolveRequestedPaths
+ || resolveCallerCatalogRoles
+ || (resolveRequestedTopLevelEntities &&
hasRequestedCatalogRoles);
boolean resolveCallerPrincipal =
- selections.contains(Resolvable.CALLER_PRINCIPAL) ||
resolvePrincipalRoles;
+ selections.contains(Resolvable.CALLER_PRINCIPAL) ||
resolveCallerPrincipalRoles;
boolean hasReferenceCatalog = referenceCatalogName != null;
if (!hasReferenceCatalog && resolveReferenceCatalog) {
@@ -927,11 +945,11 @@ public class Resolver {
return new ResolvePlan(
resolveCallerPrincipal,
- resolvePrincipalRoles,
+ resolveCallerPrincipalRoles,
resolveReferenceCatalog,
- resolveCatalogRoles,
- resolveTopLevelEntities,
- resolvePaths);
+ resolveCallerCatalogRoles,
+ resolveRequestedTopLevelEntities,
+ resolveRequestedPaths);
}
}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
index 3af68107a..edf5de2de 100644
---
a/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
@@ -120,7 +120,7 @@ public class ResolverTest extends BaseResolverTest {
}
@Test
- public void testResolveSelectionsRequiresCallerPrincipalForCatalogRoles() {
+ public void
testResolveSelectionsRequiresCallerPrincipalForCallerCatalogRoles() {
Resolver resolver =
new Resolver(
diagServices,
@@ -129,11 +129,31 @@ public class ResolverTest extends BaseResolverTest {
PolarisPrincipal.of("missing", Map.of(), Set.of()),
null,
"test");
- ResolverStatus status =
resolver.resolveSelections(Set.of(Resolvable.CATALOG_ROLES));
+ ResolverStatus status =
resolver.resolveSelections(Set.of(Resolvable.CALLER_CATALOG_ROLES));
Assertions.assertThat(status.getStatus())
.isEqualTo(ResolverStatus.StatusEnum.CALLER_PRINCIPAL_DOES_NOT_EXIST);
}
+ @Test
+ public void
+
testResolveSelectionsRequestedTopLevelEntitiesWithCatalogRoleResolvesReferenceCatalog()
{
+ Resolver resolver =
+ new Resolver(
+ diagServices,
+ callCtx(),
+ metaStoreManager(),
+ PolarisPrincipal.of("missing", Map.of(), Set.of()),
+ null,
+ "test");
+ resolver.addOptionalEntityByName(PolarisEntityType.CATALOG_ROLE, "role1");
+ ResolverStatus status =
+
resolver.resolveSelections(Set.of(Resolvable.REQUESTED_TOP_LEVEL_ENTITIES));
+
Assertions.assertThat(status.getStatus()).isEqualTo(ResolverStatus.StatusEnum.SUCCESS);
+ ResolvedPolarisEntity resolvedCatalog =
resolver.getResolvedReferenceCatalog();
+ Assertions.assertThat(resolvedCatalog).isNotNull();
+
Assertions.assertThat(resolvedCatalog.getEntity().getName()).isEqualTo("test");
+ }
+
@Test
public void testResolveSelectionsRequiresCallerPrincipalForCallerPrincipal()
{
Resolver resolver =