Skip to content

Commit bdb0fa3

Browse files
committed
Fix running on Nix
1 parent d6fc8f9 commit bdb0fa3

File tree

7 files changed

+237
-1
lines changed

7 files changed

+237
-1
lines changed

.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use nix

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
tmp/
55
/target
66
roles/create-vm/files/guest-files/spice-guest-tools.exe
7+
/.direnv

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ It also assumes that the Kubernetes cluster and Windows VM will be running on th
2727

2828
In addition, for a completely unattended installation, the ISO must be patched using cdrtools.
2929

30+
When using Nix, you *need* to run inside `direnv` or `nix-shell` (which will provide Ansible for you). Nixpkgs's regular Ansible is *not* enough.
31+
3032
## Using it
3133

3234
1. Put your Windows ISO in `target/Windows Server 2022 EVAL.iso` (or modify `install_iso_windows` to point at it)
3335
2. Run `ansible-playbook install.yaml -i inventory.ini`
3436
3. Open virt-manager
3537
4. When the VM appears, open it and answer the "press any key to boot" prompt (reboot the VM if you missed it)
3638
5. Wait for the playbook to complete
37-
6. Done!
39+
6. Done!
3840

3941
### Completely unattended (noprompt patch)
4042

install.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
- name: Load Python path override
2+
hosts: localhost
3+
tasks:
4+
- set_fact:
5+
ansible_python_interpreter: "{{ lookup('ansible.builtin.env', 'ANSIBLE_PYTHON_INTERPRETER') }}"
16
- name: Create VM and install Windows
27
hosts: localhost
38
roles:

nix/sources.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"nixpkgs": {
3+
"branch": "nixos-unstable",
4+
"description": "Nix Packages collection",
5+
"homepage": null,
6+
"owner": "NixOS",
7+
"repo": "nixpkgs",
8+
"rev": "8a3354191c0d7144db9756a74755672387b702ba",
9+
"sha256": "0awagdjzv2fsy5v7a0wxz1hd642gsglib2gk4lnqm0iybly7kf0s",
10+
"type": "tarball",
11+
"url": "https://github.com/NixOS/nixpkgs/archive/8a3354191c0d7144db9756a74755672387b702ba.tar.gz",
12+
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13+
}
14+
}

