diff options
author | Jon Marius Venstad <jonmv@users.noreply.github.com> | 2021-05-25 18:56:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-25 18:56:36 +0200 |
commit | b419ca923a7a3dd05087d2d28c7481cf144024a5 (patch) | |
tree | e8c54d18f522a017b066de57cfb07db6fb9fb79d | |
parent | 8e3d515ff5c5c58ce6e7ae16ac386f9e4655494c (diff) | |
parent | 6115afc38ac577eea18c63d33ebc9d5b0193dcb3 (diff) |
Merge pull request #17971 from vespa-engine/bjorncs/vespa-feed-client-cli
Bjorncs/vespa feed client cli
15 files changed, 147 insertions, 46 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1045f6270c8..7bf698b7a98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,7 @@ add_subdirectory(vdslib) add_subdirectory(vdstestlib) add_subdirectory(vespa-athenz) add_subdirectory(vespa-feed-client) +add_subdirectory(vespa-feed-client-cli) add_subdirectory(vespa-http-client) add_subdirectory(vespa-osgi-testrunner) add_subdirectory(vespa-testrunner-components) diff --git a/dist/vespa.spec b/dist/vespa.spec index 3a3c46dba8c..de92077fdbd 100644 --- a/dist/vespa.spec +++ b/dist/vespa.spec @@ -728,7 +728,7 @@ fi %dir %{_prefix}/lib/jars %{_prefix}/bin/vespa-feed-client %{_prefix}/lib/jars/vespa-http-client-jar-with-dependencies.jar -%{_prefix}/lib/jars/vespa-feed-client-jar-with-dependencies.jar +%{_prefix}/lib/jars/vespa-feed-client-cli.jar %files config-model-fat %if %{_defattr_is_vespa_vespa} @@ -133,6 +133,7 @@ <module>vespa-athenz</module> <module>vespa-documentgen-plugin</module> <module>vespa-feed-client</module> + <module>vespa-feed-client-cli</module> <module>vespa-hadoop</module> <module>vespa-http-client</module> <module>vespa-maven-plugin</module> diff --git a/vespa-feed-client-cli/CMakeLists.txt b/vespa-feed-client-cli/CMakeLists.txt new file mode 100644 index 00000000000..a918981dcd3 --- /dev/null +++ b/vespa-feed-client-cli/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +install_java_artifact(vespa-feed-client-cli) + +vespa_install_script(src/main/sh/vespa-feed-client.sh vespa-feed-client bin) diff --git a/vespa-feed-client-cli/OWNERS b/vespa-feed-client-cli/OWNERS new file mode 100644 index 00000000000..606d074d8a8 --- /dev/null +++ b/vespa-feed-client-cli/OWNERS @@ -0,0 +1,2 @@ +bjorncs +jonmv diff --git a/vespa-feed-client-cli/pom.xml b/vespa-feed-client-cli/pom.xml new file mode 100644 index 00000000000..62ff5c149ec --- /dev/null +++ b/vespa-feed-client-cli/pom.xml @@ -0,0 +1,87 @@ +<?xml version="1.0"?> +<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.yahoo.vespa</groupId> + <artifactId>parent</artifactId> + <version>7-SNAPSHOT</version> + <relativePath>../parent/pom.xml</relativePath> + </parent> + <artifactId>vespa-feed-client-cli</artifactId> + <packaging>jar</packaging> + <version>7-SNAPSHOT</version> + + <properties> + <maven.javadoc.skip>true</maven.javadoc.skip> + <!-- Used by internal properties that are still using JDK8--> + <maven.compiler.release>8</maven.compiler.release> + </properties> + + <dependencies> + <!-- compile scope --> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>vespa-feed-client</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>commons-cli</groupId> + <artifactId>commons-cli</artifactId> + <scope>compile</scope> + </dependency> + + <!-- test scope --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <jdkToolchain> + <version>${java.version}</version> + </jdkToolchain> + <source>${java.version}</source> + <target>${java.version}</target> + <showDeprecation>true</showDeprecation> + <compilerArgs> + <arg>-Xlint:all</arg> + <arg>-Xlint:-serial</arg> + <arg>-Werror</arg> + </compilerArgs> + </configuration> + </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> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</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-cli/src/main/java/ai/vespa/feed/client/CliArguments.java index 06c994b12b6..06c994b12b6 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliArguments.java +++ b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliArguments.java diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliClient.java b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java index 84a29f9c3e4..060f406f38f 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/CliClient.java +++ b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java @@ -13,13 +13,13 @@ import java.util.Properties; * * @author bjorncs */ -class CliClient { +public class CliClient { private final PrintStream systemOut; private final PrintStream systemError; private final Properties systemProperties; - CliClient(PrintStream systemOut, PrintStream systemError, Properties systemProperties) { + private CliClient(PrintStream systemOut, PrintStream systemError, Properties systemProperties) { this.systemOut = systemOut; this.systemError = systemError; this.systemProperties = systemProperties; @@ -31,7 +31,7 @@ class CliClient { System.exit(exitCode); } - int run(String[] rawArgs) { + private int run(String[] rawArgs) { try { CliArguments cliArgs = CliArguments.fromRawArgs(rawArgs); if (cliArgs.helpSpecified()) { diff --git a/vespa-feed-client/src/main/sh/vespa-feed-client.sh b/vespa-feed-client-cli/src/main/sh/vespa-feed-client.sh index 2e8d22a4245..2a166dd40bb 100755 --- a/vespa-feed-client/src/main/sh/vespa-feed-client.sh +++ b/vespa-feed-client-cli/src/main/sh/vespa-feed-client.sh @@ -79,4 +79,4 @@ 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 +-cp ${VESPA_HOME}/lib/jars/vespa-feed-client-cli.jar ai.vespa.feed.client.CliClient "$@" diff --git a/vespa-feed-client/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java b/vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java index be479d294d5..be479d294d5 100644 --- a/vespa-feed-client/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java +++ b/vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java diff --git a/vespa-feed-client/src/test/resources/help.txt b/vespa-feed-client-cli/src/test/resources/help.txt index 8ad153bc0e0..8ad153bc0e0 100644 --- a/vespa-feed-client/src/test/resources/help.txt +++ b/vespa-feed-client-cli/src/test/resources/help.txt 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/FeedClientBuilder.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClientBuilder.java index 95a49abcc25..3cd3f3cb4ca 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClientBuilder.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClientBuilder.java @@ -3,7 +3,10 @@ package ai.vespa.feed.client; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URI; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; @@ -27,6 +30,9 @@ public class FeedClientBuilder { int maxConnections = 4; int maxStreamsPerConnection = 1024; FeedClient.RetryStrategy retryStrategy = defaultRetryStrategy; + Path certificate; + Path privateKey; + Path caCertificates; public static FeedClientBuilder create(URI endpoint) { return new FeedClientBuilder(endpoint); } @@ -63,6 +69,9 @@ public class FeedClientBuilder { } public FeedClientBuilder setSslContext(SSLContext context) { + if (certificate != null || caCertificates != null || privateKey != null) { + throw new IllegalArgumentException("Cannot set both SSLContext and certificate / CA certificates"); + } this.sslContext = requireNonNull(context); return this; } @@ -86,8 +95,25 @@ public class FeedClientBuilder { return this; } + public FeedClientBuilder setCertificate(Path certificatePemFile, Path privateKeyPemFile) { + if (sslContext != null) throw new IllegalArgumentException("Cannot set both SSLContext and certificate"); + this.certificate = certificatePemFile; + this.privateKey = privateKeyPemFile; + return this; + } + + public FeedClientBuilder setCaCertificates(Path caCertificatesFile) { + if (sslContext != null) throw new IllegalArgumentException("Cannot set both SSLContext and CA certificate"); + this.caCertificates = caCertificatesFile; + return this; + } + public FeedClient build() { - return new HttpFeedClient(this); + try { + return new HttpFeedClient(this); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } } diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java index 64b99961e61..98edc32a107 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java @@ -19,6 +19,7 @@ import org.apache.hc.core5.reactor.IOReactorConfig; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; +import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; @@ -48,7 +49,7 @@ class HttpFeedClient implements FeedClient { private final CloseableHttpAsyncClient httpClient; private final AtomicBoolean closed = new AtomicBoolean(); - HttpFeedClient(FeedClientBuilder builder) { + HttpFeedClient(FeedClientBuilder builder) throws IOException { this.endpoint = builder.endpoint; this.requestHeaders = new HashMap<>(builder.requestHeaders); @@ -57,7 +58,7 @@ class HttpFeedClient implements FeedClient { this.httpClient.start(); } - private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilder builder, HttpRequestStrategy retryStrategy) { + private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilder builder, HttpRequestStrategy retryStrategy) throws IOException { HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create() .setUserAgent(String.format("vespa-feed-client/%s", Vespa.VERSION)) .setDefaultHeaders(Collections.singletonList(new BasicHeader("Vespa-Client-Version", Vespa.VERSION))) @@ -86,18 +87,28 @@ class HttpFeedClient implements FeedClient { .setMaxConnTotal(builder.maxConnections) .setMaxConnPerRoute(builder.maxConnections) .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.LAX); - if (builder.sslContext != null) { - ClientTlsStrategyBuilder tlsStrategyBuilder = ClientTlsStrategyBuilder.create() - .setSslContext(builder.sslContext); - if (builder.hostnameVerifier != null) { - tlsStrategyBuilder.setHostnameVerifier(builder.hostnameVerifier); - } - connectionManagerBuilder.setTlsStrategy(tlsStrategyBuilder.build()); + ClientTlsStrategyBuilder tlsStrategyBuilder = ClientTlsStrategyBuilder.create() + .setSslContext(constructSslContext(builder)); + if (builder.hostnameVerifier != null) { + tlsStrategyBuilder.setHostnameVerifier(builder.hostnameVerifier); } + connectionManagerBuilder.setTlsStrategy(tlsStrategyBuilder.build()); httpClientBuilder.setConnectionManager(connectionManagerBuilder.build()); return httpClientBuilder.build(); } + private static SSLContext constructSslContext(FeedClientBuilder builder) throws IOException { + if (builder.sslContext != null) return builder.sslContext; + SslContextBuilder sslContextBuilder = new SslContextBuilder(); + if (builder.certificate != null && builder.privateKey != null) { + sslContextBuilder.withCertificateAndKey(builder.certificate, builder.privateKey); + } + if (builder.caCertificates != null) { + sslContextBuilder.withCaCertificates(builder.caCertificates); + } + return sslContextBuilder.build(); + } + @Override public CompletableFuture<Result> put(DocumentId documentId, String documentJson, OperationParameters params) { return send("POST", documentId, requireNonNull(documentJson), params); |