Merge branch 'master' of github.com:NixOS/nixpkgs into update/jetbrains-2019.4
This commit is contained in:
commit
305f2863cf
8
.github/CODEOWNERS
vendored
8
.github/CODEOWNERS
vendored
|
@ -47,6 +47,9 @@
|
||||||
/nixos/doc/manual/man-nixos-option.xml @nbp
|
/nixos/doc/manual/man-nixos-option.xml @nbp
|
||||||
/nixos/modules/installer/tools/nixos-option.sh @nbp
|
/nixos/modules/installer/tools/nixos-option.sh @nbp
|
||||||
|
|
||||||
|
# NixOS integration test driver
|
||||||
|
/nixos/lib/test-driver @tfc
|
||||||
|
|
||||||
# New NixOS modules
|
# New NixOS modules
|
||||||
/nixos/modules/module-list.nix @Infinisil
|
/nixos/modules/module-list.nix @Infinisil
|
||||||
|
|
||||||
|
@ -167,3 +170,8 @@
|
||||||
/nixos/modules/services/monitoring/prometheus/exporters.nix @WilliButz
|
/nixos/modules/services/monitoring/prometheus/exporters.nix @WilliButz
|
||||||
/nixos/modules/services/monitoring/prometheus/exporters.xml @WilliButz
|
/nixos/modules/services/monitoring/prometheus/exporters.xml @WilliButz
|
||||||
/nixos/tests/prometheus-exporters.nix @WilliButz
|
/nixos/tests/prometheus-exporters.nix @WilliButz
|
||||||
|
|
||||||
|
# PHP
|
||||||
|
/pkgs/development/interpreters/php @etu
|
||||||
|
/pkgs/top-level/php-packages.nix @etu
|
||||||
|
/pkgs/build-support/build-pecl.nix @etu
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
preFixup = ''
|
preFixup = ''
|
||||||
for f in $(find $out/bin/ $out/libexec/ -type f -executable); do
|
for f in $(find $out/bin/ $out/libexec/ -type f -executable); do
|
||||||
wrapProgram "$f" \
|
wrapProgram "$f" \
|
||||||
--prefix GIO_EXTRA_MODULES : "${getLib gnome3.dconf}/lib/gio/modules" \
|
--prefix GIO_EXTRA_MODULES : "${getLib dconf}/lib/gio/modules" \
|
||||||
--prefix XDG_DATA_DIRS : "$out/share" \
|
--prefix XDG_DATA_DIRS : "$out/share" \
|
||||||
--prefix XDG_DATA_DIRS : "$out/share/gsettings-schemas/${name}" \
|
--prefix XDG_DATA_DIRS : "$out/share/gsettings-schemas/${name}" \
|
||||||
--prefix XDG_DATA_DIRS : "${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}" \
|
--prefix XDG_DATA_DIRS : "${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}" \
|
||||||
|
@ -102,7 +102,7 @@ preFixup = ''
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem xml:id="ssec-gnome-hooks-dconf">
|
<listitem xml:id="ssec-gnome-hooks-dconf">
|
||||||
<para>
|
<para>
|
||||||
<package>gnome3.dconf.lib</package> is a dependency of <package>wrapGAppsHook</package>, which then also adds it to the <envar>GIO_EXTRA_MODULES</envar> variable.
|
<package>dconf.lib</package> is a dependency of <package>wrapGAppsHook</package>, which then also adds it to the <envar>GIO_EXTRA_MODULES</envar> variable.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem xml:id="ssec-gnome-hooks-hicolor-icon-theme">
|
<listitem xml:id="ssec-gnome-hooks-hicolor-icon-theme">
|
||||||
|
|
|
@ -25,14 +25,14 @@ avoided that by keeping all Haskell-related packages in a separate attribute
|
||||||
set called `haskellPackages`, which the following command will list:
|
set called `haskellPackages`, which the following command will list:
|
||||||
```
|
```
|
||||||
$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages
|
$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages
|
||||||
haskellPackages.a50 a50-0.5
|
haskellPackages.a50 a50-0.5
|
||||||
haskellPackages.abacate haskell-abacate-0.0.0.0
|
haskellPackages.AAI AAI-0.2.0.1
|
||||||
haskellPackages.abcBridge haskell-abcBridge-0.12
|
haskellPackages.abacate abacate-0.0.0.0
|
||||||
haskellPackages.afv afv-0.1.1
|
haskellPackages.abc-puzzle abc-puzzle-0.2.1
|
||||||
haskellPackages.alex alex-3.1.4
|
haskellPackages.abcBridge abcBridge-0.15
|
||||||
haskellPackages.Allure Allure-0.4.101.1
|
haskellPackages.abcnotation abcnotation-1.9.0
|
||||||
haskellPackages.alms alms-0.6.7
|
haskellPackages.abeson abeson-0.1.0.1
|
||||||
[... some 8000 entries omitted ...]
|
[... some 14000 entries omitted ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
To install any of those packages into your profile, refer to them by their
|
To install any of those packages into your profile, refer to them by their
|
||||||
|
@ -101,19 +101,21 @@ to compile your Haskell packages with any GHC version you please. The following
|
||||||
command displays the complete list of available compilers:
|
command displays the complete list of available compilers:
|
||||||
```
|
```
|
||||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler
|
$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler
|
||||||
haskell.compiler.ghc6104 ghc-6.10.4
|
haskell.compiler.ghc822 ghc-8.2.2
|
||||||
haskell.compiler.ghc6123 ghc-6.12.3
|
haskell.compiler.integer-simple.ghc822 ghc-8.2.2
|
||||||
haskell.compiler.ghc704 ghc-7.0.4
|
haskell.compiler.ghc822Binary ghc-8.2.2-binary
|
||||||
haskell.compiler.ghc722 ghc-7.2.2
|
haskell.compiler.ghc844 ghc-8.4.4
|
||||||
haskell.compiler.ghc742 ghc-7.4.2
|
haskell.compiler.ghc863Binary ghc-8.6.3-binary
|
||||||
haskell.compiler.ghc763 ghc-7.6.3
|
haskell.compiler.ghc864 ghc-8.6.4
|
||||||
haskell.compiler.ghc784 ghc-7.8.4
|
haskell.compiler.integer-simple.ghc864 ghc-8.6.4
|
||||||
haskell.compiler.ghc7102 ghc-7.10.2
|
haskell.compiler.ghc865 ghc-8.6.5
|
||||||
haskell.compiler.ghcHEAD ghc-7.11.20150402
|
haskell.compiler.integer-simple.ghc865 ghc-8.6.5
|
||||||
haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704
|
haskell.compiler.ghc881 ghc-8.8.1
|
||||||
haskell.compiler.ghcjs ghcjs-0.1.0
|
haskell.compiler.integer-simple.ghc881 ghc-8.8.1
|
||||||
haskell.compiler.jhc jhc-0.8.2
|
haskell.compiler.ghcHEAD ghc-8.9.20190601
|
||||||
haskell.compiler.uhc uhc-1.1.9.0
|
haskell.compiler.integer-simple.ghcHEAD ghc-8.9.20190601
|
||||||
|
haskell.compiler.ghcjs84 ghcjs-8.4.0.1
|
||||||
|
haskell.compiler.ghcjs ghcjs-8.6.0.1
|
||||||
```
|
```
|
||||||
|
|
||||||
We have no package sets for `jhc` or `uhc` yet, unfortunately, but for every
|
We have no package sets for `jhc` or `uhc` yet, unfortunately, but for every
|
||||||
|
|
|
@ -244,7 +244,7 @@
|
||||||
</question>
|
</question>
|
||||||
<answer>
|
<answer>
|
||||||
<para>
|
<para>
|
||||||
Many packages assume that an unprefixed <command>ar</command> is available, but Nix doesn't provide one. It only provides a prefixed one, just as it only does for all the other binutils programs. It may be necessary to patch the package to fix the build system to use a prefixed `ar`.
|
Many packages assume that an unprefixed <command>ar</command> is available, but Nix doesn't provide one. It only provides a prefixed one, just as it only does for all the other binutils programs. It may be necessary to patch the package to fix the build system to use a prefixed <command>ar</command>.
|
||||||
</para>
|
</para>
|
||||||
</answer>
|
</answer>
|
||||||
</qandaentry>
|
</qandaentry>
|
||||||
|
|
|
@ -1717,7 +1717,7 @@ someVar=$(stripHash $name)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The most typical use of the setup hook is actually to add other hooks which are then run (i.e. after all the setup hooks) on each dependency. For example, the C compiler wrapper's setup hook feeds itself flags for each dependency that contains relevant libraries and headers. This is done by defining a bash function, and appending its name to one of <envar>envBuildBuildHooks</envar>`, <envar>envBuildHostHooks</envar>`, <envar>envBuildTargetHooks</envar>`, <envar>envHostHostHooks</envar>`, <envar>envHostTargetHooks</envar>`, or <envar>envTargetTargetHooks</envar>`. These 6 bash variables correspond to the 6 sorts of dependencies by platform (there's 12 total but we ignore the propagated/non-propagated axis).
|
The most typical use of the setup hook is actually to add other hooks which are then run (i.e. after all the setup hooks) on each dependency. For example, the C compiler wrapper's setup hook feeds itself flags for each dependency that contains relevant libraries and headers. This is done by defining a bash function, and appending its name to one of <envar>envBuildBuildHooks</envar>, <envar>envBuildHostHooks</envar>, <envar>envBuildTargetHooks</envar>, <envar>envHostHostHooks</envar>, <envar>envHostTargetHooks</envar>, or <envar>envTargetTargetHooks</envar>. These 6 bash variables correspond to the 6 sorts of dependencies by platform (there's 12 total but we ignore the propagated/non-propagated axis).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -141,11 +141,10 @@
|
||||||
For a more useful example, try the following. This configuration only allows unfree packages named flash player and visual studio code:
|
For a more useful example, try the following. This configuration only allows unfree packages named flash player and visual studio code:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
allowUnfreePredicate = (pkg: builtins.elem
|
allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||||
(pkg.pname or (builtins.parseDrvName pkg.name).name) [
|
"flashplayer"
|
||||||
"flashplayer"
|
"vscode"
|
||||||
"vscode"
|
];
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
@ -217,7 +216,7 @@
|
||||||
The following configuration example only allows insecure packages with very short names:
|
The following configuration example only allows insecure packages with very short names:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
allowInsecurePredicate = (pkg: (builtins.stringLength (builtins.parseDrvName pkg.name).name) <= 5);
|
allowInsecurePredicate = pkg: builtins.stringLength (lib.getName pkg) <= 5;
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -84,7 +84,8 @@ let
|
||||||
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
||||||
escapeShellArg escapeShellArgs replaceChars lowerChars
|
escapeShellArg escapeShellArgs replaceChars lowerChars
|
||||||
upperChars toLower toUpper addContextFrom splitString
|
upperChars toLower toUpper addContextFrom splitString
|
||||||
removePrefix removeSuffix versionOlder versionAtLeast getVersion
|
removePrefix removeSuffix versionOlder versionAtLeast
|
||||||
|
getName getVersion
|
||||||
nameFromURL enableFeature enableFeatureAs withFeature
|
nameFromURL enableFeature enableFeatureAs withFeature
|
||||||
withFeatureAs fixedWidthString fixedWidthNumber isStorePath
|
withFeatureAs fixedWidthString fixedWidthNumber isStorePath
|
||||||
toInt readPathsFromFile fileContents;
|
toInt readPathsFromFile fileContents;
|
||||||
|
|
|
@ -472,6 +472,23 @@ rec {
|
||||||
*/
|
*/
|
||||||
versionAtLeast = v1: v2: !versionOlder v1 v2;
|
versionAtLeast = v1: v2: !versionOlder v1 v2;
|
||||||
|
|
||||||
|
/* This function takes an argument that's either a derivation or a
|
||||||
|
derivation's "name" attribute and extracts the name part from that
|
||||||
|
argument.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
getName "youtube-dl-2016.01.01"
|
||||||
|
=> "youtube-dl"
|
||||||
|
getName pkgs.youtube-dl
|
||||||
|
=> "youtube-dl"
|
||||||
|
*/
|
||||||
|
getName = x:
|
||||||
|
let
|
||||||
|
parse = drv: (builtins.parseDrvName drv).name;
|
||||||
|
in if isString x
|
||||||
|
then parse x
|
||||||
|
else x.pname or (parse x.name);
|
||||||
|
|
||||||
/* This function takes an argument that's either a derivation or a
|
/* This function takes an argument that's either a derivation or a
|
||||||
derivation's "name" attribute and extracts the version part from that
|
derivation's "name" attribute and extracts the version part from that
|
||||||
argument.
|
argument.
|
||||||
|
|
|
@ -37,6 +37,7 @@ rec {
|
||||||
else if final.isAndroid then "bionic"
|
else if final.isAndroid then "bionic"
|
||||||
else if final.isLinux /* default */ then "glibc"
|
else if final.isLinux /* default */ then "glibc"
|
||||||
else if final.isMsp430 then "newlib"
|
else if final.isMsp430 then "newlib"
|
||||||
|
else if final.isVc4 then "newlib"
|
||||||
else if final.isAvr then "avrlibc"
|
else if final.isAvr then "avrlibc"
|
||||||
else if final.isNetBSD then "nblibc"
|
else if final.isNetBSD then "nblibc"
|
||||||
# TODO(@Ericson2314) think more about other operating systems
|
# TODO(@Ericson2314) think more about other operating systems
|
||||||
|
|
|
@ -26,7 +26,7 @@ let
|
||||||
|
|
||||||
"riscv32-linux" "riscv64-linux"
|
"riscv32-linux" "riscv64-linux"
|
||||||
|
|
||||||
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none"
|
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none" "vc4-none"
|
||||||
];
|
];
|
||||||
|
|
||||||
allParsed = map parse.mkSystemFromString all;
|
allParsed = map parse.mkSystemFromString all;
|
||||||
|
@ -45,6 +45,7 @@ in {
|
||||||
x86_64 = filterDoubles predicates.isx86_64;
|
x86_64 = filterDoubles predicates.isx86_64;
|
||||||
mips = filterDoubles predicates.isMips;
|
mips = filterDoubles predicates.isMips;
|
||||||
riscv = filterDoubles predicates.isRiscV;
|
riscv = filterDoubles predicates.isRiscV;
|
||||||
|
vc4 = filterDoubles predicates.isVc4;
|
||||||
|
|
||||||
cygwin = filterDoubles predicates.isCygwin;
|
cygwin = filterDoubles predicates.isCygwin;
|
||||||
darwin = filterDoubles predicates.isDarwin;
|
darwin = filterDoubles predicates.isDarwin;
|
||||||
|
|
|
@ -118,6 +118,12 @@ rec {
|
||||||
config = "avr";
|
config = "avr";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vc4 = {
|
||||||
|
config = "vc4-elf";
|
||||||
|
libc = "newlib";
|
||||||
|
platform = {};
|
||||||
|
};
|
||||||
|
|
||||||
arm-embedded = {
|
arm-embedded = {
|
||||||
config = "arm-none-eabi";
|
config = "arm-none-eabi";
|
||||||
libc = "newlib";
|
libc = "newlib";
|
||||||
|
|
|
@ -21,6 +21,7 @@ rec {
|
||||||
isSparc = { cpu = { family = "sparc"; }; };
|
isSparc = { cpu = { family = "sparc"; }; };
|
||||||
isWasm = { cpu = { family = "wasm"; }; };
|
isWasm = { cpu = { family = "wasm"; }; };
|
||||||
isMsp430 = { cpu = { family = "msp430"; }; };
|
isMsp430 = { cpu = { family = "msp430"; }; };
|
||||||
|
isVc4 = { cpu = { family = "vc4"; }; };
|
||||||
isAvr = { cpu = { family = "avr"; }; };
|
isAvr = { cpu = { family = "avr"; }; };
|
||||||
isAlpha = { cpu = { family = "alpha"; }; };
|
isAlpha = { cpu = { family = "alpha"; }; };
|
||||||
isJavaScript = { cpu = cpuTypes.js; };
|
isJavaScript = { cpu = cpuTypes.js; };
|
||||||
|
|
|
@ -112,6 +112,8 @@ rec {
|
||||||
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
|
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
|
||||||
avr = { bits = 8; family = "avr"; };
|
avr = { bits = 8; family = "avr"; };
|
||||||
|
|
||||||
|
vc4 = { bits = 32; significantByte = littleEndian; family = "vc4"; };
|
||||||
|
|
||||||
js = { bits = 32; significantByte = littleEndian; family = "js"; };
|
js = { bits = 32; significantByte = littleEndian; family = "js"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1484,6 +1484,16 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
d-goldin = {
|
||||||
|
email = "dgoldin+github@protonmail.ch";
|
||||||
|
github = "d-goldin";
|
||||||
|
githubId = 43349662;
|
||||||
|
name = "Dima";
|
||||||
|
keys = [{
|
||||||
|
longkeyid = "rsa4096/BAB1D15FB7B4D4CE";
|
||||||
|
fingerprint = "1C4E F4FE 7F8E D8B7 1E88 CCDF BAB1 D15F B7B4 D4CE";
|
||||||
|
}];
|
||||||
|
};
|
||||||
dadada = {
|
dadada = {
|
||||||
name = "dadada";
|
name = "dadada";
|
||||||
email = "dadada@dadada.li";
|
email = "dadada@dadada.li";
|
||||||
|
@ -1780,6 +1790,12 @@
|
||||||
githubId = 875324;
|
githubId = 875324;
|
||||||
name = "David Johnson";
|
name = "David Johnson";
|
||||||
};
|
};
|
||||||
|
dmrauh = {
|
||||||
|
email = "dmrauh@posteo.de";
|
||||||
|
github = "dmrauh";
|
||||||
|
githubId = 37698547;
|
||||||
|
name = "Dominik Michael Rauh";
|
||||||
|
};
|
||||||
dmvianna = {
|
dmvianna = {
|
||||||
email = "dmlvianna@gmail.com";
|
email = "dmlvianna@gmail.com";
|
||||||
github = "dmvianna";
|
github = "dmvianna";
|
||||||
|
@ -2515,6 +2531,7 @@
|
||||||
gazally = {
|
gazally = {
|
||||||
email = "gazally@runbox.com";
|
email = "gazally@runbox.com";
|
||||||
github = "gazally";
|
github = "gazally";
|
||||||
|
githubId = 16470252;
|
||||||
name = "Gemini Lasswell";
|
name = "Gemini Lasswell";
|
||||||
};
|
};
|
||||||
gebner = {
|
gebner = {
|
||||||
|
@ -3594,6 +3611,12 @@
|
||||||
github = "klntsky";
|
github = "klntsky";
|
||||||
githubId = 18447310;
|
githubId = 18447310;
|
||||||
};
|
};
|
||||||
|
kmcopper = {
|
||||||
|
email = "kmcopper@danwin1210.me";
|
||||||
|
name = "Kyle Copperfield";
|
||||||
|
github = "kmcopper";
|
||||||
|
githubId = 57132115;
|
||||||
|
};
|
||||||
kmeakin = {
|
kmeakin = {
|
||||||
email = "karlwfmeakin@gmail.com";
|
email = "karlwfmeakin@gmail.com";
|
||||||
name = "Karl Meakin";
|
name = "Karl Meakin";
|
||||||
|
@ -4139,6 +4162,12 @@
|
||||||
github = "marcweber";
|
github = "marcweber";
|
||||||
githubId = 34086;
|
githubId = 34086;
|
||||||
name = "Marc Weber";
|
name = "Marc Weber";
|
||||||
|
};
|
||||||
|
marcus7070 = {
|
||||||
|
email = "marcus@geosol.com.au";
|
||||||
|
github = "marcus7070";
|
||||||
|
githubId = 50230945;
|
||||||
|
name = "Marcus Boyd";
|
||||||
};
|
};
|
||||||
marenz = {
|
marenz = {
|
||||||
email = "marenz@arkom.men";
|
email = "marenz@arkom.men";
|
||||||
|
@ -4478,6 +4507,12 @@
|
||||||
githubId = 16974598;
|
githubId = 16974598;
|
||||||
name = "Mike Playle";
|
name = "Mike Playle";
|
||||||
};
|
};
|
||||||
|
mkaito = {
|
||||||
|
email = "chris@mkaito.net";
|
||||||
|
github = "mkaito";
|
||||||
|
githubId = 20434;
|
||||||
|
name = "Christian Höppner";
|
||||||
|
};
|
||||||
mkazulak = {
|
mkazulak = {
|
||||||
email = "kazulakm@gmail.com";
|
email = "kazulakm@gmail.com";
|
||||||
github = "mulderr";
|
github = "mulderr";
|
||||||
|
@ -4517,6 +4552,12 @@
|
||||||
githubId = 117842;
|
githubId = 117842;
|
||||||
name = "Henri Bourcereau";
|
name = "Henri Bourcereau";
|
||||||
};
|
};
|
||||||
|
mmilata = {
|
||||||
|
email = "martin@martinmilata.cz";
|
||||||
|
github = "mmilata";
|
||||||
|
gitHubId = 85857;
|
||||||
|
name = "Martin Milata";
|
||||||
|
};
|
||||||
mmlb = {
|
mmlb = {
|
||||||
email = "me.mmlb@mmlb.me";
|
email = "me.mmlb@mmlb.me";
|
||||||
github = "mmlb";
|
github = "mmlb";
|
||||||
|
@ -4631,6 +4672,12 @@
|
||||||
githubId = 2881922;
|
githubId = 2881922;
|
||||||
name = "Francis St-Amour";
|
name = "Francis St-Amour";
|
||||||
};
|
};
|
||||||
|
mtrsk = {
|
||||||
|
email = "marcos.schonfinkel@protonmail.com";
|
||||||
|
github = "mtrsk";
|
||||||
|
githubId = 16356569;
|
||||||
|
name = "Marcos Benevides";
|
||||||
|
};
|
||||||
mredaelli = {
|
mredaelli = {
|
||||||
email = "massimo@typish.io";
|
email = "massimo@typish.io";
|
||||||
github = "mredaelli";
|
github = "mredaelli";
|
||||||
|
@ -6099,7 +6146,7 @@
|
||||||
name = "Shahrukh Khan";
|
name = "Shahrukh Khan";
|
||||||
};
|
};
|
||||||
shanemikel = {
|
shanemikel = {
|
||||||
email = "shanemikel1@gmail.com";
|
email = "shanepearlman@pm.me";
|
||||||
github = "shanemikel";
|
github = "shanemikel";
|
||||||
githubId = 6720672;
|
githubId = 6720672;
|
||||||
name = "Shane Pearlman";
|
name = "Shane Pearlman";
|
||||||
|
@ -6720,6 +6767,12 @@
|
||||||
githubId = 42933;
|
githubId = 42933;
|
||||||
name = "Andrew Childs";
|
name = "Andrew Childs";
|
||||||
};
|
};
|
||||||
|
thefenriswolf = {
|
||||||
|
email = "stefan.rohrbacher97@gmail.com";
|
||||||
|
github = "thefenriswolf";
|
||||||
|
githubId = "8547242";
|
||||||
|
name = "Stefan Rohrbacher";
|
||||||
|
};
|
||||||
thesola10 = {
|
thesola10 = {
|
||||||
email = "thesola10@bobile.fr";
|
email = "thesola10@bobile.fr";
|
||||||
github = "thesola10";
|
github = "thesola10";
|
||||||
|
@ -7611,4 +7664,16 @@
|
||||||
githubId = 50867187;
|
githubId = 50867187;
|
||||||
name = "Rakesh Gupta";
|
name = "Rakesh Gupta";
|
||||||
};
|
};
|
||||||
|
mlatus = {
|
||||||
|
email = "wqseleven@gmail.com";
|
||||||
|
github = "Ninlives";
|
||||||
|
githubId = 17873203;
|
||||||
|
name = "mlatus";
|
||||||
|
};
|
||||||
|
waiting-for-dev = {
|
||||||
|
email = "marc@lamarciana.com";
|
||||||
|
github = "waiting-for-dev";
|
||||||
|
githubId = 52650;
|
||||||
|
name = "Marc Busqué";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ let
|
||||||
|
|
||||||
packageData = package: {
|
packageData = package: {
|
||||||
name = package.name;
|
name = package.name;
|
||||||
pname = (builtins.parseDrvName package.name).name;
|
pname = pkgs.lib.getName package;
|
||||||
updateScript = map builtins.toString (pkgs.lib.toList package.updateScript);
|
updateScript = map builtins.toString (pkgs.lib.toList package.updateScript);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,7 @@
|
||||||
<para>
|
<para>
|
||||||
It sets <xref linkend="opt-services.xserver.enable"/>,
|
It sets <xref linkend="opt-services.xserver.enable"/>,
|
||||||
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/>,
|
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/>,
|
||||||
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> (
|
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/>, and
|
||||||
<link linkend="opt-services.xserver.desktopManager.plasma5.enableQt4Support">
|
|
||||||
without Qt4 Support</link>), and
|
|
||||||
<xref linkend="opt-services.xserver.libinput.enable"/> to true. It also
|
<xref linkend="opt-services.xserver.libinput.enable"/> to true. It also
|
||||||
includes glxinfo and firefox in the system packages list.
|
includes glxinfo and firefox in the system packages list.
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -163,6 +163,57 @@
|
||||||
time during the releases development (if viable).
|
time during the releases development (if viable).
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <link linkend="opt-services.phpfpm.pools">phpfpm</link> module now sets
|
||||||
|
<literal>PrivateTmp=true</literal> in its systemd units for better process isolation.
|
||||||
|
If you rely on <literal>/tmp</literal> being shared with other services, explicitly override this by
|
||||||
|
setting <literal>serviceConfig.PrivateTmp</literal> to <literal>false</literal> for each phpfpm unit.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
KDE’s old multimedia framework Phonon no longer supports Qt 4. For that reason, Plasma desktop also does not have <option>enableQt4Support</option> option any more.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The BeeGFS module has been removed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The osquery module has been removed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Going forward, <literal>~/bin</literal> in the users home directory will no longer be in <literal>PATH</literal> by default.
|
||||||
|
If you depend on this you should set the option <literal>environment.homeBinInPath</literal> to <literal>true</literal>.
|
||||||
|
The aforementioned option was added this release.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
|
||||||
|
This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The packages <literal>openobex</literal> and <literal>obexftp</literal>
|
||||||
|
are no loger installed when enabling bluetooth via
|
||||||
|
<option>hardware.bluetooth.enable</option>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <literal>dump1090</literal> derivation has been changed to use FlightAware's dump1090
|
||||||
|
as its upstream. However, this version does not have an internal webserver anymore. The
|
||||||
|
assets in the <literal>share/dump1090</literal> directory of the derivation can be used
|
||||||
|
in conjunction with an external webserver to replace this functionality.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ let
|
||||||
optionsList = lib.sort optionLess optionsListDesc;
|
optionsList = lib.sort optionLess optionsListDesc;
|
||||||
|
|
||||||
# Convert the list of options into an XML file.
|
# Convert the list of options into an XML file.
|
||||||
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
|
optionsXML = pkgs.writeText "options.xml" (builtins.toXML optionsList);
|
||||||
|
|
||||||
optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
|
optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ from contextlib import contextmanager, _GeneratorContextManager
|
||||||
from xml.sax.saxutils import XMLGenerator
|
from xml.sax.saxutils import XMLGenerator
|
||||||
import _thread
|
import _thread
|
||||||
import atexit
|
import atexit
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import ptpython.repl
|
import ptpython.repl
|
||||||
import pty
|
import pty
|
||||||
|
@ -16,7 +15,9 @@ import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from typing import Tuple, TextIO, Any, Callable, Dict, Iterator, Optional, List
|
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
|
||||||
|
import shlex
|
||||||
|
import pathlib
|
||||||
|
|
||||||
CHAR_TO_KEY = {
|
CHAR_TO_KEY = {
|
||||||
"A": "shift-a",
|
"A": "shift-a",
|
||||||
|
@ -92,6 +93,10 @@ def eprint(*args: object, **kwargs: Any) -> None:
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def make_command(args: list) -> str:
|
||||||
|
return " ".join(map(shlex.quote, (map(str, args))))
|
||||||
|
|
||||||
|
|
||||||
def create_vlan(vlan_nr: str) -> Tuple[str, str, "subprocess.Popen[bytes]", Any]:
|
def create_vlan(vlan_nr: str) -> Tuple[str, str, "subprocess.Popen[bytes]", Any]:
|
||||||
global log
|
global log
|
||||||
log.log("starting VDE switch for network {}".format(vlan_nr))
|
log.log("starting VDE switch for network {}".format(vlan_nr))
|
||||||
|
@ -216,7 +221,7 @@ class Machine:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
self.state_dir = create_dir("vm-state-{}".format(self.name))
|
self.state_dir = create_dir("vm-state-{}".format(self.name))
|
||||||
self.shared_dir = create_dir("xchg-shared")
|
self.shared_dir = create_dir("{}/xchg".format(self.state_dir))
|
||||||
|
|
||||||
self.booted = False
|
self.booted = False
|
||||||
self.connected = False
|
self.connected = False
|
||||||
|
@ -525,6 +530,33 @@ class Machine:
|
||||||
if ret.returncode != 0:
|
if ret.returncode != 0:
|
||||||
raise Exception("Cannot convert screenshot")
|
raise Exception("Cannot convert screenshot")
|
||||||
|
|
||||||
|
def copy_from_vm(self, source: str, target_dir: str = "") -> None:
|
||||||
|
"""Copy a file from the VM (specified by an in-VM source path) to a path
|
||||||
|
relative to `$out`. The file is copied via the `shared_dir` shared among
|
||||||
|
all the VMs (using a temporary directory).
|
||||||
|
"""
|
||||||
|
# Compute the source, target, and intermediate shared file names
|
||||||
|
out_dir = pathlib.Path(os.environ.get("out", os.getcwd()))
|
||||||
|
vm_src = pathlib.Path(source)
|
||||||
|
with tempfile.TemporaryDirectory(dir=self.shared_dir) as shared_td:
|
||||||
|
shared_temp = pathlib.Path(shared_td)
|
||||||
|
vm_shared_temp = pathlib.Path("/tmp/xchg") / shared_temp.name
|
||||||
|
vm_intermediate = vm_shared_temp / vm_src.name
|
||||||
|
intermediate = shared_temp / vm_src.name
|
||||||
|
# Copy the file to the shared directory inside VM
|
||||||
|
self.succeed(make_command(["mkdir", "-p", vm_shared_temp]))
|
||||||
|
self.succeed(make_command(["cp", "-r", vm_src, vm_intermediate]))
|
||||||
|
self.succeed("sync")
|
||||||
|
abs_target = out_dir / target_dir / vm_src.name
|
||||||
|
abs_target.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
# Copy the file from the shared directory outside VM
|
||||||
|
if intermediate.is_dir():
|
||||||
|
shutil.copytree(intermediate, abs_target)
|
||||||
|
else:
|
||||||
|
shutil.copy(intermediate, abs_target)
|
||||||
|
# Make sure the cleanup is synced into VM
|
||||||
|
self.succeed("sync")
|
||||||
|
|
||||||
def dump_tty_contents(self, tty: str) -> None:
|
def dump_tty_contents(self, tty: str) -> None:
|
||||||
"""Debugging: Dump the contents of the TTY<n>
|
"""Debugging: Dump the contents of the TTY<n>
|
||||||
"""
|
"""
|
||||||
|
@ -771,7 +803,9 @@ def run_tests() -> None:
|
||||||
machine.execute("sync")
|
machine.execute("sync")
|
||||||
|
|
||||||
if nr_tests != 0:
|
if nr_tests != 0:
|
||||||
log.log("{} out of {} tests succeeded".format(nr_succeeded, nr_tests))
|
eprint("{} out of {} tests succeeded".format(nr_succeeded, nr_tests))
|
||||||
|
if nr_tests > nr_succeeded:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
|
|
@ -122,7 +122,7 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Include ~/bin/ in $PATH.
|
Include ~/bin/ in $PATH.
|
||||||
'';
|
'';
|
||||||
default = true;
|
default = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.networking.vpnc;
|
|
||||||
mkServiceDef = name: value:
|
|
||||||
{
|
|
||||||
name = "vpnc/${name}.conf";
|
|
||||||
value = { text = value; };
|
|
||||||
};
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
networking.vpnc = {
|
|
||||||
services = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = {};
|
|
||||||
example = literalExample ''
|
|
||||||
{ test = '''
|
|
||||||
IPSec gateway 192.168.1.1
|
|
||||||
IPSec ID someID
|
|
||||||
IPSec secret secretKey
|
|
||||||
Xauth username name
|
|
||||||
Xauth password pass
|
|
||||||
''';
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
description =
|
|
||||||
''
|
|
||||||
The names of cisco VPNs and their associated definitions
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config.environment.etc = mapAttrs' mkServiceDef cfg.services;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -111,9 +111,10 @@ in
|
||||||
config = mkIf enabled {
|
config = mkIf enabled {
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
{
|
||||||
assertion = with config.services.xserver.displayManager; gdm.enable -> !gdm.wayland;
|
assertion = with config.services.xserver.displayManager; gdm.nvidiaWayland -> cfg.modesetting.enable;
|
||||||
message = "NVIDIA drivers don't support wayland, set services.xserver.displayManager.gdm.wayland=false";
|
message = "You cannot use wayland with GDM without modesetting enabled for NVIDIA drivers, set `hardware.nvidia.modesetting.enable = true`";
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
assertion = !optimusCfg.enable ||
|
assertion = !optimusCfg.enable ||
|
||||||
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
|
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
|
||||||
|
|
|
@ -55,7 +55,7 @@ in
|
||||||
|
|
||||||
# Without dconf enabled it is impossible to use IBus
|
# Without dconf enabled it is impossible to use IBus
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
gnome3.dconf ibusAutostart
|
dconf ibusAutostart
|
||||||
];
|
];
|
||||||
|
|
||||||
environment.variables = {
|
environment.variables = {
|
||||||
|
|
|
@ -11,7 +11,6 @@ with lib;
|
||||||
services.xserver = {
|
services.xserver = {
|
||||||
desktopManager.plasma5 = {
|
desktopManager.plasma5 = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableQt4Support = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Automatically login as nixos.
|
# Automatically login as nixos.
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
./config/terminfo.nix
|
./config/terminfo.nix
|
||||||
./config/unix-odbc-drivers.nix
|
./config/unix-odbc-drivers.nix
|
||||||
./config/users-groups.nix
|
./config/users-groups.nix
|
||||||
./config/vpnc.nix
|
|
||||||
./config/vte.nix
|
./config/vte.nix
|
||||||
./config/zram.nix
|
./config/zram.nix
|
||||||
./hardware/acpilight.nix
|
./hardware/acpilight.nix
|
||||||
|
@ -308,6 +307,7 @@
|
||||||
./services/desktops/gnome3/sushi.nix
|
./services/desktops/gnome3/sushi.nix
|
||||||
./services/desktops/gnome3/tracker.nix
|
./services/desktops/gnome3/tracker.nix
|
||||||
./services/desktops/gnome3/tracker-miners.nix
|
./services/desktops/gnome3/tracker-miners.nix
|
||||||
|
./services/desktops/neard.nix
|
||||||
./services/desktops/profile-sync-daemon.nix
|
./services/desktops/profile-sync-daemon.nix
|
||||||
./services/desktops/system-config-printer.nix
|
./services/desktops/system-config-printer.nix
|
||||||
./services/desktops/telepathy.nix
|
./services/desktops/telepathy.nix
|
||||||
|
@ -519,7 +519,6 @@
|
||||||
./services/monitoring/munin.nix
|
./services/monitoring/munin.nix
|
||||||
./services/monitoring/nagios.nix
|
./services/monitoring/nagios.nix
|
||||||
./services/monitoring/netdata.nix
|
./services/monitoring/netdata.nix
|
||||||
./services/monitoring/osquery.nix
|
|
||||||
./services/monitoring/prometheus/default.nix
|
./services/monitoring/prometheus/default.nix
|
||||||
./services/monitoring/prometheus/alertmanager.nix
|
./services/monitoring/prometheus/alertmanager.nix
|
||||||
./services/monitoring/prometheus/exporters.nix
|
./services/monitoring/prometheus/exporters.nix
|
||||||
|
@ -539,7 +538,6 @@
|
||||||
./services/monitoring/zabbix-agent.nix
|
./services/monitoring/zabbix-agent.nix
|
||||||
./services/monitoring/zabbix-proxy.nix
|
./services/monitoring/zabbix-proxy.nix
|
||||||
./services/monitoring/zabbix-server.nix
|
./services/monitoring/zabbix-server.nix
|
||||||
./services/network-filesystems/beegfs.nix
|
|
||||||
./services/network-filesystems/cachefilesd.nix
|
./services/network-filesystems/cachefilesd.nix
|
||||||
./services/network-filesystems/davfs2.nix
|
./services/network-filesystems/davfs2.nix
|
||||||
./services/network-filesystems/drbd.nix
|
./services/network-filesystems/drbd.nix
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
displayManager.sddm.enable = true;
|
displayManager.sddm.enable = true;
|
||||||
desktopManager.plasma5 = {
|
desktopManager.plasma5 = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableQt4Support = false;
|
|
||||||
};
|
};
|
||||||
libinput.enable = true; # for touchpad support on many laptops
|
libinput.enable = true; # for touchpad support on many laptops
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,13 +32,13 @@ in
|
||||||
environment.etc = optionals (cfg.profiles != {})
|
environment.etc = optionals (cfg.profiles != {})
|
||||||
(mapAttrsToList mkDconfProfile cfg.profiles);
|
(mapAttrsToList mkDconfProfile cfg.profiles);
|
||||||
|
|
||||||
services.dbus.packages = [ pkgs.gnome3.dconf ];
|
services.dbus.packages = [ pkgs.dconf ];
|
||||||
|
|
||||||
# For dconf executable
|
# For dconf executable
|
||||||
environment.systemPackages = [ pkgs.gnome3.dconf ];
|
environment.systemPackages = [ pkgs.dconf ];
|
||||||
|
|
||||||
# Needed for unwrapped applications
|
# Needed for unwrapped applications
|
||||||
environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.gnome3.dconf.lib}/lib/gio/modules" ];
|
environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,16 @@
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
cfg = config.services.ssmtp;
|
||||||
cfg = config.networking.defaultMailServer;
|
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
|
||||||
networking.defaultMailServer = {
|
services.ssmtp = {
|
||||||
|
|
||||||
directDelivery = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
|
@ -29,7 +27,7 @@ in
|
||||||
<command>sendmail</command> or <command>postfix</command> on
|
<command>sendmail</command> or <command>postfix</command> on
|
||||||
your machine, set this option to <literal>true</literal>, and
|
your machine, set this option to <literal>true</literal>, and
|
||||||
set the option
|
set the option
|
||||||
<option>networking.defaultMailServer.hostName</option> to the
|
<option>services.ssmtp.hostName</option> to the
|
||||||
host name of your preferred mail server.
|
host name of your preferred mail server.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -129,9 +127,9 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
config = mkIf cfg.directDelivery {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
networking.defaultMailServer.authPassFile = mkIf (cfg.authPass != "")
|
services.ssmtp.authPassFile = mkIf (cfg.authPass != "")
|
||||||
(mkDefault (toString (pkgs.writeTextFile {
|
(mkDefault (toString (pkgs.writeTextFile {
|
||||||
name = "ssmtp-authpass";
|
name = "ssmtp-authpass";
|
||||||
text = cfg.authPass;
|
text = cfg.authPass;
|
||||||
|
|
|
@ -10,6 +10,9 @@ with lib;
|
||||||
(mkRenamedOptionModule [ "networking" "enableRalinkFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
(mkRenamedOptionModule [ "networking" "enableRalinkFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
||||||
(mkRenamedOptionModule [ "networking" "enableRTL8192cFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
(mkRenamedOptionModule [ "networking" "enableRTL8192cFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
||||||
(mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ])
|
(mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ])
|
||||||
|
(mkRenamedOptionModule [ "networking" "connman" ] [ "services" "connman" ])
|
||||||
|
(mkRenamedOptionModule [ "networking" "defaultMailServer" ] [ "services" "ssmtp" ])
|
||||||
|
(mkRenamedOptionModule [ "services" "ssmtp" "directDelivery" ] [ "services" "ssmtp" "enable" ])
|
||||||
(mkChangedOptionModule [ "services" "printing" "gutenprint" ] [ "services" "printing" "drivers" ]
|
(mkChangedOptionModule [ "services" "printing" "gutenprint" ] [ "services" "printing" "drivers" ]
|
||||||
(config:
|
(config:
|
||||||
let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config;
|
let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config;
|
||||||
|
@ -235,6 +238,7 @@ with lib;
|
||||||
(mkRemovedOptionModule [ "services" "zabbixServer" "dbPassword" ] "Use services.zabbixServer.database.passwordFile instead.")
|
(mkRemovedOptionModule [ "services" "zabbixServer" "dbPassword" ] "Use services.zabbixServer.database.passwordFile instead.")
|
||||||
(mkRemovedOptionModule [ "systemd" "generator-packages" ] "Use systemd.packages instead.")
|
(mkRemovedOptionModule [ "systemd" "generator-packages" ] "Use systemd.packages instead.")
|
||||||
(mkRemovedOptionModule [ "fonts" "enableCoreFonts" ] "Use fonts.fonts = [ pkgs.corefonts ]; instead.")
|
(mkRemovedOptionModule [ "fonts" "enableCoreFonts" ] "Use fonts.fonts = [ pkgs.corefonts ]; instead.")
|
||||||
|
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
|
||||||
|
|
||||||
# ZSH
|
# ZSH
|
||||||
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
||||||
|
@ -279,6 +283,13 @@ with lib;
|
||||||
# BLCR
|
# BLCR
|
||||||
(mkRemovedOptionModule [ "environment.blcr.enable" ] "The BLCR module has been removed")
|
(mkRemovedOptionModule [ "environment.blcr.enable" ] "The BLCR module has been removed")
|
||||||
|
|
||||||
|
# beegfs
|
||||||
|
(mkRemovedOptionModule [ "services.beegfsEnable" ] "The BeeGFS module has been removed")
|
||||||
|
(mkRemovedOptionModule [ "services.beegfs" ] "The BeeGFS module has been removed")
|
||||||
|
|
||||||
|
# osquery
|
||||||
|
(mkRemovedOptionModule [ "services.osquery" ] "The osquery module has been removed")
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
(mkRemovedOptionModule [ "services" "redis" "user" ] "The redis module now is hardcoded to the redis user.")
|
(mkRemovedOptionModule [ "services" "redis" "user" ] "The redis module now is hardcoded to the redis user.")
|
||||||
(mkRemovedOptionModule [ "services" "redis" "dbpath" ] "The redis module now uses /var/lib/redis as data directory.")
|
(mkRemovedOptionModule [ "services" "redis" "dbpath" ] "The redis module now uses /var/lib/redis as data directory.")
|
||||||
|
|
|
@ -66,7 +66,8 @@ in {
|
||||||
if cfg.user == "roon-server" then {
|
if cfg.user == "roon-server" then {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
description = "Roon Server user";
|
description = "Roon Server user";
|
||||||
groups = [ cfg.group "audio" ];
|
group = cfg.group;
|
||||||
|
extraGroups = [ "audio" ];
|
||||||
}
|
}
|
||||||
else {};
|
else {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,15 +8,11 @@ let
|
||||||
|
|
||||||
mysql = cfg.package;
|
mysql = cfg.package;
|
||||||
|
|
||||||
isMariaDB =
|
isMariaDB = lib.getName mysql == lib.getName pkgs.mariadb;
|
||||||
let
|
|
||||||
pName = _p: (builtins.parseDrvName (_p.name)).name;
|
|
||||||
in pName mysql == pName pkgs.mariadb;
|
|
||||||
isMysqlAtLeast57 =
|
isMysqlAtLeast57 =
|
||||||
let
|
(lib.getName mysql == lib.getName pkgs.mysql57)
|
||||||
pName = _p: (builtins.parseDrvName (_p.name)).name;
|
&& (builtins.compareVersions mysql.version "5.7" >= 0);
|
||||||
in (pName mysql == pName pkgs.mysql57)
|
|
||||||
&& ((builtins.compareVersions mysql.version "5.7") >= 0);
|
|
||||||
|
|
||||||
mysqldOptions =
|
mysqldOptions =
|
||||||
"--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}";
|
"--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}";
|
||||||
|
|
23
nixos/modules/services/desktops/neard.nix
Normal file
23
nixos/modules/services/desktops/neard.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# neard service.
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
###### interface
|
||||||
|
options = {
|
||||||
|
services.neard = {
|
||||||
|
enable = mkEnableOption "neard, NFC daemon";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
config = mkIf config.services.neard.enable {
|
||||||
|
environment.systemPackages = [ pkgs.neard ];
|
||||||
|
|
||||||
|
services.dbus.packages = [ pkgs.neard ];
|
||||||
|
|
||||||
|
systemd.packages = [ pkgs.neard ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ in
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
StateDirectory = "openarena";
|
StateDirectory = "openarena";
|
||||||
ExecStart = "${pkgs.openarena}/bin/openarena-server +set fs_basepath ${pkgs.openarena}/openarena-0.8.8 +set fs_homepath /var/lib/openarena ${concatStringsSep " " cfg.extraFlags}";
|
ExecStart = "${pkgs.openarena}/bin/oa_ded +set fs_basepath ${pkgs.openarena}/openarena-0.8.8 +set fs_homepath /var/lib/openarena ${concatStringsSep " " cfg.extraFlags}";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
|
|
||||||
# Hardening
|
# Hardening
|
||||||
|
|
|
@ -36,17 +36,25 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = with types; attrsOf (attrsOf (oneOf [ bool int str ]));
|
||||||
|
example = {
|
||||||
|
General = {
|
||||||
|
ControllerMode = "bredr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
description = "Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf).";
|
||||||
|
};
|
||||||
|
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.lines;
|
type = with types; nullOr lines;
|
||||||
default = "";
|
default = null;
|
||||||
example = ''
|
example = ''
|
||||||
[General]
|
[General]
|
||||||
ControllerMode = bredr
|
ControllerMode = bredr
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = ''
|
||||||
Set additional configuration for system-wide bluetooth (/etc/bluetooth/main.conf).
|
Set additional configuration for system-wide bluetooth (/etc/bluetooth/main.conf).
|
||||||
|
|
||||||
NOTE: We already include [Policy], so any configuration under the Policy group should come first.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -56,16 +64,18 @@ in {
|
||||||
###### implementation
|
###### implementation
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
warnings = optional (cfg.extraConfig != null) "hardware.bluetooth.`extraConfig` is deprecated, please use hardware.bluetooth.`config`.";
|
||||||
|
|
||||||
environment.systemPackages = [ bluez-bluetooth pkgs.openobex pkgs.obexftp ];
|
hardware.bluetooth.config = {
|
||||||
|
Policy = {
|
||||||
|
AutoEnable = mkDefault cfg.powerOnBoot;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = [ bluez-bluetooth ];
|
||||||
|
|
||||||
environment.etc = singleton {
|
environment.etc = singleton {
|
||||||
source = pkgs.writeText "main.conf" ''
|
source = pkgs.writeText "main.conf" (generators.toINI { } cfg.config + optionalString (cfg.extraConfig != null) cfg.extraConfig);
|
||||||
[Policy]
|
|
||||||
AutoEnable=${lib.boolToString cfg.powerOnBoot}
|
|
||||||
|
|
||||||
${cfg.extraConfig}
|
|
||||||
'';
|
|
||||||
target = "bluetooth/main.conf";
|
target = "bluetooth/main.conf";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,8 @@ in
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
ExecStart = "${pkg}/bin/beanstalkd -l ${cfg.listen.address} -p ${toString cfg.listen.port}";
|
ExecStart = "${pkg}/bin/beanstalkd -l ${cfg.listen.address} -p ${toString cfg.listen.port} -b $STATE_DIRECTORY";
|
||||||
|
StateDirectory = "beanstalkd";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -394,6 +394,28 @@ in
|
||||||
WorkingDirectory = cfg.stateDir;
|
WorkingDirectory = cfg.stateDir;
|
||||||
ExecStart = "${gitea.bin}/bin/gitea web";
|
ExecStart = "${gitea.bin}/bin/gitea web";
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
|
|
||||||
|
# Filesystem
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
PrivateDevices = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ReadWritePaths = cfg.stateDir;
|
||||||
|
# Caps
|
||||||
|
CapabilityBoundingSet = "";
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
# Misc.
|
||||||
|
LockPersonality = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
PrivateMounts = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
SystemCallFilter = "~@chown @clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @privileged @raw-io @reboot @resources @setuid @swap";
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||||
};
|
};
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
with builtins;
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.osquery;
|
|
||||||
|
|
||||||
in
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
options = {
|
|
||||||
|
|
||||||
services.osquery = {
|
|
||||||
|
|
||||||
enable = mkEnableOption "osquery";
|
|
||||||
|
|
||||||
loggerPath = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = "Base directory used for logging.";
|
|
||||||
default = "/var/log/osquery";
|
|
||||||
};
|
|
||||||
|
|
||||||
pidfile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = "Path used for pid file.";
|
|
||||||
default = "/var/osquery/osqueryd.pidfile";
|
|
||||||
};
|
|
||||||
|
|
||||||
utc = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
description = "Attempt to convert all UNIX calendar times to UTC.";
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
databasePath = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = "Path used for database file.";
|
|
||||||
default = "/var/osquery/osquery.db";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.attrs // {
|
|
||||||
merge = loc: foldl' (res: def: recursiveUpdate res def.value) {};
|
|
||||||
};
|
|
||||||
description = "Extra config to be recursively merged into the JSON config file.";
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.osquery ];
|
|
||||||
|
|
||||||
environment.etc."osquery/osquery.conf".text = toJSON (
|
|
||||||
recursiveUpdate {
|
|
||||||
options = {
|
|
||||||
config_plugin = "filesystem";
|
|
||||||
logger_plugin = "filesystem";
|
|
||||||
logger_path = cfg.loggerPath;
|
|
||||||
database_path = cfg.databasePath;
|
|
||||||
utc = cfg.utc;
|
|
||||||
};
|
|
||||||
} cfg.extraConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
systemd.services.osqueryd = {
|
|
||||||
description = "The osquery Daemon";
|
|
||||||
after = [ "network.target" "syslog.service" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
path = [ pkgs.osquery ];
|
|
||||||
preStart = ''
|
|
||||||
mkdir -p ${escapeShellArg cfg.loggerPath}
|
|
||||||
mkdir -p "$(dirname ${escapeShellArg cfg.pidfile})"
|
|
||||||
mkdir -p "$(dirname ${escapeShellArg cfg.databasePath})"
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
|
||||||
TimeoutStartSec = "infinity";
|
|
||||||
ExecStart = "${pkgs.osquery}/bin/osqueryd --logger_path ${escapeShellArg cfg.loggerPath} --pidfile ${escapeShellArg cfg.pidfile} --database_path ${escapeShellArg cfg.databasePath}";
|
|
||||||
KillMode = "process";
|
|
||||||
KillSignal = "SIGTERM";
|
|
||||||
Restart = "on-failure";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -197,6 +197,9 @@ in
|
||||||
services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey;
|
services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey;
|
||||||
})] ++ [(mkIf config.services.rspamd.enable {
|
})] ++ [(mkIf config.services.rspamd.enable {
|
||||||
services.prometheus.exporters.rspamd.url = mkDefault "http://localhost:11334/stat";
|
services.prometheus.exporters.rspamd.url = mkDefault "http://localhost:11334/stat";
|
||||||
|
})] ++ [(mkIf config.services.nginx.enable {
|
||||||
|
systemd.services.prometheus-nginx-exporter.after = [ "nginx.service" ];
|
||||||
|
systemd.services.prometheus-nginx-exporter.requires = [ "nginx.service" ];
|
||||||
})] ++ (mapAttrsToList (name: conf:
|
})] ++ (mapAttrsToList (name: conf:
|
||||||
mkExporterConf {
|
mkExporterConf {
|
||||||
inherit name;
|
inherit name;
|
||||||
|
|
|
@ -1,357 +0,0 @@
|
||||||
{ config, lib, pkgs, ...} :
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.beegfs;
|
|
||||||
|
|
||||||
# functions for the generations of config files
|
|
||||||
|
|
||||||
configMgmtd = name: cfg: pkgs.writeText "mgmt-${name}.conf" ''
|
|
||||||
storeMgmtdDirectory = ${cfg.mgmtd.storeDir}
|
|
||||||
storeAllowFirstRunInit = false
|
|
||||||
connAuthFile = ${cfg.connAuthFile}
|
|
||||||
connPortShift = ${toString cfg.connPortShift}
|
|
||||||
|
|
||||||
${cfg.mgmtd.extraConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
configAdmon = name: cfg: pkgs.writeText "admon-${name}.conf" ''
|
|
||||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
|
||||||
connAuthFile = ${cfg.connAuthFile}
|
|
||||||
connPortShift = ${toString cfg.connPortShift}
|
|
||||||
|
|
||||||
${cfg.admon.extraConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
configMeta = name: cfg: pkgs.writeText "meta-${name}.conf" ''
|
|
||||||
storeMetaDirectory = ${cfg.meta.storeDir}
|
|
||||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
|
||||||
connAuthFile = ${cfg.connAuthFile}
|
|
||||||
connPortShift = ${toString cfg.connPortShift}
|
|
||||||
storeAllowFirstRunInit = false
|
|
||||||
|
|
||||||
${cfg.meta.extraConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
configStorage = name: cfg: pkgs.writeText "storage-${name}.conf" ''
|
|
||||||
storeStorageDirectory = ${cfg.storage.storeDir}
|
|
||||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
|
||||||
connAuthFile = ${cfg.connAuthFile}
|
|
||||||
connPortShift = ${toString cfg.connPortShift}
|
|
||||||
storeAllowFirstRunInit = false
|
|
||||||
|
|
||||||
${cfg.storage.extraConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
configHelperd = name: cfg: pkgs.writeText "helperd-${name}.conf" ''
|
|
||||||
connAuthFile = ${cfg.connAuthFile}
|
|
||||||
${cfg.helperd.extraConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
configClientFilename = name : "/etc/beegfs/client-${name}.conf";
|
|
||||||
|
|
||||||
configClient = name: cfg: ''
|
|
||||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
|
||||||
connAuthFile = ${cfg.connAuthFile}
|
|
||||||
connPortShift = ${toString cfg.connPortShift}
|
|
||||||
|
|
||||||
${cfg.client.extraConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
serviceList = [
|
|
||||||
{ service = "admon"; cfgFile = configAdmon; }
|
|
||||||
{ service = "meta"; cfgFile = configMeta; }
|
|
||||||
{ service = "mgmtd"; cfgFile = configMgmtd; }
|
|
||||||
{ service = "storage"; cfgFile = configStorage; }
|
|
||||||
];
|
|
||||||
|
|
||||||
# functions to generate systemd.service entries
|
|
||||||
|
|
||||||
systemdEntry = service: cfgFile: (mapAttrs' ( name: cfg:
|
|
||||||
(nameValuePair "beegfs-${service}-${name}" (mkIf cfg.${service}.enable {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
requires = [ "network-online.target" ];
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
serviceConfig = rec {
|
|
||||||
ExecStart = ''
|
|
||||||
${pkgs.beegfs}/bin/beegfs-${service} \
|
|
||||||
cfgFile=${cfgFile name cfg} \
|
|
||||||
pidFile=${PIDFile}
|
|
||||||
'';
|
|
||||||
PIDFile = "/run/beegfs-${service}-${name}.pid";
|
|
||||||
TimeoutStopSec = "300";
|
|
||||||
};
|
|
||||||
}))) cfg);
|
|
||||||
|
|
||||||
systemdHelperd = mapAttrs' ( name: cfg:
|
|
||||||
(nameValuePair "beegfs-helperd-${name}" (mkIf cfg.client.enable {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
requires = [ "network-online.target" ];
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
serviceConfig = rec {
|
|
||||||
ExecStart = ''
|
|
||||||
${pkgs.beegfs}/bin/beegfs-helperd \
|
|
||||||
cfgFile=${configHelperd name cfg} \
|
|
||||||
pidFile=${PIDFile}
|
|
||||||
'';
|
|
||||||
PIDFile = "/run/beegfs-helperd-${name}.pid";
|
|
||||||
TimeoutStopSec = "300";
|
|
||||||
};
|
|
||||||
}))) cfg;
|
|
||||||
|
|
||||||
# wrappers to beegfs tools. Avoid typing path of config files
|
|
||||||
utilWrappers = mapAttrsToList ( name: cfg:
|
|
||||||
( pkgs.runCommand "beegfs-utils-${name}" {
|
|
||||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
|
||||||
preferLocalBuild = true;
|
|
||||||
} ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
|
|
||||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-check-servers \
|
|
||||||
$out/bin/beegfs-check-servers-${name} \
|
|
||||||
--add-flags "-c ${configClientFilename name}" \
|
|
||||||
--prefix PATH : ${lib.makeBinPath [ pkgs.beegfs ]}
|
|
||||||
|
|
||||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \
|
|
||||||
$out/bin/beegfs-ctl-${name} \
|
|
||||||
--add-flags "--cfgFile=${configClientFilename name}"
|
|
||||||
|
|
||||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \
|
|
||||||
$out/bin/beegfs-df-${name} \
|
|
||||||
--add-flags "--cfgFile=${configClientFilename name}" \
|
|
||||||
--add-flags --listtargets \
|
|
||||||
--add-flags --hidenodeid \
|
|
||||||
--add-flags --pools \
|
|
||||||
--add-flags --spaceinfo
|
|
||||||
|
|
||||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-fsck \
|
|
||||||
$out/bin/beegfs-fsck-${name} \
|
|
||||||
--add-flags "--cfgFile=${configClientFilename name}"
|
|
||||||
''
|
|
||||||
)) cfg;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
###### interface
|
|
||||||
|
|
||||||
options = {
|
|
||||||
services.beegfsEnable = mkEnableOption "BeeGFS";
|
|
||||||
|
|
||||||
services.beegfs = mkOption {
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
BeeGFS configurations. Every mount point requires a separate configuration.
|
|
||||||
'';
|
|
||||||
type = with types; attrsOf (submodule ({ ... } : {
|
|
||||||
options = {
|
|
||||||
mgmtdHost = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = null;
|
|
||||||
example = "master";
|
|
||||||
description = ''Hostname of managament host.'';
|
|
||||||
};
|
|
||||||
|
|
||||||
connAuthFile = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "";
|
|
||||||
example = "/etc/my.key";
|
|
||||||
description = "File containing shared secret authentication.";
|
|
||||||
};
|
|
||||||
|
|
||||||
connPortShift = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 0;
|
|
||||||
example = 5;
|
|
||||||
description = ''
|
|
||||||
For each additional beegfs configuration shift all
|
|
||||||
service TCP/UDP ports by at least 5.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
client = {
|
|
||||||
enable = mkEnableOption "BeeGFS client";
|
|
||||||
|
|
||||||
mount = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "Create fstab entry automatically";
|
|
||||||
};
|
|
||||||
|
|
||||||
mountPoint = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "/run/beegfs";
|
|
||||||
description = ''
|
|
||||||
Mount point under which the beegfs filesytem should be mounted.
|
|
||||||
If mounted manually the mount option specifing the config file is needed:
|
|
||||||
cfgFile=/etc/beegfs/beegfs-client-<name>.conf
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.lines;
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Additional lines for beegfs-client.conf.
|
|
||||||
See documentation for further details.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
helperd = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Enable the BeeGFS helperd.
|
|
||||||
The helpered is need for logging purposes on the client.
|
|
||||||
Disabling <literal>helperd</literal> allows for runing the client
|
|
||||||
with <literal>allowUnfree = false</literal>.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.lines;
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Additional lines for beegfs-helperd.conf. See documentation
|
|
||||||
for further details.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mgmtd = {
|
|
||||||
enable = mkEnableOption "BeeGFS mgmtd daemon";
|
|
||||||
|
|
||||||
storeDir = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = null;
|
|
||||||
example = "/data/beegfs-mgmtd";
|
|
||||||
description = ''
|
|
||||||
Data directory for mgmtd.
|
|
||||||
Must not be shared with other beegfs daemons.
|
|
||||||
This directory must exist and it must be initialized
|
|
||||||
with beegfs-setup-mgmtd, e.g. "beegfs-setup-mgmtd -C -p <storeDir>"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.lines;
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Additional lines for beegfs-mgmtd.conf. See documentation
|
|
||||||
for further details.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
admon = {
|
|
||||||
enable = mkEnableOption "BeeGFS admon daemon";
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.lines;
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Additional lines for beegfs-admon.conf. See documentation
|
|
||||||
for further details.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
enable = mkEnableOption "BeeGFS meta data daemon";
|
|
||||||
|
|
||||||
storeDir = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = null;
|
|
||||||
example = "/data/beegfs-meta";
|
|
||||||
description = ''
|
|
||||||
Data directory for meta data service.
|
|
||||||
Must not be shared with other beegfs daemons.
|
|
||||||
The underlying filesystem must be mounted with xattr turned on.
|
|
||||||
This directory must exist and it must be initialized
|
|
||||||
with beegfs-setup-meta, e.g.
|
|
||||||
"beegfs-setup-meta -C -s <serviceID> -p <storeDir>"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Additional lines for beegfs-meta.conf. See documentation
|
|
||||||
for further details.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
storage = {
|
|
||||||
enable = mkEnableOption "BeeGFS storage daemon";
|
|
||||||
|
|
||||||
storeDir = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = null;
|
|
||||||
example = "/data/beegfs-storage";
|
|
||||||
description = ''
|
|
||||||
Data directories for storage service.
|
|
||||||
Must not be shared with other beegfs daemons.
|
|
||||||
The underlying filesystem must be mounted with xattr turned on.
|
|
||||||
This directory must exist and it must be initialized
|
|
||||||
with beegfs-setup-storage, e.g.
|
|
||||||
"beegfs-setup-storage -C -s <serviceID> -i <storageTargetID> -p <storeDir>"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Addional lines for beegfs-storage.conf. See documentation
|
|
||||||
for further details.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
###### implementation
|
|
||||||
|
|
||||||
config =
|
|
||||||
mkIf config.services.beegfsEnable {
|
|
||||||
|
|
||||||
environment.systemPackages = utilWrappers;
|
|
||||||
|
|
||||||
# Put the client.conf files in /etc since they are needed
|
|
||||||
# by the commandline tools
|
|
||||||
environment.etc = mapAttrs' ( name: cfg:
|
|
||||||
(nameValuePair "beegfs/client-${name}.conf" (mkIf (cfg.client.enable)
|
|
||||||
{
|
|
||||||
enable = true;
|
|
||||||
text = configClient name cfg;
|
|
||||||
}))) cfg;
|
|
||||||
|
|
||||||
# Kernel module, we need it only once per host.
|
|
||||||
boot = mkIf (
|
|
||||||
foldr (a: b: a || b) false
|
|
||||||
(map (x: x.client.enable) (collect (x: x ? client) cfg)))
|
|
||||||
{
|
|
||||||
kernelModules = [ "beegfs" ];
|
|
||||||
extraModulePackages = [ pkgs.linuxPackages.beegfs-module ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# generate fstab entries
|
|
||||||
fileSystems = mapAttrs' (name: cfg:
|
|
||||||
(nameValuePair cfg.client.mountPoint (optionalAttrs cfg.client.mount (mkIf cfg.client.enable {
|
|
||||||
device = "beegfs_nodev";
|
|
||||||
fsType = "beegfs";
|
|
||||||
mountPoint = cfg.client.mountPoint;
|
|
||||||
options = [ "cfgFile=${configClientFilename name}" "_netdev" ];
|
|
||||||
})))) cfg;
|
|
||||||
|
|
||||||
# generate systemd services
|
|
||||||
systemd.services = systemdHelperd //
|
|
||||||
foldr (a: b: a // b) {}
|
|
||||||
(map (x: systemdEntry x.service x.cfgFile) serviceList);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -115,7 +115,7 @@ in
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = pkgs.samba;
|
default = pkgs.samba;
|
||||||
defaultText = "pkgs.samba";
|
defaultText = "pkgs.samba";
|
||||||
example = literalExample "pkgs.samba3";
|
example = literalExample "pkgs.samba4Full";
|
||||||
description = ''
|
description = ''
|
||||||
Defines which package should be used for the samba server.
|
Defines which package should be used for the samba server.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -4,7 +4,7 @@ with pkgs;
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.networking.connman;
|
cfg = config.services.connman;
|
||||||
configFile = pkgs.writeText "connman.conf" ''
|
configFile = pkgs.writeText "connman.conf" ''
|
||||||
[General]
|
[General]
|
||||||
NetworkInterfaceBlacklist=${concatStringsSep "," cfg.networkInterfaceBlacklist}
|
NetworkInterfaceBlacklist=${concatStringsSep "," cfg.networkInterfaceBlacklist}
|
||||||
|
@ -17,7 +17,7 @@ in {
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
|
||||||
networking.connman = {
|
services.connman = {
|
||||||
|
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -71,13 +71,13 @@ in {
|
||||||
|
|
||||||
assertions = [{
|
assertions = [{
|
||||||
assertion = !config.networking.useDHCP;
|
assertion = !config.networking.useDHCP;
|
||||||
message = "You can not use services.networking.connman with services.networking.useDHCP";
|
message = "You can not use services.connman with networking.useDHCP";
|
||||||
}{
|
}{
|
||||||
assertion = config.networking.wireless.enable;
|
assertion = config.networking.wireless.enable;
|
||||||
message = "You must use services.networking.connman with services.networking.wireless";
|
message = "You must use services.connman with networking.wireless";
|
||||||
}{
|
}{
|
||||||
assertion = !config.networking.networkmanager.enable;
|
assertion = !config.networking.networkmanager.enable;
|
||||||
message = "You can not use services.networking.connman with services.networking.networkmanager";
|
message = "You can not use services.connman with networking.networkmanager";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
environment.systemPackages = [ connman ];
|
environment.systemPackages = [ connman ];
|
||||||
|
|
|
@ -137,7 +137,7 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries {
|
services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries {
|
||||||
forwardZones =
|
forwardZonesRecurse =
|
||||||
{ bit = "127.0.0.1:${toString cfg.dns.port}";
|
{ bit = "127.0.0.1:${toString cfg.dns.port}";
|
||||||
dns = "127.0.0.1:${toString cfg.dns.port}";
|
dns = "127.0.0.1:${toString cfg.dns.port}";
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,11 +90,19 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
forwardZones = mkOption {
|
forwardZones = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
DNS zones to be forwarded to other authoritative servers.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
forwardZonesRecurse = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
example = { eth = "127.0.0.1:5353"; };
|
example = { eth = "127.0.0.1:5353"; };
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = ''
|
||||||
DNS zones to be forwarded to other servers.
|
DNS zones to be forwarded to other recursive servers.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,7 +166,8 @@ in {
|
||||||
webserver-port = cfg.api.port;
|
webserver-port = cfg.api.port;
|
||||||
webserver-allow-from = cfg.api.allowFrom;
|
webserver-allow-from = cfg.api.allowFrom;
|
||||||
|
|
||||||
forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones;
|
forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones;
|
||||||
|
forward-zones-recurse = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZonesRecurse;
|
||||||
export-etc-hosts = cfg.exportHosts;
|
export-etc-hosts = cfg.exportHosts;
|
||||||
dnssec = cfg.dnssecValidation;
|
dnssec = cfg.dnssecValidation;
|
||||||
serve-rfc1918 = cfg.serveRFC1918;
|
serve-rfc1918 = cfg.serveRFC1918;
|
||||||
|
|
|
@ -236,9 +236,12 @@ in {
|
||||||
${if ifaces == [] then ''
|
${if ifaces == [] then ''
|
||||||
for i in $(cd /sys/class/net && echo *); do
|
for i in $(cd /sys/class/net && echo *); do
|
||||||
DEVTYPE=
|
DEVTYPE=
|
||||||
source /sys/class/net/$i/uevent
|
UEVENT_PATH=/sys/class/net/$i/uevent
|
||||||
if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
|
if [ -e "$UEVENT_PATH" ]; then
|
||||||
ifaces="$ifaces''${ifaces:+ -N} -i$i"
|
source "$UEVENT_PATH"
|
||||||
|
if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
|
||||||
|
ifaces="$ifaces''${ifaces:+ -N} -i$i"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
'' else ''
|
'' else ''
|
||||||
|
|
|
@ -239,7 +239,7 @@ in
|
||||||
services.znc = {
|
services.znc = {
|
||||||
configFile = mkDefault (pkgs.writeText "znc-generated.conf" semanticString);
|
configFile = mkDefault (pkgs.writeText "znc-generated.conf" semanticString);
|
||||||
config = {
|
config = {
|
||||||
Version = (builtins.parseDrvName pkgs.znc.name).version;
|
Version = lib.getVersion pkgs.znc;
|
||||||
Listener.l.Port = mkDefault 5000;
|
Listener.l.Port = mkDefault 5000;
|
||||||
Listener.l.SSL = mkDefault true;
|
Listener.l.SSL = mkDefault true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,12 +84,6 @@ GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
||||||
<title>Issues</title>
|
<title>Issues</title>
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Matomo's file integrity check will warn you. This is due to the patches
|
|
||||||
necessary for NixOS, you can safely ignore this.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Matomo will warn you that the JavaScript tracker is not writable. This is
|
Matomo will warn you that the JavaScript tracker is not writable. This is
|
||||||
|
|
|
@ -390,6 +390,7 @@ in {
|
||||||
in {
|
in {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
before = [ "phpfpm-nextcloud.service" ];
|
before = [ "phpfpm-nextcloud.service" ];
|
||||||
|
path = [ occ ];
|
||||||
script = ''
|
script = ''
|
||||||
chmod og+x ${cfg.home}
|
chmod og+x ${cfg.home}
|
||||||
ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
|
ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
|
||||||
|
|
|
@ -262,6 +262,7 @@ in {
|
||||||
in {
|
in {
|
||||||
Slice = "phpfpm.slice";
|
Slice = "phpfpm.slice";
|
||||||
PrivateDevices = true;
|
PrivateDevices = true;
|
||||||
|
PrivateTmp = true;
|
||||||
ProtectSystem = "full";
|
ProtectSystem = "full";
|
||||||
ProtectHome = true;
|
ProtectHome = true;
|
||||||
# XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work
|
# XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work
|
||||||
|
|
|
@ -27,20 +27,13 @@ in
|
||||||
example = "vlc";
|
example = "vlc";
|
||||||
description = "Phonon audio backend to install.";
|
description = "Phonon audio backend to install.";
|
||||||
};
|
};
|
||||||
|
|
||||||
enableQt4Support = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Enable support for Qt 4-based applications. Particularly, install a
|
|
||||||
default backend for Phonon.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
imports = [
|
||||||
|
(mkRemovedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "enableQt4Support" ] "Phonon no longer supports Qt 4.")
|
||||||
|
];
|
||||||
|
|
||||||
config = mkMerge [
|
config = mkMerge [
|
||||||
(mkIf cfg.enable {
|
(mkIf cfg.enable {
|
||||||
|
@ -173,12 +166,10 @@ in
|
||||||
|
|
||||||
# Phonon audio backend
|
# Phonon audio backend
|
||||||
++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer
|
++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer
|
||||||
++ lib.optional (cfg.phononBackend == "gstreamer" && cfg.enableQt4Support) pkgs.phonon-backend-gstreamer
|
|
||||||
++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc
|
++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc
|
||||||
++ lib.optional (cfg.phononBackend == "vlc" && cfg.enableQt4Support) pkgs.phonon-backend-vlc
|
|
||||||
|
|
||||||
# Optional hardware support features
|
# Optional hardware support features
|
||||||
++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt ]
|
++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt openobex obexftp ]
|
||||||
++ lib.optional config.networking.networkmanager.enable plasma-nm
|
++ lib.optional config.networking.networkmanager.enable plasma-nm
|
||||||
++ lib.optional config.hardware.pulseaudio.enable plasma-pa
|
++ lib.optional config.hardware.pulseaudio.enable plasma-pa
|
||||||
++ lib.optional config.powerManagement.enable powerdevil
|
++ lib.optional config.powerManagement.enable powerdevil
|
||||||
|
|
|
@ -31,6 +31,44 @@ let
|
||||||
load-module module-position-event-sounds
|
load-module module-position-event-sounds
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
dmDefault = config.services.xserver.desktopManager.default;
|
||||||
|
wmDefault = config.services.xserver.windowManager.default;
|
||||||
|
hasDefaultUserSession = dmDefault != "none" || wmDefault != "none";
|
||||||
|
defaultSessionName = dmDefault + optionalString (wmDefault != "none") ("+" + wmDefault);
|
||||||
|
|
||||||
|
setSessionScript = pkgs.python3.pkgs.buildPythonApplication {
|
||||||
|
name = "set-session";
|
||||||
|
|
||||||
|
format = "other";
|
||||||
|
|
||||||
|
src = ./set-session.py;
|
||||||
|
|
||||||
|
dontUnpack = true;
|
||||||
|
|
||||||
|
strictDeps = false;
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
wrapGAppsHook
|
||||||
|
gobject-introspection
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
accountsservice
|
||||||
|
glib
|
||||||
|
];
|
||||||
|
|
||||||
|
propagatedBuildInputs = with pkgs.python3.pkgs; [
|
||||||
|
pygobject3
|
||||||
|
ordered-set
|
||||||
|
];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp $src $out/bin/set-session
|
||||||
|
chmod +x $out/bin/set-session
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -88,11 +126,21 @@ in
|
||||||
wayland = mkOption {
|
wayland = mkOption {
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = ''
|
||||||
Allow GDM run on Wayland instead of Xserver
|
Allow GDM to run on Wayland instead of Xserver.
|
||||||
|
Note to enable Wayland with Nvidia you need to
|
||||||
|
enable the <option>nvidiaWayland</option>.
|
||||||
'';
|
'';
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nvidiaWayland = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to allow wayland to be used with the proprietary
|
||||||
|
NVidia graphics driver.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
autoSuspend = mkOption {
|
autoSuspend = mkOption {
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = ''
|
||||||
|
@ -156,6 +204,8 @@ in
|
||||||
cat - > /run/gdm/.config/gnome-initial-setup-done <<- EOF
|
cat - > /run/gdm/.config/gnome-initial-setup-done <<- EOF
|
||||||
yes
|
yes
|
||||||
EOF
|
EOF
|
||||||
|
'' + optionalString hasDefaultUserSession ''
|
||||||
|
${setSessionScript}/bin/set-session ${defaultSessionName}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,6 +247,19 @@ in
|
||||||
|
|
||||||
services.dbus.packages = [ gdm ];
|
services.dbus.packages = [ gdm ];
|
||||||
|
|
||||||
|
# We duplicate upstream's udev rules manually to make wayland with nvidia configurable
|
||||||
|
services.udev.extraRules = ''
|
||||||
|
# disable Wayland on Cirrus chipsets
|
||||||
|
ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="${gdm}/libexec/gdm-disable-wayland"
|
||||||
|
# disable Wayland on Hi1710 chipsets
|
||||||
|
ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="${gdm}/libexec/gdm-disable-wayland"
|
||||||
|
${optionalString (!cfg.gdm.nvidiaWayland) ''
|
||||||
|
DRIVER=="nvidia", RUN+="${gdm}/libexec/gdm-disable-wayland"
|
||||||
|
''}
|
||||||
|
# disable Wayland when modesetting is disabled
|
||||||
|
IMPORT{cmdline}="nomodeset", RUN+="${gdm}/libexec/gdm-disable-wayland"
|
||||||
|
'';
|
||||||
|
|
||||||
systemd.user.services.dbus.wantedBy = [ "default.target" ];
|
systemd.user.services.dbus.wantedBy = [ "default.target" ];
|
||||||
|
|
||||||
programs.dconf.profiles.gdm =
|
programs.dconf.profiles.gdm =
|
||||||
|
@ -218,7 +281,7 @@ in
|
||||||
customDconfDb = pkgs.stdenv.mkDerivation {
|
customDconfDb = pkgs.stdenv.mkDerivation {
|
||||||
name = "gdm-dconf-db";
|
name = "gdm-dconf-db";
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
${pkgs.gnome3.dconf}/bin/dconf compile $out ${customDconf}/dconf
|
${pkgs.dconf}/bin/dconf compile $out ${customDconf}/dconf
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in pkgs.stdenv.mkDerivation {
|
in pkgs.stdenv.mkDerivation {
|
||||||
|
|
86
nixos/modules/services/x11/display-managers/set-session.py
Executable file
86
nixos/modules/services/x11/display-managers/set-session.py
Executable file
|
@ -0,0 +1,86 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import gi, argparse, os, logging, sys
|
||||||
|
|
||||||
|
gi.require_version("AccountsService", "1.0")
|
||||||
|
from gi.repository import AccountsService, GLib
|
||||||
|
from ordered_set import OrderedSet
|
||||||
|
|
||||||
|
|
||||||
|
def get_session_file(session):
|
||||||
|
system_data_dirs = GLib.get_system_data_dirs()
|
||||||
|
|
||||||
|
session_dirs = OrderedSet(
|
||||||
|
os.path.join(data_dir, session)
|
||||||
|
for data_dir in system_data_dirs
|
||||||
|
for session in {"wayland-sessions", "xsessions"}
|
||||||
|
)
|
||||||
|
|
||||||
|
session_files = OrderedSet(
|
||||||
|
os.path.join(dir, session + ".desktop")
|
||||||
|
for dir in session_dirs
|
||||||
|
if os.path.exists(os.path.join(dir, session + ".desktop"))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Deal with duplicate wayland-sessions and xsessions.
|
||||||
|
# Needed for the situation in gnome-session, where there's
|
||||||
|
# a xsession named the same as a wayland session.
|
||||||
|
if any(map(is_session_wayland, session_files)):
|
||||||
|
session_files = OrderedSet(
|
||||||
|
session for session in session_files if is_session_wayland(session)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
session_files = OrderedSet(
|
||||||
|
session for session in session_files if is_session_xsession(session)
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(session_files) == 0:
|
||||||
|
logging.warning("No session files are found.")
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
return session_files[0]
|
||||||
|
|
||||||
|
|
||||||
|
def is_session_xsession(session_file):
|
||||||
|
return "/xsessions/" in session_file
|
||||||
|
|
||||||
|
|
||||||
|
def is_session_wayland(session_file):
|
||||||
|
return "/wayland-sessions/" in session_file
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Set session type for all normal users."
|
||||||
|
)
|
||||||
|
parser.add_argument("session", help="Name of session to set.")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
session = getattr(args, "session")
|
||||||
|
session_file = get_session_file(session)
|
||||||
|
|
||||||
|
user_manager = AccountsService.UserManager.get_default()
|
||||||
|
users = user_manager.list_users()
|
||||||
|
|
||||||
|
for user in users:
|
||||||
|
if user.is_system_account():
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if is_session_wayland(session_file):
|
||||||
|
logging.debug(
|
||||||
|
f"Setting session name: {session}, as we found the existing wayland-session: {session_file}"
|
||||||
|
)
|
||||||
|
user.set_session(session)
|
||||||
|
elif is_session_xsession(session_file):
|
||||||
|
logging.debug(
|
||||||
|
f"Setting session name: {session}, as we found the existing xsession: {session_file}"
|
||||||
|
)
|
||||||
|
user.set_x_session(session)
|
||||||
|
else:
|
||||||
|
logging.error(f"Couldn't figure out session type for {session_file}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -47,8 +47,8 @@ let
|
||||||
grub = f grub;
|
grub = f grub;
|
||||||
grubTarget = f (grub.grubTarget or "");
|
grubTarget = f (grub.grubTarget or "");
|
||||||
shell = "${pkgs.runtimeShell}";
|
shell = "${pkgs.runtimeShell}";
|
||||||
fullName = (builtins.parseDrvName realGrub.name).name;
|
fullName = lib.getName realGrub;
|
||||||
fullVersion = (builtins.parseDrvName realGrub.name).version;
|
fullVersion = lib.getVersion realGrub;
|
||||||
grubEfi = f grubEfi;
|
grubEfi = f grubEfi;
|
||||||
grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f (grubEfi.grubTarget or "") else "";
|
grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f (grubEfi.grubTarget or "") else "";
|
||||||
bootPath = args.path;
|
bootPath = args.path;
|
||||||
|
|
|
@ -201,7 +201,7 @@ let
|
||||||
(assertValueOneOf "IPv6AcceptRA" boolValues)
|
(assertValueOneOf "IPv6AcceptRA" boolValues)
|
||||||
(assertValueOneOf "IPv4ProxyARP" boolValues)
|
(assertValueOneOf "IPv4ProxyARP" boolValues)
|
||||||
(assertValueOneOf "IPv6ProxyNDP" boolValues)
|
(assertValueOneOf "IPv6ProxyNDP" boolValues)
|
||||||
(assertValueOneOf "IPv6PrefixDelegation" boolValues)
|
(assertValueOneOf "IPv6PrefixDelegation" (boolValues ++ [ "dhcpv6" "static" ]))
|
||||||
(assertValueOneOf "ActiveSlave" boolValues)
|
(assertValueOneOf "ActiveSlave" boolValues)
|
||||||
(assertValueOneOf "PrimarySlave" boolValues)
|
(assertValueOneOf "PrimarySlave" boolValues)
|
||||||
(assertValueOneOf "ConfigureWithoutCarrier" boolValues)
|
(assertValueOneOf "ConfigureWithoutCarrier" boolValues)
|
||||||
|
@ -924,6 +924,8 @@ in
|
||||||
|
|
||||||
config = mkIf config.systemd.network.enable {
|
config = mkIf config.systemd.network.enable {
|
||||||
|
|
||||||
|
users.users.systemd-network.group = "systemd-network";
|
||||||
|
|
||||||
systemd.additionalUpstreamSystemUnits = [
|
systemd.additionalUpstreamSystemUnits = [
|
||||||
"systemd-networkd.service" "systemd-networkd-wait-online.service"
|
"systemd-networkd.service" "systemd-networkd-wait-online.service"
|
||||||
];
|
];
|
||||||
|
|
|
@ -136,6 +136,8 @@ in
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
users.users.resolved.group = "systemd-resolve";
|
||||||
|
|
||||||
systemd.additionalUpstreamSystemUnits = [
|
systemd.additionalUpstreamSystemUnits = [
|
||||||
"systemd-resolved.service"
|
"systemd-resolved.service"
|
||||||
];
|
];
|
||||||
|
|
|
@ -50,7 +50,10 @@ with lib;
|
||||||
${config.services.timesyncd.extraConfig}
|
${config.services.timesyncd.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
users.users.systemd-timesync.uid = config.ids.uids.systemd-timesync;
|
users.users.systemd-timesync = {
|
||||||
|
uid = config.ids.uids.systemd-timesync;
|
||||||
|
group = "systemd-timesync";
|
||||||
|
};
|
||||||
users.groups.systemd-timesync.gid = config.ids.gids.systemd-timesync;
|
users.groups.systemd-timesync.gid = config.ids.gids.systemd-timesync;
|
||||||
|
|
||||||
system.activationScripts.systemd-timesyncd-migration = mkIf (versionOlder config.system.stateVersion "19.09") ''
|
system.activationScripts.systemd-timesyncd-migration = mkIf (versionOlder config.system.stateVersion "19.09") ''
|
||||||
|
|
|
@ -149,7 +149,7 @@ let
|
||||||
--setenv PATH="$PATH" \
|
--setenv PATH="$PATH" \
|
||||||
${optionalString cfg.ephemeral "--ephemeral"} \
|
${optionalString cfg.ephemeral "--ephemeral"} \
|
||||||
${if cfg.additionalCapabilities != null && cfg.additionalCapabilities != [] then
|
${if cfg.additionalCapabilities != null && cfg.additionalCapabilities != [] then
|
||||||
''--capability="${concatStringsSep " " cfg.additionalCapabilities}"'' else ""
|
''--capability="${concatStringsSep "," cfg.additionalCapabilities}"'' else ""
|
||||||
} \
|
} \
|
||||||
${if cfg.tmpfs != null && cfg.tmpfs != [] then
|
${if cfg.tmpfs != null && cfg.tmpfs != [] then
|
||||||
''--tmpfs=${concatStringsSep " --tmpfs=" cfg.tmpfs}'' else ""
|
''--tmpfs=${concatStringsSep " --tmpfs=" cfg.tmpfs}'' else ""
|
||||||
|
|
197
nixos/modules/virtualisation/digital-ocean-config.nix
Normal file
197
nixos/modules/virtualisation/digital-ocean-config.nix
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
{ config, pkgs, lib, modulesPath, ... }:
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
(modulesPath + "/virtualisation/digital-ocean-init.nix")
|
||||||
|
];
|
||||||
|
options.virtualisation.digitalOcean = with types; {
|
||||||
|
setRootPassword = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = false;
|
||||||
|
example = true;
|
||||||
|
description = "Whether to set the root password from the Digital Ocean metadata";
|
||||||
|
};
|
||||||
|
setSshKeys = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
example = true;
|
||||||
|
description = "Whether to fetch ssh keys from Digital Ocean";
|
||||||
|
};
|
||||||
|
seedEntropy = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
example = true;
|
||||||
|
description = "Whether to run the kernel RNG entropy seeding script from the Digital Ocean vendor data";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
cfg = config.virtualisation.digitalOcean;
|
||||||
|
hostName = config.networking.hostName;
|
||||||
|
doMetadataFile = "/run/do-metadata/v1.json";
|
||||||
|
in mkMerge [{
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
autoResize = true;
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
boot = {
|
||||||
|
growPartition = true;
|
||||||
|
kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ];
|
||||||
|
initrd.kernelModules = [ "virtio_scsi" ];
|
||||||
|
kernelModules = [ "virtio_pci" "virtio_net" ];
|
||||||
|
loader = {
|
||||||
|
grub.device = "/dev/vda";
|
||||||
|
timeout = 0;
|
||||||
|
grub.configurationLimit = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.openssh = {
|
||||||
|
enable = mkDefault true;
|
||||||
|
passwordAuthentication = mkDefault false;
|
||||||
|
};
|
||||||
|
services.do-agent.enable = mkDefault true;
|
||||||
|
networking = {
|
||||||
|
hostName = mkDefault ""; # use Digital Ocean metadata server
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Check for and wait for the metadata server to become reachable.
|
||||||
|
* This serves as a dependency for all the other metadata services. */
|
||||||
|
systemd.services.digitalocean-metadata = {
|
||||||
|
path = [ pkgs.curl ];
|
||||||
|
description = "Get host metadata provided by Digitalocean";
|
||||||
|
script = ''
|
||||||
|
set -eu
|
||||||
|
DO_DELAY_ATTEMPTS=0
|
||||||
|
while ! curl -fsSL -o $RUNTIME_DIRECTORY/v1.json http://169.254.169.254/metadata/v1.json; do
|
||||||
|
DO_DELAY_ATTEMPTS=$((DO_DELAY_ATTEMPTS + 1))
|
||||||
|
if (( $DO_DELAY_ATTEMPTS >= $DO_DELAY_ATTEMPTS_MAX )); then
|
||||||
|
echo "giving up"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "metadata unavailable, trying again in 1s..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
chmod 600 $RUNTIME_DIRECTORY/v1.json
|
||||||
|
'';
|
||||||
|
environment = {
|
||||||
|
DO_DELAY_ATTEMPTS_MAX = "10";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
RuntimeDirectory = "do-metadata";
|
||||||
|
RuntimeDirectoryPreserve = "yes";
|
||||||
|
};
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!${doMetadataFile}";
|
||||||
|
After = [ "network-pre.target" ] ++
|
||||||
|
optional config.networking.dhcpcd.enable "dhcpcd.service" ++
|
||||||
|
optional config.systemd.network.enable "systemd-networkd.service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Fetch the root password from the digital ocean metadata.
|
||||||
|
* There is no specific route for this, so we use jq to get
|
||||||
|
* it from the One Big JSON metadata blob */
|
||||||
|
systemd.services.digitalocean-set-root-password = mkIf cfg.setRootPassword {
|
||||||
|
path = [ pkgs.shadow pkgs.jq ];
|
||||||
|
description = "Set root password provided by Digitalocean";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
script = ''
|
||||||
|
set -eo pipefail
|
||||||
|
ROOT_PASSWORD=$(jq -er '.auth_key' ${doMetadataFile})
|
||||||
|
echo "root:$ROOT_PASSWORD" | chpasswd
|
||||||
|
mkdir -p /etc/do-metadata/set-root-password
|
||||||
|
'';
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/etc/do-metadata/set-root-password";
|
||||||
|
Before = optional config.services.openssh.enable "sshd.service";
|
||||||
|
After = [ "digitalocean-metadata.service" ];
|
||||||
|
Requires = [ "digitalocean-metadata.service" ];
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set the hostname from Digital Ocean, unless the user configured it in
|
||||||
|
* the NixOS configuration. The cached metadata file isn't used here
|
||||||
|
* because the hostname is a mutable part of the droplet. */
|
||||||
|
systemd.services.digitalocean-set-hostname = mkIf (hostName == "") {
|
||||||
|
path = [ pkgs.curl pkgs.nettools ];
|
||||||
|
description = "Set hostname provided by Digitalocean";
|
||||||
|
wantedBy = [ "network.target" ];
|
||||||
|
script = ''
|
||||||
|
set -e
|
||||||
|
DIGITALOCEAN_HOSTNAME=$(curl -fsSL http://169.254.169.254/metadata/v1/hostname)
|
||||||
|
hostname "$DIGITALOCEAN_HOSTNAME"
|
||||||
|
if [[ ! -e /etc/hostname || -w /etc/hostname ]]; then
|
||||||
|
printf "%s\n" "$DIGITALOCEAN_HOSTNAME" > /etc/hostname
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
unitConfig = {
|
||||||
|
Before = [ "network.target" ];
|
||||||
|
After = [ "digitalocean-metadata.service" ];
|
||||||
|
Wants = [ "digitalocean-metadata.service" ];
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Fetch the ssh keys for root from Digital Ocean */
|
||||||
|
systemd.services.digitalocean-ssh-keys = mkIf cfg.setSshKeys {
|
||||||
|
description = "Set root ssh keys provided by Digital Ocean";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
path = [ pkgs.jq ];
|
||||||
|
script = ''
|
||||||
|
set -e
|
||||||
|
mkdir -m 0700 -p /root/.ssh
|
||||||
|
jq -er '.public_keys[]' ${doMetadataFile} > /root/.ssh/authorized_keys
|
||||||
|
chmod 600 /root/.ssh/authorized_keys
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/root/.ssh/authorized_keys";
|
||||||
|
Before = optional config.services.openssh.enable "sshd.service";
|
||||||
|
After = [ "digitalocean-metadata.service" ];
|
||||||
|
Requires = [ "digitalocean-metadata.service" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Initialize the RNG by running the entropy-seed script from the
|
||||||
|
* Digital Ocean metadata
|
||||||
|
*/
|
||||||
|
systemd.services.digitalocean-entropy-seed = mkIf cfg.seedEntropy {
|
||||||
|
description = "Run the kernel RNG entropy seeding script from the Digital Ocean vendor data";
|
||||||
|
wantedBy = [ "network.target" ];
|
||||||
|
path = [ pkgs.jq pkgs.mpack ];
|
||||||
|
script = ''
|
||||||
|
set -eo pipefail
|
||||||
|
TEMPDIR=$(mktemp -d)
|
||||||
|
jq -er '.vendor_data' ${doMetadataFile} | munpack -tC $TEMPDIR
|
||||||
|
ENTROPY_SEED=$(grep -rl "DigitalOcean Entropy Seed script" $TEMPDIR)
|
||||||
|
${pkgs.runtimeShell} $ENTROPY_SEED
|
||||||
|
rm -rf $TEMPDIR
|
||||||
|
'';
|
||||||
|
unitConfig = {
|
||||||
|
Before = [ "network.target" ];
|
||||||
|
After = [ "digitalocean-metadata.service" ];
|
||||||
|
Requires = [ "digitalocean-metadata.service" ];
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
];
|
||||||
|
meta.maintainers = with maintainers; [ arianvp eamsden ];
|
||||||
|
}
|
||||||
|
|
69
nixos/modules/virtualisation/digital-ocean-image.nix
Normal file
69
nixos/modules/virtualisation/digital-ocean-image.nix
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.virtualisation.digitalOceanImage;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
imports = [ ./digital-ocean-config.nix ];
|
||||||
|
|
||||||
|
options = {
|
||||||
|
virtualisation.digitalOceanImage.diskSize = mkOption {
|
||||||
|
type = with types; int;
|
||||||
|
default = 4096;
|
||||||
|
description = ''
|
||||||
|
Size of disk image. Unit is MB.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.digitalOceanImage.configFile = mkOption {
|
||||||
|
type = with types; nullOr path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
A path to a configuration file which will be placed at
|
||||||
|
<literal>/etc/nixos/configuration.nix</literal> and be used when switching
|
||||||
|
to a new configuration. If set to <literal>null</literal>, a default
|
||||||
|
configuration is used that imports
|
||||||
|
<literal>(modulesPath + "/virtualisation/digital-ocean-config.nix")</literal>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.digitalOceanImage.compressionMethod = mkOption {
|
||||||
|
type = types.enum [ "gzip" "bzip2" ];
|
||||||
|
default = "gzip";
|
||||||
|
example = "bzip2";
|
||||||
|
description = ''
|
||||||
|
Disk image compression method. Choose bzip2 to generate smaller images that
|
||||||
|
take longer to generate but will consume less metered storage space on your
|
||||||
|
Digital Ocean account.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#### implementation
|
||||||
|
config = {
|
||||||
|
|
||||||
|
system.build.digitalOceanImage = import ../../lib/make-disk-image.nix {
|
||||||
|
name = "digital-ocean-image";
|
||||||
|
format = "qcow2";
|
||||||
|
postVM = let
|
||||||
|
compress = {
|
||||||
|
"gzip" = "${pkgs.gzip}/bin/gzip";
|
||||||
|
"bzip2" = "${pkgs.bzip2}/bin/bzip2";
|
||||||
|
}.${cfg.compressionMethod};
|
||||||
|
in ''
|
||||||
|
${compress} $diskImage
|
||||||
|
'';
|
||||||
|
configFile = if cfg.configFile == null
|
||||||
|
then config.virtualisation.digitalOcean.defaultConfigFile
|
||||||
|
else cfg.configFile;
|
||||||
|
inherit (cfg) diskSize;
|
||||||
|
inherit config lib pkgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with maintainers; [ arianvp eamsden ];
|
||||||
|
|
||||||
|
}
|
95
nixos/modules/virtualisation/digital-ocean-init.nix
Normal file
95
nixos/modules/virtualisation/digital-ocean-init.nix
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.virtualisation.digitalOcean;
|
||||||
|
defaultConfigFile = pkgs.writeText "digitalocean-configuration.nix" ''
|
||||||
|
{ modulesPath, lib, ... }:
|
||||||
|
{
|
||||||
|
imports = lib.optional (builtins.pathExists ./do-userdata.nix) ./do-userdata.nix ++ [
|
||||||
|
(modulesPath + "/virtualisation/digital-ocean-config.nix")
|
||||||
|
];
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
options.virtualisation.digitalOcean.rebuildFromUserData = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
example = true;
|
||||||
|
description = "Whether to reconfigure the system from Digital Ocean user data";
|
||||||
|
};
|
||||||
|
options.virtualisation.digitalOcean.defaultConfigFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = defaultConfigFile;
|
||||||
|
defaultText = ''
|
||||||
|
The default configuration imports user-data if applicable and
|
||||||
|
<literal>(modulesPath + "/virtualisation/digital-ocean-config.nix")</literal>.
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
A path to a configuration file which will be placed at
|
||||||
|
<literal>/etc/nixos/configuration.nix</literal> and be used when switching to
|
||||||
|
a new configuration.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
systemd.services.digitalocean-init = mkIf cfg.rebuildFromUserData {
|
||||||
|
description = "Reconfigure the system from Digital Ocean userdata on startup";
|
||||||
|
wantedBy = [ "network-online.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/etc/nixos/do-userdata.nix";
|
||||||
|
After = [ "digitalocean-metadata.service" "network-online.target" ];
|
||||||
|
Requires = [ "digitalocean-metadata.service" ];
|
||||||
|
X-StopOnRemoval = false;
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
path = [ pkgs.jq pkgs.gnused pkgs.gnugrep pkgs.systemd config.nix.package config.system.build.nixos-rebuild ];
|
||||||
|
environment = {
|
||||||
|
HOME = "/root";
|
||||||
|
NIX_PATH = concatStringsSep ":" [
|
||||||
|
"/nix/var/nix/profiles/per-user/root/channels/nixos"
|
||||||
|
"nixos-config=/etc/nixos/configuration.nix"
|
||||||
|
"/nix/var/nix/profiles/per-user/root/channels"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
set -e
|
||||||
|
echo "attempting to fetch configuration from Digital Ocean user data..."
|
||||||
|
userData=$(mktemp)
|
||||||
|
if jq -er '.user_data' /run/do-metadata/v1.json > $userData; then
|
||||||
|
# If the user-data looks like it could be a nix expression,
|
||||||
|
# copy it over. Also, look for a magic three-hash comment and set
|
||||||
|
# that as the channel.
|
||||||
|
if nix-instantiate --parse $userData > /dev/null; then
|
||||||
|
channels="$(grep '^###' "$userData" | sed 's|###\s*||')"
|
||||||
|
printf "%s" "$channels" | while read channel; do
|
||||||
|
echo "writing channel: $channel"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n "$channels" ]]; then
|
||||||
|
printf "%s" "$channels" > /root/.nix-channels
|
||||||
|
nix-channel --update
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "setting configuration from Digital Ocean user data"
|
||||||
|
cp "$userData" /etc/nixos/do-userdata.nix
|
||||||
|
if [[ ! -e /etc/nixos/configuration.nix ]]; then
|
||||||
|
install -m0644 ${cfg.defaultConfigFile} /etc/nixos/configuration.nix
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "user data does not appear to be a Nix expression; ignoring"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
nixos-rebuild switch
|
||||||
|
else
|
||||||
|
echo "no user data is available"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
meta.maintainers = with maintainers; [ arianvp eamsden ];
|
||||||
|
}
|
|
@ -42,6 +42,9 @@ in {
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Whether to start racoon service for openvswitch.
|
Whether to start racoon service for openvswitch.
|
||||||
|
Supported only if openvswitch version is less than 2.6.0.
|
||||||
|
Use <literal>virtualisation.vswitch.package = pkgs.openvswitch-lts</literal>
|
||||||
|
for a version that supports ipsec over GRE.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -89,6 +92,13 @@ in {
|
||||||
"${cfg.package}/share/openvswitch/vswitch.ovsschema"
|
"${cfg.package}/share/openvswitch/vswitch.ovsschema"
|
||||||
fi
|
fi
|
||||||
chmod -R +w /var/db/openvswitch
|
chmod -R +w /var/db/openvswitch
|
||||||
|
if ${cfg.package}/bin/ovsdb-tool needs-conversion /var/db/openvswitch/conf.db | grep -q "yes"
|
||||||
|
then
|
||||||
|
echo "Performing database upgrade"
|
||||||
|
${cfg.package}/bin/ovsdb-tool convert /var/db/openvswitch/conf.db
|
||||||
|
else
|
||||||
|
echo "Database already up to date"
|
||||||
|
fi
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart =
|
ExecStart =
|
||||||
|
@ -133,7 +143,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
(mkIf cfg.ipsec {
|
(mkIf (cfg.ipsec && (versionOlder cfg.package.version "2.6.0")) {
|
||||||
services.racoon.enable = true;
|
services.racoon.enable = true;
|
||||||
services.racoon.configPath = "${runDir}/ipsec/etc/racoon/racoon.conf";
|
services.racoon.configPath = "${runDir}/ipsec/etc/racoon/racoon.conf";
|
||||||
|
|
||||||
|
@ -172,5 +182,4 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
})]));
|
})]));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -620,7 +620,7 @@ in
|
||||||
|
|
||||||
# Wireless won't work in the VM.
|
# Wireless won't work in the VM.
|
||||||
networking.wireless.enable = mkVMOverride false;
|
networking.wireless.enable = mkVMOverride false;
|
||||||
networking.connman.enable = mkVMOverride false;
|
services.connman.enable = mkVMOverride false;
|
||||||
|
|
||||||
# Speed up booting by not waiting for ARP.
|
# Speed up booting by not waiting for ARP.
|
||||||
networking.dhcpcd.extraConfig = "noarp";
|
networking.dhcpcd.extraConfig = "noarp";
|
||||||
|
|
|
@ -63,8 +63,7 @@ in rec {
|
||||||
|
|
||||||
#(all nixos.tests.containers)
|
#(all nixos.tests.containers)
|
||||||
(all nixos.tests.containers-imperative)
|
(all nixos.tests.containers-imperative)
|
||||||
(all nixos.tests.containers-ipv4)
|
(all nixos.tests.containers-ip)
|
||||||
(all nixos.tests.containers-ipv6)
|
|
||||||
nixos.tests.chromium.x86_64-linux or []
|
nixos.tests.chromium.x86_64-linux or []
|
||||||
(all nixos.tests.firefox)
|
(all nixos.tests.firefox)
|
||||||
(all nixos.tests.firewall)
|
(all nixos.tests.firewall)
|
||||||
|
|
|
@ -32,8 +32,7 @@ in rec {
|
||||||
tests = {
|
tests = {
|
||||||
inherit (nixos'.tests)
|
inherit (nixos'.tests)
|
||||||
containers-imperative
|
containers-imperative
|
||||||
containers-ipv4
|
containers-ip
|
||||||
containers-ipv6
|
|
||||||
firewall
|
firewall
|
||||||
ipv6
|
ipv6
|
||||||
login
|
login
|
||||||
|
|
|
@ -28,7 +28,7 @@ in
|
||||||
babeld = handleTest ./babeld.nix {};
|
babeld = handleTest ./babeld.nix {};
|
||||||
bcachefs = handleTestOn ["x86_64-linux"] ./bcachefs.nix {}; # linux-4.18.2018.10.12 is unsupported on aarch64
|
bcachefs = handleTestOn ["x86_64-linux"] ./bcachefs.nix {}; # linux-4.18.2018.10.12 is unsupported on aarch64
|
||||||
beanstalkd = handleTest ./beanstalkd.nix {};
|
beanstalkd = handleTest ./beanstalkd.nix {};
|
||||||
beegfs = handleTestOn ["x86_64-linux"] ./beegfs.nix {}; # beegfs is unsupported on aarch64
|
bees = handleTest ./bees.nix {};
|
||||||
bind = handleTest ./bind.nix {};
|
bind = handleTest ./bind.nix {};
|
||||||
bittorrent = handleTest ./bittorrent.nix {};
|
bittorrent = handleTest ./bittorrent.nix {};
|
||||||
#blivet = handleTest ./blivet.nix {}; # broken since 2017-07024
|
#blivet = handleTest ./blivet.nix {}; # broken since 2017-07024
|
||||||
|
@ -53,8 +53,7 @@ in
|
||||||
containers-extra_veth = handleTest ./containers-extra_veth.nix {};
|
containers-extra_veth = handleTest ./containers-extra_veth.nix {};
|
||||||
containers-hosts = handleTest ./containers-hosts.nix {};
|
containers-hosts = handleTest ./containers-hosts.nix {};
|
||||||
containers-imperative = handleTest ./containers-imperative.nix {};
|
containers-imperative = handleTest ./containers-imperative.nix {};
|
||||||
containers-ipv4 = handleTest ./containers-ipv4.nix {};
|
containers-ip = handleTest ./containers-ip.nix {};
|
||||||
containers-ipv6 = handleTest ./containers-ipv6.nix {};
|
|
||||||
containers-macvlans = handleTest ./containers-macvlans.nix {};
|
containers-macvlans = handleTest ./containers-macvlans.nix {};
|
||||||
containers-physical_interfaces = handleTest ./containers-physical_interfaces.nix {};
|
containers-physical_interfaces = handleTest ./containers-physical_interfaces.nix {};
|
||||||
containers-restart_networking = handleTest ./containers-restart_networking.nix {};
|
containers-restart_networking = handleTest ./containers-restart_networking.nix {};
|
||||||
|
@ -206,7 +205,6 @@ in
|
||||||
openstack-image-metadata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).metadata or {};
|
openstack-image-metadata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).metadata or {};
|
||||||
orangefs = handleTest ./orangefs.nix {};
|
orangefs = handleTest ./orangefs.nix {};
|
||||||
os-prober = handleTestOn ["x86_64-linux"] ./os-prober.nix {};
|
os-prober = handleTestOn ["x86_64-linux"] ./os-prober.nix {};
|
||||||
osquery = handleTest ./osquery.nix {};
|
|
||||||
osrm-backend = handleTest ./osrm-backend.nix {};
|
osrm-backend = handleTest ./osrm-backend.nix {};
|
||||||
overlayfs = handleTest ./overlayfs.nix {};
|
overlayfs = handleTest ./overlayfs.nix {};
|
||||||
packagekit = handleTest ./packagekit.nix {};
|
packagekit = handleTest ./packagekit.nix {};
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
import ./make-test.nix ({ ... } :
|
|
||||||
|
|
||||||
let
|
|
||||||
connAuthFile="beegfs/auth-def.key";
|
|
||||||
|
|
||||||
client = { pkgs, ... } : {
|
|
||||||
networking.firewall.enable = false;
|
|
||||||
services.beegfsEnable = true;
|
|
||||||
services.beegfs.default = {
|
|
||||||
mgmtdHost = "mgmt";
|
|
||||||
connAuthFile = "/etc/${connAuthFile}";
|
|
||||||
client = {
|
|
||||||
mount = false;
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems = pkgs.lib.mkVMOverride # FIXME: this should be creatd by the module
|
|
||||||
[ { mountPoint = "/beegfs";
|
|
||||||
device = "default";
|
|
||||||
fsType = "beegfs";
|
|
||||||
options = [ "cfgFile=/etc/beegfs/client-default.conf" "_netdev" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.etc.${connAuthFile} = {
|
|
||||||
enable = true;
|
|
||||||
text = "ThisIsALousySecret";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
server = service : { pkgs, ... } : {
|
|
||||||
networking.firewall.enable = false;
|
|
||||||
boot.initrd.postDeviceCommands = ''
|
|
||||||
${pkgs.e2fsprogs}/bin/mkfs.ext4 -L data /dev/vdb
|
|
||||||
'';
|
|
||||||
|
|
||||||
virtualisation.emptyDiskImages = [ 4096 ];
|
|
||||||
|
|
||||||
fileSystems = pkgs.lib.mkVMOverride
|
|
||||||
[ { mountPoint = "/data";
|
|
||||||
device = "/dev/disk/by-label/data";
|
|
||||||
fsType = "ext4";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ beegfs ];
|
|
||||||
environment.etc.${connAuthFile} = {
|
|
||||||
enable = true;
|
|
||||||
text = "ThisIsALousySecret";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.beegfsEnable = true;
|
|
||||||
services.beegfs.default = {
|
|
||||||
mgmtdHost = "mgmt";
|
|
||||||
connAuthFile = "/etc/${connAuthFile}";
|
|
||||||
${service} = {
|
|
||||||
enable = true;
|
|
||||||
storeDir = "/data";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
name = "beegfs";
|
|
||||||
|
|
||||||
nodes = {
|
|
||||||
meta = server "meta";
|
|
||||||
mgmt = server "mgmtd";
|
|
||||||
storage1 = server "storage";
|
|
||||||
storage2 = server "storage";
|
|
||||||
client1 = client;
|
|
||||||
client2 = client;
|
|
||||||
};
|
|
||||||
|
|
||||||
testScript = ''
|
|
||||||
# Initalize the data directories
|
|
||||||
$mgmt->waitForUnit("default.target");
|
|
||||||
$mgmt->succeed("beegfs-setup-mgmtd -C -f -p /data");
|
|
||||||
$mgmt->succeed("systemctl start beegfs-mgmtd-default");
|
|
||||||
|
|
||||||
$meta->waitForUnit("default.target");
|
|
||||||
$meta->succeed("beegfs-setup-meta -C -f -s 1 -p /data");
|
|
||||||
$meta->succeed("systemctl start beegfs-meta-default");
|
|
||||||
|
|
||||||
$storage1->waitForUnit("default.target");
|
|
||||||
$storage1->succeed("beegfs-setup-storage -C -f -s 1 -i 1 -p /data");
|
|
||||||
$storage1->succeed("systemctl start beegfs-storage-default");
|
|
||||||
|
|
||||||
$storage2->waitForUnit("default.target");
|
|
||||||
$storage2->succeed("beegfs-setup-storage -C -f -s 2 -i 2 -p /data");
|
|
||||||
$storage2->succeed("systemctl start beegfs-storage-default");
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
# Basic test
|
|
||||||
$client1->waitForUnit("beegfs.mount");
|
|
||||||
$client1->succeed("beegfs-check-servers-default");
|
|
||||||
$client1->succeed("echo test > /beegfs/test");
|
|
||||||
$client2->waitForUnit("beegfs.mount");
|
|
||||||
$client2->succeed("test -e /beegfs/test");
|
|
||||||
$client2->succeed("cat /beegfs/test | grep test");
|
|
||||||
|
|
||||||
# test raid0/stripping
|
|
||||||
$client1->succeed("dd if=/dev/urandom bs=1M count=10 of=/beegfs/striped");
|
|
||||||
$client2->succeed("cat /beegfs/striped > /dev/null");
|
|
||||||
|
|
||||||
# check if fs is still healthy
|
|
||||||
$client1->succeed("beegfs-fsck-default --checkfs");
|
|
||||||
'';
|
|
||||||
})
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ lib, ... }:
|
import ./make-test-python.nix ({ lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
name = "bees";
|
name = "bees";
|
||||||
|
|
||||||
|
@ -29,27 +29,34 @@ import ./make-test.nix ({ lib, ... }:
|
||||||
|
|
||||||
testScript =
|
testScript =
|
||||||
let
|
let
|
||||||
withRetry = content: maxTests: sleepTime: ''
|
someContentIsShared = loc: pkgs.writeShellScript "some-content-is-shared" ''
|
||||||
max_tests=${lib.escapeShellArg maxTests}; sleep_time=${lib.escapeShellArg sleepTime}; for ((i=0; i<max_tests; i++)); do ${content} && exit 0; sleep "$sleep_time"; done; exit 1;
|
[[ $(btrfs fi du -s --raw ${lib.escapeShellArg loc}/dedup-me-{1,2} | awk 'BEGIN { count=0; } NR>1 && $3 == 0 { count++ } END { print count }') -eq 0 ]]
|
||||||
'';
|
'';
|
||||||
someContentIsShared = loc: ''[[ $(btrfs fi du -s --raw ${lib.escapeShellArg loc}/dedup-me-{1,2} | awk 'BEGIN { count=0; } NR>1 && $3 == 0 { count++ } END { print count }') -eq 0 ]]'';
|
|
||||||
in ''
|
in ''
|
||||||
# shut down the instance started by systemd at boot, so we can test our test procedure
|
# shut down the instance started by systemd at boot, so we can test our test procedure
|
||||||
$machine->succeed("systemctl stop beesd\@aux1.service");
|
machine.succeed("systemctl stop beesd@aux1.service")
|
||||||
|
|
||||||
$machine->succeed("dd if=/dev/urandom of=/aux1/dedup-me-1 bs=1M count=8");
|
machine.succeed(
|
||||||
$machine->succeed("cp --reflink=never /aux1/dedup-me-1 /aux1/dedup-me-2");
|
"dd if=/dev/urandom of=/aux1/dedup-me-1 bs=1M count=8",
|
||||||
$machine->succeed("cp --reflink=never /aux1/* /aux2/");
|
"cp --reflink=never /aux1/dedup-me-1 /aux1/dedup-me-2",
|
||||||
$machine->succeed("sync");
|
"cp --reflink=never /aux1/* /aux2/",
|
||||||
$machine->fail(q(${someContentIsShared "/aux1"}));
|
"sync",
|
||||||
$machine->fail(q(${someContentIsShared "/aux2"}));
|
)
|
||||||
$machine->succeed("systemctl start beesd\@aux1.service");
|
machine.fail(
|
||||||
|
"${someContentIsShared "/aux1"}",
|
||||||
|
"${someContentIsShared "/aux2"}",
|
||||||
|
)
|
||||||
|
machine.succeed("systemctl start beesd@aux1.service")
|
||||||
|
|
||||||
# assert that "Set Shared" column is nonzero
|
# assert that "Set Shared" column is nonzero
|
||||||
$machine->succeed(q(${withRetry (someContentIsShared "/aux1") 20 2}));
|
machine.wait_until_succeeds(
|
||||||
$machine->fail(q(${someContentIsShared "/aux2"}));
|
"${someContentIsShared "/aux1"}",
|
||||||
|
)
|
||||||
|
machine.fail("${someContentIsShared "/aux2"}")
|
||||||
|
|
||||||
# assert that 16MB hash table size requested was honored
|
# assert that 16MB hash table size requested was honored
|
||||||
$machine->succeed(q([[ $(stat -c %s /aux1/.beeshome/beeshash.dat) = $(( 16 * 1024 * 1024)) ]]))
|
machine.succeed(
|
||||||
|
"[[ $(stat -c %s /aux1/.beeshome/beeshash.dat) = $(( 16 * 1024 * 1024)) ]]"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ... }: {
|
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
name = "clickhouse";
|
name = "clickhouse";
|
||||||
meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ma27 ];
|
meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ma27 ];
|
||||||
|
|
||||||
|
@ -14,12 +14,18 @@ import ./make-test.nix ({ pkgs, ... }: {
|
||||||
selectQuery = pkgs.writeText "select.sql" "SELECT * from `demo`";
|
selectQuery = pkgs.writeText "select.sql" "SELECT * from `demo`";
|
||||||
in
|
in
|
||||||
''
|
''
|
||||||
$machine->start();
|
machine.start()
|
||||||
$machine->waitForUnit("clickhouse.service");
|
machine.wait_for_unit("clickhouse.service")
|
||||||
$machine->waitForOpenPort(9000);
|
machine.wait_for_open_port(9000)
|
||||||
|
|
||||||
$machine->succeed("cat ${tableDDL} | clickhouse-client");
|
machine.succeed(
|
||||||
$machine->succeed("cat ${insertQuery} | clickhouse-client");
|
"cat ${tableDDL} | clickhouse-client"
|
||||||
$machine->succeed("cat ${selectQuery} | clickhouse-client | grep foo");
|
)
|
||||||
|
machine.succeed(
|
||||||
|
"cat ${insertQuery} | clickhouse-client"
|
||||||
|
)
|
||||||
|
machine.succeed(
|
||||||
|
"cat ${selectQuery} | clickhouse-client | grep foo"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ... }:
|
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||||
{
|
{
|
||||||
name = "codimd";
|
name = "codimd";
|
||||||
|
|
||||||
|
@ -35,20 +35,18 @@ import ./make-test.nix ({ pkgs, lib, ... }:
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll();
|
start_all()
|
||||||
|
|
||||||
subtest "CodiMD sqlite", sub {
|
with subtest("CodiMD sqlite"):
|
||||||
$codimdSqlite->waitForUnit("codimd.service");
|
codimdSqlite.wait_for_unit("codimd.service")
|
||||||
$codimdSqlite->waitForOpenPort(3000);
|
codimdSqlite.wait_for_open_port(3000)
|
||||||
$codimdSqlite->waitUntilSucceeds("curl -sSf http://localhost:3000/new");
|
codimdSqlite.wait_until_succeeds("curl -sSf http://localhost:3000/new")
|
||||||
};
|
|
||||||
|
|
||||||
subtest "CodiMD postgres", sub {
|
with subtest("CodiMD postgres"):
|
||||||
$codimdPostgres->waitForUnit("postgresql.service");
|
codimdPostgres.wait_for_unit("postgresql.service")
|
||||||
$codimdPostgres->waitForUnit("codimd.service");
|
codimdPostgres.wait_for_unit("codimd.service")
|
||||||
$codimdPostgres->waitForOpenPort(5432);
|
codimdPostgres.wait_for_open_port(5432)
|
||||||
$codimdPostgres->waitForOpenPort(3000);
|
codimdPostgres.wait_for_open_port(3000)
|
||||||
$codimdPostgres->waitUntilSucceeds("curl -sSf http://localhost:3000/new");
|
codimdPostgres.wait_until_succeeds("curl -sSf http://localhost:3000/new")
|
||||||
};
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ let
|
||||||
containerIp6 = "fc00::2/7";
|
containerIp6 = "fc00::2/7";
|
||||||
in
|
in
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "containers-bridge";
|
name = "containers-bridge";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
||||||
|
@ -61,43 +61,42 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript =
|
testScript = ''
|
||||||
''
|
machine.wait_for_unit("default.target")
|
||||||
$machine->waitForUnit("default.target");
|
assert "webserver" in machine.succeed("nixos-container list")
|
||||||
$machine->succeed("nixos-container list") =~ /webserver/ or die;
|
|
||||||
|
|
||||||
# Start the webserver container.
|
with subtest("Start the webserver container"):
|
||||||
$machine->succeed("nixos-container status webserver") =~ /up/ or die;
|
assert "up" in machine.succeed("nixos-container status webserver")
|
||||||
|
|
||||||
# Check if bridges exist inside containers
|
with subtest("Bridges exist inside containers"):
|
||||||
$machine->succeed("nixos-container run webserver -- ip link show eth0");
|
machine.succeed(
|
||||||
$machine->succeed("nixos-container run web-noip -- ip link show eth0");
|
"nixos-container run webserver -- ip link show eth0",
|
||||||
|
"nixos-container run web-noip -- ip link show eth0",
|
||||||
|
)
|
||||||
|
|
||||||
"${containerIp}" =~ /([^\/]+)\/([0-9+])/;
|
ip = "${containerIp}".split("/")[0]
|
||||||
my $ip = $1;
|
machine.succeed(f"ping -n -c 1 {ip}")
|
||||||
chomp $ip;
|
machine.succeed(f"curl --fail http://{ip}/ > /dev/null")
|
||||||
$machine->succeed("ping -n -c 1 $ip");
|
|
||||||
$machine->succeed("curl --fail http://$ip/ > /dev/null");
|
|
||||||
|
|
||||||
"${containerIp6}" =~ /([^\/]+)\/([0-9+])/;
|
ip6 = "${containerIp6}".split("/")[0]
|
||||||
my $ip6 = $1;
|
machine.succeed(f"ping -n -c 1 {ip6}")
|
||||||
chomp $ip6;
|
machine.succeed(f"curl --fail http://[{ip6}]/ > /dev/null")
|
||||||
$machine->succeed("ping -n -c 1 $ip6");
|
|
||||||
$machine->succeed("curl --fail http://[$ip6]/ > /dev/null");
|
|
||||||
|
|
||||||
# Check that nixos-container show-ip works in case of an ipv4 address with
|
with subtest(
|
||||||
# subnetmask in CIDR notation.
|
"nixos-container show-ip works in case of an ipv4 address "
|
||||||
my $result = $machine->succeed("nixos-container show-ip webserver");
|
+ "with subnetmask in CIDR notation."
|
||||||
chomp $result;
|
):
|
||||||
$result eq $ip or die;
|
result = machine.succeed("nixos-container show-ip webserver").rstrip()
|
||||||
|
assert result == ip
|
||||||
|
|
||||||
# Stop the container.
|
with subtest("Stop the container"):
|
||||||
$machine->succeed("nixos-container stop webserver");
|
machine.succeed("nixos-container stop webserver")
|
||||||
$machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null");
|
machine.fail(
|
||||||
$machine->fail("curl --fail --connect-timeout 2 http://[$ip6]/ > /dev/null");
|
f"curl --fail --connect-timeout 2 http://{ip}/ > /dev/null",
|
||||||
|
f"curl --fail --connect-timeout 2 http://[{ip6}]/ > /dev/null",
|
||||||
# Destroying a declarative container should fail.
|
)
|
||||||
$machine->fail("nixos-container destroy webserver");
|
|
||||||
'';
|
|
||||||
|
|
||||||
|
# Destroying a declarative container should fail.
|
||||||
|
machine.fail("nixos-container destroy webserver")
|
||||||
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test for NixOS' container support.
|
# Test for NixOS' container support.
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "containers-ephemeral";
|
name = "containers-ephemeral";
|
||||||
|
|
||||||
machine = { pkgs, ... }: {
|
machine = { pkgs, ... }: {
|
||||||
|
@ -16,10 +16,10 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
virtualHosts.localhost = {
|
virtualHosts.localhost = {
|
||||||
root = (pkgs.runCommand "localhost" {} ''
|
root = pkgs.runCommand "localhost" {} ''
|
||||||
mkdir "$out"
|
mkdir "$out"
|
||||||
echo hello world > "$out/index.html"
|
echo hello world > "$out/index.html"
|
||||||
'');
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||||
|
@ -28,29 +28,27 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
$machine->succeed("nixos-container list") =~ /webserver/ or die;
|
assert "webserver" in machine.succeed("nixos-container list")
|
||||||
|
|
||||||
# Start the webserver container.
|
machine.succeed("nixos-container start webserver")
|
||||||
$machine->succeed("nixos-container start webserver");
|
|
||||||
|
|
||||||
# Check that container got its own root folder
|
with subtest("Container got its own root folder"):
|
||||||
$machine->succeed("ls /run/containers/webserver");
|
machine.succeed("ls /run/containers/webserver")
|
||||||
|
|
||||||
# Check that container persistent directory is not created
|
with subtest("Container persistent directory is not created"):
|
||||||
$machine->fail("ls /var/lib/containers/webserver");
|
machine.fail("ls /var/lib/containers/webserver")
|
||||||
|
|
||||||
# Since "start" returns after the container has reached
|
# Since "start" returns after the container has reached
|
||||||
# multi-user.target, we should now be able to access it.
|
# multi-user.target, we should now be able to access it.
|
||||||
my $ip = $machine->succeed("nixos-container show-ip webserver");
|
ip = machine.succeed("nixos-container show-ip webserver").rstrip()
|
||||||
chomp $ip;
|
machine.succeed(f"ping -n -c1 {ip}")
|
||||||
$machine->succeed("ping -n -c1 $ip");
|
machine.succeed(f"curl --fail http://{ip}/ > /dev/null")
|
||||||
$machine->succeed("curl --fail http://$ip/ > /dev/null");
|
|
||||||
|
|
||||||
# Stop the container.
|
with subtest("Stop the container"):
|
||||||
$machine->succeed("nixos-container stop webserver");
|
machine.succeed("nixos-container stop webserver")
|
||||||
$machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null");
|
machine.fail(f"curl --fail --connect-timeout 2 http://{ip}/ > /dev/null")
|
||||||
|
|
||||||
# Check that container's root folder was removed
|
with subtest("Container's root folder was removed"):
|
||||||
$machine->fail("ls /run/containers/webserver");
|
machine.fail("ls /run/containers/webserver")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test for NixOS' container support.
|
# Test for NixOS' container support.
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "containers-hosts";
|
name = "containers-hosts";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ montag451 ];
|
maintainers = [ montag451 ];
|
||||||
|
@ -42,11 +42,11 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
start_all()
|
||||||
$machine->waitForUnit("default.target");
|
machine.wait_for_unit("default.target")
|
||||||
|
|
||||||
# Ping the containers using the entries added in /etc/hosts
|
with subtest("Ping the containers using the entries added in /etc/hosts"):
|
||||||
$machine->succeed("ping -n -c 1 simple.containers");
|
for host in "simple.containers", "netmask.containers":
|
||||||
$machine->succeed("ping -n -c 1 netmask.containers");
|
machine.succeed(f"ping -n -c 1 {host}")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test for NixOS' container support.
|
# Test for NixOS' container support.
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "containers-imperative";
|
name = "containers-imperative";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
||||||
|
@ -36,95 +36,99 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = let
|
testScript = let
|
||||||
tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" ''
|
tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" ''
|
||||||
{
|
{
|
||||||
systemd.tmpfiles.rules = [ "d /foo - - - - -" ];
|
systemd.tmpfiles.rules = [ "d /foo - - - - -" ];
|
||||||
systemd.services.foo = {
|
systemd.services.foo = {
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
script = "ls -al /foo";
|
script = "ls -al /foo";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
''; in
|
'';
|
||||||
''
|
in ''
|
||||||
# Make sure we have a NixOS tree (required by ‘nixos-container create’).
|
with subtest("Make sure we have a NixOS tree (required by ‘nixos-container create’)"):
|
||||||
$machine->succeed("PAGER=cat nix-env -qa -A nixos.hello >&2");
|
machine.succeed("PAGER=cat nix-env -qa -A nixos.hello >&2")
|
||||||
|
|
||||||
# Create some containers imperatively.
|
id1, id2 = None, None
|
||||||
my $id1 = $machine->succeed("nixos-container create foo --ensure-unique-name");
|
|
||||||
chomp $id1;
|
|
||||||
$machine->log("created container $id1");
|
|
||||||
|
|
||||||
my $id2 = $machine->succeed("nixos-container create foo --ensure-unique-name");
|
with subtest("Create some containers imperatively"):
|
||||||
chomp $id2;
|
id1 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip()
|
||||||
$machine->log("created container $id2");
|
machine.log(f"created container {id1}")
|
||||||
|
|
||||||
die if $id1 eq $id2;
|
id2 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip()
|
||||||
|
machine.log(f"created container {id2}")
|
||||||
|
|
||||||
# Put the root of $id2 into a bind mount.
|
assert id1 != id2
|
||||||
$machine->succeed(
|
|
||||||
"mv /var/lib/containers/$id2 /id2-bindmount",
|
|
||||||
"mount --bind /id2-bindmount /var/lib/containers/$id1"
|
|
||||||
);
|
|
||||||
|
|
||||||
my $ip1 = $machine->succeed("nixos-container show-ip $id1");
|
with subtest(f"Put the root of {id2} into a bind mount"):
|
||||||
chomp $ip1;
|
machine.succeed(
|
||||||
my $ip2 = $machine->succeed("nixos-container show-ip $id2");
|
f"mv /var/lib/containers/{id2} /id2-bindmount",
|
||||||
chomp $ip2;
|
f"mount --bind /id2-bindmount /var/lib/containers/{id1}",
|
||||||
die if $ip1 eq $ip2;
|
)
|
||||||
|
|
||||||
# Create a directory and a file we can later check if it still exists
|
ip1 = machine.succeed(f"nixos-container show-ip {id1}").rstrip()
|
||||||
# after destruction of the container.
|
ip2 = machine.succeed(f"nixos-container show-ip {id2}").rstrip()
|
||||||
$machine->succeed(
|
assert ip1 != ip2
|
||||||
"mkdir /nested-bindmount",
|
|
||||||
"echo important data > /nested-bindmount/dummy",
|
|
||||||
);
|
|
||||||
|
|
||||||
# Create a directory with a dummy file and bind-mount it into both
|
with subtest(
|
||||||
# containers.
|
"Create a directory and a file we can later check if it still exists "
|
||||||
foreach ($id1, $id2) {
|
+ "after destruction of the container"
|
||||||
my $importantPath = "/var/lib/containers/$_/very/important/data";
|
):
|
||||||
$machine->succeed(
|
machine.succeed("mkdir /nested-bindmount")
|
||||||
"mkdir -p $importantPath",
|
machine.succeed("echo important data > /nested-bindmount/dummy")
|
||||||
"mount --bind /nested-bindmount $importantPath"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Start one of them.
|
with subtest(
|
||||||
$machine->succeed("nixos-container start $id1");
|
"Create a directory with a dummy file and bind-mount it into both containers."
|
||||||
|
):
|
||||||
|
for id in id1, id2:
|
||||||
|
important_path = f"/var/lib/containers/{id}/very/important/data"
|
||||||
|
machine.succeed(
|
||||||
|
f"mkdir -p {important_path}",
|
||||||
|
f"mount --bind /nested-bindmount {important_path}",
|
||||||
|
)
|
||||||
|
|
||||||
# Execute commands via the root shell.
|
with subtest("Start one of them"):
|
||||||
$machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
|
machine.succeed(f"nixos-container start {id1}")
|
||||||
|
|
||||||
# Execute a nix command via the root shell. (regression test for #40355)
|
with subtest("Execute commands via the root shell"):
|
||||||
$machine->succeed("nixos-container run $id1 -- nix-instantiate -E 'derivation { name = \"empty\"; builder = \"false\"; system = \"false\"; }'");
|
assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname")
|
||||||
|
|
||||||
# Stop and start (regression test for #4989)
|
with subtest("Execute a nix command via the root shell. (regression test for #40355)"):
|
||||||
$machine->succeed("nixos-container stop $id1");
|
machine.succeed(
|
||||||
$machine->succeed("nixos-container start $id1");
|
f"nixos-container run {id1} -- nix-instantiate -E "
|
||||||
|
+ '\'derivation { name = "empty"; builder = "false"; system = "false"; }\' '
|
||||||
|
)
|
||||||
|
|
||||||
# Ensure tmpfiles are present
|
with subtest("Stop and start (regression test for #4989)"):
|
||||||
$machine->log("creating container tmpfiles");
|
machine.succeed(f"nixos-container stop {id1}")
|
||||||
$machine->succeed("nixos-container create tmpfiles --config-file ${tmpfilesContainerConfig}");
|
machine.succeed(f"nixos-container start {id1}")
|
||||||
$machine->log("created, starting…");
|
|
||||||
$machine->succeed("nixos-container start tmpfiles");
|
|
||||||
$machine->log("done starting, investigating…");
|
|
||||||
$machine->succeed("echo \$(nixos-container run tmpfiles -- systemctl is-active foo.service) | grep -q active;");
|
|
||||||
$machine->succeed("nixos-container destroy tmpfiles");
|
|
||||||
|
|
||||||
# Execute commands via the root shell.
|
with subtest("tmpfiles are present"):
|
||||||
$machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
|
machine.log("creating container tmpfiles")
|
||||||
|
machine.succeed(
|
||||||
|
"nixos-container create tmpfiles --config-file ${tmpfilesContainerConfig}"
|
||||||
|
)
|
||||||
|
machine.log("created, starting…")
|
||||||
|
machine.succeed("nixos-container start tmpfiles")
|
||||||
|
machine.log("done starting, investigating…")
|
||||||
|
machine.succeed(
|
||||||
|
"echo $(nixos-container run tmpfiles -- systemctl is-active foo.service) | grep -q active;"
|
||||||
|
)
|
||||||
|
machine.succeed("nixos-container destroy tmpfiles")
|
||||||
|
|
||||||
# Destroy the containers.
|
with subtest("Execute commands via the root shell"):
|
||||||
$machine->succeed("nixos-container destroy $id1");
|
assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname")
|
||||||
$machine->succeed("nixos-container destroy $id2");
|
|
||||||
|
|
||||||
$machine->succeed(
|
with subtest("Destroy the containers"):
|
||||||
# Check whether destruction of any container has killed important data
|
for id in id1, id2:
|
||||||
"grep -qF 'important data' /nested-bindmount/dummy",
|
machine.succeed(f"nixos-container destroy {id}")
|
||||||
# Ensure that the container path is gone
|
|
||||||
"test ! -e /var/lib/containers/$id1"
|
with subtest("Check whether destruction of any container has killed important data"):
|
||||||
);
|
machine.succeed("grep -qF 'important data' /nested-bindmount/dummy")
|
||||||
|
|
||||||
|
with subtest("Ensure that the container path is gone"):
|
||||||
|
print(machine.succeed("ls -lsa /var/lib/containers"))
|
||||||
|
machine.succeed(f"test ! -e /var/lib/containers/{id1}")
|
||||||
'';
|
'';
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
77
nixos/tests/containers-ip.nix
Normal file
77
nixos/tests/containers-ip.nix
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# Test for NixOS' container support.
|
||||||
|
|
||||||
|
let
|
||||||
|
webserverFor = hostAddress: localAddress: {
|
||||||
|
inherit hostAddress localAddress;
|
||||||
|
privateNetwork = true;
|
||||||
|
config = {
|
||||||
|
services.httpd = {
|
||||||
|
enable = true;
|
||||||
|
adminAddr = "foo@example.org";
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
|
name = "containers-ipv4-ipv6";
|
||||||
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
|
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
||||||
|
};
|
||||||
|
|
||||||
|
machine =
|
||||||
|
{ pkgs, ... }: {
|
||||||
|
imports = [ ../modules/installer/cd-dvd/channel.nix ];
|
||||||
|
virtualisation = {
|
||||||
|
writableStore = true;
|
||||||
|
memorySize = 768;
|
||||||
|
};
|
||||||
|
|
||||||
|
containers.webserver4 = webserverFor "10.231.136.1" "10.231.136.2";
|
||||||
|
containers.webserver6 = webserverFor "fc00::2" "fc00::1";
|
||||||
|
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = { nodes, ... }: ''
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def curl_host(ip):
|
||||||
|
# put [] around ipv6 addresses for curl
|
||||||
|
host = ip if ":" not in ip else f"[{ip}]"
|
||||||
|
return f"curl --fail --connect-timeout 2 http://{host}/ > /dev/null"
|
||||||
|
|
||||||
|
|
||||||
|
def get_ip(container):
|
||||||
|
# need to distinguish because show-ip won't work for ipv6
|
||||||
|
if container == "webserver4":
|
||||||
|
ip = machine.succeed(f"nixos-container show-ip {container}").rstrip()
|
||||||
|
assert ip == "${nodes.machine.config.containers.webserver4.localAddress}"
|
||||||
|
return ip
|
||||||
|
return "${nodes.machine.config.containers.webserver6.localAddress}"
|
||||||
|
|
||||||
|
|
||||||
|
for container in "webserver4", "webserver6":
|
||||||
|
assert container in machine.succeed("nixos-container list")
|
||||||
|
|
||||||
|
with subtest(f"Start container {container}"):
|
||||||
|
machine.succeed(f"nixos-container start {container}")
|
||||||
|
# wait 2s for container to start and network to be up
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Since "start" returns after the container has reached
|
||||||
|
# multi-user.target, we should now be able to access it.
|
||||||
|
|
||||||
|
ip = get_ip(container)
|
||||||
|
with subtest(f"{container} reacts to pings and HTTP requests"):
|
||||||
|
machine.succeed(f"ping -n -c1 {ip}")
|
||||||
|
machine.succeed(curl_host(ip))
|
||||||
|
|
||||||
|
with subtest(f"Stop container {container}"):
|
||||||
|
machine.succeed(f"nixos-container stop {container}")
|
||||||
|
machine.fail(curl_host(ip))
|
||||||
|
|
||||||
|
# Destroying a declarative container should fail.
|
||||||
|
machine.fail(f"nixos-container destroy {container}")
|
||||||
|
'';
|
||||||
|
})
|
|
@ -1,55 +0,0 @@
|
||||||
# Test for NixOS' container support.
|
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
|
||||||
name = "containers-ipv4";
|
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
|
||||||
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
|
||||||
};
|
|
||||||
|
|
||||||
machine =
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{ imports = [ ../modules/installer/cd-dvd/channel.nix ];
|
|
||||||
virtualisation.writableStore = true;
|
|
||||||
virtualisation.memorySize = 768;
|
|
||||||
|
|
||||||
containers.webserver =
|
|
||||||
{ privateNetwork = true;
|
|
||||||
hostAddress = "10.231.136.1";
|
|
||||||
localAddress = "10.231.136.2";
|
|
||||||
config =
|
|
||||||
{ services.httpd.enable = true;
|
|
||||||
services.httpd.adminAddr = "foo@example.org";
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
|
||||||
system.stateVersion = "18.03";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
|
||||||
};
|
|
||||||
|
|
||||||
testScript =
|
|
||||||
''
|
|
||||||
$machine->succeed("nixos-container list") =~ /webserver/ or die;
|
|
||||||
|
|
||||||
# Start the webserver container.
|
|
||||||
$machine->succeed("nixos-container start webserver");
|
|
||||||
|
|
||||||
# wait two seconds for the container to start and the network to be up
|
|
||||||
sleep 2;
|
|
||||||
|
|
||||||
# Since "start" returns after the container has reached
|
|
||||||
# multi-user.target, we should now be able to access it.
|
|
||||||
my $ip = $machine->succeed("nixos-container show-ip webserver");
|
|
||||||
chomp $ip;
|
|
||||||
$machine->succeed("ping -n -c1 $ip");
|
|
||||||
$machine->succeed("curl --fail http://$ip/ > /dev/null");
|
|
||||||
|
|
||||||
# Stop the container.
|
|
||||||
$machine->succeed("nixos-container stop webserver");
|
|
||||||
$machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null");
|
|
||||||
|
|
||||||
# Destroying a declarative container should fail.
|
|
||||||
$machine->fail("nixos-container destroy webserver");
|
|
||||||
'';
|
|
||||||
|
|
||||||
})
|
|
|
@ -1,60 +0,0 @@
|
||||||
# Test for NixOS' container support.
|
|
||||||
|
|
||||||
let
|
|
||||||
hostIp = "fc00::2";
|
|
||||||
localIp = "fc00::1";
|
|
||||||
in
|
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
|
||||||
name = "containers-ipv6";
|
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
|
||||||
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
|
||||||
};
|
|
||||||
|
|
||||||
machine =
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{ imports = [ ../modules/installer/cd-dvd/channel.nix ];
|
|
||||||
virtualisation.writableStore = true;
|
|
||||||
virtualisation.memorySize = 768;
|
|
||||||
|
|
||||||
containers.webserver =
|
|
||||||
{ privateNetwork = true;
|
|
||||||
hostAddress6 = hostIp;
|
|
||||||
localAddress6 = localIp;
|
|
||||||
config =
|
|
||||||
{ services.httpd.enable = true;
|
|
||||||
services.httpd.adminAddr = "foo@example.org";
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
|
||||||
};
|
|
||||||
|
|
||||||
testScript =
|
|
||||||
''
|
|
||||||
$machine->waitForUnit("default.target");
|
|
||||||
$machine->succeed("nixos-container list") =~ /webserver/ or die;
|
|
||||||
|
|
||||||
# Start the webserver container.
|
|
||||||
$machine->succeed("nixos-container start webserver");
|
|
||||||
|
|
||||||
# wait two seconds for the container to start and the network to be up
|
|
||||||
sleep 2;
|
|
||||||
|
|
||||||
# Since "start" returns after the container has reached
|
|
||||||
# multi-user.target, we should now be able to access it.
|
|
||||||
my $ip = "${localIp}";
|
|
||||||
chomp $ip;
|
|
||||||
$machine->succeed("ping -n -c 1 $ip");
|
|
||||||
$machine->succeed("curl --fail http://[$ip]/ > /dev/null");
|
|
||||||
|
|
||||||
# Stop the container.
|
|
||||||
$machine->succeed("nixos-container stop webserver");
|
|
||||||
$machine->fail("curl --fail --connect-timeout 2 http://[$ip]/ > /dev/null");
|
|
||||||
|
|
||||||
# Destroying a declarative container should fail.
|
|
||||||
$machine->fail("nixos-container destroy webserver");
|
|
||||||
'';
|
|
||||||
|
|
||||||
})
|
|
|
@ -1,7 +1,7 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ...} :
|
import ./make-test-python.nix ({ pkgs, lib, ...} :
|
||||||
let
|
let
|
||||||
client_base = {
|
client_base = {
|
||||||
|
|
||||||
containers.test1 = {
|
containers.test1 = {
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
config = {
|
config = {
|
||||||
|
@ -48,18 +48,25 @@ in {
|
||||||
c1System = nodes.client_c1.config.system.build.toplevel;
|
c1System = nodes.client_c1.config.system.build.toplevel;
|
||||||
c2System = nodes.client_c2.config.system.build.toplevel;
|
c2System = nodes.client_c2.config.system.build.toplevel;
|
||||||
in ''
|
in ''
|
||||||
$client->start();
|
client.start()
|
||||||
$client->waitForUnit("default.target");
|
client.wait_for_unit("default.target")
|
||||||
$client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_base ]] >&2");
|
|
||||||
|
|
||||||
$client->succeed("${c1System}/bin/switch-to-configuration test >&2");
|
assert "client_base" in client.succeed("nixos-container run test1 cat /etc/check")
|
||||||
$client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_c1 ]] >&2");
|
|
||||||
$client->succeed("systemctl status httpd -M test1 >&2");
|
|
||||||
|
|
||||||
$client->succeed("${c2System}/bin/switch-to-configuration test >&2");
|
with subtest("httpd is available after activating config1"):
|
||||||
$client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_c2 ]] >&2");
|
client.succeed(
|
||||||
$client->fail("systemctl status httpd -M test1 >&2");
|
"${c1System}/bin/switch-to-configuration test >&2",
|
||||||
$client->succeed("systemctl status nginx -M test1 >&2");
|
"[[ $(nixos-container run test1 cat /etc/check) == client_c1 ]] >&2",
|
||||||
|
"systemctl status httpd -M test1 >&2",
|
||||||
|
)
|
||||||
|
|
||||||
|
with subtest("httpd is not available any longer after switching to config2"):
|
||||||
|
client.succeed(
|
||||||
|
"${c2System}/bin/switch-to-configuration test >&2",
|
||||||
|
"[[ $(nixos-container run test1 cat /etc/check) == client_c2 ]] >&2",
|
||||||
|
"systemctl status nginx -M test1 >&2",
|
||||||
|
)
|
||||||
|
client.fail("systemctl status httpd -M test1 >&2")
|
||||||
'';
|
'';
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test for NixOS' container support.
|
# Test for NixOS' container support.
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "containers-tmpfs";
|
name = "containers-tmpfs";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ kampka ];
|
maintainers = [ kampka ];
|
||||||
|
@ -31,49 +31,63 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript =
|
testScript = ''
|
||||||
''
|
machine.wait_for_unit("default.target")
|
||||||
$machine->waitForUnit("default.target");
|
assert "tmpfs" in machine.succeed("nixos-container list")
|
||||||
$machine->succeed("nixos-container list") =~ /tmpfs/ or die;
|
|
||||||
|
|
||||||
# Start the tmpfs container.
|
with subtest("tmpfs container is up"):
|
||||||
#$machine->succeed("nixos-container status tmpfs") =~ /up/ or die;
|
assert "up" in machine.succeed("nixos-container status tmpfs")
|
||||||
|
|
||||||
# Verify that /var is mounted as a tmpfs
|
|
||||||
#$machine->succeed("nixos-container run tmpfs -- systemctl status var.mount --no-pager 2>/dev/null") =~ /What: tmpfs/ or die;
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- mountpoint -q /var 2>/dev/null");
|
|
||||||
|
|
||||||
# Verify that /var/log is mounted as a tmpfs
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- systemctl status var-log.mount --no-pager 2>/dev/null") =~ /What: tmpfs/ or die;
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- mountpoint -q /var/log 2>/dev/null");
|
|
||||||
|
|
||||||
# Verify that /some/random/path is mounted as a tmpfs
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- systemctl status some-random-path.mount --no-pager 2>/dev/null") =~ /What: tmpfs/ or die;
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- mountpoint -q /some/random/path 2>/dev/null");
|
|
||||||
|
|
||||||
# Verify that files created in the container in a non-tmpfs directory are visible on the host.
|
|
||||||
# This establishes legitimacy for the following tests
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- touch /root/test.file 2>/dev/null");
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- ls -l /root | grep -q test.file 2>/dev/null");
|
|
||||||
$machine->succeed("test -e /var/lib/containers/tmpfs/root/test.file");
|
|
||||||
|
|
||||||
|
|
||||||
# Verify that /some/random/path is writable and that files created there
|
def tmpfs_cmd(command):
|
||||||
# are not in the hosts container dir but in the tmpfs
|
return f"nixos-container run tmpfs -- {command} 2>/dev/null"
|
||||||
$machine->succeed("nixos-container run tmpfs -- touch /some/random/path/test.file 2>/dev/null");
|
|
||||||
$machine->succeed("nixos-container run tmpfs -- test -e /some/random/path/test.file 2>/dev/null");
|
|
||||||
|
|
||||||
$machine->fail("test -e /var/lib/containers/tmpfs/some/random/path/test.file");
|
|
||||||
|
|
||||||
# Verify that files created in the hosts container dir in a path where a tmpfs file system has been mounted
|
with subtest("/var is mounted as a tmpfs"):
|
||||||
# are not visible to the container as the do not exist in the tmpfs
|
machine.succeed(tmpfs_cmd("mountpoint -q /var"))
|
||||||
$machine->succeed("touch /var/lib/containers/tmpfs/var/test.file");
|
|
||||||
|
|
||||||
$machine->succeed("test -e /var/lib/containers/tmpfs/var/test.file");
|
with subtest("/var/log is mounted as a tmpfs"):
|
||||||
$machine->succeed("ls -l /var/lib/containers/tmpfs/var/ | grep -q test.file 2>/dev/null");
|
assert "What: tmpfs" in machine.succeed(
|
||||||
|
tmpfs_cmd("systemctl status var-log.mount --no-pager")
|
||||||
|
)
|
||||||
|
machine.succeed(tmpfs_cmd("mountpoint -q /var/log"))
|
||||||
|
|
||||||
$machine->fail("nixos-container run tmpfs -- ls -l /var | grep -q test.file 2>/dev/null");
|
with subtest("/some/random/path is mounted as a tmpfs"):
|
||||||
|
assert "What: tmpfs" in machine.succeed(
|
||||||
|
tmpfs_cmd("systemctl status some-random-path.mount --no-pager")
|
||||||
|
)
|
||||||
|
machine.succeed(tmpfs_cmd("mountpoint -q /some/random/path"))
|
||||||
|
|
||||||
|
with subtest(
|
||||||
|
"files created in the container in a non-tmpfs directory are visible on the host."
|
||||||
|
):
|
||||||
|
# This establishes legitimacy for the following tests
|
||||||
|
machine.succeed(
|
||||||
|
tmpfs_cmd("touch /root/test.file"),
|
||||||
|
tmpfs_cmd("ls -l /root | grep -q test.file"),
|
||||||
|
"test -e /var/lib/containers/tmpfs/root/test.file",
|
||||||
|
)
|
||||||
|
|
||||||
|
with subtest(
|
||||||
|
"/some/random/path is writable and that files created there are not "
|
||||||
|
+ "in the hosts container dir but in the tmpfs"
|
||||||
|
):
|
||||||
|
machine.succeed(
|
||||||
|
tmpfs_cmd("touch /some/random/path/test.file"),
|
||||||
|
tmpfs_cmd("test -e /some/random/path/test.file"),
|
||||||
|
)
|
||||||
|
machine.fail("test -e /var/lib/containers/tmpfs/some/random/path/test.file")
|
||||||
|
|
||||||
|
with subtest(
|
||||||
|
"files created in the hosts container dir in a path where a tmpfs "
|
||||||
|
+ "file system has been mounted are not visible to the container as "
|
||||||
|
+ "the do not exist in the tmpfs"
|
||||||
|
):
|
||||||
|
machine.succeed(
|
||||||
|
"touch /var/lib/containers/tmpfs/var/test.file",
|
||||||
|
"test -e /var/lib/containers/tmpfs/var/test.file",
|
||||||
|
"ls -l /var/lib/containers/tmpfs/var/ | grep -q test.file 2>/dev/null",
|
||||||
|
)
|
||||||
|
machine.fail(tmpfs_cmd("ls -l /var | grep -q test.file"))
|
||||||
'';
|
'';
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "deluge";
|
name = "deluge";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ flokli ];
|
maintainers = [ flokli ];
|
||||||
|
@ -45,18 +45,20 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
start_all()
|
||||||
|
|
||||||
$simple->waitForUnit("deluged");
|
simple.wait_for_unit("deluged")
|
||||||
$simple->waitForUnit("delugeweb");
|
simple.wait_for_unit("delugeweb")
|
||||||
$simple->waitForOpenPort("8112");
|
simple.wait_for_open_port("8112")
|
||||||
$declarative->waitForUnit("network.target");
|
declarative.wait_for_unit("network.target")
|
||||||
$declarative->waitUntilSucceeds("curl --fail http://simple:8112");
|
declarative.wait_until_succeeds("curl --fail http://simple:8112")
|
||||||
|
|
||||||
$declarative->waitForUnit("deluged");
|
declarative.wait_for_unit("deluged")
|
||||||
$declarative->waitForUnit("delugeweb");
|
declarative.wait_for_unit("delugeweb")
|
||||||
$declarative->waitUntilSucceeds("curl --fail http://declarative:3142");
|
declarative.wait_until_succeeds("curl --fail http://declarative:3142")
|
||||||
$declarative->succeed("deluge-console 'help' | grep -q 'rm - Remove a torrent'");
|
declarative.succeed("deluge-console 'help' | grep -q 'rm - Remove a torrent'")
|
||||||
$declarative->succeed("deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm - Remove a torrent'");
|
declarative.succeed(
|
||||||
|
"deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm - Remove a torrent'"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This test runs docker-registry and check if it works
|
# This test runs docker-registry and check if it works
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "docker-registry";
|
name = "docker-registry";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ globin ma27 ironpinguin ];
|
maintainers = [ globin ma27 ironpinguin ];
|
||||||
|
@ -28,36 +28,34 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
$client1->start();
|
client1.start()
|
||||||
$client1->waitForUnit("docker.service");
|
client1.wait_for_unit("docker.service")
|
||||||
$client1->succeed("tar cv --files-from /dev/null | docker import - scratch");
|
client1.succeed("tar cv --files-from /dev/null | docker import - scratch")
|
||||||
$client1->succeed("docker tag scratch registry:8080/scratch");
|
client1.succeed("docker tag scratch registry:8080/scratch")
|
||||||
|
|
||||||
$registry->start();
|
registry.start()
|
||||||
$registry->waitForUnit("docker-registry.service");
|
registry.wait_for_unit("docker-registry.service")
|
||||||
$registry->waitForOpenPort("8080");
|
registry.wait_for_open_port("8080")
|
||||||
$client1->succeed("docker push registry:8080/scratch");
|
client1.succeed("docker push registry:8080/scratch")
|
||||||
|
|
||||||
$client2->start();
|
client2.start()
|
||||||
$client2->waitForUnit("docker.service");
|
client2.wait_for_unit("docker.service")
|
||||||
$client2->succeed("docker pull registry:8080/scratch");
|
client2.succeed("docker pull registry:8080/scratch")
|
||||||
$client2->succeed("docker images | grep scratch");
|
client2.succeed("docker images | grep scratch")
|
||||||
|
|
||||||
$client2->succeed(
|
client2.succeed(
|
||||||
'curl -fsS -X DELETE registry:8080/v2/scratch/manifests/$(curl -fsS -I -H"Accept: application/vnd.docker.distribution.manifest.v2+json" registry:8080/v2/scratch/manifests/latest | grep Docker-Content-Digest | sed -e \'s/Docker-Content-Digest: //\' | tr -d \'\r\')'
|
"curl -fsS -X DELETE registry:8080/v2/scratch/manifests/$(curl -fsS -I -H\"Accept: application/vnd.docker.distribution.manifest.v2+json\" registry:8080/v2/scratch/manifests/latest | grep Docker-Content-Digest | sed -e 's/Docker-Content-Digest: //' | tr -d '\\r')"
|
||||||
);
|
)
|
||||||
|
|
||||||
$registry->systemctl("start docker-registry-garbage-collect.service");
|
registry.systemctl("start docker-registry-garbage-collect.service")
|
||||||
$registry->waitUntilFails("systemctl status docker-registry-garbage-collect.service");
|
registry.wait_until_fails("systemctl status docker-registry-garbage-collect.service")
|
||||||
$registry->waitForUnit("docker-registry.service");
|
registry.wait_for_unit("docker-registry.service")
|
||||||
|
|
||||||
$registry->fail(
|
registry.fail("ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data")
|
||||||
'ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data'
|
|
||||||
);
|
|
||||||
|
|
||||||
$client1->succeed("docker push registry:8080/scratch");
|
client1.succeed("docker push registry:8080/scratch")
|
||||||
$registry->succeed(
|
registry.succeed(
|
||||||
'ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data'
|
"ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data"
|
||||||
);
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix {
|
import ./make-test-python.nix {
|
||||||
name = "dovecot";
|
name = "dovecot";
|
||||||
|
|
||||||
machine = { pkgs, ... }: {
|
machine = { pkgs, ... }: {
|
||||||
|
@ -66,12 +66,12 @@ import ./make-test.nix {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
$machine->waitForUnit('postfix.service');
|
machine.wait_for_unit("postfix.service")
|
||||||
$machine->waitForUnit('dovecot2.service');
|
machine.wait_for_unit("dovecot2.service")
|
||||||
$machine->succeed('send-testmail');
|
machine.succeed("send-testmail")
|
||||||
$machine->succeed('send-lda');
|
machine.succeed("send-lda")
|
||||||
$machine->waitUntilFails('[ "$(postqueue -p)" != "Mail queue is empty" ]');
|
machine.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||||
$machine->succeed('test-imap');
|
machine.succeed("test-imap")
|
||||||
$machine->succeed('test-pop');
|
machine.succeed("test-pop")
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This test runs simple etcd cluster
|
# This test runs simple etcd cluster
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ... } : let
|
import ./make-test-python.nix ({ pkgs, ... } : let
|
||||||
|
|
||||||
runWithOpenSSL = file: cmd: pkgs.runCommand file {
|
runWithOpenSSL = file: cmd: pkgs.runCommand file {
|
||||||
buildInputs = [ pkgs.openssl ];
|
buildInputs = [ pkgs.openssl ];
|
||||||
|
@ -129,29 +129,26 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
subtest "should start etcd cluster", sub {
|
with subtest("should start etcd cluster"):
|
||||||
$node1->start();
|
node1.start()
|
||||||
$node2->start();
|
node2.start()
|
||||||
$node1->waitForUnit("etcd.service");
|
node1.wait_for_unit("etcd.service")
|
||||||
$node2->waitForUnit("etcd.service");
|
node2.wait_for_unit("etcd.service")
|
||||||
$node2->waitUntilSucceeds("etcdctl cluster-health");
|
node2.wait_until_succeeds("etcdctl cluster-health")
|
||||||
$node1->succeed("etcdctl set /foo/bar 'Hello world'");
|
node1.succeed("etcdctl set /foo/bar 'Hello world'")
|
||||||
$node2->succeed("etcdctl get /foo/bar | grep 'Hello world'");
|
node2.succeed("etcdctl get /foo/bar | grep 'Hello world'")
|
||||||
};
|
|
||||||
|
|
||||||
subtest "should add another member", sub {
|
with subtest("should add another member"):
|
||||||
$node1->waitUntilSucceeds("etcdctl member add node3 https://node3:2380");
|
node1.wait_until_succeeds("etcdctl member add node3 https://node3:2380")
|
||||||
$node3->start();
|
node3.start()
|
||||||
$node3->waitForUnit("etcd.service");
|
node3.wait_for_unit("etcd.service")
|
||||||
$node3->waitUntilSucceeds("etcdctl member list | grep 'node3'");
|
node3.wait_until_succeeds("etcdctl member list | grep 'node3'")
|
||||||
$node3->succeed("etcdctl cluster-health");
|
node3.succeed("etcdctl cluster-health")
|
||||||
};
|
|
||||||
|
|
||||||
subtest "should survive member crash", sub {
|
with subtest("should survive member crash"):
|
||||||
$node3->crash;
|
node3.crash()
|
||||||
$node1->succeed("etcdctl cluster-health");
|
node1.succeed("etcdctl cluster-health")
|
||||||
$node1->succeed("etcdctl set /foo/bar 'Hello degraded world'");
|
node1.succeed("etcdctl set /foo/bar 'Hello degraded world'")
|
||||||
$node1->succeed("etcdctl get /foo/bar | grep 'Hello degraded world'");
|
node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'")
|
||||||
};
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This test runs simple etcd node
|
# This test runs simple etcd node
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ... } : {
|
import ./make-test-python.nix ({ pkgs, ... } : {
|
||||||
name = "etcd";
|
name = "etcd";
|
||||||
|
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
|
@ -14,14 +14,12 @@ import ./make-test.nix ({ pkgs, ... } : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
subtest "should start etcd node", sub {
|
with subtest("should start etcd node"):
|
||||||
$node->start();
|
node.start()
|
||||||
$node->waitForUnit("etcd.service");
|
node.wait_for_unit("etcd.service")
|
||||||
};
|
|
||||||
|
|
||||||
subtest "should write and read some values to etcd", sub {
|
with subtest("should write and read some values to etcd"):
|
||||||
$node->succeed("etcdctl set /foo/bar 'Hello world'");
|
node.succeed("etcdctl set /foo/bar 'Hello world'")
|
||||||
$node->succeed("etcdctl get /foo/bar | grep 'Hello world'");
|
node.succeed("etcdctl get /foo/bar | grep 'Hello world'")
|
||||||
}
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ... } : {
|
import ./make-test-python.nix ({ pkgs, ... } : {
|
||||||
name = "fancontrol";
|
name = "fancontrol";
|
||||||
|
|
||||||
machine =
|
machine =
|
||||||
|
@ -19,7 +19,10 @@ import ./make-test.nix ({ pkgs, ... } : {
|
||||||
|
|
||||||
# This configuration cannot be valid for the test VM, so it's expected to get an 'outdated' error.
|
# This configuration cannot be valid for the test VM, so it's expected to get an 'outdated' error.
|
||||||
testScript = ''
|
testScript = ''
|
||||||
$machine->waitForUnit("fancontrol.service");
|
start_all()
|
||||||
$machine->waitUntilSucceeds("journalctl -eu fancontrol | grep 'Configuration appears to be outdated'");
|
machine.wait_for_unit("fancontrol.service")
|
||||||
|
machine.wait_until_succeeds(
|
||||||
|
"journalctl -eu fancontrol | grep 'Configuration appears to be outdated'"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "ferm";
|
name = "ferm";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ mic92 ];
|
maintainers = [ mic92 ];
|
||||||
|
@ -53,24 +53,22 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
|
|
||||||
testScript =
|
testScript =
|
||||||
''
|
''
|
||||||
startAll;
|
start_all()
|
||||||
|
|
||||||
$client->waitForUnit("network-online.target");
|
client.wait_for_unit("network-online.target")
|
||||||
$server->waitForUnit("ferm.service");
|
server.wait_for_unit("ferm.service")
|
||||||
$server->waitForUnit("nginx.service");
|
server.wait_for_unit("nginx.service")
|
||||||
$server->waitUntilSucceeds("ss -ntl | grep -q 80");
|
server.wait_until_succeeds("ss -ntl | grep -q 80")
|
||||||
|
|
||||||
subtest "port 80 is allowed", sub {
|
with subtest("port 80 is allowed"):
|
||||||
$client->succeed("curl --fail -g http://192.168.1.1:80/status");
|
client.succeed("curl --fail -g http://192.168.1.1:80/status")
|
||||||
$client->succeed("curl --fail -g http://[fd00::1]:80/status");
|
client.succeed("curl --fail -g http://[fd00::1]:80/status")
|
||||||
};
|
|
||||||
|
|
||||||
subtest "port 8080 is not allowed", sub {
|
with subtest("port 8080 is not allowed"):
|
||||||
$server->succeed("curl --fail -g http://192.168.1.1:8080/status");
|
server.succeed("curl --fail -g http://192.168.1.1:8080/status")
|
||||||
$server->succeed("curl --fail -g http://[fd00::1]:8080/status");
|
server.succeed("curl --fail -g http://[fd00::1]:8080/status")
|
||||||
|
|
||||||
$client->fail("curl --fail -g http://192.168.1.1:8080/status");
|
client.fail("curl --fail -g http://192.168.1.1:8080/status")
|
||||||
$client->fail("curl --fail -g http://[fd00::1]:8080/status");
|
client.fail("curl --fail -g http://[fd00::1]:8080/status")
|
||||||
};
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test the firewall module.
|
# Test the firewall module.
|
||||||
|
|
||||||
import ./make-test.nix ( { pkgs, ... } : {
|
import ./make-test-python.nix ( { pkgs, ... } : {
|
||||||
name = "firewall";
|
name = "firewall";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ eelco ];
|
maintainers = [ eelco ];
|
||||||
|
@ -36,30 +36,30 @@ import ./make-test.nix ( { pkgs, ... } : {
|
||||||
testScript = { nodes, ... }: let
|
testScript = { nodes, ... }: let
|
||||||
newSystem = nodes.walled2.config.system.build.toplevel;
|
newSystem = nodes.walled2.config.system.build.toplevel;
|
||||||
in ''
|
in ''
|
||||||
$walled->start;
|
start_all()
|
||||||
$attacker->start;
|
|
||||||
|
|
||||||
$walled->waitForUnit("firewall");
|
walled.wait_for_unit("firewall")
|
||||||
$walled->waitForUnit("httpd");
|
walled.wait_for_unit("httpd")
|
||||||
$attacker->waitForUnit("network.target");
|
attacker.wait_for_unit("network.target")
|
||||||
|
|
||||||
# Local connections should still work.
|
# Local connections should still work.
|
||||||
$walled->succeed("curl -v http://localhost/ >&2");
|
walled.succeed("curl -v http://localhost/ >&2")
|
||||||
|
|
||||||
# Connections to the firewalled machine should fail, but ping should succeed.
|
# Connections to the firewalled machine should fail, but ping should succeed.
|
||||||
$attacker->fail("curl --fail --connect-timeout 2 http://walled/ >&2");
|
attacker.fail("curl --fail --connect-timeout 2 http://walled/ >&2")
|
||||||
$attacker->succeed("ping -c 1 walled >&2");
|
attacker.succeed("ping -c 1 walled >&2")
|
||||||
|
|
||||||
# Outgoing connections/pings should still work.
|
# Outgoing connections/pings should still work.
|
||||||
$walled->succeed("curl -v http://attacker/ >&2");
|
walled.succeed("curl -v http://attacker/ >&2")
|
||||||
$walled->succeed("ping -c 1 attacker >&2");
|
walled.succeed("ping -c 1 attacker >&2")
|
||||||
|
|
||||||
# If we stop the firewall, then connections should succeed.
|
# If we stop the firewall, then connections should succeed.
|
||||||
$walled->stopJob("firewall");
|
walled.stop_job("firewall")
|
||||||
$attacker->succeed("curl -v http://walled/ >&2");
|
attacker.succeed("curl -v http://walled/ >&2")
|
||||||
|
|
||||||
# Check whether activation of a new configuration reloads the firewall.
|
# Check whether activation of a new configuration reloads the firewall.
|
||||||
$walled->succeed("${newSystem}/bin/switch-to-configuration test 2>&1" .
|
walled.succeed(
|
||||||
" | grep -qF firewall.service");
|
"${newSystem}/bin/switch-to-configuration test 2>&1 | grep -qF firewall.service"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ... }: {
|
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
name = "fish";
|
name = "fish";
|
||||||
|
|
||||||
machine =
|
machine =
|
||||||
|
@ -14,8 +14,11 @@ import ./make-test.nix ({ pkgs, ... }: {
|
||||||
|
|
||||||
testScript =
|
testScript =
|
||||||
''
|
''
|
||||||
$machine->waitForFile("/etc/fish/generated_completions/coreutils.fish");
|
start_all()
|
||||||
$machine->waitForFile("/etc/fish/generated_completions/kill.fish");
|
machine.wait_for_file("/etc/fish/generated_completions/coreutils.fish")
|
||||||
$machine->succeed("fish -ic 'echo \$fish_complete_path' | grep -q '/share/fish/completions /etc/fish/generated_completions /root/.local/share/fish/generated_completions\$'");
|
machine.wait_for_file("/etc/fish/generated_completions/kill.fish")
|
||||||
|
machine.succeed(
|
||||||
|
"fish -ic 'echo $fish_complete_path' | grep -q '/share/fish/completions /etc/fish/generated_completions /root/.local/share/fish/generated_completions$'"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ... }: {
|
import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
||||||
name = "fluentd";
|
name = "fluentd";
|
||||||
|
|
||||||
machine = { pkgs, ... }: {
|
machine = { pkgs, ... }: {
|
||||||
|
@ -33,14 +33,17 @@ import ./make-test.nix ({ pkgs, lib, ... }: {
|
||||||
inherit testMessage;
|
inherit testMessage;
|
||||||
});
|
});
|
||||||
in ''
|
in ''
|
||||||
$machine->start;
|
machine.start()
|
||||||
$machine->waitForUnit('fluentd.service');
|
machine.wait_for_unit("fluentd.service")
|
||||||
$machine->waitForOpenPort(9880);
|
machine.wait_for_open_port(9880)
|
||||||
|
|
||||||
$machine->succeed("curl -fsSL -X POST -H 'Content-type: application/json' -d @${payload} http://localhost:9880/test.tag");
|
machine.succeed(
|
||||||
|
"curl -fsSL -X POST -H 'Content-type: application/json' -d @${payload} http://localhost:9880/test.tag"
|
||||||
|
)
|
||||||
|
|
||||||
$machine->succeed("systemctl stop fluentd"); # blocking flush
|
# blocking flush
|
||||||
|
machine.succeed("systemctl stop fluentd")
|
||||||
|
|
||||||
$machine->succeed("grep '${testMessage}' /tmp/current-log");
|
machine.succeed("grep '${testMessage}' /tmp/current-log")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
let
|
let
|
||||||
initialRootPassword = "notproduction";
|
initialRootPassword = "notproduction";
|
||||||
in
|
in
|
||||||
import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
|
import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; {
|
||||||
name = "gitlab";
|
name = "gitlab";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ globin ];
|
maintainers = [ globin ];
|
||||||
|
@ -63,21 +63,35 @@ import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
|
||||||
});
|
});
|
||||||
in
|
in
|
||||||
''
|
''
|
||||||
$gitlab->start();
|
gitlab.start()
|
||||||
$gitlab->waitForUnit("gitaly.service");
|
gitlab.wait_for_unit("gitaly.service")
|
||||||
$gitlab->waitForUnit("gitlab-workhorse.service");
|
gitlab.wait_for_unit("gitlab-workhorse.service")
|
||||||
$gitlab->waitForUnit("gitlab.service");
|
gitlab.wait_for_unit("gitlab.service")
|
||||||
$gitlab->waitForUnit("gitlab-sidekiq.service");
|
gitlab.wait_for_unit("gitlab-sidekiq.service")
|
||||||
$gitlab->waitForFile("/var/gitlab/state/tmp/sockets/gitlab.socket");
|
gitlab.wait_for_file("/var/gitlab/state/tmp/sockets/gitlab.socket")
|
||||||
$gitlab->waitUntilSucceeds("curl -sSf http://gitlab/users/sign_in");
|
gitlab.wait_until_succeeds("curl -sSf http://gitlab/users/sign_in")
|
||||||
$gitlab->succeed("curl -isSf http://gitlab | grep -i location | grep -q http://gitlab/users/sign_in");
|
gitlab.succeed(
|
||||||
$gitlab->succeed("${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2");
|
"curl -isSf http://gitlab | grep -i location | grep -q http://gitlab/users/sign_in"
|
||||||
$gitlab->succeed("echo \"Authorization: Bearer \$(curl -X POST -H 'Content-Type: application/json' -d @${auth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers");
|
)
|
||||||
$gitlab->succeed("curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createProject} http://gitlab/api/v4/projects");
|
gitlab.succeed(
|
||||||
$gitlab->succeed("curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${putFile} http://gitlab/api/v4/projects/1/repository/files/some-file.txt");
|
"${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2"
|
||||||
$gitlab->succeed("curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.gz > /tmp/archive.tar.gz");
|
)
|
||||||
$gitlab->succeed("curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.bz2 > /tmp/archive.tar.bz2");
|
gitlab.succeed(
|
||||||
$gitlab->succeed("test -s /tmp/archive.tar.gz");
|
"echo \"Authorization: Bearer \$(curl -X POST -H 'Content-Type: application/json' -d @${auth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers"
|
||||||
$gitlab->succeed("test -s /tmp/archive.tar.bz2");
|
)
|
||||||
|
gitlab.succeed(
|
||||||
|
"curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createProject} http://gitlab/api/v4/projects"
|
||||||
|
)
|
||||||
|
gitlab.succeed(
|
||||||
|
"curl -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${putFile} http://gitlab/api/v4/projects/1/repository/files/some-file.txt"
|
||||||
|
)
|
||||||
|
gitlab.succeed(
|
||||||
|
"curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.gz > /tmp/archive.tar.gz"
|
||||||
|
)
|
||||||
|
gitlab.succeed(
|
||||||
|
"curl -H @/tmp/headers http://gitlab/api/v4/projects/1/repository/archive.tar.bz2 > /tmp/archive.tar.bz2"
|
||||||
|
)
|
||||||
|
gitlab.succeed("test -s /tmp/archive.tar.gz")
|
||||||
|
gitlab.succeed("test -s /tmp/archive.tar.bz2")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ...}:
|
import ./make-test-python.nix ({ pkgs, ...}:
|
||||||
|
|
||||||
let
|
let
|
||||||
adminPrivateKey = pkgs.writeText "id_ed25519" ''
|
adminPrivateKey = pkgs.writeText "id_ed25519" ''
|
||||||
|
@ -43,7 +43,7 @@ let
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJZNonUP1ePHLrvn0W9D2hdN6zWWZYFyJc+QR6pOKQEw bob@client
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJZNonUP1ePHLrvn0W9D2hdN6zWWZYFyJc+QR6pOKQEw bob@client
|
||||||
'';
|
'';
|
||||||
|
|
||||||
gitoliteAdminConfSnippet = ''
|
gitoliteAdminConfSnippet = pkgs.writeText "gitolite-admin-conf-snippet" ''
|
||||||
repo alice-project
|
repo alice-project
|
||||||
RW+ = alice
|
RW+ = alice
|
||||||
'';
|
'';
|
||||||
|
@ -85,55 +85,54 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
start_all()
|
||||||
|
|
||||||
subtest "can setup ssh keys on system", sub {
|
with subtest("can setup ssh keys on system"):
|
||||||
$client->mustSucceed("mkdir -p ~root/.ssh");
|
client.succeed(
|
||||||
$client->mustSucceed("cp ${adminPrivateKey} ~root/.ssh/id_ed25519");
|
"mkdir -p ~root/.ssh",
|
||||||
$client->mustSucceed("chmod 600 ~root/.ssh/id_ed25519");
|
"cp ${adminPrivateKey} ~root/.ssh/id_ed25519",
|
||||||
|
"chmod 600 ~root/.ssh/id_ed25519",
|
||||||
|
)
|
||||||
|
client.succeed(
|
||||||
|
"sudo -u alice mkdir -p ~alice/.ssh",
|
||||||
|
"sudo -u alice cp ${alicePrivateKey} ~alice/.ssh/id_ed25519",
|
||||||
|
"sudo -u alice chmod 600 ~alice/.ssh/id_ed25519",
|
||||||
|
)
|
||||||
|
client.succeed(
|
||||||
|
"sudo -u bob mkdir -p ~bob/.ssh",
|
||||||
|
"sudo -u bob cp ${bobPrivateKey} ~bob/.ssh/id_ed25519",
|
||||||
|
"sudo -u bob chmod 600 ~bob/.ssh/id_ed25519",
|
||||||
|
)
|
||||||
|
|
||||||
$client->mustSucceed("sudo -u alice mkdir -p ~alice/.ssh");
|
with subtest("gitolite server starts"):
|
||||||
$client->mustSucceed("sudo -u alice cp ${alicePrivateKey} ~alice/.ssh/id_ed25519");
|
server.wait_for_unit("gitolite-init.service")
|
||||||
$client->mustSucceed("sudo -u alice chmod 600 ~alice/.ssh/id_ed25519");
|
server.wait_for_unit("sshd.service")
|
||||||
|
client.succeed("ssh gitolite@server info")
|
||||||
|
|
||||||
$client->mustSucceed("sudo -u bob mkdir -p ~bob/.ssh");
|
with subtest("admin can clone and configure gitolite-admin.git"):
|
||||||
$client->mustSucceed("sudo -u bob cp ${bobPrivateKey} ~bob/.ssh/id_ed25519");
|
client.succeed(
|
||||||
$client->mustSucceed("sudo -u bob chmod 600 ~bob/.ssh/id_ed25519");
|
"git clone gitolite@server:gitolite-admin.git",
|
||||||
};
|
"git config --global user.name 'System Administrator'",
|
||||||
|
"git config --global user.email root\@domain.example",
|
||||||
|
"cp ${alicePublicKey} gitolite-admin/keydir/alice.pub",
|
||||||
|
"cp ${bobPublicKey} gitolite-admin/keydir/bob.pub",
|
||||||
|
"(cd gitolite-admin && git add . && git commit -m 'Add keys for alice, bob' && git push)",
|
||||||
|
"cat ${gitoliteAdminConfSnippet} >> gitolite-admin/conf/gitolite.conf",
|
||||||
|
"(cd gitolite-admin && git add . && git commit -m 'Add repo for alice' && git push)",
|
||||||
|
)
|
||||||
|
|
||||||
subtest "gitolite server starts", sub {
|
with subtest("non-admins cannot clone gitolite-admin.git"):
|
||||||
$server->waitForUnit("gitolite-init.service");
|
client.fail("sudo -i -u alice git clone gitolite@server:gitolite-admin.git")
|
||||||
$server->waitForUnit("sshd.service");
|
client.fail("sudo -i -u bob git clone gitolite@server:gitolite-admin.git")
|
||||||
$client->mustSucceed('ssh gitolite@server info');
|
|
||||||
};
|
|
||||||
|
|
||||||
subtest "admin can clone and configure gitolite-admin.git", sub {
|
with subtest("non-admins can clone testing.git"):
|
||||||
$client->mustSucceed('git clone gitolite@server:gitolite-admin.git');
|
client.succeed("sudo -i -u alice git clone gitolite@server:testing.git")
|
||||||
$client->mustSucceed("git config --global user.name 'System Administrator'");
|
client.succeed("sudo -i -u bob git clone gitolite@server:testing.git")
|
||||||
$client->mustSucceed("git config --global user.email root\@domain.example");
|
|
||||||
$client->mustSucceed("cp ${alicePublicKey} gitolite-admin/keydir/alice.pub");
|
|
||||||
$client->mustSucceed("cp ${bobPublicKey} gitolite-admin/keydir/bob.pub");
|
|
||||||
$client->mustSucceed('(cd gitolite-admin && git add . && git commit -m "Add keys for alice, bob" && git push)');
|
|
||||||
$client->mustSucceed("printf '${gitoliteAdminConfSnippet}' >> gitolite-admin/conf/gitolite.conf");
|
|
||||||
$client->mustSucceed('(cd gitolite-admin && git add . && git commit -m "Add repo for alice" && git push)');
|
|
||||||
};
|
|
||||||
|
|
||||||
subtest "non-admins cannot clone gitolite-admin.git", sub {
|
with subtest("alice can clone alice-project.git"):
|
||||||
$client->mustFail('sudo -i -u alice git clone gitolite@server:gitolite-admin.git');
|
client.succeed("sudo -i -u alice git clone gitolite@server:alice-project.git")
|
||||||
$client->mustFail('sudo -i -u bob git clone gitolite@server:gitolite-admin.git');
|
|
||||||
};
|
|
||||||
|
|
||||||
subtest "non-admins can clone testing.git", sub {
|
with subtest("bob cannot clone alice-project.git"):
|
||||||
$client->mustSucceed('sudo -i -u alice git clone gitolite@server:testing.git');
|
client.fail("sudo -i -u bob git clone gitolite@server:alice-project.git")
|
||||||
$client->mustSucceed('sudo -i -u bob git clone gitolite@server:testing.git');
|
|
||||||
};
|
|
||||||
|
|
||||||
subtest "alice can clone alice-project.git", sub {
|
|
||||||
$client->mustSucceed('sudo -i -u alice git clone gitolite@server:alice-project.git');
|
|
||||||
};
|
|
||||||
|
|
||||||
subtest "bob cannot clone alice-project.git", sub {
|
|
||||||
$client->mustFail('sudo -i -u bob git clone gitolite@server:alice-project.git');
|
|
||||||
};
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ ... } :
|
import ./make-test-python.nix ({pkgs, lib, ...}:
|
||||||
|
|
||||||
let
|
let
|
||||||
client = { pkgs, ... } : {
|
client = { pkgs, ... } : {
|
||||||
|
@ -39,27 +39,29 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
$server1->waitForUnit("glusterd.service");
|
server1.wait_for_unit("glusterd.service")
|
||||||
$server2->waitForUnit("glusterd.service");
|
server2.wait_for_unit("glusterd.service")
|
||||||
|
|
||||||
|
server1.wait_until_succeeds("gluster peer status")
|
||||||
|
server2.wait_until_succeeds("gluster peer status")
|
||||||
|
|
||||||
# establish initial contact
|
# establish initial contact
|
||||||
$server1->succeed("sleep 2");
|
server1.succeed("gluster peer probe server2")
|
||||||
$server1->succeed("gluster peer probe server2");
|
server1.succeed("gluster peer probe server1")
|
||||||
$server1->succeed("gluster peer probe server1");
|
|
||||||
|
|
||||||
$server1->succeed("gluster peer status | grep Connected");
|
server1.succeed("gluster peer status | grep Connected")
|
||||||
|
|
||||||
# create volumes
|
# create volumes
|
||||||
$server1->succeed("mkdir -p /data/vg0");
|
server1.succeed("mkdir -p /data/vg0")
|
||||||
$server2->succeed("mkdir -p /data/vg0");
|
server2.succeed("mkdir -p /data/vg0")
|
||||||
$server1->succeed("gluster volume create gv0 server1:/data/vg0 server2:/data/vg0");
|
server1.succeed("gluster volume create gv0 server1:/data/vg0 server2:/data/vg0")
|
||||||
$server1->succeed("gluster volume start gv0");
|
server1.succeed("gluster volume start gv0")
|
||||||
|
|
||||||
# test clients
|
# test clients
|
||||||
$client1->waitForUnit("gluster.mount");
|
client1.wait_for_unit("gluster.mount")
|
||||||
$client2->waitForUnit("gluster.mount");
|
client2.wait_for_unit("gluster.mount")
|
||||||
|
|
||||||
$client1->succeed("echo test > /gluster/file1");
|
client1.succeed("echo test > /gluster/file1")
|
||||||
$client2->succeed("grep test /gluster/file1");
|
client2.succeed("grep test /gluster/file1")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import ../make-test.nix ({ pkgs, ... } :
|
import ../make-test-python.nix ({ pkgs, ... } :
|
||||||
let
|
let
|
||||||
inherit (import ./../ssh-keys.nix pkgs)
|
inherit (import ./../ssh-keys.nix pkgs)
|
||||||
snakeOilPrivateKey snakeOilPublicKey;
|
snakeOilPrivateKey snakeOilPublicKey;
|
||||||
|
|
||||||
|
# don't check host keys or known hosts, use the snakeoil ssh key
|
||||||
|
ssh-config = builtins.toFile "ssh.conf" ''
|
||||||
|
UserKnownHostsFile=/dev/null
|
||||||
|
StrictHostKeyChecking=no
|
||||||
|
IdentityFile=~/.ssh/id_snakeoil
|
||||||
|
'';
|
||||||
in {
|
in {
|
||||||
name = "google-oslogin";
|
name = "google-oslogin";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
|
@ -15,38 +22,49 @@ in {
|
||||||
client = { ... }: {};
|
client = { ... }: {};
|
||||||
};
|
};
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
start_all()
|
||||||
|
|
||||||
$server->waitForUnit("mock-google-metadata.service");
|
server.wait_for_unit("mock-google-metadata.service")
|
||||||
$server->waitForOpenPort(80);
|
server.wait_for_open_port(80)
|
||||||
|
|
||||||
# mockserver should return a non-expired ssh key for both mockuser and mockadmin
|
# mockserver should return a non-expired ssh key for both mockuser and mockadmin
|
||||||
$server->succeed('${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys mockuser | grep -q "${snakeOilPublicKey}"');
|
server.succeed(
|
||||||
$server->succeed('${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys mockadmin | grep -q "${snakeOilPublicKey}"');
|
'${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys mockuser | grep -q "${snakeOilPublicKey}"'
|
||||||
|
)
|
||||||
|
server.succeed(
|
||||||
|
'${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys mockadmin | grep -q "${snakeOilPublicKey}"'
|
||||||
|
)
|
||||||
|
|
||||||
# install snakeoil ssh key on the client
|
# install snakeoil ssh key on the client, and provision .ssh/config file
|
||||||
$client->succeed("mkdir -p ~/.ssh");
|
client.succeed("mkdir -p ~/.ssh")
|
||||||
$client->succeed("cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil");
|
client.succeed(
|
||||||
$client->succeed("chmod 600 ~/.ssh/id_snakeoil");
|
"cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil"
|
||||||
|
)
|
||||||
|
client.succeed("chmod 600 ~/.ssh/id_snakeoil")
|
||||||
|
client.succeed("cp ${ssh-config} ~/.ssh/config")
|
||||||
|
|
||||||
$client->waitForUnit("network.target");
|
client.wait_for_unit("network.target")
|
||||||
$server->waitForUnit("sshd.service");
|
server.wait_for_unit("sshd.service")
|
||||||
|
|
||||||
# we should not be able to connect as non-existing user
|
# we should not be able to connect as non-existing user
|
||||||
$client->fail("ssh -o User=ghost -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server -i ~/.ssh/id_snakeoil 'true'");
|
client.fail("ssh ghost@server 'true'")
|
||||||
|
|
||||||
# we should be able to connect as mockuser
|
# we should be able to connect as mockuser
|
||||||
$client->succeed("ssh -o User=mockuser -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server -i ~/.ssh/id_snakeoil 'true'");
|
client.succeed("ssh mockuser@server 'true'")
|
||||||
# but we shouldn't be able to sudo
|
# but we shouldn't be able to sudo
|
||||||
$client->fail("ssh -o User=mockuser -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server -i ~/.ssh/id_snakeoil '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'");
|
client.fail(
|
||||||
|
"ssh mockuser@server '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'"
|
||||||
|
)
|
||||||
|
|
||||||
# we should also be able to log in as mockadmin
|
# we should also be able to log in as mockadmin
|
||||||
$client->succeed("ssh -o User=mockadmin -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server -i ~/.ssh/id_snakeoil 'true'");
|
client.succeed("ssh mockadmin@server 'true'")
|
||||||
# pam_oslogin_admin.so should now have generated a sudoers file
|
# pam_oslogin_admin.so should now have generated a sudoers file
|
||||||
$server->succeed("find /run/google-sudoers.d | grep -q '/run/google-sudoers.d/mockadmin'");
|
server.succeed("find /run/google-sudoers.d | grep -q '/run/google-sudoers.d/mockadmin'")
|
||||||
|
|
||||||
# and we should be able to sudo
|
# and we should be able to sudo
|
||||||
$client->succeed("ssh -o User=mockadmin -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server -i ~/.ssh/id_snakeoil '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'");
|
client.succeed(
|
||||||
|
"ssh mockadmin@server '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ...} : {
|
import ./make-test-python.nix ({ pkgs, lib, ...} : {
|
||||||
name = "gotify-server";
|
name = "gotify-server";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ ma27 ];
|
maintainers = [ ma27 ];
|
||||||
|
@ -14,32 +14,32 @@ import ./make-test.nix ({ pkgs, lib, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
machine.start()
|
||||||
|
|
||||||
$machine->waitForUnit("gotify-server");
|
machine.wait_for_unit("gotify-server.service")
|
||||||
$machine->waitForOpenPort(3000);
|
machine.wait_for_open_port(3000)
|
||||||
|
|
||||||
my $token = $machine->succeed(
|
token = machine.succeed(
|
||||||
"curl --fail -sS -X POST localhost:3000/application -F name=nixos " .
|
"curl --fail -sS -X POST localhost:3000/application -F name=nixos "
|
||||||
'-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" ' .
|
+ '-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" '
|
||||||
'| jq .token | xargs echo -n'
|
+ "| jq .token | xargs echo -n"
|
||||||
);
|
)
|
||||||
|
|
||||||
my $usertoken = $machine->succeed(
|
usertoken = machine.succeed(
|
||||||
"curl --fail -sS -X POST localhost:3000/client -F name=nixos " .
|
"curl --fail -sS -X POST localhost:3000/client -F name=nixos "
|
||||||
'-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" ' .
|
+ '-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" '
|
||||||
'| jq .token | xargs echo -n'
|
+ "| jq .token | xargs echo -n"
|
||||||
);
|
)
|
||||||
|
|
||||||
$machine->succeed(
|
machine.succeed(
|
||||||
"curl --fail -sS -X POST 'localhost:3000/message?token=$token' -H 'Accept: application/json' " .
|
f"curl --fail -sS -X POST 'localhost:3000/message?token={token}' -H 'Accept: application/json' "
|
||||||
'-F title=Gotify -F message=Works'
|
+ "-F title=Gotify -F message=Works"
|
||||||
);
|
)
|
||||||
|
|
||||||
my $title = $machine->succeed(
|
title = machine.succeed(
|
||||||
"curl --fail -sS 'localhost:3000/message?since=0&token=$usertoken' | jq '.messages|.[0]|.title' | xargs echo -n"
|
f"curl --fail -sS 'localhost:3000/message?since=0&token={usertoken}' | jq '.messages|.[0]|.title' | xargs echo -n"
|
||||||
);
|
)
|
||||||
|
|
||||||
$title eq "Gotify" or die "Wrong title ($title), expected 'Gotify'!";
|
assert title == "Gotify"
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ... }: {
|
import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
||||||
name = "graylog";
|
name = "graylog";
|
||||||
meta.maintainers = with lib.maintainers; [ ma27 ];
|
meta.maintainers = with lib.maintainers; [ ma27 ];
|
||||||
|
|
||||||
|
@ -64,48 +64,52 @@ import ./make-test.nix ({ pkgs, lib, ... }: {
|
||||||
facility = "Test";
|
facility = "Test";
|
||||||
});
|
});
|
||||||
in ''
|
in ''
|
||||||
$machine->start;
|
machine.start()
|
||||||
$machine->waitForUnit("graylog.service");
|
machine.wait_for_unit("graylog.service")
|
||||||
$machine->waitForOpenPort(9000);
|
machine.wait_for_open_port(9000)
|
||||||
$machine->succeed("curl -sSfL http://127.0.0.1:9000/");
|
machine.succeed("curl -sSfL http://127.0.0.1:9000/")
|
||||||
|
|
||||||
my $session = $machine->succeed("curl -X POST "
|
session = machine.succeed(
|
||||||
. "-sSfL http://127.0.0.1:9000/api/system/sessions "
|
"curl -X POST "
|
||||||
. "-d \$(cat ${payloads.login}) "
|
+ "-sSfL http://127.0.0.1:9000/api/system/sessions "
|
||||||
. "-H 'Content-Type: application/json' "
|
+ "-d $(cat ${payloads.login}) "
|
||||||
. "-H 'Accept: application/json' "
|
+ "-H 'Content-Type: application/json' "
|
||||||
. "-H 'x-requested-by: cli' "
|
+ "-H 'Accept: application/json' "
|
||||||
. "| jq .session_id | xargs echo"
|
+ "-H 'x-requested-by: cli' "
|
||||||
);
|
+ "| jq .session_id | xargs echo"
|
||||||
|
).rstrip()
|
||||||
|
|
||||||
chomp($session);
|
machine.succeed(
|
||||||
|
"curl -X POST "
|
||||||
|
+ f"-sSfL http://127.0.0.1:9000/api/system/inputs -u {session}:session "
|
||||||
|
+ '-d $(cat ${payloads.input} | sed -e "s,@node@,$(cat /var/lib/graylog/server/node-id),") '
|
||||||
|
+ "-H 'Accept: application/json' "
|
||||||
|
+ "-H 'Content-Type: application/json' "
|
||||||
|
+ "-H 'x-requested-by: cli' "
|
||||||
|
)
|
||||||
|
|
||||||
$machine->succeed("curl -X POST "
|
machine.wait_until_succeeds(
|
||||||
. "-sSfL http://127.0.0.1:9000/api/system/inputs -u $session:session "
|
"test \"$(curl -sSfL 'http://127.0.0.1:9000/api/cluster/inputstates' "
|
||||||
. "-d \$(cat ${payloads.input} | sed -e \"s,\@node\@,\$(cat /var/lib/graylog/server/node-id),\") "
|
+ f"-u {session}:session "
|
||||||
. "-H 'Accept: application/json' "
|
+ "-H 'Accept: application/json' "
|
||||||
. "-H 'Content-Type: application/json' "
|
+ "-H 'Content-Type: application/json' "
|
||||||
. "-H 'x-requested-by: cli' "
|
+ "-H 'x-requested-by: cli'"
|
||||||
);
|
+ "| jq 'to_entries[]|.value|.[0]|.state' | xargs echo"
|
||||||
|
+ ')" = "RUNNING"'
|
||||||
|
)
|
||||||
|
|
||||||
$machine->waitUntilSucceeds("test \"\$(curl -sSfL 'http://127.0.0.1:9000/api/cluster/inputstates' "
|
machine.succeed(
|
||||||
. "-u $session:session "
|
"echo -n $(cat ${payloads.gelf_message}) | nc -w10 -u 127.0.0.1 12201"
|
||||||
. "-H 'Accept: application/json' "
|
)
|
||||||
. "-H 'Content-Type: application/json' "
|
|
||||||
. "-H 'x-requested-by: cli'"
|
|
||||||
. "| jq 'to_entries[]|.value|.[0]|.state' | xargs echo"
|
|
||||||
. ")\" = \"RUNNING\""
|
|
||||||
);
|
|
||||||
|
|
||||||
$machine->succeed("echo -n \$(cat ${payloads.gelf_message}) | nc -w10 -u 127.0.0.1 12201");
|
machine.succeed(
|
||||||
|
'test "$(curl -X GET '
|
||||||
$machine->succeed("test \"\$(curl -X GET "
|
+ "-sSfL 'http://127.0.0.1:9000/api/search/universal/relative?query=*' "
|
||||||
. "-sSfL 'http://127.0.0.1:9000/api/search/universal/relative?query=*' "
|
+ f"-u {session}:session "
|
||||||
. "-u $session:session "
|
+ "-H 'Accept: application/json' "
|
||||||
. "-H 'Accept: application/json' "
|
+ "-H 'Content-Type: application/json' "
|
||||||
. "-H 'Content-Type: application/json' "
|
+ "-H 'x-requested-by: cli'"
|
||||||
. "-H 'x-requested-by: cli'"
|
+ ' | jq \'.total_results\' | xargs echo)" = "1"'
|
||||||
. " | jq '.total_results' | xargs echo)\" = \"1\""
|
)
|
||||||
);
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ... }:
|
import ./make-test-python.nix ({ pkgs, ... }:
|
||||||
let
|
let
|
||||||
# Download Big Buck Bunny example, licensed under CC Attribution 3.0.
|
# Download Big Buck Bunny example, licensed under CC Attribution 3.0.
|
||||||
testMkv = pkgs.fetchurl {
|
testMkv = pkgs.fetchurl {
|
||||||
|
@ -19,7 +19,13 @@ in {
|
||||||
testScript = ''
|
testScript = ''
|
||||||
# Test MP4 and MKV transcoding. Since this is a short clip, transcoding typically
|
# Test MP4 and MKV transcoding. Since this is a short clip, transcoding typically
|
||||||
# only takes a few seconds.
|
# only takes a few seconds.
|
||||||
$machine->succeed("HandBrakeCLI -i ${testMkv} -o test.mp4 -e x264 -q 20 -B 160");
|
start_all()
|
||||||
$machine->succeed("HandBrakeCLI -i ${testMkv} -o test.mkv -e x264 -q 20 -B 160");
|
|
||||||
|
machine.succeed(
|
||||||
|
"HandBrakeCLI -i ${testMkv} -o test.mp4 -e x264 -q 20 -B 160"
|
||||||
|
)
|
||||||
|
machine.succeed(
|
||||||
|
"HandBrakeCLI -i ${testMkv} -o test.mkv -e x264 -q 20 -B 160"
|
||||||
|
)
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test whether hibernation from partition works.
|
# Test whether hibernation from partition works.
|
||||||
|
|
||||||
import ./make-test.nix (pkgs: {
|
import ./make-test-python.nix (pkgs: {
|
||||||
name = "hibernate";
|
name = "hibernate";
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
|
@ -28,16 +28,17 @@ import ./make-test.nix (pkgs: {
|
||||||
|
|
||||||
testScript =
|
testScript =
|
||||||
''
|
''
|
||||||
$machine->waitForUnit("multi-user.target");
|
machine.start()
|
||||||
$machine->succeed("mkswap /dev/vdb");
|
machine.wait_for_unit("multi-user.target")
|
||||||
$machine->succeed("swapon -a");
|
machine.succeed("mkswap /dev/vdb")
|
||||||
$machine->startJob("listener");
|
machine.succeed("swapon -a")
|
||||||
$machine->waitForOpenPort(4444);
|
machine.start_job("listener")
|
||||||
$machine->succeed("systemctl hibernate &");
|
machine.wait_for_open_port(4444)
|
||||||
$machine->waitForShutdown;
|
machine.succeed("systemctl hibernate &")
|
||||||
$probe->waitForUnit("multi-user.target");
|
machine.wait_for_shutdown()
|
||||||
$machine->start;
|
probe.wait_for_unit("multi-user.target")
|
||||||
$probe->waitUntilSucceeds("echo test | nc machine 4444 -N");
|
machine.start()
|
||||||
|
probe.wait_until_succeeds("echo test | nc machine 4444 -N")
|
||||||
'';
|
'';
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Test whether `houndd` indexes nixpkgs
|
# Test whether `houndd` indexes nixpkgs
|
||||||
import ./make-test.nix ({ pkgs, ... } : {
|
import ./make-test-python.nix ({ pkgs, ... } : {
|
||||||
name = "hound";
|
name = "hound";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ grahamc ];
|
maintainers = [ grahamc ];
|
||||||
|
@ -46,13 +46,14 @@ import ./make-test.nix ({ pkgs, ... } : {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript =
|
testScript = ''
|
||||||
'' startAll;
|
start_all()
|
||||||
|
|
||||||
$machine->waitForUnit("network.target");
|
machine.wait_for_unit("network.target")
|
||||||
$machine->waitForUnit("hound.service");
|
machine.wait_for_unit("hound.service")
|
||||||
$machine->waitForOpenPort(6080);
|
machine.wait_for_open_port(6080)
|
||||||
$machine->waitUntilSucceeds('curl http://127.0.0.1:6080/api/v1/search\?stats\=fosho\&repos\=\*\&rng=%3A20\&q\=hi\&files\=\&i=nope | grep "Filename" | grep "hello"');
|
machine.wait_until_succeeds(
|
||||||
|
"curl http://127.0.0.1:6080/api/v1/search\?stats\=fosho\&repos\=\*\&rng=%3A20\&q\=hi\&files\=\&i=nope | grep 'Filename' | grep 'hello'"
|
||||||
'';
|
)
|
||||||
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, ... }: {
|
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
name = "icingaweb2";
|
name = "icingaweb2";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ das_j ];
|
maintainers = [ das_j ];
|
||||||
|
@ -64,8 +64,8 @@ import ./make-test.nix ({ pkgs, ... }: {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll();
|
start_all()
|
||||||
$icingaweb2->waitForUnit("multi-user.target");
|
icingaweb2.wait_for_unit("multi-user.target")
|
||||||
$icingaweb2->succeed("curl -sSf http://icingaweb2/authentication/login");
|
icingaweb2.succeed("curl -sSf http://icingaweb2/authentication/login")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ... }:
|
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
|
@ -18,17 +18,16 @@ with lib;
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
subtest "machine with iftop enabled", sub {
|
with subtest("machine with iftop enabled"):
|
||||||
$withIftop->waitForUnit("default.target");
|
withIftop.wait_for_unit("default.target")
|
||||||
# limit to eth1 (eth0 is the test driver's control interface)
|
# limit to eth1 (eth0 is the test driver's control interface)
|
||||||
# and don't try name lookups
|
# and don't try name lookups
|
||||||
$withIftop->succeed("su -l alice -c 'iftop -t -s 1 -n -i eth1'");
|
withIftop.succeed("su -l alice -c 'iftop -t -s 1 -n -i eth1'")
|
||||||
};
|
|
||||||
subtest "machine without iftop", sub {
|
with subtest("machine without iftop"):
|
||||||
$withoutIftop->waitForUnit("default.target");
|
withoutIftop.wait_for_unit("default.target")
|
||||||
# check that iftop is there but user alice lacks capabilities
|
# check that iftop is there but user alice lacks capabilitie
|
||||||
$withoutIftop->succeed("iftop -t -s 1 -n -i eth1");
|
withoutIftop.succeed("iftop -t -s 1 -n -i eth1")
|
||||||
$withoutIftop->fail("su -l alice -c 'iftop -t -s 1 -n -i eth1'");
|
withoutIftop.fail("su -l alice -c 'iftop -t -s 1 -n -i eth1'")
|
||||||
};
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({ pkgs, lib, ... }:
|
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
name = "incron";
|
name = "incron";
|
||||||
|
@ -19,34 +19,34 @@ import ./make-test.nix ({ pkgs, lib, ... }:
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
start_all()
|
||||||
|
|
||||||
$machine->waitForUnit("multi-user.target");
|
machine.wait_for_unit("multi-user.target")
|
||||||
$machine->waitForUnit("incron.service");
|
machine.wait_for_unit("incron.service")
|
||||||
|
|
||||||
$machine->succeed("test -d /test");
|
machine.succeed("test -d /test")
|
||||||
# create some activity for incron to monitor
|
# create some activity for incron to monitor
|
||||||
$machine->succeed("touch /test/file");
|
machine.succeed("touch /test/file")
|
||||||
$machine->succeed("echo foo >> /test/file");
|
machine.succeed("echo foo >> /test/file")
|
||||||
$machine->succeed("mv /test/file /root");
|
machine.succeed("mv /test/file /root")
|
||||||
$machine->succeed("mv /root/file /test");
|
machine.succeed("mv /root/file /test")
|
||||||
|
|
||||||
$machine->sleep(1);
|
machine.sleep(1)
|
||||||
|
|
||||||
# touch /test/file
|
# touch /test/file
|
||||||
$machine->succeed("grep '/test/file IN_CREATE' /root/incron.log");
|
machine.succeed("grep '/test/file IN_CREATE' /root/incron.log")
|
||||||
|
|
||||||
# echo foo >> /test/file
|
# echo foo >> /test/file
|
||||||
$machine->succeed("grep '/test/file IN_MODIFY' /root/incron.log");
|
machine.succeed("grep '/test/file IN_MODIFY' /root/incron.log")
|
||||||
$machine->succeed("grep '/test/file IN_CLOSE_WRITE' /root/incron.log");
|
machine.succeed("grep '/test/file IN_CLOSE_WRITE' /root/incron.log")
|
||||||
|
|
||||||
# mv /test/file /root
|
# mv /test/file /root
|
||||||
$machine->succeed("grep '/test/file IN_MOVED_FROM' /root/incron.log");
|
machine.succeed("grep '/test/file IN_MOVED_FROM' /root/incron.log")
|
||||||
|
|
||||||
# mv /root/file /test
|
# mv /root/file /test
|
||||||
$machine->succeed("grep '/test/file IN_MOVED_TO' /root/incron.log");
|
machine.succeed("grep '/test/file IN_MOVED_TO' /root/incron.log")
|
||||||
|
|
||||||
# ensure something unexpected is not present
|
# ensure something unexpected is not present
|
||||||
$machine->fail("grep 'IN_OPEN' /root/incron.log");
|
machine.fail("grep 'IN_OPEN' /root/incron.log")
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This test runs influxdb and checks if influxdb is up and running
|
# This test runs influxdb and checks if influxdb is up and running
|
||||||
|
|
||||||
import ./make-test.nix ({ pkgs, ...} : {
|
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
name = "influxdb";
|
name = "influxdb";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ offline ];
|
maintainers = [ offline ];
|
||||||
|
@ -9,25 +9,32 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||||
nodes = {
|
nodes = {
|
||||||
one = { ... }: {
|
one = { ... }: {
|
||||||
services.influxdb.enable = true;
|
services.influxdb.enable = true;
|
||||||
|
environment.systemPackages = [ pkgs.httpie ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
import shlex
|
||||||
|
|
||||||
$one->waitForUnit("influxdb.service");
|
start_all()
|
||||||
|
|
||||||
|
one.wait_for_unit("influxdb.service")
|
||||||
|
|
||||||
# create database
|
# create database
|
||||||
$one->succeed(q~
|
one.succeed(
|
||||||
curl -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE test"
|
"curl -XPOST http://localhost:8086/query --data-urlencode 'q=CREATE DATABASE test'"
|
||||||
~);
|
)
|
||||||
|
|
||||||
# write some points and run simple query
|
# write some points and run simple query
|
||||||
$one->succeed(q~
|
out = one.succeed(
|
||||||
curl -XPOST 'http://localhost:8086/write?db=test' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'
|
"curl -XPOST 'http://localhost:8086/write?db=test' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'"
|
||||||
~);
|
)
|
||||||
$one->succeed(q~
|
|
||||||
curl -GET 'http://localhost:8086/query' --data-urlencode "db=test" --data-urlencode "q=SELECT \"value\" FROM \"cpu_load_short\" WHERE \"region\"='us-west'" | grep "0\.64"
|
qv = "SELECT value FROM cpu_load_short WHERE region='us-west'"
|
||||||
~);
|
cmd = f'curl -GET "http://localhost:8086/query?db=test" --data-urlencode {shlex.quote("q="+ qv)}'
|
||||||
|
out = one.succeed(cmd)
|
||||||
|
|
||||||
|
assert "2015-06-11T20:46:02Z" in out
|
||||||
|
assert "0.64" in out
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue