Merge pull request #17 from numtide/system_packages

Add support for environment.systemPackages.
This commit is contained in:
Ramses 2023-07-11 14:40:58 +02:00 committed by GitHub
commit 60ece25c0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 218 additions and 54 deletions

View file

@ -63,6 +63,10 @@ A simple System Manager module could look something like this:
launch_the_rockets = true launch_the_rockets = true
''; '';
}; };
systemPackages = [
pkgs.ripgrep
pkgs.fd
];
}; };
systemd.services = { systemd.services = {

View file

@ -1,53 +1,61 @@
{ lib, ... }: { { lib, pkgs, ... }: {
config = { config = {
nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.hostPlatform = "x86_64-linux";
services.nginx.enable = true; services.nginx.enable = true;
environment.etc = { environment = {
foo = { systemPackages = [
text = '' pkgs.ripgrep
This is just a test! pkgs.fd
];
etc = {
foo = {
text = ''
This is just a test!
'';
target = "foo_test";
};
"foo.conf".text = ''
launch_the_rockets = true
''; '';
target = "foo_test";
};
"foo.conf".text = '' "baz/bar/foo2" = {
launch_the_rockets = true text = ''
''; Another test!
'';
mode = "symlink";
};
"baz/bar/foo2" = { foo3 = {
text = '' text = "boo!";
Another test! mode = "0700";
''; user = "root";
mode = "symlink"; group = "root";
}; };
foo3 = { "a/nested/example/foo3" = {
text = "boo!"; text = "boo!";
mode = "0700"; mode = "0764";
user = "root"; user = "root";
group = "root"; group = "root";
}; };
"a/nested/example/foo3" = { "a/nested/example2/foo3" = {
text = "boo!"; text = "boo!";
mode = "0764"; mode = "0764";
user = "root"; user = "root";
group = "root"; group = "root";
}; };
"a/nested/example2/foo3" = { out-of-store = {
text = "boo!"; source = "/run/systemd/system/";
mode = "0764"; };
user = "root";
group = "root";
};
out-of-store = {
source = "/run/systemd/system/";
}; };
}; };
systemd.services = systemd.services =
lib.listToAttrs lib.listToAttrs
(lib.flip lib.genList 10 (ix: (lib.flip lib.genList 10 (ix:

View file

@ -284,6 +284,31 @@ in
cp ${resultImg} $out cp ${resultImg} $out
''; '';
mkTestPreamble =
{ node
, profile
, action
}: ''
${node}.succeed("/${profile}/bin/${action} 2>&1 | tee /tmp/output.log")
${node}.succeed("! grep -F 'ERROR' /tmp/output.log")
'';
activateProfileSnippet = { node, profile ? "system-manager-profile" }:
self.lib.mkTestPreamble {
inherit node profile;
action = "activate";
};
deactivateProfileSnippet = { node, profile ? "system-manager-profile" }:
self.lib.mkTestPreamble {
inherit node profile;
action = "deactivate";
};
prepopulateProfileSnippet = { node, profile ? "system-manager-profile" }:
self.lib.mkTestPreamble {
inherit node profile;
action = "prepopulate";
};
make-vm-test = make-vm-test =
name: name:
{ system { system

View file

@ -6,6 +6,7 @@
}: }:
{ {
imports = [ imports = [
./environment.nix
./etc.nix ./etc.nix
./systemd.nix ./systemd.nix
./upstream/nixpkgs ./upstream/nixpkgs
@ -16,7 +17,6 @@
inherit (lib) types; inherit (lib) types;
in in
{ {
nixpkgs = { nixpkgs = {
# TODO: switch to lib.systems.parsedPlatform # TODO: switch to lib.systems.parsedPlatform
hostPlatform = lib.mkOption { hostPlatform = lib.mkOption {

View file

@ -0,0 +1,70 @@
{ lib, config, pkgs, ... }:
{
options.environment = {
systemPackages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = [ ];
};
pathsToLink = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
};
config =
let
pathDir = "/run/system-manager/sw";
in
{
environment = {
pathsToLink = [
"/bin"
];
etc = {
"profile.d/system-manager-path.sh".source =
pkgs.writeText "system-manager-path.sh" ''
export PATH=${pathDir}/bin/:''${PATH}
'';
# TODO: figure out how to properly add fish support. We could start by
# looking at what NixOS and HM do to set up the fish env.
#"fish/conf.d/system-manager-path.fish".source =
# pkgs.writeTextFile {
# name = "system-manager-path.fish";
# executable = true;
# text = ''
# set -gx PATH "${pathDir}/bin/" $PATH
# '';
# };
};
};
systemd.services.system-manager-path = {
enable = true;
description = "";
wantedBy = [ "system-manager.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script =
let
pathDrv = pkgs.buildEnv {
name = "system-manager-path";
paths = config.environment.systemPackages;
inherit (config.environment) pathsToLink;
};
in
''
mkdir --parents $(dirname "${pathDir}")
if [ -L "${pathDir}" ]; then
unlink "${pathDir}"
fi
ln --symbolic --force "${pathDrv}" "${pathDir}"
'';
};
};
}

View file

@ -50,12 +50,18 @@ let
services.nginx.enable = false; services.nginx.enable = false;
environment.etc = { environment = {
foo_new = { etc = {
text = '' foo_new = {
This is just a test! text = ''
''; This is just a test!
'';
};
}; };
systemPackages = [
pkgs.fish
];
}; };
systemd.services = { systemd.services = {
@ -115,8 +121,7 @@ forEachUbuntuImage
node1.succeed("grep -F 'Error while creating file in /etc: Unmanaged path already exists in filesystem, please remove it and run system-manager again: /etc/foo_test' /tmp/output.log") node1.succeed("grep -F 'Error while creating file in /etc: Unmanaged path already exists in filesystem, please remove it and run system-manager again: /etc/foo_test' /tmp/output.log")
node1.succeed("rm /etc/foo_test") node1.succeed("rm /etc/foo_test")
node1.succeed("/system-manager-profile/bin/activate 2>&1 | tee /tmp/output.log") ${system-manager.lib.activateProfileSnippet { node = "node1"; }}
node1.succeed("! grep -F 'ERROR' /tmp/output.log")
node1.wait_for_unit("system-manager.target") node1.wait_for_unit("system-manager.target")
node1.succeed("systemctl status service-9.service") node1.succeed("systemctl status service-9.service")
@ -126,8 +131,7 @@ forEachUbuntuImage
node1.succeed("grep -F 'launch_the_rockets = true' /etc/foo.conf") node1.succeed("grep -F 'launch_the_rockets = true' /etc/foo.conf")
node1.fail("grep -F 'launch_the_rockets = false' /etc/foo.conf") node1.fail("grep -F 'launch_the_rockets = false' /etc/foo.conf")
node1.succeed("${newConfig}/bin/activate 2>&1 | tee /tmp/output.log") ${system-manager.lib.activateProfileSnippet { node = "node1"; profile = newConfig; }}
node1.succeed("! grep -F 'ERROR' /tmp/output.log")
node1.succeed("systemctl status new-service.service") node1.succeed("systemctl status new-service.service")
node1.fail("systemctl status service-9.service") node1.fail("systemctl status service-9.service")
node1.fail("cat /etc/a/nested/example/foo3") node1.fail("cat /etc/a/nested/example/foo3")
@ -151,7 +155,7 @@ forEachUbuntuImage
node1.fail("cat /etc/baz/bar/foo2") node1.fail("cat /etc/baz/bar/foo2")
node1.succeed("cat /etc/foo_new") node1.succeed("cat /etc/foo_new")
node1.succeed("${newConfig}/bin/deactivate") ${system-manager.lib.deactivateProfileSnippet { node = "node1"; profile = newConfig; }}
node1.fail("systemctl status new-service.service") node1.fail("systemctl status new-service.service")
node1.fail("cat /etc/foo_new") node1.fail("cat /etc/foo_new")
''; '';
@ -160,7 +164,7 @@ forEachUbuntuImage
}) })
) )
// //
forEachUbuntuImage forEachUbuntuImage
(imgName: image: lib.nameValuePair (imgName: image: lib.nameValuePair
@ -192,8 +196,8 @@ forEachUbuntuImage
node1.wait_for_unit("default.target") node1.wait_for_unit("default.target")
node1.succeed("/system-manager-profile/bin/prepopulate 2>&1 | tee /tmp/output.log") ${system-manager.lib.activateProfileSnippet { node = "node1"; }}
node1.succeed("! grep -F 'ERROR' /tmp/output.log")
node1.systemctl("daemon-reload") node1.systemctl("daemon-reload")
node1.systemctl("start default.target") node1.systemctl("start default.target")
node1.wait_for_unit("system-manager.target") node1.wait_for_unit("system-manager.target")
@ -205,15 +209,14 @@ forEachUbuntuImage
node1.succeed("grep -F 'launch_the_rockets = true' /etc/foo.conf") node1.succeed("grep -F 'launch_the_rockets = true' /etc/foo.conf")
node1.fail("grep -F 'launch_the_rockets = false' /etc/foo.conf") node1.fail("grep -F 'launch_the_rockets = false' /etc/foo.conf")
node1.succeed("${newConfig}/bin/activate 2>&1 | tee /tmp/output.log") ${system-manager.lib.activateProfileSnippet { node = "node1"; profile = newConfig; }}
node1.succeed("! grep -F 'ERROR' /tmp/output.log")
node1.succeed("systemctl status new-service.service") node1.succeed("systemctl status new-service.service")
node1.fail("systemctl status service-9.service") node1.fail("systemctl status service-9.service")
node1.fail("cat /etc/a/nested/example/foo3") node1.fail("cat /etc/a/nested/example/foo3")
node1.fail("cat /etc/baz/bar/foo2") node1.fail("cat /etc/baz/bar/foo2")
node1.succeed("cat /etc/foo_new") node1.succeed("cat /etc/foo_new")
node1.succeed("${newConfig}/bin/deactivate") ${system-manager.lib.deactivateProfileSnippet { node = "node1"; profile = newConfig; }}
node1.fail("systemctl status new-service.service") node1.fail("systemctl status new-service.service")
node1.fail("cat /etc/foo_new") node1.fail("cat /etc/foo_new")
''; '';
@ -222,3 +225,57 @@ forEachUbuntuImage
]; ];
}) })
) )
//
forEachUbuntuImage
(imgName: image: lib.nameValuePair
"vm-test-system-path-${imgName}"
(system-manager.lib.make-vm-test "vm-test-system-path-${imgName}" {
inherit system;
modules = [
({ config, ... }:
let
inherit (config) hostPkgs;
in
{
nodes = {
node1 = { config, ... }: {
modules = [
../../../examples/example.nix
];
virtualisation.rootImage = system-manager.lib.prepareUbuntuImage {
inherit hostPkgs image;
nodeConfig = config;
};
};
};
testScript = ''
# Start all machines in parallel
start_all()
node1.wait_for_unit("default.target")
node1.fail("bash --login -c '$(which rg)'")
node1.fail("bash --login -c '$(which fd)'")
${system-manager.lib.activateProfileSnippet { node = "node1"; }}
node1.wait_for_unit("system-manager.target")
node1.wait_for_unit("system-manager-path.service")
node1.fail("bash --login -c '$(which fish)'")
node1.succeed("bash --login -c 'realpath $(which rg) | grep -F ${hostPkgs.ripgrep}/bin/rg'")
node1.succeed("bash --login -c 'realpath $(which fd) | grep -F ${hostPkgs.fd}/bin/fd'")
${system-manager.lib.activateProfileSnippet { node = "node1"; profile = newConfig; }}
node1.fail("bash --login -c '$(which rg)'")
node1.fail("bash --login -c '$(which fd)'")
node1.succeed("bash --login -c 'realpath $(which fish) | grep -F ${hostPkgs.fish}/bin/fish'")
'';
})
];
})
)