2024-03-17 21:00:44 +01:00
|
|
|
{ depot, pkgs, lib, ... }:
|
2023-09-25 12:59:25 +02:00
|
|
|
|
2024-03-11 23:07:46 +01:00
|
|
|
let
|
2024-12-09 19:00:22 +01:00
|
|
|
# Seed a tvix-store with the specified path, then start a VM with the
|
|
|
|
# tvix-boot initrd.
|
|
|
|
# Allows customizing the cmdline, which can be used to list files,
|
|
|
|
# or specify what init should be booted.
|
2024-03-17 21:00:44 +01:00
|
|
|
mkBootTest =
|
|
|
|
{ blobServiceAddr ? "memory://"
|
|
|
|
, directoryServiceAddr ? "memory://"
|
|
|
|
, pathInfoServiceAddr ? "memory://"
|
2024-03-18 10:41:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
# The path to import.
|
|
|
|
, path
|
|
|
|
|
|
|
|
# Whether the path should be imported as a closure.
|
|
|
|
# If false, importPathName must be specified.
|
|
|
|
, isClosure ? false
|
2024-06-29 14:31:45 +02:00
|
|
|
# Whether to use nar-bridge to upload, rather than tvix-store copy.
|
|
|
|
# using nar-bridge currently is "slower", as the `pkgs.mkBinaryCache` build
|
|
|
|
# takes quite some time.
|
|
|
|
, useNarBridge ? false
|
|
|
|
|
2024-03-18 10:41:29 +01:00
|
|
|
, importPathName ? null
|
|
|
|
|
2024-06-29 16:51:00 +02:00
|
|
|
# Commands to run before starting the tvix-daemon. Useful to provide
|
|
|
|
# auxillary mock services.
|
|
|
|
, preStart ? ""
|
|
|
|
|
2024-03-18 11:08:47 +01:00
|
|
|
# The cmdline to pass to the VM.
|
|
|
|
# Defaults to tvix.find, which lists all files in the store.
|
|
|
|
, vmCmdline ? "tvix.find"
|
|
|
|
# The string we expect to find in the VM output.
|
|
|
|
# Defaults the value of `path` (the store path we upload).
|
|
|
|
, assertVMOutput ? path
|
2024-03-17 21:00:44 +01:00
|
|
|
}:
|
2024-03-18 10:41:29 +01:00
|
|
|
|
|
|
|
assert isClosure -> importPathName == null;
|
|
|
|
assert (!isClosure) -> importPathName != null;
|
|
|
|
|
2024-06-29 13:48:09 +02:00
|
|
|
pkgs.stdenv.mkDerivation ({
|
2024-03-18 10:41:29 +01:00
|
|
|
name = "run-vm";
|
|
|
|
|
|
|
|
nativeBuildInputs = [
|
|
|
|
depot.tvix.store
|
|
|
|
depot.tvix.boot.runVM
|
2024-06-29 14:31:45 +02:00
|
|
|
] ++ lib.optionals (isClosure && useNarBridge) [
|
2024-07-21 01:36:36 +02:00
|
|
|
depot.tvix.nar-bridge
|
2024-06-29 14:31:45 +02:00
|
|
|
pkgs.curl
|
|
|
|
pkgs.parallel
|
|
|
|
pkgs.xz.bin
|
2024-03-18 10:41:29 +01:00
|
|
|
];
|
|
|
|
buildCommand = ''
|
|
|
|
touch $out
|
2024-06-29 16:50:13 +02:00
|
|
|
# Ensure we can construct http clients.
|
2024-07-07 16:16:36 +02:00
|
|
|
export SSL_CERT_FILE=/dev/null
|
2024-03-18 10:41:29 +01:00
|
|
|
|
2024-06-29 16:51:00 +02:00
|
|
|
${preStart}
|
|
|
|
|
2024-03-18 10:41:29 +01:00
|
|
|
# Start the tvix daemon, listening on a unix socket.
|
2024-06-29 16:51:59 +02:00
|
|
|
BLOB_SERVICE_ADDR=${lib.escapeShellArg blobServiceAddr} \
|
|
|
|
DIRECTORY_SERVICE_ADDR=${lib.escapeShellArg directoryServiceAddr} \
|
|
|
|
PATH_INFO_SERVICE_ADDR=${lib.escapeShellArg pathInfoServiceAddr} \
|
2024-03-18 11:07:56 +01:00
|
|
|
tvix-store \
|
|
|
|
--otlp=false \
|
|
|
|
daemon -l $PWD/tvix-store.sock &
|
2024-03-18 10:41:29 +01:00
|
|
|
|
2024-07-23 16:21:56 +02:00
|
|
|
# Wait for the service to report healthy.
|
|
|
|
timeout 22 sh -c "until ${pkgs.ip2unix}/bin/ip2unix -r out,path=$PWD/tvix-store.sock ${pkgs.grpc-health-check}/bin/grpc-health-check --address 127.0.0.1 --port 8080; do sleep 1; done"
|
2024-03-18 10:41:29 +01:00
|
|
|
|
|
|
|
# Export env vars so that subsequent tvix-store commands will talk to
|
|
|
|
# our tvix-store daemon over the unix socket.
|
|
|
|
export BLOB_SERVICE_ADDR=grpc+unix://$PWD/tvix-store.sock
|
|
|
|
export DIRECTORY_SERVICE_ADDR=grpc+unix://$PWD/tvix-store.sock
|
|
|
|
export PATH_INFO_SERVICE_ADDR=grpc+unix://$PWD/tvix-store.sock
|
|
|
|
'' + lib.optionalString (!isClosure) ''
|
|
|
|
echo "Importing ${path} into tvix-store with name ${importPathName}…"
|
|
|
|
cp -R ${path} ${importPathName}
|
|
|
|
outpath=$(tvix-store import ${importPathName})
|
|
|
|
|
|
|
|
echo "imported to $outpath"
|
2024-06-29 14:31:45 +02:00
|
|
|
'' + lib.optionalString (isClosure && !useNarBridge) ''
|
2024-04-12 19:27:15 +02:00
|
|
|
echo "Copying closure ${path}…"
|
|
|
|
# This picks up the `closure` key in `$NIX_ATTRS_JSON_FILE` automatically.
|
|
|
|
tvix-store --otlp=false copy
|
2024-06-29 14:31:45 +02:00
|
|
|
'' + lib.optionalString (isClosure && useNarBridge) ''
|
|
|
|
echo "Starting nar-bridge…"
|
2024-07-21 01:36:36 +02:00
|
|
|
nar-bridge \
|
2024-06-29 14:31:45 +02:00
|
|
|
--otlp=false \
|
2024-07-21 01:36:36 +02:00
|
|
|
-l $PWD/nar-bridge.sock &
|
2024-06-29 14:31:45 +02:00
|
|
|
|
2024-07-23 16:22:29 +02:00
|
|
|
# Wait for nar-bridge to report healthy.
|
|
|
|
timeout 22 sh -c "until ${pkgs.curl}/bin/curl -s --unix-socket $PWD/nar-bridge.sock http:///nix-binary-cache; do sleep 1; done"
|
2024-06-29 14:31:45 +02:00
|
|
|
|
|
|
|
# Upload. We can't use nix copy --to http://…, as it wants access to the nix db.
|
|
|
|
# However, we can use mkBinaryCache to assemble .narinfo and .nar.xz to upload,
|
|
|
|
# and then drive a HTTP client ourselves.
|
|
|
|
to_upload=${pkgs.mkBinaryCache { rootPaths = [path];}}
|
|
|
|
|
|
|
|
# Upload all NAR files (with some parallelism).
|
|
|
|
# As mkBinaryCache produces them xz-compressed, unpack them on the fly.
|
|
|
|
# nar-bridge doesn't care about the path we upload *to*, but a
|
|
|
|
# subsequent .narinfo upload need to refer to its contents (by narhash).
|
|
|
|
echo -e "Uploading NARs… "
|
|
|
|
ls -d $to_upload/nar/*.nar.xz | parallel 'xz -d < {} | curl -s -T - --unix-socket $PWD/nar-bridge.sock http://localhost:9000/nar/$(basename {} | cut -d "." -f 1).nar'
|
|
|
|
echo "Done."
|
|
|
|
|
|
|
|
# Upload all NARInfo files.
|
|
|
|
# FUTUREWORK: This doesn't upload them in order, and currently relies
|
|
|
|
# on PathInfoService not doing any checking.
|
|
|
|
# In the future, we might want to make this behaviour configurable,
|
|
|
|
# and disable checking here, to keep the logic simple.
|
|
|
|
ls -d $to_upload/*.narinfo | parallel 'curl -s -T - --unix-socket $PWD/nar-bridge.sock http://localhost:9000/$(basename {}) < {}'
|
2024-03-18 10:41:29 +01:00
|
|
|
'' + ''
|
|
|
|
# Invoke a VM using tvix as the backing store, ensure the outpath appears in its listing.
|
2024-03-18 11:09:49 +01:00
|
|
|
echo "Starting VM…"
|
2024-03-18 10:41:29 +01:00
|
|
|
|
2024-03-18 11:08:47 +01:00
|
|
|
CH_CMDLINE="${vmCmdline}" run-tvix-vm 2>&1 | tee output.txt
|
|
|
|
grep "${assertVMOutput}" output.txt
|
2024-03-18 10:41:29 +01:00
|
|
|
'';
|
|
|
|
requiredSystemFeatures = [ "kvm" ];
|
2024-08-17 19:03:44 +02:00
|
|
|
# HACK: The boot tests are sometimes flaky, and we don't want them to
|
|
|
|
# periodically fail other build. Have Buildkite auto-retry them 2 times
|
|
|
|
# on failure.
|
|
|
|
# Logs for individual failures are still available, so it won't hinder
|
|
|
|
# flakiness debuggability.
|
|
|
|
meta.ci.buildkiteExtraStepArgs = {
|
|
|
|
retry.automatic = true;
|
|
|
|
};
|
2024-06-29 14:31:45 +02:00
|
|
|
} // lib.optionalAttrs (isClosure && !useNarBridge) {
|
2024-06-29 13:48:09 +02:00
|
|
|
__structuredAttrs = true;
|
|
|
|
exportReferencesGraph.closure = [ path ];
|
|
|
|
});
|
2024-03-18 11:09:49 +01:00
|
|
|
|
2024-08-19 15:08:33 +02:00
|
|
|
testSystem = (pkgs.nixos {
|
2024-03-18 11:09:49 +01:00
|
|
|
# Set some options necessary to evaluate.
|
|
|
|
boot.loader.systemd-boot.enable = true;
|
|
|
|
# TODO: figure out how to disable this without causing eval to fail
|
|
|
|
fileSystems."/" = {
|
|
|
|
device = "/dev/root";
|
|
|
|
fsType = "tmpfs";
|
|
|
|
};
|
|
|
|
|
|
|
|
services.getty.helpLine = "Onwards and upwards.";
|
|
|
|
systemd.services.do-shutdown = {
|
|
|
|
after = [ "getty.target" ];
|
|
|
|
description = "Shut down again";
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
serviceConfig.Type = "oneshot";
|
|
|
|
script = "/run/current-system/sw/bin/systemctl poweroff --when=+10s";
|
|
|
|
};
|
|
|
|
|
|
|
|
# Don't warn about stateVersion.
|
|
|
|
system.stateVersion = "24.05";
|
2024-08-19 15:08:33 +02:00
|
|
|
|
|
|
|
# Speed-up evaluation and building.
|
|
|
|
documentation.enable = lib.mkForce false;
|
|
|
|
}).config.system.build.toplevel;
|
2024-03-18 11:09:49 +01:00
|
|
|
|
2024-03-11 23:07:46 +01:00
|
|
|
in
|
2024-03-18 10:41:29 +01:00
|
|
|
depot.nix.readTree.drvTargets
|
|
|
|
{
|
|
|
|
docs-memory = (mkBootTest {
|
|
|
|
path = ../../docs;
|
|
|
|
importPathName = "docs";
|
|
|
|
});
|
2024-05-10 12:45:07 +02:00
|
|
|
docs-persistent = (mkBootTest {
|
2024-06-29 16:51:59 +02:00
|
|
|
blobServiceAddr = "objectstore+file:///build/blobs";
|
2024-08-01 17:03:03 +02:00
|
|
|
directoryServiceAddr = "redb:///build/directories.redb";
|
|
|
|
pathInfoServiceAddr = "redb:///build/pathinfo.redb";
|
2024-03-18 10:41:29 +01:00
|
|
|
path = ../../docs;
|
|
|
|
importPathName = "docs";
|
2024-03-17 21:00:44 +01:00
|
|
|
});
|
2024-03-18 10:41:29 +01:00
|
|
|
|
|
|
|
closure-tvix = (mkBootTest {
|
2024-06-29 16:51:59 +02:00
|
|
|
blobServiceAddr = "objectstore+file:///build/blobs";
|
2024-03-18 10:41:29 +01:00
|
|
|
path = depot.tvix.store;
|
|
|
|
isClosure = true;
|
2024-03-17 21:00:44 +01:00
|
|
|
});
|
2024-03-18 11:09:49 +01:00
|
|
|
|
|
|
|
closure-nixos = (mkBootTest {
|
2024-06-29 16:51:59 +02:00
|
|
|
blobServiceAddr = "objectstore+file:///build/blobs";
|
2024-07-21 00:36:19 +02:00
|
|
|
pathInfoServiceAddr = "redb:///build/pathinfo.redb";
|
2024-07-26 22:46:24 +02:00
|
|
|
directoryServiceAddr = "redb:///build/directories.redb";
|
2024-03-18 11:09:49 +01:00
|
|
|
path = testSystem;
|
|
|
|
isClosure = true;
|
|
|
|
vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic
|
|
|
|
assertVMOutput = "Onwards and upwards.";
|
|
|
|
});
|
2024-06-29 14:31:45 +02:00
|
|
|
|
2024-06-29 16:52:53 +02:00
|
|
|
closure-nixos-bigtable = (mkBootTest {
|
|
|
|
blobServiceAddr = "objectstore+file:///build/blobs";
|
|
|
|
directoryServiceAddr = "bigtable://instance-1?project_id=project-1&table_name=directories&family_name=cf1";
|
|
|
|
pathInfoServiceAddr = "bigtable://instance-1?project_id=project-1&table_name=pathinfos&family_name=cf1";
|
|
|
|
path = testSystem;
|
|
|
|
useNarBridge = true;
|
|
|
|
preStart = ''
|
|
|
|
${pkgs.cbtemulator}/bin/cbtemulator -address $PWD/cbtemulator.sock &
|
|
|
|
timeout 22 sh -c 'until [ -e $PWD/cbtemulator.sock ]; do sleep 1; done'
|
|
|
|
|
|
|
|
export BIGTABLE_EMULATOR_HOST=unix://$PWD/cbtemulator.sock
|
|
|
|
${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createtable directories
|
|
|
|
${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createfamily directories cf1
|
|
|
|
${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createtable pathinfos
|
|
|
|
${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createfamily pathinfos cf1
|
|
|
|
'';
|
|
|
|
isClosure = true;
|
|
|
|
vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic
|
|
|
|
assertVMOutput = "Onwards and upwards.";
|
|
|
|
});
|
|
|
|
|
2024-06-29 17:10:31 +02:00
|
|
|
closure-nixos-s3 = (mkBootTest {
|
|
|
|
blobServiceAddr = "objectstore+s3://mybucket/blobs?aws_access_key_id=myaccesskey&aws_secret_access_key=supersecret&aws_endpoint_url=http%3A%2F%2Flocalhost%3A9000&aws_allow_http=1";
|
|
|
|
# we cannot use s3 here yet without any caching layer, as we don't allow "deeper" access to directories (non-root nodes)
|
|
|
|
# directoryServiceAddr = "objectstore+s3://mybucket/directories?aws_access_key_id=myaccesskey&aws_secret_access_key=supersecret&endpoint=http%3A%2F%2Flocalhost%3A9000&aws_allow_http=1";
|
|
|
|
directoryServiceAddr = "memory://";
|
|
|
|
pathInfoServiceAddr = "memory://";
|
|
|
|
path = testSystem;
|
|
|
|
useNarBridge = true;
|
|
|
|
preStart = ''
|
|
|
|
MINIO_ACCESS_KEY=myaccesskey MINIO_SECRET_KEY=supersecret MINIO_ADDRESS=127.0.0.1:9000 ${pkgs.minio}/bin/minio server $(mktemp -d) &
|
|
|
|
timeout 22 sh -c 'until ${pkgs.netcat}/bin/nc -z $0 $1; do sleep 1; done' localhost 9000
|
|
|
|
mc_config_dir=$(mktemp -d)
|
|
|
|
${pkgs.minio-client}/bin/mc --config-dir $mc_config_dir alias set 'myminio' 'http://127.0.0.1:9000' 'myaccesskey' 'supersecret'
|
|
|
|
${pkgs.minio-client}/bin/mc --config-dir $mc_config_dir mb myminio/mybucket
|
|
|
|
'';
|
|
|
|
isClosure = true;
|
|
|
|
vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic
|
|
|
|
assertVMOutput = "Onwards and upwards.";
|
|
|
|
});
|
|
|
|
|
2024-06-29 14:31:45 +02:00
|
|
|
closure-nixos-nar-bridge = (mkBootTest {
|
2024-06-29 16:51:59 +02:00
|
|
|
blobServiceAddr = "objectstore+file:///build/blobs";
|
2024-06-29 14:31:45 +02:00
|
|
|
path = testSystem;
|
|
|
|
useNarBridge = true;
|
|
|
|
isClosure = true;
|
|
|
|
vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic
|
|
|
|
assertVMOutput = "Onwards and upwards.";
|
|
|
|
});
|
2023-09-25 12:59:25 +02:00
|
|
|
}
|