diff options
-rw-r--r-- | src/main/java/io/github/jshipit/Commands.java | 9 | ||||
-rw-r--r-- | src/main/java/io/github/jshipit/ContainerManager.java | 16 | ||||
-rwxr-xr-x | src/main/java/io/github/jshipit/JshipIT.java | 14 | ||||
-rwxr-xr-x | src/main/java/io/github/jshipit/OCIDataStore.java | 2 | ||||
-rw-r--r-- | src/main/java/io/github/jshipit/SysUtils.java | 2 |
5 files changed, 32 insertions, 11 deletions
diff --git a/src/main/java/io/github/jshipit/Commands.java b/src/main/java/io/github/jshipit/Commands.java index ffdbe38..1b4b913 100644 --- a/src/main/java/io/github/jshipit/Commands.java +++ b/src/main/java/io/github/jshipit/Commands.java @@ -3,11 +3,17 @@ package io.github.jshipit; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; +import java.util.ArrayList; +import java.util.List; + @Parameters(commandDescription = "Open a shell in a container") class CommandShell { @Parameter(names = {"--name", "-n"}, description = "Name of the container", required = true) public String containerName; + @Parameter(names = {"--mount", "-m"}, description = "Mount a directory into the container", required = false) + public List<String> containerMount = new ArrayList<>(); + @Parameter(names = "--help", help = true) private boolean help; } @@ -20,6 +26,9 @@ class CommandStart { @Parameter(names = {"--command", "-c"}, description = "Command to run in the container", required = false) public String containerCommand = null; + @Parameter(names = {"--mount", "-m"}, description = "Mount a directory into the container", required = false) + public List<String> containerMount = new ArrayList<>(); + @Parameter(names = "--help", help = true) private boolean help; } diff --git a/src/main/java/io/github/jshipit/ContainerManager.java b/src/main/java/io/github/jshipit/ContainerManager.java index 07dae9c..d276f75 100644 --- a/src/main/java/io/github/jshipit/ContainerManager.java +++ b/src/main/java/io/github/jshipit/ContainerManager.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -18,24 +19,27 @@ public class ContainerManager { private String containerApiRepo; private String containerCommand; + private List<String> containerMounts; private OCIDataStore dataStore; - public ContainerManager(String containerName, String containerImage, String containerTag, String containerApiRepo, String containerRepo, OCIDataStore dataStore) { + public ContainerManager(String containerName, String containerImage, String containerTag, String containerApiRepo, String containerRepo, List<String> containerMounts, OCIDataStore dataStore) { this.containerName = containerName; this.containerImage = containerImage; this.containerTag = containerTag; this.containerApiRepo = containerApiRepo; this.containerRepo = containerRepo; + this.containerMounts = containerMounts; this.dataStore = dataStore; } - public ContainerManager(String containerName, String containerCommand, OCIDataStore dataStore) { + public ContainerManager(String containerName, String containerCommand, List<String> containerMounts, OCIDataStore dataStore) { this.containerName = containerName; this.containerImage = dataStore.getContainerImage(containerName); this.containerTag = dataStore.getContainerTag(containerName); this.containerApiRepo = dataStore.getContainerApiRepo(containerName); this.containerRepo = dataStore.getContainerRepo(containerName); this.containerCommand = containerCommand; + this.containerMounts = containerMounts; this.dataStore = dataStore; } @@ -135,6 +139,14 @@ public class ContainerManager { } bwrapCommand.add("--bind "+containerDirectory+"/root / --chdir /"); // Bind the root to / inside the bwrap namespace + + if (this.containerMounts != null) { + for (String mount : containerMounts) { + bwrapCommand.add("--bind "+mount.split(":")[0]+" "+mount.split(":")[1]); // Bind the mount to the destination specified in the config file + } + } + + bwrapCommand.add("--ro-bind /etc/resolv.conf /etc/resolv.conf"); // Bind the host resolv.conf to the container bwrapCommand.add("--share-net"); // Share the network namespace bwrapCommand.add("--unshare-uts --hostname "+ (!hostname.isBlank() ? hostname : this.containerName+"-"+this.containerImage)); // Unshare the UTS namespace and set the hostname bwrapCommand.add("/bin/sh -c '"+(this.containerCommand != null ? this.containerCommand : cmd)+"'"); // Run the command specified in the config file or the command specified in the constructor diff --git a/src/main/java/io/github/jshipit/JshipIT.java b/src/main/java/io/github/jshipit/JshipIT.java index 76f224b..4304051 100755 --- a/src/main/java/io/github/jshipit/JshipIT.java +++ b/src/main/java/io/github/jshipit/JshipIT.java @@ -25,7 +25,7 @@ public class JshipIT { commands.parse(args); - OCIDataStore dataStore = new OCIDataStore(System.getenv("HOME") + "/.local/share/dataStore"); + OCIDataStore dataStore = new OCIDataStore(System.getenv("HOME") + "/.local/share/jshipit/dataStore"); if (commands.getParsedCommand() == null) { commands.usage(); @@ -45,11 +45,11 @@ public class JshipIT { String containerRepo = String.join("/", image); // Convert the registry name to the OCI registry name - if (apiRepo == "docker.io") { + if (apiRepo.equalsIgnoreCase("docker.io")) { apiRepo = "registry.docker.io"; } - ContainerManager containerManager = new ContainerManager(commandCreate.containerName, containerImage, commandCreate.containerImage.split(":")[1], apiRepo, containerRepo, dataStore); + ContainerManager containerManager = new ContainerManager(commandCreate.containerName, containerImage, commandCreate.containerImage.split(":")[1], apiRepo, containerRepo, null, dataStore); containerManager.createContainer(); } else if (commands.getParsedCommand().equals("pull")) { @@ -62,20 +62,20 @@ public class JshipIT { String containerRepo = String.join("/", image); // Convert the registry name to the OCI registry name - if (apiRepo == "docker.io") { + if (apiRepo.equalsIgnoreCase("docker.io")) { apiRepo = "registry.docker.io"; } System.out.println("Pulling image " + containerImage + " from " + apiRepo + "/" + containerRepo); dataStore.createImage(apiRepo, containerRepo, containerImage, commandPull.containerImage.split(":")[1]); } else if (commands.getParsedCommand().equals("start")) { - ContainerManager containerManager = new ContainerManager(commandStart.containerName, commandStart.containerCommand, dataStore); + ContainerManager containerManager = new ContainerManager(commandStart.containerName, commandStart.containerCommand, commandStart.containerMount, dataStore); containerManager.runCommand(); } else if (commands.getParsedCommand().equals("shell")) { - ContainerManager containerManager = new ContainerManager(commandShell.containerName, "/bin/sh", dataStore); // A proper linux system should always have /bin/sh, skill issue if it doesn't + ContainerManager containerManager = new ContainerManager(commandShell.containerName, "/bin/sh", commandShell.containerMount, dataStore); // A proper linux system should always have /bin/sh, skill issue if it doesn't containerManager.runCommand(); } else if (commands.getParsedCommand().equals("delete")) { - ContainerManager containerManager = new ContainerManager(commandDelete.containerName, null, dataStore); + ContainerManager containerManager = new ContainerManager(commandDelete.containerName, null, null, dataStore); containerManager.deleteContainer(); } } diff --git a/src/main/java/io/github/jshipit/OCIDataStore.java b/src/main/java/io/github/jshipit/OCIDataStore.java index c77f671..b8626ee 100755 --- a/src/main/java/io/github/jshipit/OCIDataStore.java +++ b/src/main/java/io/github/jshipit/OCIDataStore.java @@ -43,7 +43,7 @@ public class OCIDataStore { System.out.println("Creating OCI Data Store"); Path path = Path.of(this.path); try { - Files.createDirectory(path); + Files.createDirectories(path); } catch (IOException e) { if (!(e instanceof FileAlreadyExistsException)) { System.out.println("Failed to create directory: " + path); diff --git a/src/main/java/io/github/jshipit/SysUtils.java b/src/main/java/io/github/jshipit/SysUtils.java index ed14612..8bcd7b6 100644 --- a/src/main/java/io/github/jshipit/SysUtils.java +++ b/src/main/java/io/github/jshipit/SysUtils.java @@ -71,7 +71,7 @@ public class SysUtils { if (Platform.isLinux()) { // unshare creates a new user namespace, so we can mount without root // This only works on Linux version 5.11 and above, which everyone should have by now - ProcessBuilder pb = new ProcessBuilder("unshare", "--user", "--map-root-user", "--mount", "mount", "-t", "overlay", "overlay", "-o", "lowerdir="+String.join(":", lower)+",upperdir="+upper+",workdir="+work, target); + ProcessBuilder pb = new ProcessBuilder("unshare", "--user", "--map-root-user", "--mount", "mount", "-t", "overlay", "overlay", "-o", "lowerdir="+String.join(":", lower)+",upperdir="+upper+",workdir="+work+",userxattr", target); pb.inheritIO(); try { Process p = pb.start(); |