diff options
Diffstat (limited to 'src/main/java/io/github/jshipit')
-rw-r--r-- | src/main/java/io/github/jshipit/Commands.java | 6 | ||||
-rw-r--r-- | src/main/java/io/github/jshipit/ContainerManager.java | 72 | ||||
-rwxr-xr-x | src/main/java/io/github/jshipit/JshipIT.java | 10 | ||||
-rwxr-xr-x | src/main/java/io/github/jshipit/OCIDataStore.java | 106 | ||||
-rw-r--r-- | src/main/java/io/github/jshipit/SysUtils.java | 12 |
5 files changed, 185 insertions, 21 deletions
diff --git a/src/main/java/io/github/jshipit/Commands.java b/src/main/java/io/github/jshipit/Commands.java index f4d301e..98283e3 100644 --- a/src/main/java/io/github/jshipit/Commands.java +++ b/src/main/java/io/github/jshipit/Commands.java @@ -3,6 +3,12 @@ package io.github.jshipit; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; +@Parameters(commandDescription = "Start a container") +class CommandStart { + @Parameter(names = {"--name", "-n"}, description = "Name of the container") + public String containerName; +} + @Parameters(commandDescription = "Create a container") class CommandCreate { @Parameter(names = {"--name", "-n"}, description = "Name of the container") diff --git a/src/main/java/io/github/jshipit/ContainerManager.java b/src/main/java/io/github/jshipit/ContainerManager.java index cacf313..c22d51b 100644 --- a/src/main/java/io/github/jshipit/ContainerManager.java +++ b/src/main/java/io/github/jshipit/ContainerManager.java @@ -1,5 +1,9 @@ package io.github.jshipit; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; @@ -8,25 +12,31 @@ import java.util.List; import java.util.UUID; public class ContainerManager { - private String containerID; private String containerName; private String containerRepo; private String containerImage; private String containerTag; private String containerApiRepo; - private String entryCommand; private OCIDataStore dataStore; - public ContainerManager(String containerName, String containerImage, String containerTag, String entryCommand, String containerApiRepo, String containerRepo, OCIDataStore dataStore) { + public ContainerManager(String containerName, String containerImage, String containerTag, String containerApiRepo, String containerRepo, OCIDataStore dataStore) { this.containerName = containerName; this.containerImage = containerImage; this.containerTag = containerTag; - this.entryCommand = entryCommand; this.containerApiRepo = containerApiRepo; this.containerRepo = containerRepo; this.dataStore = dataStore; } + public ContainerManager(String containerName, 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.dataStore = dataStore; + } + public void createContainer() { System.out.println("Creating container"); @@ -35,11 +45,7 @@ public class ContainerManager { return; } - if (this.containerID == null) { - this.containerID = genContainerID(); - } - - String containerDirectory = dataStore.createContainerDirectory(this.containerImage, this.containerTag, this.containerName, this.containerID); + String containerDirectory = dataStore.createContainerDirectory(this.containerImage, this.containerTag, this.containerName, this.containerApiRepo, this.containerRepo); new File(containerDirectory + "/containerOverlay").mkdirs(); new File(containerDirectory + "/root").mkdirs(); @@ -48,7 +54,7 @@ public class ContainerManager { public void startContainer() { - String containerDirectory = dataStore.getContainerPath(this.containerName, this.containerID); + String containerDirectory = dataStore.getContainerPath(this.containerName); List<String> content = null; try { content = Files.readAllLines(Paths.get(this.dataStore.getPath() + "/" + this.containerImage + "/" + this.containerTag + "/layers")); @@ -68,6 +74,52 @@ public class ContainerManager { } + public void runCommand(String command) { + String containerDirectory = dataStore.getContainerPath(this.containerName); + String dataStorePath = dataStore.getPath(); + startContainer(); + + File configPath = new File(dataStorePath + "/" + this.containerImage + "/" + this.containerTag + "/config"); + String content = null; + try { + content = Files.readAllLines(Paths.get(configPath.getAbsolutePath())).toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + ObjectMapper mapper = new ObjectMapper(); + List<String> env = new ArrayList<>(); + String cmd = null; + String hostname = null; + try { + JsonNode config = mapper.readTree(content.toString()).get(0).get("config"); + config.get("Env").forEach((JsonNode envVar) -> { + env.add(envVar.asText()); + }); + cmd = config.get("Cmd").get(0).asText(); + hostname = config.get("Hostname").asText(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + // why would these be null? I don't know, but I won't bother handling this better + assert hostname != null; + assert cmd != null; + + List<String> bwrapCommand = new ArrayList<>(); + + for(String envVar : env) { + bwrapCommand.add("--setenv "+envVar.split("=")[0]+" "+envVar.split("=")[1]); + } + + bwrapCommand.add("--ro-bind "+containerDirectory+"/root / --chdir /"); + bwrapCommand.add("--share-net"); + bwrapCommand.add("--hostname "+ (!hostname.isBlank() ? hostname : this.containerName+"-"+this.containerImage)); + bwrapCommand.add(cmd); + SysUtils sysUtils = new SysUtils(); + sysUtils.execInBwrap(bwrapCommand.toArray(new String[0])); + } + public String genContainerID() { return UUID.randomUUID().toString(); } diff --git a/src/main/java/io/github/jshipit/JshipIT.java b/src/main/java/io/github/jshipit/JshipIT.java index d51ddbe..9d109ba 100755 --- a/src/main/java/io/github/jshipit/JshipIT.java +++ b/src/main/java/io/github/jshipit/JshipIT.java @@ -11,12 +11,13 @@ import com.beust.jcommander.Parameter; public class JshipIT { public JshipIT(String[] args) { - + CommandStart commandStart = new CommandStart(); CommandCreate commandCreate = new CommandCreate(); CommandPull commandPull = new CommandPull(); JCommander commands = JCommander.newBuilder() .addCommand("create", commandCreate) .addCommand("pull", commandPull) + .addCommand("start", commandStart) .build(); commands.parse(args); @@ -27,11 +28,14 @@ public class JshipIT { commands.usage(); System.exit(1); } else if (commands.getParsedCommand().equals("create")) { - ContainerManager containerManager = new ContainerManager(commandCreate.containerName, commandCreate.containerImage, commandCreate.containerTag, "bash", commandCreate.containerApiRepo, commandCreate.containerRepo, dataStore); + ContainerManager containerManager = new ContainerManager(commandCreate.containerName, commandCreate.containerImage, commandCreate.containerTag, commandCreate.containerApiRepo, commandCreate.containerRepo, dataStore); containerManager.createContainer(); - containerManager.startContainer(); } else if (commands.getParsedCommand().equals("pull")) { dataStore.createImage(commandPull.containerApiRepo, commandPull.containerRepo, commandPull.containerImage, commandPull.containerTag); + } else if (commands.getParsedCommand().equals("start")) { + ContainerManager containerManager = new ContainerManager(commandStart.containerName, dataStore); + containerManager.startContainer(); + containerManager.runCommand(null); } diff --git a/src/main/java/io/github/jshipit/OCIDataStore.java b/src/main/java/io/github/jshipit/OCIDataStore.java index 6991af4..0a80b3f 100755 --- a/src/main/java/io/github/jshipit/OCIDataStore.java +++ b/src/main/java/io/github/jshipit/OCIDataStore.java @@ -55,7 +55,7 @@ public class OCIDataStore { statement.setQueryTimeout(30); // set timeout to 30 sec. statement.executeUpdate("CREATE TABLE IF NOT EXISTS blobs (id INTEGER PRIMARY KEY AUTOINCREMENT, digest TEXT, path TEXT)"); - statement.executeUpdate("CREATE TABLE IF NOT EXISTS containers (containerID INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, id TEXT, path TEXT)"); + statement.executeUpdate("CREATE TABLE IF NOT EXISTS containers (containerID INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, path TEXT, image TEXT, tag TEXT, apiRepo TEXT, repo TEXT)"); System.out.println("A new database has been created."); } @@ -98,7 +98,7 @@ public class OCIDataStore { return false; } - public void addContainerToDatabase(String path, String name, String id) { + public void addContainerToDatabase(String path, String name, String image, String tag, String apiRepo, String repo) { String url = "jdbc:sqlite:" + this.databasePath; try (Connection conn = DriverManager.getConnection(url)) { @@ -106,7 +106,7 @@ public class OCIDataStore { Statement statement = conn.createStatement(); statement.setQueryTimeout(30); // set timeout to 30 sec. - statement.executeUpdate("INSERT INTO containers (name, id, path) VALUES ('" + name + "', '" + id + "', '" + path + "')"); + statement.executeUpdate("INSERT INTO containers (name, path, image, tag, apiRepo, repo) VALUES ('" + name + "', '" + path + "', '" + image + "', '" + tag + "', '" + apiRepo + "', '" + repo + "')"); } } catch (SQLException e) { @@ -114,7 +114,7 @@ public class OCIDataStore { } } - public String getContainerPath(String name, String id) { + public String getContainerID(String name) { String url = "jdbc:sqlite:" + this.databasePath; try (Connection conn = DriverManager.getConnection(url)) { @@ -122,7 +122,25 @@ public class OCIDataStore { Statement statement = conn.createStatement(); statement.setQueryTimeout(30); // set timeout to 30 sec. - ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "' AND id = '" + id + "'"); + ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "'"); + return rs.getString("containerID"); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return null; + } + + public String getContainerPath(String name) { + String url = "jdbc:sqlite:" + this.databasePath; + + try (Connection conn = DriverManager.getConnection(url)) { + if (conn != null) { + Statement statement = conn.createStatement(); + statement.setQueryTimeout(30); // set timeout to 30 sec. + + ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "'"); return rs.getString("path"); } @@ -132,8 +150,80 @@ public class OCIDataStore { return null; } - public String createContainerDirectory(String image, String tag, String name, String id) { - Path containerPath = Path.of(this.path+"/"+image+"/"+tag+"/"+name+"_"+id); + public String getContainerImage(String name) { + String url = "jdbc:sqlite:" + this.databasePath; + + try (Connection conn = DriverManager.getConnection(url)) { + if (conn != null) { + Statement statement = conn.createStatement(); + statement.setQueryTimeout(30); // set timeout to 30 sec. + + ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "'"); + return rs.getString("image"); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return null; + } + + public String getContainerTag(String name) { + String url = "jdbc:sqlite:" + this.databasePath; + + try (Connection conn = DriverManager.getConnection(url)) { + if (conn != null) { + Statement statement = conn.createStatement(); + statement.setQueryTimeout(30); // set timeout to 30 sec. + + ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "'"); + return rs.getString("tag"); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return null; + } + + public String getContainerApiRepo(String name) { + String url = "jdbc:sqlite:" + this.databasePath; + + try (Connection conn = DriverManager.getConnection(url)) { + if (conn != null) { + Statement statement = conn.createStatement(); + statement.setQueryTimeout(30); // set timeout to 30 sec. + + ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "'"); + return rs.getString("apiRepo"); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return null; + } + + public String getContainerRepo(String name) { + String url = "jdbc:sqlite:" + this.databasePath; + + try (Connection conn = DriverManager.getConnection(url)) { + if (conn != null) { + Statement statement = conn.createStatement(); + statement.setQueryTimeout(30); // set timeout to 30 sec. + + ResultSet rs = statement.executeQuery("SELECT * FROM containers WHERE name = '" + name + "'"); + return rs.getString("repo"); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return null; + } + + public String createContainerDirectory(String image, String tag, String name, String apiRepo, String repo) { + Path containerPath = Path.of(this.path+"/"+image+"/"+tag+"/"+name); try { Files.createDirectory(containerPath); } catch (IOException e) { @@ -141,7 +231,7 @@ public class OCIDataStore { e.printStackTrace(); return null; } - addContainerToDatabase(containerPath.toString(), name, id); + addContainerToDatabase(containerPath.toString(), name, image, tag, apiRepo, repo); return containerPath.toString(); } diff --git a/src/main/java/io/github/jshipit/SysUtils.java b/src/main/java/io/github/jshipit/SysUtils.java index 877b61e..e6de886 100644 --- a/src/main/java/io/github/jshipit/SysUtils.java +++ b/src/main/java/io/github/jshipit/SysUtils.java @@ -29,6 +29,18 @@ public class SysUtils { } } + public void execInBwrap(String[] args) { + //System.out.println("bwrap "+String.join(" ", args)); + ProcessBuilder pb = new ProcessBuilder("bwrap", args.toString()); + pb.inheritIO(); + try { + Process p = pb.start(); + p.waitFor(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + public void overlayMount(String[] lower, String upper, String target, String work) { if (Platform.isLinux()) { |