Skip to content

Commit

Permalink
Polaris Server Admin Tool
Browse files Browse the repository at this point in the history
Implement Bootstrap and Purge commands for the Quarkus server runtime
  • Loading branch information
adutra committed Jan 8, 2025
1 parent a397b65 commit 6a50ff4
Show file tree
Hide file tree
Showing 14 changed files with 515 additions and 0 deletions.
2 changes: 2 additions & 0 deletions LICENSE-BINARY-DIST
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ commons-io:commons-io
commons-logging:commons-logging
commons-net:commons-net
dev.failsafe:failsafe
info.picocli:picocli
io.airlift:aircompressor
io.grpc:grpc-alts
io.grpc:grpc-api
Expand Down Expand Up @@ -399,6 +400,7 @@ io.quarkus:quarkus-micrometer-registry-prometheus
io.quarkus:quarkus-mutiny
io.quarkus:quarkus-netty
io.quarkus:quarkus-opentelemetry
io.quarkus:quarkus-picocli
io.quarkus:quarkus-reactive-routes
io.quarkus:quarkus-rest
io.quarkus:quarkus-rest-common
Expand Down
1 change: 1 addition & 0 deletions gradle/projects.main.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ polaris-api-management-model=api/management-model
polaris-api-management-service=api/management-service
polaris-service-common=service/common
polaris-quarkus-service=quarkus/service
polaris-quarkus-admin=quarkus/admin
polaris-eclipselink=extension/persistence/eclipselink
polaris-jpa-model=extension/persistence/jpa-model
aggregated-license-report=aggregated-license-report
Expand Down
86 changes: 86 additions & 0 deletions quarkus/admin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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.
*/

import io.quarkus.gradle.tasks.QuarkusBuild

plugins {
alias(libs.plugins.quarkus)
alias(libs.plugins.openapi.generator)
id("polaris-server")
id("polaris-license-report")
id("application")
}

dependencies {
implementation(project(":polaris-core"))
implementation(project(":polaris-api-management-service"))
implementation(project(":polaris-api-iceberg-service"))
implementation(project(":polaris-service-common"))
implementation(project(":polaris-quarkus-service"))

implementation(platform(libs.quarkus.bom))
implementation("io.quarkus:quarkus-picocli")

implementation("org.jboss.slf4j:slf4j-jboss-logmanager")

// override dnsjava version in dependencies due to https://github.com/dnsjava/dnsjava/issues/329
implementation(platform(libs.dnsjava))

testImplementation(enforcedPlatform(libs.quarkus.bom))
testImplementation("io.quarkus:quarkus-junit5")

testImplementation(platform(libs.junit.bom))
testImplementation(libs.bundles.junit.testing)
}

