Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only define Docker pkg tests if Docker is available #47640

Merged
merged 50 commits into from
Nov 4, 2019
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
521d41d
Revert "Mute docker packaging tests (DockerTests)"
pugnascotia Oct 7, 2019
c01dd7b
Only define Docker pkg tests where appropriate
pugnascotia Oct 7, 2019
d2dccce
Fix lint error
pugnascotia Oct 7, 2019
5eb2a28
Docs and refactoring
pugnascotia Oct 8, 2019
ec8b085
Enable IPv4 forwarding on ubuntu in 16.04
pugnascotia Oct 8, 2019
1f48f44
Use host networking when building docker images
pugnascotia Oct 8, 2019
560adb6
Address review feedback
pugnascotia Oct 9, 2019
7212a9c
Exclude Docker distro tests per VM
pugnascotia Oct 9, 2019
de9bb33
Handle Docker version numbers
pugnascotia Oct 10, 2019
2020084
Merge branch 'master' into fix-docker-tests-on-gcp
elasticmachine Oct 10, 2019
e8a920a
Only run Docker tests on some host OSs
pugnascotia Oct 10, 2019
2d8ca75
Make /etc/os-release parsing better
pugnascotia Oct 10, 2019
1684857
Try to fix Docker task generation
pugnascotia Oct 10, 2019
1641b38
Add a debug stmt, figure out debian-8 issue
pugnascotia Oct 11, 2019
54d322c
Merge branch 'master' into fix-docker-tests-on-gcp
elasticmachine Oct 22, 2019
2d96534
Fix how we use data from /etc/os-release
pugnascotia Oct 23, 2019
64051ed
Fix checkstyle
pugnascotia Oct 23, 2019
6a64065
Trying to diagnose CI failures
pugnascotia Oct 23, 2019
8cb1389
Still trying to diagnose failures on CI
pugnascotia Oct 23, 2019
b0e3a9e
Please, just print my debug info
pugnascotia Oct 23, 2019
a20b3d4
Please, just print my debug info
pugnascotia Oct 24, 2019
daec2ad
Still trying to debug
pugnascotia Oct 24, 2019
be25db4
Only define docker distros when Docker is available
pugnascotia Oct 24, 2019
12bb939
Merge branch 'master' into fix-docker-tests-on-gcp
elasticmachine Oct 26, 2019
31fec0b
Use host networking when building docker images
pugnascotia Oct 26, 2019
5c785c7
Merge branch 'master' into fix-docker-tests-on-gcp
elasticmachine Oct 28, 2019
2293017
Revert docker network change
pugnascotia Oct 28, 2019
8c819fb
Workaround infra issue 15654
pugnascotia Oct 29, 2019
55d4cfc
Merge remote-tracking branch 'upstream/master' into fix-docker-tests-…
pugnascotia Oct 29, 2019
b8d44c7
Increase docker pkg test timeouts
pugnascotia Oct 29, 2019
dc19fed
Merge remote-tracking branch 'upstream/master' into fix-docker-tests-…
pugnascotia Oct 29, 2019
e98e4bc
Tiny change to try and get CI to work
pugnascotia Oct 29, 2019
0831884
Docker test fixes following JVM options work
pugnascotia Oct 29, 2019
0a29d8d
Simplify how Docker test tasks are defined
pugnascotia Oct 30, 2019
048832a
Reimplement Docker tests exclude list
pugnascotia Oct 30, 2019
99ded1c
Remove sles-15 from .ci/dockerOnLinuxExclusions
pugnascotia Oct 30, 2019
12bd9fb
Fix access modifiers in DockerUtils
pugnascotia Oct 31, 2019
97fca15
Use project.exec to run commands in DockerUtils
pugnascotia Oct 31, 2019
617f494
Fix
pugnascotia Oct 31, 2019
ffcf939
Fix JavaDoc ref
pugnascotia Oct 31, 2019
0b49a7a
Don't always create a docker distribution
pugnascotia Oct 31, 2019
611b914
Fix logic
pugnascotia Oct 31, 2019
aac11a4
Update .ci/dockerOnLinuxExclusions
pugnascotia Oct 31, 2019
e0010a6
Expand comment re: configuring Docker tasks for Vagrant
pugnascotia Nov 4, 2019
f189ca1
Merge remote-tracking branch 'upstream/master' into fix-docker-tests-…
pugnascotia Nov 4, 2019
63a758d
Tweak logging
pugnascotia Nov 4, 2019
3e8d10d
Add debugging statements
pugnascotia Nov 4, 2019
cedacee
Pointless change to get CI to run the right code
pugnascotia Nov 4, 2019
ef924fc
Various fixes to docker packaging test logic
pugnascotia Nov 4, 2019
9d50aaa
Pointless change to try and get CI to run the right code
pugnascotia Nov 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .ci/dockerOnLinuxExclusions
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This file specifies the Linux OS versions on which we can't build and
mark-vieira marked this conversation as resolved.
Show resolved Hide resolved
# test Docker images for some reason. These values correspond to ID and
# VERSION_ID from /etc/os-release, and a matching value will cause the
# Docker tests to be skipped on that OS. If /etc/os-release doesn't exist
# (as is the case on centos-6, for example) then that OS will again be
# excluded.

