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

[grid][java] browser containers provisioned in dynamic grid can get hostconfig from node-docker #13804

Merged
merged 3 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions java/src/org/openqa/selenium/docker/ContainerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand All @@ -42,6 +43,7 @@ public class ContainerConfig {
private final String networkName;
private final boolean autoRemove;
private final long shmSize;
private final Map<String, Object> hostConfig;

public ContainerConfig(
Image image,
Expand All @@ -51,6 +53,26 @@ public ContainerConfig(
List<Device> devices,
String networkName,
long shmSize) {
this(
image,
portBindings,
envVars,
volumeBinds,
devices,
networkName,
shmSize,
ImmutableMap.of());
}

public ContainerConfig(
Image image,
Multimap<String, Map<String, Object>> portBindings,
Map<String, String> envVars,
Map<String, String> volumeBinds,
List<Device> devices,
String networkName,
long shmSize,
Map<String, Object> hostConfig) {
this.image = image;
this.portBindings = portBindings;
this.envVars = envVars;
Expand All @@ -59,6 +81,7 @@ public ContainerConfig(
this.networkName = networkName;
this.autoRemove = true;
this.shmSize = shmSize;
this.hostConfig = hostConfig;
}

public static ContainerConfig image(Image image) {
Expand Down Expand Up @@ -123,6 +146,17 @@ public ContainerConfig devices(List<Device> devices) {
image, portBindings, envVars, volumeBinds, devices, networkName, shmSize);
}

public ContainerConfig applyHostConfig(Map<String, Object> hostConfig, List<String> configKeys) {
Map<String, Object> setHostConfig =
configKeys.stream()
.filter(hostConfig::containsKey)
.filter(key -> hostConfig.get(key) != null)
.collect(Collectors.toMap(key -> key, hostConfig::get));

return new ContainerConfig(
image, portBindings, envVars, volumeBinds, devices, networkName, shmSize, setHostConfig);
}

@Override
public String toString() {
return "ContainerConfig{"
Expand All @@ -142,6 +176,8 @@ public String toString() {
+ autoRemove
+ ", shmSize="
+ shmSize
+ ", hostConfig="
+ hostConfig
+ '}';
}

Expand Down Expand Up @@ -175,6 +211,12 @@ private Map<String, Object> toJson() {
"Binds", volumeBinds,
"Devices", devicesMapping);

if (!this.hostConfig.isEmpty()) {
Map<String, Object> copyMap = new HashMap<>(hostConfig);
copyMap.putAll(this.hostConfig);
hostConfig = ImmutableMap.copyOf(copyMap);
}

return ImmutableMap.of(
"Image", image.getId(),
"Env", envVars,
Expand Down
12 changes: 11 additions & 1 deletion java/src/org/openqa/selenium/docker/ContainerInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,19 @@ public class ContainerInfo {
private final ContainerId id;
private final List<Map<String, Object>> mountedVolumes;
private final String networkName;
private Map<String, Object> hostConfig;

public ContainerInfo(
ContainerId id, String ip, List<Map<String, Object>> mountedVolumes, String networkName) {
ContainerId id,
String ip,
List<Map<String, Object>> mountedVolumes,
String networkName,
Map<String, Object> hostConfig) {
this.ip = Require.nonNull("Container ip address", ip);
this.id = Require.nonNull("Container id", id);
this.mountedVolumes = Require.nonNull("Mounted volumes", mountedVolumes);
this.networkName = Require.nonNull("Network name", networkName);
this.hostConfig = Require.nonNull("Host config", hostConfig);
}

public String getIp() {
Expand All @@ -54,6 +60,10 @@ public String getNetworkName() {
return networkName;
}

public Map<String, Object> getHostConfig() {
return this.hostConfig;
}

@Override
public String toString() {
return "ContainerInfo{"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static org.openqa.selenium.remote.http.HttpMethod.GET;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
Expand Down Expand Up @@ -67,7 +68,9 @@ public ContainerInfo apply(ContainerId id) {
ArrayList<Object> mounts = (ArrayList<Object>) rawInspectInfo.get("Mounts");
List<Map<String, Object>> mountedVolumes =
mounts.stream().map(mount -> (Map<String, Object>) mount).collect(Collectors.toList());
Map<String, Object> hostConfig =
(Map<String, Object>) rawInspectInfo.getOrDefault("HostConfig", Collections.emptyMap());

return new ContainerInfo(id, ip, mountedVolumes, networkName);
return new ContainerInfo(id, ip, mountedVolumes, networkName, hostConfig);
}
}
12 changes: 12 additions & 0 deletions java/src/org/openqa/selenium/grid/node/docker/DockerFlags.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ public class DockerFlags implements HasRoles {
"[\"selenium/standalone-firefox:latest\", \"{\\\"browserName\\\": \\\"firefox\\\"}\"]")
private List<String> images2Capabilities;

@Parameter(
names = {"--docker-host-config-keys"},
description =
"Specify which docker host configuration keys should be passed to browser containers."
+ " Keys name can be found in the Docker API documentation, or by running `docker"
+ " inspect` the node-docker container.")
@ConfigValue(
section = DockerOptions.DOCKER_SECTION,
name = "host-config-keys",
example = "[\"Dns\", \"DnsOptions\", \"DnsSearch\", \"ExtraHosts\", \"Binds\"]")
private List<String> hostConfigKeys;

@Parameter(
names = {"--docker-devices"},
description =
Expand Down
13 changes: 12 additions & 1 deletion java/src/org/openqa/selenium/grid/node/docker/DockerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ public Map<Capabilities, Collection<SessionFactory>> getDockerSessionFactories(
.getAll(DOCKER_SECTION, "configs")
.orElseThrow(() -> new DockerException("Unable to find docker configs"));

List<String> hostConfigKeys =
config.getAll(DOCKER_SECTION, "host-config-keys").orElseGet(Collections::emptyList);

Multimap<String, Capabilities> kinds = HashMultimap.create();
for (int i = 0; i < allConfigs.size(); i++) {
String imageName = allConfigs.get(i);
Expand All @@ -152,6 +155,7 @@ public Map<Capabilities, Collection<SessionFactory>> getDockerSessionFactories(

DockerAssetsPath assetsPath = getAssetsPath(info);
String networkName = getDockerNetworkName(info);
Map<String, Object> hostConfig = getDockerHostConfig(info);

loadImages(docker, kinds.keySet().toArray(new String[0]));
Image videoImage = getVideoImage(docker);
Expand Down Expand Up @@ -182,7 +186,9 @@ public Map<Capabilities, Collection<SessionFactory>> getDockerSessionFactories(
assetsPath,
networkName,
info.isPresent(),
capabilities -> options.getSlotMatcher().matches(caps, capabilities)));
capabilities -> options.getSlotMatcher().matches(caps, capabilities),
hostConfig,
hostConfigKeys));
}
LOG.info(
String.format(
Expand Down Expand Up @@ -229,6 +235,11 @@ private String getDockerNetworkName(Optional<ContainerInfo> info) {
return DEFAULT_DOCKER_NETWORK;
}

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private Map<String, Object> getDockerHostConfig(Optional<ContainerInfo> info) {
return info.map(ContainerInfo::getHostConfig).orElse(Collections.emptyMap());
}

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private DockerAssetsPath getAssetsPath(Optional<ContainerInfo> info) {
if (info.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public class DockerSessionFactory implements SessionFactory {
private final String networkName;
private final boolean runningInDocker;
private final Predicate<Capabilities> predicate;
private final Map<String, Object> hostConfig;
private final List<String> hostConfigKeys;

public DockerSessionFactory(
Tracer tracer,
Expand All @@ -115,7 +117,9 @@ public DockerSessionFactory(
DockerAssetsPath assetsPath,
String networkName,
boolean runningInDocker,
Predicate<Capabilities> predicate) {
Predicate<Capabilities> predicate,
Map<String, Object> hostConfig,
List<String> hostConfigKeys) {
this.tracer = Require.nonNull("Tracer", tracer);
this.clientFactory = Require.nonNull("HTTP client", clientFactory);
this.sessionTimeout = Require.nonNull("Session timeout", sessionTimeout);
Expand All @@ -129,6 +133,8 @@ public DockerSessionFactory(
this.assetsPath = assetsPath;
this.runningInDocker = runningInDocker;
this.predicate = Require.nonNull("Accepted capabilities predicate", predicate);
this.hostConfig = Require.nonNull("Container host config", hostConfig);
this.hostConfigKeys = Require.nonNull("Browser container host config keys", hostConfigKeys);
}

@Override
Expand Down Expand Up @@ -285,10 +291,12 @@ private Container createBrowserContainer(int port, Capabilities sessionCapabilit
.env(browserContainerEnvVars)
.shmMemorySize(browserContainerShmMemorySize)
.network(networkName)
.devices(devices);
.devices(devices)
.applyHostConfig(hostConfig, hostConfigKeys);
if (!runningInDocker) {
containerConfig = containerConfig.map(Port.tcp(4444), Port.tcp(port));
}
LOG.fine("Container config: " + containerConfig);
return docker.create(containerConfig);
}

Expand Down
Loading