1{ lib, pkgs, ... }:
2
3let
4 inherit (import ./ssh-keys.nix pkgs)
5 snakeOilPrivateKey
6 snakeOilPublicKey
7 ;
8
9 metadataDrive = pkgs.stdenv.mkDerivation {
10 name = "metadata";
11 buildCommand = ''
12 mkdir -p $out/iso
13
14 cat << EOF > $out/iso/user-data
15 #cloud-config
16 write_files:
17 - content: |
18 cloudinit
19 path: /tmp/cloudinit-write-file
20
21 users:
22 - default
23 - name: nixos
24 ssh_authorized_keys:
25 - "${snakeOilPublicKey}"
26 EOF
27
28 cat << EOF > $out/iso/meta-data
29 instance-id: iid-local01
30 local-hostname: "test"
31 public-keys:
32 - "${snakeOilPublicKey}"
33 EOF
34
35 cat << EOF > $out/iso/network-config
36 version: 1
37 config:
38 - type: physical
39 name: eth0
40 mac_address: '52:54:00:12:34:56'
41 subnets:
42 - type: static
43 address: '12.34.56.78'
44 netmask: '255.255.255.0'
45 gateway: '12.34.56.9'
46 - type: nameserver
47 address:
48 - '6.7.8.9'
49 search:
50 - 'example.com'
51 EOF
52 ${pkgs.cdrkit}/bin/genisoimage -volid cidata -joliet -rock -o $out/metadata.iso $out/iso
53 '';
54 };
55
56in
57{
58 name = "cloud-init";
59 meta.maintainers = with lib.maintainers; [
60 lewo
61 illustris
62 ];
63 nodes.machine = {
64 virtualisation.qemu.options = [
65 "-cdrom"
66 "${metadataDrive}/metadata.iso"
67 ];
68 services.cloud-init = {
69 enable = true;
70 network.enable = true;
71 };
72 services.openssh.enable = true;
73 networking.hostName = "";
74 networking.useDHCP = false;
75 };
76 testScript = ''
77 # To wait until cloud-init terminates its run
78 unnamed.wait_for_unit("cloud-init-local.service")
79 unnamed.wait_for_unit("cloud-final.service")
80
81 unnamed.succeed("cat /tmp/cloudinit-write-file | grep -q 'cloudinit'")
82
83 # install snakeoil ssh key and provision .ssh/config file
84 unnamed.succeed("mkdir -p ~/.ssh")
85 unnamed.succeed(
86 "cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil"
87 )
88 unnamed.succeed("chmod 600 ~/.ssh/id_snakeoil")
89
90 unnamed.wait_for_unit("sshd.service")
91
92 # we should be able to log in as the root user, as well as the created nixos user
93 unnamed.succeed(
94 "timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentityFile=~/.ssh/id_snakeoil root@localhost 'true'"
95 )
96 unnamed.succeed(
97 "timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentityFile=~/.ssh/id_snakeoil nixos@localhost 'true'"
98 )
99
100 # test changing hostname via cloud-init worked
101 assert (
102 unnamed.succeed(
103 "timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentityFile=~/.ssh/id_snakeoil nixos@localhost 'hostname'"
104 ).strip()
105 == "test"
106 )
107
108 # check IP and route configs
109 assert "default via 12.34.56.9 dev eth0 proto static" in unnamed.succeed("ip route")
110 assert "12.34.56.0/24 dev eth0 proto kernel scope link src 12.34.56.78" in unnamed.succeed("ip route")
111
112 # check nameserver and search configs
113 assert "6.7.8.9" in unnamed.succeed("resolvectl status")
114 assert "example.com" in unnamed.succeed("resolvectl status")
115
116 '';
117}