centos-6
debian-8
opensuse-15-1
oraclelinux-6
oraclelinux-7
sles-12
10 changes: 10 additions & 0 deletions .ci/os.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ if which zypper > /dev/null ; then
sudo zypper install -y insserv-compat
fi

if [ -e /etc/sysctl.d/99-gce.conf ]; then
# The GCE defaults disable IPv4 forwarding, which breaks the Docker
# build. Workaround this by renaming the file so that it is executed
# earlier than our own overrides.
#
# This ultimately needs to be fixed at the image level - see infra
# issue 15654.
sudo mv /etc/sysctl.d/99-gce.conf /etc/sysctl.d/98-gce.conf
fi

# Required by bats
sudo touch /etc/is_vagrant_vm
sudo useradd vagrant
Expand Down
6 changes: 5 additions & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Vagrant.configure(2) do |config|
end
'fedora-29'.tap do |box|
config.vm.define box, define_opts do |config|
config.vm.box = 'elastic/fedora-28-x86_64'
config.vm.box = 'elastic/fedora-29-x86_64'
dnf_common config, box
dnf_docker config
end
Expand Down Expand Up @@ -216,6 +216,10 @@ def ubuntu_docker(config)

# Add vagrant to the Docker group, so that it can run commands
usermod -aG docker vagrant

# Enable IPv4 forwarding
sed -i '/net.ipv4.ip_forward/s/^#//' /etc/sysctl.conf
systemctl restart networking
SHELL
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,14 @@ import org.gradle.external.javadoc.CoreJavadocOptions
import org.gradle.internal.jvm.Jvm
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.gradle.process.CommandLineArgumentProvider
import org.gradle.process.ExecResult
import org.gradle.process.ExecSpec
import org.gradle.util.GradleVersion

import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.util.regex.Matcher

import static org.elasticsearch.gradle.tool.Boilerplate.maybeConfigure
import static org.elasticsearch.gradle.tool.DockerUtils.assertDockerIsAvailable
import static org.elasticsearch.gradle.tool.DockerUtils.getDockerPath

/**
* Encapsulates build configuration for elasticsearch projects.
Expand Down Expand Up @@ -188,8 +187,7 @@ class BuildPlugin implements Plugin<Project> {
*/

// check if the Docker binary exists and record its path
final List<String> maybeDockerBinaries = ['/usr/bin/docker', '/usr/local/bin/docker']
final String dockerBinary = maybeDockerBinaries.find { it -> new File(it).exists() }
final String dockerBinary = getDockerPath().orElse(null)

