aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/io/github/jshipit/BlobDownloader.java25
-rw-r--r--src/main/java/io/github/jshipit/ContainerManager.java46
-rwxr-xr-xsrc/main/java/io/github/jshipit/DockerAPIHelper.java4
-rwxr-xr-xsrc/main/java/io/github/jshipit/JshipIT.java5
-rw-r--r--src/main/java/io/github/jshipit/Mount.java48
-rwxr-xr-xsrc/main/java/io/github/jshipit/OCIDataStore.java38
6 files changed, 142 insertions, 24 deletions
diff --git a/src/main/java/io/github/jshipit/BlobDownloader.java b/src/main/java/io/github/jshipit/BlobDownloader.java
index 91f126e..3aafec4 100644
--- a/src/main/java/io/github/jshipit/BlobDownloader.java
+++ b/src/main/java/io/github/jshipit/BlobDownloader.java
@@ -6,6 +6,8 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import java.io.*;
import java.net.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
public class BlobDownloader extends Thread {
@@ -14,13 +16,15 @@ public class BlobDownloader extends Thread {
private final String[][] headers;
private final String tmpdir;
private final boolean extract;
+ private final String renameTo;
- public BlobDownloader(String url, String digest, String[][] headers, String tmpdir, boolean extract) {
+ public BlobDownloader(String url, String digest, String[][] headers, String tmpdir, boolean extract, String renameTo) {
this.url = url;
this.digest = digest;
this.headers = headers;
this.tmpdir = tmpdir;
this.extract = extract;
+ this.renameTo = renameTo;
}
public void run() {
@@ -75,14 +79,27 @@ public class BlobDownloader extends Thread {
e.printStackTrace();
}
- File extracted = new File(tmpdir + "/" + digest.replace("sha256:", ""));
- if (extracted.exists()) {
- extracted.delete();
+ if (this.renameTo == null) {
+ return;
+ }
+
+ Path rename = new File(renameTo).toPath();
+ Path current = new File(tmpdir + "/" + digest.replace("sha256:", "")+".tar.gz").toPath();
+ try {
+ Files.move(current, rename);
+ } catch (IOException e) {
+ System.out.println("Failed to rename file "+digest);
+ e.printStackTrace();
}
if (!extract) {
return;
}
+
+ File extracted = new File(tmpdir + "/" + digest.replace("sha256:", ""));
+ if (extracted.exists()) {
+ extracted.delete();
+ }
TarManager tarManager = new TarManager();
try {
tarManager.untar(tmpdir + "/" + digest.replace("sha256:", "") + ".tar.gz", extracted);
diff --git a/src/main/java/io/github/jshipit/ContainerManager.java b/src/main/java/io/github/jshipit/ContainerManager.java
index e8e2dad..3121061 100644
--- a/src/main/java/io/github/jshipit/ContainerManager.java
+++ b/src/main/java/io/github/jshipit/ContainerManager.java
@@ -1,9 +1,15 @@
package io.github.jshipit;
-import java.io.File;
+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.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
import java.util.UUID;
public class ContainerManager {
@@ -16,20 +22,22 @@ public class ContainerManager {
private String entryCommand;
private OCIDataStore dataStore;
- public ContainerManager(String containerName, String containerImage, String containerTag, String entryCommand, OCIDataStore dataStore) {
+ public ContainerManager(String containerName, String containerImage, String containerTag, String entryCommand, 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 void createContainer() {
System.out.println("Creating container");
- if (!Files.isDirectory(Paths.get(dataStore.getPath() + this.containerImage + "/" + this.containerTag))) {
- System.out.println("Image does not exist, pulling now");
- dataStore.createImage(this.containerApiRepo, this.containerRepo, this.containerImage, this.containerTag);
+ if (!Files.isDirectory(Paths.get(dataStore.getPath() + "/" + this.containerImage + "/" + this.containerTag))) {
+ System.out.println("Image does not exist");
+ return;
}
if (this.containerID == null) {
@@ -43,9 +51,37 @@ public class ContainerManager {
new File(containerDirectory + "/containerOverlay").mkdirs();
new File(containerDirectory + "/root").mkdirs();
+ }
+
+ public void startContainer() {
+ System.out.println("Starting container");
+ System.out.println("Container ID: " + this.containerID);
+ System.out.println("Container name: " + this.containerName);
+ System.out.println("Container image: " + this.containerImage);
+ System.out.println("Container tag: " + this.containerTag);
+ System.out.println("Container entry command: " + this.entryCommand);
+ System.out.println("Container data store: " + this.dataStore.getPath());
+ String containerDirectory = dataStore.getContainerPath(this.containerName, this.containerID);
+ System.out.println("Container directory: " + containerDirectory);
+
+ List<String> content = null;
+ try {
+ content = Files.readAllLines(Paths.get(this.dataStore.getPath() + "/" + this.containerImage + "/" + this.containerTag + "/layers"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ assert content != null;
+ List<String> layers = new ArrayList<>();
+ for (String line : content) {
+ layers.add(this.dataStore.getPath() + "/blobs/" + line.replace("sha256:", ""));
+ }
+ assert layers.size() > 0;
+ Mount mount = new Mount();
+ String[] diffs = layers.toArray(new String[0]);
+ mount.overlayMount(diffs, containerDirectory + "/containerOverlay", containerDirectory + "/root");
}
diff --git a/src/main/java/io/github/jshipit/DockerAPIHelper.java b/src/main/java/io/github/jshipit/DockerAPIHelper.java
index d11f581..21fd9c3 100755
--- a/src/main/java/io/github/jshipit/DockerAPIHelper.java
+++ b/src/main/java/io/github/jshipit/DockerAPIHelper.java
@@ -138,10 +138,10 @@ public class DockerAPIHelper {
}
}
- public void fetchBlob(String digest, String tmpdir, boolean extract) throws IOException, RuntimeException {
+ public void fetchBlob(String digest, String tmpdir, boolean extract, String renameTo) throws IOException, RuntimeException {
String url = "https://" + this.apiRepo + "/v2/" + this.repository + "/" + this.image + "/blobs/"+digest;
String[][] headers = {{"Authorization", "Bearer "+this.apiToken}, {"Accept", "application/vnd/docker.distribution.manifest.v2+json"}};
- BlobDownloader downloader = new BlobDownloader(url, digest, headers, tmpdir, extract);
+ BlobDownloader downloader = new BlobDownloader(url, digest, headers, tmpdir, extract, renameTo);
downloader.start();
}
diff --git a/src/main/java/io/github/jshipit/JshipIT.java b/src/main/java/io/github/jshipit/JshipIT.java
index 7784128..5ccd96e 100755
--- a/src/main/java/io/github/jshipit/JshipIT.java
+++ b/src/main/java/io/github/jshipit/JshipIT.java
@@ -43,6 +43,9 @@ public class JshipIT {
*/
OCIDataStore dataStore = new OCIDataStore("./tmp");
- dataStore.createImage("registry.docker.io","library", "bash", "devel-alpine3.18");
+ //dataStore.createImage("registry.docker.io","library", "bash", "devel-alpine3.18");
+ ContainerManager containerManager = new ContainerManager("testContainer", "bash", "devel-alpine3.18", "bash", "registry.docker.io", "library", dataStore);
+ containerManager.createContainer();
+ containerManager.startContainer();
}
} \ No newline at end of file
diff --git a/src/main/java/io/github/jshipit/Mount.java b/src/main/java/io/github/jshipit/Mount.java
new file mode 100644
index 0000000..63b60dd
--- /dev/null
+++ b/src/main/java/io/github/jshipit/Mount.java
@@ -0,0 +1,48 @@
+package io.github.jshipit;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Platform;
+
+public class Mount {
+ public interface CLibrary extends Library {
+ int mount(String source, String target,
+ String filesystemtype, int mountflags,
+ String data);
+
+ int umount(String target);
+ }
+
+ public void mount(String source, String target,
+ String filesystemtype, int mountflags,
+ String data) {
+ CLibrary libc;
+
+ if (Platform.isLinux()) {
+ libc = Native.load("c", CLibrary.class);
+ int result = libc.mount(source, target, filesystemtype, mountflags, data);
+ if (result == 0) {
+ System.out.println("Device mounted successfully.");
+ } else {
+ System.out.println("Device mount failed.");
+ }
+ }
+ }
+
+ public void overlayMount(String[] lower, String upper, String target) {
+ CLibrary libc;
+
+ if (Platform.isLinux()) {
+ libc = Native.load("c", CLibrary.class);
+ int result = libc.mount("overlay", target, "overlay", 0, "lowerdir="+String.join(":", lower)+",upperdir="+upper+",workdir="+target+"/work");
+ if (result == 0) {
+ System.out.println("Device mounted successfully.");
+ } else {
+ System.out.println("Device mount failed.");
+ }
+ } else {
+ System.out.println("Platform not supported.");
+ System.out.println("mount -t overlay overlay -o lowerdir="+String.join(":", lower)+",upperdir="+upper+",workdir="+target+"/work "+target);
+ }
+ }
+}
diff --git a/src/main/java/io/github/jshipit/OCIDataStore.java b/src/main/java/io/github/jshipit/OCIDataStore.java
index 3e0b9f3..92db6c2 100755
--- a/src/main/java/io/github/jshipit/OCIDataStore.java
+++ b/src/main/java/io/github/jshipit/OCIDataStore.java
@@ -52,7 +52,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 (id 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, id TEXT, path TEXT)");
System.out.println("A new database has been created.");
}
@@ -111,6 +111,24 @@ public class OCIDataStore {
}
}
+ public String getContainerPath(String name, String id) {
+ 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 + "' AND id = '" + id + "'");
+ return rs.getString("path");
+ }
+
+ } catch (SQLException e) {
+ System.out.println(e.getMessage());
+ }
+ return null;
+ }
+
public String createContainerDirectory(String image, String tag, String name, String id) {
Path containerPath = Path.of(this.path+"/"+image+"/"+tag+"/"+name+"_"+id);
try {
@@ -167,7 +185,6 @@ public class OCIDataStore {
assert manifest != null;
JsonNode layers = manifest.get("layers");
- List<String> digests = new ArrayList<String>();
String layerpath = this.path+"/blobs";
try {
Files.createDirectory(Path.of(layerpath));
@@ -178,38 +195,35 @@ public class OCIDataStore {
return;
}
}
+ List <String> layerDigests = new ArrayList<>();
for (JsonNode layer : layers) {
System.out.println("Layer: " + layer);
try {
if (!isBlobInDatabase(layer.get("digest").asText())) {
- api.fetchBlob(layer.get("digest").asText(), layerpath, true);
+ api.fetchBlob(layer.get("digest").asText(), layerpath, true, null);
addBlobToDatabase(layer.get("digest").asText());
+ layerDigests.add(layer.get("digest").asText());
} else {
System.out.println("Blob already in database: " + layer.get("digest").asText());
}
- digests.add(layer.get("digest").asText());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
- api.fetchBlob(manifest.get("config").get("digest").asText(), this.path+"/"+image+"/"+tag, false);
- File config = new File(this.path+"/"+image+"/"+tag+manifest.get("config").get("digest").asText().replace("sha256:", ""));
- config.renameTo(new File(this.path+"/"+image+"/"+tag+"/config"));
+ Files.write(Path.of(this.path+"/"+image+"/"+tag+"/layers"), layerDigests);
} catch (IOException e) {
e.printStackTrace();
}
- FileWriter writer = null;
try {
- writer = new FileWriter(this.path+"/"+image+"/"+tag+"/layers");
- writer.write(String.join("\n", digests));
- writer.close();
+ api.fetchBlob(manifest.get("config").get("digest").asText(), this.path+"/"+image+"/"+tag, false, this.path+"/"+image+"/"+tag+"/config");
} catch (IOException e) {
- throw new RuntimeException(e);
+ e.printStackTrace();
}
+
}
public String getPath() {