Skip to content

Commit 293c890

Browse files
authored
new inspect image tool (#261)
1 parent 3f259c7 commit 293c890

File tree

10 files changed

+253
-36
lines changed

10 files changed

+253
-36
lines changed

imagetool/src/main/java/com/oracle/weblogic/imagetool/cli/ImageTool.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.oracle.weblogic.imagetool.api.model.CommandResponse;
1010
import com.oracle.weblogic.imagetool.cli.cache.CacheCLI;
1111
import com.oracle.weblogic.imagetool.cli.menu.CreateImage;
12+
import com.oracle.weblogic.imagetool.cli.menu.InspectImage;
1213
import com.oracle.weblogic.imagetool.cli.menu.RebaseImage;
1314
import com.oracle.weblogic.imagetool.cli.menu.UpdateImage;
1415
import com.oracle.weblogic.imagetool.logging.LoggingFacade;
@@ -29,6 +30,7 @@
2930
CreateImage.class,
3031
UpdateImage.class,
3132
RebaseImage.class,
33+
InspectImage.class,
3234
HelpCommand.class
3335
},
3436
requiredOptionMarker = '*',

imagetool/src/main/java/com/oracle/weblogic/imagetool/cli/menu/CommonOptions.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,8 @@ public void copyOptionsFromImage(String fromImage, String tmpDir) throws IOExcep
356356
logger.finer("IMG-0002", fromImage);
357357
dockerfileOptions.setBaseImage(fromImage);
358358

359-
Utils.copyResourceAsFile("/probe-env/test-create-env.sh",
360-
tmpDir + File.separator + "test-env.sh", true);
361-
362-
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, fromImage, tmpDir);
359+
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, fromImage,
360+
"/probe-env/test-create-env.sh", tmpDir);
363361

364362
if (baseImageProperties.getProperty("WLS_VERSION", null) != null) {
365363
throw new IllegalArgumentException(Utils.getMessage("IMG-0038", fromImage,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright (c) 2021, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
package com.oracle.weblogic.imagetool.cli.menu;
5+
6+
import java.io.BufferedWriter;
7+
import java.io.OutputStreamWriter;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
import java.nio.file.Paths;
11+
import java.util.Map;
12+
import java.util.Properties;
13+
import java.util.TreeMap;
14+
import java.util.concurrent.Callable;
15+
16+
import com.github.mustachejava.DefaultMustacheFactory;
17+
import com.github.mustachejava.Mustache;
18+
import com.github.mustachejava.MustacheFactory;
19+
import com.github.mustachejava.util.DecoratedCollection;
20+
import com.oracle.weblogic.imagetool.api.model.CommandResponse;
21+
import com.oracle.weblogic.imagetool.util.Utils;
22+
import picocli.CommandLine;
23+
24+
@CommandLine.Command(
25+
name = "inspect",
26+
description = "Inspect an image created by this tool",
27+
requiredOptionMarker = '*',
28+
abbreviateSynopsis = true
29+
)
30+
public class InspectImage implements Callable<CommandResponse> {
31+
@Override
32+
public CommandResponse call() throws Exception {
33+
Path tmpDir = Files.createTempDirectory(Paths.get(Utils.getBuildWorkingDir()), "wlsimgbuilder_temp");
34+
String tempDirectory = tmpDir.toAbsolutePath().toString();
35+
36+
String scriptToRun = "/probe-env/inspect-image.sh";
37+
// add additional formats here, the ENUM, and to the resources/inspect-responses folder
38+
if (listPatches) {
39+
scriptToRun = "/probe-env/inspect-image-long.sh";
40+
}
41+
42+
Properties baseImageProperties =
43+
Utils.getBaseImageProperties(buildEngine, imageName, scriptToRun, tempDirectory);
44+
MustacheFactory mf = new DefaultMustacheFactory("inspect-responses");
45+
46+
String outputTemplate;
47+
// add additional formats here, the ENUM, and to the resources/inspect-responses folder
48+
switch (ouptutFormat) {
49+
case JSON:
50+
default:
51+
outputTemplate = "inspect-json.mustache";
52+
}
53+
Mustache mustache = mf.compile(outputTemplate);
54+
55+
// sort the output alphabetically for easier readability
56+
TreeMap<String,String> sortedSet = new TreeMap<>();
57+
for (Map.Entry<Object,Object> x: baseImageProperties.entrySet()) {
58+
sortedSet.put(x.getKey().toString(), x.getValue().toString());
59+
}
60+
61+
try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out))) {
62+
// create a decorated collection so that the output template can utilize "last" (last collection item)
63+
mustache.execute(out, new Object() {
64+
@SuppressWarnings("unused")
65+
final DecoratedCollection<Map.Entry<String, String>> response =
66+
new DecoratedCollection<>(sortedSet.entrySet());
67+
}).flush();
68+
}
69+
return new CommandResponse(0, "");
70+
}
71+
72+
@CommandLine.Option(
73+
names = {"--image", "-i"},
74+
required = true,
75+
paramLabel = "IMAGE:ID",
76+
description = "Image ID or image name to be inspected"
77+
)
78+
private String imageName;
79+
80+
@CommandLine.Option(
81+
names = {"--builder", "-b"},
82+
description = "Executable to inspect docker images. Default: ${DEFAULT-VALUE}"
83+
)
84+
String buildEngine = "docker";
85+
86+
@CommandLine.Option(
87+
names = {"--patches"},
88+
description = "Include OPatch information in the output, including a list of patches applied.",
89+
defaultValue = "false"
90+
)
91+
private boolean listPatches;
92+
93+
@CommandLine.Option(
94+
names = {"--format"},
95+
paramLabel = "FORMAT",
96+
description = "Output format. Supported values: ${COMPLETION-CANDIDATES} Default: ${DEFAULT-VALUE}",
97+
defaultValue = "JSON"
98+
)
99+
private OutputFormat ouptutFormat;
100+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2021, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
package com.oracle.weblogic.imagetool.cli.menu;
5+
6+
public enum OutputFormat {
7+
JSON
8+
}

imagetool/src/main/java/com/oracle/weblogic/imagetool/cli/menu/RebaseImage.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,9 @@ public CommandResponse call() throws Exception {
6565
logger.finer("IMG-0002", sourceImage);
6666
dockerfileOptions.setSourceImage(sourceImage);
6767

68-
// Get source image
69-
Utils.copyResourceAsFile("/probe-env/test-update-env.sh",
70-
tmpDir + File.separator + "test-env.sh", true);
71-
7268
logger.info("IMG-0091", sourceImage);
73-
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, sourceImage, tmpDir);
69+
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, sourceImage,
70+
"/probe-env/test-update-env.sh", tmpDir);
7471

