about summary refs log tree commit diff
path: root/tvix/tests/tvix-init.go
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-09-23T14·34+0300
committerflokli <flokli@flokli.de>2023-09-24T17·05+0000
commitba3edc5638f656b73592a44151fd9341a5935031 (patch)
tree3ab092f883a1ad98ae0d245a9ab119d735da8b6c /tvix/tests/tvix-init.go
parent93071ca4505b79b3a39038002e816b14c65e497c (diff)
feat(tvix/tests): add basic plumbing for integration tests r/6645
This adds a basic skeleton to test various tvix components in
combination.

As a first start, we test the virtiofs integration, by seeding the tvix-
store with some data, booting a VM, and listing the contents from there.

Change-Id: Ice6516d0eb508d19ea8fabefee860a0950046171
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9449
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: Connor Brewster <cbrewster@hey.com>
Diffstat (limited to 'tvix/tests/tvix-init.go')
-rw-r--r--tvix/tests/tvix-init.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/tvix/tests/tvix-init.go b/tvix/tests/tvix-init.go
new file mode 100644
index 000000000000..a81001159ae2
--- /dev/null
+++ b/tvix/tests/tvix-init.go
@@ -0,0 +1,85 @@
+package main
+
+import (
+	"log"
+	"os"
+	"os/exec"
+	"strings"
+	"syscall"
+)
+
+// run the given command, connecting std{in,err,out} with the OS one.
+func run(args ...string) error {
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Stdin = os.Stdin
+	cmd.Stderr = os.Stderr
+	cmd.Stdout = os.Stdout
+
+	return cmd.Run()
+}
+
+// parse the cmdline, return a map[string]string.
+func parseCmdline(cmdline string) map[string]string {
+	line := strings.TrimSuffix(cmdline, "\n")
+	fields := strings.Fields(line)
+	out := make(map[string]string, 0)
+
+	for _, arg := range fields {
+		kv := strings.SplitN(arg, "=", 2)
+		switch len(kv) {
+		case 1:
+			out[kv[0]] = ""
+		case 2:
+			out[kv[0]] = kv[1]
+		}
+	}
+
+	return out
+}
+
+func main() {
+	log.Println("Running tvix-init…")
+
+	log.Println("Creating /nix/store")
+	os.MkdirAll("/nix/store", os.ModePerm)
+
+	cmdline, err := os.ReadFile("/proc/cmdline")
+	if err != nil {
+		log.Printf("Failed to read cmdline: %s\n", err)
+	}
+	cmdlineFields := parseCmdline(string(cmdline))
+
+	log.Println("Mounting…")
+	if err := run("mount", "-t", "virtiofs", "tvix", "/nix/store", "-o", "ro"); err != nil {
+		log.Printf("Failed to run mount: %v\n", err)
+	}
+
+	// If tvix.find is set, invoke find /nix/store
+	if _, ok := cmdlineFields["tvix.find"]; ok {
+		log.Println("Listing…")
+		if err := run("find", "/nix/store"); err != nil {
+			log.Printf("Failed to run find command: %s\n", err)
+		}
+	}
+
+	// If tvix.shell is set, invoke the elvish shell
+	if v, ok := cmdlineFields["tvix.shell"]; ok {
+		log.Printf("Invoking shell%s\n…", v)
+		if err := run("elvish"); err != nil {
+			log.Printf("Failed to run shell: %s\n", err)
+		}
+	}
+
+	// If tvix.exec is set, invoke the binary specified
+	if v, ok := cmdlineFields["tvix.exec"]; ok {
+		log.Printf("Invoking %s\n…", v)
+		if err := syscall.Exec(v, []string{v}, []string{}); err != nil {
+			log.Printf("Failed to exec: %s\n", err)
+		}
+	}
+
+	log.Println("Powering off")
+	if err := run("poweroff"); err != nil {
+		log.Printf("Failed to run command: %v\n", err)
+	}
+}