final boolean buildDocker
final String buildDockerProperty = System.getProperty("build.docker")
Copy link
Contributor

Choose a reason for hiding this comment

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

This property is a left over and it's my bad for not removing it yet. See #45034.
Please remove this property here together with the conditionals and the ext.set('buildDocker' from bellow it as it's not used, and make sure we don't mention it in any new code we add.

The way this is meant to work is that docker is required if you need it to build something, trying to build that something without docker should fail. It's optional for anything involving testing.
We usually get around this by only calling build ( which includes assemble ) on CI workers that have docker, and calling check when they might not , which doesn't include a full assemble and only builds what it needs for the tests, if no tests can run nothing gets assembled. The logic is implemented in the test fixtures plugin.
The docker rest tests are a special case that the test fixtures plugin doesn't fully handle, see distribution/docker/build.gradle that has this :

 if (TestFixturesPlugin.dockerComposeSupported()) {
    dependsOn assemble
  }

We got into this situation because we have platforms for which we can't have docker in CI, but still want to run the rest of the tests. Ideally we would just require docker for development as we rely on it in some many ways these days. (Of course we would have to support test fixtures on mac and windows which we don't yet, but that's a different story).

The situation is a bit different here because we are able to pick when to run and when not to because we know what platform we are running against, but that's only when we are running against vagrant and the subprojects are actually in use. In this case the VMs will have docker as we install it in the Vagrant file, but the host also has to have it to build the image, which our bare metal workers do have, so we are ok to fail, since there's no way to test docker without having it installed.

On the GCP images, we may not have it, so we can't build nor test, anything docker related, so I think we need to keep the same semantics here, avoid pulling in the dependency to build the images and skip the docker related tests ( which we already do ), since this has to do with GCP it's similar to the rest of CI, as in we don't have a way of configuring the platforms that are ok not to have docker, so the only way to implement my earlier suggestion to have a list of platforms where it's ok not to have docker is in CI and it would be similar for every CI job and worker we have, not specific to packaging tests.
I think the easiest way to accomplish this is to skip configuring the distribution altogether in this case, similar to how we deal with docker rest tests.

We don't really care about not having docker on the host running the vagrant tests,
so I don't think we should do anything about it.
As sych the part of the PR that configures the shouldTestDocker ext property should be discarded.

Expand All @@ -208,84 +206,16 @@ class BuildPlugin implements Plugin<Project> {
ext.set('requiresDocker', [])
rootProject.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
final List<String> tasks = taskGraph.allTasks.intersect(ext.get('requiresDocker') as List<Task>).collect { " ${it.path}".toString()}
if (tasks.isEmpty() == false) {
/*
* There are tasks in the task graph that require Docker. Now we are failing because either the Docker binary does not
* exist or because execution of a privileged Docker command failed.
*/
if (dockerBinary == null) {
final String message = String.format(
Locale.ROOT,
"Docker (checked [%s]) is required to run the following task%s: \n%s",
maybeDockerBinaries.join(","),
tasks.size() > 1 ? "s" : "",
tasks.join('\n'))
throwDockerRequiredException(message)
}

// we use a multi-stage Docker build, check the Docker version since 17.05
final ByteArrayOutputStream dockerVersionOutput = new ByteArrayOutputStream()
LoggedExec.exec(
rootProject,
{ ExecSpec it ->
it.commandLine = [dockerBinary, '--version']
it.standardOutput = dockerVersionOutput
})
final String dockerVersion = dockerVersionOutput.toString().trim()
checkDockerVersionRecent(dockerVersion)

final ByteArrayOutputStream dockerImagesErrorOutput = new ByteArrayOutputStream()
// the Docker binary executes, check that we can execute a privileged command
final ExecResult dockerImagesResult = LoggedExec.exec(
rootProject,
{ ExecSpec it ->
it.commandLine = [dockerBinary, "images"]
it.errorOutput = dockerImagesErrorOutput
it.ignoreExitValue = true
})

if (dockerImagesResult.exitValue != 0) {
final String message = String.format(
Locale.ROOT,
"a problem occurred running Docker from [%s] yet it is required to run the following task%s: \n%s\n" +
"the problem is that Docker exited with exit code [%d] with standard error output [%s]",
dockerBinary,
tasks.size() > 1 ? "s" : "",
tasks.join('\n'),
dockerImagesResult.exitValue,
dockerImagesErrorOutput.toString().trim())
throwDockerRequiredException(message)
}

if (tasks.isEmpty() == false) {
assertDockerIsAvailable(task.project, tasks)
}
}
}

(ext.get('requiresDocker') as List<Task>).add(task)
}

