Enable OAP gRPC SSL transportation (#4470)
* Enable OAP gRPC SSL transportation Porting to OpenSSL to enable SSL transportation. The server private key is in the format of PCKS#8, certificates is x509 though. Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Add netty-tcnative-boringssl-static 2.0.26 licnese Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Update docs/en/setup/backend/grpc-ssl.md Co-Authored-By: kezhenxu94 <kezhenxu94@apache.org> * Update docs/en/setup/backend/grpc-ssl.md Co-Authored-By: kezhenxu94 <kezhenxu94@apache.org> * Add SSL to grpc remote client and sharing server Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Update documents Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Fix nits Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Fix test case Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Add e2e-ssl and remove other test cases temporarily Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Add TLS relevant files Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Decrease timeout Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Test config works Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * triger CI on oap-ssl branch * Disable agent ca Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Switch to sharing server Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Add agent log to console Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Upload log files * Change backend Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Revert "Change backend" This reverts commit 7a085711e3653d3bf642aa84f73650e22595e383. * Update backend Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Revert e2e Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Ignore TSL relevant files Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Polish codes Signed-off-by: Gao Hongtao <hanahmily@gmail.com> * Update certificates expires year to 2120 Signed-off-by: Gao Hongtao <hanahmily@gmail.com> Co-authored-by: 吴晟 Wu Sheng <wu.sheng@foxmail.com> Co-authored-by: kezhenxu94 <kezhenxu94@apache.org>
This commit is contained in:
parent
d5efc97c80
commit
78d14ebbd6
|
|
@ -58,6 +58,13 @@ jobs:
|
|||
run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-agent-reboot
|
||||
- name: Agent Auth Tests(JDK8)
|
||||
run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-agent-auth
|
||||
- name: Agent and OAP SSL Tests(JDK8)
|
||||
run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-ssl
|
||||
- uses: actions/upload-artifact@v1.0.0
|
||||
if: always()
|
||||
with:
|
||||
name: logs
|
||||
path: /tmp/logs
|
||||
|
||||
Cluster:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ core:
|
|||
restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
|
||||
gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
|
||||
gRPCPort: ${SW_CORE_GRPC_PORT:11800}
|
||||
gRPCSslEnabled: ${SW_CORE_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: ${SW_CORE_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: ${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
gRPCSslTrustedCAPath: ${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
|
||||
downsampling:
|
||||
- Hour
|
||||
- Day
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ The text of each license is also included at licenses/LICENSE-[project].txt.
|
|||
|
||||
Apache: httpcomponents 4.x.x: http://hc.apache.org/index.html, Apache 2.0
|
||||
Apache: fastjson 1.2.47: https://github.com/alibaba/fastjson, Apache 2.0
|
||||
Apache: netty-tcnative-boringssl-static 2.0.26: https://github.com/netty/netty-tcnative, Apache 2.0
|
||||
|
||||
========================================================================
|
||||
Apache 2.0 licenses
|
||||
|
|
|
|||
|
|
@ -332,6 +332,10 @@ core:
|
|||
restContextPath: \${SW_CORE_REST_CONTEXT_PATH:/}
|
||||
gRPCHost: \${SW_CORE_GRPC_HOST:0.0.0.0}
|
||||
gRPCPort: \${SW_CORE_GRPC_PORT:11800}
|
||||
gRPCSslEnabled: \${SW_CORE_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: \${SW_CORE_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: \${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
gRPCSslTrustedCAPath: \${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
|
||||
downsampling:
|
||||
- Hour
|
||||
- Day
|
||||
|
|
@ -371,6 +375,9 @@ receiver-sharing-server:
|
|||
gRPCThreadPoolSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_SIZE:0}
|
||||
gRPCThreadPoolQueueSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_QUEUE_SIZE:0}
|
||||
authentication: \${SW_AUTHENTICATION:""}
|
||||
gRPCSslEnabled: \${SW_RECEIVER_SHARING_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: \${SW_RECEIVER_SHARING_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: \${SW_RECEIVER_SHARING_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
receiver-register:
|
||||
default:
|
||||
receiver-trace:
|
||||
|
|
|
|||
|
|
@ -333,6 +333,10 @@ core:
|
|||
restContextPath: \${SW_CORE_REST_CONTEXT_PATH:/}
|
||||
gRPCHost: \${SW_CORE_GRPC_HOST:0.0.0.0}
|
||||
gRPCPort: \${SW_CORE_GRPC_PORT:11800}
|
||||
gRPCSslEnabled: \${SW_CORE_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: \${SW_CORE_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: \${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
gRPCSslTrustedCAPath: \${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
|
||||
downsampling:
|
||||
- Hour
|
||||
- Day
|
||||
|
|
@ -372,6 +376,9 @@ receiver-sharing-server:
|
|||
gRPCThreadPoolSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_SIZE:0}
|
||||
gRPCThreadPoolQueueSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_QUEUE_SIZE:0}
|
||||
authentication: \${SW_AUTHENTICATION:""}
|
||||
gRPCSslEnabled: \${SW_RECEIVER_SHARING_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: \${SW_RECEIVER_SHARING_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: \${SW_RECEIVER_SHARING_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
receiver-register:
|
||||
default:
|
||||
receiver-trace:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
# Support gRPC SSL transportation for OAP server
|
||||
|
||||
For OAP communication we are currently using gRPC, a multi-platform RPC framework that uses protocol buffers for
|
||||
message serialization. The nice part about gRPC is that it promotes the use of SSL/TLS to authenticate and encrypt
|
||||
exchanges. Now OAP supports to enable SSL transportation for gRPC receivers.
|
||||
|
||||
You can follow below steps to enable this feature
|
||||
|
||||
## Creating SSL/TLS Certificates
|
||||
|
||||
It seems like step one is to generate certificates and key files for encrypting communication. I thought this would be
|
||||
fairly straightforward using `openssl` from the command line.
|
||||
|
||||
Use this [script](../../../../../tools/TLS/tls_key_generate.sh) if you are not familiar with how to generate key files.
|
||||
|
||||
We need below files:
|
||||
- `server.pem` a private RSA key to sign and authenticate the public key.
|
||||
- `server.crt` self-signed X.509 public keys for distribution.
|
||||
- `ca.crt` a certificate authority public key for a client to validate the server's certificate.
|
||||
|
||||
## Config OAP server
|
||||
|
||||
You can enable gRPC SSL by add following lines to `application.yml/core/default`.
|
||||
```json
|
||||
gRPCSslEnabled: true
|
||||
gRPCSslKeyPath: /path/to/server.pem
|
||||
gRPCSslCertChainPath: /path/to/server.crt
|
||||
gRPCSslTrustedCAPath: /path/to/ca.crt
|
||||
```
|
||||
|
||||
`gRPCSslKeyPath` and `gRPCSslCertChainPath` are loaded by OAP server to encrypt the communication. `gRPCSslTrustedCAPath`
|
||||
helps gRPC client to verify server certificates in cluster mode.
|
||||
|
||||
If you enable `sharding-server` to ingest data from external, add following lines to `application.yml/receiver-sharing-server/default`:
|
||||
|
||||
```json
|
||||
gRPCSslEnabled: true
|
||||
gRPCSslKeyPath: /path/to/server.pem
|
||||
gRPCSslCertChainPath: /path/to/server.crt
|
||||
```
|
||||
|
||||
Because `sharding-server` only receives data from external, so it doesn't need CA at all.
|
||||
|
||||
If you port to java agent, refer to [TLS.md](../service-agent/java-agent/TLS.md) to config java agent to enable TLS.
|
||||
|
|
@ -11,7 +11,8 @@ at the same time, the SkyWalking backend is in another region (VPC).
|
|||
Only support **no mutual auth**.
|
||||
- Use this [script](../../../../../tools/TLS/tls_key_generate.sh) if you are not familiar with how to generate key files.
|
||||
- Find `ca.crt`, and use it at client side
|
||||
- Find `server.crt` and `server.pem`. Use them at server side.
|
||||
- Find `server.crt` ,`server.pem` and `ca.crt`. Use them at server side. Please refer to [gRPC SSL](../../backend/grpc-ssl.md)
|
||||
for more details.
|
||||
|
||||
## Open and config TLS
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
<graphql-java-tools.version>5.2.3</graphql-java-tools.version>
|
||||
<graphql-java.version>8.0</graphql-java.version>
|
||||
<zookeeper.version>3.4.10</zookeeper.version>
|
||||
<netty-tcnative-boringssl-static.version>2.0.7.Final</netty-tcnative-boringssl-static.version>
|
||||
<netty-tcnative-boringssl-static.version>2.0.26.Final</netty-tcnative-boringssl-static.version>
|
||||
<jetty.version>9.4.2.v20170220</jetty.version>
|
||||
<h2.version>1.4.196</h2.version>
|
||||
<commons-dbcp.version>1.4</commons-dbcp.version>
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ core:
|
|||
restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
|
||||
gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
|
||||
gRPCPort: ${SW_CORE_GRPC_PORT:11800}
|
||||
gRPCSslEnabled: ${SW_CORE_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: ${SW_CORE_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: ${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
gRPCSslTrustedCAPath: ${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
|
||||
downsampling:
|
||||
- Hour
|
||||
- Day
|
||||
|
|
@ -173,6 +177,9 @@ storage:
|
|||
receiver-sharing-server:
|
||||
default:
|
||||
authentication: ${SW_AUTHENTICATION:""}
|
||||
gRPCSslEnabled: ${SW_RECEIVER_SHARING_GRPC_SSL_ENABLED:false}
|
||||
gRPCSslKeyPath: ${SW_RECEIVER_SHARING_GRPC_SSL_KEY_PATH:""}
|
||||
gRPCSslCertChainPath: ${SW_RECEIVER_SHARING_GRPC_SSL_CERT_CHAIN_PATH:""}
|
||||
receiver-register:
|
||||
default:
|
||||
receiver-trace:
|
||||
|
|
|
|||
|
|
@ -44,6 +44,14 @@ public class CoreModuleConfig extends ModuleConfig {
|
|||
@Setter
|
||||
private int gRPCPort;
|
||||
@Setter
|
||||
private boolean gRPCSslEnabled = false;
|
||||
@Setter
|
||||
private String gRPCSslKeyPath;
|
||||
@Setter
|
||||
private String gRPCSslCertChainPath;
|
||||
@Setter
|
||||
private String gRPCSslTrustedCAPath;
|
||||
@Setter
|
||||
private int maxConcurrentCallsPerConnection;
|
||||
@Setter
|
||||
private int maxMessageSize;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package org.apache.skywalking.oap.server.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
|
||||
import org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
|
||||
import org.apache.skywalking.oap.server.core.analysis.ApdexThresholdConfig;
|
||||
|
|
@ -166,7 +167,13 @@ public class CoreModuleProvider extends ModuleProvider {
|
|||
throw new ModuleStartException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort());
|
||||
if (moduleConfig.isGRPCSslEnabled()) {
|
||||
grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort(),
|
||||
Paths.get(moduleConfig.getGRPCSslCertChainPath()).toFile(),
|
||||
Paths.get(moduleConfig.getGRPCSslKeyPath()).toFile());
|
||||
} else {
|
||||
grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort());
|
||||
}
|
||||
if (moduleConfig.getMaxConcurrentCallsPerConnection() > 0) {
|
||||
grpcServer.setMaxConcurrentCallsPerConnection(moduleConfig.getMaxConcurrentCallsPerConnection());
|
||||
}
|
||||
|
|
@ -245,7 +252,12 @@ public class CoreModuleProvider extends ModuleProvider {
|
|||
|
||||
annotationScan.registerListener(streamAnnotationListener);
|
||||
|
||||
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout());
|
||||
if (moduleConfig.isGRPCSslEnabled()) {
|
||||
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout(),
|
||||
Paths.get(moduleConfig.getGRPCSslTrustedCAPath()).toFile());
|
||||
} else {
|
||||
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout());
|
||||
}
|
||||
this.registerServiceImplementation(RemoteClientManager.class, remoteClientManager);
|
||||
|
||||
MetricsStreamProcessor.getInstance().setEnableDatabaseSession(moduleConfig.isEnableDatabaseSession());
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.remote.client;
|
|||
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -51,6 +52,7 @@ public class GRPCRemoteClient implements RemoteClient {
|
|||
private final int bufferSize;
|
||||
private final Address address;
|
||||
private final AtomicInteger concurrentStreamObserverNumber = new AtomicInteger(0);
|
||||
private SslContext sslContext;
|
||||
private GRPCClient client;
|
||||
private DataCarrier<RemoteMessage> carrier;
|
||||
private boolean isConnect;
|
||||
|
|
@ -58,23 +60,29 @@ public class GRPCRemoteClient implements RemoteClient {
|
|||
private CounterMetrics remoteOutErrorCounter;
|
||||
private int remoteTimeout;
|
||||
|
||||
public GRPCRemoteClient(ModuleDefineHolder moduleDefineHolder, Address address, int channelSize, int bufferSize,
|
||||
int remoteTimeout) {
|
||||
public GRPCRemoteClient(final ModuleDefineHolder moduleDefineHolder,
|
||||
final Address address,
|
||||
final int channelSize,
|
||||
final int bufferSize,
|
||||
final int remoteTimeout,
|
||||
final SslContext sslContext) {
|
||||
|
||||
this.address = address;
|
||||
this.channelSize = channelSize;
|
||||
this.bufferSize = bufferSize;
|
||||
this.remoteTimeout = remoteTimeout;
|
||||
this.sslContext = sslContext;
|
||||
|
||||
remoteOutCounter = moduleDefineHolder.find(TelemetryModule.NAME)
|
||||
.provider()
|
||||
.getService(MetricsCreator.class)
|
||||
.createCounter("remote_out_count", "The number(client side) of inside remote inside aggregate rpc.", new MetricsTag.Keys("dest", "self"), new MetricsTag.Values(address
|
||||
.toString(), "N"));
|
||||
.toString(), "N"));
|
||||
remoteOutErrorCounter = moduleDefineHolder.find(TelemetryModule.NAME)
|
||||
.provider()
|
||||
.getService(MetricsCreator.class)
|
||||
.createCounter("remote_out_error_count", "The error number(client side) of inside remote inside aggregate rpc.", new MetricsTag.Keys("dest", "self"), new MetricsTag.Values(address
|
||||
.toString(), "N"));
|
||||
.toString(), "N"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -99,7 +107,7 @@ public class GRPCRemoteClient implements RemoteClient {
|
|||
if (Objects.isNull(client)) {
|
||||
synchronized (GRPCRemoteClient.class) {
|
||||
if (Objects.isNull(client)) {
|
||||
this.client = new GRPCClient(address.getHost(), address.getPort());
|
||||
this.client = new GRPCClient(address.getHost(), address.getPort(), sslContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ package org.apache.skywalking.oap.server.core.remote.client;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import io.grpc.netty.GrpcSslContexts;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -31,6 +34,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.net.ssl.SSLException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
|
@ -55,6 +59,7 @@ public class RemoteClientManager implements Service {
|
|||
private static final Logger logger = LoggerFactory.getLogger(RemoteClientManager.class);
|
||||
|
||||
private final ModuleDefineHolder moduleDefineHolder;
|
||||
private SslContext sslContext;
|
||||
private ClusterNodesQuery clusterNodesQuery;
|
||||
private volatile List<RemoteClient> usingClients;
|
||||
private GaugeMetrics gauge;
|
||||
|
|
@ -62,11 +67,29 @@ public class RemoteClientManager implements Service {
|
|||
|
||||
/**
|
||||
* Initial the manager for all remote communication clients.
|
||||
*
|
||||
* @param moduleDefineHolder for looking up other modules
|
||||
* @param remoteTimeout for cluster internal communication, in second unit.
|
||||
* @param trustedCAFile SslContext to verify server certificates.
|
||||
*/
|
||||
public RemoteClientManager(ModuleDefineHolder moduleDefineHolder, int remoteTimeout) {
|
||||
public RemoteClientManager(ModuleDefineHolder moduleDefineHolder,
|
||||
int remoteTimeout,
|
||||
File trustedCAFile) {
|
||||
this(moduleDefineHolder, remoteTimeout);
|
||||
try {
|
||||
sslContext = GrpcSslContexts.forClient().trustManager(trustedCAFile).build();
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial the manager for all remote communication clients.
|
||||
*
|
||||
* Initial the manager for all remote communication clients.
|
||||
* @param moduleDefineHolder for looking up other modules
|
||||
* @param remoteTimeout for cluster internal communication, in second unit.
|
||||
*/
|
||||
public RemoteClientManager(final ModuleDefineHolder moduleDefineHolder, final int remoteTimeout) {
|
||||
this.moduleDefineHolder = moduleDefineHolder;
|
||||
this.usingClients = ImmutableList.of();
|
||||
this.remoteTimeout = remoteTimeout;
|
||||
|
|
@ -197,7 +220,8 @@ public class RemoteClientManager implements Service {
|
|||
RemoteClient client = new SelfRemoteClient(moduleDefineHolder, address);
|
||||
newRemoteClients.add(client);
|
||||
} else {
|
||||
RemoteClient client = new GRPCRemoteClient(moduleDefineHolder, address, 1, 3000, remoteTimeout);
|
||||
RemoteClient client;
|
||||
client = new GRPCRemoteClient(moduleDefineHolder, address, 1, 3000, remoteTimeout, sslContext);
|
||||
client.connect();
|
||||
newRemoteClients.add(client);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class GRPCRemoteClientRealClient {
|
|||
moduleManager.put(TelemetryModule.NAME, telemetryModuleDefine);
|
||||
telemetryModuleDefine.provider().registerServiceImplementation(MetricsCreator.class, metricsCreator);
|
||||
|
||||
GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10));
|
||||
GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10, null));
|
||||
remoteClient.connect();
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public class GRPCRemoteClientTestCase {
|
|||
grpcServerRule.getServiceRegistry().addService(new RemoteServiceHandler(moduleManager));
|
||||
|
||||
Address address = new Address("not-important", 11, false);
|
||||
GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10));
|
||||
GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10, null));
|
||||
remoteClient.connect();
|
||||
|
||||
doReturn(grpcServerRule.getChannel()).when(remoteClient).getChannel();
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@
|
|||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-netty</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ package org.apache.skywalking.oap.server.library.client.grpc;
|
|||
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.netty.NettyChannelBuilder;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import lombok.Getter;
|
||||
import org.apache.skywalking.oap.server.library.client.Client;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -35,6 +37,8 @@ public class GRPCClient implements Client {
|
|||
@Getter
|
||||
private final int port;
|
||||
|
||||
private SslContext sslContext;
|
||||
|
||||
private ManagedChannel channel;
|
||||
|
||||
public GRPCClient(String host, int port) {
|
||||
|
|
@ -42,9 +46,18 @@ public class GRPCClient implements Client {
|
|||
this.port = port;
|
||||
}
|
||||
|
||||
public GRPCClient(String host, int port, final SslContext sslContext) {
|
||||
this(host, port);
|
||||
this.sslContext = sslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
|
||||
if (sslContext == null) {
|
||||
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
|
||||
return;
|
||||
}
|
||||
channel = NettyChannelBuilder.forAddress(host, port).sslContext(sslContext).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -84,8 +84,7 @@ public class GRPCServer implements Server {
|
|||
* @param privateKeyFile `server.pem` file
|
||||
*/
|
||||
public GRPCServer(String host, int port, File certChainFile, File privateKeyFile) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this(host, port);
|
||||
this.certChainFile = certChainFile;
|
||||
this.privateKeyFile = privateKeyFile;
|
||||
this.sslContextBuilder = SslContextBuilder.forServer(certChainFile, privateKeyFile);
|
||||
|
|
|
|||
|
|
@ -41,4 +41,7 @@ public class SharingServerConfig extends ModuleConfig {
|
|||
private int gRPCThreadPoolSize;
|
||||
private int gRPCThreadPoolQueueSize;
|
||||
private String authentication;
|
||||
private boolean gRPCSslEnabled = false;
|
||||
private String gRPCSslKeyPath;
|
||||
private String gRPCSslCertChainPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.receiver.sharing.server;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Objects;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.apache.skywalking.apm.util.StringUtil;
|
||||
|
|
@ -78,8 +79,15 @@ public class SharingServerModuleProvider extends ModuleProvider {
|
|||
}
|
||||
|
||||
if (config.getGRPCPort() != 0) {
|
||||
grpcServer = new GRPCServer(Strings.isBlank(config.getGRPCHost()) ? "0.0.0.0" : config.getGRPCHost(), config
|
||||
.getGRPCPort());
|
||||
if (config.isGRPCSslEnabled()) {
|
||||
grpcServer = new GRPCServer(Strings.isBlank(config.getGRPCHost()) ? "0.0.0.0" : config.getGRPCHost(),
|
||||
config.getGRPCPort(),
|
||||
Paths.get(config.getGRPCSslCertChainPath()).toFile(),
|
||||
Paths.get(config.getGRPCSslKeyPath()).toFile());
|
||||
} else {
|
||||
grpcServer = new GRPCServer(Strings.isBlank(config.getGRPCHost()) ? "0.0.0.0" : config.getGRPCHost(),
|
||||
config.getGRPCPort());
|
||||
}
|
||||
if (config.getMaxMessageSize() > 0) {
|
||||
grpcServer.setMaxMessageSize(config.getMaxMessageSize());
|
||||
}
|
||||
|
|
|
|||
6
pom.xml
6
pom.xml
|
|
@ -195,7 +195,7 @@
|
|||
<protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
|
||||
<com.google.protobuf.protoc.version>3.3.0</com.google.protobuf.protoc.version>
|
||||
<protoc-gen-grpc-java.plugin.version>1.8.0</protoc-gen-grpc-java.plugin.version>
|
||||
<netty-tcnative-boringssl-static.version>2.0.25.Final</netty-tcnative-boringssl-static.version>
|
||||
<netty-tcnative-boringssl-static.version>2.0.26.Final</netty-tcnative-boringssl-static.version>
|
||||
|
||||
<!-- Plugin versions -->
|
||||
<docker.plugin.version>0.4.13</docker.plugin.version>
|
||||
|
|
@ -464,6 +464,10 @@
|
|||
<!-- generated file from test agent plugin scenarios -->
|
||||
<exclude>**/test/plugin/workspace/**</exclude>
|
||||
|
||||
<!-- TSL relevant files for e2e test -->
|
||||
<exclude>**/*.crt</exclude>
|
||||
<exclude>**/*.pem</exclude>
|
||||
|
||||
<exclude>.m2/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,151 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
~ contributor license agreements. See the NOTICE file distributed with
|
||||
~ this work for additional information regarding copyright ownership.
|
||||
~ The ASF licenses this file to You 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<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/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>apache-skywalking-e2e</artifactId>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>e2e-ssl</artifactId>
|
||||
|
||||
<properties>
|
||||
<e2e.container.version>1.1</e2e.container.version>
|
||||
<e2e.container.name.prefix>skywalking-e2e-container-${build.id}-agent-auth</e2e.container.name.prefix>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>e2e-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<configuration>
|
||||
<executable>true</executable>
|
||||
<addResources>true</addResources>
|
||||
<excludeDevtools>true</excludeDevtools>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<containerNamePattern>%a-%t-%i</containerNamePattern>
|
||||
<images>
|
||||
<image>
|
||||
<name>skyapm/e2e-container:${e2e.container.version}</name>
|
||||
<alias>${e2e.container.name.prefix}</alias>
|
||||
<run>
|
||||
<env>
|
||||
<INSTRUMENTED_SERVICE>${project.build.finalName}.jar</INSTRUMENTED_SERVICE>
|
||||
<INSTRUMENTED_SERVICE_OPTS>-Dskywalking.collector.backend_service=oap.skywalking:11800 -Dskywalking.logging.dir=/tmp/logs/agent</INSTRUMENTED_SERVICE_OPTS>
|
||||
</env>
|
||||
<ports>
|
||||
<port>+webapp.host:webapp.port:8080</port>
|
||||
<port>+client.host:client.port:9090</port>
|
||||
</ports>
|
||||
<volumes>
|
||||
<bind>
|
||||
<volume>${sw.home}:/sw</volume>
|
||||
<volume>${project.build.directory}:/home</volume>
|
||||
<volume>${project.basedir}/src/docker/rc.d:/rc.d:ro</volume>
|
||||
<volume>${project.basedir}/src/docker/certs:/sw/certs:ro</volume>
|
||||
<volume>${project.basedir}/src/docker/ca:/sw/agent/ca:ro</volume>
|
||||
<volume>${project.basedir}/src/docker/hosts:/etc/hosts:ro</volume>
|
||||
<volume>/tmp/logs:/tmp/logs:rw</volume>
|
||||
</bind>
|
||||
</volumes>
|
||||
<wait>
|
||||
<http>
|
||||
<url>
|
||||
http://${docker.host.address}:${client.port}/e2e/health-check
|
||||
</url>
|
||||
<method>GET</method>
|
||||
<status>200</status>
|
||||
</http>
|
||||
<time>300000</time>
|
||||
</wait>
|
||||
</run>
|
||||
</image>
|
||||
</images>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- set the system properties that can be used in test codes -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<sw.webapp.host>
|
||||
${webapp.host}
|
||||
</sw.webapp.host>
|
||||
<sw.webapp.port>
|
||||
${webapp.port}
|
||||
</sw.webapp.port>
|
||||
<client.host>
|
||||
${client.host}
|
||||
</client.host>
|
||||
<client.port>
|
||||
${client.port}
|
||||
</client.port>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIE3DCCAsSgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYTAg
|
||||
Fw0yMDAzMTQxMTAyMzJaGA8yMTIwMDMxNDExMDIyN1owDTELMAkGA1UEAxMCY2Ew
|
||||
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzC+MyVQhw8fstg0sZtAJO
|
||||
u1LGGN6uk0Dto4dXiqjeJ5NNDlwFCa4JZQzPXR5h3LN5ztvSPp9cYB3KXhRmQL/D
|
||||
sjdnJEL07mMGF5Om6yZgvE/xY1p7xzkpNfmrMrdjbCsHCX8mHV5RBWAs+dWdF8K0
|
||||
JxjuoY4sbOIugKBdIYX+BaKTnywcl2f6vnvbACGzR2DHNa0gdceradYkurxia6dD
|
||||
JC46N+E3PofhIGuOzUgBMad7L1Ju1OLNxI8bK2XT/nVHvjhUL50MJDEqaPpHXRgg
|
||||
7Mcvb6CwCeUeWjFJPcKHPG8L55j2HijMV4uukZmTzeiiYmocnMlrDm7NWeVeT9V+
|
||||
207i/fx2dd0o7xoec3vP9WAd/8dF6rxkgLC3cE09dTLlTaVSbWs3glwZNh1NizpH
|
||||
hMV2Ifl4e/BP6sxyuQk8TPjGqP+2nSkzvqiAmi7hyHYv3BPJXbG5FF2jGcXIbMpi
|
||||
i+0tRrAUFvvsFwvdZ01ElfsIeZ50Cwo21HObDO9Y3vu8K1z/4+anm+dtYPrzlWK2
|
||||
/oUKkzkAViKODQq8hyzHvIkky2iclfZTm+I3XXAMahwk8Uq1yD/3pHIkWomwp5YE
|
||||
YZqglIV7Vddsox5rBVCeFx4OFYYIUXoJ+G/L7Bm+L3F/iAdtEpFI08PAaVMBEPGc
|
||||
3M2dF8OYv9PFlXlzsWp9HwIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T
|
||||
AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUtdnblxrM2bUBOcdFx/AV5xyCb5MwDQYJ
|
||||
KoZIhvcNAQELBQADggIBAGpHU5iRp6Ook8Uu/W0RdsM2uZWM7Nqfcm2AVngQEJ+z
|
||||
IO3FIoL4NGmR2/r12CnPe/p0c74fQTv2xlzWiV5yFpqEb9UujfKhj9tUpZnqucyu
|
||||
zy4sACld3Rxpro2PbIgzslNRkr9lMEpcDEIwGx+HiqBgSrvWjQv3Cn/f8eIV8sXr
|
||||
7hC93N7AC29TROdj+xiImGakK3fy3qRusEAFWv49EsQKX1sQ6WmcniLJ/J82w2cf
|
||||
BDytrMlzhX4ecAYZGCrwObS85cBLNZY7U5CzIVk76x2VHny38/ikcHZDQmThk1d0
|
||||
Rhcb5JPf/v3VdzfmIc5cvHMcdx0ZFOTG8Gg1tsTFOOXWR91VWpbCelRZ6H+J2ubV
|
||||
5ZRVwqyGOP3K40rEGvBoRANtBrStqqv8QHBdAAVRsga4MyzIv3+pSNeFtoEJn3i3
|
||||
NFGqow5z1xdWSIQsqzkqLxUVX7ErMlmCb9gOfn/VHVr1iJ0/Y295cWpCH+HQ4D1h
|
||||
Hk//XciqIOSF1TceRymC4a2MZCHXZHuztYZ5ULDXRSco6xFnEfjHWKNNqpkDUjQv
|
||||
xfVJ6UMS1QV+xrcmd9SPz0B+eIFGjWtgos+OmubhrJuroSLQTXFpse3BsFcKATtE
|
||||
JNrEYxN2pIHV2yVSXolc73barRd1Gm0SZEawnhgA+422p/U2o1i30HXgoESZT3hN
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIE3DCCAsSgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYTAg
|
||||
Fw0yMDAzMTQxMTAyMzJaGA8yMTIwMDMxNDExMDIyN1owDTELMAkGA1UEAxMCY2Ew
|
||||
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzC+MyVQhw8fstg0sZtAJO
|
||||
u1LGGN6uk0Dto4dXiqjeJ5NNDlwFCa4JZQzPXR5h3LN5ztvSPp9cYB3KXhRmQL/D
|
||||
sjdnJEL07mMGF5Om6yZgvE/xY1p7xzkpNfmrMrdjbCsHCX8mHV5RBWAs+dWdF8K0
|
||||
JxjuoY4sbOIugKBdIYX+BaKTnywcl2f6vnvbACGzR2DHNa0gdceradYkurxia6dD
|
||||
JC46N+E3PofhIGuOzUgBMad7L1Ju1OLNxI8bK2XT/nVHvjhUL50MJDEqaPpHXRgg
|
||||
7Mcvb6CwCeUeWjFJPcKHPG8L55j2HijMV4uukZmTzeiiYmocnMlrDm7NWeVeT9V+
|
||||
207i/fx2dd0o7xoec3vP9WAd/8dF6rxkgLC3cE09dTLlTaVSbWs3glwZNh1NizpH
|
||||
hMV2Ifl4e/BP6sxyuQk8TPjGqP+2nSkzvqiAmi7hyHYv3BPJXbG5FF2jGcXIbMpi
|
||||
i+0tRrAUFvvsFwvdZ01ElfsIeZ50Cwo21HObDO9Y3vu8K1z/4+anm+dtYPrzlWK2
|
||||
/oUKkzkAViKODQq8hyzHvIkky2iclfZTm+I3XXAMahwk8Uq1yD/3pHIkWomwp5YE
|
||||
YZqglIV7Vddsox5rBVCeFx4OFYYIUXoJ+G/L7Bm+L3F/iAdtEpFI08PAaVMBEPGc
|
||||
3M2dF8OYv9PFlXlzsWp9HwIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T
|
||||
AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUtdnblxrM2bUBOcdFx/AV5xyCb5MwDQYJ
|
||||
KoZIhvcNAQELBQADggIBAGpHU5iRp6Ook8Uu/W0RdsM2uZWM7Nqfcm2AVngQEJ+z
|
||||
IO3FIoL4NGmR2/r12CnPe/p0c74fQTv2xlzWiV5yFpqEb9UujfKhj9tUpZnqucyu
|
||||
zy4sACld3Rxpro2PbIgzslNRkr9lMEpcDEIwGx+HiqBgSrvWjQv3Cn/f8eIV8sXr
|
||||
7hC93N7AC29TROdj+xiImGakK3fy3qRusEAFWv49EsQKX1sQ6WmcniLJ/J82w2cf
|
||||
BDytrMlzhX4ecAYZGCrwObS85cBLNZY7U5CzIVk76x2VHny38/ikcHZDQmThk1d0
|
||||
Rhcb5JPf/v3VdzfmIc5cvHMcdx0ZFOTG8Gg1tsTFOOXWR91VWpbCelRZ6H+J2ubV
|
||||
5ZRVwqyGOP3K40rEGvBoRANtBrStqqv8QHBdAAVRsga4MyzIv3+pSNeFtoEJn3i3
|
||||
NFGqow5z1xdWSIQsqzkqLxUVX7ErMlmCb9gOfn/VHVr1iJ0/Y295cWpCH+HQ4D1h
|
||||
Hk//XciqIOSF1TceRymC4a2MZCHXZHuztYZ5ULDXRSco6xFnEfjHWKNNqpkDUjQv
|
||||
xfVJ6UMS1QV+xrcmd9SPz0B+eIFGjWtgos+OmubhrJuroSLQTXFpse3BsFcKATtE
|
||||
JNrEYxN2pIHV2yVSXolc73barRd1Gm0SZEawnhgA+422p/U2o1i30HXgoESZT3hN
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDapRERykKZD+Be
|
||||
W8KDr0NdrW9FNiBMe6GgPVCEE3C822c83mEaSxx7daVZNJYXXIL4u4evkQLkSqAf
|
||||
7dNSv+Rznl0EwxZGZVJBBJb7PYwg+2WYYM6CUYQ7X8EnH7X8/3n8xGKfra6vS4vy
|
||||
mvGmYMkLHtf0JgrnsF+O5uTTYOIdHsCSO6hAz6lN2xRJo1O8DpB4WjkzJI8ZaofC
|
||||
mkLKoMXKWeOKqTJc9CewTNwuxQsx0EQdShdrkZvyft1CXL/5oMBvQu4h6/dAI4TF
|
||||
F37MYvYX9DfsRpULpuFx01QUUj54/A1JH27aw89Z6yAyBAjsnhqcdVJaiM6F6d8i
|
||||
iZpVyrxdAgMBAAECggEAAVMQqGfuQVkcRdYOdpfAM7gSPXwXc/8nun3EmBg6DZrS
|
||||
pEbAldUwpfrPdpvf8OJJlNIl/0VEnDdrguYA6rZo3t5tt9KqtuB0QBqUA4+a4rRD
|
||||
KEol1hpCT83DsMX7Zz3w8jwKUOdPcJZnkZ+oqRZbAWs9aag1VrP10DrL1g/3Lq/3
|
||||
Icpue1ll2JXYpLUvqhmhukiIsq2n5GIZqnL3m3kvPmUemS4wrQO9mBraLqlX93Ks
|
||||
reAoyZDQVvaAM5M2ZwFxG+GdOwLeZOCEBZ5MOpUfQA8e8k9e/QcRsA5vCrFIbGhJ
|
||||
M3vtwPXS01qSUWsI3iGriz1VfCWMpH2qOQoEk13zYQKBgQD52qc9gZXsBMiYlaLM
|
||||
S5Qp4C2txfif3UTkido7R9On3iyAZqE3FRA805wQuN2GQk6qI+UiMyIS68/nq+Ll
|
||||
uTXJNKqaajmT5gx77Wxpwv/CpJ3ZMkIEfzLQxHOOrjPoWgTjwPw7n3dV7O2FYtZ0
|
||||
RQXWjU4nLhdzvEAsnh3Rj18VuQKBgQDgBeLpRrgAW/iK0mtU9R+XAwxQnAQ7TOrt
|
||||
BgtwVcwCdzpJzHhGmDnu1KopRn4BhfwJ0inZq3lE0UPPflmgE2E4JiOKIBin3lbw
|
||||
QJIIN5blTvy78zQXD/aBcVN0toOAPCulfRdwkAt75Ad9J0sPEQBLNewFdpOquLLo
|
||||
39UkF/mtxQKBgQDx4OholcviqhrcBHiPGFe+VmVCRlZTxSzNplqbawSPDXm9cB2A
|
||||
KqcGi8EZOy5RrF1lPsyy2BeTg7BI0lEdHbjhKVhDlrRY5quNSaLbnEhnUV/yhUH+
|
||||
AnnaO2S3axObS5JSPmCxA8bOa0jiCXYdJzjopPFU4r0XcNYbm5K4bfiaGQKBgHyK
|
||||
iTWKvSxl9OyoQkc+5sr7RNNjiO62ujv/CkjvSbVtNxhj9dG5OyvNSrQbnl2WcSG8
|
||||
lsuOCqL5e6tU4NqfK4MdoNBfO5XHg6mZHBY5YUgl+1c5w5G2rCIWMIFIHh8iVFly
|
||||
C5/mVJwRjyBCwfWkS/eECKyY2Usl10Cjf0jLk2DJAoGAZRQgdvDTGMVCDzkwYbKm
|
||||
0xEQJj6RoU5wLehCmNbCBWU4aKyVmkj2lspEtOjM5Hw+kI1Cjq01Bq7N5EYCIelb
|
||||
rO7sTDDtQ+2Jr4OKJgnBrgjwlE8C99LHboiKTHkgFWCQpGHEcgfszWaCCIRBru2l
|
||||
wmqJLv4IKD9ZHYu4zLNjhCE=
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEQDCCAiigAwIBAgIQa1fDhEPRaEtB2J+Ircp50DANBgkqhkiG9w0BAQsFADAN
|
||||
MQswCQYDVQQDEwJjYTAgFw0yMDAzMTQxMTA5MDlaGA8yMTIwMDMxNDExMDIyN1ow
|
||||
GTEXMBUGA1UEAxMOb2FwLnNreXdhbGtpbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||
DwAwggEKAoIBAQDapRERykKZD+BeW8KDr0NdrW9FNiBMe6GgPVCEE3C822c83mEa
|
||||
Sxx7daVZNJYXXIL4u4evkQLkSqAf7dNSv+Rznl0EwxZGZVJBBJb7PYwg+2WYYM6C
|
||||
UYQ7X8EnH7X8/3n8xGKfra6vS4vymvGmYMkLHtf0JgrnsF+O5uTTYOIdHsCSO6hA
|
||||
z6lN2xRJo1O8DpB4WjkzJI8ZaofCmkLKoMXKWeOKqTJc9CewTNwuxQsx0EQdShdr
|
||||
kZvyft1CXL/5oMBvQu4h6/dAI4TFF37MYvYX9DfsRpULpuFx01QUUj54/A1JH27a
|
||||
w89Z6yAyBAjsnhqcdVJaiM6F6d8iiZpVyrxdAgMBAAGjgY0wgYowDgYDVR0PAQH/
|
||||
BAQDAgO4MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU
|
||||
2GUzQtLkl/rY9dV3zXjVJ3iEmGswHwYDVR0jBBgwFoAUtdnblxrM2bUBOcdFx/AV
|
||||
5xyCb5MwGQYDVR0RBBIwEIIOb2FwLnNreXdhbGtpbmcwDQYJKoZIhvcNAQELBQAD
|
||||
ggIBAHH21tY+8SrHecDX9FBPObDJbsqqWqLHXqhqYOKKhfCIxm2F+FK35KeVOc+c
|
||||
6rGYvI62Dml3UHezYBLKgA3Ol/l1jzFU/UdLdTyzoybxljrb9TtQV5NViwk6XdVr
|
||||
jKR805LkSpQhDPO6GogSWT5cV5yDIBHjA1DMEG45CB4pX5Y4P4LA5VpmTJe/sox+
|
||||
01HmmzIU2CTt9/F3CRmC8WlMEHrT6gVuSzOh1WfYAanlggLK01F/RI5WXX+mSNoZ
|
||||
a/psQAwkX3rQaekxgYhA0puwV6GU1A7bwexw6yHK9SSiaDsmNazq5QnMGBbNv1F5
|
||||
NuxBz04IOxtrOJ0wtIld8VvePQXvYxWD9/XlQCLFnw7RXkHxZlqu/52A5KJKWxU8
|
||||
H1n5l50nP4rYH/EVmyqwzzZMQYr3HXOmijAPi0ma8oGgBDOpQos8GUZEZ+82ELgQ
|
||||
NCKucqbnaB5xC5kNEwIqf1sEyCTNginmGObDYexN+EtuT6ixutIQoSMkJ4TdPwO+
|
||||
1+caCrXmFI82/WEHartqhB36dLAix1pnRIn19cejO2AWoUacxJ4qZDShn8uQerVx
|
||||
Obfys6kfzGCwFd+bmh+pF181nNy95lqGQgAFiPqiNFsD3ioZwdCmfFJXsq0ObNFe
|
||||
I1qEbVBJy3JeU19wQr22XVx+5QpUkegxHEfZsChunH8rIr1K
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
# Licensed to the SkyAPM under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# Host Database
|
||||
#
|
||||
# localhost is used to configure the loopback interface
|
||||
# when the system is booting. Do not change this entry.
|
||||
##
|
||||
127.0.0.1 localhost
|
||||
255.255.255.255 broadcasthost
|
||||
::1 localhost
|
||||
127.0.0.1 oap.skywalking
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/env bash
|
||||
# Licensed to the SkyAPM under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
cat /etc/hosts
|
||||
|
||||
echo 'starting OAP server...' \
|
||||
&& export SW_CORE_GRPC_SSL_ENABLED=true \
|
||||
&& export SW_CORE_GRPC_SSL_KEY_PATH="${SW_HOME}/certs/server-key.pem" \
|
||||
&& export SW_CORE_GRPC_SSL_CERT_CHAIN_PATH="${SW_HOME}/certs/server.crt" \
|
||||
&& export SW_CORE_GRPC_SSL_TRUSTED_CA_PATH="${SW_HOME}/certs/ca.crt" \
|
||||
&& start_oap 'init'
|
||||
|
||||
echo 'starting Web app...' \
|
||||
&& start_webapp '0.0.0.0' 8080
|
||||
|
||||
echo 'starting instrumented services...' \
|
||||
&& start_instrumented_services
|
||||
|
||||
check_tcp 127.0.0.1 \
|
||||
9090 \
|
||||
60 \
|
||||
10 \
|
||||
"waiting for the instrumented service to be ready"
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "instrumented service failed to start in 30 * 10 seconds: "
|
||||
cat ${SERVICE_LOG}/*
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SkyWalking e2e container is ready for tests"
|
||||
|
||||
tail -f ${OAP_LOG_DIR}/* \
|
||||
${WEBAPP_LOG_DIR}/* \
|
||||
${SERVICE_LOG}/* \
|
||||
${ES_HOME}/logs/stdout.log
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.e2e.sample.client;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@EnableJpaRepositories
|
||||
@SpringBootApplication
|
||||
public class SampleClientApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleClientApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.e2e.sample.client;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/e2e")
|
||||
public class TestController {
|
||||
private final UserRepo userRepo;
|
||||
|
||||
public TestController(final UserRepo userRepo) {
|
||||
this.userRepo = userRepo;
|
||||
}
|
||||
|
||||
@GetMapping("/health-check")
|
||||
public String hello() {
|
||||
return "healthy";
|
||||
}
|
||||
|
||||
@PostMapping("/users")
|
||||
public User createAuthor(@RequestBody final User user) throws InterruptedException {
|
||||
Thread.sleep(1000L);
|
||||
return userRepo.save(user);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.e2e.sample.client;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class User {
|
||||
public User() {
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@Column
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.e2e.sample.client;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface UserRepo extends JpaRepository<User, Long> {
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
server:
|
||||
port: 9090
|
||||
|
||||
spring:
|
||||
main:
|
||||
banner-mode: 'off'
|
||||
datasource:
|
||||
url: jdbc:h2:mem:testdb
|
||||
driver-class-name: org.h2.Driver
|
||||
data-username: sa
|
||||
password: sa
|
||||
platform: org.hibernate.dialect.H2Dialect
|
||||
jpa:
|
||||
generate-ddl: true
|
||||
hibernate:
|
||||
ddl-auto: create-drop
|
||||
properties:
|
||||
hibernate.format_sql: true
|
||||
show-sql: true
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.e2e;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.skywalking.e2e.metrics.AtLeastOneOfMetricsMatcher;
|
||||
import org.apache.skywalking.e2e.metrics.Metrics;
|
||||
import org.apache.skywalking.e2e.metrics.MetricsQuery;
|
||||
import org.apache.skywalking.e2e.metrics.MetricsValueMatcher;
|
||||
import org.apache.skywalking.e2e.service.Service;
|
||||
import org.apache.skywalking.e2e.service.ServicesMatcher;
|
||||
import org.apache.skywalking.e2e.service.ServicesQuery;
|
||||
import org.apache.skywalking.e2e.service.endpoint.Endpoint;
|
||||
import org.apache.skywalking.e2e.service.endpoint.EndpointQuery;
|
||||
import org.apache.skywalking.e2e.service.endpoint.Endpoints;
|
||||
import org.apache.skywalking.e2e.service.endpoint.EndpointsMatcher;
|
||||
import org.apache.skywalking.e2e.service.instance.Instance;
|
||||
import org.apache.skywalking.e2e.service.instance.Instances;
|
||||
import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
|
||||
import org.apache.skywalking.e2e.service.instance.InstancesQuery;
|
||||
import org.apache.skywalking.e2e.topo.Call;
|
||||
import org.apache.skywalking.e2e.topo.ServiceInstanceTopoData;
|
||||
import org.apache.skywalking.e2e.topo.ServiceInstanceTopoMatcher;
|
||||
import org.apache.skywalking.e2e.topo.ServiceInstanceTopoQuery;
|
||||
import org.apache.skywalking.e2e.topo.TopoData;
|
||||
import org.apache.skywalking.e2e.topo.TopoMatcher;
|
||||
import org.apache.skywalking.e2e.topo.TopoQuery;
|
||||
import org.apache.skywalking.e2e.trace.Trace;
|
||||
import org.apache.skywalking.e2e.trace.TracesMatcher;
|
||||
import org.apache.skywalking.e2e.trace.TracesQuery;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_METRICS;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_METRICS;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_METRICS;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_CLIENT_METRICS;
|
||||
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_SERVER_METRICS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class SampleVerificationITCase {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SampleVerificationITCase.class);
|
||||
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
private final int retryInterval = 30;
|
||||
|
||||
private SimpleQueryClient queryClient;
|
||||
private String instrumentedServiceUrl;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final String swWebappHost = System.getProperty("sw.webapp.host", "127.0.0.1");
|
||||
final String swWebappPort = System.getProperty("sw.webapp.port", "32783");
|
||||
final String instrumentedServiceHost = System.getProperty("client.host", "127.0.0.1");
|
||||
final String instrumentedServicePort = System.getProperty("client.port", "32782");
|
||||
queryClient = new SimpleQueryClient(swWebappHost, swWebappPort);
|
||||
instrumentedServiceUrl = "http://" + instrumentedServiceHost + ":" + instrumentedServicePort;
|
||||
}
|
||||
|
||||
@Test(timeout = 2 * 60 * 1000)
|
||||
@DirtiesContext
|
||||
public void verify() throws Exception {
|
||||
final LocalDateTime minutesAgo = LocalDateTime.now(ZoneOffset.UTC);
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
final Map<String, String> user = new HashMap<>();
|
||||
user.put("name", "SkyWalking");
|
||||
final ResponseEntity<String> responseEntity = restTemplate.postForEntity(
|
||||
instrumentedServiceUrl + "/e2e/users", user, String.class);
|
||||
LOGGER.info("responseEntity: {}", responseEntity);
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
final List<Trace> traces = queryClient.traces(new TracesQuery().start(minutesAgo)
|
||||
.end(LocalDateTime.now())
|
||||
.orderByDuration());
|
||||
if (!traces.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(10000L);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
doRetryableVerification(() -> {
|
||||
try {
|
||||
verifyTraces(minutesAgo);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
doRetryableVerification(() -> {
|
||||
try {
|
||||
verifyServices(minutesAgo);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
doRetryableVerification(() -> {
|
||||
try {
|
||||
verifyTopo(minutesAgo);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
doRetryableVerification(() -> {
|
||||
try {
|
||||
verifyServiceInstanceTopo(minutesAgo);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void verifyTopo(LocalDateTime minutesAgo) throws Exception {
|
||||
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
||||
|
||||
final TopoData topoData = queryClient.topo(new TopoQuery().stepByMinute()
|
||||
.start(minutesAgo.minusDays(1))
|
||||
.end(now));
|
||||
LOGGER.info("topoData: {}", topoData);
|
||||
|
||||
InputStream expectedInputStream = new ClassPathResource(
|
||||
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.topo.yml")
|
||||
.getInputStream();
|
||||
|
||||
final TopoMatcher topoMatcher = new Yaml().loadAs(expectedInputStream, TopoMatcher.class);
|
||||
topoMatcher.verify(topoData);
|
||||
verifyServiceRelationMetrics(topoData.getCalls(), minutesAgo);
|
||||
}
|
||||
|
||||
private void verifyServiceInstanceTopo(LocalDateTime minutesAgo) throws Exception {
|
||||
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
||||
|
||||
final ServiceInstanceTopoData topoData = queryClient.serviceInstanceTopo(
|
||||
new ServiceInstanceTopoQuery().stepByMinute()
|
||||
.start(minutesAgo
|
||||
.minusDays(1))
|
||||
.end(now)
|
||||
.clientServiceId("1")
|
||||
.serverServiceId("2"));
|
||||
LOGGER.info("instanceTopoData: {}", topoData);
|
||||
|
||||
InputStream expectedInputStream = new ClassPathResource(
|
||||
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.serviceInstanceTopo.yml")
|
||||
.getInputStream();
|
||||
|
||||
final ServiceInstanceTopoMatcher topoMatcher = new Yaml().loadAs(
|
||||
expectedInputStream, ServiceInstanceTopoMatcher.class);
|
||||
topoMatcher.verify(topoData);
|
||||
verifyServiceInstanceRelationMetrics(topoData.getCalls(), minutesAgo);
|
||||
}
|
||||
|
||||
private void verifyServices(LocalDateTime minutesAgo) throws Exception {
|
||||
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
||||
|
||||
final List<Service> services = queryClient.services(new ServicesQuery().start(minutesAgo).end(now));
|
||||
LOGGER.info("services: {}", services);
|
||||
|
||||
InputStream expectedInputStream = new ClassPathResource(
|
||||
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.services.yml")
|
||||
.getInputStream();
|
||||
|
||||
final ServicesMatcher servicesMatcher = new Yaml().loadAs(expectedInputStream, ServicesMatcher.class);
|
||||
servicesMatcher.verify(services);
|
||||
|
||||
for (Service service : services) {
|
||||
LOGGER.info("verifying service instances: {}", service);
|
||||
|
||||
verifyServiceMetrics(service);
|
||||
|
||||
Instances instances = verifyServiceInstances(minutesAgo, now, service);
|
||||
|
||||
verifyInstancesMetrics(instances);
|
||||
|
||||
Endpoints endpoints = verifyServiceEndpoints(minutesAgo, now, service);
|
||||
|
||||
verifyEndpointsMetrics(endpoints);
|
||||
}
|
||||
}
|
||||
|
||||
private Instances verifyServiceInstances(LocalDateTime minutesAgo, LocalDateTime now,
|
||||
Service service) throws Exception {
|
||||
InputStream expectedInputStream;
|
||||
Instances instances = queryClient.instances(new InstancesQuery().serviceId(service.getKey())
|
||||
.start(minutesAgo)
|
||||
.end(now));
|
||||
LOGGER.info("instances: {}", instances);
|
||||
expectedInputStream = new ClassPathResource(
|
||||
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.instances.yml")
|
||||
.getInputStream();
|
||||
final InstancesMatcher instancesMatcher = new Yaml().loadAs(expectedInputStream, InstancesMatcher.class);
|
||||
instancesMatcher.verify(instances);
|
||||
return instances;
|
||||
}
|
||||
|
||||
private Endpoints verifyServiceEndpoints(LocalDateTime minutesAgo, LocalDateTime now,
|
||||
Service service) throws Exception {
|
||||
Endpoints instances = queryClient.endpoints(new EndpointQuery().serviceId(service.getKey()));
|
||||
LOGGER.info("instances: {}", instances);
|
||||
InputStream expectedInputStream = new ClassPathResource(
|
||||
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.endpoints.yml")
|
||||
.getInputStream();
|
||||
final EndpointsMatcher endpointsMatcher = new Yaml().loadAs(expectedInputStream, EndpointsMatcher.class);
|
||||
endpointsMatcher.verify(instances);
|
||||
return instances;
|
||||
}
|
||||
|
||||
private void verifyInstancesMetrics(Instances instances) throws Exception {
|
||||
for (Instance instance : instances.getInstances()) {
|
||||
for (String metricsName : ALL_INSTANCE_METRICS) {
|
||||
LOGGER.info("verifying service instance response time: {}", instance);
|
||||
final Metrics instanceMetrics = queryClient.metrics(new MetricsQuery().stepByMinute()
|
||||
.metricsName(metricsName)
|
||||
.id(instance.getKey()));
|
||||
LOGGER.info("instanceMetrics: {}", instanceMetrics);
|
||||
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
|
||||
MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
|
||||
greaterThanZero.setValue("gt 0");
|
||||
instanceRespTimeMatcher.setValue(greaterThanZero);
|
||||
instanceRespTimeMatcher.verify(instanceMetrics);
|
||||
LOGGER.info("{}: {}", metricsName, instanceMetrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyEndpointsMetrics(Endpoints endpoints) throws Exception {
|
||||
for (Endpoint endpoint : endpoints.getEndpoints()) {
|
||||
if (!endpoint.getLabel().equals("/e2e/users")) {
|
||||
continue;
|
||||
}
|
||||
for (String metricName : ALL_ENDPOINT_METRICS) {
|
||||
LOGGER.info("verifying endpoint {}, metrics: {}", endpoint, metricName);
|
||||
final Metrics metrics = queryClient.metrics(new MetricsQuery().stepByMinute()
|
||||
.metricsName(metricName)
|
||||
.id(endpoint.getKey()));
|
||||
LOGGER.info("metrics: {}", metrics);
|
||||
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
|
||||
MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
|
||||
greaterThanZero.setValue("gt 0");
|
||||
instanceRespTimeMatcher.setValue(greaterThanZero);
|
||||
instanceRespTimeMatcher.verify(metrics);
|
||||
LOGGER.info("{}: {}", metricName, metrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyServiceMetrics(Service service) throws Exception {
|
||||
for (String metricName : ALL_SERVICE_METRICS) {
|
||||
LOGGER.info("verifying service {}, metrics: {}", service, metricName);
|
||||
final Metrics serviceMetrics = queryClient.metrics(new MetricsQuery().stepByMinute()
|
||||
.metricsName(metricName)
|
||||
.id(service.getKey()));
|
||||
LOGGER.info("serviceMetrics: {}", serviceMetrics);
|
||||
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
|
||||
MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
|
||||
greaterThanZero.setValue("gt 0");
|
||||
instanceRespTimeMatcher.setValue(greaterThanZero);
|
||||
instanceRespTimeMatcher.verify(serviceMetrics);
|
||||
LOGGER.info("{}: {}", metricName, serviceMetrics);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyTraces(LocalDateTime minutesAgo) throws Exception {
|
||||
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
||||
|
||||
final List<Trace> traces = queryClient.traces(new TracesQuery().start(minutesAgo).end(now).orderByDuration());
|
||||
LOGGER.info("traces: {}", traces);
|
||||
|
||||
InputStream expectedInputStream = new ClassPathResource(
|
||||
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.traces.yml")
|
||||
.getInputStream();
|
||||
|
||||
final TracesMatcher tracesMatcher = new Yaml().loadAs(expectedInputStream, TracesMatcher.class);
|
||||
tracesMatcher.verifyLoosely(traces);
|
||||
}
|
||||
|
||||
private void verifyServiceInstanceRelationMetrics(List<Call> calls,
|
||||
final LocalDateTime minutesAgo) throws Exception {
|
||||
verifyRelationMetrics(
|
||||
calls, minutesAgo, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
|
||||
ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
|
||||
);
|
||||
}
|
||||
|
||||
private void verifyServiceRelationMetrics(List<Call> calls, final LocalDateTime minutesAgo) throws Exception {
|
||||
verifyRelationMetrics(
|
||||
calls, minutesAgo, ALL_SERVICE_RELATION_CLIENT_METRICS, ALL_SERVICE_RELATION_SERVER_METRICS);
|
||||
}
|
||||
|
||||
private void verifyRelationMetrics(List<Call> calls, final LocalDateTime minutesAgo, String[] relationClientMetrics,
|
||||
String[] relationServerMetrics) throws Exception {
|
||||
for (Call call : calls) {
|
||||
for (String detectPoint : call.getDetectPoints()) {
|
||||
switch (detectPoint) {
|
||||
case "CLIENT": {
|
||||
for (String metricName : relationClientMetrics) {
|
||||
verifyMetrics(queryClient, metricName, call.getId(), minutesAgo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SERVER": {
|
||||
for (String metricName : relationServerMetrics) {
|
||||
verifyMetrics(queryClient, metricName, call.getId(), minutesAgo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doRetryableVerification(Runnable runnable) throws InterruptedException {
|
||||
while (true) {
|
||||
try {
|
||||
runnable.run();
|
||||
break;
|
||||
} catch (Throwable ignored) {
|
||||
Thread.sleep(retryInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# 1 health-check by docker-maven-plugin
|
||||
# 1 drop table if exists, because we have `ddl-auto: create-drop`
|
||||
# 1 drop sequence
|
||||
# 1 create sequence
|
||||
# 1 create table statement
|
||||
|
||||
endpoints:
|
||||
- key: not null
|
||||
label: /e2e/health-check
|
||||
- key: not null
|
||||
label: /e2e/users
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# 1 health-check by docker-maven-plugin
|
||||
# 1 drop table if exists, because we have `ddl-auto: create-drop`
|
||||
# 1 drop sequence
|
||||
# 1 create sequence
|
||||
# 1 create table statement
|
||||
|
||||
instances:
|
||||
- key: 2
|
||||
label: not null
|
||||
attributes:
|
||||
- name: os_name
|
||||
value: not null
|
||||
- name: host_name
|
||||
value: not null
|
||||
- name: process_no
|
||||
value: gt 0
|
||||
- name: ipv4s
|
||||
value: not null
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# 1 health-check by docker-maven-plugin
|
||||
# 1 drop table if exists, because we have `ddl-auto: create-drop`
|
||||
# 1 drop sequence
|
||||
# 1 create sequence
|
||||
# 1 create table statement
|
||||
|
||||
nodes:
|
||||
- id: 1
|
||||
name: User
|
||||
type: USER
|
||||
serviceId: 1
|
||||
serviceName: User
|
||||
isReal: false
|
||||
- id: 2
|
||||
name: not null
|
||||
serviceId: 2
|
||||
serviceName: Your_ApplicationName
|
||||
type: Tomcat
|
||||
isReal: true
|
||||
calls:
|
||||
- id: 1_2
|
||||
source: 1
|
||||
detectPoints:
|
||||
- SERVER
|
||||
target: 2
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# 1 health-check by docker-maven-plugin
|
||||
# 1 drop table if exists, because we have `ddl-auto: create-drop`
|
||||
# 1 drop sequence
|
||||
# 1 create sequence
|
||||
# 1 create table statement
|
||||
|
||||
services:
|
||||
- key: 2
|
||||
label: "Your_ApplicationName"
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# 1 health-check by docker-maven-plugin
|
||||
# 1 drop table if exists, because we have `ddl-auto: create-drop`
|
||||
# 1 drop sequence
|
||||
# 1 create sequence
|
||||
# 1 create table statement
|
||||
|
||||
nodes:
|
||||
- id: 1
|
||||
name: User
|
||||
type: USER
|
||||
isReal: false
|
||||
- id: 2
|
||||
name: Your_ApplicationName
|
||||
type: Tomcat
|
||||
isReal: true
|
||||
- id: 3
|
||||
name: "localhost:-1"
|
||||
type: H2
|
||||
isReal: false
|
||||
calls:
|
||||
- id: 2_3
|
||||
source: 2
|
||||
detectPoints:
|
||||
- CLIENT
|
||||
target: 3
|
||||
- id: 1_2
|
||||
source: 1
|
||||
detectPoints:
|
||||
- SERVER
|
||||
target: 2
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# 1 health-check by docker-maven-plugin
|
||||
# 1 drop table if exists, because we have `ddl-auto: create-drop`
|
||||
# 1 drop sequence
|
||||
# 1 create sequence
|
||||
# 1 create table statement
|
||||
|
||||
traces:
|
||||
- key: not null
|
||||
endpointNames:
|
||||
- /e2e/users
|
||||
duration: ge 0
|
||||
start: gt 0
|
||||
isError: false
|
||||
traceIds:
|
||||
- not null
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
<module>e2e-profile</module>
|
||||
<module>e2e-protocol</module>
|
||||
<module>e2e-http-api-with-nginx-lua</module>
|
||||
<module>e2e-ssl</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ netty-handler-4.1.42.Final.jar
|
|||
netty-handler-proxy-4.1.42.Final.jar
|
||||
netty-resolver-4.1.42.Final.jar
|
||||
netty-resolver-dns-4.1.42.Final.jar
|
||||
netty-tcnative-boringssl-static-2.0.7.Final.jar
|
||||
netty-tcnative-boringssl-static-2.0.26.Final.jar
|
||||
netty-transport-4.1.42.Final.jar
|
||||
okhttp-2.7.5.jar
|
||||
okhttp-3.9.0.jar
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ netty-handler-4.1.42.Final.jar
|
|||
netty-handler-proxy-4.1.42.Final.jar
|
||||
netty-resolver-4.1.42.Final.jar
|
||||
netty-resolver-dns-4.1.42.Final.jar
|
||||
netty-tcnative-boringssl-static-2.0.7.Final.jar
|
||||
netty-tcnative-boringssl-static-2.0.26.Final.jar
|
||||
netty-transport-4.1.42.Final.jar
|
||||
okhttp-2.7.5.jar
|
||||
okhttp-3.9.0.jar
|
||||
|
|
|
|||
Loading…
Reference in New Issue