summaryrefslogtreecommitdiffstats
path: root/vespa-feed-client
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2021-05-25 17:20:33 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2021-05-25 17:22:10 +0200
commit34dfcc026213e0a5a4f7c7d1ec6e56d34438d892 (patch)
tree7de849ec7070f8f2f4d2c8b86167ed86930cc7e4 /vespa-feed-client
parent69cf843602f1e62582d365acca812357b712e883 (diff)
Split cli and programmatic API artifacts to separate Maven modules
Diffstat (limited to 'vespa-feed-client')
-rw-r--r--vespa-feed-client/CMakeLists.txt3
-rw-r--r--vespa-feed-client/pom.xml28
-rw-r--r--vespa-feed-client/src/main/java/ai/vespa/feed/client/CliArguments.java225
-rw-r--r--vespa-feed-client/src/main/java/ai/vespa/feed/client/CliClient.java93
-rwxr-xr-xvespa-feed-client/src/main/sh/vespa-feed-client.sh82
-rw-r--r--vespa-feed-client/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java61
-rw-r--r--vespa-feed-client/src/test/resources/help.txt13
7 files changed, 0 insertions, 505 deletions
diff --git a/vespa-feed-client/CMakeLists.txt b/vespa-feed-client/CMakeLists.txt
index 747000169b1..7e6346c81cb 100644
--- a/vespa-feed-client/CMakeLists.txt
+++ b/vespa-feed-client/CMakeLists.txt
@@ -1,4 +1 @@
# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-install_fat_java_artifact(vespa-feed-client)
-
-vespa_install_script(src/main/sh/vespa-feed-client.sh vespa-feed-client bin)
diff --git a/vespa-feed-client/pom.xml b/vespa-feed-client/pom.xml
index b1d11c0c8d5..7759e9d2308 100644
--- a/vespa-feed-client/pom.xml
+++ b/vespa-feed-client/pom.xml
@@ -30,11 +30,6 @@
<scope>compile</scope>
</dependency>
<dependency>
- <groupId>commons-cli</groupId>
- <artifactId>commons-cli</artifactId>
- <scope>compile</scope>
- </dependency>
- <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<scope>compile</scope>
@@ -88,29 +83,6 @@
</execution>
</executions>
</plugin>
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <archive>
- <manifest>
- <mainClass>ai.vespa.feed.client.CliClient</mainClass>
- </manifest>
- </archive>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <!-- append to the packaging phase. -->
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
</project>
diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliArguments.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliArguments.java
deleted file mode 100644
index 06c994b12b6..00000000000
--- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliArguments.java
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package ai.vespa.feed.client;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-
-import java.io.File;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.OptionalInt;
-
-/**
- * Parses command line arguments
- *
- * @author bjorncs
- */
-class CliArguments {
-
- private static final Options optionsDefinition = createOptions();
-
- private static final String HELP_OPTION = "help";
- private static final String VERSION_OPTION = "version";
- private static final String ENDPOINT_OPTION = "endpoint";
- private static final String FILE_OPTION = "file";
- private static final String CONNECTIONS_OPTION = "connections";
- private static final String MAX_STREAMS_PER_CONNECTION = "max-streams-per-connection";
- private static final String CERTIFICATE_OPTION = "certificate";
- private static final String PRIVATE_KEY_OPTION = "private-key";
- private static final String CA_CERTIFICATES_OPTION = "ca-certificates";
- private static final String DISABLE_SSL_HOSTNAME_VERIFICATION_OPTION = "disable-ssl-hostname-verification";
- private static final String HEADER_OPTION = "header";
-
- private final CommandLine arguments;
-
- private CliArguments(CommandLine arguments) {
- this.arguments = arguments;
- }
-
- static CliArguments fromRawArgs(String[] rawArgs) throws CliArgumentsException {
- CommandLineParser parser = new DefaultParser();
- try {
- return new CliArguments(parser.parse(optionsDefinition, rawArgs));
- } catch (ParseException e) {
- throw new CliArgumentsException(e);
- }
- }
-
- URI endpoint() throws CliArgumentsException {
- try {
- URL url = (URL) arguments.getParsedOptionValue(ENDPOINT_OPTION);
- if (url == null) throw new CliArgumentsException("Endpoint must be specified");
- return url.toURI();
- } catch (ParseException | URISyntaxException e) {
- throw new CliArgumentsException("Invalid endpoint: " + e.getMessage(), e);
- }
- }
-
- boolean helpSpecified() { return has(HELP_OPTION); }
-
- boolean versionSpecified() { return has(VERSION_OPTION); }
-
- OptionalInt connections() throws CliArgumentsException { return intValue(CONNECTIONS_OPTION); }
-
- OptionalInt maxStreamsPerConnection() throws CliArgumentsException { return intValue(MAX_STREAMS_PER_CONNECTION); }
-
- Optional<CertificateAndKey> certificateAndKey() throws CliArgumentsException {
- Path certificateFile = fileValue(CERTIFICATE_OPTION).orElse(null);
- Path privateKeyFile = fileValue(PRIVATE_KEY_OPTION).orElse(null);
- if ((certificateFile == null) != (privateKeyFile == null)) {
- throw new CliArgumentsException(String.format("Both '%s' and '%s' must be specified together", CERTIFICATE_OPTION, PRIVATE_KEY_OPTION));
- }
- if (privateKeyFile == null && certificateFile == null) return Optional.empty();
- return Optional.of(new CertificateAndKey(certificateFile, privateKeyFile));
- }
-
- Optional<Path> caCertificates() throws CliArgumentsException { return fileValue(CA_CERTIFICATES_OPTION); }
-
- Path inputFile() throws CliArgumentsException {
- return fileValue(FILE_OPTION)
- .orElseThrow(() -> new CliArgumentsException("Feed file must be specified"));
- }
-
- Map<String, String> headers() throws CliArgumentsException {
- String[] rawArguments = arguments.getOptionValues(HEADER_OPTION);
- if (rawArguments == null) return Collections.emptyMap();
- Map<String, String> headers = new HashMap<>();
- for (String rawArgument : rawArguments) {
- if (rawArgument.startsWith("\"") || rawArgument.startsWith("'")) {
- rawArgument = rawArgument.substring(1);
- }
- if (rawArgument.endsWith("\"") || rawArgument.endsWith("'")) {
- rawArgument = rawArgument.substring(0, rawArgument.length() - 1);
- }
- int colonIndex = rawArgument.indexOf(':');
- if (colonIndex == -1) throw new CliArgumentsException("Invalid header: '" + rawArgument + "'");
- headers.put(rawArgument.substring(0, colonIndex), rawArgument.substring(colonIndex + 1).trim());
- }
- return Collections.unmodifiableMap(headers);
- }
-
- boolean sslHostnameVerificationDisabled() { return has(DISABLE_SSL_HOSTNAME_VERIFICATION_OPTION); }
-
- private OptionalInt intValue(String option) throws CliArgumentsException {
- try {
- Number number = (Number) arguments.getParsedOptionValue(option);
- return number != null ? OptionalInt.of(number.intValue()) : OptionalInt.empty();
- } catch (ParseException e) {
- throw new CliArgumentsException(String.format("Invalid value for '%s': %s", option, e.getMessage()), e);
- }
- }
-
- private Optional<Path> fileValue(String option) throws CliArgumentsException {
- try {
- File certificateFile = (File) arguments.getParsedOptionValue(option);
- if (certificateFile == null) return Optional.empty();
- return Optional.of(certificateFile.toPath());
- } catch (ParseException e) {
- throw new CliArgumentsException(String.format("Invalid value for '%s': %s", option, e.getMessage()), e);
- }
- }
-
- private boolean has(String option) { return arguments.hasOption(option); }
-
- private static Options createOptions() {
- return new Options()
- .addOption(Option.builder()
- .longOpt(HELP_OPTION)
- .build())
- .addOption(Option.builder()
- .longOpt(VERSION_OPTION)
- .build())
- .addOption(Option.builder()
- .longOpt(ENDPOINT_OPTION)
- .hasArg()
- .type(URL.class)
- .build())
- .addOption(Option.builder()
- .longOpt(HEADER_OPTION)
- .hasArgs()
- .build())
- .addOption(Option.builder()
- .longOpt(FILE_OPTION)
- .type(File.class)
- .hasArg()
- .build())
- .addOption(Option.builder()
- .longOpt(CONNECTIONS_OPTION)
- .hasArg()
- .type(Number.class)
- .build())
- .addOption(Option.builder()
- .longOpt(MAX_STREAMS_PER_CONNECTION)
- .hasArg()
- .type(Number.class)
- .build())
- .addOption(Option.builder()
- .longOpt(CONNECTIONS_OPTION)
- .hasArg()
- .type(Number.class)
- .build())
- .addOption(Option.builder()
- .longOpt(CERTIFICATE_OPTION)
- .type(File.class)
- .hasArg()
- .build())
- .addOption(Option.builder()
- .longOpt(PRIVATE_KEY_OPTION)
- .type(File.class)
- .hasArg()
- .build())
- .addOption(Option.builder()
- .longOpt(CA_CERTIFICATES_OPTION)
- .type(File.class)
- .hasArg()
- .build())
- .addOption(Option.builder()
- .longOpt(DISABLE_SSL_HOSTNAME_VERIFICATION_OPTION)
- .build());
- }
-
- void printHelp(OutputStream out) {
- HelpFormatter formatter = new HelpFormatter();
- PrintWriter writer = new PrintWriter(out);
- formatter.printHelp(
- writer,
- formatter.getWidth(),
- "vespa-feed-client <options>",
- "Vespa feed client",
- optionsDefinition,
- formatter.getLeftPadding(),
- formatter.getDescPadding(),
- "");
- writer.flush();
- }
-
- static class CliArgumentsException extends Exception {
- CliArgumentsException(String message, Throwable cause) { super(message, cause); }
- CliArgumentsException(Throwable cause) { super(cause.getMessage(), cause); }
- CliArgumentsException(String message) { super(message); }
- }
-
- static class CertificateAndKey {
- final Path certificateFile;
- final Path privateKeyFile;
-
- CertificateAndKey(Path certificateFile, Path privateKeyFile) {
- this.certificateFile = certificateFile;
- this.privateKeyFile = privateKeyFile;
- }
- }
-
-}
diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliClient.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliClient.java
deleted file mode 100644
index 84a29f9c3e4..00000000000
--- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliClient.java
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package ai.vespa.feed.client;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSession;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.file.Path;
-import java.util.Properties;
-
-/**
- * Main method for CLI interface
- *
- * @author bjorncs
- */
-class CliClient {
-
- private final PrintStream systemOut;
- private final PrintStream systemError;
- private final Properties systemProperties;
-
- CliClient(PrintStream systemOut, PrintStream systemError, Properties systemProperties) {
- this.systemOut = systemOut;
- this.systemError = systemError;
- this.systemProperties = systemProperties;
- }
-
- public static void main(String[] args) {
- CliClient client = new CliClient(System.out, System.err, System.getProperties());
- int exitCode = client.run(args);
- System.exit(exitCode);
- }
-
- int run(String[] rawArgs) {
- try {
- CliArguments cliArgs = CliArguments.fromRawArgs(rawArgs);
- if (cliArgs.helpSpecified()) {
- cliArgs.printHelp(systemOut);
- return 0;
- }
- if (cliArgs.versionSpecified()) {
- systemOut.println(Vespa.VERSION);
- return 0;
- }
- FeedClient feedClient = createFeedClient(cliArgs);
- return 0;
- } catch (CliArguments.CliArgumentsException | IOException e) {
- return handleException(e);
- }
- }
-
- private static FeedClient createFeedClient(CliArguments cliArgs) throws CliArguments.CliArgumentsException, IOException {
- FeedClientBuilder builder = FeedClientBuilder.create(cliArgs.endpoint());
- cliArgs.connections().ifPresent(builder::setMaxConnections);
- cliArgs.maxStreamsPerConnection().ifPresent(builder::setMaxConnections);
- if (cliArgs.sslHostnameVerificationDisabled()) {
- builder.setHostnameVerifier(AcceptAllHostnameVerifier.INSTANCE);
- }
- CliArguments.CertificateAndKey certificateAndKey = cliArgs.certificateAndKey().orElse(null);
- Path caCertificates = cliArgs.caCertificates().orElse(null);
- if (certificateAndKey != null || caCertificates != null) {
- SslContextBuilder sslContextBuilder = new SslContextBuilder();
- if (certificateAndKey != null) {
- sslContextBuilder.withCertificateAndKey(certificateAndKey.certificateFile, certificateAndKey.privateKeyFile);
- }
- if (caCertificates != null) {
- sslContextBuilder.withCaCertificates(caCertificates);
- }
- builder.setSslContext(sslContextBuilder.build());
- }
- cliArgs.headers().forEach(builder::addRequestHeader);
- return builder.build();
- }
-
- private int handleException(Exception e) { return handleException(e.getMessage(), e); }
-
- private int handleException(String message, Exception exception) {
- systemError.println(message);
- if (debugMode()) {
- exception.printStackTrace(systemError);
- }
- return 1;
- }
-
- private boolean debugMode() {
- return Boolean.parseBoolean(systemProperties.getProperty("VESPA_DEBUG", Boolean.FALSE.toString()));
- }
-
- private static class AcceptAllHostnameVerifier implements HostnameVerifier {
- static final AcceptAllHostnameVerifier INSTANCE = new AcceptAllHostnameVerifier();
- @Override public boolean verify(String hostname, SSLSession session) { return true; }
- }
-}
diff --git a/vespa-feed-client/src/main/sh/vespa-feed-client.sh b/vespa-feed-client/src/main/sh/vespa-feed-client.sh
deleted file mode 100755
index 2e8d22a4245..00000000000
--- a/vespa-feed-client/src/main/sh/vespa-feed-client.sh
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/sh
-# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-# BEGIN environment bootstrap section
-# Do not edit between here and END as this section should stay identical in all scripts
-
-findpath () {
- myname=${0}
- mypath=${myname%/*}
- myname=${myname##*/}
- empty_if_start_slash=${mypath%%/*}
- if [ "${empty_if_start_slash}" ]; then
- mypath=$(pwd)/${mypath}
- fi
- if [ "$mypath" ] && [ -d "$mypath" ]; then
- return
- fi
- mypath=$(pwd)
- if [ -f "${mypath}/${myname}" ]; then
- return
- fi
- echo "FATAL: Could not figure out the path where $myname lives from $0"
- exit 1
-}
-
-COMMON_ENV=libexec/vespa/common-env.sh
-
-source_common_env () {
- if [ "$VESPA_HOME" ] && [ -d "$VESPA_HOME" ]; then
- export VESPA_HOME
- common_env=$VESPA_HOME/$COMMON_ENV
- if [ -f "$common_env" ]; then
- . $common_env
- return
- fi
- fi
- return 1
-}
-
-findroot () {
- source_common_env && return
- if [ "$VESPA_HOME" ]; then
- echo "FATAL: bad VESPA_HOME value '$VESPA_HOME'"
- exit 1
- fi
- if [ "$ROOT" ] && [ -d "$ROOT" ]; then
- VESPA_HOME="$ROOT"
- source_common_env && return
- fi
- findpath
- while [ "$mypath" ]; do
- VESPA_HOME=${mypath}
- source_common_env && return
- mypath=${mypath%/*}
- done
- echo "FATAL: missing VESPA_HOME environment variable"
- echo "Could not locate $COMMON_ENV anywhere"
- exit 1
-}
-
-findhost () {
- if [ "${VESPA_HOSTNAME}" = "" ]; then
- VESPA_HOSTNAME=$(vespa-detect-hostname || hostname -f || hostname || echo "localhost") || exit 1
- fi
- validate="${VESPA_HOME}/bin/vespa-validate-hostname"
- if [ -f "$validate" ]; then
- "$validate" "${VESPA_HOSTNAME}" || exit 1
- fi
- export VESPA_HOSTNAME
-}
-
-findroot
-findhost
-
-# END environment bootstrap section
-
-export MALLOC_ARENA_MAX=1 #Does not need fast allocation
-exec java \
--Djava.library.path=${VESPA_HOME}/libexec64/native:${VESPA_HOME}/lib64 \
--Djava.awt.headless=true \
--Xms128m -Xmx2048m $(getJavaOptionsIPV46) \
--cp ${VESPA_HOME}/lib/jars/vespa-feed-client-jar-with-dependencies.jar ai.vespa.feed.client.CliClient "$@" \ No newline at end of file
diff --git a/vespa-feed-client/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java b/vespa-feed-client/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java
deleted file mode 100644
index be479d294d5..00000000000
--- a/vespa-feed-client/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package ai.vespa.feed.client;// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-import org.junit.jupiter.api.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * @author bjorncs
- */
-class CliArgumentsTest {
-
- @Test
- void parses_parameters_correctly() throws CliArguments.CliArgumentsException {
- CliArguments args = CliArguments.fromRawArgs(new String[]{
- "--endpoint=https://vespa.ai:4443/", "--file=feed.json", "--connections=10",
- "--max-streams-per-connection=128", "--certificate=cert.pem", "--private-key=key.pem",
- "--ca-certificates=ca-certs.pem", "--disable-ssl-hostname-verification",
- "--header=\"My-Header: my-value\"", "--header", "Another-Header: another-value"});
- assertEquals(URI.create("https://vespa.ai:4443/"), args.endpoint());
- assertEquals(Paths.get("feed.json"), args.inputFile());
- assertEquals(10, args.connections().getAsInt());
- assertEquals(128, args.maxStreamsPerConnection().getAsInt());
- assertEquals(Paths.get("cert.pem"), args.certificateAndKey().get().certificateFile);
- assertEquals(Paths.get("key.pem"), args.certificateAndKey().get().privateKeyFile);
- assertEquals(Paths.get("ca-certs.pem"), args.caCertificates().get());
- assertTrue(args.sslHostnameVerificationDisabled());
- assertFalse(args.helpSpecified());
- assertFalse(args.versionSpecified());
- assertEquals(2, args.headers().size());
- assertEquals("my-value", args.headers().get("My-Header"));
- assertEquals("another-value", args.headers().get("Another-Header"));
- }
-
- @Test
- void fails_on_missing_parameters() throws CliArguments.CliArgumentsException {
- CliArguments cliArguments = CliArguments.fromRawArgs(new String[0]);
- CliArguments.CliArgumentsException exception = assertThrows(CliArguments.CliArgumentsException.class, cliArguments::endpoint);
- assertEquals("Endpoint must be specified", exception.getMessage());
- exception = assertThrows(CliArguments.CliArgumentsException.class, cliArguments::inputFile);
- assertEquals("Feed file must be specified", exception.getMessage());
- }
-
- @Test
- void generated_help_page_contains_expected_description() throws CliArguments.CliArgumentsException, IOException {
- CliArguments args = CliArguments.fromRawArgs(new String[]{"--help"});
- assertTrue(args.helpSpecified());
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- args.printHelp(out);
- String text = out.toString();
- String expectedHelp = new String(Files.readAllBytes(Paths.get("src", "test", "resources", "help.txt")));
- assertEquals(expectedHelp, text);
- }
-
-} \ No newline at end of file
diff --git a/vespa-feed-client/src/test/resources/help.txt b/vespa-feed-client/src/test/resources/help.txt
deleted file mode 100644
index 8ad153bc0e0..00000000000
--- a/vespa-feed-client/src/test/resources/help.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-usage: vespa-feed-client <options>
-Vespa feed client
- --ca-certificates <arg>
- --certificate <arg>
- --connections <arg>
- --disable-ssl-hostname-verification
- --endpoint <arg>
- --file <arg>
- --header <arg>
- --help
- --max-streams-per-connection <arg>
- --private-key <arg>
- --version