protected static void checkDockerVersionRecent(String dockerVersion) {
final Matcher matcher = dockerVersion =~ /Docker version (\d+\.\d+)\.\d+(?:-[a-zA-Z0-9]+)?, build [0-9a-f]{7,40}/
assert matcher.matches(): dockerVersion
final dockerMajorMinorVersion = matcher.group(1)
final String[] majorMinor = dockerMajorMinorVersion.split("\\.")
if (Integer.parseInt(majorMinor[0]) < 17
|| (Integer.parseInt(majorMinor[0]) == 17 && Integer.parseInt(majorMinor[1]) < 5)) {
final String message = String.format(
Locale.ROOT,
"building Docker images requires Docker version 17.05+ due to use of multi-stage builds yet was [%s]",
dockerVersion)
throwDockerRequiredException(message)
}
}

private static void throwDockerRequiredException(final String message) {
throw new GradleException(
message + "\nyou can address this by attending to the reported issue, "
+ "removing the offending tasks from being executed, "
+ "or by passing -Dbuild.docker=false")
}

/** Add a check before gradle execution phase which ensures java home for the given java version is set. */
static void requireJavaHome(Task task, int version) {
// use root project for global accounting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@
import org.elasticsearch.gradle.ElasticsearchDistribution.Type;
import org.elasticsearch.gradle.Jdk;
import org.elasticsearch.gradle.JdkDownloadPlugin;
import org.elasticsearch.gradle.OS;
import org.elasticsearch.gradle.Version;
import org.elasticsearch.gradle.VersionProperties;
import org.elasticsearch.gradle.vagrant.BatsProgressLogger;
import org.elasticsearch.gradle.vagrant.VagrantBasePlugin;
import org.elasticsearch.gradle.vagrant.VagrantExtension;
import org.gradle.api.GradleException;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.Directory;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.plugins.ExtraPropertiesExtension;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.provider.Provider;
Expand All @@ -51,6 +55,7 @@
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand All @@ -65,6 +70,7 @@
import static org.elasticsearch.gradle.vagrant.VagrantMachine.convertWindowsPath;

public class DistroTestPlugin implements Plugin<Project> {
private static final Logger logger = Logging.getLogger(DistroTestPlugin.class);

private static final String SYSTEM_JDK_VERSION = "11.0.2+9";
private static final String SYSTEM_JDK_VENDOR = "openjdk";
Expand All @@ -83,6 +89,8 @@ public class DistroTestPlugin implements Plugin<Project> {

@Override
public void apply(Project project) {
final boolean runDockerTests = shouldRunDockerTests(project);

project.getPluginManager().apply(DistributionDownloadPlugin.class);
project.getPluginManager().apply(BuildPlugin.class);

Expand All @@ -94,15 +102,17 @@ public void apply(Project project) {
Provider<Directory> upgradeDir = project.getLayout().getBuildDirectory().dir("packaging/upgrade");
Provider<Directory> pluginsDir = project.getLayout().getBuildDirectory().dir("packaging/plugins");

List<ElasticsearchDistribution> distributions = configureDistributions(project, upgradeVersion);
List<ElasticsearchDistribution> distributions = configureDistributions(project, upgradeVersion, runDockerTests);
TaskProvider<Copy> copyDistributionsTask = configureCopyDistributionsTask(project, distributionsDir);
TaskProvider<Copy> copyUpgradeTask = configureCopyUpgradeTask(project, upgradeVersion, upgradeDir);
TaskProvider<Copy> copyPluginsTask = configureCopyPluginsTask(project, pluginsDir);

TaskProvider<Task> destructiveDistroTest = project.getTasks().register("destructiveDistroTest");
for (ElasticsearchDistribution distribution : distributions) {
TaskProvider<?> destructiveTask = configureDistroTest(project, distribution);
destructiveDistroTest.configure(t -> t.dependsOn(destructiveTask));
if (distribution.getType() != Type.DOCKER || runDockerTests == true) {
TaskProvider<?> destructiveTask = configureDistroTest(project, distribution);
destructiveDistroTest.configure(t -> t.dependsOn(destructiveTask));
}
}
Map<String, TaskProvider<?>> batsTests = new HashMap<>();
batsTests.put("bats oss", configureBatsTest(project, "oss", distributionsDir, copyDistributionsTask));
Expand All @@ -128,7 +138,18 @@ public void apply(Project project) {
TaskProvider<GradleDistroTestTask> vmTask =
configureVMWrapperTask(vmProject, distribution.getName() + " distribution", destructiveTaskName, vmDependencies);
vmTask.configure(t -> t.dependsOn(distribution));
distroTest.configure(t -> t.dependsOn(vmTask));

distroTest.configure(t -> {
// Only VM sub-projects that are specifically opted-in to testing Docker should
// have the Docker task added as a dependency. The shouldTestDocker property could
// be null, hence we use Boolean.TRUE.equals()
boolean shouldExecute = distribution.getType() != Type.DOCKER
Copy link
Contributor

Choose a reason for hiding this comment

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

The typical way to go about this is to register an Gradle extension on the project where the project could provide additional configuration, like weather or not to test on docker.

Aslo, I think we should specifically opt-put instead of opt in as most platforms support it and future platforms are expected to support it.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is no longer applicable, see my earlier comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure what earlier comment you are referring to @atorok.

Also, I think this is going to have to go in an afterevaluate { } block to ensure that property has been evaluated.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was referring to this one: #47640 (comment) didn't realize GH will put it after not before.

My point is that we don't need to bother with docker support for the subprojects for when docker is not available in the Vagrant VM ( which is when these are actually used ) . The tests are skipped when there's no docker and there is no need to build an image inside the VM, so we're all good. Not having docker on the host that runs vagrant is ok to error out.

|| Boolean.TRUE.equals(vmProject.findProperty("shouldTestDocker")) == true;

if (shouldExecute) {
t.dependsOn(vmTask);
}
});
}
}

Expand Down Expand Up @@ -321,17 +342,17 @@ private static TaskProvider<BatsTestTask> configureBatsTest(Project project, Str
});
}

private List<ElasticsearchDistribution> configureDistributions(Project project, Version upgradeVersion) {
private List<ElasticsearchDistribution> configureDistributions(Project project, Version upgradeVersion, boolean runDockerTests) {
NamedDomainObjectContainer<ElasticsearchDistribution> distributions = DistributionDownloadPlugin.getContainer(project);
List<ElasticsearchDistribution> currentDistros = new ArrayList<>();
List<ElasticsearchDistribution> upgradeDistros = new ArrayList<>();

// Docker disabled for https://github.com/elastic/elasticsearch/issues/47639
for (Type type : Arrays.asList(Type.DEB, Type.RPM /*,Type.DOCKER*/)) {
for (Type type : List.of(Type.DEB, Type.RPM, Type.DOCKER)) {
for (Flavor flavor : Flavor.values()) {
for (boolean bundledJdk : Arrays.asList(true, false)) {
// We should never add a Docker distro with bundledJdk == false
boolean skip = type == Type.DOCKER && bundledJdk == false;
// All our Docker images include a bundled JDK so it doesn't make sense to test without one
boolean skip = type == Type.DOCKER && (runDockerTests == false || bundledJdk == false);

if (skip == false) {
addDistro(distributions, type, null, flavor, bundledJdk, VersionProperties.getElasticsearch(), currentDistros);
}
Expand All @@ -345,6 +366,7 @@ private List<ElasticsearchDistribution> configureDistributions(Project project,
addDistro(distributions, type, null, Flavor.OSS, true, upgradeVersion.toString(), upgradeDistros);
}
}

for (Platform platform : Arrays.asList(Platform.LINUX, Platform.WINDOWS)) {
for (Flavor flavor : Flavor.values()) {
for (boolean bundledJdk : Arrays.asList(true, false)) {
Expand Down Expand Up @@ -405,4 +427,98 @@ private static String destructiveDistroTestTaskName(ElasticsearchDistribution di
distro.getFlavor(),
distro.getBundledJdk());
}

static Map<String, String> parseOsRelease(final List<String> osReleaseLines) {
final Map<String, String> values = new HashMap<>();

for (String line : osReleaseLines) {
final String trimmed = line.trim();

// ignore empty and comment lines
if (trimmed.isEmpty() || trimmed.startsWith("#")) {
continue;
}

final String[] parts = line.split("=", 2);
final String key = parts[0];
// remove optional leading and trailing quotes and whitespace
final String value = parts[1].replaceAll("^['\"]?\\s*", "").replaceAll("\\s*['\"]?$", "");
values.put(key, value);
}

return values;
}

static String deriveId(final Map<String, String> osRelease) {
return osRelease.get("ID") + "-" + osRelease.get("VERSION_ID");
}

private static List<String> getLinuxExclusionList(Project project) {
final String exclusionsFilename = "dockerOnLinuxExclusions";
final Path exclusionsPath = project.getRootDir().toPath().resolve(Path.of(".ci", exclusionsFilename));

try {
return Files.readAllLines(exclusionsPath)
.stream()
.map(String::trim)
.filter(line -> line.startsWith("#"))
.collect(Collectors.toList());
} catch (IOException e) {
throw new GradleException("Failed to read .ci/" + exclusionsFilename, e);
}
}

/**
* The {@link DistroTestPlugin} generates a number of test tasks, some
* of which are Docker packaging tests. When running on the host OS or in CI
* i.e. not in a Vagrant VM, only certain operating systems are supported. This
* method determines whether the Docker tests should be run on the host
* OS. Essentially, unless an OS and version is specifically excluded, we expect
* to be able to run Docker and test the Docker images.
* @param project
*/
private static boolean shouldRunDockerTests(Project project) {
switch (OS.current()) {
case WINDOWS:
// Not yet supported.
return false;

case MAC:
// Assume that Docker for Mac is installed, since Docker is part of the dev workflow.
return true;

case LINUX:
// Only some hosts in CI are configured with Docker. We attempt to work out the OS
// and version, so that we know whether to expect to find Docker. We don't attempt
// to probe for whether Docker is available, because that doesn't tell us whether
// Docker is unavailable when it should be.
final Path osRelease = Paths.get("/etc/os-release");

if (Files.exists(osRelease)) {
Map<String, String> values;

try {
final List<String> osReleaseLines = Files.readAllLines(osRelease);
values = parseOsRelease(osReleaseLines);
} catch (IOException e) {
throw new GradleException("Failed to read /etc/os-release", e);
}

final String id = deriveId(values);

final boolean shouldExclude = getLinuxExclusionList(project).contains(id);

logger.info("Linux OS id [" + id + "] is " + (shouldExclude ? "" : "not ") + "present in the exclude list");

return shouldExclude == false;
}

logger.warn("/etc/os-release does not exist!");
return false;

default:
logger.warn("Unknown OS [" + OS.current() + "], answering false to shouldRunDockerTests()");
return false;
}
}
}
Loading