Merge pull request #17 from numtide/system_packages
Add support for environment.systemPackages.
This commit is contained in:
commit
60ece25c0b
6 changed files with 218 additions and 54 deletions
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
25
nix/lib.nix
25
nix/lib.nix
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
70
nix/modules/environment.nix
Normal file
70
nix/modules/environment.nix
Normal 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}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -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'")
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
];
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue