Skip to content

Commit

Permalink
[docker] Containers may not always be present
Browse files Browse the repository at this point in the history
  • Loading branch information
shs96c committed Feb 22, 2021
1 parent 1060b98 commit 6f92e8a
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 6 deletions.
10 changes: 7 additions & 3 deletions java/server/src/org/openqa/selenium/docker/Docker.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,18 @@ public Container create(ContainerConfig config) {
.orElseThrow(() -> new DockerException("Unable to create container: " + config));
}

public ContainerInfo inspect(ContainerId id) {
public Optional<ContainerInfo> inspect(ContainerId id) {
Require.nonNull("Container id", id);

LOG.info("Inspecting container with id: " + id);

return getDocker()
if (!getDocker().map(protocol -> protocol.isContainerPresent(id)).orElse(false)) {
return Optional.empty();
}

return Optional.of(getDocker()
.map(protocol -> protocol.inspectContainer(id))
.orElseThrow(() -> new DockerException("Unable to inspect container: " + id));
.orElseThrow(() -> new DockerException("Unable to inspect container: " + id)));
}

private Optional<DockerProtocol> getDocker() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface DockerProtocol {

Container create(ContainerConfig info);
void startContainer(ContainerId id) throws DockerException;
boolean isContainerPresent(ContainerId id) throws DockerException;
void stopContainer(ContainerId id, Duration timeout) throws DockerException;
ContainerInfo inspectContainer(ContainerId id) throws DockerException;
ContainerLogs getContainerLogs(ContainerId id) throws DockerException;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC 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.openqa.selenium.docker.v1_40;

import org.openqa.selenium.docker.ContainerId;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.HttpHandler;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;

import static org.openqa.selenium.remote.http.HttpMethod.GET;

class IsContainerPresent {
private final HttpHandler client;

public IsContainerPresent(HttpHandler client) {
this.client = Require.nonNull("Http client", client);
}

public boolean apply(ContainerId id) {
Require.nonNull("Container id", id);

HttpResponse res = client.execute(
new HttpRequest(GET, String.format("/v1.40/containers/%s/json", id))
.addHeader("Content-Length", "0")
.addHeader("Content-Type", "text/plain"));

return res.isSuccessful();
}
}
11 changes: 11 additions & 0 deletions java/server/src/org/openqa/selenium/docker/v1_40/V140Docker.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class V140Docker implements DockerProtocol {
private final CreateContainer createContainer;
private final StartContainer startContainer;
private final StopContainer stopContainer;
private final IsContainerPresent isContainerPresent;
private final InspectContainer inspectContainer;
private final GetContainerLogs containerLogs;

Expand All @@ -52,6 +53,7 @@ public V140Docker(HttpHandler client) {
createContainer = new CreateContainer(this, client);
startContainer = new StartContainer(client);
stopContainer = new StopContainer(client);
isContainerPresent = new IsContainerPresent(client);
inspectContainer = new InspectContainer(client);
containerLogs = new GetContainerLogs(client);
}
Expand Down Expand Up @@ -94,6 +96,15 @@ public Container create(ContainerConfig config) {
return createContainer.apply(config);
}

@Override
public boolean isContainerPresent(ContainerId id) throws DockerException {
Require.nonNull("Container id", id);

LOG.info("Checking if container is present: " + id);

return isContainerPresent.apply(id);
}

@Override
public void startContainer(ContainerId id) throws DockerException {
Require.nonNull("Container id", id);
Expand Down
14 changes: 11 additions & 3 deletions java/server/src/org/openqa/selenium/grid/docker/DockerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.openqa.selenium.grid.node.SessionFactory;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.json.Json;
import org.openqa.selenium.net.HostIdentifier;
import org.openqa.selenium.remote.http.ClientConfig;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.tracing.Tracer;
Expand Down Expand Up @@ -179,18 +180,25 @@ private DockerAssetsPath getAssetsPath(Docker docker) {
// Selenium Server is running inside a Docker container, we will inspect that container
// to get the mounted volume and use that. If no volume was mounted, no assets will be saved.
// Since Docker 1.12, the env var HOSTNAME has the container id (unless the user overwrites it)
String hostname = System.getenv("HOSTNAME");
ContainerInfo info = docker.inspect(new ContainerId(hostname));
Optional<Map<String, Object>> mountedVolume = info.getMountedVolumes()
String hostname = HostIdentifier.getHostName();

Optional<ContainerInfo> info = docker.inspect(new ContainerId(hostname));
if (!info.isPresent()) {
return null;
}

Optional<Map<String, Object>> mountedVolume = info.get().getMountedVolumes()
.stream()
.filter(
mounted ->
CONTAINER_ASSETS_PATH.equalsIgnoreCase(String.valueOf(mounted.get("Destination"))))
.findFirst();

if (mountedVolume.isPresent()) {
String hostPath = String.valueOf(mountedVolume.get().get("Source"));
return new DockerAssetsPath(hostPath, CONTAINER_ASSETS_PATH);
}

return null;
}

Expand Down

0 comments on commit 6f92e8a

Please sign in to comment.