Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Added
- Add support for forward translog reading ([#20163](https://github.com/opensearch-project/OpenSearch/pull/20163))
- Added public getter method in `SourceFieldMapper` to return excluded field ([#20205](https://github.com/opensearch-project/OpenSearch/pull/20205))
- Add test-framework for gRPC transport module ([#20383](https://github.com/opensearch-project/OpenSearch/pull/20383))
- Add integ test for simulating node join left event when data node cluster state publication lag because the cluster applier thread being busy ([#19907](https://github.com/opensearch-project/OpenSearch/pull/19907)).
- Relax jar hell check when extended plugins share transitive dependencies ([#20103](https://github.com/opensearch-project/OpenSearch/pull/20103))
- Added public getter method in `SourceFieldMapper` to return included field ([#20290](https://github.com/opensearch-project/OpenSearch/pull/20290))
Expand Down
20 changes: 17 additions & 3 deletions modules/transport-grpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,32 @@ curl -X GET "localhost:9200/_nodes/stats/thread_pool?filter_path=nodes.*.thread_

## Testing

### Unit Tests
### Module Tests

```bash
./gradlew :modules:transport-grpc:test
```

### Integration Tests

```bash
./gradlew :modules:transport-grpc:internalClusterTest
```

### Test Framework Tests

```bash
./gradlew modules:transport-grpc:test-framework:test
```

```bash
./gradlew modules:transport-grpc:test-framework:internalClusterTest
```

### SPI Tests

```bash
./gradlew :modules:transport-grpc:spi:test
```

### Running OpenSearch with gRPC Enabled

To run OpenSearch with the gRPC transport enabled:
Expand Down
13 changes: 13 additions & 0 deletions modules/transport-grpc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ testClusters {
}
}

configurations {
testArtifacts.extendsFrom testImplementation
}

task testJar(type: Jar) {
archiveClassifier = 'test'
from sourceSets.test.output
}

artifacts {
testArtifacts testJar
}

dependencies {
api project('spi')
compileOnly "com.google.code.findbugs:jsr305:3.0.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

import static org.opensearch.transport.grpc.ssl.SecureSettingsHelpers.CLIENT_KEYSTORE;
import static org.opensearch.transport.grpc.ssl.SecureSettingsHelpers.getTestKeyManagerFactory;
import static io.grpc.internal.GrpcUtil.NOOP_PROXY_DETECTOR;

public class NettyGrpcClient implements AutoCloseable {
private static final Logger logger = LogManager.getLogger(NettyGrpcClient.class);
Expand Down Expand Up @@ -133,8 +132,7 @@ public static class Builder {
public Builder() {}

public NettyGrpcClient build() throws SSLException {
NettyChannelBuilder channelBuilder = NettyChannelBuilder.forAddress(addr.getAddress(), addr.getPort())
.proxyDetector(NOOP_PROXY_DETECTOR);
NettyChannelBuilder channelBuilder = NettyChannelBuilder.forAddress(addr.getAddress(), addr.getPort()).proxyDetector(null);

if (clientAuth || insecure) {
SslContextBuilder builder = SslContextBuilder.forClient();
Expand Down
28 changes: 28 additions & 0 deletions modules/transport-grpc/test-framework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# OpenSearch gRPC Transport Test Framework

The gRPC module test framework provides high-level abstractions for implementing integration tests for plugins which extend and utilize the gRPC transport. It solves the problem of breaking changes in protobuf schemas by providing stable APIs that abstract the underlying protobuf implementation details. When protobuf schemas change in the core gRPC transport module (e.g., protobuf field `SearchRequestBody` is renamed to `SearchRequest`), plugin tests that directly reference these protobuf classes break. This creates maintenance overhead and coupling between plugin tests and core implementation details.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would only be used by plugins that don't need to construct any protobuf requests at all right? Would security plugin be the only use case for this?

With the exception of OS major version releases (e.g. 4.x), we don't plan to make breaking changes to protos nowadays (as we've completed the proto automation to be able to make protos backward compatible), so would this PR still be needed long term?


## Usage

Include in plugin integration tests by adding the following dependency to build.gradle.
```gradle
dependencies {
testImplementation project(':modules:transport-grpc:test-framework')
}
```

Example usage of `OpenSearchIntegTestCase` and helper functions.
```java
public class MyPluginTest extends OpenSearchIntegTestCase {

public void testMyPluginFeature() {
ManagedChannel plainTextGrpcChannel = NettyChannelBuilder.forAddress("localhost", 9200).
proxyDetector(NOOP_PROXY_DETECTOR).
usePlaintext()
.build();

// Bulk ingest test documents with gRPC
doBulk(plainTextGrpcChannel, "test-index", 3);
}
}
```
151 changes: 151 additions & 0 deletions modules/transport-grpc/test-framework/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

apply plugin: 'opensearch.build'
apply plugin: 'opensearch.internal-cluster-test'

description = 'gRPC Transport Test Framework for Plugin Unit and Integration Tests'

dependencies {
api project(':test:framework')
api project(':modules:transport-grpc')
api project(path: ':modules:transport-grpc', configuration: 'testArtifacts')

api "org.opensearch:protobufs:${versions.opensearchprotobufs}"
api "io.grpc:grpc-protobuf:${versions.grpc}"
api "io.grpc:grpc-api:${versions.grpc}"
api "io.grpc:grpc-core:${versions.grpc}"
api "io.grpc:grpc-netty-shaded:${versions.grpc}"
api "io.grpc:grpc-protobuf-lite:${versions.grpc}"
api "io.grpc:grpc-services:${versions.grpc}"
api "io.grpc:grpc-stub:${versions.grpc}"
api "io.grpc:grpc-util:${versions.grpc}"

api "junit:junit:${versions.junit}"

compileOnly "com.google.code.findbugs:jsr305:3.0.2"
runtimeOnly "com.google.guava:guava:${versions.guava}"
implementation "com.google.guava:failureaccess:1.0.2"
implementation "io.perfmark:perfmark-api:0.27.0"

testImplementation project(':test:framework')
internalClusterTestImplementation project(':modules:transport-grpc')
}

// Enable javadoc checks for precommit since this module has full coverage
precommit.dependsOn missingJavadoc

tasks.named("dependencyLicenses").configure {
mapping from: /grpc-.*/, to: 'grpc'
}

thirdPartyAudit {
ignoreMissingClasses(
'com.aayushatharva.brotli4j.Brotli4jLoader',
'com.aayushatharva.brotli4j.decoder.DecoderJNI$Status',
'com.aayushatharva.brotli4j.decoder.DecoderJNI$Wrapper',
'com.aayushatharva.brotli4j.encoder.BrotliEncoderChannel',
'com.aayushatharva.brotli4j.encoder.Encoder$Mode',
'com.aayushatharva.brotli4j.encoder.Encoder$Parameters',
'com.google.gson.stream.JsonReader',
'com.google.gson.stream.JsonToken',
'com.google.protobuf.nano.CodedOutputByteBufferNano',
'com.google.protobuf.nano.MessageNano',
'com.google.protobuf.util.Durations',
'com.google.protobuf.util.Timestamps',
'com.google.rpc.Status',
'com.google.rpc.Status$Builder',
'com.ning.compress.BufferRecycler',
'com.ning.compress.lzf.ChunkDecoder',
'com.ning.compress.lzf.ChunkEncoder',
'com.ning.compress.lzf.LZFChunk',
'com.ning.compress.lzf.LZFEncoder',
'com.ning.compress.lzf.util.ChunkDecoderFactory',
'com.ning.compress.lzf.util.ChunkEncoderFactory',
'lzma.sdk.lzma.Encoder',
'net.jpountz.lz4.LZ4Compressor',
'net.jpountz.lz4.LZ4Factory',
'net.jpountz.lz4.LZ4FastDecompressor',
'net.jpountz.xxhash.XXHash32',
'net.jpountz.xxhash.XXHashFactory',
'org.apache.log4j.Level',
'org.apache.log4j.Logger',
'org.bouncycastle.cert.X509v3CertificateBuilder',
'org.bouncycastle.cert.jcajce.JcaX509CertificateConverter',
'org.bouncycastle.openssl.PEMEncryptedKeyPair',
'org.bouncycastle.openssl.PEMParser',
'org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter',
'org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder',
'org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder',
'org.bouncycastle.operator.jcajce.JcaContentSignerBuilder',
'org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo',
'org.conscrypt.AllocatedBuffer',
'org.conscrypt.BufferAllocator',
'org.conscrypt.Conscrypt',
'org.conscrypt.HandshakeListener',
'org.eclipse.jetty.alpn.ALPN',
'org.eclipse.jetty.alpn.ALPN$ClientProvider',
'org.eclipse.jetty.alpn.ALPN$ServerProvider',
'org.eclipse.jetty.npn.NextProtoNego',
'org.eclipse.jetty.npn.NextProtoNego$ClientProvider',
'org.eclipse.jetty.npn.NextProtoNego$ServerProvider',
'org.jboss.marshalling.ByteInput',
'org.jboss.marshalling.ByteOutput',
'org.jboss.marshalling.Marshaller',
'org.jboss.marshalling.MarshallerFactory',
'org.jboss.marshalling.MarshallingConfiguration',
'org.jboss.marshalling.Unmarshaller',
'reactor.blockhound.BlockHound$Builder',
'reactor.blockhound.integration.BlockHoundIntegration'
)

ignoreViolations(
'com.google.common.cache.Striped64',
'com.google.common.cache.Striped64$1',
'com.google.common.cache.Striped64$Cell',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray$1',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray$2',
'com.google.common.hash.Striped64',
'com.google.common.hash.Striped64$1',
'com.google.common.hash.Striped64$Cell',
'com.google.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator',
'com.google.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator$1',
'com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper',
'com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper$1',
'io.grpc.netty.shaded.io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator',
'io.grpc.netty.shaded.io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator$1',
'io.grpc.netty.shaded.io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator$2',
'io.grpc.netty.shaded.io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator$3',
'io.grpc.netty.shaded.io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator$4',
'io.grpc.netty.shaded.io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator$5',
'io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0',
'io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$1',
'io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$2',
'io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$3',
'io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$4',
'io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$6',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseLinkedQueueConsumerNodeRef',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseLinkedQueueProducerNodeRef',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.LinkedQueueNode',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpmcArrayQueueConsumerIndexField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpmcArrayQueueProducerIndexField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.unpadded.MpscUnpaddedArrayQueueConsumerIndexField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.unpadded.MpscUnpaddedArrayQueueProducerIndexField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.unpadded.MpscUnpaddedArrayQueueProducerLimitField',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.util.UnsafeLongArrayAccess',
'io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess'
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c4a06a64e650562f30b7bf9aaec1bfed43aca12b
Loading
Loading