m/t/installer: resolve deps with bazel.Runfile
Change-Id: Ie69b8b6ef12028264d1c396dacb3c00be795ad44
Reviewed-on: https://review.monogon.dev/c/monogon/+/455
Reviewed-by: Sergiusz Bazanski <serge@monogon.tech>
diff --git a/metropolis/test/installer/main.go b/metropolis/test/installer/main.go
index ea2c20a..0f2f40e 100644
--- a/metropolis/test/installer/main.go
+++ b/metropolis/test/installer/main.go
@@ -27,23 +27,35 @@
"log"
"os"
"os/exec"
+ "path/filepath"
"syscall"
"testing"
+ "github.com/bazelbuild/rules_go/go/tools/bazel"
diskfs "github.com/diskfs/go-diskfs"
"github.com/diskfs/go-diskfs/disk"
"github.com/diskfs/go-diskfs/partition/gpt"
- "source.monogon.dev/metropolis/proto/api"
mctl "source.monogon.dev/metropolis/cli/metroctl/core"
- osimage "source.monogon.dev/metropolis/node/build/mkimage/osimage"
+ "source.monogon.dev/metropolis/node/build/mkimage/osimage"
+ "source.monogon.dev/metropolis/proto/api"
)
-const (
- InstallerEFIPayload = "metropolis/node/installer/kernel.efi"
- TestOSBundle = "metropolis/test/installer/testos/testos_bundle.zip"
- InstallerImage = "metropolis/test/installer/installer.img"
- NodeStorage = "metropolis/test/installer/stor.img"
+// Each variable in this block points to either a test dependency or a side
+// effect. These variables are initialized in TestMain using Bazel.
+var (
+ // installerEFIPayload is a filesystem path pointing at the unified kernel
+ // image dependency.
+ installerEFIPayload string
+ // testOSBundle is a filesystem path pointing at the Metropolis installation
+ // bundle.
+ testOSBundle string
+ // installerImage is a filesystem path pointing at the installer image that
+ // is generated during the test, and is removed afterwards.
+ installerImage string
+ // nodeStorage is a filesystem path pointing at the VM block device image
+ // Metropolis is installed to during the test. The file is removed afterwards.
+ nodeStorage string
)
// runQemu starts a QEMU process and waits for it to finish. args is
@@ -89,22 +101,22 @@
// concatenated to the list of predefined default arguments. It returns true if
// expectedOutput is found in the serial port output. It may return an error.
func runQemuWithInstaller(args []string, expectedOutput string) (bool, error) {
- args = append(args, "-drive", "if=virtio,format=raw,snapshot=on,cache=unsafe,file="+InstallerImage)
+ args = append(args, "-drive", "if=virtio,format=raw,snapshot=on,cache=unsafe,file="+installerImage)
return runQemu(args, expectedOutput)
}
// getStorage creates a sparse file, given a size expressed in mebibytes, and
// returns a path to that file. It may return an error.
func getStorage(size int64) (string, error) {
- image, err := os.Create(NodeStorage)
+ image, err := os.Create(nodeStorage)
if err != nil {
- return "", fmt.Errorf("couldn't create the block device image at %q: %w", NodeStorage, err)
+ return "", fmt.Errorf("couldn't create the block device image at %q: %w", nodeStorage, err)
}
if err := syscall.Ftruncate(int(image.Fd()), size*1024*1024); err != nil {
- return "", fmt.Errorf("couldn't resize the block device image at %q: %w", NodeStorage, err)
+ return "", fmt.Errorf("couldn't resize the block device image at %q: %w", nodeStorage, err)
}
image.Close()
- return NodeStorage, nil
+ return nodeStorage, nil
}
// qemuDriveParam returns QEMU parameters required to run it with a
@@ -131,18 +143,50 @@
}
func TestMain(m *testing.M) {
+ // Initialize global variables holding filesystem paths pointing to runtime
+ // dependencies and side effects.
+ paths := []struct {
+ // res is a pointer to the global variable initialized.
+ res *string
+ // dep states whether the path should be resolved as a dependency, rather
+ // than a side effect.
+ dep bool
+ // src is a source path, based on which res is resolved. In case of
+ // dependencies it must be a path relative to the repository root. For
+ // side effects, it must be just a filename.
+ src string
+ }{
+ {&installerEFIPayload, true, "metropolis/node/installer/kernel.efi"},
+ {&testOSBundle, true, "metropolis/test/installer/testos/testos_bundle.zip"},
+ {&installerImage, false, "installer.img"},
+ {&nodeStorage, false, "stor.img"},
+ }
+ for _, p := range paths {
+ if p.dep {
+ res, err := bazel.Runfile(p.src)
+ if err != nil {
+ log.Fatal(err)
+ }
+ *p.res = res
+ } else {
+ od := os.Getenv("TEST_TMPDIR")
+ // If od is empty, just use the working directory, which is set according
+ // to the rundir attribute of go_test.
+ *p.res = filepath.Join(od, p.src)
+ }
+ }
+
// Build the installer image with metroctl, given the EFI executable
- // generated by Metropolis buildsystem. This mimics standard usage of
- // metroctl CLI.
- installer, err := os.Open(InstallerEFIPayload)
+ // generated by Metropolis buildsystem.
+ installer, err := os.Open(installerEFIPayload)
if err != nil {
- log.Fatalf("Couldn't open the installer EFI executable at %q: %s", InstallerEFIPayload, err.Error())
+ log.Fatalf("Couldn't open the installer EFI executable at %q: %s", installerEFIPayload, err.Error())
}
info, err := installer.Stat()
if err != nil {
log.Fatalf("Couldn't stat the installer EFI executable: %s", err.Error())
}
- bundle, err := os.Open(TestOSBundle)
+ bundle, err := os.Open(testOSBundle)
if err != nil {
log.Fatalf("failed to open TestOS bundle: %v", err)
}
@@ -153,27 +197,27 @@
iargs := mctl.MakeInstallerImageArgs{
Installer: installer,
InstallerSize: uint64(info.Size()),
- TargetPath: InstallerImage,
+ TargetPath: installerImage,
NodeParams: &api.NodeParameters{},
Bundle: bundle,
BundleSize: uint64(bundleStat.Size()),
}
if err := mctl.MakeInstallerImage(iargs); err != nil {
- log.Fatalf("Couldn't create the installer image at %q: %s", InstallerImage, err.Error())
+ log.Fatalf("Couldn't create the installer image at %q: %s", installerImage, err.Error())
}
// With common dependencies set up, run the tests.
code := m.Run()
// Clean up.
- os.Remove(InstallerImage)
+ os.Remove(installerImage)
os.Exit(code)
}
func TestInstallerImage(t *testing.T) {
// This test examines the installer image, making sure that the GPT and the
// ESP contents are in order.
- image, err := diskfs.OpenWithMode(InstallerImage, diskfs.ReadOnly)
+ image, err := diskfs.OpenWithMode(installerImage, diskfs.ReadOnly)
if err != nil {
- t.Errorf("Couldn't open the installer image at %q: %s", InstallerImage, err.Error())
+ t.Errorf("Couldn't open the installer image at %q: %s", installerImage, err.Error())
}
// Verify that GPT exists.
ti, err := image.GetPartitionTable()