Merge staging-next into staging
This commit is contained in:
+1
-1
@@ -263,7 +263,7 @@
|
||||
- any-glob-to-any-file:
|
||||
- nixos/modules/services/cluster/rancher/default.nix
|
||||
- nixos/modules/services/cluster/rancher/k3s.nix
|
||||
- nixos/tests/k3s/**/*
|
||||
- nixos/tests/rancher/**/*
|
||||
- pkgs/applications/networking/cluster/k3s/**/*
|
||||
|
||||
"6.topic: kernel":
|
||||
|
||||
@@ -439,6 +439,7 @@ pkgs/by-name/fo/forgejo/ @adamcstephens @bendlas @emilylange
|
||||
/pkgs/build-support/node/prefetch-npm-deps @winterqt
|
||||
/doc/languages-frameworks/javascript.section.md @winterqt
|
||||
/pkgs/development/tools/pnpm @Scrumplex @gepbird
|
||||
/pkgs/build-support/node/fetch-pnpm-deps @Scrumplex @gepbird
|
||||
|
||||
# OCaml
|
||||
/pkgs/build-support/ocaml @ulrikstrid
|
||||
|
||||
@@ -1185,12 +1185,6 @@
|
||||
"module-services-gitlab-maintenance-rake": [
|
||||
"index.html#module-services-gitlab-maintenance-rake"
|
||||
],
|
||||
"module-services-gitlab-runner": [
|
||||
"index.html#module-services-gitlab-runner"
|
||||
],
|
||||
"ex-gitlab-runner-podman": [
|
||||
"index.html#ex-gitlab-runner-podman"
|
||||
],
|
||||
"module-forgejo": [
|
||||
"index.html#module-forgejo"
|
||||
],
|
||||
|
||||
@@ -502,7 +502,7 @@
|
||||
./services/continuous-integration/buildkite-agents.nix
|
||||
./services/continuous-integration/gitea-actions-runner.nix
|
||||
./services/continuous-integration/github-runners.nix
|
||||
./services/continuous-integration/gitlab-runner/runner.nix
|
||||
./services/continuous-integration/gitlab-runner.nix
|
||||
./services/continuous-integration/gocd-agent/default.nix
|
||||
./services/continuous-integration/gocd-server/default.nix
|
||||
./services/continuous-integration/hercules-ci-agent/default.nix
|
||||
|
||||
@@ -10,7 +10,6 @@ configure a webserver to proxy HTTP requests to the socket.
|
||||
|
||||
For instance, the following configuration could be used to use nginx as
|
||||
frontend proxy:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.nginx = {
|
||||
@@ -41,7 +40,6 @@ The default state dir is `/var/gitlab/state`. This is where
|
||||
all data like the repositories and uploads will be stored.
|
||||
|
||||
A basic configuration with some custom settings could look like this:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.gitlab = {
|
||||
@@ -106,7 +104,6 @@ the [services.gitlab.backup.startAt](#opt-services.gitlab.backup.startAt)
|
||||
option to configure regular backups.
|
||||
|
||||
To run a manual backup, start the `gitlab-backup` service:
|
||||
|
||||
```ShellSession
|
||||
$ systemctl start gitlab-backup.service
|
||||
```
|
||||
@@ -119,116 +116,6 @@ will have to run the command as the user that you configured to run
|
||||
GitLab with.
|
||||
|
||||
A list of all available rake tasks can be obtained by running:
|
||||
|
||||
```ShellSession
|
||||
$ sudo -u git -H gitlab-rake -T
|
||||
```
|
||||
|
||||
## Runner {#module-services-gitlab-runner}
|
||||
|
||||
GitLab Runner is a CI runner which is an executable which you can host yourself.
|
||||
A Gitlab pipeline runs operations over a Gitlab Runner. These can include
|
||||
building an executable, running a test suite, pushing a docker image, etc. The
|
||||
Gitlab Runner receives jobs from Gitlab which it then dispatches to the
|
||||
configured executors
|
||||
([`docker` (`podman`), or `shell` or `kubernetes`](https://docs.gitlab.com/runner/executors)).
|
||||
|
||||
The
|
||||
[services.gitlab-runner.services](https://search.nixos.org/options?query=services.gitlab-runner.services)
|
||||
documents a number of typical setups to configure multiple runners with
|
||||
different executors.
|
||||
|
||||
The [below example](#ex-gitlab-runner-podman) gives a **more elaborate** example how to
|
||||
configure a Gitlab Runner with caching and reasonably good security practices.
|
||||
|
||||
::: {#ex-gitlab-runner-podman .example}
|
||||
|
||||
## Example: Gitlab Runner with `podman` and Nix Store Caching
|
||||
|
||||
The [VM tested `podman-runner`](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/continuous-integration/gitlab-runner/runner.nix)
|
||||
(a NixOS module for reuse) configures an advanced Gitlab runner with the following features:
|
||||
|
||||
- The executor is `podman` which gives you better additional safety than
|
||||
`docker`. That means every job is run in a `podman` container.
|
||||
|
||||
- The following container **images** are built with Nix:
|
||||
|
||||
**Container Images for Gitlab Jobs**:
|
||||
- `local/alpine`: An image based on Alpine with a Nix installation
|
||||
(attribute `jobImages.alpine`).
|
||||
- `local/ubuntu`: An image based on Ubuntu with a Nix installation
|
||||
(attribute `jobImages.ubuntu`).
|
||||
- `local/nix`: An image based on Nix which only comes with `nix`
|
||||
installed (attribute `jobImages.nix`).
|
||||
|
||||
**Images for VM Setup**:
|
||||
- `local/nix-daemon-image`: An image with a Nix daemon which is
|
||||
used to share the `/nix/store` across jobs (variable `nixDaemonImage`) setup with some essentials derivations `bootstrapPkgs`.
|
||||
- `local/podman-daemon-image`: An image with `podman` running as a daemon which is
|
||||
used to run `podman` inside the above job containers images
|
||||
(variable `podmanDaemonImage`).
|
||||
|
||||
- Every job container runs in a `podman` container instance based by default on
|
||||
`jobImage.ubuntu`. A pipeline job can override this with `image: local/alpine`.
|
||||
- Each job container will have the `/nix/store` mounted from the container
|
||||
`nix-daemon-container` (see registration flags
|
||||
`--docker-volumes-from "nix-daemon-container:ro"`).
|
||||
|
||||
The `nix-daemon-container` is a single container instance of a
|
||||
`nixDaemonImage`. This enables caching of `/nix/store` paths across all jobs
|
||||
in **all** runners. This makes **the host VM's `/nix/store` independent of the
|
||||
Nix store used in the jobs**, which is good.
|
||||
|
||||
::: {.note}
|
||||
**Security:** If you don't want this you need multiple `nixDaemonImage`
|
||||
containers for each registered runner (`gitlab-runner.services.<name>`).
|
||||
:::
|
||||
|
||||
- Each job container will have the `/run/podman/podman.sock` socket mounted from the
|
||||
`podman-daemon-container`.
|
||||
|
||||
The `podman-daemon-container` is a single container of a `podmanDaemonImage` which runs
|
||||
`podman` as a daemon. Job containers can use this daemon to spawn nested containers as well (podman-in-podman).
|
||||
**Keep in mind that `bind` mounts are local to the `podman-daemon-container`**
|
||||
and can be be worked around with a `podman volume create <vol>` and manual copy-to/copy-from this volume `<vol>`.
|
||||
|
||||
If you only need to build containers you don't need this feature (`podman-daemon-container`), see below point.
|
||||
|
||||
Container configuration files (`auxRootFiles`) are copied to all containers to
|
||||
ensure `podman` works consistently inside the job containers.
|
||||
|
||||
- The job containers do **not** mount the `podman` socket from the host (NixOS
|
||||
VM) mounted for security reasons.
|
||||
|
||||
::: {.note}
|
||||
Building container images with `buildah` (stripped
|
||||
`podman` for building images) inside a job which runs `jobImage.alpine`
|
||||
is still possible.
|
||||
:::
|
||||
|
||||
- **Cleanup Disk Space**:
|
||||
|
||||
With this setup its really easy to clean the `nix-daemon-container`
|
||||
(e.g. if you run out of disk space), then reboot and have the runner in a clean state.
|
||||
You can do the following to effectively clean everything and start with fresh volumes safely:
|
||||
|
||||
```bash
|
||||
# Stop the Gitlab runner.
|
||||
systemctl stop gitlab-runner.service
|
||||
# Stop `systemd`-managed containers, such that they get not recreated
|
||||
# when deleting below.
|
||||
systemctl stop podman-podman-daemon-container.service \
|
||||
podman-nix-daemon-container.service \
|
||||
podman-nix-container.service \
|
||||
podman-alpine-container.service \
|
||||
podman-ubuntu-container.service || true
|
||||
|
||||
podman container rm -f --all
|
||||
podman image rm -f --all
|
||||
podman volumes rm -f --all
|
||||
|
||||
reboot
|
||||
# Systemd will restart all containers and create volumes etc.
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -89,6 +89,18 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "photoprism";
|
||||
description = "User under which photoprism runs.";
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "photoprism";
|
||||
description = "Group under which photoprism runs.";
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "photoprism" { };
|
||||
|
||||
settings = lib.mkOption {
|
||||
@@ -110,11 +122,11 @@ in
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
User = "photoprism";
|
||||
Group = "photoprism";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
DynamicUser = true;
|
||||
StateDirectory = "photoprism";
|
||||
WorkingDirectory = "/var/lib/photoprism";
|
||||
WorkingDirectory = cfg.storagePath;
|
||||
RuntimeDirectory = "photoprism";
|
||||
ReadWritePaths = [
|
||||
cfg.originalsPath
|
||||
|
||||
@@ -643,9 +643,7 @@ in
|
||||
gitdaemon = runTest ./gitdaemon.nix;
|
||||
gitea = handleTest ./gitea.nix { giteaPackage = pkgs.gitea; };
|
||||
github-runner = runTest ./github-runner.nix;
|
||||
gitlab = import ./gitlab {
|
||||
inherit runTest;
|
||||
};
|
||||
gitlab = runTest ./gitlab.nix;
|
||||
gitolite = runTest ./gitolite.nix;
|
||||
gitolite-fcgiwrap = runTest ./gitolite-fcgiwrap.nix;
|
||||
glance = runTest ./glance.nix;
|
||||
@@ -802,7 +800,11 @@ in
|
||||
jitsi-meet = runTest ./jitsi-meet.nix;
|
||||
jool = import ./jool.nix { inherit pkgs runTest; };
|
||||
jotta-cli = runTest ./jotta-cli.nix;
|
||||
k3s = handleTest ./k3s { };
|
||||
k3s = import ./rancher {
|
||||
inherit pkgs runTest;
|
||||
inherit (pkgs) lib;
|
||||
rancherDistro = "k3s";
|
||||
};
|
||||
kafka = handleTest ./kafka { };
|
||||
kaidan = runTest ./kaidan;
|
||||
kanboard = runTest ./web-apps/kanboard.nix;
|
||||
@@ -1343,7 +1345,15 @@ in
|
||||
restic-rest-server = runTest ./restic-rest-server.nix;
|
||||
retroarch = runTest ./retroarch.nix;
|
||||
ringboard = runTest ./ringboard.nix;
|
||||
rke2 = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./rke2 { };
|
||||
rke2 = import ./rancher {
|
||||
inherit pkgs;
|
||||
inherit (pkgs) lib;
|
||||
runTest = runTestOn [
|
||||
"aarch64-linux"
|
||||
"x86_64-linux"
|
||||
];
|
||||
rancherDistro = "rke2";
|
||||
};
|
||||
rkvm = handleTest ./rkvm { };
|
||||
rmfakecloud = runTest ./rmfakecloud.nix;
|
||||
robustirc-bridge = runTest ./robustirc-bridge.nix;
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
# - Opening and closing issues.
|
||||
# - Downloading repository archives as tar.gz and tar.bz2
|
||||
# Run with
|
||||
# [nixpkgs]$ nix-build -A nixosTests.gitlab.gitlab
|
||||
# [nixpkgs]$ nix-build -A nixosTests.gitlab
|
||||
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (import ../ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
|
||||
inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
|
||||
initialRootPassword = "notproduction";
|
||||
rootProjectId = "2";
|
||||
|
||||
@@ -37,7 +37,7 @@ in
|
||||
gitlab =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [ ../common/user-account.nix ];
|
||||
imports = [ common/user-account.nix ];
|
||||
|
||||
environment.systemPackages = with pkgs; [ git ];
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{ runTest }:
|
||||
{
|
||||
gitlab = runTest ./gitlab.nix;
|
||||
runner = runTest ./runner.nix;
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
# This test runs a gitlab-runner and performs the following tests in
|
||||
# two machines `gitlab` and `gitlab-runner`:
|
||||
# - Create runners in the `gitlab` machine for all runners in `./runner`.
|
||||
# - Inject the runner tokens into the `gitlab-runner.service` (machine `gitlab-runner`)
|
||||
# which runs all runners:
|
||||
# - Shell runner in `./runner/shell-runner`.
|
||||
# - Start the `gitlab-runner.service`.
|
||||
# - Check that all runners in `gitlab` are `active`.
|
||||
#
|
||||
# Run with
|
||||
# [nixpkgs]$ nix-build -A nixosTests.gitlab.runner
|
||||
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
initialRootPassword = "notproduction";
|
||||
|
||||
runnerTokenDir = "/run/secrets/gitlab-runner";
|
||||
|
||||
runnerConfigs = {
|
||||
# The Gitlab runner where each job runs
|
||||
# on the host (not containerized and very insecure).
|
||||
shell = {
|
||||
desc = "Shell runner (host NixOS shell, host Nix store)";
|
||||
name = "shell";
|
||||
tokenFile = "${runnerTokenDir}/token-shell.env";
|
||||
};
|
||||
|
||||
# The Gitlab runner which uses the Docker runner (we use podman).
|
||||
# Features:
|
||||
# - Daemonizes the Nix store into a container.
|
||||
# - All jobs run in an unprivileged container, e.g. with image
|
||||
# (`local/nix`, `local/alpine`, `local/ubuntu`)
|
||||
podman = {
|
||||
desc = "Podman runner (containers, shared containerized Nix store)";
|
||||
name = "podman";
|
||||
tokenFile = "${runnerTokenDir}/token-podman.env";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "gitlab-runner";
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
gabyx
|
||||
];
|
||||
|
||||
nodes = {
|
||||
gitlab-runner =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
../common/user-account.nix
|
||||
(import ./runner/shell-runner.nix {
|
||||
runnerConfig = runnerConfigs.shell;
|
||||
})
|
||||
]
|
||||
# Only enable the podman runner on x86_64
|
||||
# cause of built images.
|
||||
++ (lib.optional pkgs.stdenv.buildPlatform.isx86_64 (
|
||||
import ./runner/podman-runner {
|
||||
runnerConfig = runnerConfigs.podman;
|
||||
}
|
||||
));
|
||||
|
||||
virtualisation = {
|
||||
diskSize = 10000;
|
||||
};
|
||||
|
||||
# Define the Gitlab Runner.
|
||||
services.gitlab-runner = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
log_level = "info";
|
||||
};
|
||||
|
||||
gracefulTermination = false;
|
||||
};
|
||||
};
|
||||
gitlab =
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = [ ../common/user-account.nix ];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
config.services.nginx.defaultHTTPListenPort
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [ git ];
|
||||
|
||||
virtualisation.memorySize = 6144;
|
||||
virtualisation.cores = 4;
|
||||
|
||||
systemd.services.gitlab.serviceConfig.Restart = lib.mkForce "no";
|
||||
systemd.services.gitlab-workhorse.serviceConfig.Restart = lib.mkForce "no";
|
||||
systemd.services.gitaly.serviceConfig.Restart = lib.mkForce "no";
|
||||
systemd.services.gitlab-sidekiq.serviceConfig.Restart = lib.mkForce "no";
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = {
|
||||
localhost = {
|
||||
locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.gitlab = {
|
||||
enable = true;
|
||||
databasePasswordFile = pkgs.writeText "dbPassword" "xo0daiF4";
|
||||
initialRootPasswordFile = pkgs.writeText "rootPassword" initialRootPassword;
|
||||
secrets = {
|
||||
secretFile = pkgs.writeText "secret" "Aig5zaic";
|
||||
otpFile = pkgs.writeText "otpsecret" "Riew9mue";
|
||||
dbFile = pkgs.writeText "dbsecret" "we2quaeZ";
|
||||
jwsFile = pkgs.runCommand "oidcKeyBase" { } "${pkgs.openssl}/bin/openssl genrsa 2048 > $out";
|
||||
activeRecordPrimaryKeyFile = pkgs.writeText "arprimary" "vsaYPZjTRxcbG7W6gNr95AwBmzFUd4Eu";
|
||||
activeRecordDeterministicKeyFile = pkgs.writeText "ardeterministic" "kQarv9wb2JVP7XzLTh5f6DFcMHms4nEC";
|
||||
activeRecordSaltFile = pkgs.writeText "arsalt" "QkgR9CfFU3MXEWGqa7LbP24AntK5ZeYw";
|
||||
};
|
||||
|
||||
# reduce memory usage
|
||||
sidekiq.concurrency = 1;
|
||||
puma.workers = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
authPayload = pkgs.writeText "auth.json" (
|
||||
builtins.toJSON {
|
||||
grant_type = "password";
|
||||
username = "root";
|
||||
password = initialRootPassword;
|
||||
}
|
||||
);
|
||||
|
||||
runnerTokenEnv = pkgs.writeText "runner-token.env" ''
|
||||
CI_SERVER_URL=http://gitlab
|
||||
CI_SERVER_TOKEN=$token
|
||||
'';
|
||||
|
||||
createRunnerPayload = pkgs.writeText "create-runner.json" (
|
||||
builtins.toJSON {
|
||||
runner_type = "instance_type";
|
||||
}
|
||||
);
|
||||
in
|
||||
# python
|
||||
''
|
||||
# Define some globals for the python script below.
|
||||
JQ_BINARY="${pkgs.jq}/bin/jq"
|
||||
GITLAB_STATE_PATH="${nodes.gitlab.services.gitlab.statePath}"
|
||||
RUNNER_TOKEN_ENV_FILE="${runnerTokenEnv}"
|
||||
AUTH_PAYLOAD_FILE="${authPayload}"
|
||||
CREATE_RUNNER_PAYLOAD_FILE="${createRunnerPayload}"
|
||||
|
||||
${lib.readFile ./runner_test.py}
|
||||
|
||||
start_all()
|
||||
wait_for_services()
|
||||
|
||||
# Run all tests.
|
||||
test_connection()
|
||||
test_register_runner(name="shell", tokenFile="${runnerConfigs.shell.tokenFile}")
|
||||
test_register_runner(name="podman", tokenFile="${runnerConfigs.podman.tokenFile}")
|
||||
restart_gitlab_runner_service(runnerConfigs)
|
||||
test_runner_registered(runnerConfigs["shell"])
|
||||
test_runner_registered(runnerConfigs["podman"])
|
||||
'';
|
||||
}
|
||||
@@ -1,442 +0,0 @@
|
||||
{ runnerConfig }:
|
||||
# Gitlab Runner Module
|
||||
#
|
||||
# This module will add a Gitlab-Runner
|
||||
# configured similar to https://wiki.nixos.org/wiki/Gitlab_runner
|
||||
# with a nix-daemon running in a podman container `nix-daemon-container`.
|
||||
#
|
||||
# - The volumes from the `nix-daemon-container` will get mounted to
|
||||
# each job container which Gitlab starts, which gives them access
|
||||
# to a commonly shared Nix store.
|
||||
#
|
||||
# - The `/nix/store` inside the job container
|
||||
# (either image `alpineImage` or `ubuntuImage` or `nixImage`)
|
||||
# will be read-only and nix can only store stuff into this path by using the
|
||||
# `NIX_DAEMON` env. variable which lets it communicate through the
|
||||
# mounted daemon socket.
|
||||
|
||||
# - The `bootstrapPkgs` derivation is copied into the job containers
|
||||
# but without the Nix store paths cause they get provided by the
|
||||
# `nix-daemon-store` volume.
|
||||
# I cannot denote these volumes because they overmount the
|
||||
# shit which is in the image.
|
||||
# TODO: make a systemd service which starts before
|
||||
# that and creates some volumes and inits these from the image.
|
||||
#
|
||||
# - The `podman-daemon-socket` volume gets mounted to the job container
|
||||
# enabling it to use `podman`.
|
||||
# Note: The job container instance is not using the system `podman` running in NixOS.
|
||||
# Its a dedicated podman service `podmanDaemonContainer`
|
||||
# running as `--privileged`
|
||||
# [non-rootless container](https://rootlesscontaine.rs/#what-are-rootless-containers-and-what-are-not).
|
||||
# (TODO: This podman daemon instance could be maybe run as rootless
|
||||
# container under a user `ci` and a separated Gitlab Runner could
|
||||
# run over this socket, effectively run only rootless containers.)
|
||||
#
|
||||
# - There is also a job runner prebuild script which is started on every job.
|
||||
# See `scripts/prebuild.nix` to setup some missing stuff.
|
||||
#
|
||||
# Debugging on the VM:
|
||||
#
|
||||
# - You can use `journalclt -u gitlab-runner.service`.
|
||||
#
|
||||
# - To run a job container use:
|
||||
# ```bash
|
||||
# podman run --rm -it
|
||||
# --volumes-from 'nix-daemon-container'
|
||||
# -v "podman-daemon-socket:/run/podman"
|
||||
# "local/alpine" \
|
||||
# bash -c "export CI_PIPkELINE_ID=123456 && gitlab-runner-prebuild-script; echo hello"
|
||||
# ```
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nixRepo = pkgs.fetchFromGitHub {
|
||||
owner = "NixOS";
|
||||
repo = "nix";
|
||||
rev = "2.32.4";
|
||||
hash = "sha256-8QYnRyGOTm3h/Dp8I6HCmQzlO7C009Odqyp28pTWgcY=";
|
||||
};
|
||||
|
||||
# Either we use a Nix as the base image or Alpine.
|
||||
imageNames = {
|
||||
default = imageNames.alpine;
|
||||
|
||||
alpine = "local/alpine";
|
||||
nix = "local/nix";
|
||||
ubuntu = "local/ubuntu";
|
||||
|
||||
all = with imageNames; [
|
||||
alpine
|
||||
nix
|
||||
ubuntu
|
||||
];
|
||||
};
|
||||
|
||||
noPruneLabels = {
|
||||
no-prune = "true";
|
||||
};
|
||||
|
||||
# This derivation will contain a folder `/etc`
|
||||
files = pkgs.callPackage ./files { };
|
||||
preBuildScript = pkgs.callPackage ./scripts/prebuild.nix { };
|
||||
|
||||
# These derivations are Linked into the job images root dir.
|
||||
bootstrapPkgs = [
|
||||
pkgs.nix
|
||||
# Runtime dependencies of nix.
|
||||
pkgs.gnutar
|
||||
pkgs.gzip
|
||||
pkgs.openssh
|
||||
pkgs.xz
|
||||
pkgs.cacert
|
||||
|
||||
# Other stuff.
|
||||
(lib.hiPrio pkgs.coreutils)
|
||||
(lib.hiPrio pkgs.findutils)
|
||||
pkgs.openssh
|
||||
pkgs.bashInteractive
|
||||
(lib.hiPrio pkgs.git)
|
||||
pkgs.cachix
|
||||
|
||||
pkgs.just
|
||||
pkgs.podman # For nested containers.
|
||||
|
||||
preBuildScript
|
||||
|
||||
files.containers
|
||||
files.nixConfig
|
||||
];
|
||||
|
||||
# All these packages are added to the Nix daemon.
|
||||
nixStorePkgs = bootstrapPkgs ++ [
|
||||
# These files
|
||||
files.basicRoot
|
||||
files.fakeNixpkgs
|
||||
];
|
||||
|
||||
toEnvList = envs: lib.mapAttrsToList (k: v: "${k}=${v}") envs;
|
||||
|
||||
# This is the Nix base image.
|
||||
nixImageBase = pkgs.callPackage (import (nixRepo + "/docker.nix")) {
|
||||
name = "local/nix-base";
|
||||
tag = "latest";
|
||||
|
||||
bundleNixpkgs = false;
|
||||
maxLayers = 2;
|
||||
|
||||
# You can add here a user with uid,gid,uname,gname etc.
|
||||
# We are using root.
|
||||
|
||||
extraPkgs = nixStorePkgs;
|
||||
|
||||
nixConf = {
|
||||
cores = "0";
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# This is the daemon image which provides the store
|
||||
# as volumes.
|
||||
nixDaemonImage = pkgs.dockerTools.buildLayeredImage {
|
||||
fromImage = nixImageBase;
|
||||
name = "local/nix-daemon";
|
||||
tag = "latest";
|
||||
|
||||
config = {
|
||||
Volumes = {
|
||||
"/nix/store" = { };
|
||||
"/nix/var/nix/db" = { };
|
||||
"/nix/var/nix/daemon-socket" = { };
|
||||
};
|
||||
Labels = noPruneLabels;
|
||||
};
|
||||
maxLayers = 4;
|
||||
};
|
||||
|
||||
# This is the podman daemon image which enables
|
||||
# a job image to use `podman` internally.
|
||||
podmanDaemonImage =
|
||||
let
|
||||
# Update with:
|
||||
# ```shell
|
||||
# nix run "github:nixos/nixpkgs/nixos-unstable#nix-prefetch-docker" -- \
|
||||
# --image-name quay.io/podman/stable --image-tag v5.6.0
|
||||
# ```
|
||||
base = pkgs.dockerTools.pullImage {
|
||||
imageName = "quay.io/podman/stable";
|
||||
imageDigest = "sha256:7c9381b9af167cf2218831c3af3135856c99f488b543b78435c8f18e19ad739a";
|
||||
hash = "sha256-pXXCu13fB/RN9qx8iLhE5Kko6glTrFrRhR7fo2OS7V0=";
|
||||
finalImageName = "quay.io/podman/stable";
|
||||
finalImageTag = "v5.6.0";
|
||||
};
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
fromImage = base;
|
||||
name = "local/podman-daemon";
|
||||
tag = "latest";
|
||||
|
||||
config = {
|
||||
Labels = noPruneLabels;
|
||||
};
|
||||
};
|
||||
|
||||
jobImages =
|
||||
let
|
||||
extraCommands = ''
|
||||
set -eu
|
||||
# Set missing Nix directories.
|
||||
mkdir -p -m 0755 nix/var/log/nix/drvs
|
||||
mkdir -p -m 0755 nix/var/nix/{gcroots,profiles,temproots,userpool}
|
||||
mkdir -p -m 1777 nix/var/nix/{gcroots,profiles}/per-user
|
||||
mkdir -p -m 0755 nix/var/nix/profiles/per-user/root
|
||||
|
||||
# Need a HOME.
|
||||
mkdir -vp root
|
||||
mkdir -p -m 0700 root/.nix-defexpr
|
||||
'';
|
||||
in
|
||||
{
|
||||
# The Nix image.
|
||||
# Similar to https://github.com/nix-community/docker-nixpkgs/blob/main/images/nix/default.nix.
|
||||
nix = pkgs.dockerTools.buildLayeredImage {
|
||||
name = imageNames.nix;
|
||||
tag = "latest";
|
||||
|
||||
extraCommands = extraCommands + ''
|
||||
set -eu
|
||||
# For `/usr/bin/env`.
|
||||
mkdir -p usr && ln -s ../bin usr/bin
|
||||
'';
|
||||
|
||||
contents = bootstrapPkgs ++ [ files.basicRoot ];
|
||||
# No store paths are copied into. We provide them by mounting the
|
||||
# /nix/store.
|
||||
includeStorePaths = false;
|
||||
|
||||
config = {
|
||||
Labels = noPruneLabels;
|
||||
Env = toEnvList envs.nix;
|
||||
};
|
||||
maxLayers = 2;
|
||||
};
|
||||
|
||||
# This is the analog image to `local/nix` but Alpine based.
|
||||
alpine =
|
||||
let
|
||||
# Update with:
|
||||
# ```shell
|
||||
# nix run "github:nixos/nixpkgs/nixos-unstable#nix-prefetch-docker" -- --image-name alpine --image-tag latest
|
||||
# ```
|
||||
alpineBase = pkgs.dockerTools.pullImage {
|
||||
imageName = "alpine";
|
||||
imageDigest = "sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d";
|
||||
sha256 = "0gf7wbjp37zbni3pz8vdgq1mss6mz69wynms0gqhq7lsxfmg9xj9";
|
||||
finalImageName = "alpine";
|
||||
finalImageTag = "latest";
|
||||
};
|
||||
in
|
||||
(pkgs.dockerTools.buildLayeredImage {
|
||||
fromImage = alpineBase;
|
||||
name = imageNames.alpine;
|
||||
tag = "latest";
|
||||
|
||||
inherit extraCommands;
|
||||
|
||||
contents = bootstrapPkgs;
|
||||
# No store paths are copied into. We provide them by mounting the
|
||||
# /nix/store.
|
||||
includeStorePaths = false;
|
||||
|
||||
config = {
|
||||
Labels = noPruneLabels;
|
||||
Env = toEnvList envs.nix;
|
||||
};
|
||||
|
||||
# Only if `build buildLayeredImage`.
|
||||
maxLayers = 3;
|
||||
});
|
||||
|
||||
# This is the analog image to `local/nix` but Ubuntu based.
|
||||
ubuntu =
|
||||
let
|
||||
# Update with:
|
||||
# ```shell
|
||||
# nix run "github:nixos/nixpkgs/nixos-unstable#nix-prefetch-docker" -- \
|
||||
# --image-name ubuntu --image-tag latest
|
||||
# ```
|
||||
ubuntuBase = pkgs.dockerTools.pullImage {
|
||||
imageName = "ubuntu";
|
||||
imageDigest = "sha256:1e622c5f073b4f6bfad6632f2616c7f59ef256e96fe78bf6a595d1dc4376ac02";
|
||||
hash = "sha256-aC8SgxdcMSaaU89YMr/uwE022Yqey2frmeZqr+L1xEU=";
|
||||
finalImageName = "ubuntu";
|
||||
finalImageTag = "latest";
|
||||
};
|
||||
in
|
||||
(pkgs.dockerTools.buildLayeredImage {
|
||||
fromImage = ubuntuBase;
|
||||
name = imageNames.ubuntu;
|
||||
tag = "latest";
|
||||
|
||||
inherit extraCommands;
|
||||
|
||||
contents = bootstrapPkgs;
|
||||
# No store paths are copied into. We provide them by mounting the
|
||||
# /nix/store.
|
||||
includeStorePaths = false;
|
||||
|
||||
config = {
|
||||
Labels = noPruneLabels;
|
||||
Env = toEnvList envs.ubuntu;
|
||||
};
|
||||
|
||||
# Only if `build buildLayeredImage`.
|
||||
maxLayers = 3;
|
||||
});
|
||||
};
|
||||
|
||||
nixDaemonContainer = {
|
||||
imageFile = nixDaemonImage;
|
||||
image = "local/nix-daemon:latest";
|
||||
|
||||
volumes = [
|
||||
"nix-daemon-store:/nix/store"
|
||||
"nix-daemon-db:/nix/var/nix/db"
|
||||
"nix-daemon-socket:/nix/var/nix/daemon-socket"
|
||||
];
|
||||
cmd = [
|
||||
"nix"
|
||||
"daemon"
|
||||
];
|
||||
};
|
||||
|
||||
podmanDaemonContainer = {
|
||||
imageFile = podmanDaemonImage;
|
||||
image = "local/podman-daemon:latest";
|
||||
volumes = [
|
||||
"podman-daemon-socket:/run/podman"
|
||||
"podman-cache:/var/lib/container"
|
||||
# Shared images, currently not needed.
|
||||
"podman-shared:/var/lib/shared:ro"
|
||||
];
|
||||
privileged = true;
|
||||
cmd = [
|
||||
"podman"
|
||||
"system"
|
||||
"service"
|
||||
"--time=0"
|
||||
"unix:///run/podman/podman.sock"
|
||||
"--log-level"
|
||||
"info"
|
||||
];
|
||||
};
|
||||
|
||||
# Environment variables for all job containers.
|
||||
envs = rec {
|
||||
common = {
|
||||
# Access to the nix daemon.
|
||||
NIX_REMOTE = "daemon";
|
||||
# Access to podman.
|
||||
CONTAINER_HOST = "unix:///run/podman/podman.sock";
|
||||
|
||||
USER = "root";
|
||||
PATH = "/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
|
||||
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
# For shells, source this file.
|
||||
ENV = "${pkgs.nix}/etc/profile.d/nix-daemon.sh";
|
||||
BASH_ENV = "${pkgs.nix}/etc/profile.d/nix-daemon.sh";
|
||||
|
||||
# Make a fake nixpkgs which throws when using
|
||||
# `nix repl -f <nixpkgs>` for example.
|
||||
NIX_PATH = "nixpkgs=${files.fakeNixpkgs}";
|
||||
};
|
||||
|
||||
nix = common // {
|
||||
IMAGE_OS_DIST = "nix";
|
||||
};
|
||||
|
||||
alpine = common // {
|
||||
IMAGE_OS_DIST = "alpine";
|
||||
};
|
||||
|
||||
ubuntu = common // {
|
||||
IMAGE_OS_DIST = "ubuntu";
|
||||
};
|
||||
};
|
||||
|
||||
registrationFlags = [
|
||||
"--docker-volumes"
|
||||
"gitlab-runner-scratch:/scratch"
|
||||
|
||||
"--docker-volumes"
|
||||
"podman-daemon-socket:/run/podman"
|
||||
|
||||
"--docker-volumes-from"
|
||||
"nix-daemon-container:ro"
|
||||
|
||||
"--docker-pull-policy"
|
||||
"if-not-present"
|
||||
|
||||
"--docker-allowed-pull-policies"
|
||||
"if-not-present"
|
||||
|
||||
"--docker-host"
|
||||
"unix:///var/run/podman/podman.sock"
|
||||
|
||||
"--docker-network-mode"
|
||||
"host"
|
||||
];
|
||||
|
||||
in
|
||||
{
|
||||
imports = [ ./virtualization.nix ];
|
||||
|
||||
virtualisation.oci-containers = {
|
||||
backend = "podman";
|
||||
|
||||
containers = {
|
||||
nix-daemon-container = nixDaemonContainer;
|
||||
podman-daemon-container = podmanDaemonContainer;
|
||||
}
|
||||
//
|
||||
# Workaround to add the job images to the registry.
|
||||
(lib.concatMapAttrs (name: image: {
|
||||
"${name}-container" = {
|
||||
imageFile = jobImages.${name};
|
||||
image = "${imageNames.${name}}:latest";
|
||||
extraOptions = [
|
||||
"--volumes-from"
|
||||
"nix-daemon-container:ro"
|
||||
];
|
||||
dependsOn = [ "nix-daemon-container" ];
|
||||
cmd = [ "true" ];
|
||||
};
|
||||
}) jobImages);
|
||||
};
|
||||
|
||||
# Define the Gitlab Runner.
|
||||
services.gitlab-runner.services.podman-runner = {
|
||||
description = runnerConfig.desc;
|
||||
|
||||
inherit registrationFlags;
|
||||
|
||||
authenticationTokenConfigFile = runnerConfig.tokenFile;
|
||||
|
||||
executor = "docker";
|
||||
dockerImage = imageNames.default;
|
||||
dockerAllowedImages = [ ];
|
||||
dockerPrivileged = false;
|
||||
requestConcurrency = 4;
|
||||
|
||||
preBuildScript = "${preBuildScript}/bin/gitlab-runner-pre-build-script";
|
||||
};
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
root:x:0:
|
||||
wheel:x:1:
|
||||
kmem:x:2:
|
||||
tty:x:3:
|
||||
messagebus:x:4:
|
||||
disk:x:6:
|
||||
audio:x:17:
|
||||
floppy:x:18:
|
||||
uucp:x:19:
|
||||
lp:x:20:
|
||||
cdrom:x:24:
|
||||
tape:x:25:
|
||||
video:x:26:
|
||||
dialout:x:27:
|
||||
utmp:x:29:
|
||||
adm:x:55:
|
||||
keys:x:96:
|
||||
users:x:100:
|
||||
input:x:174:
|
||||
nixbld:x:30000:nixbld1,nixbld10,nixbld11,nixbld12,nixbld13,nixbld14,nixbld15,nixbld16,nixbld17,nixbld18,nixbld19,nixbld2,nixbld20,nixbld21,nixbld22,nixbld23,nixbld24,nixbld25,nixbld26,nixbld27,nixbld28,nixbld29,nixbld3,nixbld30,nixbld31,nixbld32,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9
|
||||
nogroup:x:65534:
|
||||
@@ -1,11 +0,0 @@
|
||||
passwd: files mymachines systemd
|
||||
group: files mymachines systemd
|
||||
shadow: files
|
||||
|
||||
hosts: files mymachines dns myhostname
|
||||
networks: files
|
||||
|
||||
ethers: files
|
||||
services: files
|
||||
protocols: files
|
||||
rpc: files
|
||||
@@ -1,34 +0,0 @@
|
||||
root:x:0:0:System administrator:/root:/bin/bash
|
||||
nixbld1:x:30001:30000:Nix build user 1:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld2:x:30002:30000:Nix build user 2:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld3:x:30003:30000:Nix build user 3:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld4:x:30004:30000:Nix build user 4:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld5:x:30005:30000:Nix build user 5:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld6:x:30006:30000:Nix build user 6:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld7:x:30007:30000:Nix build user 7:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld8:x:30008:30000:Nix build user 8:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld9:x:30009:30000:Nix build user 9:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld10:x:30010:30000:Nix build user 10:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld11:x:30011:30000:Nix build user 11:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld12:x:30012:30000:Nix build user 12:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld13:x:30013:30000:Nix build user 13:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld14:x:30014:30000:Nix build user 14:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld15:x:30015:30000:Nix build user 15:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld16:x:30016:30000:Nix build user 16:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld17:x:30017:30000:Nix build user 17:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld18:x:30018:30000:Nix build user 18:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld19:x:30019:30000:Nix build user 19:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld20:x:30020:30000:Nix build user 20:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld21:x:30021:30000:Nix build user 21:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld22:x:30022:30000:Nix build user 22:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld23:x:30023:30000:Nix build user 23:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld24:x:30024:30000:Nix build user 24:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld25:x:30025:30000:Nix build user 25:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld26:x:30026:30000:Nix build user 26:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld27:x:30027:30000:Nix build user 27:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld28:x:30028:30000:Nix build user 28:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld29:x:30029:30000:Nix build user 29:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld30:x:30030:30000:Nix build user 30:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld31:x:30031:30000:Nix build user 31:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nixbld32:x:30032:30000:Nix build user 32:/var/empty:/run/current-system/sw/bin/nologin
|
||||
nobody:x:65534:65534:Unprivileged account (don't use!):/var/empty:/run/current-system/sw/bin/nologin
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
[engine]
|
||||
cgroup_manager = "cgroupfs"
|
||||
@@ -1,2 +0,0 @@
|
||||
/run/secrets/etc-pki-entitlement:/run/secrets/etc-pki-entitlement
|
||||
/run/secrets/rhsm:/run/secrets/rhsm
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"default": [
|
||||
{
|
||||
"type": "insecureAcceptAnything"
|
||||
}
|
||||
],
|
||||
"transports": {
|
||||
"docker-daemon": {
|
||||
"": [{ "type": "insecureAcceptAnything" }]
|
||||
}
|
||||
}
|
||||
}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io"]
|
||||
short-name-mode = "enforcing"
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
[aliases]
|
||||
"buildah" = "quay.io/buildah/stable"
|
||||
"podman" = "quay.io/podman/stable"
|
||||
"alpine" = "docker.io/library/alpine"
|
||||
"ubuntu" = "docker.io/library/ubuntu"
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
# This is a default registries.d configuration file. You may
|
||||
# add to this file or create additional files in registries.d/.
|
||||
#
|
||||
# lookaside: for reading/writing simple signing signatures
|
||||
# lookaside-staging: for writing simple signing signatures, preferred over lookaside
|
||||
#
|
||||
# lookaside and lookaside-staging take a value of the following:
|
||||
# lookaside: {schema}://location
|
||||
#
|
||||
# For reading signatures, schema may be http, https, or file.
|
||||
# For writing signatures, schema may only be file.
|
||||
|
||||
# The default locations are built-in, for both reading and writing:
|
||||
# /var/lib/containers/sigstore for root, or
|
||||
# ~/.local/share/containers/sigstore for non-root users.
|
||||
default-docker:
|
||||
# lookaside: https://…
|
||||
# lookaside-staging: file:///…
|
||||
|
||||
# The 'docker' indicator here is the start of the configuration
|
||||
# for docker registries.
|
||||
#
|
||||
# docker:
|
||||
#
|
||||
# privateregistry.com:
|
||||
# lookaside: https://privateregistry.com/sigstore/
|
||||
# lookaside-staging: /mnt/nfs/privateregistry/sigstore
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
docker:
|
||||
registry.access.redhat.com:
|
||||
lookaside: https://access.redhat.com/webassets/docker/content/sigstore
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
docker:
|
||||
registry.redhat.io:
|
||||
lookaside: https://registry.redhat.io/containers/sigstore
|
||||
@@ -1,15 +0,0 @@
|
||||
[storage]
|
||||
driver = "overlay"
|
||||
runroot = "/run/containers/storage"
|
||||
graphroot = "/var/lib/containers/storage"
|
||||
|
||||
[storage.options]
|
||||
additionalimagestores = [
|
||||
"/var/lib/shared",
|
||||
"/usr/lib/containers/storage",
|
||||
]
|
||||
pull_options = {enable_partial_images = "true", use_hard_links = "false", ostree_repos=""}
|
||||
|
||||
[storage.options.overlay]
|
||||
mount_program = "/usr/bin/fuse-overlayfs"
|
||||
mountopt = "nodev,fsync=0"
|
||||
@@ -1,46 +0,0 @@
|
||||
# Specific files for the job images.
|
||||
#
|
||||
# - `basicRoot`: Some basic root files for the `jobImages.nix`.
|
||||
# - `fakeNixpkgs`: A fake Nixpkg directory which is set as `NIX_PATH=nixpkgs:<path>`
|
||||
# which throws on load.
|
||||
# - `nixConfig`: The Nix config with some options.
|
||||
# - `containers`:
|
||||
# These are some files which are copied to the job images needed for
|
||||
# `buildah` (`podman`):
|
||||
#
|
||||
# ```bash
|
||||
# podman create --name temp-buildah quay.io/buildah/stable:latest
|
||||
# podman cp temp-buildah:/etc/containers ./etc/
|
||||
# find ./etc -type d -empty -delete
|
||||
# podman container rm temp-buildah
|
||||
#```
|
||||
#
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
|
||||
# We need proper derivations to add it to the nixImageBase.
|
||||
mkDrv =
|
||||
name: src:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
inherit name src;
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r $src/* $out/
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
basicRoot = mkDrv "basic-root-files" ./basicRoot;
|
||||
containers = mkDrv "containers-files" ./containers;
|
||||
fakeNixpkgs = mkDrv "fake-nixpkgs" ./fake-nixpkgs;
|
||||
|
||||
nixConfig = pkgs.writeTextFile {
|
||||
name = "nix.conf";
|
||||
destination = "/etc/nix/nix.conf";
|
||||
text = ''
|
||||
accept-flake-config = true
|
||||
experimental-features = nix-command flakes
|
||||
max-jobs = auto
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
_:
|
||||
throw ''
|
||||
This container doesn't include nixpkgs.
|
||||
|
||||
The best way to work around that is to pin your dependencies. See
|
||||
https://nix.dev/tutorials/first-steps/towards-reproducibility-pinning-nixpkgs.html
|
||||
|
||||
Or if you must, override the NIX_PATH environment variable with eg:
|
||||
"NIX_PATH=nixpkgs=channel:nixos-unstable"
|
||||
''
|
||||
@@ -1,55 +0,0 @@
|
||||
{ writeShellScriptBin, nix }:
|
||||
writeShellScriptBin "gitlab-runner-pre-build-script"
|
||||
# bash
|
||||
''
|
||||
set -e
|
||||
set -u
|
||||
|
||||
function section_start() {
|
||||
local name="$1"
|
||||
shift
|
||||
echo -e "\e[0Ksection_start:$(date +%s):$name[collapsed=true]\r\e[0K$*"
|
||||
}
|
||||
|
||||
function section_end() {
|
||||
local name="$1"
|
||||
echo -e "\e[0Ksection_end:$(date +%s):$name\r\e[0K"
|
||||
}
|
||||
|
||||
function setup() {
|
||||
# We need to allow modification of nix config for cachix as
|
||||
# otherwise it is link to the read only file in the store.
|
||||
cp --remove-destination \
|
||||
"$(readlink -f /etc/nix/nix.conf)" /etc/nix/nix.conf
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. "${nix}/etc/profile.d/nix-daemon.sh"
|
||||
}
|
||||
|
||||
function setup_pipeline_scratch_dir() {
|
||||
scratch_dir="/scratch/$CI_PIPELINE_ID"
|
||||
|
||||
echo "Create scrtach directory for pipeline: $scratch_dir"
|
||||
mkdir -p "$scratch_dir" || {
|
||||
echo "Could not create scratch dir '$scratch_dir'." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
export CI_CUSTOM_SCRATCH_DIR="$scratch_dir"
|
||||
}
|
||||
|
||||
function print_info() {
|
||||
echo "Nix version:"
|
||||
nix --version
|
||||
}
|
||||
|
||||
function main() {
|
||||
print_info
|
||||
setup
|
||||
setup_pipeline_scratch_dir
|
||||
}
|
||||
|
||||
section_start gitlab-runner-prebuild "Gitlab-Runner PreBuild Script"
|
||||
main "$@"
|
||||
section_end gitlab-runner-prebuild
|
||||
''
|
||||
@@ -1,43 +0,0 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
virtualisation.docker = {
|
||||
enable = lib.mkForce false;
|
||||
};
|
||||
|
||||
virtualisation.podman = {
|
||||
enable = true;
|
||||
|
||||
# Create a `docker` alias for podman, to use it as a drop-in replacement
|
||||
# dockerCompat = true;
|
||||
dockerSocket = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Required for containers under podman-compose to be able to talk to each other.
|
||||
defaultNetwork.settings.dns_enabled = true;
|
||||
|
||||
autoPrune = {
|
||||
dates = "weekly";
|
||||
flags = [
|
||||
"--filter"
|
||||
"label!=no-prune"
|
||||
"--volumes"
|
||||
"--log-level"
|
||||
"debug"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.containers.storage.settings = {
|
||||
storage = {
|
||||
driver = "overlay";
|
||||
graphroot = "/var/lib/containers/storage";
|
||||
runroot = "/run/containers/storage";
|
||||
|
||||
# Does not work currently.
|
||||
options.overlay = {
|
||||
mountopt = "nodev,metacopy=on";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
runnerConfig,
|
||||
}:
|
||||
# This is the runner config for the `nixosConfiguration.services.gitlab-runner.services.X`
|
||||
{
|
||||
services.gitlab-runner.services.shell-runner = {
|
||||
description = runnerConfig.desc;
|
||||
authenticationTokenConfigFile = runnerConfig.tokenFile;
|
||||
|
||||
executor = "shell";
|
||||
};
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from string import Template
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class Runner:
|
||||
name: str
|
||||
tokenFile: str
|
||||
|
||||
id: str
|
||||
token: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class Machines:
|
||||
gitlab: Any
|
||||
gitlab_runner: Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class Nix:
|
||||
jq: str
|
||||
gitlab_state_path: str
|
||||
create_runner_payload_file: str
|
||||
auth_payload_file: str
|
||||
runner_token_env_file: str
|
||||
|
||||
|
||||
# Some global variables to work in the tests.
|
||||
out_dir = os.environ.get("out", os.getcwd())
|
||||
nix = Nix(
|
||||
jq=JQ_BINARY,
|
||||
gitlab_state_path=GITLAB_STATE_PATH,
|
||||
auth_payload_file=AUTH_PAYLOAD_FILE,
|
||||
create_runner_payload_file=CREATE_RUNNER_PAYLOAD_FILE,
|
||||
runner_token_env_file=RUNNER_TOKEN_ENV_FILE,
|
||||
)
|
||||
vms = Machines(gitlab, gitlab_runner)
|
||||
runnerConfigs: dict[str, Runner] = {}
|
||||
|
||||
|
||||
def wait_for_services():
|
||||
vms.gitlab.wait_for_unit("gitaly.service")
|
||||
vms.gitlab.wait_for_unit("gitlab-workhorse.service")
|
||||
vms.gitlab.wait_for_unit("gitlab.service")
|
||||
vms.gitlab.wait_for_unit("gitlab-sidekiq.service")
|
||||
vms.gitlab.wait_for_file(f"{nix.gitlab_state_path}/tmp/sockets/gitlab.socket")
|
||||
vms.gitlab.wait_until_succeeds("curl -sSf http://gitlab/users/sign_in")
|
||||
|
||||
|
||||
def test_connection():
|
||||
"""
|
||||
Test the connection to Gitlab and check if it is reachable from the runner VM.
|
||||
"""
|
||||
|
||||
print("==> Getting secrets and headers.")
|
||||
vms.gitlab.succeed(
|
||||
"cp /var/gitlab/state/config/secrets.yml /root/gitlab-secrets.yml"
|
||||
)
|
||||
|
||||
vms.gitlab.succeed(
|
||||
f"echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @{nix.auth_payload_file} http://gitlab/oauth/token | {nix.jq} -r '.access_token')\" >/tmp/headers"
|
||||
)
|
||||
|
||||
vms.gitlab.copy_from_vm("/tmp/headers")
|
||||
out_dir = os.environ.get("out", os.getcwd())
|
||||
vms.gitlab_runner.copy_from_host(str(Path(out_dir, "headers")), "/tmp/headers")
|
||||
|
||||
print("==> Testing connection.")
|
||||
vms.gitlab_runner.succeed("curl -v -H @/tmp/headers http://gitlab/api/v4/version")
|
||||
|
||||
|
||||
def test_register_runner(name: str, tokenFile: str):
|
||||
"""
|
||||
Register the runner in Gitlab and write the token file to be picked up by
|
||||
the gitlab-runner service on the other VM.
|
||||
"""
|
||||
|
||||
r = Runner(
|
||||
name=name,
|
||||
tokenFile=tokenFile,
|
||||
token="",
|
||||
id="",
|
||||
)
|
||||
runnerConfigs[r.name] = r
|
||||
|
||||
print(f"==> Create Runner '{r.name}'")
|
||||
resp = vms.gitlab.execute(
|
||||
f"""
|
||||
curl -s -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H @/tmp/headers \
|
||||
-d @{nix.create_runner_payload_file} \
|
||||
http://gitlab/api/v4/user/runners
|
||||
"""
|
||||
)[1]
|
||||
obj = json.loads(resp)
|
||||
r.id = obj["id"]
|
||||
r.token = obj["token"]
|
||||
print(f"==> Registered runner '{r.id}' with token '{r.token}'.")
|
||||
|
||||
# Push the token to the runner machine.
|
||||
print("==> Push runner token to machine.")
|
||||
tokenF = Path(out_dir, f"token-{r.name}.env")
|
||||
with open(nix.runner_token_env_file, "r") as f:
|
||||
tokenData = Template(f.read()).substitute({"token": r.token})
|
||||
with open(tokenF, "w") as w:
|
||||
w.write(tokenData)
|
||||
vms.gitlab_runner.copy_from_host(str(tokenF), r.tokenFile)
|
||||
|
||||
|
||||
def restart_gitlab_runner_service(runnerConfigs):
|
||||
print("==> Restart Gitlab Runner")
|
||||
|
||||
if any([n == "podman" for n in runnerConfigs.keys()]):
|
||||
vms.gitlab_runner.wait_for_unit("podman-nix-daemon-container.service")
|
||||
vms.gitlab_runner.wait_for_unit("podman-podman-daemon-container.service")
|
||||
|
||||
vms.gitlab_runner.systemctl("restart gitlab-runner.service")
|
||||
vms.gitlab_runner.wait_for_unit("gitlab-runner.service")
|
||||
|
||||
|
||||
def test_runner_registered(r: Runner):
|
||||
"""
|
||||
Test that the runner `r` is registered in Gitlab and its status is active.
|
||||
"""
|
||||
|
||||
print(f"==> Check that runner '{r.name}' is registered.")
|
||||
|
||||
resp = vms.gitlab.execute(
|
||||
f"""
|
||||
curl -s -X GET \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H @/tmp/headers \
|
||||
http://gitlab/api/v4/runners/{r.id}"""
|
||||
)[1]
|
||||
runnerStatus = json.loads(resp)
|
||||
|
||||
if not runnerStatus["active"]:
|
||||
raise Exception(
|
||||
f"Runner '{r.name}' [id: '{r.id}'] status is not active: {resp}"
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
# A test that imports k3s airgapped images and verifies that all expected images are present
|
||||
import ../make-test-python.nix (
|
||||
{ lib, k3s, ... }:
|
||||
{
|
||||
name = "${k3s.name}-airgap-images";
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
|
||||
nodes.machine = _: {
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = k3s;
|
||||
# Slightly reduce resource usage
|
||||
extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
];
|
||||
images = [ k3s.airgap-images ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("k3s")
|
||||
machine.wait_until_succeeds("journalctl -r --no-pager -u k3s | grep \"Imported images from /var/lib/rancher/k3s/agent/images/\"")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,204 +0,0 @@
|
||||
# Tests whether container images are imported and auto deploying Helm charts,
|
||||
# including the bundled traefik, work
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
k3s,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
testImageEnv = pkgs.buildEnv {
|
||||
name = "k3s-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
busybox
|
||||
hello
|
||||
];
|
||||
};
|
||||
testImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/test";
|
||||
tag = "local";
|
||||
# Slightly reduces the time needed to import image
|
||||
compressor = "zstd";
|
||||
copyToRoot = testImageEnv;
|
||||
};
|
||||
# pack the test helm chart as a .tgz archive
|
||||
package =
|
||||
pkgs.runCommand "k3s-test-chart.tgz"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.kubernetes-helm ];
|
||||
chart = builtins.toJSON {
|
||||
name = "k3s-test-chart";
|
||||
version = "0.1.0";
|
||||
};
|
||||
values = builtins.toJSON {
|
||||
restartPolicy = "Never";
|
||||
runCommand = "";
|
||||
image = {
|
||||
repository = "foo";
|
||||
tag = "1.0.0";
|
||||
};
|
||||
};
|
||||
job = builtins.toJSON {
|
||||
apiVersion = "batch/v1";
|
||||
kind = "Job";
|
||||
metadata = {
|
||||
name = "{{ .Release.Name }}";
|
||||
namespace = "{{ .Release.Namespace }}";
|
||||
};
|
||||
spec = {
|
||||
template = {
|
||||
spec = {
|
||||
containers = [
|
||||
{
|
||||
name = "test";
|
||||
image = "{{ .Values.image.repository }}:{{ .Values.image.tag }}";
|
||||
command = [ "sh" ];
|
||||
args = [
|
||||
"-c"
|
||||
"{{ .Values.runCommand }}"
|
||||
];
|
||||
}
|
||||
];
|
||||
restartPolicy = "{{ .Values.restartPolicy }}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
passAsFile = [
|
||||
"values"
|
||||
"chart"
|
||||
"job"
|
||||
];
|
||||
}
|
||||
''
|
||||
mkdir -p chart/templates
|
||||
cp "$chartPath" chart/Chart.yaml
|
||||
cp "$valuesPath" chart/values.yaml
|
||||
cp "$jobPath" chart/templates/job.json
|
||||
|
||||
helm package chart
|
||||
mv ./*.tgz $out
|
||||
'';
|
||||
# The common Helm chart that is used in this test
|
||||
testChart = {
|
||||
inherit package;
|
||||
values = {
|
||||
runCommand = "hello";
|
||||
image = {
|
||||
repository = testImage.imageName;
|
||||
tag = testImage.imageTag;
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "${k3s.name}-auto-deploy-helm";
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation = {
|
||||
memorySize = 1536;
|
||||
diskSize = 4096;
|
||||
};
|
||||
environment.systemPackages = [ pkgs.yq-go ];
|
||||
services.k3s = {
|
||||
enable = true;
|
||||
package = k3s;
|
||||
# Slightly reduce resource usage
|
||||
extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
];
|
||||
images = [
|
||||
# Provides the k3s Helm controller
|
||||
k3s.airgap-images
|
||||
testImage
|
||||
];
|
||||
autoDeployCharts = {
|
||||
# regular test chart that should get installed
|
||||
hello = testChart;
|
||||
# disabled chart that should not get installed
|
||||
disabled = testChart // {
|
||||
enable = false;
|
||||
};
|
||||
# chart with values set via YAML file
|
||||
values-file = testChart // {
|
||||
# Remove unsafeDiscardStringContext workaround when Nix can convert a string to a path
|
||||
# https://github.com/NixOS/nix/issues/12407
|
||||
values =
|
||||
/.
|
||||
+ builtins.unsafeDiscardStringContext (
|
||||
builtins.toFile "k3s-test-chart-values.yaml" ''
|
||||
runCommand: "echo 'Hello, file!'"
|
||||
image:
|
||||
repository: test.local/test
|
||||
tag: local
|
||||
''
|
||||
);
|
||||
};
|
||||
# advanced chart that should get installed in the "test" namespace with a custom
|
||||
# timeout and overridden values
|
||||
advanced = testChart // {
|
||||
# create the "test" namespace via extraDeploy for testing
|
||||
extraDeploy = [
|
||||
{
|
||||
apiVersion = "v1";
|
||||
kind = "Namespace";
|
||||
metadata.name = "test";
|
||||
}
|
||||
];
|
||||
extraFieldDefinitions = {
|
||||
spec = {
|
||||
# overwrite chart values
|
||||
valuesContent = ''
|
||||
runCommand: "echo 'advanced hello'"
|
||||
image:
|
||||
repository: ${testImage.imageName}
|
||||
tag: ${testImage.imageTag}
|
||||
'';
|
||||
# overwrite the chart namespace
|
||||
targetNamespace = "test";
|
||||
# set a custom timeout
|
||||
timeout = "69s";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
import json
|
||||
|
||||
machine.wait_for_unit("k3s")
|
||||
# check existence/absence of chart manifest files
|
||||
machine.succeed("test -e /var/lib/rancher/k3s/server/manifests/hello.yaml")
|
||||
machine.succeed("test ! -e /var/lib/rancher/k3s/server/manifests/disabled.yaml")
|
||||
machine.succeed("test -e /var/lib/rancher/k3s/server/manifests/values-file.yaml")
|
||||
machine.succeed("test -e /var/lib/rancher/k3s/server/manifests/advanced.yaml")
|
||||
# check that the timeout is set correctly, select only the first doc in advanced.yaml
|
||||
advancedManifest = json.loads(machine.succeed("yq -o json '.items[0]' /var/lib/rancher/k3s/server/manifests/advanced.yaml"))
|
||||
t.assertEqual(advancedManifest["spec"]["timeout"], "69s", "unexpected value for spec.timeout")
|
||||
# wait for test jobs to complete
|
||||
machine.wait_until_succeeds("kubectl wait --for=condition=complete job/hello", timeout=180)
|
||||
machine.wait_until_succeeds("kubectl wait --for=condition=complete job/values-file", timeout=180)
|
||||
machine.wait_until_succeeds("kubectl -n test wait --for=condition=complete job/advanced", timeout=180)
|
||||
# check output of test jobs
|
||||
hello_output = machine.succeed("kubectl logs -l batch.kubernetes.io/job-name=hello")
|
||||
values_file_output = machine.succeed("kubectl logs -l batch.kubernetes.io/job-name=values-file")
|
||||
advanced_output = machine.succeed("kubectl -n test logs -l batch.kubernetes.io/job-name=advanced")
|
||||
# strip the output to remove trailing whitespaces
|
||||
t.assertEqual(hello_output.rstrip(), "Hello, world!", "unexpected output of hello job")
|
||||
t.assertEqual(values_file_output.rstrip(), "Hello, file!", "unexpected output of values file job")
|
||||
t.assertEqual(advanced_output.rstrip(), "advanced hello", "unexpected output of advanced job")
|
||||
# wait for bundled traefik deployment
|
||||
machine.wait_until_succeeds("kubectl -n kube-system rollout status deployment traefik", timeout=180)
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,124 +0,0 @@
|
||||
# Tests whether container images are imported and auto deploying manifests work
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
k3s,
|
||||
...
|
||||
}:
|
||||
let
|
||||
pauseImageEnv = pkgs.buildEnv {
|
||||
name = "k3s-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
tini
|
||||
(lib.hiPrio coreutils)
|
||||
busybox
|
||||
];
|
||||
};
|
||||
pauseImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/pause";
|
||||
tag = "local";
|
||||
copyToRoot = pauseImageEnv;
|
||||
config.Entrypoint = [
|
||||
"/bin/tini"
|
||||
"--"
|
||||
"/bin/sleep"
|
||||
"inf"
|
||||
];
|
||||
};
|
||||
helloImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/hello";
|
||||
tag = "local";
|
||||
copyToRoot = pkgs.hello;
|
||||
config.Entrypoint = [ "${pkgs.hello}/bin/hello" ];
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "${k3s.name}-auto-deploy";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ k3s ];
|
||||
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s.enable = true;
|
||||
services.k3s.role = "server";
|
||||
services.k3s.package = k3s;
|
||||
# Slightly reduce resource usage
|
||||
services.k3s.extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--pause-image test.local/pause:local"
|
||||
];
|
||||
services.k3s.images = [
|
||||
pauseImage
|
||||
helloImage
|
||||
];
|
||||
services.k3s.manifests = {
|
||||
absent = {
|
||||
enable = false;
|
||||
content = {
|
||||
apiVersion = "v1";
|
||||
kind = "Namespace";
|
||||
metadata.name = "absent";
|
||||
};
|
||||
};
|
||||
|
||||
present = {
|
||||
target = "foo-namespace.yaml";
|
||||
content = {
|
||||
apiVersion = "v1";
|
||||
kind = "Namespace";
|
||||
metadata.name = "foo";
|
||||
};
|
||||
};
|
||||
|
||||
hello.content = {
|
||||
apiVersion = "batch/v1";
|
||||
kind = "Job";
|
||||
metadata.name = "hello";
|
||||
spec = {
|
||||
template.spec = {
|
||||
containers = [
|
||||
{
|
||||
name = "hello";
|
||||
image = "test.local/hello:local";
|
||||
}
|
||||
];
|
||||
restartPolicy = "OnFailure";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("k3s")
|
||||
# check existence of the manifest files
|
||||
machine.fail("ls /var/lib/rancher/k3s/server/manifests/absent.yaml")
|
||||
machine.succeed("ls /var/lib/rancher/k3s/server/manifests/foo-namespace.yaml")
|
||||
machine.succeed("ls /var/lib/rancher/k3s/server/manifests/hello.yaml")
|
||||
|
||||
# check if container images got imported
|
||||
machine.wait_until_succeeds("crictl img | grep 'test\.local/pause'")
|
||||
machine.wait_until_succeeds("crictl img | grep 'test\.local/hello'")
|
||||
|
||||
# check if resources of manifests got created
|
||||
machine.wait_until_succeeds("kubectl get ns foo")
|
||||
machine.wait_until_succeeds("kubectl wait --for=condition=complete job/hello")
|
||||
machine.fail("kubectl get ns absent")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
}
|
||||
)
|
||||
@@ -1,59 +0,0 @@
|
||||
# A test that containerdConfigTemplate settings get written to containerd/config.toml
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
k3s,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nodeName = "test";
|
||||
in
|
||||
{
|
||||
name = "${k3s.name}-containerd-config";
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s = {
|
||||
enable = true;
|
||||
package = k3s;
|
||||
# Slightly reduce resource usage
|
||||
extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--node-name ${nodeName}"
|
||||
];
|
||||
containerdConfigTemplate = ''
|
||||
# Base K3s config
|
||||
{{ template "base" . }}
|
||||
|
||||
# MAGIC COMMENT
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_unit("k3s")
|
||||
# wait until the node is ready
|
||||
machine.wait_until_succeeds(r"""kubectl get node ${nodeName} -ojson | jq -e '.status.conditions[] | select(.type == "Ready") | .status == "True"'""")
|
||||
# test whether the config template file contains the magic comment
|
||||
out=machine.succeed("cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl")
|
||||
t.assertIn("MAGIC COMMENT", out, "the containerd config template does not contain the magic comment")
|
||||
# test whether the config file contains the magic comment
|
||||
out=machine.succeed("cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml")
|
||||
t.assertIn("MAGIC COMMENT", out, "the containerd config does not contain the magic comment")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
}
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
pkgs ? import ../../.. { inherit system; },
|
||||
lib ? pkgs.lib,
|
||||
}:
|
||||
let
|
||||
allK3s = lib.filterAttrs (
|
||||
n: _: lib.strings.hasPrefix "k3s_" n && (builtins.tryEval pkgs.${n}).success
|
||||
) pkgs;
|
||||
in
|
||||
{
|
||||
airgap-images = lib.mapAttrs (
|
||||
_: k3s: import ./airgap-images.nix { inherit system pkgs k3s; }
|
||||
) allK3s;
|
||||
auto-deploy = lib.mapAttrs (_: k3s: import ./auto-deploy.nix { inherit system pkgs k3s; }) allK3s;
|
||||
auto-deploy-charts = lib.mapAttrs (
|
||||
_: k3s: import ./auto-deploy-charts.nix { inherit system pkgs k3s; }
|
||||
) allK3s;
|
||||
containerd-config = lib.mapAttrs (
|
||||
_: k3s: import ./containerd-config.nix { inherit system pkgs k3s; }
|
||||
) allK3s;
|
||||
etcd = lib.mapAttrs (
|
||||
_: k3s:
|
||||
import ./etcd.nix {
|
||||
inherit system pkgs k3s;
|
||||
inherit (pkgs) etcd;
|
||||
}
|
||||
) allK3s;
|
||||
kubelet-config = lib.mapAttrs (
|
||||
_: k3s: import ./kubelet-config.nix { inherit system pkgs k3s; }
|
||||
) allK3s;
|
||||
multi-node = lib.mapAttrs (_: k3s: import ./multi-node.nix { inherit system pkgs k3s; }) allK3s;
|
||||
single-node = lib.mapAttrs (_: k3s: import ./single-node.nix { inherit system pkgs k3s; }) allK3s;
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
# Tests K3s with Etcd backend
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
k3s,
|
||||
etcd,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
name = "${k3s.name}-etcd";
|
||||
|
||||
nodes = {
|
||||
|
||||
etcd =
|
||||
{ ... }:
|
||||
{
|
||||
services.etcd = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
listenClientUrls = [
|
||||
"http://192.168.1.1:2379"
|
||||
"http://127.0.0.1:2379"
|
||||
];
|
||||
listenPeerUrls = [ "http://192.168.1.1:2380" ];
|
||||
initialAdvertisePeerUrls = [ "http://192.168.1.1:2380" ];
|
||||
initialCluster = [ "etcd=http://192.168.1.1:2380" ];
|
||||
};
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
defaultGateway = "192.168.1.1";
|
||||
interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
|
||||
{
|
||||
address = "192.168.1.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
k3s =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [ jq ];
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = k3s;
|
||||
extraFlags = [
|
||||
"--datastore-endpoint=\"http://192.168.1.1:2379\""
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--node-ip 192.168.1.2"
|
||||
];
|
||||
};
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
allowedTCPPorts = [
|
||||
2379
|
||||
2380
|
||||
6443
|
||||
];
|
||||
allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
useDHCP = false;
|
||||
defaultGateway = "192.168.1.2";
|
||||
interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
|
||||
{
|
||||
address = "192.168.1.2";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
with subtest("should start etcd"):
|
||||
etcd.start()
|
||||
etcd.wait_for_unit("etcd.service")
|
||||
|
||||
with subtest("should wait for etcdctl endpoint status to succeed"):
|
||||
etcd.wait_until_succeeds("etcdctl endpoint status")
|
||||
|
||||
with subtest("should wait for etcdctl endpoint health to succeed"):
|
||||
etcd.wait_until_succeeds("etcdctl endpoint health")
|
||||
|
||||
with subtest("should start k3s"):
|
||||
k3s.start()
|
||||
k3s.wait_for_unit("k3s")
|
||||
|
||||
with subtest("should test if kubectl works"):
|
||||
k3s.wait_until_succeeds("k3s kubectl get node")
|
||||
|
||||
with subtest("should wait for service account to show up; takes a sec"):
|
||||
k3s.wait_until_succeeds("k3s kubectl get serviceaccount default")
|
||||
|
||||
with subtest("should create a sample secret object"):
|
||||
k3s.succeed("k3s kubectl create secret generic nixossecret --from-literal thesecret=abacadabra")
|
||||
|
||||
with subtest("should check if secret is correct"):
|
||||
k3s.wait_until_succeeds("[[ $(kubectl get secrets nixossecret -o json | jq -r .data.thesecret | base64 -d) == abacadabra ]]")
|
||||
|
||||
with subtest("should have a secret in database"):
|
||||
etcd.wait_until_succeeds("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
|
||||
|
||||
with subtest("should delete the secret"):
|
||||
k3s.succeed("k3s kubectl delete secret nixossecret")
|
||||
|
||||
with subtest("should not have a secret in database"):
|
||||
etcd.wait_until_fails("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
|
||||
'';
|
||||
|
||||
meta.maintainers = etcd.meta.maintainers ++ lib.teams.k3s.members;
|
||||
}
|
||||
)
|
||||
@@ -1,76 +0,0 @@
|
||||
# A test that sets extra kubelet configuration and enables graceful node shutdown
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
k3s,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nodeName = "test";
|
||||
shutdownGracePeriod = "1m13s";
|
||||
shutdownGracePeriodCriticalPods = "13s";
|
||||
podsPerCore = 3;
|
||||
memoryThrottlingFactor = 0.69;
|
||||
containerLogMaxSize = "5Mi";
|
||||
in
|
||||
{
|
||||
name = "${k3s.name}-kubelet-config";
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s = {
|
||||
enable = true;
|
||||
package = k3s;
|
||||
# Slightly reduce resource usage
|
||||
extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--node-name ${nodeName}"
|
||||
];
|
||||
gracefulNodeShutdown = {
|
||||
enable = true;
|
||||
inherit shutdownGracePeriod shutdownGracePeriodCriticalPods;
|
||||
};
|
||||
extraKubeletConfig = {
|
||||
inherit podsPerCore memoryThrottlingFactor containerLogMaxSize;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
import json
|
||||
|
||||
start_all()
|
||||
machine.wait_for_unit("k3s")
|
||||
# wait until the node is ready
|
||||
machine.wait_until_succeeds(r"""kubectl get node ${nodeName} -ojson | jq -e '.status.conditions[] | select(.type == "Ready") | .status == "True"'""")
|
||||
# test whether the kubelet registered an inhibitor lock
|
||||
machine.succeed("systemd-inhibit --list --no-legend | grep \"kubelet.*k3s-server.*shutdown\"")
|
||||
# run kubectl proxy in the background, close stdout through redirection to not wait for the command to finish
|
||||
machine.execute("kubectl proxy --address 127.0.0.1 --port=8001 >&2 &")
|
||||
machine.wait_until_succeeds("nc -z 127.0.0.1 8001")
|
||||
# get the kubeletconfig
|
||||
kubelet_config=json.loads(machine.succeed("curl http://127.0.0.1:8001/api/v1/nodes/${nodeName}/proxy/configz | jq '.kubeletconfig'"))
|
||||
|
||||
with subtest("Kubelet config values are set correctly"):
|
||||
t.assertEqual(kubelet_config["shutdownGracePeriod"], "${shutdownGracePeriod}")
|
||||
t.assertEqual(kubelet_config["shutdownGracePeriodCriticalPods"], "${shutdownGracePeriodCriticalPods}")
|
||||
t.assertEqual(kubelet_config["podsPerCore"], ${toString podsPerCore})
|
||||
t.assertEqual(kubelet_config["memoryThrottlingFactor"], ${toString memoryThrottlingFactor})
|
||||
t.assertEqual(kubelet_config["containerLogMaxSize"],"${containerLogMaxSize}")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
}
|
||||
)
|
||||
@@ -1,200 +0,0 @@
|
||||
# A test that runs a multi-node k3s cluster and verify pod networking works across nodes
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
k3s,
|
||||
...
|
||||
}:
|
||||
let
|
||||
imageEnv = pkgs.buildEnv {
|
||||
name = "k3s-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
tini
|
||||
bashInteractive
|
||||
coreutils
|
||||
socat
|
||||
];
|
||||
};
|
||||
pauseImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/pause";
|
||||
tag = "local";
|
||||
copyToRoot = imageEnv;
|
||||
config.Entrypoint = [
|
||||
"/bin/tini"
|
||||
"--"
|
||||
"/bin/sleep"
|
||||
"inf"
|
||||
];
|
||||
};
|
||||
# A daemonset that responds 'server' on port 8000
|
||||
networkTestDaemonset = pkgs.writeText "test.yml" ''
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: test
|
||||
labels:
|
||||
name: test
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: test.local/pause:local
|
||||
imagePullPolicy: Never
|
||||
resources:
|
||||
limits:
|
||||
memory: 20Mi
|
||||
command: ["socat", "TCP4-LISTEN:8000,fork", "EXEC:echo server"]
|
||||
'';
|
||||
tokenFile = pkgs.writeText "token" "p@s$w0rd";
|
||||
in
|
||||
{
|
||||
name = "${k3s.name}-multi-node";
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{ nodes, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
gzip
|
||||
jq
|
||||
];
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s = {
|
||||
inherit tokenFile;
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = k3s;
|
||||
images = [ pauseImage ];
|
||||
clusterInit = true;
|
||||
extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--pause-image test.local/pause:local"
|
||||
"--node-ip ${nodes.server.networking.primaryIPAddress}"
|
||||
# The interface selection logic of flannel would normally use eth0, as the nixos
|
||||
# testing driver sets a default route via dev eth0. However, in test setups we
|
||||
# have to use eth1 for inter-node communication.
|
||||
"--flannel-iface eth1"
|
||||
];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
2379
|
||||
2380
|
||||
6443
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
|
||||
server2 =
|
||||
{ nodes, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
gzip
|
||||
jq
|
||||
];
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s = {
|
||||
inherit tokenFile;
|
||||
enable = true;
|
||||
package = k3s;
|
||||
images = [ pauseImage ];
|
||||
serverAddr = "https://${nodes.server.networking.primaryIPAddress}:6443";
|
||||
clusterInit = false;
|
||||
extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--pause-image test.local/pause:local"
|
||||
"--node-ip ${nodes.server2.networking.primaryIPAddress}"
|
||||
"--flannel-iface eth1"
|
||||
];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
2379
|
||||
2380
|
||||
6443
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
|
||||
agent =
|
||||
{ nodes, pkgs, ... }:
|
||||
{
|
||||
virtualisation.memorySize = 1024;
|
||||
virtualisation.diskSize = 2048;
|
||||
services.k3s = {
|
||||
inherit tokenFile;
|
||||
enable = true;
|
||||
role = "agent";
|
||||
package = k3s;
|
||||
images = [ pauseImage ];
|
||||
serverAddr = "https://${nodes.server2.networking.primaryIPAddress}:6443";
|
||||
extraFlags = [
|
||||
"--pause-image test.local/pause:local"
|
||||
"--node-ip ${nodes.agent.networking.primaryIPAddress}"
|
||||
"--flannel-iface eth1"
|
||||
];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 6443 ];
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
|
||||
machines = [server, server2, agent]
|
||||
for m in machines:
|
||||
m.wait_for_unit("k3s")
|
||||
|
||||
# wait for the agent to show up
|
||||
server.wait_until_succeeds("k3s kubectl get node agent")
|
||||
|
||||
for m in machines:
|
||||
m.succeed("k3s check-config")
|
||||
|
||||
server.succeed("k3s kubectl cluster-info")
|
||||
# Also wait for our service account to show up; it takes a sec
|
||||
server.wait_until_succeeds("k3s kubectl get serviceaccount default")
|
||||
|
||||
# Now create a pod on each node via a daemonset and verify they can talk to each other.
|
||||
server.succeed("k3s kubectl apply -f ${networkTestDaemonset}")
|
||||
server.wait_until_succeeds(f'[ "$(k3s kubectl get ds test -o json | jq .status.numberReady)" -eq {len(machines)} ]')
|
||||
|
||||
# Get pod IPs
|
||||
pods = server.succeed("k3s kubectl get po -o json | jq '.items[].metadata.name' -r").splitlines()
|
||||
pod_ips = [server.succeed(f"k3s kubectl get po {name} -o json | jq '.status.podIP' -cr").strip() for name in pods]
|
||||
|
||||
# Verify each server can ping each pod ip
|
||||
for pod_ip in pod_ips:
|
||||
server.succeed(f"ping -c 1 {pod_ip}")
|
||||
server2.succeed(f"ping -c 1 {pod_ip}")
|
||||
agent.succeed(f"ping -c 1 {pod_ip}")
|
||||
# Verify the pods can talk to each other
|
||||
for pod in pods:
|
||||
resp = server.succeed(f"k3s kubectl exec {pod} -- socat TCP:{pod_ip}:8000 -")
|
||||
t.assertEqual(resp.strip(), "server")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
}
|
||||
)
|
||||
@@ -1,115 +0,0 @@
|
||||
# A test that runs a single node k3s cluster and verify a pod can run
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
k3s,
|
||||
...
|
||||
}:
|
||||
let
|
||||
imageEnv = pkgs.buildEnv {
|
||||
name = "k3s-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
tini
|
||||
(lib.hiPrio coreutils)
|
||||
busybox
|
||||
];
|
||||
};
|
||||
pauseImage = pkgs.dockerTools.streamLayeredImage {
|
||||
name = "test.local/pause";
|
||||
tag = "local";
|
||||
contents = imageEnv;
|
||||
config.Entrypoint = [
|
||||
"/bin/tini"
|
||||
"--"
|
||||
"/bin/sleep"
|
||||
"inf"
|
||||
];
|
||||
};
|
||||
testPodYaml = pkgs.writeText "test.yml" ''
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: test.local/pause:local
|
||||
imagePullPolicy: Never
|
||||
command: ["sh", "-c", "sleep inf"]
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "${k3s.name}-single-node";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
k3s
|
||||
gzip
|
||||
];
|
||||
|
||||
# k3s uses enough resources the default vm fails.
|
||||
virtualisation.memorySize = 1536;
|
||||
virtualisation.diskSize = 4096;
|
||||
|
||||
services.k3s.enable = true;
|
||||
services.k3s.role = "server";
|
||||
services.k3s.package = k3s;
|
||||
# Slightly reduce resource usage
|
||||
services.k3s.extraFlags = [
|
||||
"--disable coredns"
|
||||
"--disable local-storage"
|
||||
"--disable metrics-server"
|
||||
"--disable servicelb"
|
||||
"--disable traefik"
|
||||
"--pause-image test.local/pause:local"
|
||||
];
|
||||
|
||||
users.users = {
|
||||
noprivs = {
|
||||
isNormalUser = true;
|
||||
description = "Can't access k3s by default";
|
||||
password = "*";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("k3s")
|
||||
machine.succeed("kubectl cluster-info")
|
||||
machine.fail("sudo -u noprivs kubectl cluster-info")
|
||||
machine.succeed("k3s check-config")
|
||||
machine.succeed(
|
||||
"${pauseImage} | ctr image import -"
|
||||
)
|
||||
|
||||
# Also wait for our service account to show up; it takes a sec
|
||||
machine.wait_until_succeeds("kubectl get serviceaccount default")
|
||||
machine.succeed("kubectl apply -f ${testPodYaml}")
|
||||
machine.succeed("kubectl wait --for 'condition=Ready' pod/test")
|
||||
machine.succeed("kubectl delete -f ${testPodYaml}")
|
||||
|
||||
# regression test for #176445
|
||||
machine.fail("journalctl -o cat -u k3s.service | grep 'ipset utility not found'")
|
||||
|
||||
with subtest("Run k3s-killall"):
|
||||
# Call the killall script with a clean path to assert that
|
||||
# all required commands are wrapped
|
||||
output = machine.succeed("PATH= ${k3s}/bin/k3s-killall.sh 2>&1 | tee /dev/stderr")
|
||||
t.assertNotIn("command not found", output, "killall script contains unknown command")
|
||||
|
||||
# Check that killall cleaned up properly
|
||||
machine.fail("systemctl is-active k3s.service")
|
||||
machine.fail("systemctl list-units | grep containerd")
|
||||
machine.fail("ip link show | awk -F': ' '{print $2}' | grep -e flannel -e cni0")
|
||||
machine.fail("ip netns show | grep cni-")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members;
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
# A test that imports k3s airgapped images and verifies that all expected images are present
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
{
|
||||
name = "${rancherPackage.name}-airgap-images";
|
||||
|
||||
nodes.machine = _: {
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rancherPackage;
|
||||
disable = disabledComponents;
|
||||
images =
|
||||
coreImages
|
||||
++ {
|
||||
k3s = [ rancherPackage.airgap-images ];
|
||||
rke2 = [ ]; # RKE2 already includes its airgap-images in coreImages
|
||||
}
|
||||
.${rancherDistro};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("${serviceName}")
|
||||
machine.wait_until_succeeds("journalctl -r --no-pager -u ${serviceName} | grep \"Imported images from /var/lib/rancher/${rancherDistro}/agent/images/\"")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
# Tests whether container images are imported and auto deploying Helm charts,
|
||||
# including the bundled traefik or ingress-nginx, work
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
let
|
||||
testImageEnv = pkgs.buildEnv {
|
||||
name = "${rancherDistro}-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
busybox
|
||||
hello
|
||||
];
|
||||
};
|
||||
testImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/test";
|
||||
tag = "local";
|
||||
# Slightly reduces the time needed to import image
|
||||
compressor = "zstd";
|
||||
copyToRoot = testImageEnv;
|
||||
};
|
||||
# pack the test helm chart as a .tgz archive
|
||||
package =
|
||||
pkgs.runCommand "${rancherDistro}-test-chart.tgz"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.kubernetes-helm ];
|
||||
chart = builtins.toJSON {
|
||||
name = "${rancherDistro}-test-chart";
|
||||
version = "0.1.0";
|
||||
};
|
||||
values = builtins.toJSON {
|
||||
restartPolicy = "Never";
|
||||
runCommand = "";
|
||||
image = {
|
||||
repository = "foo";
|
||||
tag = "1.0.0";
|
||||
};
|
||||
};
|
||||
job = builtins.toJSON {
|
||||
apiVersion = "batch/v1";
|
||||
kind = "Job";
|
||||
metadata = {
|
||||
name = "{{ .Release.Name }}";
|
||||
namespace = "{{ .Release.Namespace }}";
|
||||
};
|
||||
spec = {
|
||||
template = {
|
||||
spec = {
|
||||
containers = [
|
||||
{
|
||||
name = "test";
|
||||
image = "{{ .Values.image.repository }}:{{ .Values.image.tag }}";
|
||||
command = [ "sh" ];
|
||||
args = [
|
||||
"-c"
|
||||
"{{ .Values.runCommand }}"
|
||||
];
|
||||
}
|
||||
];
|
||||
restartPolicy = "{{ .Values.restartPolicy }}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
passAsFile = [
|
||||
"values"
|
||||
"chart"
|
||||
"job"
|
||||
];
|
||||
}
|
||||
''
|
||||
mkdir -p chart/templates
|
||||
cp "$chartPath" chart/Chart.yaml
|
||||
cp "$valuesPath" chart/values.yaml
|
||||
cp "$jobPath" chart/templates/job.json
|
||||
|
||||
helm package chart
|
||||
mv ./*.tgz $out
|
||||
'';
|
||||
# The common Helm chart that is used in this test
|
||||
testChart = {
|
||||
inherit package;
|
||||
values = {
|
||||
runCommand = "hello";
|
||||
image = {
|
||||
repository = testImage.imageName;
|
||||
tag = testImage.imageTag;
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "${rancherPackage.name}-auto-deploy-helm";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
yq-go
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
package = rancherPackage;
|
||||
disable =
|
||||
{
|
||||
k3s = lib.remove "traefik" disabledComponents;
|
||||
rke2 = lib.remove "rke2-ingress-nginx" disabledComponents;
|
||||
}
|
||||
.${rancherDistro};
|
||||
images =
|
||||
coreImages
|
||||
# Provides the k3s Helm controller
|
||||
++ lib.optional (rancherDistro == "k3s") rancherPackage.airgap-images
|
||||
++ [
|
||||
testImage
|
||||
];
|
||||
autoDeployCharts = {
|
||||
# regular test chart that should get installed
|
||||
hello = testChart;
|
||||
# disabled chart that should not get installed
|
||||
disabled = testChart // {
|
||||
enable = false;
|
||||
};
|
||||
# chart with values set via YAML file
|
||||
values-file = testChart // {
|
||||
# Remove unsafeDiscardStringContext workaround when Nix can convert a string to a path
|
||||
# https://github.com/NixOS/nix/issues/12407
|
||||
values =
|
||||
/.
|
||||
+ builtins.unsafeDiscardStringContext (
|
||||
builtins.toFile "${rancherDistro}-test-chart-values.yaml" ''
|
||||
runCommand: "echo 'Hello, file!'"
|
||||
image:
|
||||
repository: test.local/test
|
||||
tag: local
|
||||
''
|
||||
);
|
||||
};
|
||||
# advanced chart that should get installed in the "test" namespace with a custom
|
||||
# timeout and overridden values
|
||||
advanced = testChart // {
|
||||
# create the "test" namespace via extraDeploy for testing
|
||||
extraDeploy = [
|
||||
{
|
||||
apiVersion = "v1";
|
||||
kind = "Namespace";
|
||||
metadata.name = "test";
|
||||
}
|
||||
];
|
||||
extraFieldDefinitions = {
|
||||
spec = {
|
||||
# overwrite chart values
|
||||
valuesContent = ''
|
||||
runCommand: "echo 'advanced hello'"
|
||||
image:
|
||||
repository: ${testImage.imageName}
|
||||
tag: ${testImage.imageTag}
|
||||
'';
|
||||
# overwrite the chart namespace
|
||||
targetNamespace = "test";
|
||||
# set a custom timeout
|
||||
timeout = "69s";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
let
|
||||
manifestFormat =
|
||||
{
|
||||
k3s = "yaml";
|
||||
rke2 = "json";
|
||||
}
|
||||
.${rancherDistro};
|
||||
in
|
||||
''
|
||||
import json
|
||||
|
||||
machine.wait_for_unit("${serviceName}")
|
||||
# check existence/absence of chart manifest files
|
||||
machine.succeed("test -e /var/lib/rancher/${rancherDistro}/server/manifests/hello.${manifestFormat}")
|
||||
machine.succeed("test ! -e /var/lib/rancher/${rancherDistro}/server/manifests/disabled.${manifestFormat}")
|
||||
machine.succeed("test -e /var/lib/rancher/${rancherDistro}/server/manifests/values-file.${manifestFormat}")
|
||||
machine.succeed("test -e /var/lib/rancher/${rancherDistro}/server/manifests/advanced.${manifestFormat}")
|
||||
# check that the timeout is set correctly, select only the first item in advanced.yaml
|
||||
advancedManifest = json.loads(machine.succeed("yq -o json '.items[0]' /var/lib/rancher/${rancherDistro}/server/manifests/advanced.${manifestFormat}"))
|
||||
t.assertEqual(advancedManifest["spec"]["timeout"], "69s", "unexpected value for spec.timeout")
|
||||
# wait for test jobs to complete
|
||||
machine.wait_until_succeeds("kubectl wait --for=condition=complete job/hello", timeout=180)
|
||||
machine.wait_until_succeeds("kubectl wait --for=condition=complete job/values-file", timeout=180)
|
||||
machine.wait_until_succeeds("kubectl -n test wait --for=condition=complete job/advanced", timeout=180)
|
||||
# check output of test jobs
|
||||
hello_output = machine.succeed("kubectl logs -l batch.kubernetes.io/job-name=hello")
|
||||
values_file_output = machine.succeed("kubectl logs -l batch.kubernetes.io/job-name=values-file")
|
||||
advanced_output = machine.succeed("kubectl -n test logs -l batch.kubernetes.io/job-name=advanced")
|
||||
# strip the output to remove trailing whitespaces
|
||||
t.assertEqual(hello_output.rstrip(), "Hello, world!", "unexpected output of hello job")
|
||||
t.assertEqual(values_file_output.rstrip(), "Hello, file!", "unexpected output of values file job")
|
||||
t.assertEqual(advanced_output.rstrip(), "advanced hello", "unexpected output of advanced job")
|
||||
# wait for bundled ingress deployment
|
||||
${
|
||||
{
|
||||
k3s = ''
|
||||
machine.wait_until_succeeds("kubectl -n kube-system rollout status deployment traefik", timeout=180)
|
||||
'';
|
||||
rke2 = ''
|
||||
machine.wait_until_succeeds("kubectl -n kube-system rollout status daemonset rke2-ingress-nginx-controller", timeout=180)
|
||||
'';
|
||||
}
|
||||
.${rancherDistro}
|
||||
}
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
# Tests whether container images are imported and auto deploying manifests work
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
let
|
||||
pauseImageEnv = pkgs.buildEnv {
|
||||
name = "${rancherDistro}-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
tini
|
||||
(lib.hiPrio coreutils)
|
||||
busybox
|
||||
];
|
||||
};
|
||||
pauseImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/pause";
|
||||
tag = "local";
|
||||
copyToRoot = pauseImageEnv;
|
||||
config.Entrypoint = [
|
||||
"/bin/tini"
|
||||
"--"
|
||||
"/bin/sleep"
|
||||
"inf"
|
||||
];
|
||||
};
|
||||
helloImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/hello";
|
||||
tag = "local";
|
||||
copyToRoot = pkgs.hello;
|
||||
config.Entrypoint = [ "${pkgs.hello}/bin/hello" ];
|
||||
};
|
||||
|
||||
manifestFormat =
|
||||
{
|
||||
k3s = "yaml";
|
||||
rke2 = "json";
|
||||
}
|
||||
.${rancherDistro};
|
||||
in
|
||||
{
|
||||
name = "${rancherPackage.name}-auto-deploy";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
cri-tools
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rancherPackage;
|
||||
disable = disabledComponents;
|
||||
extraFlags = [
|
||||
"--pause-image test.local/pause:local"
|
||||
];
|
||||
images = coreImages ++ [
|
||||
pauseImage
|
||||
helloImage
|
||||
];
|
||||
manifests = {
|
||||
absent = {
|
||||
enable = false;
|
||||
content = {
|
||||
apiVersion = "v1";
|
||||
kind = "Namespace";
|
||||
metadata.name = "absent";
|
||||
};
|
||||
};
|
||||
|
||||
present = {
|
||||
target = "foo-namespace.${manifestFormat}";
|
||||
content = {
|
||||
apiVersion = "v1";
|
||||
kind = "Namespace";
|
||||
metadata.name = "foo";
|
||||
};
|
||||
};
|
||||
|
||||
hello.content = {
|
||||
apiVersion = "batch/v1";
|
||||
kind = "Job";
|
||||
metadata.name = "hello";
|
||||
spec = {
|
||||
template.spec = {
|
||||
containers = [
|
||||
{
|
||||
name = "hello";
|
||||
image = "test.local/hello:local";
|
||||
}
|
||||
];
|
||||
restartPolicy = "OnFailure";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("${serviceName}")
|
||||
# check existence of the manifest files
|
||||
machine.fail("ls /var/lib/rancher/${rancherDistro}/server/manifests/absent.${manifestFormat}")
|
||||
machine.succeed("ls /var/lib/rancher/${rancherDistro}/server/manifests/foo-namespace.${manifestFormat}")
|
||||
machine.succeed("ls /var/lib/rancher/${rancherDistro}/server/manifests/hello.${manifestFormat}")
|
||||
|
||||
# check if container images got imported
|
||||
# for some reason, RKE2 also uses /run/k3s
|
||||
machine.wait_until_succeeds("crictl -r /run/k3s/containerd/containerd.sock img | grep 'test\.local/pause'")
|
||||
machine.wait_until_succeeds("crictl -r /run/k3s/containerd/containerd.sock img | grep 'test\.local/hello'")
|
||||
|
||||
# check if resources of manifests got created
|
||||
machine.wait_until_succeeds("kubectl get ns foo")
|
||||
machine.wait_until_succeeds("kubectl wait --for=condition=complete job/hello")
|
||||
machine.fail("kubectl get ns absent")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
# A test that containerdConfigTemplate settings get written to containerd/config.toml
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nodeName = "test";
|
||||
in
|
||||
{
|
||||
name = "${rancherPackage.name}-containerd-config";
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
jq
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
package = rancherPackage;
|
||||
disable = disabledComponents;
|
||||
images = coreImages;
|
||||
inherit nodeName;
|
||||
containerdConfigTemplate = ''
|
||||
# Base ${rancherDistro} config
|
||||
{{ template "base" . }}
|
||||
|
||||
# MAGIC COMMENT
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_unit("${serviceName}")
|
||||
# wait until the node is ready
|
||||
machine.wait_until_succeeds(r"""kubectl get node ${nodeName} -ojson | jq -e '.status.conditions[] | select(.type == "Ready") | .status == "True"'""")
|
||||
# test whether the config template file contains the magic comment
|
||||
out=machine.succeed("cat /var/lib/rancher/${rancherDistro}/agent/etc/containerd/config.toml.tmpl")
|
||||
t.assertIn("MAGIC COMMENT", out, "the containerd config template does not contain the magic comment")
|
||||
# test whether the config file contains the magic comment
|
||||
out=machine.succeed("cat /var/lib/rancher/${rancherDistro}/agent/etc/containerd/config.toml")
|
||||
t.assertIn("MAGIC COMMENT", out, "the containerd config does not contain the magic comment")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
{
|
||||
runTest,
|
||||
pkgs,
|
||||
lib,
|
||||
# service/package name to test
|
||||
rancherDistro,
|
||||
...
|
||||
}:
|
||||
let
|
||||
allPackages = lib.filterAttrs (
|
||||
name: package:
|
||||
builtins.match "^${rancherDistro}(_[[:digit:]]+)+$" name != null
|
||||
&& (builtins.tryEval package).success
|
||||
) pkgs;
|
||||
|
||||
allTests =
|
||||
let
|
||||
mkTestArgs = rancherPackage: {
|
||||
inherit rancherDistro rancherPackage;
|
||||
|
||||
# systemd service name
|
||||
serviceName =
|
||||
{
|
||||
k3s = "k3s";
|
||||
rke2 = "rke2-server";
|
||||
}
|
||||
.${rancherDistro};
|
||||
|
||||
# list passed to services.*.disable,
|
||||
# for slightly reduced resource usage
|
||||
disabledComponents =
|
||||
{
|
||||
k3s = [
|
||||
"coredns"
|
||||
"local-storage"
|
||||
"metrics-server"
|
||||
"servicelb"
|
||||
"traefik"
|
||||
];
|
||||
rke2 = [
|
||||
"rke2-coredns"
|
||||
"rke2-metrics-server"
|
||||
"rke2-ingress-nginx"
|
||||
"rke2-snapshot-controller"
|
||||
"rke2-snapshot-controller-crd"
|
||||
"rke2-snapshot-validation-webhook"
|
||||
];
|
||||
}
|
||||
.${rancherDistro};
|
||||
|
||||
# images that must be present for all tests
|
||||
coreImages =
|
||||
{
|
||||
k3s = [ ];
|
||||
|
||||
rke2 =
|
||||
{
|
||||
aarch64-linux = [
|
||||
rancherPackage.images-core-linux-arm64-tar-zst
|
||||
rancherPackage.images-canal-linux-arm64-tar-zst
|
||||
];
|
||||
x86_64-linux = [
|
||||
rancherPackage.images-core-linux-amd64-tar-zst
|
||||
rancherPackage.images-canal-linux-amd64-tar-zst
|
||||
];
|
||||
}
|
||||
.${pkgs.stdenv.hostPlatform.system}
|
||||
or (throw "RKE2: Unsupported system: ${pkgs.stdenv.hostPlatform.system}");
|
||||
}
|
||||
.${rancherDistro};
|
||||
|
||||
# virtualization.* attrs, since all distros
|
||||
# need more resources than the default
|
||||
vmResources =
|
||||
{
|
||||
k3s = {
|
||||
memorySize = 1536;
|
||||
diskSize = 4096;
|
||||
};
|
||||
rke2 = {
|
||||
cores = 4;
|
||||
memorySize = 4096;
|
||||
diskSize = 8092;
|
||||
};
|
||||
}
|
||||
.${rancherDistro};
|
||||
};
|
||||
|
||||
mkTests =
|
||||
path:
|
||||
lib.mapAttrs (
|
||||
name: package:
|
||||
runTest {
|
||||
imports = [ path ];
|
||||
_module.args = mkTestArgs package;
|
||||
}
|
||||
) allPackages;
|
||||
in
|
||||
{
|
||||
airgap-images = mkTests ./airgap-images.nix;
|
||||
auto-deploy = mkTests ./auto-deploy.nix;
|
||||
auto-deploy-charts = mkTests ./auto-deploy-charts.nix;
|
||||
containerd-config = mkTests ./containerd-config.nix;
|
||||
etcd = mkTests ./etcd.nix;
|
||||
kubelet-config = mkTests ./kubelet-config.nix;
|
||||
multi-node = mkTests ./multi-node.nix;
|
||||
single-node = mkTests ./single-node.nix;
|
||||
};
|
||||
in
|
||||
|
||||
allTests
|
||||
// {
|
||||
all = lib.concatMapAttrs (
|
||||
testType: lib.mapAttrs' (package: lib.nameValuePair "${testType}-${package}")
|
||||
) allTests;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
# Tests K3s with Etcd backend
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
name = "${rancherPackage.name}-etcd";
|
||||
|
||||
nodes = {
|
||||
|
||||
etcd =
|
||||
{ ... }:
|
||||
{
|
||||
services.etcd = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
listenClientUrls = [
|
||||
"http://192.168.1.1:2379"
|
||||
"http://127.0.0.1:2379"
|
||||
];
|
||||
listenPeerUrls = [ "http://192.168.1.1:2380" ];
|
||||
initialAdvertisePeerUrls = [ "http://192.168.1.1:2380" ];
|
||||
initialCluster = [ "etcd=http://192.168.1.1:2380" ];
|
||||
};
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
defaultGateway = "192.168.1.1";
|
||||
interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
|
||||
{
|
||||
address = "192.168.1.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
server =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
jq
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rancherPackage;
|
||||
disable = disabledComponents;
|
||||
images = coreImages;
|
||||
nodeIP = "192.168.1.2";
|
||||
extraFlags = [
|
||||
"--datastore-endpoint=\"http://192.168.1.1:2379\""
|
||||
];
|
||||
};
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
allowedTCPPorts = [
|
||||
2379
|
||||
2380
|
||||
6443
|
||||
];
|
||||
allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
useDHCP = false;
|
||||
defaultGateway = "192.168.1.2";
|
||||
interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
|
||||
{
|
||||
address = "192.168.1.2";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
with subtest("should start etcd"):
|
||||
etcd.start()
|
||||
etcd.wait_for_unit("etcd.service")
|
||||
|
||||
with subtest("should wait for etcdctl endpoint status to succeed"):
|
||||
etcd.wait_until_succeeds("etcdctl endpoint status")
|
||||
|
||||
with subtest("should wait for etcdctl endpoint health to succeed"):
|
||||
etcd.wait_until_succeeds("etcdctl endpoint health")
|
||||
|
||||
with subtest("should start ${rancherDistro}"):
|
||||
server.start()
|
||||
server.wait_for_unit("${serviceName}")
|
||||
|
||||
with subtest("should test if kubectl works"):
|
||||
server.wait_until_succeeds("kubectl get node")
|
||||
|
||||
with subtest("should wait for service account to show up; takes a sec"):
|
||||
server.wait_until_succeeds("kubectl get serviceaccount default")
|
||||
|
||||
with subtest("should create a sample secret object"):
|
||||
server.succeed("kubectl create secret generic nixossecret --from-literal thesecret=abacadabra")
|
||||
|
||||
with subtest("should check if secret is correct"):
|
||||
server.wait_until_succeeds("[[ $(kubectl get secrets nixossecret -o json | jq -r .data.thesecret | base64 -d) == abacadabra ]]")
|
||||
|
||||
with subtest("should have a secret in database"):
|
||||
etcd.wait_until_succeeds("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
|
||||
|
||||
with subtest("should delete the secret"):
|
||||
server.succeed("kubectl delete secret nixossecret")
|
||||
|
||||
with subtest("should not have a secret in database"):
|
||||
etcd.wait_until_fails("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
|
||||
'';
|
||||
|
||||
meta.maintainers =
|
||||
pkgs.etcd.meta.maintainers ++ lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# A test that sets extra kubelet configuration and enables graceful node shutdown
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nodeName = "test";
|
||||
shutdownGracePeriod = "1m13s";
|
||||
shutdownGracePeriodCriticalPods = "13s";
|
||||
podsPerCore = 3;
|
||||
memoryThrottlingFactor = 0.69;
|
||||
containerLogMaxSize = "5Mi";
|
||||
in
|
||||
{
|
||||
name = "${rancherPackage.name}-kubelet-config";
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
jq
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
package = rancherPackage;
|
||||
disable = disabledComponents;
|
||||
images = coreImages;
|
||||
inherit nodeName;
|
||||
gracefulNodeShutdown = {
|
||||
enable = true;
|
||||
inherit shutdownGracePeriod shutdownGracePeriodCriticalPods;
|
||||
};
|
||||
extraKubeletConfig = {
|
||||
inherit podsPerCore memoryThrottlingFactor containerLogMaxSize;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
import json
|
||||
|
||||
start_all()
|
||||
machine.wait_for_unit("${serviceName}")
|
||||
# wait until the node is ready
|
||||
machine.wait_until_succeeds(r"""kubectl get node ${nodeName} -ojson | jq -e '.status.conditions[] | select(.type == "Ready") | .status == "True"'""")
|
||||
# test whether the kubelet registered an inhibitor lock
|
||||
machine.succeed("systemd-inhibit --list --no-legend | grep \"^kubelet.*shutdown\"")
|
||||
# run kubectl proxy in the background, close stdout through redirection to not wait for the command to finish
|
||||
machine.execute("kubectl proxy --address 127.0.0.1 --port=8001 >&2 &")
|
||||
machine.wait_until_succeeds("nc -z 127.0.0.1 8001")
|
||||
# get the kubeletconfig
|
||||
kubelet_config=json.loads(machine.succeed("curl http://127.0.0.1:8001/api/v1/nodes/${nodeName}/proxy/configz | jq '.kubeletconfig'"))
|
||||
|
||||
with subtest("Kubelet config values are set correctly"):
|
||||
t.assertEqual(kubelet_config["shutdownGracePeriod"], "${shutdownGracePeriod}")
|
||||
t.assertEqual(kubelet_config["shutdownGracePeriodCriticalPods"], "${shutdownGracePeriodCriticalPods}")
|
||||
t.assertEqual(kubelet_config["podsPerCore"], ${toString podsPerCore})
|
||||
t.assertEqual(kubelet_config["memoryThrottlingFactor"], ${toString memoryThrottlingFactor})
|
||||
t.assertEqual(kubelet_config["containerLogMaxSize"],"${containerLogMaxSize}")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
# A test that runs a multi-node rancher cluster and verifies pod networking works across nodes
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
let
|
||||
imageEnv = pkgs.buildEnv {
|
||||
name = "${rancherDistro}-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
tini
|
||||
bashInteractive
|
||||
coreutils
|
||||
socat
|
||||
];
|
||||
};
|
||||
pauseImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/pause";
|
||||
tag = "local";
|
||||
copyToRoot = imageEnv;
|
||||
config.Entrypoint = [
|
||||
"/bin/tini"
|
||||
"--"
|
||||
"/bin/sleep"
|
||||
"inf"
|
||||
];
|
||||
};
|
||||
# A daemonset that responds 'server' on port 8000
|
||||
networkTestDaemonset = pkgs.writeText "test.yml" ''
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: test
|
||||
labels:
|
||||
name: test
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: test.local/pause:local
|
||||
imagePullPolicy: Never
|
||||
resources:
|
||||
limits:
|
||||
memory: 20Mi
|
||||
command: ["socat", "TCP4-LISTEN:8000,fork", "EXEC:echo server"]
|
||||
'';
|
||||
tokenFile = pkgs.writeText "token" "p@s$w0rd";
|
||||
|
||||
supervisorPort =
|
||||
{
|
||||
k3s = "6443";
|
||||
rke2 = "9345";
|
||||
}
|
||||
.${rancherDistro};
|
||||
in
|
||||
{
|
||||
name = "${rancherPackage.name}-multi-node";
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{
|
||||
nodes,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
gzip
|
||||
jq
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = lib.mkMerge [
|
||||
{
|
||||
inherit tokenFile;
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rancherPackage;
|
||||
images = coreImages ++ [ pauseImage ];
|
||||
nodeIP = config.networking.primaryIPAddress;
|
||||
disable = disabledComponents;
|
||||
extraFlags = [
|
||||
"--pause-image test.local/pause:local"
|
||||
];
|
||||
}
|
||||
{
|
||||
k3s = {
|
||||
clusterInit = true;
|
||||
extraFlags = [ "--flannel-iface eth1" ]; # see canalConfig definition
|
||||
};
|
||||
|
||||
# The interface selection logic of flannel & canal would normally use eth0, as
|
||||
# the nixos testing driver sets a default route via dev eth0. However, in test
|
||||
# setups we have to use eth1 for inter-node communication.
|
||||
# For K3s this can be handled via --flannel-iface, but RKE2's canal has to be
|
||||
# configured with this manifest.
|
||||
rke2.manifests.canal-config.content = {
|
||||
apiVersion = "helm.cattle.io/v1";
|
||||
kind = "HelmChartConfig";
|
||||
metadata = {
|
||||
name = "rke2-canal";
|
||||
namespace = "kube-system";
|
||||
};
|
||||
# spec.valuesContent needs to a string, either json or yaml
|
||||
spec.valuesContent = builtins.toJSON {
|
||||
flannel.iface = "eth1";
|
||||
};
|
||||
};
|
||||
}
|
||||
.${rancherDistro}
|
||||
];
|
||||
|
||||
networking.firewall.enable = false;
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
2379
|
||||
2380
|
||||
6443
|
||||
]
|
||||
++ lib.optionals (rancherDistro == "rke2") [
|
||||
9099
|
||||
9345
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
|
||||
server2 =
|
||||
{
|
||||
nodes,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
inherit tokenFile;
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rancherPackage;
|
||||
images = coreImages ++ [ pauseImage ];
|
||||
serverAddr = "https://${nodes.server.networking.primaryIPAddress}:${supervisorPort}";
|
||||
nodeIP = config.networking.primaryIPAddress;
|
||||
disable = disabledComponents;
|
||||
extraFlags = [
|
||||
"--pause-image test.local/pause:local"
|
||||
]
|
||||
++ lib.optional (rancherDistro == "k3s") "--flannel-iface eth1";
|
||||
};
|
||||
|
||||
networking.firewall.enable = false;
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
2379
|
||||
2380
|
||||
6443
|
||||
]
|
||||
++ lib.optionals (rancherDistro == "rke2") [
|
||||
9099
|
||||
9345
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
|
||||
agent =
|
||||
{
|
||||
nodes,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
inherit tokenFile;
|
||||
enable = true;
|
||||
role = "agent";
|
||||
package = rancherPackage;
|
||||
images = coreImages ++ [ pauseImage ];
|
||||
serverAddr = "https://${nodes.server2.networking.primaryIPAddress}:${supervisorPort}";
|
||||
nodeIP = config.networking.primaryIPAddress;
|
||||
extraFlags = [
|
||||
"--pause-image test.local/pause:local"
|
||||
]
|
||||
++ lib.optional (rancherDistro == "k3s") "--flannel-iface eth1";
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = lib.optional (rancherDistro == "rke2") 9099;
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
|
||||
servers = [server, server2]
|
||||
for m in servers:
|
||||
m.wait_for_unit("${serviceName}")
|
||||
|
||||
# wait for the agent to show up
|
||||
server.wait_until_succeeds("kubectl get node agent")
|
||||
|
||||
${lib.optionalString (rancherDistro == "k3s") ''
|
||||
for m in machines:
|
||||
m.succeed("k3s check-config")
|
||||
''}
|
||||
|
||||
server.succeed("kubectl cluster-info")
|
||||
# Also wait for our service account to show up; it takes a sec
|
||||
server.wait_until_succeeds("kubectl get serviceaccount default")
|
||||
|
||||
# Now create a pod on each node via a daemonset and verify they can talk to each other.
|
||||
server.succeed("kubectl apply -f ${networkTestDaemonset}")
|
||||
server.wait_until_succeeds(f'[ "$(kubectl get ds test -o json | jq .status.numberReady)" -eq {len(machines)} ]')
|
||||
|
||||
# Get pod IPs
|
||||
pods = server.succeed("kubectl get po -o json | jq '.items[].metadata.name' -r").splitlines()
|
||||
pod_ips = [server.succeed(f"kubectl get po {name} -o json | jq '.status.podIP' -cr").strip() for name in pods]
|
||||
|
||||
# Verify each server can ping each pod ip
|
||||
for pod_ip in pod_ips:
|
||||
server.succeed(f"ping -c 1 {pod_ip}")
|
||||
server2.succeed(f"ping -c 1 {pod_ip}")
|
||||
agent.succeed(f"ping -c 1 {pod_ip}")
|
||||
# Verify the pods can talk to each other
|
||||
for pod in pods:
|
||||
resp = server.succeed(f"kubectl exec {pod} -- socat TCP:{pod_ip}:8000 -")
|
||||
t.assertEqual(resp.strip(), "server")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
# A test that runs a single node rancher cluster and verifies a pod can run
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rancherDistro,
|
||||
rancherPackage,
|
||||
serviceName,
|
||||
disabledComponents,
|
||||
coreImages,
|
||||
vmResources,
|
||||
...
|
||||
}:
|
||||
let
|
||||
imageEnv = pkgs.buildEnv {
|
||||
name = "${rancherDistro}-pause-image-env";
|
||||
paths = with pkgs; [
|
||||
tini
|
||||
(lib.hiPrio coreutils)
|
||||
busybox
|
||||
];
|
||||
};
|
||||
pauseImage = pkgs.dockerTools.buildLayeredImage {
|
||||
name = "test.local/pause";
|
||||
tag = "local";
|
||||
contents = imageEnv;
|
||||
config.Entrypoint = [
|
||||
"/bin/tini"
|
||||
"--"
|
||||
"/bin/sleep"
|
||||
"inf"
|
||||
];
|
||||
};
|
||||
testPodYaml = pkgs.writeText "test.yaml" ''
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: test.local/pause:local
|
||||
imagePullPolicy: Never
|
||||
command: ["sh", "-c", "sleep inf"]
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "${rancherPackage.name}-single-node";
|
||||
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
kubectl
|
||||
gzip
|
||||
];
|
||||
environment.sessionVariables.KUBECONFIG = "/etc/rancher/${rancherDistro}/${rancherDistro}.yaml";
|
||||
|
||||
virtualisation = vmResources;
|
||||
|
||||
services.${rancherDistro} = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rancherPackage;
|
||||
disable = disabledComponents;
|
||||
images = coreImages ++ [ pauseImage ];
|
||||
extraFlags = [
|
||||
"--pause-image test.local/pause:local"
|
||||
];
|
||||
};
|
||||
|
||||
users.users = {
|
||||
noprivs = {
|
||||
isNormalUser = true;
|
||||
description = "Can't access ${rancherDistro} by default";
|
||||
password = "*";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("${serviceName}")
|
||||
machine.succeed("kubectl cluster-info")
|
||||
machine.fail("sudo -u noprivs kubectl cluster-info")
|
||||
${lib.optionalString (rancherDistro == "k3s") ''
|
||||
machine.succeed("k3s check-config")
|
||||
''}
|
||||
|
||||
# Also wait for our service account to show up; it takes a sec
|
||||
machine.wait_until_succeeds("kubectl get serviceaccount default")
|
||||
machine.succeed("kubectl apply -f ${testPodYaml}")
|
||||
machine.succeed("kubectl wait --for 'condition=Ready' pod/test --timeout=180s")
|
||||
machine.succeed("kubectl delete -f ${testPodYaml}")
|
||||
|
||||
# regression test for #176445
|
||||
machine.fail("journalctl -o cat -u ${serviceName}.service | grep 'ipset utility not found'")
|
||||
|
||||
with subtest("Run ${rancherDistro}-killall"):
|
||||
# Call the killall script with a clean path to assert that
|
||||
# all required commands are wrapped
|
||||
output = machine.succeed("PATH= ${rancherPackage}/bin/${rancherDistro}-killall.sh 2>&1 | tee /dev/stderr")
|
||||
t.assertNotIn("command not found", output, "killall script contains unknown command")
|
||||
|
||||
# Check that killall cleaned up properly
|
||||
machine.fail("systemctl is-active ${serviceName}.service")
|
||||
machine.wait_until_fails("systemctl list-units | grep containerd", timeout=5)
|
||||
machine.fail("ip link show | awk -F': ' '{print $2}' | grep -e flannel -e cni0")
|
||||
machine.fail("ip netns show | grep cni-")
|
||||
'';
|
||||
|
||||
meta.maintainers = lib.teams.k3s.members ++ pkgs.rke2.meta.maintainers;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
pkgs ? import ../../.. { inherit system; },
|
||||
lib ? pkgs.lib,
|
||||
}:
|
||||
let
|
||||
allRKE2 = lib.filterAttrs (n: _: lib.strings.hasPrefix "rke2" n) pkgs;
|
||||
in
|
||||
{
|
||||
# Run a single node rke2 cluster and verify a pod can run
|
||||
singleNode = lib.mapAttrs (_: rke2: import ./single-node.nix { inherit system pkgs rke2; }) allRKE2;
|
||||
# Run a multi-node rke2 cluster and verify pod networking works across nodes
|
||||
multiNode = lib.mapAttrs (_: rke2: import ./multi-node.nix { inherit system pkgs rke2; }) allRKE2;
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rke2,
|
||||
...
|
||||
}:
|
||||
let
|
||||
throwSystem = throw "RKE2: Unsupported system: ${pkgs.stdenv.hostPlatform.system}";
|
||||
coreImages =
|
||||
{
|
||||
aarch64-linux = rke2.images-core-linux-arm64-tar-zst;
|
||||
x86_64-linux = rke2.images-core-linux-amd64-tar-zst;
|
||||
}
|
||||
.${pkgs.stdenv.hostPlatform.system} or throwSystem;
|
||||
canalImages =
|
||||
{
|
||||
aarch64-linux = rke2.images-canal-linux-arm64-tar-zst;
|
||||
x86_64-linux = rke2.images-canal-linux-amd64-tar-zst;
|
||||
}
|
||||
.${pkgs.stdenv.hostPlatform.system} or throwSystem;
|
||||
helloImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/hello";
|
||||
tag = "local";
|
||||
compressor = "zstd";
|
||||
copyToRoot = pkgs.buildEnv {
|
||||
name = "rke2-hello-image-env";
|
||||
paths = with pkgs; [
|
||||
coreutils
|
||||
socat
|
||||
];
|
||||
};
|
||||
};
|
||||
tokenFile = pkgs.writeText "token" "p@s$w0rd";
|
||||
agentTokenFile = pkgs.writeText "agent-token" "agentP@s$w0rd";
|
||||
# Let flannel use eth1 to enable inter-node communication in tests
|
||||
canalConfig = {
|
||||
apiVersion = "helm.cattle.io/v1";
|
||||
kind = "HelmChartConfig";
|
||||
metadata = {
|
||||
name = "rke2-canal";
|
||||
namespace = "kube-system";
|
||||
};
|
||||
# spec.valuesContent needs to a string, either json or yaml
|
||||
spec.valuesContent = builtins.toJSON {
|
||||
flannel.iface = "eth1";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "${rke2.name}-multi-node";
|
||||
meta.maintainers = rke2.meta.maintainers;
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{
|
||||
config,
|
||||
nodes,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Canal CNI with VXLAN
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# Kubernetes API
|
||||
6443
|
||||
# Canal CNI health checks
|
||||
9099
|
||||
# RKE2 supervisor API
|
||||
9345
|
||||
];
|
||||
|
||||
# RKE2 needs more resources than the default
|
||||
virtualisation.cores = 4;
|
||||
virtualisation.memorySize = 4096;
|
||||
virtualisation.diskSize = 8092;
|
||||
|
||||
services.rke2 = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rke2;
|
||||
inherit tokenFile;
|
||||
inherit agentTokenFile;
|
||||
# Without nodeIP the apiserver starts with the wrong service IP family
|
||||
nodeIP = config.networking.primaryIPAddress;
|
||||
disable = [
|
||||
"rke2-coredns"
|
||||
"rke2-metrics-server"
|
||||
"rke2-ingress-nginx"
|
||||
"rke2-snapshot-controller"
|
||||
"rke2-snapshot-controller-crd"
|
||||
"rke2-snapshot-validation-webhook"
|
||||
];
|
||||
images = [
|
||||
coreImages
|
||||
canalImages
|
||||
helloImage
|
||||
];
|
||||
manifests = {
|
||||
canal-config.content = canalConfig;
|
||||
# A daemonset that responds 'hello' on port 8000
|
||||
network-test.content = {
|
||||
apiVersion = "apps/v1";
|
||||
kind = "DaemonSet";
|
||||
metadata = {
|
||||
name = "test";
|
||||
labels.name = "test";
|
||||
};
|
||||
spec = {
|
||||
selector.matchLabels.name = "test";
|
||||
template = {
|
||||
metadata.labels.name = "test";
|
||||
spec.containers = [
|
||||
{
|
||||
name = "hello";
|
||||
image = "${helloImage.imageName}:${helloImage.imageTag}";
|
||||
imagePullPolicy = "Never";
|
||||
command = [
|
||||
"socat"
|
||||
"TCP4-LISTEN:8000,fork"
|
||||
"EXEC:echo hello"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
agent =
|
||||
{
|
||||
config,
|
||||
nodes,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Canal CNI health checks
|
||||
networking.firewall.allowedTCPPorts = [ 9099 ];
|
||||
# Canal CNI with VXLAN
|
||||
networking.firewall.allowedUDPPorts = [ 8472 ];
|
||||
|
||||
# The agent node can work with less resources
|
||||
virtualisation.memorySize = 2048;
|
||||
virtualisation.diskSize = 8092;
|
||||
|
||||
services.rke2 = {
|
||||
enable = true;
|
||||
role = "agent";
|
||||
package = rke2;
|
||||
tokenFile = agentTokenFile;
|
||||
serverAddr = "https://${nodes.server.networking.primaryIPAddress}:9345";
|
||||
nodeIP = config.networking.primaryIPAddress;
|
||||
manifests.canal-config.content = canalConfig;
|
||||
images = [
|
||||
coreImages
|
||||
canalImages
|
||||
helloImage
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
kubectl = "${pkgs.kubectl}/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml";
|
||||
jq = "${pkgs.jq}/bin/jq";
|
||||
in
|
||||
# python
|
||||
''
|
||||
start_all()
|
||||
|
||||
server.wait_for_unit("rke2-server")
|
||||
agent.wait_for_unit("rke2-agent")
|
||||
|
||||
# Wait for the agent to be ready
|
||||
server.wait_until_succeeds(r"""${kubectl} wait --for='jsonpath={.status.conditions[?(@.type=="Ready")].status}=True' nodes/agent""")
|
||||
|
||||
server.succeed("${kubectl} cluster-info")
|
||||
server.wait_until_succeeds("${kubectl} get serviceaccount default")
|
||||
|
||||
# Now verify that each daemonset pod can talk to each other.
|
||||
server.wait_until_succeeds(
|
||||
f'[ "$(${kubectl} get ds test -o json | ${jq} .status.numberReady)" -eq {len(machines)} ]'
|
||||
)
|
||||
|
||||
# Get pod IPs
|
||||
pods = server.succeed("${kubectl} get po -o json | ${jq} '.items[].metadata.name' -r").splitlines()
|
||||
pod_ips = [
|
||||
server.succeed(f"${kubectl} get po {n} -o json | ${jq} '.status.podIP' -cr").strip() for n in pods
|
||||
]
|
||||
|
||||
# Verify each node can ping each pod ip
|
||||
for pod_ip in pod_ips:
|
||||
# The CNI sometimes needs a little time
|
||||
server.wait_until_succeeds(f"ping -c 1 {pod_ip}", timeout=5)
|
||||
agent.wait_until_succeeds(f"ping -c 1 {pod_ip}", timeout=5)
|
||||
# Verify the server can exec into the pod
|
||||
for pod in pods:
|
||||
resp = server.succeed(f"${kubectl} exec {pod} -- socat TCP:{pod_ip}:8000 -").strip()
|
||||
assert resp == "hello", f"Unexpected response from hello daemonset: {resp}"
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,144 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
rke2,
|
||||
...
|
||||
}:
|
||||
let
|
||||
throwSystem = throw "RKE2: Unsupported system: ${pkgs.stdenv.hostPlatform.system}";
|
||||
coreImages =
|
||||
{
|
||||
aarch64-linux = rke2.images-core-linux-arm64-tar-zst;
|
||||
x86_64-linux = rke2.images-core-linux-amd64-tar-zst;
|
||||
}
|
||||
.${pkgs.stdenv.hostPlatform.system} or throwSystem;
|
||||
canalImages =
|
||||
{
|
||||
aarch64-linux = rke2.images-canal-linux-arm64-tar-zst;
|
||||
x86_64-linux = rke2.images-canal-linux-amd64-tar-zst;
|
||||
}
|
||||
.${pkgs.stdenv.hostPlatform.system} or throwSystem;
|
||||
helloImage = pkgs.dockerTools.buildImage {
|
||||
name = "test.local/hello";
|
||||
tag = "local";
|
||||
compressor = "zstd";
|
||||
copyToRoot = pkgs.hello;
|
||||
config.Entrypoint = [ "${pkgs.hello}/bin/hello" ];
|
||||
};
|
||||
# A ConfigMap in regular yaml format
|
||||
cmFile = (pkgs.formats.yaml { }).generate "rke2-manifest-from-file.yaml" {
|
||||
apiVersion = "v1";
|
||||
kind = "ConfigMap";
|
||||
metadata.name = "from-file";
|
||||
data.username = "foo-file";
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "${rke2.name}-single-node";
|
||||
meta.maintainers = rke2.meta.maintainers;
|
||||
nodes.machine =
|
||||
{
|
||||
config,
|
||||
nodes,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# RKE2 needs more resources than the default
|
||||
virtualisation.cores = 4;
|
||||
virtualisation.memorySize = 4096;
|
||||
virtualisation.diskSize = 8092;
|
||||
|
||||
services.rke2 = {
|
||||
enable = true;
|
||||
role = "server";
|
||||
package = rke2;
|
||||
# Without nodeIP the apiserver starts with the wrong service IP family
|
||||
nodeIP = config.networking.primaryIPAddress;
|
||||
# Slightly reduce resource consumption
|
||||
disable = [
|
||||
"rke2-coredns"
|
||||
"rke2-metrics-server"
|
||||
"rke2-ingress-nginx"
|
||||
"rke2-snapshot-controller"
|
||||
"rke2-snapshot-controller-crd"
|
||||
"rke2-snapshot-validation-webhook"
|
||||
];
|
||||
images = [
|
||||
coreImages
|
||||
canalImages
|
||||
helloImage
|
||||
];
|
||||
manifests = {
|
||||
test-job.content = {
|
||||
apiVersion = "batch/v1";
|
||||
kind = "Job";
|
||||
metadata.name = "test";
|
||||
spec.template.spec = {
|
||||
containers = [
|
||||
{
|
||||
name = "hello";
|
||||
image = "${helloImage.imageName}:${helloImage.imageTag}";
|
||||
}
|
||||
];
|
||||
restartPolicy = "Never";
|
||||
};
|
||||
};
|
||||
disabled = {
|
||||
enable = false;
|
||||
content = {
|
||||
apiVersion = "v1";
|
||||
kind = "ConfigMap";
|
||||
metadata.name = "disabled";
|
||||
data.username = "foo";
|
||||
};
|
||||
};
|
||||
from-file.source = "${cmFile}";
|
||||
custom-target = {
|
||||
enable = true;
|
||||
target = "my-manifest.json";
|
||||
content = {
|
||||
apiVersion = "v1";
|
||||
kind = "ConfigMap";
|
||||
metadata.name = "custom-target";
|
||||
data.username = "foo-custom";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
kubectl = "${pkgs.kubectl}/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml";
|
||||
in
|
||||
# python
|
||||
''
|
||||
start_all()
|
||||
|
||||
with subtest("Start cluster"):
|
||||
machine.wait_for_unit("rke2-server")
|
||||
machine.succeed("${kubectl} cluster-info")
|
||||
machine.wait_until_succeeds("${kubectl} get serviceaccount default")
|
||||
|
||||
with subtest("Test job completes successfully"):
|
||||
machine.wait_until_succeeds("${kubectl} wait --for 'condition=complete' job/test")
|
||||
output = machine.succeed("${kubectl} logs -l batch.kubernetes.io/job-name=test").rstrip()
|
||||
assert output == "Hello, world!", f"unexpected output of test job: {output}"
|
||||
|
||||
with subtest("ConfigMap from-file exists"):
|
||||
output = machine.succeed("${kubectl} get cm from-file -o=jsonpath='{.data.username}'").rstrip()
|
||||
assert output == "foo-file", f"Unexpected data in Configmap from-file: {output}"
|
||||
|
||||
with subtest("ConfigMap custom-target exists"):
|
||||
# Check that the file exists at the custom target path
|
||||
machine.succeed("ls /var/lib/rancher/rke2/server/manifests/my-manifest.json")
|
||||
output = machine.succeed("${kubectl} get cm custom-target -o=jsonpath='{.data.username}'").rstrip()
|
||||
assert output == "foo-custom", f"Unexpected data in Configmap custom-target: {output}"
|
||||
|
||||
with subtest("Disabled ConfigMap doesn't exist"):
|
||||
machine.fail("${kubectl} get cm disabled")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"packageVersion": "145.0.1-2",
|
||||
"packageVersion": "146.0.1-1",
|
||||
"source": {
|
||||
"rev": "145.0.1-2",
|
||||
"hash": "sha256-yqOl0kPaRdthFHopGsPs4patzTmy0mzGaUg0sab5LG4="
|
||||
"rev": "146.0.1-1",
|
||||
"hash": "sha256-MYp0PEAbUSJwrvaXYaie7eXj3XRw/EyGrQvsFdVT/Y0="
|
||||
},
|
||||
"firefox": {
|
||||
"version": "145.0.1",
|
||||
"hash": "sha512-bgUv7kbDGyaWulQD+QXguUsIzjVFiM1jFdVO4dz/m4KDXWTqWldZbfsYZt0VGKKZZv2qvbTDg4EDNEvS3BjHLQ=="
|
||||
"version": "146.0.1",
|
||||
"hash": "sha512-rpW4bkg/6/jf7INHdI3ZBI7X1/hFJQ4HqoBI4rNR2mH288X4O7DQxy4adexhtg5Zu+aWOfDzNTKRD/i/XKBzlA=="
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,14 +469,11 @@ buildGoModule (finalAttrs: {
|
||||
;
|
||||
tests =
|
||||
let
|
||||
mkTests =
|
||||
version:
|
||||
let
|
||||
k3s_version = "k3s_" + lib.replaceStrings [ "." ] [ "_" ] (lib.versions.majorMinor version);
|
||||
in
|
||||
lib.mapAttrs (name: value: nixosTests.k3s.${name}.${k3s_version}) nixosTests.k3s;
|
||||
versionedPackage = "k3s_" + lib.replaceStrings [ "." ] [ "_" ] (lib.versions.majorMinor k3sVersion);
|
||||
in
|
||||
mkTests k3sVersion;
|
||||
lib.mapAttrs (name: _: nixosTests.k3s.${name}.${versionedPackage}) (
|
||||
lib.filterAttrs (n: _: n != "all") nixosTests.k3s
|
||||
);
|
||||
imagesList = throw "k3s.imagesList was removed";
|
||||
airgapImages = throw "k3s.airgapImages was renamed to k3s.airgap-images";
|
||||
airgapImagesAmd64 = throw "k3s.airgapImagesAmd64 was renamed to k3s.airgap-images-amd64-tar-zst";
|
||||
|
||||
@@ -7,7 +7,7 @@ A K3s maintainer, maintains K3s's:
|
||||
- [documentation](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/cluster/k3s/README.md)
|
||||
- [issues](https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+k3s)
|
||||
- [pull requests](https://github.com/NixOS/nixpkgs/pulls?q=is%3Aopen+is%3Apr+label%3A%226.topic%3A+k3s%22)
|
||||
- [NixOS tests](https://github.com/NixOS/nixpkgs/tree/master/nixos/tests/k3s)
|
||||
- [NixOS tests](https://github.com/NixOS/nixpkgs/tree/master/nixos/tests/rancher)
|
||||
- [NixOS service module](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/cluster/rancher)
|
||||
- [update script](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/cluster/k3s/update-script.sh) (the process of updating)
|
||||
- updates (the act of updating) and [r-ryantm bot logs](https://r.ryantm.com/log/k3s/)
|
||||
|
||||
@@ -22,6 +22,7 @@ lib:
|
||||
makeWrapper,
|
||||
fetchzip,
|
||||
fetchurl,
|
||||
versionCheckHook,
|
||||
|
||||
# Runtime dependencies
|
||||
procps,
|
||||
@@ -42,7 +43,6 @@ lib:
|
||||
|
||||
# Testing dependencies
|
||||
nixosTests,
|
||||
testers,
|
||||
}:
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "rke2";
|
||||
@@ -129,25 +129,19 @@ buildGoModule (finalAttrs: {
|
||||
go tool nm $out/bin/.rke2-wrapped | grep '_Cfunc__goboringcrypto_' > /dev/null
|
||||
runHook postInstallCheck
|
||||
'';
|
||||
nativeInstallCheckInputs = [ versionCheckHook ];
|
||||
versionCheckProgramArg = "--version";
|
||||
|
||||
passthru = {
|
||||
inherit updateScript;
|
||||
tests =
|
||||
let
|
||||
moduleTests =
|
||||
let
|
||||
package_version =
|
||||
"rke2_" + lib.replaceStrings [ "." ] [ "_" ] (lib.versions.majorMinor rke2Version);
|
||||
in
|
||||
lib.mapAttrs (name: value: nixosTests.rke2.${name}.${package_version}) nixosTests.rke2;
|
||||
versionedPackage =
|
||||
"rke2_" + lib.replaceStrings [ "." ] [ "_" ] (lib.versions.majorMinor rke2Version);
|
||||
in
|
||||
{
|
||||
version = testers.testVersion {
|
||||
package = finalAttrs.finalPackage;
|
||||
version = "v${finalAttrs.version}";
|
||||
};
|
||||
}
|
||||
// moduleTests;
|
||||
lib.mapAttrs (name: _: nixosTests.rke2.${name}.${versionedPackage}) (
|
||||
lib.filterAttrs (n: _: n != "all") nixosTests.rke2
|
||||
);
|
||||
}
|
||||
// (lib.mapAttrs (_: value: fetchurl value) imagesVersions);
|
||||
|
||||
|
||||
@@ -652,13 +652,13 @@
|
||||
"vendorHash": "sha256-jyfzk3vbgZwHlyiFFw1mhD+us/7WNatUQTGN4WsrfgE="
|
||||
},
|
||||
"hashicorp_tfe": {
|
||||
"hash": "sha256-W0O3J08p6QtQVCqE3AGZbR+19SQVXLbxLkkDhpZhJMM=",
|
||||
"hash": "sha256-9BrGuvIGs5ztEz2/qBkPqGHeAtPAiWA+3UeoEEOWneM=",
|
||||
"homepage": "https://registry.terraform.io/providers/hashicorp/tfe",
|
||||
"owner": "hashicorp",
|
||||
"repo": "terraform-provider-tfe",
|
||||
"rev": "v0.71.0",
|
||||
"rev": "v0.72.0",
|
||||
"spdx": "MPL-2.0",
|
||||
"vendorHash": "sha256-dZFjjogCIRzxXgJ/VW/WJY1mCNqoa3Es4q+oXLgcGQg="
|
||||
"vendorHash": "sha256-P49ShCqu3wU2baUjzq8h30s85eIGdrevgzjbOIN0jp8="
|
||||
},
|
||||
"hashicorp_time": {
|
||||
"hash": "sha256-ZArYfbzbrkxGlL1BRFM7PN3hLzdssIL4COsUBdLVMYY=",
|
||||
|
||||
@@ -86,8 +86,8 @@ rec {
|
||||
thunderbird = thunderbird-latest;
|
||||
|
||||
thunderbird-latest = common {
|
||||
version = "145.0";
|
||||
sha512 = "f33835e4d740b32d072ac915124d988ef9d4cbe55d7c972c817991d19b64e8bc95b75b503ad3cb9abf4fd1d220fc7cb61720ea84dc49482faa13da1690d7d80e";
|
||||
version = "146.0.1";
|
||||
sha512 = "8a3b2de246c7c597574fce596836c7ef7b24bd21573feb15c308003f34b82335ad865aa0f81b24d1669c8023c0448c0e273a63019aab13356b023c2e8adc2c47";
|
||||
|
||||
updateScript = callPackage ./update.nix {
|
||||
attrPath = "thunderbirdPackages.thunderbird-latest";
|
||||
|
||||
@@ -37,10 +37,10 @@ lib.extendMkDerivation {
|
||||
in
|
||||
|
||||
if args ? minimalOCamlVersion && lib.versionOlder ocaml.version args.minimalOCamlVersion then
|
||||
throw "${finalAttrs.pname}-${finalAttrs.version} is not available for OCaml ${ocaml.version}"
|
||||
throw "${pname}-${version} is not available for OCaml ${ocaml.version}"
|
||||
else
|
||||
{
|
||||
name = "ocaml${ocaml.version}-${finalAttrs.pname}-${finalAttrs.version}";
|
||||
name = "ocaml${ocaml.version}-${pname}-${version}";
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
@@ -58,14 +58,14 @@ lib.extendMkDerivation {
|
||||
buildPhase =
|
||||
args.buildPhase or ''
|
||||
runHook preBuild
|
||||
dune build -p ${finalAttrs.pname} ''${enableParallelBuilding:+-j $NIX_BUILD_CORES}
|
||||
dune build -p ${pname} ''${enableParallelBuilding:+-j $NIX_BUILD_CORES}
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase =
|
||||
args.installPhase or ''
|
||||
runHook preInstall
|
||||
dune install --prefix $out --libdir $OCAMLFIND_DESTDIR ${finalAttrs.pname} \
|
||||
dune install --prefix $out --libdir $OCAMLFIND_DESTDIR ${pname} \
|
||||
${
|
||||
if lib.versionAtLeast Dune.version "2.9" then
|
||||
"--docdir $out/share/doc --mandir $out/share/man"
|
||||
@@ -78,15 +78,11 @@ lib.extendMkDerivation {
|
||||
checkPhase =
|
||||
args.checkPhase or ''
|
||||
runHook preCheck
|
||||
dune runtest -p ${finalAttrs.pname} ''${enableParallelBuilding:+-j $NIX_BUILD_CORES}
|
||||
dune runtest -p ${pname} ''${enableParallelBuilding:+-j $NIX_BUILD_CORES}
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
meta = (args.meta or { }) // {
|
||||
# TODO: ocaml.meta.platforms is where the compiler can run
|
||||
# Package's meta.platforms are where the compiler can target.
|
||||
#
|
||||
# See: rustc.targetPlatforms
|
||||
platforms = args.meta.platforms or ocaml.meta.platforms;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
From 2e3ea5ab32ed356c45e0a7a8db37924a77a1c949 Mon Sep 17 00:00:00 2001
|
||||
From: Marcin Serwin <marcin@serwin.dev>
|
||||
Date: Sat, 20 Dec 2025 12:51:13 +0100
|
||||
Subject: [PATCH] Fix wcwidth declaration
|
||||
|
||||
The wcwidth function is declared in `wchar.h` on POSIX systems which
|
||||
is not included in the default Autoconf includes. Because of this
|
||||
HAVE_DECL_WCWIDTH would be configured to 0.
|
||||
|
||||
Since C23 functions with no arguments in prototypes are treated as
|
||||
taking no arguments. This results in mismatched declaration since in
|
||||
wchar.h the functions is declared as taking wchar_t.
|
||||
|
||||
Signed-off-by: Marcin Serwin <marcin@serwin.dev>
|
||||
---
|
||||
configure.ac | 2 +-
|
||||
mbswidth.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 7d756ee..a1ecbe2 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -61,7 +61,7 @@ AC_CHECK_HEADER(wchar.h,[
|
||||
AC_DEFINE(HAVE_WCHAR_H, 1, [Define if you have the <wchar.h> header file.])],
|
||||
[ac_have_wchar_h=no])
|
||||
AC_CHECK_FUNCS(mbtowc wcwidth mbrtowc mbsinit,,ac_widec_funcs=no)
|
||||
-AC_CHECK_DECLS(wcwidth)
|
||||
+AC_CHECK_DECLS(wcwidth, [], [], [#include <wchar.h>])
|
||||
AC_CHECK_TYPE(wchar_t,,ac_widec_funcs=no)
|
||||
|
||||
if test x$ac_widec_funcs = xyes -a x$ac_have_wchar_h = xyes; then
|
||||
diff --git a/mbswidth.c b/mbswidth.c
|
||||
index 031e6b7..54a2cb5 100644
|
||||
--- a/mbswidth.c
|
||||
+++ b/mbswidth.c
|
||||
@@ -63,7 +63,7 @@
|
||||
# warn "this configure-time declaration test was not run"
|
||||
#endif
|
||||
#if !HAVE_DECL_WCWIDTH
|
||||
-int wcwidth ();
|
||||
+int wcwidth (wchar_t);
|
||||
#endif
|
||||
|
||||
#ifndef wcwidth
|
||||
--
|
||||
2.51.2
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
lib,
|
||||
stdenv,
|
||||
fetchgit,
|
||||
fetchpatch,
|
||||
autoreconfHook,
|
||||
pkg-config,
|
||||
ncurses,
|
||||
@@ -20,10 +19,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
};
|
||||
|
||||
patches = [
|
||||
(fetchpatch {
|
||||
url = "https://aur.archlinux.org/cgit/aur.git/plain/abook-gcc15.patch?h=abook";
|
||||
hash = "sha256-+73+USELoby8JvuVOWZe6E+xtdhajnLnDkzD/77QoTo=";
|
||||
})
|
||||
./0001-Fix-wcwidth-declaration.patch
|
||||
];
|
||||
|
||||
# error: implicit declaration of function 'isalnum' [-Wimplicit-function-declaration]
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
}:
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "archipelago";
|
||||
version = "0.6.4";
|
||||
version = "0.6.5";
|
||||
src = fetchurl {
|
||||
url = "https://github.com/ArchipelagoMW/Archipelago/releases/download/${finalAttrs.version}/Archipelago_${finalAttrs.version}_linux-x86_64.AppImage";
|
||||
hash = "sha256-7yzRYLmrOuiubXOu/ljuBsWvphdJ+07v0LJD0Ae8BTQ=";
|
||||
hash = "sha256-06EFpnMMz+yqqHDuUDw9AMBd0a0Ay7oVkzD4mna7XeM=";
|
||||
};
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
lib,
|
||||
binutils,
|
||||
fetchFromGitHub,
|
||||
fetchpatch,
|
||||
cmake,
|
||||
ninja,
|
||||
pkg-config,
|
||||
@@ -121,6 +122,13 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
./patches/no-cereal.patch
|
||||
# Cmake 4 support
|
||||
./patches/cmake.patch
|
||||
# Fix build with gcc15
|
||||
# https://github.com/bambulab/BambuStudio/pull/8555
|
||||
(fetchpatch {
|
||||
name = "bambu-studio-include-stdint-header.patch";
|
||||
url = "https://github.com/bambulab/BambuStudio/commit/434752bf643933f22348d78335abe7f60550e736.patch";
|
||||
hash = "sha256-vWqTM6IHL/gBncLk6gZHw+dFe0sdVuPdUqYeVJUbTis=";
|
||||
})
|
||||
];
|
||||
|
||||
doCheck = true;
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
}:
|
||||
let
|
||||
pname = "bazecor";
|
||||
version = "1.7.0";
|
||||
version = "1.8.3";
|
||||
src = appimageTools.extract {
|
||||
inherit pname version;
|
||||
src = fetchurl {
|
||||
url = "https://github.com/Dygmalab/Bazecor/releases/download/v${version}/Bazecor-${version}-x64.AppImage";
|
||||
hash = "sha256-i+6EBgT8Fv3GN2qwnr+QH9mcDToeQvit52qRt30Y9sM=";
|
||||
hash = "sha256-OAwHeLLbW+FlKeyxS+MCOTirHCvqZptiYXbeA3l4YJc=";
|
||||
};
|
||||
|
||||
# Workaround for https://github.com/Dygmalab/Bazecor/issues/370
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"x86_64-linux": {
|
||||
"buck2": "sha256-gVOho7p25okvAV8OqXppdtwOOEzqH7VWcJBT4l5CT2U=",
|
||||
"rust-project": "sha256-HKctvCiXyGFzfHfB3Qj6qR2p46i5vaaZgPg2J827ou4="
|
||||
"buck2": "sha256-TOgL0pLnNEAhHkKvynnM91kW06K6jZPeJnpSibYg8EU=",
|
||||
"rust-project": "sha256-s5JY/m+yC3YNHiOxk6D43ZkWdtWLxlI4X72jSFFd3Hc="
|
||||
},
|
||||
"x86_64-darwin": {
|
||||
"buck2": "sha256-wHk/tJJbupMsrcmXXNVXurfLY2TOSssMnuTZ7LNjASY=",
|
||||
"rust-project": "sha256-ePawMIfltPRK3mJJxI1BvGs6b2vIcgWzW2XTJykUsdI="
|
||||
"buck2": "sha256-8SvAZ30ZFsamVAheKpa2vzGty1TZECUv+BHeXLlDneQ=",
|
||||
"rust-project": "sha256-0af+q1s7iEb6dWl4WuNxFbIskTfrHtU2uhatPyAhZNM="
|
||||
},
|
||||
"aarch64-linux": {
|
||||
"buck2": "sha256-Gn/Q2P0Fs93SbOawhzv8Z9DgbrIUlQ+9E3PyCNsV1pk=",
|
||||
"rust-project": "sha256-Pm5lEIu0hzI5BuA/LuTKjBP8S63jiz1oSB0g9tSETGU="
|
||||
"buck2": "sha256-Pka0HEEqRsQp2R435duy6gJy/RQXp5lK5Dg9+rfr9L8=",
|
||||
"rust-project": "sha256-u3b+XscQpNZOo8OTrLSazFZvm496U4nsWti/6TRf8ZA="
|
||||
},
|
||||
"aarch64-darwin": {
|
||||
"buck2": "sha256-XtGs7g64s76AYhpFDbqSuSlblRauxJM0PaAk1MNNgxA=",
|
||||
"rust-project": "sha256-CkyLLv41iJTKHVB0e355ZO2MV7NzQeiF1gtWEGF5oAY="
|
||||
"buck2": "sha256-1Fv0LzAZUN/BbcorCBaPBbm8JAzLarhJysLqPT78XEQ=",
|
||||
"rust-project": "sha256-PQ7WKjzAPT0uRirWzwJPxKr9V1RQajnlXUMnv8SYdso="
|
||||
},
|
||||
"version": "2025-08-15",
|
||||
"preludeGit": "892cb85f5fc3258c7e4f89a836821ec4b8c7ee44",
|
||||
"preludeFod": "sha256-cyuOMi8x8q9gd6p1obnYYDVPxyONZ+y41AFXvSbUjC0="
|
||||
"version": "2025-12-01",
|
||||
"preludeGit": "0a994e0b600f7d035e1ac69f374c0e37e1e19af6",
|
||||
"preludeFod": "sha256-IQa4VatN5OaDSyoTbAj1tHNBpJV6Ost9RbLxDD23xVQ="
|
||||
}
|
||||
|
||||
@@ -33,9 +33,7 @@
|
||||
#
|
||||
# from the root of the nixpkgs git repository, run:
|
||||
#
|
||||
# nix-shell maintainers/scripts/update.nix \
|
||||
# --argstr commit true \
|
||||
# --argstr package buck2
|
||||
# nix-shell maintainers/scripts/update.nix --argstr commit true --argstr package buck2
|
||||
|
||||
let
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "check-jsonschema";
|
||||
version = "0.35.0";
|
||||
version = "0.36.0";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "python-jsonschema";
|
||||
repo = "check-jsonschema";
|
||||
tag = version;
|
||||
hash = "sha256-IiNUgv0XZtTzCJjp/4jyTpw9MAyBFtuf3N4VFqatZVg=";
|
||||
hash = "sha256-volbCQ0qxd614CDu0GIFKPXF1qSvgf5tTnJ8skcnnTg=";
|
||||
};
|
||||
|
||||
build-system = with python3Packages; [ setuptools ];
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
}:
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "cocoon";
|
||||
version = "0.7.0";
|
||||
version = "0.7.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "haileyok";
|
||||
repo = "cocoon";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-/EaTQC5mkil6SeDCRUcwb8Hv68SeCrlgWDphoFrx3Aw=";
|
||||
hash = "sha256-kYBYdMoo7ToeljiW7AafL5cHzzeuaiL6MFE4Zw5Taqw=";
|
||||
};
|
||||
|
||||
ldflags = [
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
let
|
||||
pname = "decent-sampler";
|
||||
version = "1.13.12";
|
||||
version = "1.15.0";
|
||||
rlkey = "orvjprslmwn0dkfs0ncx6nxnm";
|
||||
|
||||
icon = fetchurl {
|
||||
@@ -28,8 +28,8 @@ let
|
||||
|
||||
src = fetchzip {
|
||||
# dropbox links: https://www.dropbox.com/sh/dwyry6xpy5uut07/AABBJ84bjTTSQWzXGG5TOQpfa\
|
||||
url = "https://www.dropbox.com/scl/fo/a0i0udw7ggfwnjoi05hh3/AHLHYaQpGY3OwhYqQEd06Po/Decent_Sampler-${version}-Linux-Static-x86_64.tar.gz?rlkey=${rlkey}&dl=0";
|
||||
hash = "sha256-sLaQd1AATr1mY3qhylQMkOfIIygKNwvf7K4mVqkbe8U=";
|
||||
url = "https://www.dropbox.com/scl/fo/a0i0udw7ggfwnjoi05hh3/ABn4zZmR24tyJx0xaRS_lXg/Decent_Sampler-${version}-Linux-Static-x86_64.tar.gz?rlkey=${rlkey}&dl=0";
|
||||
hash = "sha256-A+CBsGUtqXo7KAlx6BjbHGRZww73TlJCI68thicGKiE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ copyDesktopItems ];
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
From 7bc49f8edd9a49d675ee5b163ab61b405e2d0258 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Tojnar <jtojnar@gmail.com>
|
||||
Date: Thu, 7 Oct 2021 21:42:26 +0200
|
||||
Subject: [PATCH] Fix build with Vala 0.54
|
||||
|
||||
Vala codegen now emits constructor methods so we need to skip @new
|
||||
so that we can use a custom one from our VAPI overrides.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/vala/-/commit/472765b90cd98c1a628975d20005c46352d665f8
|
||||
---
|
||||
vapi/Dee-1.0.metadata | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/vapi/Dee-1.0.metadata b/vapi/Dee-1.0.metadata
|
||||
index 7e80de0..793ffd8 100644
|
||||
--- a/vapi/Dee-1.0.metadata
|
||||
+++ b/vapi/Dee-1.0.metadata
|
||||
@@ -1,6 +1,8 @@
|
||||
GListResultSet skip
|
||||
GListResultSetClass skip
|
||||
|
||||
+Filter
|
||||
+ .new skip
|
||||
FilterModel
|
||||
.filter unowned
|
||||
Model
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
gtk-doc,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
stdenv.mkDerivation {
|
||||
pname = "dee";
|
||||
version = "unstable-2017-06-16";
|
||||
|
||||
@@ -26,16 +26,11 @@ stdenv.mkDerivation rec {
|
||||
|
||||
src = fetchgit {
|
||||
url = "https://git.launchpad.net/ubuntu/+source/dee";
|
||||
rev = "import/1.2.7+17.10.20170616-4ubuntu3";
|
||||
sha256 = "09blrdj7229vscp4mkg0fabmcvc6jdpamvblrq86rbky7j2nnwlk";
|
||||
rev = "applied/1.2.7+17.10.20170616-8build1";
|
||||
hash = "sha256-ttfppqb0t8cOhWaB97uyD9heVZKlBKYF2zD6yRwPyos=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
"${src}/debian/patches/gtkdocize.patch"
|
||||
"${src}/debian/patches/strict-prototype.patch"
|
||||
"${src}/debian/patches/vapi-skip-properties.patch"
|
||||
./0001-Fix-build-with-Vala-0.54.patch
|
||||
|
||||
# Fixes glib 2.62 deprecations
|
||||
(fetchpatch {
|
||||
name = "dee-1.2.7-deprecated-g_type_class_add_private.patch";
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
pixman,
|
||||
fetchFromGitHub,
|
||||
buildNpmPackage,
|
||||
prisma,
|
||||
prisma-engines,
|
||||
prisma_6,
|
||||
prisma-engines_6,
|
||||
vips,
|
||||
pkg-config,
|
||||
cairo,
|
||||
@@ -34,9 +34,9 @@ buildNpmPackage {
|
||||
|
||||
env.PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "1";
|
||||
|
||||
env.PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines}/lib/libquery_engine.node";
|
||||
env.PRISMA_QUERY_ENGINE_BINARY = "${prisma-engines}/bin/query-engine";
|
||||
env.PRISMA_SCHEMA_ENGINE_BINARY = "${prisma-engines}/bin/schema-engine";
|
||||
env.PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines_6}/lib/libquery_engine.node";
|
||||
env.PRISMA_QUERY_ENGINE_BINARY = "${prisma-engines_6}/bin/query-engine";
|
||||
env.PRISMA_SCHEMA_ENGINE_BINARY = "${prisma-engines_6}/bin/schema-engine";
|
||||
env.TURBO_NO_UPDATE_NOTIFIER = "true";
|
||||
env.TURBO_FORCE = "true";
|
||||
env.TURBO_REMOTE_CACHE_ENABLED = "false";
|
||||
@@ -81,11 +81,11 @@ buildNpmPackage {
|
||||
cat > $out/bin/${pname} <<EOF
|
||||
#!${bash}/bin/bash
|
||||
export PKG_CONFIG_PATH=${openssl.dev}/lib/pkgconfig;
|
||||
export PRISMA_QUERY_ENGINE_LIBRARY=${prisma-engines}/lib/libquery_engine.node
|
||||
export PRISMA_QUERY_ENGINE_BINARY=${prisma-engines}/bin/query-engine
|
||||
export PRISMA_SCHEMA_ENGINE_BINARY=${prisma-engines}
|
||||
export PRISMA_QUERY_ENGINE_LIBRARY=${prisma-engines_6}/lib/libquery_engine.node
|
||||
export PRISMA_QUERY_ENGINE_BINARY=${prisma-engines_6}/bin/query-engine
|
||||
export PRISMA_SCHEMA_ENGINE_BINARY=${prisma-engines_6}
|
||||
cd $out/apps/remix
|
||||
${prisma}/bin/prisma migrate deploy --schema ../../packages/prisma/schema.prisma
|
||||
${prisma_6}/bin/prisma migrate deploy --schema ../../packages/prisma/schema.prisma
|
||||
${nodejs}/bin/node build/server/main.js
|
||||
EOF
|
||||
chmod +x $out/bin/${pname}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
fetchpatch2,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
@@ -13,6 +14,13 @@ stdenv.mkDerivation rec {
|
||||
sha256 = "1wwj2hlngi8qn2pisvhyfxxs8gyqjlgrrv5lz91w8ly54dlzvs9j";
|
||||
};
|
||||
|
||||
patches = [
|
||||
(fetchpatch2 {
|
||||
url = "https://github.com/crigler/dtach/commit/6d80909a8c0fd19717010a3c76fec560f988ca48.patch?full_index=1";
|
||||
hash = "sha256-v3vToJdSwihiPCSjXjEJghiaynHPTEql3F7URXRjCbM=";
|
||||
})
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp dtach $out/bin/dtach
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "fennel-ls";
|
||||
version = "0.2.2";
|
||||
version = "0.2.3";
|
||||
|
||||
src = fetchFromSourcehut {
|
||||
owner = "~xerool";
|
||||
repo = "fennel-ls";
|
||||
rev = finalAttrs.version;
|
||||
hash = "sha256-N1530u8Kq7ljdEdTFk0CJJyMLMVX5huQWXjyoMBJN5E=";
|
||||
hash = "sha256-BU0SkdBjq8kicvACIo3N2gf1UvTmzA3FKSt39Lxp3rs=";
|
||||
};
|
||||
buildInputs = [
|
||||
lua
|
||||
|
||||
@@ -38,13 +38,13 @@ assert withRest -> withJson;
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "freeradius";
|
||||
version = "3.2.7";
|
||||
version = "3.2.8";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "FreeRADIUS";
|
||||
repo = "freeradius-server";
|
||||
tag = "release_${lib.replaceStrings [ "." ] [ "_" ] version}";
|
||||
hash = "sha256-FG0/quBB5Q/bdYQqkFaZc/BhcIC/n2uVstlIGe4EPvE=";
|
||||
hash = "sha256-NvcXTT0jp3WR/w+JWcNESg6iNYqIV8QAlM8MxpYkpjs=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ autoreconfHook ];
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "gambit-project";
|
||||
version = "16.4.0";
|
||||
version = "16.4.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "gambitproject";
|
||||
repo = "gambit";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-fiWGRL7U4A7FKmAvzYt6WjlkOe0jSq3U2VfxPFvc+FA=";
|
||||
hash = "sha256-jRjL/rQ3k0zdTFCx1S/jdYpijcBx1aV8zsC8mz8aZ3A=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ autoreconfHook ] ++ lib.optional withGui wxGTK31;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
nodejs,
|
||||
faketty,
|
||||
openssl,
|
||||
prisma,
|
||||
prisma-engines,
|
||||
prisma_6,
|
||||
prisma-engines_6,
|
||||
}:
|
||||
|
||||
buildNpmPackage rec {
|
||||
@@ -30,7 +30,7 @@ buildNpmPackage rec {
|
||||
npmDepsHash = "sha256-KSKqybqVw2BG/WKuVRyNsneLYyedVeyCvNBLIREx7MQ=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
prisma
|
||||
prisma_6
|
||||
faketty
|
||||
];
|
||||
|
||||
@@ -67,11 +67,11 @@ buildNpmPackage rec {
|
||||
--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ openssl ]} \
|
||||
${lib.concatStringsSep " " (
|
||||
lib.mapAttrsToList (name: value: "--set ${name} ${lib.escapeShellArg value}") {
|
||||
PRISMA_SCHEMA_ENGINE_BINARY = lib.getExe' prisma-engines "schema-engine";
|
||||
PRISMA_QUERY_ENGINE_BINARY = lib.getExe' prisma-engines "query-engine";
|
||||
PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines}/lib/libquery_engine.node";
|
||||
PRISMA_INTROSPECTION_ENGINE_BINARY = lib.getExe' prisma-engines "introspection-engine";
|
||||
PRISMA_FMT_BINARY = lib.getExe' prisma-engines "prisma-fmt";
|
||||
PRISMA_SCHEMA_ENGINE_BINARY = lib.getExe' prisma-engines_6 "schema-engine";
|
||||
PRISMA_QUERY_ENGINE_BINARY = lib.getExe' prisma-engines_6 "query-engine";
|
||||
PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines_6}/lib/libquery_engine.node";
|
||||
PRISMA_INTROSPECTION_ENGINE_BINARY = lib.getExe' prisma-engines_6 "introspection-engine";
|
||||
PRISMA_FMT_BINARY = lib.getExe' prisma-engines_6 "prisma-fmt";
|
||||
}
|
||||
)}
|
||||
|
||||
|
||||
@@ -9,21 +9,18 @@
|
||||
nix-update-script,
|
||||
}:
|
||||
|
||||
let
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "git-igitt";
|
||||
version = "0.1.18";
|
||||
in
|
||||
rustPlatform.buildRustPackage {
|
||||
inherit pname version;
|
||||
version = "0.1.19";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "mlange-42";
|
||||
repo = "git-igitt";
|
||||
rev = version;
|
||||
hash = "sha256-JXEWnekL9Mtw0S3rI5aeO1HB9kJ7bRJDJ6EJ4ATlFeQ=";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-kryC07G/sMMtz1v6EZPYdCunl/CjC4H+jAV3Y91X9Cg=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-ndxxkYMFHAX6uourCyUpvJYcZCXQ5X2CMX4jTJmNRiQ=";
|
||||
cargoHash = "sha256-45ME5Uaqa6qKuqvO1ETEVrySiAylPmx30uShQPPGNmY=";
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
|
||||
@@ -47,4 +44,4 @@ rustPlatform.buildRustPackage {
|
||||
maintainers = [ lib.maintainers.pinage404 ];
|
||||
mainProgram = "git-igitt";
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "hatchet";
|
||||
version = "0.7.0";
|
||||
version = "0.7.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "simagix";
|
||||
repo = "hatchet";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-cpS46HR6hbjDEBeSYsnnumMzkXUYsEU5CAShoIfu8vo=";
|
||||
hash = "sha256-L7n5qR6Ijs5wC4ITq6at8EznkiKEceUJgYJyeSoWFWY=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-5YzrxSB/3tKxE1ObAnx1lbIc+Zlufc6wIJuDQqCcRKc=";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ./generic.nix {
|
||||
hash = "sha256-TdJe/vnjSc5ZT5tgZQsQacCVfW5+TKd5cjQLOp8SuZg=";
|
||||
version = "6.19.1";
|
||||
vendorHash = "sha256-Dx/AsSvDL/cHS/nRV5invkxgBg4w8jvtZ20LK7tOW14=";
|
||||
hash = "sha256-nhf7defhiFBHsqfZ6y+NN3TuteII6t8zCvpTsPsO+EE=";
|
||||
version = "6.20.0";
|
||||
vendorHash = "sha256-jIOV6vIkptHEuZcD/aS386o2M2AQHTjHngBxFi2tESA=";
|
||||
patches = [ ];
|
||||
nixUpdateExtraArgs = [
|
||||
"--override-filename=pkgs/by-name/in/incus/package.nix"
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "lazydocker";
|
||||
version = "0.24.2";
|
||||
version = "0.24.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jesseduffield";
|
||||
repo = "lazydocker";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-Dw7FBJ78b835iVkV8OrA06CAZ/GRCEXlLg/RfHZXfF0=";
|
||||
sha256 = "sha256-JbiG3cy+nn9BWJxX43YW+FKmWvsJPtRZ9NdMHtulzcw=";
|
||||
};
|
||||
|
||||
vendorHash = null;
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "libucontext";
|
||||
version = "1.3.3";
|
||||
version = "1.5";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "kaniini";
|
||||
repo = "libucontext";
|
||||
rev = "libucontext-${version}";
|
||||
hash = "sha256-MQCRRyA64MEtPoUtf1tFVbhiMDc4DlepSjMEFcb/Kh4=";
|
||||
hash = "sha256-asT0pV3s4L4zB2qtDJ+2XYxEP6agIEo1LtCuFeOjpRA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
openssl,
|
||||
google-fonts,
|
||||
playwright-driver,
|
||||
prisma,
|
||||
prisma-engines,
|
||||
prisma_6,
|
||||
prisma-engines_6,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -81,7 +81,7 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
nativeBuildInputs = [
|
||||
makeBinaryWrapper
|
||||
nodejs
|
||||
prisma
|
||||
prisma_6
|
||||
yarnConfigHook
|
||||
];
|
||||
|
||||
@@ -101,9 +101,9 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
|
||||
preBuild = ''
|
||||
export PRISMA_CLIENT_ENGINE_TYPE='binary'
|
||||
export PRISMA_QUERY_ENGINE_LIBRARY="${prisma-engines}/lib/libquery_engine.node"
|
||||
export PRISMA_QUERY_ENGINE_BINARY="${prisma-engines}/bin/query-engine"
|
||||
export PRISMA_SCHEMA_ENGINE_BINARY="${prisma-engines}/bin/schema-engine"
|
||||
export PRISMA_QUERY_ENGINE_LIBRARY="${prisma-engines_6}/lib/libquery_engine.node"
|
||||
export PRISMA_QUERY_ENGINE_BINARY="${prisma-engines_6}/bin/query-engine"
|
||||
export PRISMA_SCHEMA_ENGINE_BINARY="${prisma-engines_6}/bin/schema-engine"
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
@@ -151,7 +151,7 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
${lib.getExe' nodejs "npm"} start --prefix $out/share/linkwarden/apps/worker
|
||||
else
|
||||
echo "Starting server"
|
||||
${lib.getExe prisma} migrate deploy --schema $out/share/linkwarden/packages/prisma/schema.prisma \
|
||||
${lib.getExe prisma_6} migrate deploy --schema $out/share/linkwarden/packages/prisma/schema.prisma \
|
||||
&& ${lib.getExe' nodejs "npm"} start --prefix $out/share/linkwarden/apps/web -- -H \$LINKWARDEN_HOST -p \$LINKWARDEN_PORT
|
||||
fi
|
||||
" > $out/bin/start.sh
|
||||
@@ -166,9 +166,9 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
]
|
||||
}" \
|
||||
--set-default PRISMA_CLIENT_ENGINE_TYPE 'binary' \
|
||||
--set-default PRISMA_QUERY_ENGINE_LIBRARY "${prisma-engines}/lib/libquery_engine.node" \
|
||||
--set-default PRISMA_QUERY_ENGINE_BINARY "${prisma-engines}/bin/query-engine" \
|
||||
--set-default PRISMA_SCHEMA_ENGINE_BINARY "${prisma-engines}/bin/schema-engine" \
|
||||
--set-default PRISMA_QUERY_ENGINE_LIBRARY "${prisma-engines_6}/lib/libquery_engine.node" \
|
||||
--set-default PRISMA_QUERY_ENGINE_BINARY "${prisma-engines_6}/bin/query-engine" \
|
||||
--set-default PRISMA_SCHEMA_ENGINE_BINARY "${prisma-engines_6}/bin/schema-engine" \
|
||||
--set-default PLAYWRIGHT_LAUNCH_OPTIONS_EXECUTABLE_PATH ${playwright-driver.browsers-chromium}/chromium-*/chrome-linux/chrome \
|
||||
--set-default LINKWARDEN_CACHE_DIR /var/cache/linkwarden \
|
||||
--set-default LINKWARDEN_HOST localhost \
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "mcuboot-imgtool";
|
||||
version = "2.2.0";
|
||||
version = "2.3.0";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
inherit version;
|
||||
pname = "imgtool";
|
||||
hash = "sha256-XIc6EYleNtDrmeg2akOjriJwzE9Bnja2k0KJGCVRZM8=";
|
||||
hash = "sha256-//cuTnk6wOwCpJPBlUhxXMwKI1ivruqhC0nMwuC9EpU=";
|
||||
};
|
||||
|
||||
passthru.updateScript = nix-update-script { };
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "neowall";
|
||||
version = "0.4.4";
|
||||
version = "0.4.5";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "1ay1";
|
||||
repo = "neowall";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-wm9dmWoB+AeygfhPKWYh2Dn1QrXKMJpTcgKPLl0VMTQ=";
|
||||
hash = "sha256-dgego9hcYCqnky7hvCubOZWHA1HxKDY9E9F/7YIwj+I=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "nixbit";
|
||||
version = "0.5.4";
|
||||
version = "0.6.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "pbek";
|
||||
repo = "nixbit";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-3zDRR8zaO0VViMI8gtAVJvpeNp1C/VNHUNMdqqxFlPY=";
|
||||
hash = "sha256-Vbv6+d0jUNxI7TP06vIey3a7fCzX/jgnNJZ18ntBN2k=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
+219
-127
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "4.1.1",
|
||||
"version": "4.1.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "node-red",
|
||||
"version": "4.1.1",
|
||||
"version": "4.1.2",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
@@ -25,7 +25,7 @@
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.1.0",
|
||||
"express": "4.21.2",
|
||||
"express": "4.22.1",
|
||||
"express-session": "1.18.2",
|
||||
"form-data": "4.0.4",
|
||||
"fs-extra": "11.3.0",
|
||||
@@ -36,7 +36,7 @@
|
||||
"i18next": "24.2.3",
|
||||
"iconv-lite": "0.6.3",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "4.1.0",
|
||||
"js-yaml": "4.1.1",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "2.0.6",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
@@ -150,14 +150,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.28.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
|
||||
"integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
|
||||
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.3",
|
||||
"@babel/types": "^7.28.2",
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
"@jridgewell/gen-mapping": "^0.3.12",
|
||||
"@jridgewell/trace-mapping": "^0.3.28",
|
||||
"jsesc": "^3.0.2"
|
||||
@@ -187,9 +187,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
||||
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -197,13 +197,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
|
||||
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
|
||||
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.4"
|
||||
"@babel/types": "^7.28.5"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -237,18 +237,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz",
|
||||
"integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==",
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
|
||||
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.3",
|
||||
"@babel/generator": "^7.28.5",
|
||||
"@babel/helper-globals": "^7.28.0",
|
||||
"@babel/parser": "^7.28.4",
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/template": "^7.27.2",
|
||||
"@babel/types": "^7.28.4",
|
||||
"@babel/types": "^7.28.5",
|
||||
"debug": "^4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -281,14 +281,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
|
||||
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
|
||||
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.27.1"
|
||||
"@babel/helper-validator-identifier": "^7.28.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -346,9 +346,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
|
||||
"integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
|
||||
"integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -357,9 +357,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
|
||||
"integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
|
||||
"integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -817,9 +817,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@paralleldrive/cuid2": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
|
||||
"integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
|
||||
"integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1242,18 +1242,18 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.8.1.tgz",
|
||||
"integrity": "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==",
|
||||
"version": "24.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
|
||||
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.14.0"
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/readable-stream": {
|
||||
"version": "4.0.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.21.tgz",
|
||||
"integrity": "sha512-19eKVv9tugr03IgfXlA9UVUVRbW6IuqRO5B92Dl4a6pT7K8uaGrNS0GkxiZD0BOk6PLuXl5FhWl//eX/pzYdTQ==",
|
||||
"version": "4.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.22.tgz",
|
||||
"integrity": "sha512-/FFhJpfCLAPwAcN3mFycNUa77ddnr8jTgF5VmSNetaemWB2cIlfCA9t0YTM3JAT0wOcv8D4tjPo7pkDhK3EJIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
@@ -1831,9 +1831,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-6.1.4.tgz",
|
||||
"integrity": "sha512-ZV/9asSuknOExbM/zPPA8z00lc1ihPKWaStHkkQrxHNeYx+yY+TmF+v80dpv2G0mv3HVXBu7ryoAsxbFFhf4eg==",
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-6.1.6.tgz",
|
||||
"integrity": "sha512-jLsPgN/YSvPUg9UX0Kd73CXpm2Psg9FxMeCSXnk3WBO3CMT10JMwijubhGfHCnFu6TPn1ei3b975dxv7K2pWVg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/readable-stream": "^4.0.0",
|
||||
@@ -1938,6 +1938,7 @@
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz",
|
||||
"integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==",
|
||||
"deprecated": "No longer maintained. Please upgrade to a stable version.",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3431,9 +3432,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.18",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -3977,39 +3978,39 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.21.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||
"version": "4.22.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
|
||||
"integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.3",
|
||||
"content-disposition": "0.5.4",
|
||||
"body-parser": "~1.20.3",
|
||||
"content-disposition": "~0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.7.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"cookie": "~0.7.1",
|
||||
"cookie-signature": "~1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.3.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"finalhandler": "~1.3.1",
|
||||
"fresh": "~0.5.2",
|
||||
"http-errors": "~2.0.0",
|
||||
"merge-descriptors": "1.0.3",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"on-finished": "~2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.12",
|
||||
"path-to-regexp": "~0.1.12",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.13.0",
|
||||
"qs": "~6.14.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.2.1",
|
||||
"send": "0.19.0",
|
||||
"serve-static": "1.16.2",
|
||||
"send": "~0.19.0",
|
||||
"serve-static": "~1.16.2",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"statuses": "~2.0.1",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
@@ -4067,13 +4068,19 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/express/node_modules/cookie": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
|
||||
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
|
||||
"license": "MIT",
|
||||
"node_modules/express/node_modules/qs": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
||||
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/safe-buffer": {
|
||||
@@ -4097,9 +4104,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/exsolve": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
|
||||
"integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz",
|
||||
"integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -4263,17 +4270,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
|
||||
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
|
||||
"integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "2.4.1",
|
||||
"on-finished": "~2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "2.0.1",
|
||||
"statuses": "~2.0.2",
|
||||
"unpipe": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -5313,9 +5320,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/grunt/node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5604,6 +5611,15 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.10",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
|
||||
@@ -5827,9 +5843,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
|
||||
"integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
||||
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
@@ -6229,9 +6245,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -7323,9 +7339,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid/node_modules/marked": {
|
||||
"version": "16.4.1",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.1.tgz",
|
||||
"integrity": "sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==",
|
||||
"version": "16.4.2",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
|
||||
"integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -7645,6 +7661,19 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/minimatch": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
|
||||
@@ -8489,9 +8518,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nyc/node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8896,9 +8925,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/package-manager-detector": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.5.0.tgz",
|
||||
"integrity": "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz",
|
||||
"integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -9840,13 +9869,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.10",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
|
||||
"version": "1.22.11",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
|
||||
"integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.16.0",
|
||||
"is-core-module": "^2.16.1",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
@@ -10024,10 +10053,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"license": "ISC"
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
|
||||
"integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
@@ -10042,15 +10071,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
|
||||
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz",
|
||||
"integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
@@ -10065,15 +10094,6 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
@@ -10092,6 +10112,15 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/send/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
|
||||
@@ -10117,6 +10146,66 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static/node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/serve-static/node_modules/send": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
|
||||
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "2.4.1",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static/node_modules/send/node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
@@ -10611,9 +10700,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
|
||||
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
@@ -11136,11 +11225,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinyexec": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
|
||||
"integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
|
||||
"integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts": {
|
||||
"version": "6.1.86",
|
||||
@@ -11355,9 +11447,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
|
||||
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
|
||||
buildNpmPackage rec {
|
||||
pname = "node-red";
|
||||
version = "4.1.1";
|
||||
version = "4.1.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "node-red";
|
||||
repo = "node-red";
|
||||
tag = version;
|
||||
hash = "sha256-guyWY5Bk9mP5WBjPAKGq/Hp4BYF1rDYDG0m1rOLnpio=";
|
||||
hash = "sha256-Xr00S9Q8EPPGcd3kNHjmqYuzdzN6+W8xVuJsUVr4yII=";
|
||||
};
|
||||
|
||||
npmDepsHash = "sha256-GMbUAdAHrDJZIrUzXtDxW8kP0KZK2GTxsHWxoZTaqAQ=";
|
||||
npmDepsHash = "sha256-8nwIEu/p5kVYoG3+jXBss352MciCnk/aGV9nbDGHDdA=";
|
||||
|
||||
postPatch =
|
||||
let
|
||||
|
||||
+4
-9
@@ -3,7 +3,6 @@
|
||||
lib,
|
||||
openssl,
|
||||
pkg-config,
|
||||
protobuf,
|
||||
rustPlatform,
|
||||
stdenv,
|
||||
}:
|
||||
@@ -12,14 +11,14 @@
|
||||
# version of prisma-engines and prisma must be the same for them to
|
||||
# function correctly.
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "prisma-engines";
|
||||
version = "6.19.0";
|
||||
pname = "prisma-engines_6";
|
||||
version = "6.19.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "prisma";
|
||||
repo = "prisma-engines";
|
||||
rev = version;
|
||||
hash = "sha256-icFgoKIrr3fGSVmSczlMJiT5KSb746kVldtrk+Q0wW8=";
|
||||
tag = version;
|
||||
hash = "sha256-z3GdnrLEMJIGPKXXbz2wrbiGpuNlgYxqg3iYINYTnPI=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-PgCfBcmK9RCA5BMacJ5oYEpo2DnBKx2xPbdLb79yCCY=";
|
||||
@@ -35,9 +34,6 @@ rustPlatform.buildRustPackage rec {
|
||||
export OPENSSL_DIR=${lib.getDev openssl}
|
||||
export OPENSSL_LIB_DIR=${lib.getLib openssl}/lib
|
||||
|
||||
export PROTOC=${protobuf}/bin/protoc
|
||||
export PROTOC_INCLUDE="${protobuf}/include";
|
||||
|
||||
export SQLITE_MAX_VARIABLE_NUMBER=250000
|
||||
export SQLITE_MAX_EXPR_DEPTH=10000
|
||||
|
||||
@@ -71,7 +67,6 @@ rustPlatform.buildRustPackage rec {
|
||||
platforms = lib.platforms.unix;
|
||||
mainProgram = "prisma";
|
||||
maintainers = with lib.maintainers; [
|
||||
tomhoule
|
||||
aqrln
|
||||
];
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
fetchFromGitHub,
|
||||
lib,
|
||||
openssl,
|
||||
pkg-config,
|
||||
rustPlatform,
|
||||
}:
|
||||
|
||||
# Updating this package will force an update for prisma. The
|
||||
# version of prisma-engines and prisma must be the same for them to
|
||||
# function correctly.
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "prisma-engines_7";
|
||||
version = "7.0.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "prisma";
|
||||
repo = "prisma-engines";
|
||||
tag = version;
|
||||
hash = "sha256-+8k+M2+WySR2CeywYlhU/jd3av/4UeUoEOlO/qHUk5o=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-n83hJfSlvuaoBb3w9Rk8+q2emjGCoPDHhFdoVzhf4sM=";
|
||||
|
||||
# Use system openssl.
|
||||
OPENSSL_NO_VENDOR = 1;
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
|
||||
buildInputs = [ openssl ];
|
||||
|
||||
preBuild = ''
|
||||
export OPENSSL_DIR=${lib.getDev openssl}
|
||||
export OPENSSL_LIB_DIR=${lib.getLib openssl}/lib
|
||||
|
||||
export SQLITE_MAX_VARIABLE_NUMBER=250000
|
||||
export SQLITE_MAX_EXPR_DEPTH=10000
|
||||
|
||||
export GIT_HASH=0000000000000000000000000000000000000000
|
||||
'';
|
||||
|
||||
cargoBuildFlags = [
|
||||
"-p"
|
||||
"schema-engine-cli"
|
||||
];
|
||||
|
||||
# Tests are long to compile
|
||||
doCheck = false;
|
||||
|
||||
setupHook = ./setup-hook.sh;
|
||||
|
||||
meta = with lib; {
|
||||
description = "Collection of engines that power the core stack for Prisma";
|
||||
homepage = "https://www.prisma.io/";
|
||||
license = licenses.asl20;
|
||||
platforms = platforms.unix;
|
||||
mainProgram = "prisma";
|
||||
maintainers = with maintainers; [
|
||||
aqrln
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
### Troubleshooting
|
||||
# Here's an example application using Prisma with Nix: https://github.com/pimeys/nix-prisma-example
|
||||
# At example's `flake.nix` shellHook, notice the requirement of defining environment variables for prisma, it's values will show on `prisma --version`.
|
||||
# Read the example's README: https://github.com/pimeys/nix-prisma-example/blob/main/README.md
|
||||
# Prisma requires 2 packages, `prisma-engines` and `prisma`, to be at *exact* same versions.
|
||||
# Certify at `package.json` that dependencies "@prisma/client" and "prisma" are equal, meaning no caret (`^`) in version.
|
||||
# Configure NPM to use exact version: `npm config set save-exact=true`
|
||||
# Delete `package-lock.json`, delete `node_modules` directory and run `npm install`.
|
||||
# Run prisma client from `node_modules/.bin/prisma`.
|
||||
# Run `./node_modules/.bin/prisma --version` and check if both prisma packages versions are equal, current platform is `linux-nixos`, and other keys equal to the prisma environment variables you defined for prisma.
|
||||
# Test prisma with `generate`, `db push`, etc. It should work. If not, open an issue.
|
||||
@@ -0,0 +1 @@
|
||||
export PRISMA_SCHEMA_ENGINE_BINARY="@out@/bin/schema-engine"
|
||||
@@ -6,21 +6,21 @@
|
||||
pnpm_10,
|
||||
fetchPnpmDeps,
|
||||
pnpmConfigHook,
|
||||
prisma-engines,
|
||||
prisma-engines_6,
|
||||
jq,
|
||||
makeWrapper,
|
||||
moreutils,
|
||||
callPackage,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "prisma";
|
||||
version = "6.19.0";
|
||||
pname = "prisma_6";
|
||||
version = "6.19.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "prisma";
|
||||
repo = "prisma";
|
||||
rev = finalAttrs.version;
|
||||
hash = "sha256-lFPAu296cQMDnEcLTReSHuLuOz13kd7n0GV+ifcX+lQ=";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-73cnyg3NnQi2TLcGGhNYs95DRiVPz1LYStNsRw2EBNE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
@@ -36,7 +36,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
inherit (finalAttrs) pname version src;
|
||||
pnpm = pnpm_10;
|
||||
fetcherVersion = 1;
|
||||
hash = "sha256-9v30vhclD+sPcui/VG8dwaC8XGU6QFs/Gu8rjjoQy/w=";
|
||||
hash = "sha256-y0gxeOeQNZZu3/UEI/DmdhVD8kSrUnK5G/n/WLhiLZ4=";
|
||||
};
|
||||
|
||||
patchPhase = ''
|
||||
@@ -86,9 +86,9 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
makeWrapper "${lib.getExe nodejs}" "$out/bin/prisma" \
|
||||
--add-flags "$out/lib/prisma/packages/cli/build/index.js" \
|
||||
--set PRISMA_SCHEMA_ENGINE_BINARY ${prisma-engines}/bin/schema-engine \
|
||||
--set PRISMA_QUERY_ENGINE_BINARY ${prisma-engines}/bin/query-engine \
|
||||
--set PRISMA_QUERY_ENGINE_LIBRARY ${lib.getLib prisma-engines}/lib/libquery_engine.node
|
||||
--set PRISMA_SCHEMA_ENGINE_BINARY ${prisma-engines_6}/bin/schema-engine \
|
||||
--set PRISMA_QUERY_ENGINE_BINARY ${prisma-engines_6}/bin/query-engine \
|
||||
--set PRISMA_QUERY_ENGINE_LIBRARY ${lib.getLib prisma-engines_6}/lib/libquery_engine.node
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
@@ -1,20 +1,22 @@
|
||||
{
|
||||
lib,
|
||||
runCommand,
|
||||
prisma,
|
||||
prisma-engines,
|
||||
prisma_6,
|
||||
prisma-engines_6,
|
||||
sqlite-interactive,
|
||||
openssl,
|
||||
}:
|
||||
|
||||
let
|
||||
prismaMajorVersion = lib.versions.majorMinor prisma.version;
|
||||
enginesMajorVersion = lib.versions.majorMinor prisma-engines.version;
|
||||
prismaMajorVersion = lib.versions.majorMinor prisma_6.version;
|
||||
enginesMajorVersion = lib.versions.majorMinor prisma-engines_6.version;
|
||||
in
|
||||
runCommand "prisma-cli-tests"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
prisma
|
||||
prisma_6
|
||||
sqlite-interactive
|
||||
openssl
|
||||
];
|
||||
meta.timeout = 60;
|
||||
}
|
||||
@@ -30,8 +32,9 @@ runCommand "prisma-cli-tests"
|
||||
# Ensure CLI runs
|
||||
prisma --help > /dev/null
|
||||
|
||||
# Init a new project
|
||||
prisma init > /dev/null
|
||||
# Init a new project without prisma init, which needs
|
||||
# network access
|
||||
mkdir prisma
|
||||
|
||||
# Create a simple data model
|
||||
cat << EOF > prisma/schema.prisma
|
||||
@@ -0,0 +1,109 @@
|
||||
{
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
stdenv,
|
||||
nodejs,
|
||||
pnpm_10,
|
||||
prisma-engines_7,
|
||||
jq,
|
||||
makeWrapper,
|
||||
moreutils,
|
||||
callPackage,
|
||||
pnpmConfigHook,
|
||||
fetchPnpmDeps,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "prisma_7";
|
||||
version = "7.0.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "prisma";
|
||||
repo = "prisma";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-bmmthEFMBMJAracWUCU/6Nyic05JglP5t1VAWPVKFnU=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
nodejs
|
||||
pnpmConfigHook
|
||||
jq
|
||||
makeWrapper
|
||||
moreutils
|
||||
pnpm_10
|
||||
];
|
||||
|
||||
pnpmDeps = fetchPnpmDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
pnpm = pnpm_10;
|
||||
fetcherVersion = 1;
|
||||
hash = "sha256-sJmlMF8nay4/3LTHEWzBWaS8Xq91JRZlzKBfeMnJEMM=";
|
||||
};
|
||||
|
||||
patchPhase = ''
|
||||
runHook prePatch
|
||||
|
||||
for package in packages/*; do
|
||||
jq --arg version $version '.version = $version' $package/package.json | sponge $package/package.json
|
||||
done
|
||||
|
||||
runHook postPatch
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
pnpm build
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
# FIXME: Use pnpm deploy: https://github.com/pnpm/pnpm/issues/5315
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/lib/prisma
|
||||
|
||||
# Fetch CLI workspace dependencies
|
||||
deps_json=$(pnpm list --filter ./packages/cli --prod --depth Infinity --json)
|
||||
deps=$(jq -r '[.. | strings | select(startswith("link:../")) | sub("^link:../"; "")] | unique[]' <<< "$deps_json")
|
||||
|
||||
# Remove unnecessary external dependencies
|
||||
find . -name node_modules -type d -prune -exec rm -rf {} +
|
||||
pnpm install --offline --ignore-scripts --frozen-lockfile --prod
|
||||
cp -r node_modules $out/lib/prisma
|
||||
|
||||
# Only install cli and its workspace dependencies
|
||||
for package in cli $deps; do
|
||||
filename=$(npm pack --json ./packages/$package | jq -r '.[].filename')
|
||||
mkdir -p $out/lib/prisma/packages/$package
|
||||
[ -d "packages/$package/node_modules" ] && \
|
||||
cp -r packages/$package/node_modules $out/lib/prisma/packages/$package
|
||||
tar xf $filename --strip-components=1 -C $out/lib/prisma/packages/$package
|
||||
done
|
||||
|
||||
# Remove dangling symlinks to packages we didn't copy to $out
|
||||
find $out/lib/prisma/node_modules/.pnpm/node_modules -type l -exec test ! -e {} \; -delete
|
||||
|
||||
makeWrapper "${lib.getExe nodejs}" "$out/bin/prisma" \
|
||||
--add-flags "$out/lib/prisma/packages/cli/build/index.js" \
|
||||
--set PRISMA_SCHEMA_ENGINE_BINARY ${prisma-engines_7}/bin/schema-engine
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
dontStrip = true;
|
||||
|
||||
passthru.tests = {
|
||||
cli = callPackage ./test-cli.nix { };
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Next-generation ORM for Node.js and TypeScript";
|
||||
homepage = "https://www.prisma.io/";
|
||||
license = licenses.asl20;
|
||||
maintainers = with maintainers; [ aqrln ];
|
||||
mainProgram = "prisma";
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
})
|
||||
@@ -0,0 +1,83 @@
|
||||
{
|
||||
lib,
|
||||
runCommand,
|
||||
prisma_7,
|
||||
prisma-engines_7,
|
||||
sqlite-interactive,
|
||||
openssl,
|
||||
}:
|
||||
|
||||
let
|
||||
prismaMajorVersion = lib.versions.majorMinor prisma_7.version;
|
||||
enginesMajorVersion = lib.versions.majorMinor prisma-engines_7.version;
|
||||
in
|
||||
runCommand "prisma-cli-tests"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
prisma_7
|
||||
sqlite-interactive
|
||||
openssl
|
||||
];
|
||||
meta.timeout = 60;
|
||||
}
|
||||
''
|
||||
mkdir $out
|
||||
cd $out
|
||||
|
||||
# Set HOME to a writable directory (Nix sandbox sets it to /homeless-shelter)
|
||||
export HOME=$TMPDIR
|
||||
|
||||
if [ "${prismaMajorVersion}" != "${enginesMajorVersion}" ]; then
|
||||
echo "prisma in version ${prismaMajorVersion} and prisma-engines in ${enginesMajorVersion}. Major versions must match."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure CLI runs
|
||||
prisma --help > /dev/null
|
||||
|
||||
# Create project structure manually (prisma init requires network access)
|
||||
mkdir -p prisma node_modules
|
||||
|
||||
# The config file needs to be able to import from 'prisma/config'
|
||||
# so we symlink the prisma package into node_modules
|
||||
ln -s ${prisma_7}/lib/prisma/packages/cli node_modules/prisma
|
||||
|
||||
cat << 'EOF' > prisma.config.ts
|
||||
import { defineConfig } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
datasource: {
|
||||
url: 'file:prisma/test.db',
|
||||
},
|
||||
})
|
||||
EOF
|
||||
|
||||
# Create a simple data model
|
||||
cat << 'EOF' > prisma/schema.prisma
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
}
|
||||
|
||||
model A {
|
||||
id Int @id @default(autoincrement())
|
||||
b String @default("foo")
|
||||
}
|
||||
EOF
|
||||
|
||||
# Format
|
||||
prisma format > /dev/null
|
||||
|
||||
# Create the database
|
||||
prisma db push > /dev/null
|
||||
|
||||
# The database file should exist and be a SQLite database
|
||||
sqlite3 prisma/test.db "SELECT id, b FROM A" > /dev/null
|
||||
|
||||
# Introspect the database
|
||||
prisma db pull > /dev/null
|
||||
''
|
||||
@@ -9,16 +9,16 @@
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "qrtool";
|
||||
version = "0.13.1";
|
||||
version = "0.13.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "sorairolake";
|
||||
repo = "qrtool";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-ckdtmnUupnKAaspLm/l+nmPNdQ/sFAusQehzWikxq7A=";
|
||||
hash = "sha256-N/kxis/nLwl+cfmlIC0TzZe0nApp160VXWoWeDtOctU=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-RGEHsMay7+sjmrKz4g6uFXt6fUFiu0xIjr4fQaARKIM=";
|
||||
cargoHash = "sha256-PgtVl55gpVsDg3VMuqtQaR7hD2ebL5+ffLNdpHggxfg=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
asciidoctor
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "raycast";
|
||||
version = "1.103.7";
|
||||
version = "1.104.1";
|
||||
|
||||
src =
|
||||
{
|
||||
aarch64-darwin = fetchurl {
|
||||
name = "Raycast.dmg";
|
||||
url = "https://releases.raycast.com/releases/${finalAttrs.version}/download?build=arm";
|
||||
hash = "sha256-wsFjjBYF8yQE7y/WyTPX2OM5euqYK2PBcxbUFLB3XY0=";
|
||||
hash = "sha256-zm+r7f7uTUPtvLTVyVf18VwADltyOur8lPqqvpWrRu8=";
|
||||
};
|
||||
x86_64-darwin = fetchurl {
|
||||
name = "Raycast.dmg";
|
||||
url = "https://releases.raycast.com/releases/${finalAttrs.version}/download?build=x86_64";
|
||||
hash = "sha256-+btAHctDvsOLUG/v7c3PGxJTWAxj28laQu72Wq2pl/M=";
|
||||
hash = "sha256-TQNWPQzrPw43heW+zOCei6rM5sQYcIz6MEXonj8F3WM=";
|
||||
};
|
||||
}
|
||||
.${stdenvNoCC.system} or (throw "raycast: ${stdenvNoCC.system} is unsupported.");
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
|
||||
python3.pkgs.buildPythonApplication {
|
||||
pname = "renode-dts2repl";
|
||||
version = "0-unstable-2025-11-26";
|
||||
version = "0-unstable-2025-12-18";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "antmicro";
|
||||
repo = "dts2repl";
|
||||
rev = "f0c3d27b0f190defce22eaba0cb3f0b410d5d3db";
|
||||
hash = "sha256-Q90gF4UQqlRJ8Y116jp9gb/8hinpiTMg7QnXC7m2T+U=";
|
||||
rev = "927f689d40c34fbe64f246abf9e6abf2d79f2fb5";
|
||||
hash = "sha256-cR/rMXGOLNyQDJSg77AI8+sco446sQNI/4IuuWHLDhE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "shottr";
|
||||
version = "1.9";
|
||||
version = "1.9.1";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://shottr.cc/dl/Shottr-${finalAttrs.version}.dmg";
|
||||
hash = "sha256-Zk2VAjQGx/qH2IwUmgMC+4q0O7Sq3zx/epvJpER4BbA=";
|
||||
hash = "sha256-C/15fbz+xSpeEitQBirWuVSEf+O1PWdsBaxDYfUM5bM=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ undmg ];
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "smpmgr";
|
||||
version = "0.15.0";
|
||||
version = "0.16.0";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "intercreate";
|
||||
repo = "smpmgr";
|
||||
tag = version;
|
||||
hash = "sha256-ZIIHxQLBwd5OAxFqg0iOrdC7Xu3oZPHSJjdpo2CidAg=";
|
||||
hash = "sha256-woQ8NxHZ9lYKvEFjGbvBu7/949bzAV6hs9t/3+N7bJc=";
|
||||
};
|
||||
|
||||
build-system = with python3Packages; [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user