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/modules/installer/tools/nixos-option.sh @nbp
|
||||
|
||||
# NixOS integration test driver
|
||||
/nixos/lib/test-driver @tfc
|
||||
|
||||
# New NixOS modules
|
||||
/nixos/modules/module-list.nix @Infinisil
|
||||
|
||||
|
@ -167,3 +170,8 @@
|
|||
/nixos/modules/services/monitoring/prometheus/exporters.nix @WilliButz
|
||||
/nixos/modules/services/monitoring/prometheus/exporters.xml @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 = ''
|
||||
for f in $(find $out/bin/ $out/libexec/ -type f -executable); do
|
||||
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/gsettings-schemas/${name}" \
|
||||
--prefix XDG_DATA_DIRS : "${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}" \
|
||||
|
@ -102,7 +102,7 @@ preFixup = ''
|
|||
</listitem>
|
||||
<listitem xml:id="ssec-gnome-hooks-dconf">
|
||||
<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>
|
||||
</listitem>
|
||||
<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:
|
||||
```
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages
|
||||
haskellPackages.a50 a50-0.5
|
||||
haskellPackages.abacate haskell-abacate-0.0.0.0
|
||||
haskellPackages.abcBridge haskell-abcBridge-0.12
|
||||
haskellPackages.afv afv-0.1.1
|
||||
haskellPackages.alex alex-3.1.4
|
||||
haskellPackages.Allure Allure-0.4.101.1
|
||||
haskellPackages.alms alms-0.6.7
|
||||
[... some 8000 entries omitted ...]
|
||||
haskellPackages.a50 a50-0.5
|
||||
haskellPackages.AAI AAI-0.2.0.1
|
||||
haskellPackages.abacate abacate-0.0.0.0
|
||||
haskellPackages.abc-puzzle abc-puzzle-0.2.1
|
||||
haskellPackages.abcBridge abcBridge-0.15
|
||||
haskellPackages.abcnotation abcnotation-1.9.0
|
||||
haskellPackages.abeson abeson-0.1.0.1
|
||||
[... some 14000 entries omitted ...]
|
||||
```
|
||||
|
||||
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:
|
||||
```
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler
|
||||
haskell.compiler.ghc6104 ghc-6.10.4
|
||||
haskell.compiler.ghc6123 ghc-6.12.3
|
||||
haskell.compiler.ghc704 ghc-7.0.4
|
||||
haskell.compiler.ghc722 ghc-7.2.2
|
||||
haskell.compiler.ghc742 ghc-7.4.2
|
||||
haskell.compiler.ghc763 ghc-7.6.3
|
||||
haskell.compiler.ghc784 ghc-7.8.4
|
||||
haskell.compiler.ghc7102 ghc-7.10.2
|
||||
haskell.compiler.ghcHEAD ghc-7.11.20150402
|
||||
haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704
|
||||
haskell.compiler.ghcjs ghcjs-0.1.0
|
||||
haskell.compiler.jhc jhc-0.8.2
|
||||
haskell.compiler.uhc uhc-1.1.9.0
|
||||
haskell.compiler.ghc822 ghc-8.2.2
|
||||
haskell.compiler.integer-simple.ghc822 ghc-8.2.2
|
||||
haskell.compiler.ghc822Binary ghc-8.2.2-binary
|
||||
haskell.compiler.ghc844 ghc-8.4.4
|
||||
haskell.compiler.ghc863Binary ghc-8.6.3-binary
|
||||
haskell.compiler.ghc864 ghc-8.6.4
|
||||
haskell.compiler.integer-simple.ghc864 ghc-8.6.4
|
||||
haskell.compiler.ghc865 ghc-8.6.5
|
||||
haskell.compiler.integer-simple.ghc865 ghc-8.6.5
|
||||
haskell.compiler.ghc881 ghc-8.8.1
|
||||
haskell.compiler.integer-simple.ghc881 ghc-8.8.1
|
||||
haskell.compiler.ghcHEAD ghc-8.9.20190601
|
||||
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
|
||||
|
|
|
@ -244,7 +244,7 @@
|
|||
</question>
|
||||
<answer>
|
||||
<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>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
|
|
|
@ -1717,7 +1717,7 @@ someVar=$(stripHash $name)
|
|||
</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>
|
||||
|
|
|
@ -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:
|
||||
<programlisting>
|
||||
{
|
||||
allowUnfreePredicate = (pkg: builtins.elem
|
||||
(pkg.pname or (builtins.parseDrvName pkg.name).name) [
|
||||
"flashplayer"
|
||||
"vscode"
|
||||
]);
|
||||
allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||
"flashplayer"
|
||||
"vscode"
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
@ -217,7 +216,7 @@
|
|||
The following configuration example only allows insecure packages with very short names:
|
||||
<programlisting>
|
||||
{
|
||||
allowInsecurePredicate = (pkg: (builtins.stringLength (builtins.parseDrvName pkg.name).name) <= 5);
|
||||
allowInsecurePredicate = pkg: builtins.stringLength (lib.getName pkg) <= 5;
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
|
|
@ -84,7 +84,8 @@ let
|
|||
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
||||
escapeShellArg escapeShellArgs replaceChars lowerChars
|
||||
upperChars toLower toUpper addContextFrom splitString
|
||||
removePrefix removeSuffix versionOlder versionAtLeast getVersion
|
||||
removePrefix removeSuffix versionOlder versionAtLeast
|
||||
getName getVersion
|
||||
nameFromURL enableFeature enableFeatureAs withFeature
|
||||
withFeatureAs fixedWidthString fixedWidthNumber isStorePath
|
||||
toInt readPathsFromFile fileContents;
|
||||
|
|
|
@ -472,6 +472,23 @@ rec {
|
|||
*/
|
||||
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
|
||||
derivation's "name" attribute and extracts the version part from that
|
||||
argument.
|
||||
|
|
|
@ -37,6 +37,7 @@ rec {
|
|||
else if final.isAndroid then "bionic"
|
||||
else if final.isLinux /* default */ then "glibc"
|
||||
else if final.isMsp430 then "newlib"
|
||||
else if final.isVc4 then "newlib"
|
||||
else if final.isAvr then "avrlibc"
|
||||
else if final.isNetBSD then "nblibc"
|
||||
# TODO(@Ericson2314) think more about other operating systems
|
||||
|
|
|
@ -26,7 +26,7 @@ let
|
|||
|
||||
"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;
|
||||
|
@ -45,6 +45,7 @@ in {
|
|||
x86_64 = filterDoubles predicates.isx86_64;
|
||||
mips = filterDoubles predicates.isMips;
|
||||
riscv = filterDoubles predicates.isRiscV;
|
||||
vc4 = filterDoubles predicates.isVc4;
|
||||
|
||||
cygwin = filterDoubles predicates.isCygwin;
|
||||
darwin = filterDoubles predicates.isDarwin;
|
||||
|
|
|
@ -118,6 +118,12 @@ rec {
|
|||
config = "avr";
|
||||
};
|
||||
|
||||
vc4 = {
|
||||
config = "vc4-elf";
|
||||
libc = "newlib";
|
||||
platform = {};
|
||||
};
|
||||
|
||||
arm-embedded = {
|
||||
config = "arm-none-eabi";
|
||||
libc = "newlib";
|
||||
|
|
|
@ -21,6 +21,7 @@ rec {
|
|||
isSparc = { cpu = { family = "sparc"; }; };
|
||||
isWasm = { cpu = { family = "wasm"; }; };
|
||||
isMsp430 = { cpu = { family = "msp430"; }; };
|
||||
isVc4 = { cpu = { family = "vc4"; }; };
|
||||
isAvr = { cpu = { family = "avr"; }; };
|
||||
isAlpha = { cpu = { family = "alpha"; }; };
|
||||
isJavaScript = { cpu = cpuTypes.js; };
|
||||
|
|
|
@ -112,6 +112,8 @@ rec {
|
|||
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
|
||||
avr = { bits = 8; family = "avr"; };
|
||||
|
||||
vc4 = { bits = 32; significantByte = littleEndian; family = "vc4"; };
|
||||
|
||||
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 = {
|
||||
name = "dadada";
|
||||
email = "dadada@dadada.li";
|
||||
|
@ -1780,6 +1790,12 @@
|
|||
githubId = 875324;
|
||||
name = "David Johnson";
|
||||
};
|
||||
dmrauh = {
|
||||
email = "dmrauh@posteo.de";
|
||||
github = "dmrauh";
|
||||
githubId = 37698547;
|
||||
name = "Dominik Michael Rauh";
|
||||
};
|
||||
dmvianna = {
|
||||
email = "dmlvianna@gmail.com";
|
||||
github = "dmvianna";
|
||||
|
@ -2515,6 +2531,7 @@
|
|||
gazally = {
|
||||
email = "gazally@runbox.com";
|
||||
github = "gazally";
|
||||
githubId = 16470252;
|
||||
name = "Gemini Lasswell";
|
||||
};
|
||||
gebner = {
|
||||
|
@ -3594,6 +3611,12 @@
|
|||
github = "klntsky";
|
||||
githubId = 18447310;
|
||||
};
|
||||
kmcopper = {
|
||||
email = "kmcopper@danwin1210.me";
|
||||
name = "Kyle Copperfield";
|
||||
github = "kmcopper";
|
||||
githubId = 57132115;
|
||||
};
|
||||
kmeakin = {
|
||||
email = "karlwfmeakin@gmail.com";
|
||||
name = "Karl Meakin";
|
||||
|
@ -4139,6 +4162,12 @@
|
|||
github = "marcweber";
|
||||
githubId = 34086;
|
||||
name = "Marc Weber";
|
||||
};
|
||||
marcus7070 = {
|
||||
email = "marcus@geosol.com.au";
|
||||
github = "marcus7070";
|
||||
githubId = 50230945;
|
||||
name = "Marcus Boyd";
|
||||
};
|
||||
marenz = {
|
||||
email = "marenz@arkom.men";
|
||||
|
@ -4478,6 +4507,12 @@
|
|||
githubId = 16974598;
|
||||
name = "Mike Playle";
|
||||
};
|
||||
mkaito = {
|
||||
email = "chris@mkaito.net";
|
||||
github = "mkaito";
|
||||
githubId = 20434;
|
||||
name = "Christian Höppner";
|
||||
};
|
||||
mkazulak = {
|
||||
email = "kazulakm@gmail.com";
|
||||
github = "mulderr";
|
||||
|
@ -4517,6 +4552,12 @@
|
|||
githubId = 117842;
|
||||
name = "Henri Bourcereau";
|
||||
};
|
||||
mmilata = {
|
||||
email = "martin@martinmilata.cz";
|
||||
github = "mmilata";
|
||||
gitHubId = 85857;
|
||||
name = "Martin Milata";
|
||||
};
|
||||
mmlb = {
|
||||
email = "me.mmlb@mmlb.me";
|
||||
github = "mmlb";
|
||||
|
@ -4631,6 +4672,12 @@
|
|||
githubId = 2881922;
|
||||
name = "Francis St-Amour";
|
||||
};
|
||||
mtrsk = {
|
||||
email = "marcos.schonfinkel@protonmail.com";
|
||||
github = "mtrsk";
|
||||
githubId = 16356569;
|
||||
name = "Marcos Benevides";
|
||||
};
|
||||
mredaelli = {
|
||||
email = "massimo@typish.io";
|
||||
github = "mredaelli";
|
||||
|
@ -6099,7 +6146,7 @@
|
|||
name = "Shahrukh Khan";
|
||||
};
|
||||
shanemikel = {
|
||||
email = "shanemikel1@gmail.com";
|
||||
email = "shanepearlman@pm.me";
|
||||
github = "shanemikel";
|
||||
githubId = 6720672;
|
||||
name = "Shane Pearlman";
|
||||
|
@ -6720,6 +6767,12 @@
|
|||
githubId = 42933;
|
||||
name = "Andrew Childs";
|
||||
};
|
||||
thefenriswolf = {
|
||||
email = "stefan.rohrbacher97@gmail.com";
|
||||
github = "thefenriswolf";
|
||||
githubId = "8547242";
|
||||
name = "Stefan Rohrbacher";
|
||||
};
|
||||
thesola10 = {
|
||||
email = "thesola10@bobile.fr";
|
||||
github = "thesola10";
|
||||
|
@ -7611,4 +7664,16 @@
|
|||
githubId = 50867187;
|
||||
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: {
|
||||
name = package.name;
|
||||
pname = (builtins.parseDrvName package.name).name;
|
||||
pname = pkgs.lib.getName package;
|
||||
updateScript = map builtins.toString (pkgs.lib.toList package.updateScript);
|
||||
};
|
||||
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
<para>
|
||||
It sets <xref linkend="opt-services.xserver.enable"/>,
|
||||
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/>,
|
||||
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> (
|
||||
<link linkend="opt-services.xserver.desktopManager.plasma5.enableQt4Support">
|
||||
without Qt4 Support</link>), and
|
||||
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/>, and
|
||||
<xref linkend="opt-services.xserver.libinput.enable"/> to true. It also
|
||||
includes glxinfo and firefox in the system packages list.
|
||||
</para>
|
||||
|
|
|
@ -163,6 +163,57 @@
|
|||
time during the releases development (if viable).
|
||||
</para>
|
||||
</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>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ let
|
|||
optionsList = lib.sort optionLess optionsListDesc;
|
||||
|
||||
# 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);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ from contextlib import contextmanager, _GeneratorContextManager
|
|||
from xml.sax.saxutils import XMLGenerator
|
||||
import _thread
|
||||
import atexit
|
||||
import json
|
||||
import os
|
||||
import ptpython.repl
|
||||
import pty
|
||||
|
@ -16,7 +15,9 @@ import sys
|
|||
import tempfile
|
||||
import time
|
||||
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 = {
|
||||
"A": "shift-a",
|
||||
|
@ -92,6 +93,10 @@ def eprint(*args: object, **kwargs: Any) -> None:
|
|||
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]:
|
||||
global log
|
||||
log.log("starting VDE switch for network {}".format(vlan_nr))
|
||||
|
@ -216,7 +221,7 @@ class Machine:
|
|||
return path
|
||||
|
||||
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.connected = False
|
||||
|
@ -525,6 +530,33 @@ class Machine:
|
|||
if ret.returncode != 0:
|
||||
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:
|
||||
"""Debugging: Dump the contents of the TTY<n>
|
||||
"""
|
||||
|
@ -771,7 +803,9 @@ def run_tests() -> None:
|
|||
machine.execute("sync")
|
||||
|
||||
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
|
||||
|
|
|
@ -122,7 +122,7 @@ in
|
|||
description = ''
|
||||
Include ~/bin/ in $PATH.
|
||||
'';
|
||||
default = true;
|
||||
default = false;
|
||||
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 {
|
||||
assertions = [
|
||||
{
|
||||
assertion = with config.services.xserver.displayManager; gdm.enable -> !gdm.wayland;
|
||||
message = "NVIDIA drivers don't support wayland, set services.xserver.displayManager.gdm.wayland=false";
|
||||
assertion = with config.services.xserver.displayManager; gdm.nvidiaWayland -> cfg.modesetting.enable;
|
||||
message = "You cannot use wayland with GDM without modesetting enabled for NVIDIA drivers, set `hardware.nvidia.modesetting.enable = true`";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = !optimusCfg.enable ||
|
||||
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
|
||||
|
|
|
@ -55,7 +55,7 @@ in
|
|||
|
||||
# Without dconf enabled it is impossible to use IBus
|
||||
environment.systemPackages = with pkgs; [
|
||||
gnome3.dconf ibusAutostart
|
||||
dconf ibusAutostart
|
||||
];
|
||||
|
||||
environment.variables = {
|
||||
|
|
|
@ -11,7 +11,6 @@ with lib;
|
|||
services.xserver = {
|
||||
desktopManager.plasma5 = {
|
||||
enable = true;
|
||||
enableQt4Support = false;
|
||||
};
|
||||
|
||||
# Automatically login as nixos.
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
./config/terminfo.nix
|
||||
./config/unix-odbc-drivers.nix
|
||||
./config/users-groups.nix
|
||||
./config/vpnc.nix
|
||||
./config/vte.nix
|
||||
./config/zram.nix
|
||||
./hardware/acpilight.nix
|
||||
|
@ -308,6 +307,7 @@
|
|||
./services/desktops/gnome3/sushi.nix
|
||||
./services/desktops/gnome3/tracker.nix
|
||||
./services/desktops/gnome3/tracker-miners.nix
|
||||
./services/desktops/neard.nix
|
||||
./services/desktops/profile-sync-daemon.nix
|
||||
./services/desktops/system-config-printer.nix
|
||||
./services/desktops/telepathy.nix
|
||||
|
@ -519,7 +519,6 @@
|
|||
./services/monitoring/munin.nix
|
||||
./services/monitoring/nagios.nix
|
||||
./services/monitoring/netdata.nix
|
||||
./services/monitoring/osquery.nix
|
||||
./services/monitoring/prometheus/default.nix
|
||||
./services/monitoring/prometheus/alertmanager.nix
|
||||
./services/monitoring/prometheus/exporters.nix
|
||||
|
@ -539,7 +538,6 @@
|
|||
./services/monitoring/zabbix-agent.nix
|
||||
./services/monitoring/zabbix-proxy.nix
|
||||
./services/monitoring/zabbix-server.nix
|
||||
./services/network-filesystems/beegfs.nix
|
||||
./services/network-filesystems/cachefilesd.nix
|
||||
./services/network-filesystems/davfs2.nix
|
||||
./services/network-filesystems/drbd.nix
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
displayManager.sddm.enable = true;
|
||||
desktopManager.plasma5 = {
|
||||
enable = true;
|
||||
enableQt4Support = false;
|
||||
};
|
||||
libinput.enable = true; # for touchpad support on many laptops
|
||||
};
|
||||
|
|
|
@ -32,13 +32,13 @@ in
|
|||
environment.etc = optionals (cfg.profiles != {})
|
||||
(mapAttrsToList mkDconfProfile cfg.profiles);
|
||||
|
||||
services.dbus.packages = [ pkgs.gnome3.dconf ];
|
||||
services.dbus.packages = [ pkgs.dconf ];
|
||||
|
||||
# For dconf executable
|
||||
environment.systemPackages = [ pkgs.gnome3.dconf ];
|
||||
environment.systemPackages = [ pkgs.dconf ];
|
||||
|
||||
# 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;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.networking.defaultMailServer;
|
||||
cfg = config.services.ssmtp;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
networking.defaultMailServer = {
|
||||
services.ssmtp = {
|
||||
|
||||
directDelivery = mkOption {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
|
@ -29,7 +27,7 @@ in
|
|||
<command>sendmail</command> or <command>postfix</command> on
|
||||
your machine, set this option to <literal>true</literal>, and
|
||||
set the option
|
||||
<option>networking.defaultMailServer.hostName</option> to the
|
||||
<option>services.ssmtp.hostName</option> to the
|
||||
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 {
|
||||
name = "ssmtp-authpass";
|
||||
text = cfg.authPass;
|
||||
|
|
|
@ -10,6 +10,9 @@ with lib;
|
|||
(mkRenamedOptionModule [ "networking" "enableRalinkFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
||||
(mkRenamedOptionModule [ "networking" "enableRTL8192cFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
||||
(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" ]
|
||||
(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 [ "systemd" "generator-packages" ] "Use systemd.packages instead.")
|
||||
(mkRemovedOptionModule [ "fonts" "enableCoreFonts" ] "Use fonts.fonts = [ pkgs.corefonts ]; instead.")
|
||||
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
|
||||
|
||||
# ZSH
|
||||
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
||||
|
@ -279,6 +283,13 @@ with lib;
|
|||
# BLCR
|
||||
(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
|
||||
(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.")
|
||||
|
|
|
@ -66,7 +66,8 @@ in {
|
|||
if cfg.user == "roon-server" then {
|
||||
isSystemUser = true;
|
||||
description = "Roon Server user";
|
||||
groups = [ cfg.group "audio" ];
|
||||
group = cfg.group;
|
||||
extraGroups = [ "audio" ];
|
||||
}
|
||||
else {};
|
||||
};
|
||||
|
|
|
@ -8,15 +8,11 @@ let
|
|||
|
||||
mysql = cfg.package;
|
||||
|
||||
isMariaDB =
|
||||
let
|
||||
pName = _p: (builtins.parseDrvName (_p.name)).name;
|
||||
in pName mysql == pName pkgs.mariadb;
|
||||
isMariaDB = lib.getName mysql == lib.getName pkgs.mariadb;
|
||||
|
||||
isMysqlAtLeast57 =
|
||||
let
|
||||
pName = _p: (builtins.parseDrvName (_p.name)).name;
|
||||
in (pName mysql == pName pkgs.mysql57)
|
||||
&& ((builtins.compareVersions mysql.version "5.7") >= 0);
|
||||
(lib.getName mysql == lib.getName pkgs.mysql57)
|
||||
&& (builtins.compareVersions mysql.version "5.7" >= 0);
|
||||
|
||||
mysqldOptions =
|
||||
"--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 = {
|
||||
DynamicUser = true;
|
||||
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";
|
||||
|
||||
# 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 {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
type = with types; nullOr lines;
|
||||
default = null;
|
||||
example = ''
|
||||
[General]
|
||||
ControllerMode = bredr
|
||||
'';
|
||||
description = ''
|
||||
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
|
||||
|
||||
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 {
|
||||
source = pkgs.writeText "main.conf" ''
|
||||
[Policy]
|
||||
AutoEnable=${lib.boolToString cfg.powerOnBoot}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
source = pkgs.writeText "main.conf" (generators.toINI { } cfg.config + optionalString (cfg.extraConfig != null) cfg.extraConfig);
|
||||
target = "bluetooth/main.conf";
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ in
|
|||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
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;
|
||||
ExecStart = "${gitea.bin}/bin/gitea web";
|
||||
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 = {
|
||||
|
|
|
@ -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;
|
||||
})] ++ [(mkIf config.services.rspamd.enable {
|
||||
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:
|
||||
mkExporterConf {
|
||||
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;
|
||||
default = pkgs.samba;
|
||||
defaultText = "pkgs.samba";
|
||||
example = literalExample "pkgs.samba3";
|
||||
example = literalExample "pkgs.samba4Full";
|
||||
description = ''
|
||||
Defines which package should be used for the samba server.
|
||||
'';
|
||||
|
|
|
@ -4,7 +4,7 @@ with pkgs;
|
|||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.networking.connman;
|
||||
cfg = config.services.connman;
|
||||
configFile = pkgs.writeText "connman.conf" ''
|
||||
[General]
|
||||
NetworkInterfaceBlacklist=${concatStringsSep "," cfg.networkInterfaceBlacklist}
|
||||
|
@ -17,7 +17,7 @@ in {
|
|||
|
||||
options = {
|
||||
|
||||
networking.connman = {
|
||||
services.connman = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -71,13 +71,13 @@ in {
|
|||
|
||||
assertions = [{
|
||||
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;
|
||||
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;
|
||||
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 ];
|
||||
|
|
|
@ -137,7 +137,7 @@ in
|
|||
];
|
||||
|
||||
services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries {
|
||||
forwardZones =
|
||||
forwardZonesRecurse =
|
||||
{ bit = "127.0.0.1:${toString cfg.dns.port}";
|
||||
dns = "127.0.0.1:${toString cfg.dns.port}";
|
||||
};
|
||||
|
|
|
@ -90,11 +90,19 @@ in {
|
|||
};
|
||||
|
||||
forwardZones = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
DNS zones to be forwarded to other authoritative servers.
|
||||
'';
|
||||
};
|
||||
|
||||
forwardZonesRecurse = mkOption {
|
||||
type = types.attrs;
|
||||
example = { eth = "127.0.0.1:5353"; };
|
||||
default = {};
|
||||
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-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;
|
||||
dnssec = cfg.dnssecValidation;
|
||||
serve-rfc1918 = cfg.serveRFC1918;
|
||||
|
|
|
@ -236,9 +236,12 @@ in {
|
|||
${if ifaces == [] then ''
|
||||
for i in $(cd /sys/class/net && echo *); do
|
||||
DEVTYPE=
|
||||
source /sys/class/net/$i/uevent
|
||||
if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
|
||||
ifaces="$ifaces''${ifaces:+ -N} -i$i"
|
||||
UEVENT_PATH=/sys/class/net/$i/uevent
|
||||
if [ -e "$UEVENT_PATH" ]; then
|
||||
source "$UEVENT_PATH"
|
||||
if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
|
||||
ifaces="$ifaces''${ifaces:+ -N} -i$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
'' else ''
|
||||
|
|
|
@ -239,7 +239,7 @@ in
|
|||
services.znc = {
|
||||
configFile = mkDefault (pkgs.writeText "znc-generated.conf" semanticString);
|
||||
config = {
|
||||
Version = (builtins.parseDrvName pkgs.znc.name).version;
|
||||
Version = lib.getVersion pkgs.znc;
|
||||
Listener.l.Port = mkDefault 5000;
|
||||
Listener.l.SSL = mkDefault true;
|
||||
};
|
||||
|
|
|
@ -84,12 +84,6 @@ GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
|||
<title>Issues</title>
|
||||
|
||||
<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>
|
||||
<para>
|
||||
Matomo will warn you that the JavaScript tracker is not writable. This is
|
||||
|
|
|
@ -390,6 +390,7 @@ in {
|
|||
in {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "phpfpm-nextcloud.service" ];
|
||||
path = [ occ ];
|
||||
script = ''
|
||||
chmod og+x ${cfg.home}
|
||||
ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
|
||||
|
|
|
@ -262,6 +262,7 @@ in {
|
|||
in {
|
||||
Slice = "phpfpm.slice";
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "full";
|
||||
ProtectHome = true;
|
||||
# XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work
|
||||
|
|
|
@ -27,20 +27,13 @@ in
|
|||
example = "vlc";
|
||||
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 [
|
||||
(mkIf cfg.enable {
|
||||
|
@ -173,12 +166,10 @@ in
|
|||
|
||||
# Phonon audio backend
|
||||
++ 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" && cfg.enableQt4Support) pkgs.phonon-backend-vlc
|
||||
|
||||
# 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.hardware.pulseaudio.enable plasma-pa
|
||||
++ lib.optional config.powerManagement.enable powerdevil
|
||||
|
|
|
@ -31,6 +31,44 @@ let
|
|||
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
|
||||
|
||||
{
|
||||
|
@ -88,11 +126,21 @@ in
|
|||
wayland = mkOption {
|
||||
default = true;
|
||||
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;
|
||||
};
|
||||
|
||||
nvidiaWayland = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to allow wayland to be used with the proprietary
|
||||
NVidia graphics driver.
|
||||
'';
|
||||
};
|
||||
|
||||
autoSuspend = mkOption {
|
||||
default = true;
|
||||
description = ''
|
||||
|
@ -156,6 +204,8 @@ in
|
|||
cat - > /run/gdm/.config/gnome-initial-setup-done <<- EOF
|
||||
yes
|
||||
EOF
|
||||
'' + optionalString hasDefaultUserSession ''
|
||||
${setSessionScript}/bin/set-session ${defaultSessionName}
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -197,6 +247,19 @@ in
|
|||
|
||||
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" ];
|
||||
|
||||
programs.dconf.profiles.gdm =
|
||||
|
@ -218,7 +281,7 @@ in
|
|||
customDconfDb = pkgs.stdenv.mkDerivation {
|
||||
name = "gdm-dconf-db";
|
||||
buildCommand = ''
|
||||
${pkgs.gnome3.dconf}/bin/dconf compile $out ${customDconf}/dconf
|
||||
${pkgs.dconf}/bin/dconf compile $out ${customDconf}/dconf
|
||||
'';
|
||||
};
|
||||
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;
|
||||
grubTarget = f (grub.grubTarget or "");
|
||||
shell = "${pkgs.runtimeShell}";
|
||||
fullName = (builtins.parseDrvName realGrub.name).name;
|
||||
fullVersion = (builtins.parseDrvName realGrub.name).version;
|
||||
fullName = lib.getName realGrub;
|
||||
fullVersion = lib.getVersion realGrub;
|
||||
grubEfi = f grubEfi;
|
||||
grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f (grubEfi.grubTarget or "") else "";
|
||||
bootPath = args.path;
|
||||
|
|
|
@ -201,7 +201,7 @@ let
|
|||
(assertValueOneOf "IPv6AcceptRA" boolValues)
|
||||
(assertValueOneOf "IPv4ProxyARP" boolValues)
|
||||
(assertValueOneOf "IPv6ProxyNDP" boolValues)
|
||||
(assertValueOneOf "IPv6PrefixDelegation" boolValues)
|
||||
(assertValueOneOf "IPv6PrefixDelegation" (boolValues ++ [ "dhcpv6" "static" ]))
|
||||
(assertValueOneOf "ActiveSlave" boolValues)
|
||||
(assertValueOneOf "PrimarySlave" boolValues)
|
||||
(assertValueOneOf "ConfigureWithoutCarrier" boolValues)
|
||||
|
@ -924,6 +924,8 @@ in
|
|||
|
||||
config = mkIf config.systemd.network.enable {
|
||||
|
||||
users.users.systemd-network.group = "systemd-network";
|
||||
|
||||
systemd.additionalUpstreamSystemUnits = [
|
||||
"systemd-networkd.service" "systemd-networkd-wait-online.service"
|
||||
];
|
||||
|
|
|
@ -136,6 +136,8 @@ in
|
|||
}
|
||||
];
|
||||
|
||||
users.users.resolved.group = "systemd-resolve";
|
||||
|
||||
systemd.additionalUpstreamSystemUnits = [
|
||||
"systemd-resolved.service"
|
||||
];
|
||||
|
|
|
@ -50,7 +50,10 @@ with lib;
|
|||
${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;
|
||||
|
||||
system.activationScripts.systemd-timesyncd-migration = mkIf (versionOlder config.system.stateVersion "19.09") ''
|
||||
|
|
|
@ -149,7 +149,7 @@ let
|
|||
--setenv PATH="$PATH" \
|
||||
${optionalString cfg.ephemeral "--ephemeral"} \
|
||||
${if cfg.additionalCapabilities != null && cfg.additionalCapabilities != [] then
|
||||
''--capability="${concatStringsSep " " cfg.additionalCapabilities}"'' else ""
|
||||
''--capability="${concatStringsSep "," cfg.additionalCapabilities}"'' else ""
|
||||
} \
|
||||
${if cfg.tmpfs != null && cfg.tmpfs != [] then
|
||||
''--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;
|
||||
description = ''
|
||||
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"
|
||||
fi
|
||||
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 = {
|
||||
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.configPath = "${runDir}/ipsec/etc/racoon/racoon.conf";
|
||||
|
||||
|
@ -172,5 +182,4 @@ in {
|
|||
'';
|
||||
};
|
||||
})]));
|
||||
|
||||
}
|
||||
|
|
|
@ -620,7 +620,7 @@ in
|
|||
|
||||
# Wireless won't work in the VM.
|
||||
networking.wireless.enable = mkVMOverride false;
|
||||
networking.connman.enable = mkVMOverride false;
|
||||
services.connman.enable = mkVMOverride false;
|
||||
|
||||
# Speed up booting by not waiting for ARP.
|
||||
networking.dhcpcd.extraConfig = "noarp";
|
||||
|
|
|
@ -63,8 +63,7 @@ in rec {
|
|||
|
||||
#(all nixos.tests.containers)
|
||||
(all nixos.tests.containers-imperative)
|
||||
(all nixos.tests.containers-ipv4)
|
||||
(all nixos.tests.containers-ipv6)
|
||||
(all nixos.tests.containers-ip)
|
||||
nixos.tests.chromium.x86_64-linux or []
|
||||
(all nixos.tests.firefox)
|
||||
(all nixos.tests.firewall)
|
||||
|
|
|
@ -32,8 +32,7 @@ in rec {
|
|||
tests = {
|
||||
inherit (nixos'.tests)
|
||||
containers-imperative
|
||||
containers-ipv4
|
||||
containers-ipv6
|
||||
containers-ip
|
||||
firewall
|
||||
ipv6
|
||||
login
|
||||
|
|
|
@ -28,7 +28,7 @@ in
|
|||
babeld = handleTest ./babeld.nix {};
|
||||
bcachefs = handleTestOn ["x86_64-linux"] ./bcachefs.nix {}; # linux-4.18.2018.10.12 is unsupported on aarch64
|
||||
beanstalkd = handleTest ./beanstalkd.nix {};
|
||||
beegfs = handleTestOn ["x86_64-linux"] ./beegfs.nix {}; # beegfs is unsupported on aarch64
|
||||
bees = handleTest ./bees.nix {};
|
||||
bind = handleTest ./bind.nix {};
|
||||
bittorrent = handleTest ./bittorrent.nix {};
|
||||
#blivet = handleTest ./blivet.nix {}; # broken since 2017-07024
|
||||
|
@ -53,8 +53,7 @@ in
|
|||
containers-extra_veth = handleTest ./containers-extra_veth.nix {};
|
||||
containers-hosts = handleTest ./containers-hosts.nix {};
|
||||
containers-imperative = handleTest ./containers-imperative.nix {};
|
||||
containers-ipv4 = handleTest ./containers-ipv4.nix {};
|
||||
containers-ipv6 = handleTest ./containers-ipv6.nix {};
|
||||
containers-ip = handleTest ./containers-ip.nix {};
|
||||
containers-macvlans = handleTest ./containers-macvlans.nix {};
|
||||
containers-physical_interfaces = handleTest ./containers-physical_interfaces.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 {};
|
||||
orangefs = handleTest ./orangefs.nix {};
|
||||
os-prober = handleTestOn ["x86_64-linux"] ./os-prober.nix {};
|
||||
osquery = handleTest ./osquery.nix {};
|
||||
osrm-backend = handleTest ./osrm-backend.nix {};
|
||||
overlayfs = handleTest ./overlayfs.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";
|
||||
|
||||
|
@ -29,27 +29,34 @@ import ./make-test.nix ({ lib, ... }:
|
|||
|
||||
testScript =
|
||||
let
|
||||
withRetry = content: maxTests: sleepTime: ''
|
||||
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;
|
||||
someContentIsShared = loc: pkgs.writeShellScript "some-content-is-shared" ''
|
||||
[[ $(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 ''
|
||||
# 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("cp --reflink=never /aux1/dedup-me-1 /aux1/dedup-me-2");
|
||||
$machine->succeed("cp --reflink=never /aux1/* /aux2/");
|
||||
$machine->succeed("sync");
|
||||
$machine->fail(q(${someContentIsShared "/aux1"}));
|
||||
$machine->fail(q(${someContentIsShared "/aux2"}));
|
||||
$machine->succeed("systemctl start beesd\@aux1.service");
|
||||
machine.succeed(
|
||||
"dd if=/dev/urandom of=/aux1/dedup-me-1 bs=1M count=8",
|
||||
"cp --reflink=never /aux1/dedup-me-1 /aux1/dedup-me-2",
|
||||
"cp --reflink=never /aux1/* /aux2/",
|
||||
"sync",
|
||||
)
|
||||
machine.fail(
|
||||
"${someContentIsShared "/aux1"}",
|
||||
"${someContentIsShared "/aux2"}",
|
||||
)
|
||||
machine.succeed("systemctl start beesd@aux1.service")
|
||||
|
||||
# assert that "Set Shared" column is nonzero
|
||||
$machine->succeed(q(${withRetry (someContentIsShared "/aux1") 20 2}));
|
||||
$machine->fail(q(${someContentIsShared "/aux2"}));
|
||||
machine.wait_until_succeeds(
|
||||
"${someContentIsShared "/aux1"}",
|
||||
)
|
||||
machine.fail("${someContentIsShared "/aux2"}")
|
||||
|
||||
# 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";
|
||||
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`";
|
||||
in
|
||||
''
|
||||
$machine->start();
|
||||
$machine->waitForUnit("clickhouse.service");
|
||||
$machine->waitForOpenPort(9000);
|
||||
machine.start()
|
||||
machine.wait_for_unit("clickhouse.service")
|
||||
machine.wait_for_open_port(9000)
|
||||
|
||||
$machine->succeed("cat ${tableDDL} | clickhouse-client");
|
||||
$machine->succeed("cat ${insertQuery} | clickhouse-client");
|
||||
$machine->succeed("cat ${selectQuery} | clickhouse-client | grep foo");
|
||||
machine.succeed(
|
||||
"cat ${tableDDL} | clickhouse-client"
|
||||
)
|
||||
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";
|
||||
|
||||
|
@ -35,20 +35,18 @@ import ./make-test.nix ({ pkgs, lib, ... }:
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll();
|
||||
start_all()
|
||||
|
||||
subtest "CodiMD sqlite", sub {
|
||||
$codimdSqlite->waitForUnit("codimd.service");
|
||||
$codimdSqlite->waitForOpenPort(3000);
|
||||
$codimdSqlite->waitUntilSucceeds("curl -sSf http://localhost:3000/new");
|
||||
};
|
||||
with subtest("CodiMD sqlite"):
|
||||
codimdSqlite.wait_for_unit("codimd.service")
|
||||
codimdSqlite.wait_for_open_port(3000)
|
||||
codimdSqlite.wait_until_succeeds("curl -sSf http://localhost:3000/new")
|
||||
|
||||
subtest "CodiMD postgres", sub {
|
||||
$codimdPostgres->waitForUnit("postgresql.service");
|
||||
$codimdPostgres->waitForUnit("codimd.service");
|
||||
$codimdPostgres->waitForOpenPort(5432);
|
||||
$codimdPostgres->waitForOpenPort(3000);
|
||||
$codimdPostgres->waitUntilSucceeds("curl -sSf http://localhost:3000/new");
|
||||
};
|
||||
with subtest("CodiMD postgres"):
|
||||
codimdPostgres.wait_for_unit("postgresql.service")
|
||||
codimdPostgres.wait_for_unit("codimd.service")
|
||||
codimdPostgres.wait_for_open_port(5432)
|
||||
codimdPostgres.wait_for_open_port(3000)
|
||||
codimdPostgres.wait_until_succeeds("curl -sSf http://localhost:3000/new")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -7,7 +7,7 @@ let
|
|||
containerIp6 = "fc00::2/7";
|
||||
in
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "containers-bridge";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
||||
|
@ -61,43 +61,42 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
||||
};
|
||||
|
||||
testScript =
|
||||
''
|
||||
$machine->waitForUnit("default.target");
|
||||
$machine->succeed("nixos-container list") =~ /webserver/ or die;
|
||||
testScript = ''
|
||||
machine.wait_for_unit("default.target")
|
||||
assert "webserver" in machine.succeed("nixos-container list")
|
||||
|
||||
# Start the webserver container.
|
||||
$machine->succeed("nixos-container status webserver") =~ /up/ or die;
|
||||
with subtest("Start the webserver container"):
|
||||
assert "up" in machine.succeed("nixos-container status webserver")
|
||||
|
||||
# Check if bridges exist inside containers
|
||||
$machine->succeed("nixos-container run webserver -- ip link show eth0");
|
||||
$machine->succeed("nixos-container run web-noip -- ip link show eth0");
|
||||
with subtest("Bridges exist inside containers"):
|
||||
machine.succeed(
|
||||
"nixos-container run webserver -- ip link show eth0",
|
||||
"nixos-container run web-noip -- ip link show eth0",
|
||||
)
|
||||
|
||||
"${containerIp}" =~ /([^\/]+)\/([0-9+])/;
|
||||
my $ip = $1;
|
||||
chomp $ip;
|
||||
$machine->succeed("ping -n -c 1 $ip");
|
||||
$machine->succeed("curl --fail http://$ip/ > /dev/null");
|
||||
ip = "${containerIp}".split("/")[0]
|
||||
machine.succeed(f"ping -n -c 1 {ip}")
|
||||
machine.succeed(f"curl --fail http://{ip}/ > /dev/null")
|
||||
|
||||
"${containerIp6}" =~ /([^\/]+)\/([0-9+])/;
|
||||
my $ip6 = $1;
|
||||
chomp $ip6;
|
||||
$machine->succeed("ping -n -c 1 $ip6");
|
||||
$machine->succeed("curl --fail http://[$ip6]/ > /dev/null");
|
||||
ip6 = "${containerIp6}".split("/")[0]
|
||||
machine.succeed(f"ping -n -c 1 {ip6}")
|
||||
machine.succeed(f"curl --fail http://[{ip6}]/ > /dev/null")
|
||||
|
||||
# Check that nixos-container show-ip works in case of an ipv4 address with
|
||||
# subnetmask in CIDR notation.
|
||||
my $result = $machine->succeed("nixos-container show-ip webserver");
|
||||
chomp $result;
|
||||
$result eq $ip or die;
|
||||
with subtest(
|
||||
"nixos-container show-ip works in case of an ipv4 address "
|
||||
+ "with subnetmask in CIDR notation."
|
||||
):
|
||||
result = machine.succeed("nixos-container show-ip webserver").rstrip()
|
||||
assert result == ip
|
||||
|
||||
# Stop the container.
|
||||
$machine->succeed("nixos-container stop webserver");
|
||||
$machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null");
|
||||
$machine->fail("curl --fail --connect-timeout 2 http://[$ip6]/ > /dev/null");
|
||||
|
||||
# Destroying a declarative container should fail.
|
||||
$machine->fail("nixos-container destroy webserver");
|
||||
'';
|
||||
with subtest("Stop the container"):
|
||||
machine.succeed("nixos-container stop webserver")
|
||||
machine.fail(
|
||||
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")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Test for NixOS' container support.
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "containers-ephemeral";
|
||||
|
||||
machine = { pkgs, ... }: {
|
||||
|
@ -16,10 +16,10 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts.localhost = {
|
||||
root = (pkgs.runCommand "localhost" {} ''
|
||||
root = pkgs.runCommand "localhost" {} ''
|
||||
mkdir "$out"
|
||||
echo hello world > "$out/index.html"
|
||||
'');
|
||||
'';
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
|
@ -28,29 +28,27 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
};
|
||||
|
||||
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
|
||||
$machine->succeed("ls /run/containers/webserver");
|
||||
with subtest("Container got its own root folder"):
|
||||
machine.succeed("ls /run/containers/webserver")
|
||||
|
||||
# Check that container persistent directory is not created
|
||||
$machine->fail("ls /var/lib/containers/webserver");
|
||||
with subtest("Container persistent directory is not created"):
|
||||
machine.fail("ls /var/lib/containers/webserver")
|
||||
|
||||
# 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");
|
||||
ip = machine.succeed("nixos-container show-ip webserver").rstrip()
|
||||
machine.succeed(f"ping -n -c1 {ip}")
|
||||
machine.succeed(f"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");
|
||||
with subtest("Stop the container"):
|
||||
machine.succeed("nixos-container stop webserver")
|
||||
machine.fail(f"curl --fail --connect-timeout 2 http://{ip}/ > /dev/null")
|
||||
|
||||
# Check that container's root folder was removed
|
||||
$machine->fail("ls /run/containers/webserver");
|
||||
with subtest("Container's root folder was removed"):
|
||||
machine.fail("ls /run/containers/webserver")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Test for NixOS' container support.
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "containers-hosts";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ montag451 ];
|
||||
|
@ -42,11 +42,11 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
$machine->waitForUnit("default.target");
|
||||
start_all()
|
||||
machine.wait_for_unit("default.target")
|
||||
|
||||
# Ping the containers using the entries added in /etc/hosts
|
||||
$machine->succeed("ping -n -c 1 simple.containers");
|
||||
$machine->succeed("ping -n -c 1 netmask.containers");
|
||||
with subtest("Ping the containers using the entries added in /etc/hosts"):
|
||||
for host in "simple.containers", "netmask.containers":
|
||||
machine.succeed(f"ping -n -c 1 {host}")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Test for NixOS' container support.
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "containers-imperative";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ aristid aszlig eelco kampfschlaefer ];
|
||||
|
@ -36,95 +36,99 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
};
|
||||
|
||||
testScript = let
|
||||
tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" ''
|
||||
{
|
||||
systemd.tmpfiles.rules = [ "d /foo - - - - -" ];
|
||||
systemd.services.foo = {
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = "ls -al /foo";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
||||
''; in
|
||||
''
|
||||
# Make sure we have a NixOS tree (required by ‘nixos-container create’).
|
||||
$machine->succeed("PAGER=cat nix-env -qa -A nixos.hello >&2");
|
||||
tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" ''
|
||||
{
|
||||
systemd.tmpfiles.rules = [ "d /foo - - - - -" ];
|
||||
systemd.services.foo = {
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = "ls -al /foo";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
in ''
|
||||
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")
|
||||
|
||||
# Create some containers imperatively.
|
||||
my $id1 = $machine->succeed("nixos-container create foo --ensure-unique-name");
|
||||
chomp $id1;
|
||||
$machine->log("created container $id1");
|
||||
id1, id2 = None, None
|
||||
|
||||
my $id2 = $machine->succeed("nixos-container create foo --ensure-unique-name");
|
||||
chomp $id2;
|
||||
$machine->log("created container $id2");
|
||||
with subtest("Create some containers imperatively"):
|
||||
id1 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip()
|
||||
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.
|
||||
$machine->succeed(
|
||||
"mv /var/lib/containers/$id2 /id2-bindmount",
|
||||
"mount --bind /id2-bindmount /var/lib/containers/$id1"
|
||||
);
|
||||
assert id1 != id2
|
||||
|
||||
my $ip1 = $machine->succeed("nixos-container show-ip $id1");
|
||||
chomp $ip1;
|
||||
my $ip2 = $machine->succeed("nixos-container show-ip $id2");
|
||||
chomp $ip2;
|
||||
die if $ip1 eq $ip2;
|
||||
with subtest(f"Put the root of {id2} into a bind mount"):
|
||||
machine.succeed(
|
||||
f"mv /var/lib/containers/{id2} /id2-bindmount",
|
||||
f"mount --bind /id2-bindmount /var/lib/containers/{id1}",
|
||||
)
|
||||
|
||||
# Create a directory and a file we can later check if it still exists
|
||||
# after destruction of the container.
|
||||
$machine->succeed(
|
||||
"mkdir /nested-bindmount",
|
||||
"echo important data > /nested-bindmount/dummy",
|
||||
);
|
||||
ip1 = machine.succeed(f"nixos-container show-ip {id1}").rstrip()
|
||||
ip2 = machine.succeed(f"nixos-container show-ip {id2}").rstrip()
|
||||
assert ip1 != ip2
|
||||
|
||||
# Create a directory with a dummy file and bind-mount it into both
|
||||
# containers.
|
||||
foreach ($id1, $id2) {
|
||||
my $importantPath = "/var/lib/containers/$_/very/important/data";
|
||||
$machine->succeed(
|
||||
"mkdir -p $importantPath",
|
||||
"mount --bind /nested-bindmount $importantPath"
|
||||
);
|
||||
}
|
||||
with subtest(
|
||||
"Create a directory and a file we can later check if it still exists "
|
||||
+ "after destruction of the container"
|
||||
):
|
||||
machine.succeed("mkdir /nested-bindmount")
|
||||
machine.succeed("echo important data > /nested-bindmount/dummy")
|
||||
|
||||
# Start one of them.
|
||||
$machine->succeed("nixos-container start $id1");
|
||||
with subtest(
|
||||
"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.
|
||||
$machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
|
||||
with subtest("Start one of them"):
|
||||
machine.succeed(f"nixos-container start {id1}")
|
||||
|
||||
# Execute a nix command via the root shell. (regression test for #40355)
|
||||
$machine->succeed("nixos-container run $id1 -- nix-instantiate -E 'derivation { name = \"empty\"; builder = \"false\"; system = \"false\"; }'");
|
||||
with subtest("Execute commands via the root shell"):
|
||||
assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname")
|
||||
|
||||
# Stop and start (regression test for #4989)
|
||||
$machine->succeed("nixos-container stop $id1");
|
||||
$machine->succeed("nixos-container start $id1");
|
||||
with subtest("Execute a nix command via the root shell. (regression test for #40355)"):
|
||||
machine.succeed(
|
||||
f"nixos-container run {id1} -- nix-instantiate -E "
|
||||
+ '\'derivation { name = "empty"; builder = "false"; system = "false"; }\' '
|
||||
)
|
||||
|
||||
# Ensure tmpfiles are present
|
||||
$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");
|
||||
with subtest("Stop and start (regression test for #4989)"):
|
||||
machine.succeed(f"nixos-container stop {id1}")
|
||||
machine.succeed(f"nixos-container start {id1}")
|
||||
|
||||
# Execute commands via the root shell.
|
||||
$machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
|
||||
with subtest("tmpfiles are present"):
|
||||
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.
|
||||
$machine->succeed("nixos-container destroy $id1");
|
||||
$machine->succeed("nixos-container destroy $id2");
|
||||
with subtest("Execute commands via the root shell"):
|
||||
assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname")
|
||||
|
||||
$machine->succeed(
|
||||
# Check whether destruction of any container has killed important data
|
||||
"grep -qF 'important data' /nested-bindmount/dummy",
|
||||
# Ensure that the container path is gone
|
||||
"test ! -e /var/lib/containers/$id1"
|
||||
);
|
||||
with subtest("Destroy the containers"):
|
||||
for id in id1, id2:
|
||||
machine.succeed(f"nixos-container destroy {id}")
|
||||
|
||||
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
|
||||
client_base = {
|
||||
|
||||
|
||||
containers.test1 = {
|
||||
autoStart = true;
|
||||
config = {
|
||||
|
@ -48,18 +48,25 @@ in {
|
|||
c1System = nodes.client_c1.config.system.build.toplevel;
|
||||
c2System = nodes.client_c2.config.system.build.toplevel;
|
||||
in ''
|
||||
$client->start();
|
||||
$client->waitForUnit("default.target");
|
||||
$client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_base ]] >&2");
|
||||
client.start()
|
||||
client.wait_for_unit("default.target")
|
||||
|
||||
$client->succeed("${c1System}/bin/switch-to-configuration test >&2");
|
||||
$client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_c1 ]] >&2");
|
||||
$client->succeed("systemctl status httpd -M test1 >&2");
|
||||
assert "client_base" in client.succeed("nixos-container run test1 cat /etc/check")
|
||||
|
||||
$client->succeed("${c2System}/bin/switch-to-configuration test >&2");
|
||||
$client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_c2 ]] >&2");
|
||||
$client->fail("systemctl status httpd -M test1 >&2");
|
||||
$client->succeed("systemctl status nginx -M test1 >&2");
|
||||
with subtest("httpd is available after activating config1"):
|
||||
client.succeed(
|
||||
"${c1System}/bin/switch-to-configuration test >&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.
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "containers-tmpfs";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ kampka ];
|
||||
|
@ -31,49 +31,63 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
virtualisation.pathsInNixDB = [ pkgs.stdenv ];
|
||||
};
|
||||
|
||||
testScript =
|
||||
''
|
||||
$machine->waitForUnit("default.target");
|
||||
$machine->succeed("nixos-container list") =~ /tmpfs/ or die;
|
||||
testScript = ''
|
||||
machine.wait_for_unit("default.target")
|
||||
assert "tmpfs" in machine.succeed("nixos-container list")
|
||||
|
||||
# Start the tmpfs container.
|
||||
#$machine->succeed("nixos-container status tmpfs") =~ /up/ or die;
|
||||
|
||||
# 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");
|
||||
with subtest("tmpfs container is up"):
|
||||
assert "up" in machine.succeed("nixos-container status tmpfs")
|
||||
|
||||
|
||||
# Verify that /some/random/path is writable and that files created there
|
||||
# are not in the hosts container dir but in the tmpfs
|
||||
$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");
|
||||
def tmpfs_cmd(command):
|
||||
return f"nixos-container run tmpfs -- {command} 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
|
||||
# are not visible to the container as the do not exist in the tmpfs
|
||||
$machine->succeed("touch /var/lib/containers/tmpfs/var/test.file");
|
||||
with subtest("/var is mounted as a tmpfs"):
|
||||
machine.succeed(tmpfs_cmd("mountpoint -q /var"))
|
||||
|
||||
$machine->succeed("test -e /var/lib/containers/tmpfs/var/test.file");
|
||||
$machine->succeed("ls -l /var/lib/containers/tmpfs/var/ | grep -q test.file 2>/dev/null");
|
||||
with subtest("/var/log is mounted as a tmpfs"):
|
||||
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";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ flokli ];
|
||||
|
@ -45,18 +45,20 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
start_all()
|
||||
|
||||
$simple->waitForUnit("deluged");
|
||||
$simple->waitForUnit("delugeweb");
|
||||
$simple->waitForOpenPort("8112");
|
||||
$declarative->waitForUnit("network.target");
|
||||
$declarative->waitUntilSucceeds("curl --fail http://simple:8112");
|
||||
simple.wait_for_unit("deluged")
|
||||
simple.wait_for_unit("delugeweb")
|
||||
simple.wait_for_open_port("8112")
|
||||
declarative.wait_for_unit("network.target")
|
||||
declarative.wait_until_succeeds("curl --fail http://simple:8112")
|
||||
|
||||
$declarative->waitForUnit("deluged");
|
||||
$declarative->waitForUnit("delugeweb");
|
||||
$declarative->waitUntilSucceeds("curl --fail http://declarative:3142");
|
||||
$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.wait_for_unit("deluged")
|
||||
declarative.wait_for_unit("delugeweb")
|
||||
declarative.wait_until_succeeds("curl --fail http://declarative:3142")
|
||||
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'"
|
||||
)
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This test runs docker-registry and check if it works
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "docker-registry";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ globin ma27 ironpinguin ];
|
||||
|
@ -28,36 +28,34 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
$client1->start();
|
||||
$client1->waitForUnit("docker.service");
|
||||
$client1->succeed("tar cv --files-from /dev/null | docker import - scratch");
|
||||
$client1->succeed("docker tag scratch registry:8080/scratch");
|
||||
client1.start()
|
||||
client1.wait_for_unit("docker.service")
|
||||
client1.succeed("tar cv --files-from /dev/null | docker import - scratch")
|
||||
client1.succeed("docker tag scratch registry:8080/scratch")
|
||||
|
||||
$registry->start();
|
||||
$registry->waitForUnit("docker-registry.service");
|
||||
$registry->waitForOpenPort("8080");
|
||||
$client1->succeed("docker push registry:8080/scratch");
|
||||
registry.start()
|
||||
registry.wait_for_unit("docker-registry.service")
|
||||
registry.wait_for_open_port("8080")
|
||||
client1.succeed("docker push registry:8080/scratch")
|
||||
|
||||
$client2->start();
|
||||
$client2->waitForUnit("docker.service");
|
||||
$client2->succeed("docker pull registry:8080/scratch");
|
||||
$client2->succeed("docker images | grep scratch");
|
||||
client2.start()
|
||||
client2.wait_for_unit("docker.service")
|
||||
client2.succeed("docker pull registry:8080/scratch")
|
||||
client2.succeed("docker images | grep scratch")
|
||||
|
||||
$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\')'
|
||||
);
|
||||
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')"
|
||||
)
|
||||
|
||||
$registry->systemctl("start docker-registry-garbage-collect.service");
|
||||
$registry->waitUntilFails("systemctl status docker-registry-garbage-collect.service");
|
||||
$registry->waitForUnit("docker-registry.service");
|
||||
registry.systemctl("start docker-registry-garbage-collect.service")
|
||||
registry.wait_until_fails("systemctl status docker-registry-garbage-collect.service")
|
||||
registry.wait_for_unit("docker-registry.service")
|
||||
|
||||
$registry->fail(
|
||||
'ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data'
|
||||
);
|
||||
registry.fail("ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data")
|
||||
|
||||
$client1->succeed("docker push registry:8080/scratch");
|
||||
$registry->succeed(
|
||||
'ls -l /var/lib/docker-registry/docker/registry/v2/blobs/sha256/*/*/data'
|
||||
);
|
||||
client1.succeed("docker push registry:8080/scratch")
|
||||
registry.succeed(
|
||||
"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";
|
||||
|
||||
machine = { pkgs, ... }: {
|
||||
|
@ -66,12 +66,12 @@ import ./make-test.nix {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
$machine->waitForUnit('postfix.service');
|
||||
$machine->waitForUnit('dovecot2.service');
|
||||
$machine->succeed('send-testmail');
|
||||
$machine->succeed('send-lda');
|
||||
$machine->waitUntilFails('[ "$(postqueue -p)" != "Mail queue is empty" ]');
|
||||
$machine->succeed('test-imap');
|
||||
$machine->succeed('test-pop');
|
||||
machine.wait_for_unit("postfix.service")
|
||||
machine.wait_for_unit("dovecot2.service")
|
||||
machine.succeed("send-testmail")
|
||||
machine.succeed("send-lda")
|
||||
machine.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
machine.succeed("test-imap")
|
||||
machine.succeed("test-pop")
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 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 {
|
||||
buildInputs = [ pkgs.openssl ];
|
||||
|
@ -129,29 +129,26 @@ in {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
subtest "should start etcd cluster", sub {
|
||||
$node1->start();
|
||||
$node2->start();
|
||||
$node1->waitForUnit("etcd.service");
|
||||
$node2->waitForUnit("etcd.service");
|
||||
$node2->waitUntilSucceeds("etcdctl cluster-health");
|
||||
$node1->succeed("etcdctl set /foo/bar 'Hello world'");
|
||||
$node2->succeed("etcdctl get /foo/bar | grep 'Hello world'");
|
||||
};
|
||||
with subtest("should start etcd cluster"):
|
||||
node1.start()
|
||||
node2.start()
|
||||
node1.wait_for_unit("etcd.service")
|
||||
node2.wait_for_unit("etcd.service")
|
||||
node2.wait_until_succeeds("etcdctl cluster-health")
|
||||
node1.succeed("etcdctl set /foo/bar 'Hello world'")
|
||||
node2.succeed("etcdctl get /foo/bar | grep 'Hello world'")
|
||||
|
||||
subtest "should add another member", sub {
|
||||
$node1->waitUntilSucceeds("etcdctl member add node3 https://node3:2380");
|
||||
$node3->start();
|
||||
$node3->waitForUnit("etcd.service");
|
||||
$node3->waitUntilSucceeds("etcdctl member list | grep 'node3'");
|
||||
$node3->succeed("etcdctl cluster-health");
|
||||
};
|
||||
with subtest("should add another member"):
|
||||
node1.wait_until_succeeds("etcdctl member add node3 https://node3:2380")
|
||||
node3.start()
|
||||
node3.wait_for_unit("etcd.service")
|
||||
node3.wait_until_succeeds("etcdctl member list | grep 'node3'")
|
||||
node3.succeed("etcdctl cluster-health")
|
||||
|
||||
subtest "should survive member crash", sub {
|
||||
$node3->crash;
|
||||
$node1->succeed("etcdctl cluster-health");
|
||||
$node1->succeed("etcdctl set /foo/bar 'Hello degraded world'");
|
||||
$node1->succeed("etcdctl get /foo/bar | grep 'Hello degraded world'");
|
||||
};
|
||||
with subtest("should survive member crash"):
|
||||
node3.crash()
|
||||
node1.succeed("etcdctl cluster-health")
|
||||
node1.succeed("etcdctl set /foo/bar 'Hello degraded world'")
|
||||
node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This test runs simple etcd node
|
||||
|
||||
import ./make-test.nix ({ pkgs, ... } : {
|
||||
import ./make-test-python.nix ({ pkgs, ... } : {
|
||||
name = "etcd";
|
||||
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
|
@ -14,14 +14,12 @@ import ./make-test.nix ({ pkgs, ... } : {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
subtest "should start etcd node", sub {
|
||||
$node->start();
|
||||
$node->waitForUnit("etcd.service");
|
||||
};
|
||||
with subtest("should start etcd node"):
|
||||
node.start()
|
||||
node.wait_for_unit("etcd.service")
|
||||
|
||||
subtest "should write and read some values to etcd", sub {
|
||||
$node->succeed("etcdctl set /foo/bar 'Hello world'");
|
||||
$node->succeed("etcdctl get /foo/bar | grep 'Hello world'");
|
||||
}
|
||||
with subtest("should write and read some values to etcd"):
|
||||
node.succeed("etcdctl set /foo/bar '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";
|
||||
|
||||
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.
|
||||
testScript = ''
|
||||
$machine->waitForUnit("fancontrol.service");
|
||||
$machine->waitUntilSucceeds("journalctl -eu fancontrol | grep 'Configuration appears to be outdated'");
|
||||
start_all()
|
||||
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";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ mic92 ];
|
||||
|
@ -53,24 +53,22 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
|
||||
testScript =
|
||||
''
|
||||
startAll;
|
||||
start_all()
|
||||
|
||||
$client->waitForUnit("network-online.target");
|
||||
$server->waitForUnit("ferm.service");
|
||||
$server->waitForUnit("nginx.service");
|
||||
$server->waitUntilSucceeds("ss -ntl | grep -q 80");
|
||||
client.wait_for_unit("network-online.target")
|
||||
server.wait_for_unit("ferm.service")
|
||||
server.wait_for_unit("nginx.service")
|
||||
server.wait_until_succeeds("ss -ntl | grep -q 80")
|
||||
|
||||
subtest "port 80 is allowed", sub {
|
||||
$client->succeed("curl --fail -g http://192.168.1.1:80/status");
|
||||
$client->succeed("curl --fail -g http://[fd00::1]:80/status");
|
||||
};
|
||||
with subtest("port 80 is allowed"):
|
||||
client.succeed("curl --fail -g http://192.168.1.1:80/status")
|
||||
client.succeed("curl --fail -g http://[fd00::1]:80/status")
|
||||
|
||||
subtest "port 8080 is not allowed", sub {
|
||||
$server->succeed("curl --fail -g http://192.168.1.1:8080/status");
|
||||
$server->succeed("curl --fail -g http://[fd00::1]:8080/status");
|
||||
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://[fd00::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://192.168.1.1:8080/status")
|
||||
client.fail("curl --fail -g http://[fd00::1]:8080/status")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Test the firewall module.
|
||||
|
||||
import ./make-test.nix ( { pkgs, ... } : {
|
||||
import ./make-test-python.nix ( { pkgs, ... } : {
|
||||
name = "firewall";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ eelco ];
|
||||
|
@ -36,30 +36,30 @@ import ./make-test.nix ( { pkgs, ... } : {
|
|||
testScript = { nodes, ... }: let
|
||||
newSystem = nodes.walled2.config.system.build.toplevel;
|
||||
in ''
|
||||
$walled->start;
|
||||
$attacker->start;
|
||||
start_all()
|
||||
|
||||
$walled->waitForUnit("firewall");
|
||||
$walled->waitForUnit("httpd");
|
||||
$attacker->waitForUnit("network.target");
|
||||
walled.wait_for_unit("firewall")
|
||||
walled.wait_for_unit("httpd")
|
||||
attacker.wait_for_unit("network.target")
|
||||
|
||||
# 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.
|
||||
$attacker->fail("curl --fail --connect-timeout 2 http://walled/ >&2");
|
||||
$attacker->succeed("ping -c 1 walled >&2");
|
||||
attacker.fail("curl --fail --connect-timeout 2 http://walled/ >&2")
|
||||
attacker.succeed("ping -c 1 walled >&2")
|
||||
|
||||
# Outgoing connections/pings should still work.
|
||||
$walled->succeed("curl -v http://attacker/ >&2");
|
||||
$walled->succeed("ping -c 1 attacker >&2");
|
||||
walled.succeed("curl -v http://attacker/ >&2")
|
||||
walled.succeed("ping -c 1 attacker >&2")
|
||||
|
||||
# If we stop the firewall, then connections should succeed.
|
||||
$walled->stopJob("firewall");
|
||||
$attacker->succeed("curl -v http://walled/ >&2");
|
||||
walled.stop_job("firewall")
|
||||
attacker.succeed("curl -v http://walled/ >&2")
|
||||
|
||||
# Check whether activation of a new configuration reloads the firewall.
|
||||
$walled->succeed("${newSystem}/bin/switch-to-configuration test 2>&1" .
|
||||
" | grep -qF firewall.service");
|
||||
walled.succeed(
|
||||
"${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";
|
||||
|
||||
machine =
|
||||
|
@ -14,8 +14,11 @@ import ./make-test.nix ({ pkgs, ... }: {
|
|||
|
||||
testScript =
|
||||
''
|
||||
$machine->waitForFile("/etc/fish/generated_completions/coreutils.fish");
|
||||
$machine->waitForFile("/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\$'");
|
||||
start_all()
|
||||
machine.wait_for_file("/etc/fish/generated_completions/coreutils.fish")
|
||||
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";
|
||||
|
||||
machine = { pkgs, ... }: {
|
||||
|
@ -33,14 +33,17 @@ import ./make-test.nix ({ pkgs, lib, ... }: {
|
|||
inherit testMessage;
|
||||
});
|
||||
in ''
|
||||
$machine->start;
|
||||
$machine->waitForUnit('fluentd.service');
|
||||
$machine->waitForOpenPort(9880);
|
||||
machine.start()
|
||||
machine.wait_for_unit("fluentd.service")
|
||||
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
|
||||
initialRootPassword = "notproduction";
|
||||
in
|
||||
import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
|
||||
import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; {
|
||||
name = "gitlab";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ globin ];
|
||||
|
@ -63,21 +63,35 @@ import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
|
|||
});
|
||||
in
|
||||
''
|
||||
$gitlab->start();
|
||||
$gitlab->waitForUnit("gitaly.service");
|
||||
$gitlab->waitForUnit("gitlab-workhorse.service");
|
||||
$gitlab->waitForUnit("gitlab.service");
|
||||
$gitlab->waitForUnit("gitlab-sidekiq.service");
|
||||
$gitlab->waitForFile("/var/gitlab/state/tmp/sockets/gitlab.socket");
|
||||
$gitlab->waitUntilSucceeds("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("${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2");
|
||||
$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("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");
|
||||
gitlab.start()
|
||||
gitlab.wait_for_unit("gitaly.service")
|
||||
gitlab.wait_for_unit("gitlab-workhorse.service")
|
||||
gitlab.wait_for_unit("gitlab.service")
|
||||
gitlab.wait_for_unit("gitlab-sidekiq.service")
|
||||
gitlab.wait_for_file("/var/gitlab/state/tmp/sockets/gitlab.socket")
|
||||
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(
|
||||
"${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2"
|
||||
)
|
||||
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(
|
||||
"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
|
||||
adminPrivateKey = pkgs.writeText "id_ed25519" ''
|
||||
|
@ -43,7 +43,7 @@ let
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJZNonUP1ePHLrvn0W9D2hdN6zWWZYFyJc+QR6pOKQEw bob@client
|
||||
'';
|
||||
|
||||
gitoliteAdminConfSnippet = ''
|
||||
gitoliteAdminConfSnippet = pkgs.writeText "gitolite-admin-conf-snippet" ''
|
||||
repo alice-project
|
||||
RW+ = alice
|
||||
'';
|
||||
|
@ -85,55 +85,54 @@ in
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
start_all()
|
||||
|
||||
subtest "can setup ssh keys on system", sub {
|
||||
$client->mustSucceed("mkdir -p ~root/.ssh");
|
||||
$client->mustSucceed("cp ${adminPrivateKey} ~root/.ssh/id_ed25519");
|
||||
$client->mustSucceed("chmod 600 ~root/.ssh/id_ed25519");
|
||||
with subtest("can setup ssh keys on system"):
|
||||
client.succeed(
|
||||
"mkdir -p ~root/.ssh",
|
||||
"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");
|
||||
$client->mustSucceed("sudo -u alice cp ${alicePrivateKey} ~alice/.ssh/id_ed25519");
|
||||
$client->mustSucceed("sudo -u alice chmod 600 ~alice/.ssh/id_ed25519");
|
||||
with subtest("gitolite server starts"):
|
||||
server.wait_for_unit("gitolite-init.service")
|
||||
server.wait_for_unit("sshd.service")
|
||||
client.succeed("ssh gitolite@server info")
|
||||
|
||||
$client->mustSucceed("sudo -u bob mkdir -p ~bob/.ssh");
|
||||
$client->mustSucceed("sudo -u bob cp ${bobPrivateKey} ~bob/.ssh/id_ed25519");
|
||||
$client->mustSucceed("sudo -u bob chmod 600 ~bob/.ssh/id_ed25519");
|
||||
};
|
||||
with subtest("admin can clone and configure gitolite-admin.git"):
|
||||
client.succeed(
|
||||
"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 {
|
||||
$server->waitForUnit("gitolite-init.service");
|
||||
$server->waitForUnit("sshd.service");
|
||||
$client->mustSucceed('ssh gitolite@server info');
|
||||
};
|
||||
with subtest("non-admins cannot clone gitolite-admin.git"):
|
||||
client.fail("sudo -i -u alice git clone gitolite@server:gitolite-admin.git")
|
||||
client.fail("sudo -i -u bob git clone gitolite@server:gitolite-admin.git")
|
||||
|
||||
subtest "admin can clone and configure gitolite-admin.git", sub {
|
||||
$client->mustSucceed('git clone gitolite@server:gitolite-admin.git');
|
||||
$client->mustSucceed("git config --global user.name 'System Administrator'");
|
||||
$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)');
|
||||
};
|
||||
with subtest("non-admins can clone testing.git"):
|
||||
client.succeed("sudo -i -u alice git clone gitolite@server:testing.git")
|
||||
client.succeed("sudo -i -u bob git clone gitolite@server:testing.git")
|
||||
|
||||
subtest "non-admins cannot clone gitolite-admin.git", sub {
|
||||
$client->mustFail('sudo -i -u alice git clone gitolite@server:gitolite-admin.git');
|
||||
$client->mustFail('sudo -i -u bob git clone gitolite@server:gitolite-admin.git');
|
||||
};
|
||||
with subtest("alice can clone alice-project.git"):
|
||||
client.succeed("sudo -i -u alice git clone gitolite@server:alice-project.git")
|
||||
|
||||
subtest "non-admins can clone testing.git", sub {
|
||||
$client->mustSucceed('sudo -i -u alice git clone gitolite@server:testing.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');
|
||||
};
|
||||
with subtest("bob cannot clone alice-project.git"):
|
||||
client.fail("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
|
||||
client = { pkgs, ... } : {
|
||||
|
@ -39,27 +39,29 @@ in {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
$server1->waitForUnit("glusterd.service");
|
||||
$server2->waitForUnit("glusterd.service");
|
||||
server1.wait_for_unit("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
|
||||
$server1->succeed("sleep 2");
|
||||
$server1->succeed("gluster peer probe server2");
|
||||
$server1->succeed("gluster peer probe server1");
|
||||
server1.succeed("gluster peer probe server2")
|
||||
server1.succeed("gluster peer probe server1")
|
||||
|
||||
$server1->succeed("gluster peer status | grep Connected");
|
||||
server1.succeed("gluster peer status | grep Connected")
|
||||
|
||||
# create volumes
|
||||
$server1->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 start gv0");
|
||||
server1.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 start gv0")
|
||||
|
||||
# test clients
|
||||
$client1->waitForUnit("gluster.mount");
|
||||
$client2->waitForUnit("gluster.mount");
|
||||
client1.wait_for_unit("gluster.mount")
|
||||
client2.wait_for_unit("gluster.mount")
|
||||
|
||||
$client1->succeed("echo test > /gluster/file1");
|
||||
$client2->succeed("grep test /gluster/file1");
|
||||
client1.succeed("echo 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
|
||||
inherit (import ./../ssh-keys.nix pkgs)
|
||||
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 {
|
||||
name = "google-oslogin";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
|
@ -15,38 +22,49 @@ in {
|
|||
client = { ... }: {};
|
||||
};
|
||||
testScript = ''
|
||||
startAll;
|
||||
start_all()
|
||||
|
||||
$server->waitForUnit("mock-google-metadata.service");
|
||||
$server->waitForOpenPort(80);
|
||||
server.wait_for_unit("mock-google-metadata.service")
|
||||
server.wait_for_open_port(80)
|
||||
|
||||
# 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('${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys mockadmin | grep -q "${snakeOilPublicKey}"');
|
||||
server.succeed(
|
||||
'${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
|
||||
$client->succeed("mkdir -p ~/.ssh");
|
||||
$client->succeed("cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil");
|
||||
$client->succeed("chmod 600 ~/.ssh/id_snakeoil");
|
||||
# install snakeoil ssh key on the client, and provision .ssh/config file
|
||||
client.succeed("mkdir -p ~/.ssh")
|
||||
client.succeed(
|
||||
"cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil"
|
||||
)
|
||||
client.succeed("chmod 600 ~/.ssh/id_snakeoil")
|
||||
client.succeed("cp ${ssh-config} ~/.ssh/config")
|
||||
|
||||
$client->waitForUnit("network.target");
|
||||
$server->waitForUnit("sshd.service");
|
||||
client.wait_for_unit("network.target")
|
||||
server.wait_for_unit("sshd.service")
|
||||
|
||||
# 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
|
||||
$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
|
||||
$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
|
||||
$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
|
||||
$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
|
||||
$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";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ ma27 ];
|
||||
|
@ -14,32 +14,32 @@ import ./make-test.nix ({ pkgs, lib, ...} : {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
machine.start()
|
||||
|
||||
$machine->waitForUnit("gotify-server");
|
||||
$machine->waitForOpenPort(3000);
|
||||
machine.wait_for_unit("gotify-server.service")
|
||||
machine.wait_for_open_port(3000)
|
||||
|
||||
my $token = $machine->succeed(
|
||||
"curl --fail -sS -X POST localhost:3000/application -F name=nixos " .
|
||||
'-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" ' .
|
||||
'| jq .token | xargs echo -n'
|
||||
);
|
||||
token = machine.succeed(
|
||||
"curl --fail -sS -X POST localhost:3000/application -F name=nixos "
|
||||
+ '-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" '
|
||||
+ "| jq .token | xargs echo -n"
|
||||
)
|
||||
|
||||
my $usertoken = $machine->succeed(
|
||||
"curl --fail -sS -X POST localhost:3000/client -F name=nixos " .
|
||||
'-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" ' .
|
||||
'| jq .token | xargs echo -n'
|
||||
);
|
||||
usertoken = machine.succeed(
|
||||
"curl --fail -sS -X POST localhost:3000/client -F name=nixos "
|
||||
+ '-H "Authorization: Basic $(echo -ne "admin:admin" | base64 --wrap 0)" '
|
||||
+ "| jq .token | xargs echo -n"
|
||||
)
|
||||
|
||||
$machine->succeed(
|
||||
"curl --fail -sS -X POST 'localhost:3000/message?token=$token' -H 'Accept: application/json' " .
|
||||
'-F title=Gotify -F message=Works'
|
||||
);
|
||||
machine.succeed(
|
||||
f"curl --fail -sS -X POST 'localhost:3000/message?token={token}' -H 'Accept: application/json' "
|
||||
+ "-F title=Gotify -F message=Works"
|
||||
)
|
||||
|
||||
my $title = $machine->succeed(
|
||||
"curl --fail -sS 'localhost:3000/message?since=0&token=$usertoken' | jq '.messages|.[0]|.title' | xargs echo -n"
|
||||
);
|
||||
title = machine.succeed(
|
||||
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";
|
||||
meta.maintainers = with lib.maintainers; [ ma27 ];
|
||||
|
||||
|
@ -64,48 +64,52 @@ import ./make-test.nix ({ pkgs, lib, ... }: {
|
|||
facility = "Test";
|
||||
});
|
||||
in ''
|
||||
$machine->start;
|
||||
$machine->waitForUnit("graylog.service");
|
||||
$machine->waitForOpenPort(9000);
|
||||
$machine->succeed("curl -sSfL http://127.0.0.1:9000/");
|
||||
machine.start()
|
||||
machine.wait_for_unit("graylog.service")
|
||||
machine.wait_for_open_port(9000)
|
||||
machine.succeed("curl -sSfL http://127.0.0.1:9000/")
|
||||
|
||||
my $session = $machine->succeed("curl -X POST "
|
||||
. "-sSfL http://127.0.0.1:9000/api/system/sessions "
|
||||
. "-d \$(cat ${payloads.login}) "
|
||||
. "-H 'Content-Type: application/json' "
|
||||
. "-H 'Accept: application/json' "
|
||||
. "-H 'x-requested-by: cli' "
|
||||
. "| jq .session_id | xargs echo"
|
||||
);
|
||||
session = machine.succeed(
|
||||
"curl -X POST "
|
||||
+ "-sSfL http://127.0.0.1:9000/api/system/sessions "
|
||||
+ "-d $(cat ${payloads.login}) "
|
||||
+ "-H 'Content-Type: application/json' "
|
||||
+ "-H 'Accept: application/json' "
|
||||
+ "-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 "
|
||||
. "-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.wait_until_succeeds(
|
||||
"test \"$(curl -sSfL 'http://127.0.0.1:9000/api/cluster/inputstates' "
|
||||
+ f"-u {session}:session "
|
||||
+ "-H 'Accept: application/json' "
|
||||
+ "-H 'Content-Type: application/json' "
|
||||
+ "-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' "
|
||||
. "-u $session:session "
|
||||
. "-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("echo -n \$(cat ${payloads.gelf_message}) | nc -w10 -u 127.0.0.1 12201");
|
||||
|
||||
$machine->succeed("test \"\$(curl -X GET "
|
||||
. "-sSfL 'http://127.0.0.1:9000/api/search/universal/relative?query=*' "
|
||||
. "-u $session:session "
|
||||
. "-H 'Accept: application/json' "
|
||||
. "-H 'Content-Type: application/json' "
|
||||
. "-H 'x-requested-by: cli'"
|
||||
. " | jq '.total_results' | xargs echo)\" = \"1\""
|
||||
);
|
||||
machine.succeed(
|
||||
'test "$(curl -X GET '
|
||||
+ "-sSfL 'http://127.0.0.1:9000/api/search/universal/relative?query=*' "
|
||||
+ f"-u {session}:session "
|
||||
+ "-H 'Accept: application/json' "
|
||||
+ "-H 'Content-Type: application/json' "
|
||||
+ "-H 'x-requested-by: cli'"
|
||||
+ ' | jq \'.total_results\' | xargs echo)" = "1"'
|
||||
)
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import ./make-test.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
let
|
||||
# Download Big Buck Bunny example, licensed under CC Attribution 3.0.
|
||||
testMkv = pkgs.fetchurl {
|
||||
|
@ -19,7 +19,13 @@ in {
|
|||
testScript = ''
|
||||
# Test MP4 and MKV transcoding. Since this is a short clip, transcoding typically
|
||||
# only takes a few seconds.
|
||||
$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");
|
||||
start_all()
|
||||
|
||||
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.
|
||||
|
||||
import ./make-test.nix (pkgs: {
|
||||
import ./make-test-python.nix (pkgs: {
|
||||
name = "hibernate";
|
||||
|
||||
nodes = {
|
||||
|
@ -28,16 +28,17 @@ import ./make-test.nix (pkgs: {
|
|||
|
||||
testScript =
|
||||
''
|
||||
$machine->waitForUnit("multi-user.target");
|
||||
$machine->succeed("mkswap /dev/vdb");
|
||||
$machine->succeed("swapon -a");
|
||||
$machine->startJob("listener");
|
||||
$machine->waitForOpenPort(4444);
|
||||
$machine->succeed("systemctl hibernate &");
|
||||
$machine->waitForShutdown;
|
||||
$probe->waitForUnit("multi-user.target");
|
||||
$machine->start;
|
||||
$probe->waitUntilSucceeds("echo test | nc machine 4444 -N");
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.succeed("mkswap /dev/vdb")
|
||||
machine.succeed("swapon -a")
|
||||
machine.start_job("listener")
|
||||
machine.wait_for_open_port(4444)
|
||||
machine.succeed("systemctl hibernate &")
|
||||
machine.wait_for_shutdown()
|
||||
probe.wait_for_unit("multi-user.target")
|
||||
machine.start()
|
||||
probe.wait_until_succeeds("echo test | nc machine 4444 -N")
|
||||
'';
|
||||
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Test whether `houndd` indexes nixpkgs
|
||||
import ./make-test.nix ({ pkgs, ... } : {
|
||||
import ./make-test-python.nix ({ pkgs, ... } : {
|
||||
name = "hound";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ grahamc ];
|
||||
|
@ -46,13 +46,14 @@ import ./make-test.nix ({ pkgs, ... } : {
|
|||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
'' startAll;
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
$machine->waitForUnit("network.target");
|
||||
$machine->waitForUnit("hound.service");
|
||||
$machine->waitForOpenPort(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_for_unit("network.target")
|
||||
machine.wait_for_unit("hound.service")
|
||||
machine.wait_for_open_port(6080)
|
||||
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";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ das_j ];
|
||||
|
@ -64,8 +64,8 @@ import ./make-test.nix ({ pkgs, ... }: {
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll();
|
||||
$icingaweb2->waitForUnit("multi-user.target");
|
||||
$icingaweb2->succeed("curl -sSf http://icingaweb2/authentication/login");
|
||||
start_all()
|
||||
icingaweb2.wait_for_unit("multi-user.target")
|
||||
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;
|
||||
|
||||
|
@ -18,17 +18,16 @@ with lib;
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
subtest "machine with iftop enabled", sub {
|
||||
$withIftop->waitForUnit("default.target");
|
||||
# limit to eth1 (eth0 is the test driver's control interface)
|
||||
# and don't try name lookups
|
||||
$withIftop->succeed("su -l alice -c 'iftop -t -s 1 -n -i eth1'");
|
||||
};
|
||||
subtest "machine without iftop", sub {
|
||||
$withoutIftop->waitForUnit("default.target");
|
||||
# check that iftop is there but user alice lacks capabilities
|
||||
$withoutIftop->succeed("iftop -t -s 1 -n -i eth1");
|
||||
$withoutIftop->fail("su -l alice -c 'iftop -t -s 1 -n -i eth1'");
|
||||
};
|
||||
with subtest("machine with iftop enabled"):
|
||||
withIftop.wait_for_unit("default.target")
|
||||
# limit to eth1 (eth0 is the test driver's control interface)
|
||||
# and don't try name lookups
|
||||
withIftop.succeed("su -l alice -c 'iftop -t -s 1 -n -i eth1'")
|
||||
|
||||
with subtest("machine without iftop"):
|
||||
withoutIftop.wait_for_unit("default.target")
|
||||
# check that iftop is there but user alice lacks capabilitie
|
||||
withoutIftop.succeed("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";
|
||||
|
@ -19,34 +19,34 @@ import ./make-test.nix ({ pkgs, lib, ... }:
|
|||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
start_all()
|
||||
|
||||
$machine->waitForUnit("multi-user.target");
|
||||
$machine->waitForUnit("incron.service");
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.wait_for_unit("incron.service")
|
||||
|
||||
$machine->succeed("test -d /test");
|
||||
machine.succeed("test -d /test")
|
||||
# create some activity for incron to monitor
|
||||
$machine->succeed("touch /test/file");
|
||||
$machine->succeed("echo foo >> /test/file");
|
||||
$machine->succeed("mv /test/file /root");
|
||||
$machine->succeed("mv /root/file /test");
|
||||
machine.succeed("touch /test/file")
|
||||
machine.succeed("echo foo >> /test/file")
|
||||
machine.succeed("mv /test/file /root")
|
||||
machine.succeed("mv /root/file /test")
|
||||
|
||||
$machine->sleep(1);
|
||||
machine.sleep(1)
|
||||
|
||||
# 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
|
||||
$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_MODIFY' /root/incron.log")
|
||||
machine.succeed("grep '/test/file IN_CLOSE_WRITE' /root/incron.log")
|
||||
|
||||
# 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
|
||||
$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
|
||||
$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
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test-python.nix ({ pkgs, ...} : {
|
||||
name = "influxdb";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ offline ];
|
||||
|
@ -9,25 +9,32 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
nodes = {
|
||||
one = { ... }: {
|
||||
services.influxdb.enable = true;
|
||||
environment.systemPackages = [ pkgs.httpie ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
|
||||
$one->waitForUnit("influxdb.service");
|
||||
import shlex
|
||||
|
||||
start_all()
|
||||
|
||||
one.wait_for_unit("influxdb.service")
|
||||
|
||||
# create database
|
||||
$one->succeed(q~
|
||||
curl -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE test"
|
||||
~);
|
||||
one.succeed(
|
||||
"curl -XPOST http://localhost:8086/query --data-urlencode 'q=CREATE DATABASE test'"
|
||||
)
|
||||
|
||||
# write some points and run simple query
|
||||
$one->succeed(q~
|
||||
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"
|
||||
~);
|
||||
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'"
|
||||
)
|
||||
|
||||
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