Fix the bug #5443 and add documents for the local E2E remote debugging. (#5457)

* fix the E2E bug when running locally with multiple `docker-compose.yml` files #5443

* add documents for the for local remote debugging.

Co-authored-by: kezhenxu94 <kezhenxu94@apache.org>
This commit is contained in:
CoderGang 2020-09-09 00:26:11 +08:00 committed by GitHub
parent 10fe6b2585
commit c89e766f0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 103 additions and 28 deletions

View File

@ -0,0 +1,28 @@
# Using E2E local remote debugging
The E2E remote debugging port of service containers is `5005`. If the developer wants to use remote debugging, he needs to add remote debugging parameters to the start service command, and then expose the port `5005`.
For example, this is the configuration of a container in the [skywalking/test/e2e/e2e-test/docker/base-compose.yml](https://github.com/apache/skywalking/blob/master/test/e2e/e2e-test/docker/base-compose.yml). [JAVA_OPTS](https://github.com/apache/skywalking/blob/190ca93b6bf48e9d966de5b05cd6490ba54b7266/docker/oap/docker-entrypoint.sh) is a preset variable for passing additional parameters in the AOP service startup command, so we only need to add the JAVA remote debugging parameters `agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005` to the configuration and exposes the port `5005`.
```yml
oap:
image: skywalking/oap:latest
expose:
...
- 5005
...
environment:
...
JAVA_OPTS: >-
...
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
...
```
At last, if the E2E test failed and is retrying, the developer can get the ports mapping in the file `skywalking/test/e2e/e2e-test/remote_real_port` and selects the host port of the corresponding service for remote debugging. For example,
```bash
#remote_real_port
#The remote debugging port on the host is 32783
oap-localhost:32783
#The remote debugging port on the host is 32782
provider-localhost:32782
```

View File

@ -97,6 +97,9 @@ We expose all the logs from all containers to the stdout in non-CI (local) mode,
**NOTE:** Please verify the newly-added E2E test case locally first, however, if you find it passed locally but failed in the PR check status, make sure all the updated/newly-added files (especially those in submodules)
are committed and included in that PR, or reset the git HEAD to the remote and verify locally again.
#### E2E local remote debugging
When the E2E test is executed locally, if any test case fails, the [E2E local remote debugging function](E2E-local-remote-debug.md) can be used to quickly troubleshoot the bug.
### Project Extensions
SkyWalking project supports many ways to extend existing features. If you are interesting in these ways,
read the following guides.

View File

@ -48,6 +48,7 @@ import org.testcontainers.containers.DockerComposeContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
import static java.util.stream.Collectors.joining;
import static org.apache.skywalking.e2e.utils.Yamls.load;
/**
@ -203,22 +204,20 @@ public final class SkyWalkingAnnotations {
final DockerComposeContainer<?> compose = new DockerComposeContainer<>(IDENTIFIER, files);
if (!IS_CI) {
files.forEach(file -> {
try {
DockerComposeFile dockerComposeFile = DockerComposeFile.getAllConfigInfo(
file.getAbsolutePath());
LOGGER.info(file.getAbsolutePath());
dockerComposeFile.getServices().forEach(
(service, ignored) -> {
if (dockerComposeFile.isExposedPort(service, REMOTE_DEBUG_PORT)) {
REMOTE_SERVICE_NAMES.add(service);
compose.withExposedService(service, REMOTE_DEBUG_PORT, Wait.forListeningPort());
}
});
} catch (IOException | InterruptedException e) {
LOGGER.error(e.getMessage(), e);
}
});
List<String> filePathList = files.stream().map(File::getAbsolutePath).collect(Collectors.toList());
try {
LOGGER.info("Parse files:{}", filePathList.stream().collect(joining(" ", " ", "")));
DockerComposeFile dockerComposeFile = DockerComposeFile.getAllConfigInfo(filePathList);
dockerComposeFile.getServices().forEach((service, ignored) -> {
if (dockerComposeFile.isExposedPort(service, REMOTE_DEBUG_PORT)) {
REMOTE_SERVICE_NAMES.add(service);
compose.withExposedService(service, REMOTE_DEBUG_PORT, Wait.forListeningPort());
}
});
} catch (IOException | InterruptedException e) {
LOGGER.error(e.getMessage(), e);
}
}
for (final Field field : fields) {

View File

@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import lombok.Data;
import static java.util.stream.Collectors.joining;
import static org.apache.skywalking.e2e.utils.Yamls.load;
@Data
@ -34,8 +35,9 @@ public final class DockerComposeFile {
private Map<String, Map<String, Object>> services;
private Map<String, Map<String, Object>> networks;
public static DockerComposeFile getAllConfigInfo(String composeFile) throws IOException, InterruptedException {
String shStr = String.format("docker-compose -f %s config", composeFile);
public static DockerComposeFile getAllConfigInfo(List<String> composeFiles) throws IOException, InterruptedException {
String shStr = String.format("docker-compose %s config",
composeFiles.stream().collect(joining(" -f", " -f", "")));
Process process = Runtime.getRuntime().exec(shStr, null, null);
InputStreamReader ir = new InputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader(ir);

View File

@ -26,41 +26,54 @@ import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
class DockerComposeFileTest {
private static DockerComposeFile COMPOSE_FILE = null;
private static DockerComposeFile COMPOSE_FILE_ONE = null;
private static DockerComposeFile COMPOSE_FILE_TWO = null;
@BeforeAll
static void setUp() throws Exception {
COMPOSE_FILE = Yamls.load("docker-compose.yml").as(DockerComposeFile.class);
COMPOSE_FILE_ONE = Yamls.load("docker-compose.one.yml").as(DockerComposeFile.class);
COMPOSE_FILE_TWO = Yamls.load("docker-compose.two.yml").as(DockerComposeFile.class);
}
@Test
void getAllConfigInfo() throws IOException, InterruptedException, URISyntaxException {
File file = new File(DockerComposeFileTest.class
File composeOne = new File(DockerComposeFileTest.class
.getClassLoader()
.getResource("docker-compose.yml")
.getResource("docker-compose.one.yml")
.toURI());
DockerComposeFile testFile = DockerComposeFile.getAllConfigInfo(file.getAbsolutePath());
File composeTwo = new File(DockerComposeFileTest.class
.getClassLoader()
.getResource("docker-compose.two.yml")
.toURI());
List<String> filePathList = new ArrayList<>();
filePathList.add(composeOne.getAbsolutePath());
filePathList.add(composeTwo.getAbsolutePath());
DockerComposeFile testFile = DockerComposeFile.getAllConfigInfo(filePathList);
Assert.assertNotNull(testFile);
Assert.assertNotNull(testFile.getServices());
Assert.assertEquals(COMPOSE_FILE.getServices().size(), testFile.getServices().size());
Assert.assertEquals(COMPOSE_FILE.getVersion(), testFile.getVersion());
Assert.assertEquals(COMPOSE_FILE_ONE.getServices().size() + COMPOSE_FILE_TWO.getServices().size(),
testFile.getServices().size());
Assert.assertEquals(COMPOSE_FILE_ONE.getVersion(), testFile.getVersion());
}
@Test
void getServiceExposedPort() {
List<String> ports = COMPOSE_FILE.getServiceExposedPorts("oap");
List<String> ports = COMPOSE_FILE_TWO.getServiceExposedPorts("oap");
Assert.assertNotNull(ports);
Assert.assertEquals(3, ports.size());
}
@Test
void isExposedPort() {
boolean result = COMPOSE_FILE.isExposedPort("oap", 5005);
boolean result = COMPOSE_FILE_TWO.isExposedPort("oap", 5005);
Assert.assertTrue(result);
result = COMPOSE_FILE.isExposedPort("oap", 5006);
result = COMPOSE_FILE_TWO.isExposedPort("oap", 5006);
Assert.assertFalse(result);
}
}

View File

@ -0,0 +1,30 @@
# 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.
version: '2.1'
services:
ui:
depends_on:
oap:
condition: service_healthy
environment:
SW_OAP_ADDRESS: oap:12800
expose:
- '8080'
image: skywalking/ui:latest
networks:
- e2e