Conversation
542d619 to
70ad92f
Compare
|
@flyrain : CI fails? 🤔 |
|
@flyrain the CI failure is an interesting one. After some investigation, it seems related to the colored output that we have by default when running server tests: Quarkus CLI tests seem unable to capture colored output properly. This can be fixed in two ways: by removing the colored output completely for all tests (but that's frustrating) – or by implementing public class RelationalJdbcAdminProfile extends RelationalJdbcProfile {
@Override
public Map<String, String> getConfigOverrides() {...}
@Override
public List<TestResourceEntry> testResources() {...}
// ADD THIS
@Override public String getConfigProfile() { return "cli"; }
}The above will make the test run under the |
| %cli.quarkus.log.category."io.quarkus".level=ERROR | ||
| %cli.quarkus.log.category."io.quarkus.agroal.deployment".level=ERROR | ||
| %cli.quarkus.log.category."org.hibernate.validator".level=ERROR | ||
| %cli.quarkus.log.category."org.apache.polaris.service.config.ServiceProducers".level=ERROR |
There was a problem hiding this comment.
Rather than silencing the whole class, I'd suggest modifying the maybeBootstrap method as follows:
public void maybeBootstrap(
@Observes Startup event,
MetaStoreManagerFactory factory,
PersistenceConfiguration config,
RealmContextConfiguration realmContextConfiguration) {
if (ConfigUtils.isProfileActive("cli")) {
return; // never bootstrap realms in CLI profile
}
...I'd also suggest moving this method to a separate class, as it is becoming quite big and complex.
There was a problem hiding this comment.
SGTM. Adopted the change.
For moving it to a separate class, I'd suggest to tackle it in a followup PR given the current PR is big already.
dimas-b
left a comment
There was a problem hiding this comment.
Thanks for you effort, @flyrain !
I played with a local build of this PR and it seems generally usable 👍
However, I believe the PR still needs some attention in the areas of production checks and CDI in general.
Adding some more specific comments below.
...rc/main/java/org/apache/polaris/persistence/relational/jdbc/RelationalJdbcConfiguration.java
Outdated
Show resolved
Hide resolved
.../org/apache/polaris/persistence/relational/jdbc/RelationalJdbcProductionReadinessChecks.java
Outdated
Show resolved
Hide resolved
.../org/apache/polaris/persistence/relational/jdbc/RelationalJdbcProductionReadinessChecks.java
Outdated
Show resolved
Hide resolved
| public Integer call() { | ||
| PrintWriter out = spec.commandLine().getOut(); | ||
| spec.commandLine().usage(out); | ||
| // When invoked without a subcommand, show usage |
There was a problem hiding this comment.
How is it possible to invoke the Admin CLI without a subcommand now? 🤔
There was a problem hiding this comment.
Both work per my test. I have removed the comment to avoid confusion.
yufei@Yufeis-MacBook-Pro-2 polaris % java -jar runtime/server/build/quarkus-app/quarkus-run.jar -h
Usage: polaris-admin-tool.jar [-hV] [COMMAND]
Polaris administration & maintenance tool
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
Commands:
help Display help information about the specified command.
bootstrap Bootstraps realms and root principal credentials.
purge Purge realms and all associated entities.
yufei@Yufeis-MacBook-Pro-2 polaris % java -jar runtime/server/build/quarkus-app/quarkus-run.jar purge -h
Usage: polaris-admin-tool.jar purge [-hV] -r=<realm> [-r=<realm>]...
Purge realms and all associated entities.
-h, --help Show this help message and exit.
-r, --realm=<realm> The name of a realm to purge.
-V, --version Print version information and exit.
| implementation(project(":polaris-runtime-service")) | ||
|
|
||
| // Dependencies from merged polaris-admin module | ||
| implementation(project(":polaris-core")) |
There was a problem hiding this comment.
Is this necessary? I suppose runtime/server included polaris-core before 🤔
There was a problem hiding this comment.
Changed it to compileOnly, otherwise the compilation will fail.
There was a problem hiding this comment.
Oh, I did not mean to imply that the dep. was wrong... I was just wondering 🙂
If core is require for complication, we should probably keep it as an implementation dep.
| Instance<ProductionReadinessCheck> checks, | ||
| ReadinessConfiguration config) { | ||
| // Skip production readiness checks in CLI mode - they're only relevant for server deployments | ||
| if ("cli".equals(System.getProperty("quarkus.profile"))) { |
There was a problem hiding this comment.
Let's try to find a more natural way to perform readiness checks under the CLI env.
There was a problem hiding this comment.
Sure, I'm open for suggestions.
There was a problem hiding this comment.
It's safer to use the following idiom, as more than one profile can be specified with quarkus.profile:
if (ConfigUtils.isProfileActive("cli")) {There was a problem hiding this comment.
Fixed in the new commit. Thanks for the suggestion.
.asf.yaml
Outdated
| - "Quarkus Tests" | ||
| - "Quarkus Integration Tests" | ||
| - "Quarkus Admin Tests" | ||
| - "Quarkus Server Tests" |
There was a problem hiding this comment.
I believe we simply need to remove Quarkus Admin Tests here, not rename
runtime/server/src/main/java/org/apache/polaris/admintool/config/AdminToolProducers.java
Outdated
Show resolved
Hide resolved
Awesome! Thanks a lot for the suggestion, @adutra! All tests passed now! |
dimas-b
left a comment
There was a problem hiding this comment.
from my POV this PR is almost ready to merge :) I hope a few new minor comments, below could still be squeezed in.
| quarkus.banner.enabled=false | ||
|
|
||
| # Logging configuration - suppress verbose output for CLI | ||
| quarkus.log.level=WARN |
There was a problem hiding this comment.
Should we suppress CONSOLE log instead but keep default levels informative in case a user enabled FILE logging?
There was a problem hiding this comment.
I'm open for that, but the WARN level logging was carried from the application.properties in the removed admin module,
There was a problem hiding this comment.
ah, sorry, I missed that. Current code is fine for now 👍
| # Get the directory | ||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| cd "$SCRIPT_DIR/../admin" | ||
| cd "$SCRIPT_DIR/../server" |
There was a problem hiding this comment.
for follow-up: with a single binary package, we may want to rename / restructure the binary dist for clarity.
There was a problem hiding this comment.
Definitely, there are a few places needed to be changed, including doc. I will address them in followups.
| Instance<ProductionReadinessCheck> checks, | ||
| ReadinessConfiguration config) { | ||
| // Skip production readiness checks in CLI mode - they're only relevant for server deployments | ||
| if (ConfigUtils.isProfileActive("cli")) { |
There was a problem hiding this comment.
This is probably ok in the interest of progress, but in general I hope we could leverage profile-specific config like polaris.production.readiness.checks.enabled=true (or false for CLI). WDYT?
There was a problem hiding this comment.
That's probably a good idea, esp. if we want to group a set of methods under the same configure key, instead of spreed if (ConfigUtils.isProfileActive("cli") in multiple places. We could improve in followups.
There was a problem hiding this comment.
I believe using dedicated config properties for this is a small change :) but I'm also ok with addressing this in a follow-up PR.
| MetaStoreManagerFactory factory, | ||
| PersistenceConfiguration config, | ||
| RealmContextConfiguration realmContextConfiguration) { | ||
| if (ConfigUtils.isProfileActive("cli")) { |
There was a problem hiding this comment.
Same here: I'd prefer to use explicit config flags (set differently in each profile) vs. checking the name of the profile, please.
| Instance<ProductionReadinessCheck> checks, | ||
| ReadinessConfiguration config) { | ||
| // Skip production readiness checks in CLI mode - they're only relevant for server deployments | ||
| if (ConfigUtils.isProfileActive("cli")) { |
There was a problem hiding this comment.
I believe using dedicated config properties for this is a small change :) but I'm also ok with addressing this in a follow-up PR.
# Conflicts: # runtime/admin/src/main/docker/Dockerfile.jvm
adutra
left a comment
There was a problem hiding this comment.
This is looking really good! I only have a few minor comments.
| # Launch Quarkus | ||
| exec "$JAVA_CMD" ${POLARIS_JAVA_OPTS:-} -jar quarkus-run.jar "$@" | ||
| # Show the usage when no argument is provided | ||
| if [ "$#" -eq 0 ]; then |
runtime/server/build.gradle.kts
Outdated
|
|
||
| // These are already provided transitively by polaris-runtime-service | ||
| // but we need them at compile time for CLI code | ||
| compileOnly(project(":polaris-core")) |
There was a problem hiding this comment.
Agree with @dimas-b these should be implementation for most of them. I would reorder them as below:
implementation(project(":polaris-core"))
implementation(project(":polaris-version"))
implementation(project(":polaris-api-management-service"))
implementation(project(":polaris-api-iceberg-service"))
implementation(project(":polaris-runtime-service"))
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
implementation("io.quarkus:quarkus-picocli")| * <ol> | ||
| * <li>(400) System properties: -D flags at JVM startup | ||
| * <li>(300) Environment variables | ||
| * <li>(260) External config/application-cli.properties: Profile-specific external config |
There was a problem hiding this comment.
As I mentioned on the ML, I'm unsure whether we should mention the possibility of adding this profile-aware external config file, as it has very little added value.
There was a problem hiding this comment.
+1 Let's advise users to customize via the profile-neutral application.properties (and/or corresponding -D and env. vars).
There was a problem hiding this comment.
If a user runs both the server and the CLI with the same Polaris binary of the same location, a shared application.properties applies to both use cases. In that setup, having a separate application-cli.properties still seems useful to capture CLI specific configuration that should not affect the server behavior. That separation feels reasonable and keeps the shared defaults clean while allowing targeted overrides for the CLI. For example, CLI specific configs like the following will be overwritten by application.properties
quarkus.banner.enabled=false
quarkus.log.level=WARN
WDYT?
There was a problem hiding this comment.
AFAIK, profile-specific config works in conjunction with the profile-neutral config. In other words, application.properties is always loaded. This might be too much low-level details for end users to think about.
Even if all the code is bundled in the same Quarkus application, Server and Admin could still have distinct shell entry points and distinct application.properties files (each in its own directory). That would be my preference for the tar-based distribution.
Docker images can bundle anything that Polaris developers are ok with. In docker, users will override config via external mechanisms like env. variables. If a config map is used to define application.properties it will be specific to a particular runtime scenario anyway (Server or Admin, but not both).
There was a problem hiding this comment.
profile-specific config works in conjunction with the profile-neutral config
That's true, and I can confirm that's how it work today.
This might be too much low-level details for end users to think about.
This isn't a user-face doc. This is a comment in the source code. I think it should be fine to be here to provide complete view of how it works.
Even if all the code is bundled in the same Quarkus application, Server and Admin could still have distinct shell entry points and distinct application.properties files (each in its own directory). That would be my preference for the tar-based distribution.
Docker images can bundle anything that Polaris developers are ok with. In docker, users will override config via external mechanisms like env. variables. If a config map is used to define application.properties it will be specific to a particular runtime scenario anyway (Server or Admin, but not both).
I understand that these particular use cases may not require profile specific config files today. That said, this does not mean the scenarios I mentioned will never occur. Providing clear and explicit messaging still has value in that context. Even if a user never actively uses External config/application-cli.properties as a profile specific external config, having a clear understanding of how it works can be important when diagnosing or debugging unexpected behavior.
There was a problem hiding this comment.
Sorry for the last minute comment here, but I wonder if it might make sense to keep the runtime/admin module as a home for Admin code, but not build a Quarkus app from it. The runtime/server module will then import runtime/admin and we end up with one Quarkus app both for the Server and Admin Tool... WDYT?
My rationale for keeping the runtime/admin module is just better code isolation at compile time. The runtime/server module is mostly an assembly descriptor, ATM it does not have any feature code. It might be preferable to keep it this way to allow simpler reuse of feature code from their dedicated modules.
There was a problem hiding this comment.
+1, that's actually a nice idea!
There was a problem hiding this comment.
I see the appeal of this approach, but I worry it may dismiss some of the key benefits of the current refactor(we will need a few common modules to enable a separate admin module), and make the dependency structure less clearer. Please note that, the CLI will need ServiceProvider to work now.
It also makes testing a bit awkward. Tests that are specific to the CLI behavior would have to depend on the default and service module just to pick up application-cli and application properties , which feels indirect and less explicit. For those reasons, I think the current direction still has advantages in terms of modularity, clarity, and test ergonomics.
There was a problem hiding this comment.
I agree on "test ergonomics" as an advantage in the current diff of this PR, but I do not think "modularity" is better - that's exactly what I meant to highlight in my comment above :)
IMHO, better modularity is preferable to "test ergonomics".
There was a problem hiding this comment.
Testing the admin tool could follow the same approach as testing OPA (which is not monolithic with the server, but a pure puglin)... WDYT?
There was a problem hiding this comment.
We will need a few common modules to enable a separate admin module. I believe this is one of areas we used to struggle with.
There was a problem hiding this comment.
In terms of modularity, splitting functionalities across multiple modules does not automatically improve modularity. In many cases it does the opposite. It makes the dependency graph harder to reason about, and forces consumers and tests to pull in modules that exist only to host a thin slice of logic. I think good modularity is about cohesion and clear ownership. A module should group functionality that changes together and represents a meaningful boundary. And I'm not a fan of how we layout OPA modules.
In practice, over splitting often trades real modularity for superficial structure, while introducing costs in test ergonomics, dependency clarity, and mental overhead. Keeping related behavior together, even if it is small, is often the more modular choice. I have mentioned that we have to keep introducing new modules like runtime/common, runtime/test-common, runtime/distribution, they are the side effect of over splitting, which can be avoided in the beginning.
There was a problem hiding this comment.
I don't think keeping the admin module around is "over-splitting".
This PR, while interesting in that it achieves a single artifact/jar for both usages (server and CLI), does create an imbalanced layout where the top module includes code for the CLI, but the code for the server lives in a dependency:
flowchart TD
A["`polaris-server<br/>(incl. admin tool)`"] --> B
B[polaris-runtime-service]
Whereas @dimas-b proposal still keeps the single entrypoint but each usage has its own module:
flowchart TD
A[polaris-server] --> B
A --> C
B[polaris-runtime-service] --> D
C[polaris-admin] --> E
B --> F
C --> F
D[specific deps]
E[specific deps]
F[common deps]
This has a net advantage imho of leaving polaris-server as a mere "assembly descriptor" as @dimas-b puts it.
It makes the dependency graph harder to reason about, and forces consumers and tests to pull in modules that exist only to host a thin slice of logic
I don't buy much this argument: while a proliferation of modules can complicate the dependency graph, modularity offers many upsides: modern build tools efficiently manage even hundreds of dependencies; a DAG enforces clearer mental models about dependencies than monoliths that often create dependency cycles; smaller modules accelerate compilation; and downstream integrators benefit from leaner CDI contexts.
Polaris is currently in an intermediate, non-optimal state: it's neither a monolith, nor a well organized modular application. We should rethink the purpose of those "common" modules, but also consider separating disparate concerns in modules like polaris-runtime-service: what does telemetry have to do with authentication? And what does the secrets manager have to do with events processing? I support moving towards a well-thought modular organization, and I think @dimas-b suggestion goes in that direction.
snazy
left a comment
There was a problem hiding this comment.
This change effectively removed and required LICENSE entries.
This change will also "leak" all server parts into the admin-tool (+ vice versa) and cause (existing and future) CDI components to be initialized even if those must/should not run in the admin-tool. Everybody contributing code to Polaris server must now fully understand and consider this non-obvious behavior (e.g. observing the startup event). Working around the previous example would require conditional if statements scattered around the code base.
Users who would like to use configuration profiles for other more advanced purposes would have to change the production code. See these "if configuration-profile-name equals cli, which would not work for other profile names.
All changes and additions to the non-profile scoped configuration file "leak" into both the server and admin-tool, which can have unintended consequences, which are hard to understand and likely surprising, especially for new contributors.
I think we should be really careful with such an intrusive change.
If the main concern of this change is to address the admittedly long LICENSE + NOTICE file contents for server + admin-tool, I propose to split those into into one shared plus specific sets and join those during the build.
|
|
||
| # force the locale, just in case the system's using another default locale | ||
| quarkus.default-locale=en_US | ||
|
|
There was a problem hiding this comment.
Unrelated change to this already big PR.
|
|
||
| implementation(project(":polaris-runtime-defaults")) | ||
| implementation(project(":polaris-runtime-common")) | ||
| implementation(project(":polaris-runtime-defaults")) |
| api(project(":polaris-extensions-auth-opa")) | ||
|
|
||
| api(project(":polaris-admin")) | ||
| api(project(":polaris-runtime-common")) |
There was a problem hiding this comment.
This should not be removed from the bom
| * tools/minio-testcontainer/src/main/java/org/apache/polaris/test/minio/MinioAccess.java | ||
| * tools/minio-testcontainer/src/main/java/org/apache/polaris/test/minio/MinioContainer.java | ||
| * tools/minio-testcontainer/src/main/java/org/apache/polaris/test/minio/MinioExtension.java | ||
| * runtime/admin/src/main/java/org/apache/polaris/admintool/PolarisAdminTool.java |
There was a problem hiding this comment.
This file has been moved, not removed.
There was a problem hiding this comment.
Good point. We should just update the path (and possibly move this line if sort order matters).
There was a problem hiding this comment.
The LICENSE file contains entries that are not migrated.
Pausing until this discussion is settled: #3340 (comment)

Please check the motivation here, https://lists.apache.org/thread/fs7j81kv2kn0wsh05412yk6pp7w7r5nz
Checklist
CHANGELOG.md(if needed)site/content/in-dev/unreleased(if needed)