Skip to content
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
11 changes: 11 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 @@ -115,6 +115,17 @@ public class DockerFlags implements HasRoles {
example = "[\"/dev/kvm:/dev/kvm\"]")
private List<String> devices;

@Parameter(
names = {"--docker-grouping-labels"},
description =
"Users to specify custom labels for grouping dynamic containers. This will make the"
+ " system more flexible for different platforms and use cases")
@ConfigValue(
section = DockerOptions.DOCKER_SECTION,
name = "grouping-labels",
example = "[\"azure.container.group\", \"aws.ecs.cluster\"]")
private List<String> groupingLabels;

@Parameter(
names = {"--docker-video-image"},
description = "Docker image to be used when video recording is enabled")
Expand Down
20 changes: 15 additions & 5 deletions java/src/org/openqa/selenium/grid/node/docker/DockerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
Expand Down Expand Up @@ -174,7 +176,7 @@ public Map<Capabilities, Collection<SessionFactory>> getDockerSessionFactories(
DockerAssetsPath assetsPath = getAssetsPath(info);
String networkName = getDockerNetworkName(info);
Map<String, Object> hostConfig = getDockerHostConfig(info);
Map<String, String> composeLabels = getComposeLabels(info);
Map<String, String> groupingLabels = getGroupingLabels(info);

loadImages(docker, kinds.keySet().toArray(new String[0]));
Image videoImage = getVideoImage(docker);
Expand Down Expand Up @@ -211,7 +213,7 @@ public Map<Capabilities, Collection<SessionFactory>> getDockerSessionFactories(
capabilities -> options.getSlotMatcher().matches(caps, capabilities),
hostConfig,
hostConfigKeys,
composeLabels));
groupingLabels));
}
LOG.info(
String.format(
Expand Down Expand Up @@ -261,15 +263,23 @@ private Map<String, Object> getDockerHostConfig(Optional<ContainerInfo> info) {
}

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private Map<String, String> getComposeLabels(Optional<ContainerInfo> info) {
private Map<String, String> getGroupingLabels(Optional<ContainerInfo> info) {
if (info.isEmpty()) {
return Collections.emptyMap();
}

// Get custom grouping labels from configuration
List<String> customLabelKeys =
config.getAll(DOCKER_SECTION, "grouping-labels").orElseGet(Collections::emptyList);

Set<String> groupingKeys = new HashSet<>(customLabelKeys);
groupingKeys.add("com.docker.compose.project");
groupingKeys.add("io.podman.compose.project");

Map<String, String> allLabels = info.get().getLabels();
// Filter for Docker Compose labels (com.docker.compose.*)
// Filter for grouping labels that work across orchestration systems
return allLabels.entrySet().stream()
.filter(entry -> entry.getKey().startsWith("com.docker.compose."))
.filter(entry -> groupingKeys.contains(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public class DockerSessionFactory implements SessionFactory {
private final Predicate<Capabilities> predicate;
private final Map<String, Object> hostConfig;
private final List<String> hostConfigKeys;
private final Map<String, String> composeLabels;
private final Map<String, String> groupingLabels;

public DockerSessionFactory(
Tracer tracer,
Expand All @@ -124,7 +124,7 @@ public DockerSessionFactory(
Predicate<Capabilities> predicate,
Map<String, Object> hostConfig,
List<String> hostConfigKeys,
Map<String, String> composeLabels) {
Map<String, String> groupingLabels) {
this.tracer = Require.nonNull("Tracer", tracer);
this.clientFactory = Require.nonNull("HTTP client", clientFactory);
this.sessionTimeout = Require.nonNull("Session timeout", sessionTimeout);
Expand All @@ -141,11 +141,7 @@ public DockerSessionFactory(
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);
// Merge compose labels with oneoff=False to prevent triggering --exit-code-from dynamic grid
Map<String, String> allLabels =
new HashMap<>(Require.nonNull("Docker Compose labels", composeLabels));
allLabels.put("com.docker.compose.oneoff", "False");
this.composeLabels = Collections.unmodifiableMap(allLabels);
this.groupingLabels = Require.nonNull("Container grouping labels", groupingLabels);
}

@Override
Expand Down Expand Up @@ -332,7 +328,7 @@ private Container createBrowserContainer(
.network(networkName)
.devices(devices)
.applyHostConfig(hostConfig, hostConfigKeys)
.labels(composeLabels)
.labels(groupingLabels)
.name(containerName);
Optional<DockerAssetsPath> path = ofNullable(this.assetsPath);
if (path.isPresent() && videoImage == null && recordVideoForSession(sessionCapabilities)) {
Expand Down Expand Up @@ -397,7 +393,7 @@ private Container startVideoContainer(
.env(envVars)
.bind(volumeBinds)
.network(networkName)
.labels(composeLabels)
.labels(groupingLabels)
.name(containerName);
if (!runningInDocker) {
videoPort = PortProber.findFreePort();
Expand Down