7572
oldOracleHome = baseImageProperties.getProperty("ORACLE_HOME", null);
7673
oldJavaHome = baseImageProperties.getProperty("JAVA_PATH", null);
@@ -85,11 +82,9 @@ public CommandResponse call() throws Exception {
8582
logger.finer("IMG-0002", targetImage);
8683
dockerfileOptions.setTargetImage(targetImage);
8784
dockerfileOptions.setRebaseToTarget(true);
88-
// Get source image
89-
Utils.copyResourceAsFile("/probe-env/test-update-env.sh",
90-
tmpDir + File.separator + "test-env.sh", true);
9185

92-
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, targetImage, tmpDir);
86+
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, targetImage,
87+
"/probe-env/test-update-env.sh", tmpDir);
9388

9489
newOracleHome = baseImageProperties.getProperty("ORACLE_HOME", null);
9590
newJavaHome = baseImageProperties.getProperty("JAVA_PATH", null);

imagetool/src/main/java/com/oracle/weblogic/imagetool/cli/menu/UpdateImage.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,8 @@ public CommandResponse call() throws Exception {
5757

5858
tmpDir = getTempDirectory();
5959

60-
Utils.copyResourceAsFile("/probe-env/test-update-env.sh",
61-
tmpDir + File.separator + "test-env.sh", true);
62-
63-
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, fromImage, tmpDir);
60+
Properties baseImageProperties = Utils.getBaseImageProperties(buildEngine, fromImage,
61+
"/probe-env/test-update-env.sh", tmpDir);
6462

6563
dockerfileOptions.setJavaHome(baseImageProperties.getProperty("JAVA_HOME", null));
6664