tasks.withType<ProcessResources>().configureEach {
from("src/main/resources") {
expand("polarisVersion" to version)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}

quarkus {
quarkusBuildProperties.put("quarkus.package.type", "uber-jar")
// Pull manifest attributes from the "main" `jar` task to get the
// release-information into the jars generated by Quarkus.
quarkusBuildProperties.putAll(
provider {
tasks
.named("jar", Jar::class.java)
.get()
.manifest
.attributes
.map { e -> "quarkus.package.jar.manifest.attributes.\"${e.key}\"" to e.value.toString() }
.toMap()
}
)
}

publishing {
publications {
named<MavenPublication>("maven") {
val quarkusBuild = tasks.getByName<QuarkusBuild>("quarkusBuild")
artifact(quarkusBuild.runnerJar) {
classifier = "runner"
builtBy(quarkusBuild)
}
}
}
}
46 changes: 46 additions & 0 deletions quarkus/admin/src/main/docker/Dockerfile.jvm
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#
# 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.
#
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20-2.1726695192

LABEL org.opencontainers.image.source=https://github.com/apache/polaris
LABEL org.opencontainers.image.description="Apache Polaris (incubating) Admin Tool"
LABEL org.opencontainers.image.licenses=Apache-2.0

ENV LANGUAGE='en_US:en'

USER root
RUN groupadd --gid 10001 polaris \
&& useradd --uid 10000 --gid polaris polaris \
&& chown -R polaris:polaris /opt/jboss/container \
&& chown -R polaris:polaris /deployments

USER polaris
WORKDIR /home/polaris
ENV USER=polaris
ENV UID=10000
ENV HOME=/home/polaris

# We make four distinct layers so if there are application changes the library layers can be re-used
COPY --chown=polaris:polaris build/quarkus-app/lib/ /deployments/lib/
COPY --chown=polaris:polaris build/quarkus-app/*.jar /deployments/
COPY --chown=polaris:polaris build/quarkus-app/app/ /deployments/app/
COPY --chown=polaris:polaris build/quarkus-app/quarkus/ /deployments/quarkus/

ENV AB_JOLOKIA_OFF=""
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.polaris.service.quarkus.admin;

import jakarta.inject.Inject;
import java.util.concurrent.Callable;
import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
import org.apache.polaris.service.quarkus.persistence.QuarkusPersistenceConfiguration;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Spec;

public abstract class BaseCommand implements Callable<Integer> {

public static final Integer EXIT_CODE_GENERIC_ERROR = 1;
public static final Integer EXIT_CODE_BOOTSTRAP_ERROR = 2;
public static final Integer EXIT_CODE_PURGE_ERROR = 3;

@Inject QuarkusPersistenceConfiguration persistenceConfiguration;

@Inject MetaStoreManagerFactory metaStoreManagerFactory;

@Spec CommandSpec spec;

protected void warnOnInMemory() {
if (persistenceConfiguration.type().equalsIgnoreCase("in-memory")) {
spec.commandLine()
.getErr()
.println(
spec.commandLine()
.getColorScheme()
.errorText(
"""
*********************************************************************************************
** Running the Admin Tool on a Polaris instance with in-memory persistence is meaningless! **
*********************************************************************************************
"""));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.polaris.service.quarkus.admin;

import java.util.List;
import java.util.Map;
import org.apache.polaris.core.auth.PolarisSecretsManager.PrincipalSecretsResult;
import picocli.CommandLine;

@CommandLine.Command(
name = "bootstrap",
mixinStandardHelpOptions = true,
description = "Bootstraps principal credentials for all realms and prints them to log.")
public class BootstrapCommand extends BaseCommand {

@CommandLine.Option(
names = {"-r", "--realm"},
required = true,
description = "The name of the realm to bootstrap.")
List<String> realms;

@Override
public Integer call() {
warnOnInMemory();

// Execute the bootstrap
Map<String, PrincipalSecretsResult> results = metaStoreManagerFactory.bootstrapRealms(realms);

// Log any errors:
boolean success = true;
for (Map.Entry<String, PrincipalSecretsResult> result : results.entrySet()) {
if (!result.getValue().isSuccess()) {
spec.commandLine()
.getErr()
.printf(
"Bootstrapping `%s` failed: %s%n",
result.getKey(), result.getValue().getReturnStatus().toString());
success = false;
}
}

if (success) {
spec.commandLine().getOut().println("Bootstrap completed successfully.");
return 0;
} else {
spec.commandLine().getErr().println("Bootstrap encountered errors during operation.");
return EXIT_CODE_BOOTSTRAP_ERROR;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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.polaris.service.quarkus.admin;

import io.quarkus.picocli.runtime.annotations.TopCommand;
import java.io.PrintWriter;
import picocli.CommandLine.Command;
import picocli.CommandLine.HelpCommand;

@TopCommand
@Command(
name = "polaris-admin-tool-runner.jar",
mixinStandardHelpOptions = true,
versionProvider = PolarisVersionProvider.class,
description = "Nessie Server Admin Tool",
subcommands = {
HelpCommand.class,
BootstrapCommand.class,
PurgeCommand.class,
})
public class PolarisAdminTool extends BaseCommand {

@Override
public Integer call() {
return info();
}

private int info() {
warnOnInMemory();

PrintWriter out = spec.commandLine().getOut();

out.println("Polaris server information & maintenance tool.");
out.println("Use the 'help' command.");
out.println();
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.polaris.service.quarkus.admin;

import java.io.InputStream;
import java.net.URL;
import java.util.Objects;
import java.util.Properties;
import picocli.CommandLine.IVersionProvider;

public class PolarisVersionProvider implements IVersionProvider {

@Override
public String[] getVersion() throws Exception {
URL resource =
Objects.requireNonNull(PolarisVersionProvider.class.getResource("version.properties"));
try (InputStream input = resource.openConnection().getInputStream()) {
Properties props = new Properties();
props.load(input);
return new String[] {props.getProperty("polaris.version")};
}
}
}
Loading

0 comments on commit 6a50ff4

Please sign in to comment.