Skip to content

Commit

Permalink
EXPERIMENT: New Nessie CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
snazy committed Apr 26, 2024
1 parent 9b7eb0f commit b492737
Show file tree
Hide file tree
Showing 80 changed files with 7,604 additions and 0 deletions.
2 changes: 2 additions & 0 deletions bom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ dependencies {
constraints {
api(rootProject)
api(project(":nessie-azurite-testcontainer"))
api(project(":nessie-cli"))
api(project(":nessie-cli-grammar"))
api(project(":nessie-client"))
api(project(":nessie-client-testextension"))
api(project(":nessie-combined-cs"))
Expand Down
125 changes: 125 additions & 0 deletions cli/cli/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (C) 2022 Dremio
*
* Licensed 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
import org.apache.tools.ant.taskdefs.condition.Os

plugins {
alias(libs.plugins.quarkus)
id("nessie-conventions-quarkus")
id("nessie-jacoco")
}

extra["maven.name"] = "Nessie - CLI"

configurations.all { exclude(group = "org.projectnessie.nessie", module = "nessie-model") }

dependencies {
implementation(project(":nessie-model-quarkus"))
implementation(project(":nessie-client"))
implementation(project(":nessie-cli-grammar"))

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

compileOnly(libs.immutables.value.annotations)
annotationProcessor(libs.immutables.value.processor)

compileOnly(libs.jakarta.annotation.api)
compileOnly(libs.microprofile.openapi)

implementation(platform(libs.jackson.bom))
implementation("com.fasterxml.jackson.core:jackson-databind")

compileOnly(libs.immutables.builder)
compileOnly(libs.immutables.value.annotations)
annotationProcessor(libs.immutables.value.processor)

testFixturesApi(enforcedPlatform(libs.quarkus.bom))
testFixturesApi("io.quarkus:quarkus-junit5")
testFixturesApi(libs.microprofile.openapi)

testFixturesApi(platform(libs.junit.bom))
testFixturesApi(libs.bundles.junit.testing)

testCompileOnly(libs.immutables.value.annotations)
}

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

val packageType = quarkusPackageType()

quarkus {
quarkusBuildProperties.put("quarkus.package.type", packageType)
// quarkusBuildProperties.put("quarkus.package.output-directory",
// project.layout.buildDirectory.dir("nessie-cli").get().toString())
// quarkusBuildProperties.put("quarkus.package.output-name", "nessie-cli")
quarkusBuildProperties.put("quarkus.package.add-runner-suffix", "false")
// 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.manifest.attributes.\"${e.key}\"" to e.value.toString() }
.toMap()
}
)
}

if (quarkusFatJar()) {
afterEvaluate {
publishing {
publications {
named<MavenPublication>("maven") {
val quarkusBuild = tasks.getByName<QuarkusBuild>("quarkusBuild")
artifact(quarkusBuild.runnerJar) {
classifier = "runner"
builtBy(quarkusBuild)
}
}
}
}
}
}

listOf("javadoc", "sourcesJar").forEach { name ->
tasks.named(name).configure { dependsOn(tasks.named("compileQuarkusGeneratedSourcesJava")) }
}

listOf("checkstyleTest", "compileTestJava").forEach { name ->
tasks.named(name).configure { dependsOn(tasks.named("compileQuarkusTestGeneratedSourcesJava")) }
}

// Testcontainers is not supported on Windows :(
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
tasks.named<Test>("intTest").configure { this.enabled = false }
}

// Issue w/ testcontainers/podman in GH workflows :(
if (Os.isFamily(Os.FAMILY_MAC) && System.getenv("CI") != null) {
tasks.named<Test>("intTest").configure { this.enabled = false }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2024 Dremio
*
* Licensed 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.projectnessie.nessie.cli.cli;

import static org.projectnessie.nessie.cli.cli.NessieCliImpl.OPTION_COMMAND;
import static org.projectnessie.nessie.cli.cli.NessieCliImpl.OPTION_CONTINUE_ON_ERROR;
import static org.projectnessie.nessie.cli.cli.NessieCliImpl.OPTION_KEEP_RUNNING;
import static org.projectnessie.nessie.cli.cli.NessieCliImpl.OPTION_SCRIPT;

import java.util.List;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Option;

class CommandsToRun {

@ArgGroup CommandsSource commandsSource;

@Option(
names = {"-K", OPTION_KEEP_RUNNING},
description = {
"When running commands via the "
+ OPTION_COMMAND
+ " option the process will exit once the commands have been executed.",
"To keep the REPL running, specify this option."
})
boolean keepRunning;

@Option(
names = {"-E", OPTION_CONTINUE_ON_ERROR},
description = {
"When running commands via the "
+ OPTION_COMMAND
+ " option the process will stop/exit when a command could not be parsed or ran into an error.",
"Specifying this option lets the REPL continue executing the remaining commands after parse or runtime errors."
})
boolean continueOnError;

@Override
public String toString() {
return "CommandsToRun{"
+ "commandsSource="
+ commandsSource
+ ", keepRunning="
+ keepRunning
+ ", continueOnError="
+ continueOnError
+ '}';
}

static class CommandsSource {
@Option(
names = {"-s", OPTION_SCRIPT},
description = {
"Run the commands in the Nessie CLI script referenced by this option.",
"Possible values are either a file path or use the minus character ('-') to read the script from stdin."
})
String scriptFile;

@Option(
names = {"-c", OPTION_COMMAND},
arity = "*",
description = {
"Nessie CLI commands to run. Each value represents one command.",
"The process will exit once all specified commands have been executed. To keep the REPL running, specify the "
+ OPTION_KEEP_RUNNING
+ " option."
})
List<String> commands = List.of();

@Override
public String toString() {
return "CommandsSource{" + "runScript='" + scriptFile + '\'' + ", commands=" + commands + '}';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2024 Dremio
*
* Licensed 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.projectnessie.nessie.cli.cli;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import picocli.CommandLine.Option;

class ConnectOptions {
@Option(
names = {"-u", "--uri"},
required = true,
description = "REST API endpoint URI to connect to.")
URI uri;

@Option(
names = "--client-name",
description =
"Name of the client implementation to use, defaults to HTTP suitable for Nessie REST API.")
String clientName;

@Option(
names = {"-o", "--client-option"},
description = "Parameters to configure the REST client.",
split = ",",
arity = "0..*")
Map<String, String> clientOptions = new HashMap<>();

@Option(
names = {"-r", "--initial-reference"},
description = "Name of the Nessie reference to use.")
String initialReference;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2024 Dremio
*
* Licensed 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.projectnessie.nessie.cli.cli;

import java.io.PrintWriter;
import java.util.Optional;
import org.jline.terminal.Terminal;
import org.projectnessie.client.api.NessieApiV2;
import org.projectnessie.model.Reference;

public interface NessieCli {
PrintWriter writer();

String readResource(String resource);

void exitRepl(int exitCode);

Terminal terminal();

boolean dumbTerminal();

void connected(NessieApiV2 nessieApi);

void setCurrentReference(Reference reference);

Reference getCurrentReference();

Optional<NessieApiV2> nessieApi();

NessieApiV2 mandatoryNessieApi();
}
Loading

0 comments on commit b492737

Please sign in to comment.