imagetool/src/main/java/com/oracle/weblogic/imagetool/util/Utils.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.nio.file.attribute.PosixFilePermissions;
2323
import java.text.MessageFormat;
2424
import java.util.ArrayList;
25-
import java.util.Arrays;
2625
import java.util.Base64;
2726
import java.util.Collection;
2827
import java.util.Collections;
@@ -413,17 +412,21 @@ public static boolean isEmptyString(String s) {
413412
/**
414413
* Reads the docker image environment variables into Java Properties.
415414
*
415+
* @param builder the binary to create the container (like docker)
416416
* @param dockerImage the name of the Docker image to read from
417-
* @param tmpDir the directory to use on the container to copy a script
417+
* @param script the script resource (path to the script in the JAR)
418+
* @param contextDir the image build context folder
418419
* @return The key/value pairs representing the ENV of the Docker image
419420
* @throws IOException when the Docker command fails
420421
* @throws InterruptedException when the Docker command is interrupted
421422
*/
422-
public static Properties getBaseImageProperties(String builder, String dockerImage, String tmpDir)
423-
throws IOException, InterruptedException {
424-
425-
logger.entering(dockerImage, tmpDir);
426-
List<String> imageEnvCmd = Utils.getDockerRunCmd(builder, tmpDir, dockerImage, "test-env.sh");
423+
public static Properties getBaseImageProperties(String builder, String dockerImage, String script,
424+
String contextDir) throws IOException, InterruptedException {
425+
logger.entering(builder, dockerImage, script, contextDir);
426+
final String scriptToRun = "test-env.sh";
427+
Utils.copyResourceAsFile(script, contextDir + File.separator + scriptToRun, true);
428+
List<String> imageEnvCmd = Utils.getDockerRunCmd(builder,
429+
contextDir + File.separator + scriptToRun, dockerImage);
427430
Properties result = Utils.runDockerCommand(imageEnvCmd);
428431
logger.exiting(result);
429432
return result;
@@ -433,14 +436,12 @@ public static Properties getBaseImageProperties(String builder, String dockerIma
433436
* Constructs a docker command to run a script in the container with a volume mount.
434437
*
435438
* @param builder docker/podman executable
436-
* @param hostDirToMount host dir
439+
* @param scriptToRun the local script to encode and run
437440
* @param dockerImage docker image tag
438-
* @param scriptToRun script to execute on the container
439-
* @param args args to the script
440441
* @return command
441442
*/
442-
private static List<String> getDockerRunCmd(String builder, String hostDirToMount, String dockerImage,
443-
String scriptToRun, String... args) throws IOException {
443+
private static List<String> getDockerRunCmd(String builder, String scriptToRun, String dockerImage)
444+
throws IOException {
444445

445446
// We are removing the volume mount option, -v won't work in remote docker daemon and also
446447
// problematic if the mounted volume source is on a nfs volume as we have no idea what the docker volume
@@ -449,17 +450,13 @@ private static List<String> getDockerRunCmd(String builder, String hostDirToMoun
449450
// Now are encoding the test script and decode on the fly and execute it.
450451
// Warning: don't pass in a big file
451452

452-
byte[] fileBytes = Files.readAllBytes(Paths.get(hostDirToMount + File.separator + scriptToRun));
453+
byte[] fileBytes = Files.readAllBytes(Paths.get(scriptToRun));
453454
String encodedFile = Base64.getEncoder().encodeToString(fileBytes);
454455
String oneCommand = String.format("echo %s | base64 -d | /bin/bash", encodedFile);
455-
logger.finer("ONE COMMAND [" + oneCommand + "]");
456-
final List<String> retVal = Stream.of(
456+
logger.finest("running command in image [" + oneCommand + "]");
457+
return Stream.of(
457458
builder, "run", "--rm",
458459
dockerImage, "/bin/bash", "-c", oneCommand).collect(Collectors.toList());
459-
if (args != null && args.length > 0) {
460-
retVal.addAll(Arrays.asList(args));
461-
}
462-
return retVal;
463460
}
464461

465462
/**
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
{{#response}}
3+
{{value.key}}: "{{value.value}}"{{^last}}, {{/last}}
4+
{{/response}}
5+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env bash
2+
#
3+
#Copyright (c) 2021, Oracle and/or its affiliates.
4+
#
5+
#Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
6+
#
7+
for token in $(java -version 2>&1)
8+
do
9+
if [[ $token =~ \"([[:digit:]])\.([[:digit:]])\.(.*)\" ]]
10+
then
11+
echo javaVersion="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
12+
fi
13+
done
14+
15+
if command -v dnf &> /dev/null; then
16+
echo packageManager=dnf
17+
elif command -v yum &> /dev/null; then
18+
echo packageManager=yum
19+
elif command -v microdnf &> /dev/null; then
20+
echo packageManager=microdnf
21+
elif command -v apt-get &> /dev/null; then
22+
echo packageManager=aptget
23+
elif command -v apk &> /dev/null; then
24+
echo packageManager=apk
25+
elif command -v zypper &> /dev/null; then
26+
echo packageManager=zypper
27+
fi
28+
29+
if [[ -n "$JAVA_HOME" ]]; then
30+
echo javaHome="$JAVA_HOME"
31+
fi
32+
33+
if [[ -n "$ORACLE_HOME" ]]; then
34+
echo oracleHome="$ORACLE_HOME"
35+
WLS_TYPE=$(cat "$ORACLE_HOME"/inventory/registry.xml 2> /dev/null | grep -q 'WebLogic Server for FMW' && printf "fmw")
36+
if [[ -n "$WLS_TYPE" ]]; then
37+
echo wlsType="$WLS_TYPE"
38+
fi
39+
if [[ -n "$JAVA_HOME" ]]; then
40+
echo wlsVersion="$("$JAVA_HOME"/bin/java -cp "$ORACLE_HOME"/wlserver/server/lib/weblogic.jar weblogic.version 2> /dev/null | grep -oE -m 1 '([[:digit:]\.]+)' | head -1)"
41+
fi
42+
echo oracleHomeUser="$(stat -c '%U' "$ORACLE_HOME")"
43+
echo oracleHomeGroup="$(stat -c '%G' "$ORACLE_HOME")"
44+
45+
echo opatchVersion="$("$ORACLE_HOME"/OPatch/opatch version 2> /dev/null | grep -oE -m 1 '([[:digit:]\.]+)')"
46+
echo oraclePatches=$("$ORACLE_HOME"/OPatch/opatch lspatches | awk -F";" '/^[0-9]/ {print $0";"}')
47+
fi
48+
49+
if [[ -n "$DOMAIN_HOME" ]]; then
50+
echo domainHome="$DOMAIN_HOME"
51+
if [[ ! -d "$DOMAIN_HOME" ]] || [[ -z "$(ls -A $DOMAIN_HOME)" ]]; then
52+
echo wdtModelOnly=true
53+
fi
54+
fi
55+
56+
if [[ -n "$WDT_MODEL_HOME" ]]; then
57+
echo wdtModelHome="$WDT_MODEL_HOME"
58+
fi
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bash
2+
#
3+
#Copyright (c) 2021, Oracle and/or its affiliates.
4+
#
5+
#Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
6+
#
7+
for token in $(java -version 2>&1)
8+
do
9+
if [[ $token =~ \"([[:digit:]])\.([[:digit:]])\.(.*)\" ]]
10+
then
11+
echo javaVersion="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
12+
fi
13+
done
14+
15+
if command -v dnf &> /dev/null; then
16+
echo packageManager=dnf
17+
elif command -v yum &> /dev/null; then
18+
echo packageManager=yum
19+
elif command -v microdnf &> /dev/null; then
20+
echo packageManager=microdnf
21+
elif command -v apt-get &> /dev/null; then
22+
echo packageManager=aptget
23+
elif command -v apk &> /dev/null; then
24+
echo packageManager=apk
25+
elif command -v zypper &> /dev/null; then
26+
echo packageManager=zypper
27+
fi
28+
29+
if [[ -n "$JAVA_HOME" ]]; then
30+
echo javaHome="$JAVA_HOME"
31+
fi
32+
33+
if [[ -n "$ORACLE_HOME" ]]; then
34+
echo oracleHome="$ORACLE_HOME"
35+
WLS_TYPE=$(cat "$ORACLE_HOME"/inventory/registry.xml 2> /dev/null | grep -q 'WebLogic Server for FMW' && printf "fmw")
36+
if [[ -n "$WLS_TYPE" ]]; then
37+
echo wlsType="$WLS_TYPE"
38+
fi
39+
if [[ -n "$JAVA_HOME" ]]; then
40+
echo wlsVersion="$("$JAVA_HOME"/bin/java -cp "$ORACLE_HOME"/wlserver/server/lib/weblogic.jar weblogic.version 2> /dev/null | grep -oE -m 1 '([[:digit:]\.]+)' | head -1)"
41+
fi
42+
43+
echo oracleHomeUser="$(stat -c '%U' "$ORACLE_HOME")"
44+
echo oracleHomeGroup="$(stat -c '%G' "$ORACLE_HOME")"
45+
fi
46+
47+
if [[ -n "$DOMAIN_HOME" ]]; then
48+
echo domainHome="$DOMAIN_HOME"
49+
if [[ ! -d "$DOMAIN_HOME" ]] || [[ -z "$(ls -A $DOMAIN_HOME)" ]]; then
50+
echo wdtModelOnly=true
51+
fi
52+
fi
53+
54+
if [[ -n "$WDT_MODEL_HOME" ]]; then
55+
echo wdtModelHome="$WDT_MODEL_HOME"
56+
fi

0 commit comments

Comments
 (0)