nix/sources.nix

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# This file has been generated by Niv.
2+
3+
let
4+
5+
#
6+
# The fetchers. fetch_<type> fetches specs of type <type>.
7+
#
8+
9+
fetch_file = pkgs: name: spec:
10+
let
11+
name' = sanitizeName name + "-src";
12+
in
13+
if spec.builtin or true then
14+
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
15+
else
16+
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
17+
18+
fetch_tarball = pkgs: name: spec:
19+
let
20+
name' = sanitizeName name + "-src";
21+
in
22+
if spec.builtin or true then
23+
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
24+
else
25+
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
26+
27+
fetch_git = name: spec:
28+
let
29+
ref =
30+
spec.ref or (
31+
if spec ? branch then "refs/heads/${spec.branch}" else
32+
if spec ? tag then "refs/tags/${spec.tag}" else
33+
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"
34+
);
35+
submodules = spec.submodules or false;
36+
submoduleArg =
37+
let
38+
nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0;
39+
emptyArgWithWarning =
40+
if submodules
41+
then
42+
builtins.trace
43+
(
44+
"The niv input \"${name}\" uses submodules "
45+
+ "but your nix's (${builtins.nixVersion}) builtins.fetchGit "
46+
+ "does not support them"
47+
)
48+
{ }
49+
else { };
50+
in
51+
if nixSupportsSubmodules
52+
then { inherit submodules; }
53+
else emptyArgWithWarning;
54+
in
55+
builtins.fetchGit
56+
({ url = spec.repo; inherit (spec) rev; inherit ref; } // submoduleArg);
57+
58+
fetch_local = spec: spec.path;
59+
60+
fetch_builtin-tarball = name: throw
61+
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
62+
$ niv modify ${name} -a type=tarball -a builtin=true'';
63+
64+
fetch_builtin-url = name: throw
65+
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
66+
$ niv modify ${name} -a type=file -a builtin=true'';
67+
68+
#
69+
# Various helpers
70+
#
71+
72+
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
73+
sanitizeName = name:
74+
(
75+
concatMapStrings (s: if builtins.isList s then "-" else s)
76+
(
77+
builtins.split "[^[:alnum:]+._?=-]+"
78+
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
79+
)
80+
);
81+
82+
# The set of packages used when specs are fetched using non-builtins.
83+
mkPkgs = sources: system:
84+
let
85+
sourcesNixpkgs =
86+
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
87+
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
88+
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
89+
in
90+
if builtins.hasAttr "nixpkgs" sources
91+
then sourcesNixpkgs
92+
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
93+
import <nixpkgs> { }
94+
else
95+
abort
96+
''
97+
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
98+
add a package called "nixpkgs" to your sources.json.
99+
'';
100+
101+
# The actual fetching function.
102+
fetch = pkgs: name: spec:
103+
104+
if ! builtins.hasAttr "type" spec then
105+
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
106+
else if spec.type == "file" then fetch_file pkgs name spec
107+
else if spec.type == "tarball" then fetch_tarball pkgs name spec
108+
else if spec.type == "git" then fetch_git name spec
109+
else if spec.type == "local" then fetch_local spec
110+
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
111+
else if spec.type == "builtin-url" then fetch_builtin-url name
112+
else
113+
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
114+
115+
# If the environment variable NIV_OVERRIDE_${name} is set, then use
116+
# the path directly as opposed to the fetched source.
117+
replace = name: drv:
118+
let
119+
saneName = stringAsChars (c: if (builtins.match "[a-zA-Z0-9]" c) == null then "_" else c) name;
120+
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
121+
in
122+
if ersatz == "" then drv else
123+
# this turns the string into an actual Nix path (for both absolute and
124+
# relative paths)
125+
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
126+
127+
# Ports of functions for older nix versions
128+
129+
# a Nix version of mapAttrs if the built-in doesn't exist
130+
mapAttrs = builtins.mapAttrs or (
131+
f: set: with builtins;
132+
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
133+
);
134+
135+
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
136+
range = first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1);
137+
138+
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
139+
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
140+
141+
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
142+
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
143+
concatMapStrings = f: list: concatStrings (map f list);
144+
concatStrings = builtins.concatStringsSep "";
145+
146+
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
147+
optionalAttrs = cond: as: if cond then as else { };
148+
149+
# fetchTarball version that is compatible between all the versions of Nix
150+
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
151+
let
152+
inherit (builtins) lessThan nixVersion fetchTarball;
153+
in
154+
if lessThan nixVersion "1.12" then
155+
fetchTarball ({ inherit url; } // (optionalAttrs (name != null) { inherit name; }))
156+
else
157+
fetchTarball attrs;
158+
159+
# fetchurl version that is compatible between all the versions of Nix
160+
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
161+
let
162+
inherit (builtins) lessThan nixVersion fetchurl;
163+
in
164+
if lessThan nixVersion "1.12" then
165+
fetchurl ({ inherit url; } // (optionalAttrs (name != null) { inherit name; }))
166+
else
167+
fetchurl attrs;
168+
169+
# Create the final "sources" from the config
170+
mkSources = config:
171+
mapAttrs
172+
(
173+
name: spec:
174+
if builtins.hasAttr "outPath" spec
175+
then
176+
abort
177+
"The values in sources.json should not have an 'outPath' attribute"
178+
else
179+
spec // { outPath = replace name (fetch config.pkgs name spec); }
180+
)
181+
config.sources;
182+
183+
# The "config" used by the fetchers
184+
mkConfig =
185+
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
186+
, sources ? if sourcesFile == null then { } else builtins.fromJSON (builtins.readFile sourcesFile)
187+
, system ? builtins.currentSystem
188+
, pkgs ? mkPkgs sources system
189+
}: rec {
190+
# The sources, i.e. the attribute set of spec name to spec
191+
inherit sources;
192+
193+
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
194+
inherit pkgs;
195+
};
196+
197+
in
198+
mkSources (mkConfig { }) // { __functor = _: settings: mkSources (mkConfig settings); }

shell.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{ sources ? import nix/sources.nix
2+
, pkgs ? import sources.nixpkgs {} }:
3+
4+
with pkgs;
5+
6+
mkShell {
7+
buildInputs = [ pkgs.ansible ];
8+
9+
# Ansible runs modules in a separate interpreter, which bypasses Nix's added packages
10+
# Hence, override that interpreter with one that has the required dependencies installed
11+
ANSIBLE_PYTHON_INTERPRETER = pkgs.python3.withPackages (pkgs: [
12+
# community.libvirt
13+
pkgs.libvirt pkgs.lxml
14+
]) + "/bin/python";
15+
}

0 commit comments

Comments
 (0)