Skip to content

Commit 9c29a10

Browse files
authored
#16: implement tool commandlet docker (devonfw#249)
1 parent 970e1fc commit 9c29a10

File tree

5 files changed

+165
-18
lines changed

5 files changed

+165
-18
lines changed

cli/src/main/java/com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.devonfw.tools.ide.tool.aws.Aws;
1313
import com.devonfw.tools.ide.tool.az.Azure;
1414
import com.devonfw.tools.ide.tool.cobigen.Cobigen;
15+
import com.devonfw.tools.ide.tool.docker.Docker;
1516
import com.devonfw.tools.ide.tool.eclipse.Eclipse;
1617
import com.devonfw.tools.ide.tool.gcviewer.GcViewer;
1718
import com.devonfw.tools.ide.tool.gh.Gh;
@@ -84,6 +85,7 @@ public CommandletManagerImpl(IdeContext context) {
8485
add(new Aws(context));
8586
add(new Cobigen(context));
8687
add(new Jmc(context));
88+
add(new Docker(context));
8789
add(new Sonar(context));
8890
}
8991

cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
package com.devonfw.tools.ide.process;
22

3-
import com.devonfw.tools.ide.cli.CliException;
4-
import com.devonfw.tools.ide.common.SystemPath;
5-
import com.devonfw.tools.ide.context.IdeContext;
6-
import com.devonfw.tools.ide.environment.VariableLine;
7-
import com.devonfw.tools.ide.log.IdeSubLogger;
8-
import com.devonfw.tools.ide.os.SystemInfoImpl;
9-
import com.devonfw.tools.ide.util.FilenameUtil;
10-
113
import java.io.BufferedReader;
124
import java.io.IOException;
135
import java.io.InputStream;
@@ -22,6 +14,14 @@
2214
import java.util.Objects;
2315
import java.util.stream.Collectors;
2416

