Skip to content

Commit

Permalink
Merge branch 'main' into logging
Browse files Browse the repository at this point in the history
  • Loading branch information
jjiwooLim committed Sep 22, 2023
2 parents 876ffb7 + 79f69e4 commit a9f7920
Show file tree
Hide file tree
Showing 9 changed files with 545 additions and 428 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.project
.settings
target
.DS_Store

# Compiled class file
*.class
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/**
* (C) Copyright IBM Corporation 2020, 2023.
*
* Licensed 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 io.openliberty.tools.common.plugins.util;

import java.io.BufferedReader;
Expand All @@ -7,6 +23,14 @@

public abstract class AbstractContainerSupportUtil {

private static final String CONTAINER_DOCKER_PREFIX = "docker ";
private static final String CONTAINER_PODMAN_PREFIX = "podman ";

protected static final int CONTAINER_TIMEOUT = 20; // seconds

private boolean checkedContainerType = false;
protected boolean isDocker = true;

/**
* Log debug
* @param msg
Expand All @@ -21,21 +45,77 @@ public abstract class AbstractContainerSupportUtil {
*/
public abstract void error(String msg, Throwable e);

/**
* Log info
* @param msg
*/
public abstract void info(String msg);

protected String getContainerCommandPrefix() throws PluginExecutionException {
if (!checkedContainerType) {
checkDockerVersion();
}

return isDocker ? CONTAINER_DOCKER_PREFIX : CONTAINER_PODMAN_PREFIX;
}

/**
* Retrieve the current docker version and compare to a known value.
* The Maven class ComparableVersion allows for numbers, letters and certain words.
* Throw an exception if there is a problem with the version.
*/
private static final String MIN_DOCKER_VERSION = "18.03.0"; // Must use Docker 18.03.0 or higher
protected void checkDockerVersion() throws PluginExecutionException {
String versionCmd = "docker version --format {{.Client.Version}}";
String dockerVersion = execContainerCmd(versionCmd, CONTAINER_TIMEOUT);
if (dockerVersion == null) {
checkPodmanVersion(); // Check Podman version if no Docker
return;
}
debug("Detected Docker version: " + dockerVersion);

if (VersionUtility.compareArtifactVersion(dockerVersion, MIN_DOCKER_VERSION, false) < 0) {
checkPodmanVersion(); // Check that bad Docker version isn't just a Podman version
if (!isDocker) {
return;
}
throw new PluginExecutionException("The detected Docker client version number is not supported:" + dockerVersion.trim() + ". Docker version must be " + MIN_DOCKER_VERSION + " or higher.");
}
isDocker = true;
checkedContainerType = true;
}

private static final String MIN_PODMAN_VERSION = "4.4.4"; // Must use Docker 4.4.4 or higher
private void checkPodmanVersion() throws PluginExecutionException {
String versionCmd = "podman version --format {{.Client.Version}}";
String podmanVersion = execContainerCmd(versionCmd, CONTAINER_TIMEOUT);
if (podmanVersion == null) {
return; // Can't tell if the version is valid.
}
debug("Detected Podman version: " + podmanVersion);

if (VersionUtility.compareArtifactVersion(podmanVersion, MIN_PODMAN_VERSION, false) < 0) {
throw new PluginExecutionException("The detected Podman client version number is not supported:" + podmanVersion.trim() + ". Podman version must be " + MIN_PODMAN_VERSION + " or higher.");
}
isDocker = false;
checkedContainerType = true;
}

/**
* @param timeout unit is seconds
* @return the stdout of the command or null for no output on stdout
*/
protected String execDockerCmd(String command, int timeout, boolean throwExceptionOnError) {
protected String execContainerCmd(String command, int timeout, boolean throwExceptionOnError) {
String result = null;
try {
debug("execDocker, timeout=" + timeout + ", cmd=" + command);
debug("execContainer, timeout=" + timeout + ", cmd=" + command);
Process p = Runtime.getRuntime().exec(command);

p.waitFor(timeout, TimeUnit.SECONDS);

// After waiting for the process, handle the error case and normal termination.
if (p.exitValue() != 0) {
debug("Error running docker command, return value="+p.exitValue());
debug("Error running container command, return value="+p.exitValue());
// read messages from standard err
char[] d = new char[1023];
new InputStreamReader(p.getErrorStream()).read(d);
Expand All @@ -48,22 +128,40 @@ protected String execDockerCmd(String command, int timeout, boolean throwExcepti
}
result = readStdOut(p);
} catch (IllegalThreadStateException e) {
// the timeout was too short and the docker command has not yet completed. There is no exit value.
// the timeout was too short and the container command has not yet completed. There is no exit value.
debug("IllegalThreadStateException, message="+e.getMessage());
error("The docker command did not complete within the timeout period: " + timeout + " seconds.", e);
throw new RuntimeException("The docker command did not complete within the timeout period: " + timeout + " seconds. ");
error("The container command did not complete within the timeout period: " + timeout + " seconds.", e);
throw new RuntimeException("The container command did not complete within the timeout period: " + timeout + " seconds. ");
} catch (InterruptedException e) {
// If a runtime exception occurred in the server task, log and rethrow
error("An interruption error occurred while running a docker command: " + e.getMessage(), e);
error("An interruption error occurred while running a container command: " + e.getMessage(), e);
throw new RuntimeException(e.getMessage());
} catch (IOException e) {
// If a runtime exception occurred in the server task, log and rethrow
error("An error occurred while running a docker command: " + e.getMessage(), e);
throw new RuntimeException(e.getMessage());
// Logging IOExceptions in info stream. This is thrown if Docker or Podman are not installed on the system.
info("An error occurred while running a container command: " + e.getMessage());
info("This message will occur when Docker or Podman are not installed.");
}
return result;
}

protected String execContainerCmd(String command, int timeout) {
return execContainerCmd(command, timeout, true);
}

protected String execContainerCmdWithPrefix(String command, int timeout) {
return execContainerCmdWithPrefix(command, timeout, true);
}

protected String execContainerCmdWithPrefix(String command, int timeout, boolean throwExceptionOnError) {
try {
String containerCommand = getContainerCommandPrefix() + " " + command;
return execContainerCmd(containerCommand, timeout, throwExceptionOnError);
} catch (PluginExecutionException pe) {
error("Error while determining container command prefix.", pe);
return pe.getMessage();
}
}

protected String readStdOut(Process p) throws IOException, InterruptedException {
String result = null;
// Read all the output on stdout and return it to the caller
Expand Down
Loading

0 comments on commit a9f7920

Please sign in to comment.