Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{
2 lib,
3 # Build helpers
4 stdenv,
5 runCommand,
6 vmTools,
7 writeClosure,
8 writeDirectReferencesToFile,
9 writeScript,
10 writeStringReferencesToFile,
11 # Native build inputs
12 buildPackages,
13 e2fsprogs,
14 util-linux,
15 # Build inputs
16 bashInteractive,
17 runtimeShell,
18 singularity,
19}:
20
21let
22 defaultSingularity = singularity;
23in
24lib.makeExtensible (final: {
25 buildImage =
26 {
27 name,
28 contents ? [ ],
29 diskSize ? 1024,
30 memSize ? 1024,
31 runAsRoot ? null,
32 runScript ? "#!${stdenv.shell}\nexec /bin/sh",
33 singularity ? defaultSingularity,
34 }:
35 let
36 projectName = singularity.projectName or "singularity";
37 runAsRootFile = buildPackages.writers.writeBash "run-as-root.sh" ''
38 set -e
39 ${runAsRoot}
40 '';
41 runScriptFile = writeScript "run-script.sh" ''
42 #!/bin/sh
43 set -e
44 ${runScript}
45 '';
46 runScriptReferences =
47 if builtins ? getContext then
48 lib.splitString "\n" (writeStringReferencesToFile runScriptFile.text).text
49 else
50 [ (writeDirectReferencesToFile runScriptFile) ];
51 result = vmTools.runInLinuxVM (
52 runCommand "${projectName}-image-${name}.sif"
53 {
54 __structuredAttrs = true;
55 nativeBuildInputs = [
56 singularity
57 e2fsprogs
58 util-linux
59 ];
60 strictDeps = true;
61 inherit contents;
62 layerClosure = writeClosure ([ bashInteractive ] ++ runScriptReferences ++ contents);
63 preVM = vmTools.createEmptyImage {
64 size = diskSize;
65 fullName = "${projectName}-run-disk";
66 # Leaving "$out" for the Singularity/Container image
67 destination = "disk-image";
68 };
69 inherit memSize;
70 }
71 ''
72 mkdir workspace
73 mkfs -t ext3 -b 4096 /dev/${vmTools.hd}
74 mount /dev/${vmTools.hd} workspace
75 mkdir -p workspace/img
76 cd workspace/img
77 mkdir proc sys dev
78
79 # Run root script
80 ${lib.optionalString (runAsRoot != null) ''
81 mkdir -p ./${builtins.storeDir}
82 mount --rbind "${builtins.storeDir}" ./${builtins.storeDir}
83 unshare -imnpuf --mount-proc chroot ./ ${runAsRootFile}
84 umount -R ./${builtins.storeDir}
85 ''}
86
87 # Build /bin and copy across closure
88 mkdir -p bin ./${builtins.storeDir}
89 # Loop over the line-separated paths in $layerClosure
90 while IFS= read -r f; do
91 cp -ar "$f" "./$f"
92 done < "$layerClosure"
93
94 for c in "''${contents[@]}"; do
95 for f in "$c"/bin/* ; do
96 if [ ! -e "bin/$(basename "$f")" ] ; then
97 ln -s "$f" bin/
98 fi
99 done
100 done
101
102 # Link /bin/sh
103 if [ ! -e bin/sh ]; then
104 ln -s ${lib.getExe bashInteractive} bin/sh
105 fi
106 mkdir -p .singularity.d
107
108 # Create runscript
109 cp "${runScriptFile}" .singularity.d/runscript
110
111 # Fill out .singularity.d
112 mkdir -p .singularity.d/env
113 touch .singularity.d/env/94-appsbase.sh
114
115 cd ..
116 mkdir -p /var/lib/${projectName}/mnt/session
117 echo "root:x:0:0:System administrator:/root:/bin/sh" > /etc/passwd
118 echo > /etc/resolv.conf
119 TMPDIR="$(pwd -P)" ${projectName} build "$out" ./img
120 ''
121 );
122
123 in
124 result;
125})