Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ result*/**
/bin
sysroot
devroot
creds.json
111 changes: 111 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,117 @@ let
config.Cmd = [ "/libexec/frr/docker-start" ];
};

# Local dev-only container image for the vlab test environment. Replaces
# the old Ubuntu-based scripts/vlab/Dockerfile: every tool the vlab runtime
# needs comes from nix (pinned via npins), not apt + wget + `curl | bash`,
# so there is no unverified download in the image build.
#
# The hhfab CLI is still fetched at runtime via i.hhdev.io/hhfab -- it is
# a fast-moving test tool that we intentionally track against master rather
# than pin into the image closure.
#
# Fixed tag "latest" so scripts/vlab/run.sh can refer to `vlab` unambiguously
# without threading the dataplane's `tag` argstr through.
containers.vlab = pkgs.dockerTools.buildLayeredImage {
name = "vlab";
tag = "latest";
contents = pkgs.buildEnv {
name = "vlab-env";
pathsToLink = [ "/" ];
paths = with pkgs.pkgsHostHost; [
bashInteractive
cacert
coreutils
curl
docker-client
dockerTools.binSh
dockerTools.fakeNss
dockerTools.usrBinEnv
findutils
gawk
git
gnugrep
gnused
gnutar
gzip
iproute2
jq
less
neovim
openssh
openssl
oras
qemu_kvm
socat
sudo
wget
# Python's kislyuk yq (supports the `-y` flag used by run.sh);
# nixpkgs.yq-go is mikefarah's Go port with a different CLI surface.
yq
zot

# nixpkgs' sudo is always built with PAM on linux, so we need to ship
# a /etc/pam.d/sudo config or sudo aborts with "unable to initialize
# PAM: Critical error - immediate abort" the moment hhfab vlab up
# shells out to it. The container runs as root in a privileged
# sandbox, so we use pam_permit.so for every stage; absolute module
# paths sidestep libpam's compiled-in module search path.
(writeTextDir "etc/pam.d/sudo" ''
auth sufficient ${pam}/lib/security/pam_permit.so
account sufficient ${pam}/lib/security/pam_permit.so
password sufficient ${pam}/lib/security/pam_permit.so
session sufficient ${pam}/lib/security/pam_permit.so
'')

# zot config and cert.ini are immutable across runs, so they live
# in the image rather than in any mount or bind-mount.
(writeTextDir "etc/zot/config.json" (builtins.readFile ./scripts/vlab/root/etc/zot/config.json))
(writeTextDir "etc/zot/cert.ini" (builtins.readFile ./scripts/vlab/root/etc/zot/cert.ini))

# Entrypoint script: generates TLS material into a tmpfs, validates
# or provisions ghcr.io credentials in a persistent docker volume,
# then execs zot. See scripts/vlab/entrypoint.sh for modes.
(writeShellApplication {
name = "vlab-entrypoint";
runtimeInputs = [
cacert
coreutils
curl
jq
openssl
zot
];
text = builtins.readFile ./scripts/vlab/entrypoint.sh;
})
];
};

# /tmp, /run/vlab (for the merged CA bundle), and /vlab (the working/volume
# dir) don't exist in the pure nix closure; pre-create them so the
# entrypoint and docker exec commands can write to them.
# /tmp and the /vlab working dir don't exist in the pure nix closure;
# pre-create them so docker exec commands can write to them. The tmpfs
# at /run/vlab and the vlab-secrets volume at /var/lib/vlab are created
# by docker at container start.
extraCommands = ''
mkdir -p tmp vlab
chmod 1777 tmp
'';

config = {
WorkingDir = "/vlab";
Volumes."/vlab" = { };
Env = [
# Go (and hhfab) read SSL_CERT_FILE; the entrypoint writes the merged
# bundle (nixpkgs system CAs + the freshly-minted zot CA) to this path
# before exec'ing zot.
"SSL_CERT_FILE=/run/vlab/ca-bundle.pem"
];
Entrypoint = [ "/bin/vlab-entrypoint" ];
Cmd = [ "run" ];
};
};

containers.frr.host = pkgs.dockerTools.buildLayeredImage {
name = "ghcr.io/githedgehog/dataplane/frr-host";
inherit tag;
Expand Down
57 changes: 57 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,60 @@ bump_version version:
[script]
shell:
nix-shell

# OCI repo used by the vlab Zot registry
[private]
vlab_oci_repo := "192.168.19.1:30000"

# Start the vlab environment
[script]
vlab-up: (build "containers.vlab")
{{ _just_debuggable_ }}
docker load < ./results/containers.vlab
pushd ./scripts/vlab
./run.sh
popd

# Open a shell or run a command on the vlab control plane
[script]
vlab-control *args:
{{ _just_debuggable_ }}
pushd ./scripts/vlab
./control.sh {{ args }}
popd

# Stop the vlab container and remove the docker network
[confirm]
[script]
vlab-down:
{{ _just_debuggable_ }}
docker stop vlab || true
docker rm vlab || true
docker network rm zot || true

# Stop vlab and remove all associated docker volumes
[confirm]
[script]
vlab-purge: vlab-down
{{ _just_debuggable_ }}
docker volume rm vlab || true
docker volume rm zot || true
docker volume rm vlab-secrets || true

# Build, push the dataplane image to the vlab registry, and patch the running fabric
[script]
vlab-patch-dataplane:
{{ _just_debuggable_ }}
just oci_insecure=true oci_repo="{{ vlab_oci_repo }}" push-container dataplane
pushd ./scripts/vlab
./control.sh kubectl -n fab patch fab/default --type=merge -p '{"spec":{"overrides":{"versions":{"gateway":{"dataplane":"{{version}}"}}}}}'
popd

# Build, push the FRR image to the vlab registry, and patch the running fabric
[script]
vlab-patch-frr:
{{ _just_debuggable_ }}
just oci_insecure=true oci_repo="{{ vlab_oci_repo }}" push-container frr.dataplane
pushd ./scripts/vlab
./control.sh kubectl -n fab patch fab/default --type=merge -p '{"spec":{"overrides":{"versions":{"gateway":{"frr":"{{version}}"}}}}}'
popd
3 changes: 3 additions & 0 deletions nix/overlays/dataplane-dev.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ in
opengrep = final.callPackage ../pkgs/opengrep {
src = sources.opengrep;
};
zot = final.callPackage ../pkgs/zot {
src = sources.zot;
};
cargo-bolero = prev.cargo-bolero.override { inherit (override-packages) rustPlatform; };
cargo-deny = prev.cargo-deny.override { inherit (override-packages) rustPlatform; };
cargo-edit = prev.cargo-edit.override { inherit (override-packages) rustPlatform; };
Expand Down
1 change: 1 addition & 0 deletions nix/pkgs/zot/binary.sri
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sha256-a8CsTdz/c1F0tsc45u6cNXmYwjxVRlC+hhNdI3IN3Yw=
51 changes: 51 additions & 0 deletions nix/pkgs/zot/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Install a prebuilt zot binary from upstream GitHub releases. The project
# ships statically-linked linux/amd64 binaries per release; we fetch the asset
# directly rather than rebuild it from source.
#
# Versioning: the tag name (e.g. "v2.1.15") comes from the npins `zot` pin,
# so a plain `npins update` (i.e. `just bump pins`) bumps the version.
# The release asset is a raw ELF binary (no archive), which npins' tarball
# pin type rejects, so the binary's content hash is carried in ./binary.sri
# and is refreshed by scripts/bump.sh on every `just bump pins`.
{
stdenvNoCC,
fetchurl,
autoPatchelfHook,
lib,
src,
}:
stdenvNoCC.mkDerivation {
pname = "zot";
# src.version carries the tag (e.g. "v2.1.15"); strip the leading "v" so
# the derivation name reads as a plain version.
version = lib.removePrefix "v" src.version;

src = fetchurl {
url = "https://github.com/project-zot/zot/releases/download/${src.version}/zot-linux-amd64";
hash = lib.removeSuffix "\n" (builtins.readFile ./binary.sri);
};

dontUnpack = true;
dontStrip = true;
dontConfigure = true;
dontBuild = true;

# zot ships a statically-linked Go binary, so autoPatchelfHook has nothing
# to patch; it's kept as a safety net in case upstream ever switches to a
# dynamically-linked build.
nativeBuildInputs = [ autoPatchelfHook ];

installPhase = ''
runHook preInstall
install -Dm755 $src $out/bin/zot
runHook postInstall
'';

meta = {
description = "OCI-native container image registry";
homepage = "https://zotregistry.dev";
license = lib.licenses.asl20;
mainProgram = "zot";
platforms = [ "x86_64-linux" ];
};
}
29 changes: 29 additions & 0 deletions npins/sources.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions scripts/bump.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@ nix-hash --to-sri --type sha256 \
"$(nix-prefetch-url --type sha256 "$opengrep_url")" \
> nix/pkgs/opengrep/binary.sri

# Refresh the zot release-asset content hash on the same contract as opengrep
# above: the pin tracks the tag, the raw binary hash lives in
# nix/pkgs/zot/binary.sri.
zot_version="$(jq --exit-status --raw-output '.pins.zot.version' npins/sources.json)"
zot_url="https://github.com/project-zot/zot/releases/download/${zot_version}/zot-linux-amd64"
nix-hash --to-sri --type sha256 \
"$(nix-prefetch-url --type sha256 "$zot_url")" \
> nix/pkgs/zot/binary.sri

./scripts/update-doc-headers.sh
3 changes: 3 additions & 0 deletions scripts/gen-pins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ npins add github githedgehog dplane-plugin --branch master # floats with branch
npins add github opengrep opengrep
npins add github mermaid-js mermaid --release-prefix "mermaid@"
npins add github KaTeX KaTeX

npins add github project-zot zot
npins add github githedgehog fabricator --branch master # floats with branch on pin bump
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean it'll not be always using latest master? If that's the case, it's quite bad - in dev you should use either last release or actual latest master, no pinning for some intermidiate commits.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand this logic, but I can make it use the latest master easily.

It is actually easier that way. It's just that we pin literally every other thing. All of it. Including the api and everything

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can also very easily make it use latest release, which makes more sense to me (but might cause DX problems)

20 changes: 20 additions & 0 deletions scripts/vlab/control.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0
# Copyright Open Network Fabric Authors

Comment thread
daniel-noland marked this conversation as resolved.
set -euo pipefail

if [ -z "$*" ]; then
declare -r cmd="k9s --namespace fab --command pod"
else
declare -r cmd="$(printf '%q ' "$@")"
fi

docker exec -it vlab \
ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-t \
-p 22000 \
-i /vlab/vlab/sshkey \
core@localhost "export PATH=\"/usr/bin:/bin:/opt/bin\"; $cmd"
Comment thread
daniel-noland marked this conversation as resolved.
Loading
Loading