mirror of https://github.com/grpc/grpc-java.git
istio-interop-testing: create a separate project and add istio echo server code (#9321)
* istio-interop-testing: create a separate project and add istio echo server code after removing from the grpc-interop-testing project * add jib support * use imported echo.proto from istio repo * use context to propagate values from interceptor so the service's echo method has all values required to compose EchoResponse
This commit is contained in:
parent
377e3ce557
commit
6271bab20d
|
|
@ -4,6 +4,7 @@ plugins {
|
|||
id "com.google.osdetector" apply false
|
||||
id "me.champeau.gradle.japicmp" apply false
|
||||
id "net.ltgt.errorprone" apply false
|
||||
id 'com.google.cloud.tools.jib' apply false
|
||||
}
|
||||
|
||||
import net.ltgt.gradle.errorprone.CheckSeverity
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
plugins {
|
||||
id "application"
|
||||
id "java"
|
||||
|
||||
id "com.google.protobuf"
|
||||
id 'com.google.cloud.tools.jib'
|
||||
}
|
||||
|
||||
description = "gRPC: Istio Interop testing"
|
||||
|
||||
configurations {
|
||||
alpnagent
|
||||
}
|
||||
|
||||
evaluationDependsOn(project(':grpc-context').path)
|
||||
|
||||
dependencies {
|
||||
implementation project(':grpc-core'),
|
||||
project(':grpc-netty'),
|
||||
project(':grpc-protobuf'),
|
||||
project(':grpc-services'),
|
||||
project(':grpc-stub'),
|
||||
project(':grpc-testing')
|
||||
|
||||
compileOnly libraries.javax.annotation
|
||||
|
||||
runtimeOnly libraries.netty.tcnative,
|
||||
libraries.netty.tcnative.classes
|
||||
testImplementation project(':grpc-context').sourceSets.test.output,
|
||||
project(':grpc-api').sourceSets.test.output,
|
||||
project(':grpc-core').sourceSets.test.output,
|
||||
libraries.mockito.core,
|
||||
libraries.junit,
|
||||
libraries.truth
|
||||
alpnagent libraries.jetty.alpn.agent
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
proto {
|
||||
srcDir 'third_party/istio/src/main/proto'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configureProtoCompilation()
|
||||
|
||||
import net.ltgt.gradle.errorprone.CheckSeverity
|
||||
|
||||
compileJava {
|
||||
// This isn't a library; it can use beta APIs
|
||||
options.errorprone.check("BetaApi", CheckSeverity.OFF)
|
||||
}
|
||||
|
||||
|
||||
// For releasing to Docker Hub
|
||||
jib {
|
||||
from.image = "gcr.io/distroless/java:8"
|
||||
container {
|
||||
ports = ['50051']
|
||||
mainClass="io.grpc.testing.istio.EchoTestServer"
|
||||
}
|
||||
outputPaths {
|
||||
tar = 'build/istio-echo-server.tar'
|
||||
digest = 'build/istio-echo-server.digest'
|
||||
imageId = 'build/istio-echo-server.id'
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,350 @@
|
|||
package io.istio.test;
|
||||
|
||||
import static io.grpc.MethodDescriptor.generateFullMethodName;
|
||||
|
||||
/**
|
||||
*/
|
||||
@javax.annotation.Generated(
|
||||
value = "by gRPC proto compiler",
|
||||
comments = "Source: test/echo/proto/echo.proto")
|
||||
@io.grpc.stub.annotations.GrpcGenerated
|
||||
public final class EchoTestServiceGrpc {
|
||||
|
||||
private EchoTestServiceGrpc() {}
|
||||
|
||||
public static final String SERVICE_NAME = "proto.EchoTestService";
|
||||
|
||||
// Static method descriptors that strictly reflect the proto.
|
||||
private static volatile io.grpc.MethodDescriptor<io.istio.test.Echo.EchoRequest,
|
||||
io.istio.test.Echo.EchoResponse> getEchoMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "Echo",
|
||||
requestType = io.istio.test.Echo.EchoRequest.class,
|
||||
responseType = io.istio.test.Echo.EchoResponse.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
public static io.grpc.MethodDescriptor<io.istio.test.Echo.EchoRequest,
|
||||
io.istio.test.Echo.EchoResponse> getEchoMethod() {
|
||||
io.grpc.MethodDescriptor<io.istio.test.Echo.EchoRequest, io.istio.test.Echo.EchoResponse> getEchoMethod;
|
||||
if ((getEchoMethod = EchoTestServiceGrpc.getEchoMethod) == null) {
|
||||
synchronized (EchoTestServiceGrpc.class) {
|
||||
if ((getEchoMethod = EchoTestServiceGrpc.getEchoMethod) == null) {
|
||||
EchoTestServiceGrpc.getEchoMethod = getEchoMethod =
|
||||
io.grpc.MethodDescriptor.<io.istio.test.Echo.EchoRequest, io.istio.test.Echo.EchoResponse>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "Echo"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||
io.istio.test.Echo.EchoRequest.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||
io.istio.test.Echo.EchoResponse.getDefaultInstance()))
|
||||
.setSchemaDescriptor(new EchoTestServiceMethodDescriptorSupplier("Echo"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getEchoMethod;
|
||||
}
|
||||
|
||||
private static volatile io.grpc.MethodDescriptor<io.istio.test.Echo.ForwardEchoRequest,
|
||||
io.istio.test.Echo.ForwardEchoResponse> getForwardEchoMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "ForwardEcho",
|
||||
requestType = io.istio.test.Echo.ForwardEchoRequest.class,
|
||||
responseType = io.istio.test.Echo.ForwardEchoResponse.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
public static io.grpc.MethodDescriptor<io.istio.test.Echo.ForwardEchoRequest,
|
||||
io.istio.test.Echo.ForwardEchoResponse> getForwardEchoMethod() {
|
||||
io.grpc.MethodDescriptor<io.istio.test.Echo.ForwardEchoRequest, io.istio.test.Echo.ForwardEchoResponse> getForwardEchoMethod;
|
||||
if ((getForwardEchoMethod = EchoTestServiceGrpc.getForwardEchoMethod) == null) {
|
||||
synchronized (EchoTestServiceGrpc.class) {
|
||||
if ((getForwardEchoMethod = EchoTestServiceGrpc.getForwardEchoMethod) == null) {
|
||||
EchoTestServiceGrpc.getForwardEchoMethod = getForwardEchoMethod =
|
||||
io.grpc.MethodDescriptor.<io.istio.test.Echo.ForwardEchoRequest, io.istio.test.Echo.ForwardEchoResponse>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "ForwardEcho"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||
io.istio.test.Echo.ForwardEchoRequest.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||
io.istio.test.Echo.ForwardEchoResponse.getDefaultInstance()))
|
||||
.setSchemaDescriptor(new EchoTestServiceMethodDescriptorSupplier("ForwardEcho"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getForwardEchoMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new async stub that supports all call types for the service
|
||||
*/
|
||||
public static EchoTestServiceStub newStub(io.grpc.Channel channel) {
|
||||
io.grpc.stub.AbstractStub.StubFactory<EchoTestServiceStub> factory =
|
||||
new io.grpc.stub.AbstractStub.StubFactory<EchoTestServiceStub>() {
|
||||
@java.lang.Override
|
||||
public EchoTestServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
return new EchoTestServiceStub(channel, callOptions);
|
||||
}
|
||||
};
|
||||
return EchoTestServiceStub.newStub(factory, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new blocking-style stub that supports unary and streaming output calls on the service
|
||||
*/
|
||||
public static EchoTestServiceBlockingStub newBlockingStub(
|
||||
io.grpc.Channel channel) {
|
||||
io.grpc.stub.AbstractStub.StubFactory<EchoTestServiceBlockingStub> factory =
|
||||
new io.grpc.stub.AbstractStub.StubFactory<EchoTestServiceBlockingStub>() {
|
||||
@java.lang.Override
|
||||
public EchoTestServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
return new EchoTestServiceBlockingStub(channel, callOptions);
|
||||
}
|
||||
};
|
||||
return EchoTestServiceBlockingStub.newStub(factory, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ListenableFuture-style stub that supports unary calls on the service
|
||||
*/
|
||||
public static EchoTestServiceFutureStub newFutureStub(
|
||||
io.grpc.Channel channel) {
|
||||
io.grpc.stub.AbstractStub.StubFactory<EchoTestServiceFutureStub> factory =
|
||||
new io.grpc.stub.AbstractStub.StubFactory<EchoTestServiceFutureStub>() {
|
||||
@java.lang.Override
|
||||
public EchoTestServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
return new EchoTestServiceFutureStub(channel, callOptions);
|
||||
}
|
||||
};
|
||||
return EchoTestServiceFutureStub.newStub(factory, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static abstract class EchoTestServiceImplBase implements io.grpc.BindableService {
|
||||
|
||||
/**
|
||||
*/
|
||||
public void echo(io.istio.test.Echo.EchoRequest request,
|
||||
io.grpc.stub.StreamObserver<io.istio.test.Echo.EchoResponse> responseObserver) {
|
||||
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getEchoMethod(), responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void forwardEcho(io.istio.test.Echo.ForwardEchoRequest request,
|
||||
io.grpc.stub.StreamObserver<io.istio.test.Echo.ForwardEchoResponse> responseObserver) {
|
||||
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getForwardEchoMethod(), responseObserver);
|
||||
}
|
||||
|
||||
@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
|
||||
return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
|
||||
.addMethod(
|
||||
getEchoMethod(),
|
||||
io.grpc.stub.ServerCalls.asyncUnaryCall(
|
||||
new MethodHandlers<
|
||||
io.istio.test.Echo.EchoRequest,
|
||||
io.istio.test.Echo.EchoResponse>(
|
||||
this, METHODID_ECHO)))
|
||||
.addMethod(
|
||||
getForwardEchoMethod(),
|
||||
io.grpc.stub.ServerCalls.asyncUnaryCall(
|
||||
new MethodHandlers<
|
||||
io.istio.test.Echo.ForwardEchoRequest,
|
||||
io.istio.test.Echo.ForwardEchoResponse>(
|
||||
this, METHODID_FORWARD_ECHO)))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static final class EchoTestServiceStub extends io.grpc.stub.AbstractAsyncStub<EchoTestServiceStub> {
|
||||
private EchoTestServiceStub(
|
||||
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
super(channel, callOptions);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected EchoTestServiceStub build(
|
||||
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
return new EchoTestServiceStub(channel, callOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void echo(io.istio.test.Echo.EchoRequest request,
|
||||
io.grpc.stub.StreamObserver<io.istio.test.Echo.EchoResponse> responseObserver) {
|
||||
io.grpc.stub.ClientCalls.asyncUnaryCall(
|
||||
getChannel().newCall(getEchoMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void forwardEcho(io.istio.test.Echo.ForwardEchoRequest request,
|
||||
io.grpc.stub.StreamObserver<io.istio.test.Echo.ForwardEchoResponse> responseObserver) {
|
||||
io.grpc.stub.ClientCalls.asyncUnaryCall(
|
||||
getChannel().newCall(getForwardEchoMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static final class EchoTestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub<EchoTestServiceBlockingStub> {
|
||||
private EchoTestServiceBlockingStub(
|
||||
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
super(channel, callOptions);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected EchoTestServiceBlockingStub build(
|
||||
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
return new EchoTestServiceBlockingStub(channel, callOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public io.istio.test.Echo.EchoResponse echo(io.istio.test.Echo.EchoRequest request) {
|
||||
return io.grpc.stub.ClientCalls.blockingUnaryCall(
|
||||
getChannel(), getEchoMethod(), getCallOptions(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public io.istio.test.Echo.ForwardEchoResponse forwardEcho(io.istio.test.Echo.ForwardEchoRequest request) {
|
||||
return io.grpc.stub.ClientCalls.blockingUnaryCall(
|
||||
getChannel(), getForwardEchoMethod(), getCallOptions(), request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static final class EchoTestServiceFutureStub extends io.grpc.stub.AbstractFutureStub<EchoTestServiceFutureStub> {
|
||||
private EchoTestServiceFutureStub(
|
||||
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
super(channel, callOptions);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected EchoTestServiceFutureStub build(
|
||||
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||
return new EchoTestServiceFutureStub(channel, callOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public com.google.common.util.concurrent.ListenableFuture<io.istio.test.Echo.EchoResponse> echo(
|
||||
io.istio.test.Echo.EchoRequest request) {
|
||||
return io.grpc.stub.ClientCalls.futureUnaryCall(
|
||||
getChannel().newCall(getEchoMethod(), getCallOptions()), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public com.google.common.util.concurrent.ListenableFuture<io.istio.test.Echo.ForwardEchoResponse> forwardEcho(
|
||||
io.istio.test.Echo.ForwardEchoRequest request) {
|
||||
return io.grpc.stub.ClientCalls.futureUnaryCall(
|
||||
getChannel().newCall(getForwardEchoMethod(), getCallOptions()), request);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int METHODID_ECHO = 0;
|
||||
private static final int METHODID_FORWARD_ECHO = 1;
|
||||
|
||||
private static final class MethodHandlers<Req, Resp> implements
|
||||
io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
|
||||
io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
|
||||
io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
|
||||
io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
|
||||
private final EchoTestServiceImplBase serviceImpl;
|
||||
private final int methodId;
|
||||
|
||||
MethodHandlers(EchoTestServiceImplBase serviceImpl, int methodId) {
|
||||
this.serviceImpl = serviceImpl;
|
||||
this.methodId = methodId;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("unchecked")
|
||||
public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
|
||||
switch (methodId) {
|
||||
case METHODID_ECHO:
|
||||
serviceImpl.echo((io.istio.test.Echo.EchoRequest) request,
|
||||
(io.grpc.stub.StreamObserver<io.istio.test.Echo.EchoResponse>) responseObserver);
|
||||
break;
|
||||
case METHODID_FORWARD_ECHO:
|
||||
serviceImpl.forwardEcho((io.istio.test.Echo.ForwardEchoRequest) request,
|
||||
(io.grpc.stub.StreamObserver<io.istio.test.Echo.ForwardEchoResponse>) responseObserver);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("unchecked")
|
||||
public io.grpc.stub.StreamObserver<Req> invoke(
|
||||
io.grpc.stub.StreamObserver<Resp> responseObserver) {
|
||||
switch (methodId) {
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class EchoTestServiceBaseDescriptorSupplier
|
||||
implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
|
||||
EchoTestServiceBaseDescriptorSupplier() {}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
|
||||
return io.istio.test.Echo.getDescriptor();
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
|
||||
return getFileDescriptor().findServiceByName("EchoTestService");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class EchoTestServiceFileDescriptorSupplier
|
||||
extends EchoTestServiceBaseDescriptorSupplier {
|
||||
EchoTestServiceFileDescriptorSupplier() {}
|
||||
}
|
||||
|
||||
private static final class EchoTestServiceMethodDescriptorSupplier
|
||||
extends EchoTestServiceBaseDescriptorSupplier
|
||||
implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
|
||||
private final String methodName;
|
||||
|
||||
EchoTestServiceMethodDescriptorSupplier(String methodName) {
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
|
||||
return getServiceDescriptor().findMethodByName(methodName);
|
||||
}
|
||||
}
|
||||
|
||||
private static volatile io.grpc.ServiceDescriptor serviceDescriptor;
|
||||
|
||||
public static io.grpc.ServiceDescriptor getServiceDescriptor() {
|
||||
io.grpc.ServiceDescriptor result = serviceDescriptor;
|
||||
if (result == null) {
|
||||
synchronized (EchoTestServiceGrpc.class) {
|
||||
result = serviceDescriptor;
|
||||
if (result == null) {
|
||||
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
|
||||
.setSchemaDescriptor(new EchoTestServiceFileDescriptorSupplier())
|
||||
.addMethod(getEchoMethod())
|
||||
.addMethod(getForwardEchoMethod())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
/*
|
||||
* Copyright 2022 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.testing.istio;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.Contexts;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.InsecureChannelCredentials;
|
||||
import io.grpc.InsecureServerCredentials;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerCall;
|
||||
import io.grpc.ServerCallHandler;
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.ServerInterceptors;
|
||||
import io.grpc.ServerServiceDefinition;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import io.grpc.stub.MetadataUtils;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.istio.test.Echo.EchoRequest;
|
||||
import io.istio.test.Echo.EchoResponse;
|
||||
import io.istio.test.Echo.ForwardEchoRequest;
|
||||
import io.istio.test.Echo.ForwardEchoResponse;
|
||||
import io.istio.test.Echo.Header;
|
||||
import io.istio.test.EchoTestServiceGrpc;
|
||||
import io.istio.test.EchoTestServiceGrpc.EchoTestServiceBlockingStub;
|
||||
import io.istio.test.EchoTestServiceGrpc.EchoTestServiceImplBase;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class implements the Istio echo server functionality similar to
|
||||
* https://github.com/istio/istio/blob/master/pkg/test/echo/server/endpoint/grpc.go .
|
||||
* Please see Istio framework docs https://github.com/istio/istio/wiki/Istio-Test-Framework .
|
||||
*/
|
||||
public final class EchoTestServer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(EchoTestServer.class.getName());
|
||||
|
||||
static final Context.Key<String> CLIENT_ADDRESS_CONTEXT_KEY =
|
||||
Context.key("io.grpc.testing.istio.ClientAddress");
|
||||
static final Context.Key<String> AUTHORITY_CONTEXT_KEY =
|
||||
Context.key("io.grpc.testing.istio.Authority");
|
||||
static final Context.Key<Map<String,String>> REQUEST_HEADERS_CONTEXT_KEY =
|
||||
Context.key("io.grpc.testing.istio.RequestHeaders");
|
||||
|
||||
private static final String REQUEST_ID = "x-request-id";
|
||||
private static final String STATUS_CODE = "StatusCode";
|
||||
private static final String HOST = "Host";
|
||||
private static final String HOSTNAME = "Hostname";
|
||||
private static final String REQUEST_HEADER = "RequestHeader";
|
||||
private static final String IP = "IP";
|
||||
public static final String GRPC_SCHEME = "grpc://";
|
||||
|
||||
@VisibleForTesting List<Server> servers;
|
||||
|
||||
/**
|
||||
* Preprocess args, for two things:
|
||||
* 1. merge duplicate flags. So "--grpc=8080 --grpc=9090" becomes
|
||||
* "--grpc=8080,9090".
|
||||
* 2. replace '-' to '_'. So "--istio-version=123" becomes
|
||||
* "--istio_version=123" (so exclude the leading "--").
|
||||
**/
|
||||
@VisibleForTesting
|
||||
static Map<String, List<String>> preprocessArgs(String[] args) {
|
||||
HashMap<String, List<String>> argsMap = new HashMap<>();
|
||||
for (String arg : args) {
|
||||
String[] keyValue = arg.split("=", 2);
|
||||
|
||||
if (keyValue.length == 2) {
|
||||
String key = keyValue[0];
|
||||
String value = keyValue[1];
|
||||
|
||||
key = key.substring(0, 2) + key.substring(2).replace('-', '_');
|
||||
List<String> oldValue = argsMap.get(key);
|
||||
if (oldValue == null) {
|
||||
oldValue = new ArrayList<>();
|
||||
}
|
||||
oldValue.add(value);
|
||||
argsMap.put(key, oldValue);
|
||||
}
|
||||
}
|
||||
return ImmutableMap.<String, List<String>>builder().putAll(argsMap).build();
|
||||
}
|
||||
|
||||
/** Turn gRPC ports from a string list to an int list. */
|
||||
@VisibleForTesting
|
||||
static List<Integer> getGrpcPorts(Map<String, List<String>> args) {
|
||||
List<String> grpcPorts = args.get("--grpc");
|
||||
List<Integer> grpcPortsInt = new ArrayList<>(grpcPorts.size());
|
||||
|
||||
for (String port : grpcPorts) {
|
||||
grpcPortsInt.add(Integer.parseInt(port));
|
||||
}
|
||||
return grpcPortsInt;
|
||||
}
|
||||
|
||||
private static String determineHostname() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.INFO, "Failed to determine hostname. Will generate one", ex);
|
||||
}
|
||||
// let's make an identifier for ourselves.
|
||||
return "generated-" + new Random().nextInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main application allowing this program to be launched from the command line.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
Map<String, List<String>> processedArgs = preprocessArgs(args);
|
||||
List<Integer> grpcPorts = getGrpcPorts(processedArgs);
|
||||
|
||||
String hostname = determineHostname();
|
||||
EchoTestServer echoTestServer = new EchoTestServer();
|
||||
echoTestServer.runServers(grpcPorts, hostname);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
try {
|
||||
System.out.println("Shutting down");
|
||||
echoTestServer.stopServers();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "stopServers", e);
|
||||
throw e;
|
||||
}
|
||||
}));
|
||||
echoTestServer.blockUntilShutdown();
|
||||
}
|
||||
|
||||
void runServers(List<Integer> grpcPorts, String hostname) throws IOException {
|
||||
ServerServiceDefinition service = ServerInterceptors.intercept(
|
||||
new EchoTestServiceImpl(hostname), new EchoTestServerInterceptor());
|
||||
servers = new ArrayList<>(grpcPorts.size() + 1);
|
||||
for (int port : grpcPorts) {
|
||||
runServer(port, service);
|
||||
}
|
||||
}
|
||||
|
||||
void runServer(int port, ServerServiceDefinition service) throws IOException {
|
||||
logger.log(Level.INFO, "Listening GRPC on " + port);
|
||||
servers.add(Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
|
||||
.addService(service)
|
||||
.build().start());
|
||||
}
|
||||
|
||||
void stopServers() {
|
||||
for (Server server : servers) {
|
||||
server.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
void blockUntilShutdown() throws InterruptedException {
|
||||
for (Server server : servers) {
|
||||
if (!server.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
System.err.println("Timed out waiting for server shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class EchoTestServerInterceptor implements ServerInterceptor {
|
||||
|
||||
@Override
|
||||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call,
|
||||
final Metadata requestHeaders, ServerCallHandler<ReqT, RespT> next) {
|
||||
final String methodName = call.getMethodDescriptor().getBareMethodName();
|
||||
|
||||
// we need this processing only for Echo
|
||||
if (!"Echo".equals(methodName)) {
|
||||
return next.startCall(call, requestHeaders);
|
||||
}
|
||||
final SocketAddress peerAddress = call.getAttributes()
|
||||
.get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
|
||||
|
||||
Context ctx = Context.current();
|
||||
if (peerAddress instanceof InetSocketAddress) {
|
||||
InetSocketAddress inetPeerAddress = (InetSocketAddress) peerAddress;
|
||||
ctx = ctx.withValue(CLIENT_ADDRESS_CONTEXT_KEY,
|
||||
inetPeerAddress.getAddress().getHostAddress());
|
||||
}
|
||||
ctx = ctx.withValue(AUTHORITY_CONTEXT_KEY, call.getAuthority());
|
||||
Map<String, String> requestHeadersCopy = new HashMap<>();
|
||||
for (String key : requestHeaders.keys()) {
|
||||
if (!key.endsWith("-bin")) {
|
||||
requestHeadersCopy.put(key,
|
||||
requestHeaders.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER)));
|
||||
}
|
||||
}
|
||||
ctx = ctx.withValue(REQUEST_HEADERS_CONTEXT_KEY, requestHeadersCopy);
|
||||
return Contexts.interceptCall(
|
||||
ctx,
|
||||
call,
|
||||
requestHeaders,
|
||||
next);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EchoTestServiceImpl extends EchoTestServiceImplBase {
|
||||
|
||||
private final String hostname;
|
||||
|
||||
EchoTestServiceImpl(String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void echo(EchoRequest request,
|
||||
io.grpc.stub.StreamObserver<EchoResponse> responseObserver) {
|
||||
|
||||
EchoMessage echoMessage = new EchoMessage();
|
||||
echoMessage.writeKeyValue(HOSTNAME, hostname);
|
||||
echoMessage.writeKeyValue("Echo", request.getMessage());
|
||||
String clientAddress = CLIENT_ADDRESS_CONTEXT_KEY.get();
|
||||
if (clientAddress != null) {
|
||||
echoMessage.writeKeyValue(IP, clientAddress);
|
||||
}
|
||||
Map<String, String> requestHeadersCopy = REQUEST_HEADERS_CONTEXT_KEY.get();
|
||||
for (Map.Entry<String, String> entry : requestHeadersCopy.entrySet()) {
|
||||
echoMessage.writeKeyValueForRequest(REQUEST_HEADER, entry.getKey(), entry.getValue());
|
||||
}
|
||||
echoMessage.writeKeyValue(STATUS_CODE, "200");
|
||||
echoMessage.writeKeyValue(HOST, AUTHORITY_CONTEXT_KEY.get());
|
||||
EchoResponse echoResponse = EchoResponse.newBuilder()
|
||||
.setMessage(echoMessage.toString())
|
||||
.build();
|
||||
|
||||
responseObserver.onNext(echoResponse);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forwardEcho(ForwardEchoRequest request,
|
||||
StreamObserver<ForwardEchoResponse> responseObserver) {
|
||||
try {
|
||||
responseObserver.onNext(buildEchoResponse(request));
|
||||
responseObserver.onCompleted();
|
||||
} catch (InterruptedException e) {
|
||||
responseObserver.onError(e);
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
responseObserver.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private ForwardEchoResponse buildEchoResponse(ForwardEchoRequest request)
|
||||
throws InterruptedException {
|
||||
ForwardEchoResponse.Builder forwardEchoResponseBuilder
|
||||
= ForwardEchoResponse.newBuilder();
|
||||
String rawUrl = request.getUrl();
|
||||
if (!rawUrl.startsWith(GRPC_SCHEME)) {
|
||||
throw new StatusRuntimeException(
|
||||
Status.UNIMPLEMENTED.withDescription("protocol grpc:// required"));
|
||||
}
|
||||
rawUrl = rawUrl.substring(GRPC_SCHEME.length());
|
||||
|
||||
// May need to use xds security if urlScheme is "xds"
|
||||
ManagedChannelBuilder<?> channelBuilder = Grpc.newChannelBuilder(
|
||||
rawUrl, InsecureChannelCredentials.create());
|
||||
ManagedChannel channel = channelBuilder.build();
|
||||
|
||||
List<Header> requestHeaders = request.getHeadersList();
|
||||
Metadata metadata = new Metadata();
|
||||
|
||||
for (Header header : requestHeaders) {
|
||||
metadata.put(Metadata.Key.of(header.getKey(), Metadata.ASCII_STRING_MARSHALLER),
|
||||
header.getValue());
|
||||
}
|
||||
|
||||
int count = request.getCount() == 0 ? 1 : request.getCount();
|
||||
Duration durationPerQuery = Duration.ZERO;
|
||||
if (request.getQps() > 0) {
|
||||
durationPerQuery = Duration.ofNanos(
|
||||
Duration.ofSeconds(1).toNanos() / request.getQps());
|
||||
}
|
||||
logger.info("qps=" + request.getQps());
|
||||
logger.info("durationPerQuery=" + durationPerQuery);
|
||||
EchoRequest echoRequest = EchoRequest.newBuilder()
|
||||
.setMessage(request.getMessage())
|
||||
.build();
|
||||
Instant start = Instant.now();
|
||||
logger.info("starting instant=" + start);
|
||||
Duration expected = Duration.ZERO;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Metadata currentMetadata = new Metadata();
|
||||
currentMetadata.merge(metadata);
|
||||
currentMetadata.put(
|
||||
Metadata.Key.of(REQUEST_ID, Metadata.ASCII_STRING_MARSHALLER), "" + i);
|
||||
EchoTestServiceBlockingStub stub
|
||||
= EchoTestServiceGrpc.newBlockingStub(channel).withInterceptors(
|
||||
MetadataUtils.newAttachHeadersInterceptor(currentMetadata))
|
||||
.withDeadlineAfter(request.getTimeoutMicros(), TimeUnit.MICROSECONDS);
|
||||
String response = callEcho(stub, echoRequest, i);
|
||||
forwardEchoResponseBuilder.addOutput(response);
|
||||
Instant current = Instant.now();
|
||||
logger.info("after rpc instant=" + current);
|
||||
Duration elapsed = Duration.between(start, current);
|
||||
expected = expected.plus(durationPerQuery);
|
||||
Duration timeLeft = expected.minus(elapsed);
|
||||
logger.info("elapsed=" + elapsed + ", expected=" + expected + ", timeLeft=" + timeLeft);
|
||||
if (!timeLeft.isNegative()) {
|
||||
logger.info("sleeping for ms =" + timeLeft);
|
||||
Thread.sleep(timeLeft.toMillis());
|
||||
}
|
||||
}
|
||||
return forwardEchoResponseBuilder.build();
|
||||
}
|
||||
|
||||
private String callEcho(EchoTestServiceBlockingStub stub,
|
||||
EchoRequest echoRequest, int count) {
|
||||
try {
|
||||
EchoResponse echoResponse = stub.echo(echoRequest);
|
||||
return echoResponse.getMessage();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.INFO, "RPC failed " + count, e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static class EchoMessage {
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
|
||||
void writeKeyValue(String key, String value) {
|
||||
sb.append(key).append("=").append(value).append("\n");
|
||||
}
|
||||
|
||||
void writeKeyValueForRequest(String requestHeader, String key, String value) {
|
||||
if (value != null) {
|
||||
writeKeyValue(requestHeader, key + ":" + value);
|
||||
}
|
||||
}
|
||||
|
||||
void writeMessage(String message) {
|
||||
sb.append(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright 2022 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.testing.istio;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.InsecureChannelCredentials;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.stub.MetadataUtils;
|
||||
import io.istio.test.Echo.EchoRequest;
|
||||
import io.istio.test.Echo.EchoResponse;
|
||||
import io.istio.test.Echo.ForwardEchoRequest;
|
||||
import io.istio.test.Echo.ForwardEchoResponse;
|
||||
import io.istio.test.Echo.Header;
|
||||
import io.istio.test.EchoTestServiceGrpc;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EchoTestServer}.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class EchoTestServerTest {
|
||||
|
||||
@Test
|
||||
public void preprocessArgsTest() {
|
||||
String[] splitArgs = TEST_ARGS.split(" ");
|
||||
Map<String, List<String>> processedArgs = EchoTestServer.preprocessArgs(splitArgs);
|
||||
|
||||
assertEquals(processedArgs.keySet(), ImmutableSet.copyOf(EXPECTED_KEY_SET));
|
||||
assertEquals(processedArgs.get("--server_first"), ImmutableList.of("16060", "16061"));
|
||||
assertEquals(processedArgs.get("--bind_ip"), ImmutableList.of("18082"));
|
||||
assertEquals(processedArgs.get("--bind_localhost"), ImmutableList.of("18084"));
|
||||
assertEquals(processedArgs.get("--version"), ImmutableList.of("\"v1\""));
|
||||
assertEquals(processedArgs.get("--grpc"), ImmutableList.of("\"17070\"", "\"17071\""));
|
||||
assertEquals(processedArgs.get("--tls"), ImmutableList.of("18443", "19443"));
|
||||
assertEquals(processedArgs.get("--cluster"), ImmutableList.of("\"cluster-0\""));
|
||||
assertEquals(processedArgs.get("--key"), ImmutableList.of("/cert.key"));
|
||||
assertEquals(processedArgs.get("--tcp"), ImmutableList.of("\"19090\"", "\"16060\"",
|
||||
"\"19091\"","\"16061\"","\"19092\""));
|
||||
assertEquals(processedArgs.get("--istio_version"), ImmutableList.of("3"));
|
||||
assertEquals(processedArgs.get("--crt"), ImmutableList.of("/cert.crt"));
|
||||
assertEquals(processedArgs.get("--metrics"), ImmutableList.of("15014"));
|
||||
assertEquals(
|
||||
processedArgs.get("--port"),
|
||||
ImmutableList.of(
|
||||
"\"18080\"",
|
||||
"\"18085\"",
|
||||
"\"18443\"",
|
||||
"\"18081\"",
|
||||
"\"19443\"",
|
||||
"\"18082\"",
|
||||
"\"18084\"",
|
||||
"\"18083\"",
|
||||
"\"8080\"",
|
||||
"\"3333\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void echoTest() throws IOException, InterruptedException {
|
||||
EchoTestServer echoTestServer = new EchoTestServer();
|
||||
|
||||
echoTestServer.runServers(ImmutableList.of(0, 0), "test-host");
|
||||
assertEquals(2, echoTestServer.servers.size());
|
||||
int port = echoTestServer.servers.get(0).getPort();
|
||||
assertNotEquals(0, port);
|
||||
assertNotEquals(0, echoTestServer.servers.get(1).getPort());
|
||||
|
||||
ManagedChannelBuilder<?> channelBuilder =
|
||||
Grpc.newChannelBuilderForAddress("localhost", port, InsecureChannelCredentials.create());
|
||||
ManagedChannel channel = channelBuilder.build();
|
||||
|
||||
Metadata metadata = new Metadata();
|
||||
metadata.put(Metadata.Key.of("header1", Metadata.ASCII_STRING_MARSHALLER), "value1");
|
||||
metadata.put(Metadata.Key.of("header2", Metadata.ASCII_STRING_MARSHALLER), "value2");
|
||||
|
||||
EchoTestServiceGrpc.EchoTestServiceBlockingStub stub =
|
||||
EchoTestServiceGrpc.newBlockingStub(channel)
|
||||
.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata));
|
||||
|
||||
EchoRequest echoRequest = EchoRequest.newBuilder()
|
||||
.setMessage("test-message1")
|
||||
.build();
|
||||
EchoResponse echoResponse = stub.echo(echoRequest);
|
||||
String echoMessage = echoResponse.getMessage();
|
||||
Set<String> lines = ImmutableSet.copyOf(echoMessage.split("\n"));
|
||||
|
||||
assertThat(lines).contains("RequestHeader=header1:value1");
|
||||
assertThat(lines).contains("RequestHeader=header2:value2");
|
||||
assertThat(lines).contains("Echo=test-message1");
|
||||
assertThat(lines).contains("Hostname=test-host");
|
||||
assertThat(lines).contains("Host=localhost:" + port);
|
||||
assertThat(lines).contains("StatusCode=200");
|
||||
|
||||
echoTestServer.stopServers();
|
||||
echoTestServer.blockUntilShutdown();
|
||||
}
|
||||
|
||||
static final int COUNT_OF_REQUESTS_TO_FORWARD = 60;
|
||||
|
||||
@Test
|
||||
public void forwardEchoTest() throws IOException {
|
||||
EchoTestServer echoTestServer = new EchoTestServer();
|
||||
|
||||
echoTestServer.runServers(ImmutableList.of(0, 0), "test-host");
|
||||
assertEquals(2, echoTestServer.servers.size());
|
||||
int port1 = echoTestServer.servers.get(0).getPort();
|
||||
int port2 = echoTestServer.servers.get(1).getPort();
|
||||
|
||||
ManagedChannelBuilder<?> channelBuilder =
|
||||
Grpc.newChannelBuilderForAddress("localhost", port1, InsecureChannelCredentials.create());
|
||||
ManagedChannel channel = channelBuilder.build();
|
||||
|
||||
ForwardEchoRequest forwardEchoRequest =
|
||||
ForwardEchoRequest.newBuilder()
|
||||
.setCount(COUNT_OF_REQUESTS_TO_FORWARD)
|
||||
.setQps(100)
|
||||
.setTimeoutMicros(2000_000L) // 2000 millis
|
||||
.setUrl("grpc://localhost:" + port2)
|
||||
.addHeaders(
|
||||
Header.newBuilder().setKey("test-key1").setValue("test-value1").build())
|
||||
.addHeaders(
|
||||
Header.newBuilder().setKey("test-key2").setValue("test-value2").build())
|
||||
.setMessage("forward-echo-test-message")
|
||||
.build();
|
||||
|
||||
EchoTestServiceGrpc.EchoTestServiceBlockingStub stub =
|
||||
EchoTestServiceGrpc.newBlockingStub(channel);
|
||||
|
||||
Instant start = Instant.now();
|
||||
ForwardEchoResponse forwardEchoResponse = stub.forwardEcho(forwardEchoRequest);
|
||||
Instant end = Instant.now();
|
||||
List<String> outputs = forwardEchoResponse.getOutputList();
|
||||
assertEquals(COUNT_OF_REQUESTS_TO_FORWARD, outputs.size());
|
||||
for (int i = 0; i < COUNT_OF_REQUESTS_TO_FORWARD; i++) {
|
||||
validateOutput(outputs.get(i), i);
|
||||
}
|
||||
long duration = Duration.between(start, end).toMillis();
|
||||
assertThat(duration).isAtLeast(COUNT_OF_REQUESTS_TO_FORWARD * 10L);
|
||||
}
|
||||
|
||||
private static void validateOutput(String output, int i) {
|
||||
assertThat(output).contains("RequestHeader=x-request-id:" + i);
|
||||
assertThat(output).contains("RequestHeader=test-key1:test-value1");
|
||||
assertThat(output).contains("RequestHeader=test-key2:test-value2");
|
||||
assertThat(output).contains("Hostname=test-host");
|
||||
assertThat(output).contains("StatusCode=200");
|
||||
assertThat(output).contains("Echo=forward-echo-test-message");
|
||||
}
|
||||
|
||||
private static final String[] EXPECTED_KEY_SET = {
|
||||
"--server_first",
|
||||
"--bind_ip", "--istio_version", "--bind_localhost", "--version", "--grpc", "--tls",
|
||||
"--cluster", "--key", "--tcp", "--crt", "--metrics", "--port"
|
||||
};
|
||||
|
||||
private static final String TEST_ARGS =
|
||||
"--metrics=15014 --cluster=\"cluster-0\" --port=\"18080\" --grpc=\"17070\" --port=\"18085\""
|
||||
+ " --tcp=\"19090\" --port=\"18443\" --tls=18443 --tcp=\"16060\" --server_first=16060"
|
||||
+ " --tcp=\"19091\" --tcp=\"16061\" --server_first=16061 --port=\"18081\""
|
||||
+ " --grpc=\"17071\" --port=\"19443\" --tls=19443 --port=\"18082\" --bind_ip=18082"
|
||||
+ " --port=\"18084\" --bind_localhost=18084 --tcp=\"19092\" --port=\"18083\""
|
||||
+ " --port=\"8080\" --port=\"3333\" --version=\"v1\" --istio-version=3 --crt=/cert.crt"
|
||||
+ " --key=/cert.key";
|
||||
}
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2016-2020 Istio Authors
|
||||
|
||||
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.
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2018 The gRPC Authors
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Update VERSION then in this directory run ./import.sh
|
||||
|
||||
set -e
|
||||
BRANCH=master
|
||||
# import VERSION from the istio repository
|
||||
VERSION=cbee1999ad8b0f1ec790ec47f9ea33fed887f4a7
|
||||
GIT_REPO="https://github.com/istio/istio.git"
|
||||
GIT_BASE_DIR=istio
|
||||
SOURCE_PROTO_BASE_DIR=istio/pkg
|
||||
TARGET_PROTO_BASE_DIR=src/main/proto
|
||||
# Sorted alphabetically.
|
||||
FILES=(
|
||||
test/echo/proto/echo.proto
|
||||
)
|
||||
|
||||
pushd `git rev-parse --show-toplevel`/istio-interop-testing/third_party/istio
|
||||
|
||||
# clone the istio github repo in a tmp directory
|
||||
tmpdir="$(mktemp -d)"
|
||||
trap "rm -rf ${tmpdir}" EXIT
|
||||
|
||||
pushd "${tmpdir}"
|
||||
git clone -b $BRANCH $GIT_REPO
|
||||
trap "rm -rf $GIT_BASE_DIR" EXIT
|
||||
cd "$GIT_BASE_DIR"
|
||||
git checkout $VERSION
|
||||
popd
|
||||
|
||||
cp -p "${tmpdir}/${GIT_BASE_DIR}/LICENSE" LICENSE
|
||||
|
||||
rm -rf "${TARGET_PROTO_BASE_DIR}"
|
||||
mkdir -p "${TARGET_PROTO_BASE_DIR}"
|
||||
pushd "${TARGET_PROTO_BASE_DIR}"
|
||||
|
||||
# copy proto files to project directory
|
||||
for file in "${FILES[@]}"
|
||||
do
|
||||
mkdir -p "$(dirname "${file}")"
|
||||
cp -p "${tmpdir}/${SOURCE_PROTO_BASE_DIR}/${file}" "${file}"
|
||||
done
|
||||
popd
|
||||
|
||||
popd
|
||||
93
istio-interop-testing/third_party/istio/src/main/proto/test/echo/proto/echo.proto
vendored
Normal file
93
istio-interop-testing/third_party/istio/src/main/proto/test/echo/proto/echo.proto
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright Istio Authors
|
||||
//
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
// Generate with protoc --go_out=. echo.proto -I /work/common-protos/ -I.
|
||||
package proto;
|
||||
option go_package="../proto";
|
||||
option java_package = "io.istio.test";
|
||||
option java_outer_classname = "Echo";
|
||||
|
||||
service EchoTestService {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse);
|
||||
rpc ForwardEcho (ForwardEchoRequest) returns (ForwardEchoResponse);
|
||||
}
|
||||
|
||||
message EchoRequest {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message Header {
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message ForwardEchoRequest {
|
||||
int32 count = 1;
|
||||
int32 qps = 2;
|
||||
int64 timeout_micros = 3;
|
||||
string url = 4;
|
||||
repeated Header headers = 5;
|
||||
string message = 6;
|
||||
// Method for the request. Valid only for HTTP
|
||||
string method = 9;
|
||||
// If true, requests will be sent using h2c prior knowledge
|
||||
bool http2 = 7;
|
||||
// If true, requests will be sent using http3
|
||||
bool http3 = 15;
|
||||
// If true, requests will not be sent until magic string is received
|
||||
bool serverFirst = 8;
|
||||
// If true, 301 redirects will be followed
|
||||
bool followRedirects = 14;
|
||||
// If non-empty, make the request with the corresponding cert and key.
|
||||
string cert = 10;
|
||||
string key = 11;
|
||||
// If non-empty, verify the server CA
|
||||
string caCert = 12;
|
||||
// If non-empty, make the request with the corresponding cert and key file.
|
||||
string certFile = 16;
|
||||
string keyFile = 17;
|
||||
// If non-empty, verify the server CA with the ca cert file.
|
||||
string caCertFile = 18;
|
||||
// Skip verifying peer's certificate.
|
||||
bool insecureSkipVerify = 19;
|
||||
// List of ALPNs to present. If not set, this will be automatically be set based on the protocol
|
||||
Alpn alpn = 13;
|
||||
// Server name (SNI) to present in TLS connections. If not set, Host will be used for http requests.
|
||||
string serverName = 20;
|
||||
// Expected response determines what string to look for in the response to validate TCP requests succeeded.
|
||||
// If not set, defaults to "StatusCode=200"
|
||||
google.protobuf.StringValue expectedResponse = 21;
|
||||
// If set, a new connection will be made to the server for each individual request. If false, an attempt
|
||||
// will be made to re-use the connection for the life of the forward request. This is automatically
|
||||
// set for DNS, TCP, TLS, and WebSocket protocols.
|
||||
bool newConnectionPerRequest = 22;
|
||||
// If set, each request will force a DNS lookup. Only applies if newConnectionPerRequest is set.
|
||||
bool forceDNSLookup = 23;
|
||||
}
|
||||
|
||||
message Alpn {
|
||||
repeated string value = 1;
|
||||
}
|
||||
|
||||
message ForwardEchoResponse {
|
||||
repeated string output = 1;
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ pluginManagement {
|
|||
id "com.android.library" version "4.2.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "com.github.kt3k.coveralls" version "2.12.0"
|
||||
id "com.google.cloud.tools.jib" version "3.2.1"
|
||||
id "com.google.osdetector" version "1.7.0"
|
||||
id "com.google.protobuf" version "0.8.18"
|
||||
id "digital.wup.android-maven-publish" version "3.6.3"
|
||||
|
|
@ -54,6 +55,7 @@ include ":grpc-bom"
|
|||
include ":grpc-rls"
|
||||
include ":grpc-authz"
|
||||
include ":grpc-gcp-observability"
|
||||
include ":grpc-istio-interop-testing"
|
||||
|
||||
project(':grpc-api').projectDir = "$rootDir/api" as File
|
||||
project(':grpc-core').projectDir = "$rootDir/core" as File
|
||||
|
|
@ -81,6 +83,7 @@ project(':grpc-bom').projectDir = "$rootDir/bom" as File
|
|||
project(':grpc-rls').projectDir = "$rootDir/rls" as File
|
||||
project(':grpc-authz').projectDir = "$rootDir/authz" as File
|
||||
project(':grpc-gcp-observability').projectDir = "$rootDir/gcp-observability" as File
|
||||
project(':grpc-istio-interop-testing').projectDir = "$rootDir/istio-interop-testing" as File
|
||||
|
||||
if (settings.hasProperty('skipCodegen') && skipCodegen.toBoolean()) {
|
||||
println '*** Skipping the build of codegen and compilation of proto files because skipCodegen=true'
|
||||
|
|
|
|||
Loading…
Reference in New Issue