17+
import com.devonfw.tools.ide.cli.CliException;
18+
import com.devonfw.tools.ide.common.SystemPath;
19+
import com.devonfw.tools.ide.context.IdeContext;
20+
import com.devonfw.tools.ide.environment.VariableLine;
21+
import com.devonfw.tools.ide.log.IdeSubLogger;
22+
import com.devonfw.tools.ide.os.SystemInfoImpl;
23+
import com.devonfw.tools.ide.util.FilenameUtil;
24+
2525
/**
2626
* Implementation of {@link ProcessContext}.
2727
*/
@@ -116,7 +116,7 @@ public ProcessResult run(ProcessMode processMode) {
116116
if (this.executable == null) {
117117
throw new IllegalStateException("Missing executable to run process!");
118118
}
119-
List<String> args = new ArrayList<>(this.arguments.size() + 2);
119+
List<String> args = new ArrayList<>(this.arguments.size() + 4);
120120
String interpreter = addExecutable(this.executable.toString(), args);
121121
args.addAll(this.arguments);
122122
if (this.context.debug().isEnabled()) {
@@ -140,7 +140,7 @@ public ProcessResult run(ProcessMode processMode) {
140140
List<String> err = null;
141141

142142
if (processMode == ProcessMode.DEFAULT_CAPTURE) {
143-
try (BufferedReader outReader = new BufferedReader(new InputStreamReader(process.getInputStream()));) {
143+
try (BufferedReader outReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
144144
out = outReader.lines().collect(Collectors.toList());
145145
}
146146
try (BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
@@ -192,8 +192,7 @@ private String createCommandMessage(String interpreter, String suffix) {
192192
}
193193
}
194194
sb.append(suffix);
195-
String message = sb.toString();
196-
return message;
195+
return sb.toString();
197196
}
198197

199198
private String getSheBang(Path file) {
@@ -314,6 +313,10 @@ private String addExecutable(String executable, List<String> args) {
314313
}
315314
args.add(bash);
316315
}
316+
if ("msi".equalsIgnoreCase(fileExtension)) {
317+
args.add(0, "/i");
318+
args.add(0, "msiexec");
319+
}
317320
args.add(executable);
318321
return interpreter;
319322
}

cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package com.devonfw.tools.ide.tool;
22

3+
import java.nio.file.Files;
4+
import java.nio.file.Path;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Set;
8+
39
import com.devonfw.tools.ide.common.Tag;
410
import com.devonfw.tools.ide.context.IdeContext;
511
import com.devonfw.tools.ide.io.FileAccess;
@@ -9,10 +15,6 @@
915
import com.devonfw.tools.ide.repo.ToolRepository;
1016
import com.devonfw.tools.ide.version.VersionIdentifier;
1117

12-
import java.nio.file.Files;
13-
import java.nio.file.Path;
14-
import java.util.Set;
15-
1618
/**
1719
* {@link ToolCommandlet} that is installed globally.
1820
*/
@@ -24,13 +26,70 @@ public abstract class GlobalToolCommandlet extends ToolCommandlet {
2426
* @param context the {@link IdeContext}.
2527
* @param tool the {@link #getName() tool name}.
2628
* @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of}
27-
* method.
29+
* method.
2830
*/
2931
public GlobalToolCommandlet(IdeContext context, String tool, Set<Tag> tags) {
3032

3133
super(context, tool, tags);
3234
}
3335

36+
/**
37+
* Performs the installation of the {@link #getName() tool} via a package manager.
38+
*
39+
* @param silent - {@code true} if called recursively to suppress verbose logging, {@code false} otherwise.
40+
* @param commands - A {@link Map} containing the commands used to perform the installation for each package manager.
41+
* @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and
42+
* nothing has changed.
43+
*/
44+
protected boolean installWithPackageManger(Map<PackageManager, List<String>> commands, boolean silent) {
45+
46+
Path binaryPath = this.context.getPath().findBinary(Path.of(getBinaryName()));
47+
48+
if (binaryPath != null && Files.exists(binaryPath) && !this.context.isForceMode()) {
49+
IdeLogLevel level = silent ? IdeLogLevel.DEBUG : IdeLogLevel.INFO;
50+
this.context.level(level).log("{} is already installed at {}", this.tool, binaryPath);
51+
return false;
52+
}
53+
54+
Path bashPath = this.context.getPath().findBinary(Path.of("bash"));
55+
if (bashPath == null || !Files.exists(bashPath)) {
56+
context.warning("Bash was not found on this machine. Not Proceeding with installation of tool " + this.tool);
57+
return false;
58+
}
59+
60+
PackageManager foundPackageManager = null;
61+
for (PackageManager pm : commands.keySet()) {
62+
if (Files.exists(this.context.getPath().findBinary(Path.of(pm.toString().toLowerCase())))) {
63+
foundPackageManager = pm;
64+
break;
65+
}
66+
}
67+
68+
int finalExitCode = 0;
69+
if (foundPackageManager == null) {
70+
context.warning("No supported Package Manager found for installation");
71+
return false;
72+
} else {
73+
List<String> commandList = commands.get(foundPackageManager);
74+
if (commandList != null) {
75+
for (String command : commandList) {
76+
ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING).executable(bashPath)
77+
.addArgs("-c", command);
78+
finalExitCode = pc.run();
79+
}
80+
}
81+
}
82+
83+
if (finalExitCode == 0) {
84+
this.context.success("Successfully installed {}", this.tool);
85+
} else {
86+
this.context.warning("{} was not successfully installed", this.tool);
87+
return false;
88+
}
89+
postInstall();
90+
return true;
91+
}
92+
3493
@Override
3594
protected boolean isExtract() {
3695

@@ -79,5 +138,4 @@ protected boolean doInstall(boolean silent) {
79138
postInstall();
80139
return true;
81140
}
82-
83141
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.devonfw.tools.ide.tool;
2+
3+
public enum PackageManager {
4+
APT, ZYPPER, YUM, DNF
5+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.devonfw.tools.ide.tool.docker;
2+
3+
import java.util.Arrays;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Set;
8+
9+
import com.devonfw.tools.ide.common.Tag;
10+
import com.devonfw.tools.ide.context.IdeContext;
11+
import com.devonfw.tools.ide.os.SystemArchitecture;
12+
import com.devonfw.tools.ide.repo.ToolRepository;
13+
import com.devonfw.tools.ide.tool.GlobalToolCommandlet;
14+
import com.devonfw.tools.ide.tool.PackageManager;
15+
import com.devonfw.tools.ide.version.VersionIdentifier;
16+
17+
public class Docker extends GlobalToolCommandlet {
18+
/**
19+
* The constructor.
20+
*
21+
* @param context the {@link IdeContext}.
22+
*/
23+
public Docker(IdeContext context) {
24+
25+
super(context, "docker", Set.of(Tag.DOCKER));
26+
}
27+
28+
@Override
29+
public boolean isExtract() {
30+
31+
return switch (context.getSystemInfo().getOs()) {
32+
case WINDOWS -> false;
33+
case MAC -> context.getSystemInfo().getArchitecture().equals(SystemArchitecture.ARM64);
34+
case LINUX -> true;
35+
};
36+
}
37+
38+
@Override
39+
protected boolean doInstall(boolean silent) {
40+
41+
if (context.getSystemInfo().isLinux()) {
42+
return installWithPackageManger(getPackageMangerCommands(), silent);
43+
} else {
44+
return super.doInstall(silent);
45+
}
46+
}
47+
48+
private Map<PackageManager, List<String>> getPackageMangerCommands() {
49+
50+
Map<PackageManager, List<String>> commands = new HashMap<>();
51+
52+
String edition = getEdition();
53+
ToolRepository toolRepository = this.context.getDefaultToolRepository();
54+
VersionIdentifier configuredVersion = getConfiguredVersion();
55+
String resolvedVersion = toolRepository.resolveVersion(this.tool, edition, configuredVersion).toString();
56+
57+
commands.put(PackageManager.ZYPPER, Arrays.asList(
58+
"sudo zypper addrepo https://download.opensuse.org/repositories/isv:/Rancher:/stable/rpm/isv:Rancher:stable.repo",
59+
String.format("sudo zypper --no-gpg-checks install rancher-desktop=%s*", resolvedVersion)));
60+
61+
commands.put(PackageManager.APT, Arrays.asList(
62+
"curl -s https://download.opensuse.org/repositories/isv:/Rancher:/stable/deb/Release.key | gpg --dearmor | sudo dd status=none of=/usr/share/keyrings/isv-rancher-stable-archive-keyring.gpg",
63+
"echo 'deb [signed-by=/usr/share/keyrings/isv-rancher-stable-archive-keyring.gpg] https://download.opensuse.org/repositories/isv:/Rancher:/stable/deb/ ./' | sudo dd status=none of=/etc/apt/sources.list.d/isv-rancher-stable.list",
64+
"sudo apt update",
65+
String.format("sudo apt install -y --allow-downgrades rancher-desktop=%s*", resolvedVersion)));
66+
67+
return commands;
68+
}
69+
70+
@Override
71+
protected String getBinaryName() {
72+
73+
if (context.getSystemInfo().isLinux()) {
74+
return "rancher-desktop";
75+
} else {
76+
return super.getBinaryName();
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)