confctl 2.2.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/.git-hooks/pre_commit/nixfmt.rb +13 -0
  3. data/.github/workflows/rspec.yml +64 -0
  4. data/.github/workflows/rubocop.yml +27 -0
  5. data/.github/workflows/tests.yml +139 -0
  6. data/.gitignore +12 -7
  7. data/.overcommit.yml +2 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +8 -1
  10. data/AGENTS.md +42 -0
  11. data/CHANGELOG.md +57 -0
  12. data/Gemfile +3 -2
  13. data/Gemfile.lock +198 -0
  14. data/README.md +166 -58
  15. data/Rakefile +5 -0
  16. data/confctl.gemspec +20 -2
  17. data/docs/carrier.md +3 -3
  18. data/docs/flake-inputs.md +159 -0
  19. data/docs/swpins-to-flakes.md +325 -0
  20. data/example/cluster/module-list.nix +2 -1
  21. data/example/cluster/nixos-machine/config.nix +12 -2
  22. data/example/cluster/nixos-machine/hardware.nix +6 -1
  23. data/example/cluster/vpsadminos-container/config.nix +6 -1
  24. data/example/cluster/vpsadminos-container/module.nix +4 -1
  25. data/example/cluster/vpsadminos-machine/config.nix +6 -1
  26. data/example/cluster/vpsadminos-machine/hardware.nix +6 -1
  27. data/example/cluster/vpsadminos-machine/module.nix +5 -2
  28. data/example/cluster/vpsfreecz-vps/config.nix +6 -1
  29. data/example/cluster/vpsfreecz-vps/module.nix +4 -1
  30. data/example/configs/swpins.nix +8 -3
  31. data/example/environments/base.nix +6 -1
  32. data/example/swpins/core.json +35 -0
  33. data/example-flake/.gitignore +2 -0
  34. data/example-flake/README.md +38 -0
  35. data/example-flake/cluster/cluster.nix +5 -0
  36. data/example-flake/cluster/module-list.nix +4 -0
  37. data/example-flake/cluster/nested/nixos-machine/config.nix +25 -0
  38. data/example-flake/cluster/nested/nixos-machine/hardware.nix +9 -0
  39. data/example-flake/cluster/nested/nixos-machine/module.nix +8 -0
  40. data/example-flake/cluster/nixos-machine/config.nix +25 -0
  41. data/example-flake/cluster/nixos-machine/hardware.nix +9 -0
  42. data/example-flake/cluster/nixos-machine/module.nix +8 -0
  43. data/example-flake/cluster/vpsadminos-container/config.nix +28 -0
  44. data/example-flake/cluster/vpsadminos-container/module.nix +8 -0
  45. data/example-flake/cluster/vpsadminos-machine/config.nix +27 -0
  46. data/example-flake/cluster/vpsadminos-machine/hardware.nix +9 -0
  47. data/example-flake/cluster/vpsadminos-machine/module.nix +8 -0
  48. data/example-flake/cluster/vpsfreecz-vps/config.nix +31 -0
  49. data/example-flake/cluster/vpsfreecz-vps/module.nix +8 -0
  50. data/example-flake/configs/confctl.nix +10 -0
  51. data/example-flake/data/default.nix +5 -0
  52. data/example-flake/data/ssh-keys.nix +7 -0
  53. data/example-flake/environments/base.nix +18 -0
  54. data/example-flake/flake.lock +75 -0
  55. data/example-flake/flake.nix +36 -0
  56. data/example-flake/modules/module-list.nix +13 -0
  57. data/example-flake/shell.nix +11 -0
  58. data/flake.lock +159 -0
  59. data/flake.nix +189 -0
  60. data/gemset.nix +1022 -0
  61. data/lib/confctl/cli/app.rb +145 -0
  62. data/lib/confctl/cli/attr_filters.rb +1 -1
  63. data/lib/confctl/cli/cluster.rb +681 -108
  64. data/lib/confctl/cli/command.rb +24 -2
  65. data/lib/confctl/cli/configuration.rb +171 -106
  66. data/lib/confctl/cli/generation.rb +65 -1
  67. data/lib/confctl/cli/inputs/channels.rb +190 -0
  68. data/lib/confctl/cli/inputs/machines.rb +83 -0
  69. data/lib/confctl/cli/inputs/root.rb +101 -0
  70. data/lib/confctl/cli/inputs.rb +5 -0
  71. data/lib/confctl/cli/log_view.rb +21 -10
  72. data/lib/confctl/cli/migrate/swpins_to_flakes.rb +866 -0
  73. data/lib/confctl/cli/migrate.rb +5 -0
  74. data/lib/confctl/cli/output_formatter.rb +5 -7
  75. data/lib/confctl/cli/swpins/base.rb +9 -0
  76. data/lib/confctl/cli/swpins/channel.rb +2 -5
  77. data/lib/confctl/cli/swpins/cluster.rb +2 -5
  78. data/lib/confctl/cli/swpins/core.rb +2 -5
  79. data/lib/confctl/config_type.rb +7 -0
  80. data/lib/confctl/flake_lock.rb +78 -0
  81. data/lib/confctl/flake_lock_diff.rb +36 -0
  82. data/lib/confctl/generation/build.rb +131 -24
  83. data/lib/confctl/generation/build_list.rb +4 -3
  84. data/lib/confctl/generation/unified.rb +14 -1
  85. data/lib/confctl/git_repo_mirror.rb +2 -2
  86. data/lib/confctl/health_checks/run_command.rb +3 -2
  87. data/lib/confctl/health_checks/systemd/properties.rb +1 -1
  88. data/lib/confctl/health_checks/systemd/property_list.rb +2 -2
  89. data/lib/confctl/inputs/commit_message.rb +125 -0
  90. data/lib/confctl/inputs/git_commit.rb +17 -0
  91. data/lib/confctl/inputs/nix_output_guard.rb +37 -0
  92. data/lib/confctl/inputs/setter.rb +179 -0
  93. data/lib/confctl/inputs/updater.rb +76 -0
  94. data/lib/confctl/inputs.rb +5 -0
  95. data/lib/confctl/inputs_info.rb +50 -0
  96. data/lib/confctl/line_buffer.rb +1 -1
  97. data/lib/confctl/machine.rb +18 -3
  98. data/lib/confctl/machine_control.rb +8 -2
  99. data/lib/confctl/machine_list.rb +2 -2
  100. data/lib/confctl/machine_status.rb +63 -20
  101. data/lib/confctl/nix/args.rb +48 -0
  102. data/lib/confctl/nix.rb +30 -437
  103. data/lib/confctl/nix_build_flake.rb +95 -0
  104. data/lib/confctl/nix_copy.rb +14 -2
  105. data/lib/confctl/nix_flake.rb +449 -0
  106. data/lib/confctl/nix_format.rb +3 -3
  107. data/lib/confctl/nix_legacy.rb +467 -0
  108. data/lib/confctl/swpins/change_set.rb +29 -3
  109. data/lib/confctl/swpins/specs/base.rb +2 -2
  110. data/lib/confctl/ui.rb +19 -0
  111. data/lib/confctl/version.rb +1 -1
  112. data/man/index.html +11 -0
  113. data/man/man8/confctl-options.nix.8.html +113 -0
  114. data/man/man8/confctl.8 +152 -21
  115. data/man/man8/confctl.8.html +355 -0
  116. data/man/man8/confctl.8.md +148 -17
  117. data/man/style.css +301 -0
  118. data/nix/evaluator.nix +94 -69
  119. data/nix/flake/mk-confctl-devshell.nix +85 -0
  120. data/nix/flake/mk-confctl-outputs.nix +522 -0
  121. data/nix/flake/mk-config-devshell.nix +168 -0
  122. data/nix/lib/default.nix +118 -65
  123. data/nix/lib/machine/default.nix +65 -45
  124. data/nix/lib/machine/info.nix +16 -5
  125. data/nix/lib/swpins/eval.nix +42 -29
  126. data/nix/lib/swpins/options.nix +6 -2
  127. data/nix/machines.nix +23 -15
  128. data/nix/modules/cluster/default.nix +104 -41
  129. data/nix/modules/confctl/carrier/base.nix +11 -4
  130. data/nix/modules/confctl/carrier/carrier-env.rb +2 -2
  131. data/nix/modules/confctl/carrier/netboot/build-netboot-server.rb +50 -16
  132. data/nix/modules/confctl/carrier/netboot/nixos.nix +56 -24
  133. data/nix/modules/confctl/configuration-info.nix +17 -0
  134. data/nix/modules/confctl/generations.nix +2 -2
  135. data/nix/modules/confctl/host.nix +13 -0
  136. data/nix/modules/confctl/inputs-info.nix +21 -0
  137. data/nix/modules/confctl/kexec-netboot/default.nix +13 -6
  138. data/nix/modules/confctl/kexec-netboot/kexec-netboot.8.adoc +3 -0
  139. data/nix/modules/confctl/kexec-netboot/kexec-netboot.rb +25 -16
  140. data/nix/modules/confctl/nix.nix +31 -1
  141. data/nix/modules/confctl/swpins.nix +13 -6
  142. data/nix/modules/module-list.nix +4 -2
  143. data/nix/modules/system-list.nix +4 -1
  144. data/nix/package.nix +37 -0
  145. data/shell.nix +39 -8
  146. data/skills/confctl-configuration-update/SKILL.md +228 -0
  147. data/skills/confctl-configuration-update/agents/openai.yaml +4 -0
  148. data/skills/confctl-release/SKILL.md +102 -0
  149. data/skills/confctl-release/agents/openai.yaml +4 -0
  150. data/spec/confctl/cli/cluster_health_check_spec.rb +43 -0
  151. data/spec/confctl/cli/cluster_skip_current_deploy_spec.rb +157 -0
  152. data/spec/confctl/cli/cluster_status_flake_spec.rb +83 -0
  153. data/spec/confctl/cli/inputs_set_output_spec.rb +70 -0
  154. data/spec/confctl/configuration_spec.rb +45 -0
  155. data/spec/confctl/inputs_spec.rb +104 -0
  156. data/spec/confctl/machine_control_spec.rb +112 -0
  157. data/spec/confctl/machine_list_spec.rb +47 -0
  158. data/spec/confctl/nix_flake_spec.rb +41 -0
  159. data/spec/confctl/swpins_spec.rb +106 -0
  160. data/spec/generation/build_modes_spec.rb +132 -0
  161. data/spec/inputs/commit_message_spec.rb +205 -0
  162. data/spec/inputs/nix_cached_fallback_spec.rb +50 -0
  163. data/spec/inputs/nix_output_guard_spec.rb +45 -0
  164. data/spec/spec_helper.rb +12 -0
  165. data/spec/support/cli_helper.rb +57 -0
  166. data/test-runner.sh +7 -0
  167. data/tests/all-tests.nix +30 -0
  168. data/tests/make-test.nix +15 -0
  169. data/tests/runner/extensions/confctl_helpers.rb +238 -0
  170. data/tests/runner/extensions/hostfwd_ports.rb +41 -0
  171. data/tests/suite/auto_rollback.nix +344 -0
  172. data/tests/suite/carrier/deploy.nix +751 -0
  173. data/tests/suite/carrier/netboot.nix +849 -0
  174. data/tests/suite/deploy/base.nix +806 -0
  175. data/tests/suite/deploy/flakes.nix +1 -0
  176. data/tests/suite/deploy/swpins.nix +1 -0
  177. metadata +104 -4
  178. data/nix/modules/confctl/overlays.nix +0 -15
@@ -1,17 +1,31 @@
1
- { config, lib, confLib, ... }@args:
1
+ {
2
+ config,
3
+ lib,
4
+ confLib,
5
+ ...
6
+ }@args:
2
7
  with lib;
3
8
  let
4
9
  machine =
5
- { config, ...}:
10
+ { config, ... }:
6
11
  {
7
12
  options = {
8
13
  managed = mkOption {
9
14
  type = types.nullOr types.bool;
10
15
  default = null;
11
- apply = v:
12
- if !isNull v then v
13
- else if elem config.spin [ "nixos" "vpsadminos" ] then true
14
- else false;
16
+ apply =
17
+ v:
18
+ if !isNull v then
19
+ v
20
+ else if
21
+ elem config.spin [
22
+ "nixos"
23
+ "vpsadminos"
24
+ ]
25
+ then
26
+ true
27
+ else
28
+ false;
15
29
  description = ''
16
30
  Determines whether the machine is managed using confctl or not
17
31
 
@@ -20,23 +34,30 @@ let
20
34
  };
21
35
 
22
36
  spin = mkOption {
23
- type = types.enum [ "openvz" "nixos" "vpsadminos" "other" ];
37
+ type = types.enum [
38
+ "openvz"
39
+ "nixos"
40
+ "vpsadminos"
41
+ "other"
42
+ ];
24
43
  description = "OS type";
25
44
  };
26
45
 
27
46
  swpins = {
28
47
  channels = mkOption {
29
48
  type = types.listOf types.str;
30
- default = [];
49
+ default = [ ];
31
50
  description = ''
32
51
  List of channels from <option>confctl.swpins.channels</option>
33
52
  to use on this machine
53
+
54
+ This option is legacy in flake mode, prefer <option>cluster.&lt;name&gt;.inputs.channels</option>.
34
55
  '';
35
56
  };
36
57
 
37
58
  pins = mkOption {
38
59
  type = types.attrsOf (types.submodule swpinOptions.specModule);
39
- default = {};
60
+ default = { };
40
61
  description = ''
41
62
  List of swpins for this machine, which can supplement or
42
63
  override swpins from configured channels
@@ -44,9 +65,32 @@ let
44
65
  };
45
66
  };
46
67
 
68
+ inputs = {
69
+ channels = mkOption {
70
+ type = types.listOf types.str;
71
+ default = [ ];
72
+ description = ''
73
+ List of flake pin channels to use on this machine.
74
+
75
+ In flake mode, this selects entries from the `channels` mapping
76
+ passed to `mkConfctlOutputs` (e.g. "production", "staging", "os-staging").
77
+
78
+ This replaces legacy `swpins.channels`.
79
+ '';
80
+ };
81
+
82
+ overrides = mkOption {
83
+ type = types.attrsOf types.str;
84
+ default = { };
85
+ description = ''
86
+ Override role -> flake input mapping for this machine
87
+ '';
88
+ };
89
+ };
90
+
47
91
  addresses = mkOption {
48
92
  type = types.nullOr (types.submodule addresses);
49
- default = {};
93
+ default = { };
50
94
  description = ''
51
95
  IP addresses
52
96
  '';
@@ -56,7 +100,7 @@ let
56
100
  enable = mkEnableOption "Include this system on pxe servers";
57
101
  macs = mkOption {
58
102
  type = types.listOf types.str;
59
- default = [];
103
+ default = [ ];
60
104
  description = ''
61
105
  List of MAC addresses for iPXE node auto-detection
62
106
  '';
@@ -65,7 +109,11 @@ let
65
109
 
66
110
  buildAttribute = mkOption {
67
111
  type = types.listOf types.str;
68
- default = [ "system" "build" "toplevel" ];
112
+ default = [
113
+ "system"
114
+ "build"
115
+ "toplevel"
116
+ ];
69
117
  description = ''
70
118
  Path to the attribute in machine system config that should be built
71
119
 
@@ -79,7 +127,7 @@ let
79
127
 
80
128
  machines = mkOption {
81
129
  type = types.listOf (types.submodule carriedMachine);
82
- default = [];
130
+ default = [ ];
83
131
  description = ''
84
132
  List of carried machines
85
133
  '';
@@ -93,7 +141,7 @@ let
93
141
 
94
142
  labels = mkOption {
95
143
  type = types.attrs;
96
- default = {};
144
+ default = { };
97
145
  description = ''
98
146
  Optional user-defined labels to classify the machine
99
147
  '';
@@ -101,7 +149,7 @@ let
101
149
 
102
150
  tags = mkOption {
103
151
  type = types.listOf types.str;
104
- default = [];
152
+ default = [ ];
105
153
  description = ''
106
154
  Optional user-defined tags to classify the machine
107
155
  '';
@@ -110,7 +158,7 @@ let
110
158
  nix = {
111
159
  nixPath = mkOption {
112
160
  type = types.listOf types.str;
113
- default = [];
161
+ default = [ ];
114
162
  description = ''
115
163
  List of extra paths added to environment variable
116
164
  <literal>NIX_PATH</literal> for <literal>nix-build</literal>
@@ -219,7 +267,10 @@ let
219
267
  systemProperties = mkOption {
220
268
  type = types.listOf (types.submodule systemdProperty);
221
269
  default = [
222
- { property = "SystemState"; value = "running"; }
270
+ {
271
+ property = "SystemState";
272
+ value = "running";
273
+ }
223
274
  ];
224
275
  description = ''
225
276
  Check systemd manager properties reported by systemctl show
@@ -228,7 +279,7 @@ let
228
279
 
229
280
  unitProperties = mkOption {
230
281
  type = types.attrsOf (types.listOf (types.submodule systemdProperty));
231
- default = {};
282
+ default = { };
232
283
  example = literalExpression ''
233
284
  {
234
285
  "firewall.service" = [
@@ -244,7 +295,7 @@ let
244
295
 
245
296
  builderCommands = mkOption {
246
297
  type = types.listOf (types.submodule checkCommand);
247
- default = [];
298
+ default = [ ];
248
299
  example = literalExpression ''
249
300
  [
250
301
  { description = "ping"; command = [ "ping" "-c1" "{host.fqdn}" ]; }
@@ -257,7 +308,7 @@ let
257
308
 
258
309
  machineCommands = mkOption {
259
310
  type = types.listOf (types.submodule checkCommand);
260
- default = [];
311
+ default = [ ];
261
312
  example = literalExpression ''
262
313
  [
263
314
  { description = "curl"; command = [ "curl" "-s" "http://localhost:80" ]; }
@@ -282,9 +333,9 @@ let
282
333
  primary = mkOption {
283
334
  type = types.nullOr (types.submodule (confLib.mkOptions.addresses 4));
284
335
  default =
285
- if config.v4 != [] then
336
+ if config.v4 != [ ] then
286
337
  head config.v4
287
- else if config.v6 != [] then
338
+ else if config.v6 != [ ] then
288
339
  head config.v6
289
340
  else
290
341
  null;
@@ -297,7 +348,7 @@ let
297
348
 
298
349
  v4 = mkOption {
299
350
  type = types.listOf (types.submodule (confLib.mkOptions.addresses 4));
300
- default = [];
351
+ default = [ ];
301
352
  description = ''
302
353
  List of IPv4 addresses this machine responds to
303
354
  '';
@@ -305,7 +356,7 @@ let
305
356
 
306
357
  v6 = mkOption {
307
358
  type = types.listOf (types.submodule (confLib.mkOptions.addresses 6));
308
- default = [];
359
+ default = [ ];
309
360
  description = ''
310
361
  List of IPv6 addresses this machine responds to
311
362
  '';
@@ -321,7 +372,7 @@ let
321
372
  type = types.nullOr types.str;
322
373
  default = null;
323
374
  description = ''
324
- Host name
375
+ Host name
325
376
  '';
326
377
  };
327
378
 
@@ -347,12 +398,10 @@ let
347
398
  description = ''
348
399
  Domain including location, i.e. FQDN without host name
349
400
  '';
350
- apply = v:
401
+ apply =
402
+ v:
351
403
  if isNull v && !isNull config.domain then
352
- concatStringsSep "." (
353
- (optional (!isNull config.location) config.location)
354
- ++ [ config.domain ]
355
- )
404
+ concatStringsSep "." ((optional (!isNull config.location) config.location) ++ [ config.domain ])
356
405
  else
357
406
  v;
358
407
  };
@@ -363,7 +412,8 @@ let
363
412
  description = ''
364
413
  Host FQDN
365
414
  '';
366
- apply = v:
415
+ apply =
416
+ v:
367
417
  if isNull v && !isNull config.name then
368
418
  concatStringsSep "." (
369
419
  [ config.name ]
@@ -384,6 +434,14 @@ let
384
434
  as a carried machine.
385
435
  '';
386
436
  };
437
+
438
+ port = mkOption {
439
+ type = types.int;
440
+ default = 22;
441
+ description = ''
442
+ SSH port used to connect to this machine.
443
+ '';
444
+ };
387
445
  };
388
446
  };
389
447
 
@@ -403,7 +461,7 @@ let
403
461
 
404
462
  labels = mkOption {
405
463
  type = types.attrs;
406
- default = {};
464
+ default = { };
407
465
  description = ''
408
466
  Optional user-defined labels to classify the machine
409
467
  '';
@@ -411,7 +469,7 @@ let
411
469
 
412
470
  tags = mkOption {
413
471
  type = types.listOf types.str;
414
- default = [];
472
+ default = [ ];
415
473
  description = ''
416
474
  Optional user-defined tags to classify the machine
417
475
  '';
@@ -419,7 +477,7 @@ let
419
477
 
420
478
  extraModules = mkOption {
421
479
  type = types.listOf types.path;
422
- default = [];
480
+ default = [ ];
423
481
  description = ''
424
482
  A list of additional NixOS modules to be imported for this machine
425
483
  '';
@@ -427,7 +485,11 @@ let
427
485
 
428
486
  buildAttribute = mkOption {
429
487
  type = types.listOf types.str;
430
- default = [ "system" "build" "toplevel" ];
488
+ default = [
489
+ "system"
490
+ "build"
491
+ "toplevel"
492
+ ];
431
493
  description = ''
432
494
  Path to the attribute in machine system config that should be built
433
495
 
@@ -564,13 +626,13 @@ let
564
626
 
565
627
  include = mkOption {
566
628
  type = types.listOf types.str;
567
- default = [];
629
+ default = [ ];
568
630
  description = "Strings that must be included in standard output";
569
631
  };
570
632
 
571
633
  exclude = mkOption {
572
634
  type = types.listOf types.str;
573
- default = [];
635
+ default = [ ];
574
636
  description = "Strings that must not be included in standard output";
575
637
  };
576
638
  };
@@ -584,13 +646,13 @@ let
584
646
 
585
647
  include = mkOption {
586
648
  type = types.listOf types.str;
587
- default = [];
649
+ default = [ ];
588
650
  description = "String that must be included in standard error";
589
651
  };
590
652
 
591
653
  exclude = mkOption {
592
654
  type = types.listOf types.str;
593
- default = [];
655
+ default = [ ];
594
656
  description = "String that must not be included in standard error";
595
657
  };
596
658
  };
@@ -608,11 +670,12 @@ let
608
670
  };
609
671
  };
610
672
  };
611
- in {
673
+ in
674
+ {
612
675
  options = {
613
676
  cluster = mkOption {
614
677
  type = types.attrsOf (types.submodule machine);
615
- default = {};
678
+ default = { };
616
679
  };
617
680
  };
618
681
  }
@@ -1,10 +1,16 @@
1
- { config, pkgs, lib, confMachine, ... }:
1
+ {
2
+ config,
3
+ pkgs,
4
+ lib,
5
+ confMachine,
6
+ ...
7
+ }:
2
8
  let
3
9
  inherit (lib) mkIf mkOption types;
4
10
 
5
11
  cfg = config.confctl.carrier;
6
12
 
7
- carrier-env = pkgs.confReplaceVarsWith {
13
+ carrier-env = pkgs.replaceVarsWith {
8
14
  src = ./carrier-env.rb;
9
15
  name = "carrier-env";
10
16
  isExecutable = true;
@@ -17,7 +23,8 @@ let
17
23
  '';
18
24
  };
19
25
  };
20
- in {
26
+ in
27
+ {
21
28
  options = {
22
29
  confctl.carrier.onChangeCommands = mkOption {
23
30
  type = types.lines;
@@ -34,4 +41,4 @@ in {
34
41
  carrier-env
35
42
  ];
36
43
  };
37
- }
44
+ }
@@ -63,8 +63,8 @@ class CarrierEnv
63
63
  on_change_commands
64
64
  end
65
65
 
66
- def nix_env(*args)
67
- system_command('nix-env', '-p', @profile, *args)
66
+ def nix_env(*)
67
+ system_command('nix-env', '-p', @profile, *)
68
68
  end
69
69
 
70
70
  def on_change_commands
@@ -128,7 +128,7 @@ class NetbootBuilder
128
128
  puts m.fqdn
129
129
 
130
130
  m.generations.each do |g|
131
- puts " - #{g.time_s} - #{g.version}#{g.current ? ' (current)' : ''}"
131
+ puts " - #{g.time_s} - #{g.version}#{' (current)' if g.current}"
132
132
  end
133
133
 
134
134
  puts
@@ -434,14 +434,14 @@ class TftpBuilder < RootBuilder
434
434
  MENU LABEL <%= m.label %>
435
435
  LINUX boot/<%= m.fqdn %>/<%= m.current.generation %>/bzImage
436
436
  INITRD boot/<%= m.fqdn %>/<%= m.current.generation %>/initrd
437
- APPEND init=<%= m.current.toplevel %>/init loglevel=7
437
+ APPEND <%= m.current.pxe_kernel_params.join(' ') %>
438
438
 
439
439
  <% m.generations[1..].each do |g| -%>
440
440
  LABEL <%= m.fqdn %>-<%= g.generation %>
441
441
  MENU LABEL Gen <%= g.generation %> - <%= g.time_s %> - <%= g.shortrev %>
442
442
  LINUX boot/<%= m.fqdn %>/<%= g.generation %>/bzImage
443
443
  INITRD boot/<%= m.fqdn %>/<%= g.generation %>/initrd
444
- APPEND init=<%= g.toplevel %>/init loglevel=7
444
+ APPEND <%= g.pxe_kernel_params.join(' ') %>
445
445
 
446
446
  <% end -%>
447
447
  <% if enable_memtest -%>
@@ -466,6 +466,20 @@ class TftpBuilder < RootBuilder
466
466
  },
467
467
  "pxeserver/machines/#{machine.fqdn}/menu.cfg"
468
468
  )
469
+
470
+ tpl = <<~ERB
471
+ DEFAULT <%= m.fqdn %>
472
+ PROMPT 0
473
+ TIMEOUT 50
474
+
475
+ LABEL <%= m.fqdn %>
476
+ MENU LABEL <%= m.label %>
477
+ LINUX boot/<%= m.fqdn %>/<%= m.current.generation %>/bzImage
478
+ INITRD boot/<%= m.fqdn %>/<%= m.current.generation %>/initrd
479
+ APPEND <%= m.current.pxe_kernel_params.join(' ') %>
480
+ ERB
481
+
482
+ render_to(tpl, { m: machine }, "pxeserver/machines/#{machine.fqdn}/auto.cfg")
469
483
  end
470
484
 
471
485
  def render_machine_vpsadminos(machine)
@@ -694,7 +708,7 @@ class Machine
694
708
  nil
695
709
  end
696
710
 
697
- def to_json(*args)
711
+ def to_json(*)
698
712
  {
699
713
  url:,
700
714
  name:,
@@ -702,7 +716,7 @@ class Machine
702
716
  fqdn:,
703
717
  label:,
704
718
  generations:
705
- }.to_json(*args)
719
+ }.to_json(*)
706
720
  end
707
721
 
708
722
  protected
@@ -723,12 +737,9 @@ class Machine
723
737
  @spin = @current.json.fetch('spin', spin)
724
738
  @fqdn = @current.json.fetch('fqdn', name)
725
739
 
726
- # rubocop:disable Naming/MemoizedInstanceVariableName
727
740
  @label = @current.json.fetch('label', nil)
728
741
  @label ||= @current.json.fetch('fqdn', nil)
729
742
  @label ||= name
730
- # rubocop:enable Naming/MemoizedInstanceVariableName
731
-
732
743
  @short_label = @label.split('.')[0..1].join('.')
733
744
  end
734
745
  end
@@ -830,13 +841,20 @@ class Generation
830
841
  @url = File.join(machine.url, generation.to_s)
831
842
  @boot_files = find_boot_files
832
843
  @variants = Variant.for_machine(machine)
844
+ @kernel_params.reject! { |v| v.start_with?('httproot=') }
845
+ ensure_nixos_init_param
833
846
 
834
- return if machine.spin != 'vpsadminos'
847
+ httproot =
848
+ if machine.spin == 'vpsadminos'
849
+ boot_files['root.squashfs']&.url
850
+ else
851
+ boot_files['initrd']&.url || boot_files['bzImage']&.url
852
+ end
835
853
 
836
- @kernel_params.insert(0, "httproot=#{boot_files['root.squashfs'].url}")
854
+ @kernel_params.insert(0, "httproot=#{httproot}") if httproot
837
855
  end
838
856
 
839
- def to_json(*args)
857
+ def to_json(*)
840
858
  {
841
859
  url:,
842
860
  store_path:,
@@ -854,11 +872,27 @@ class Generation
854
872
  boot_files:,
855
873
  variants:,
856
874
  swpins_info: json['swpins-info']
857
- }.to_json(*args)
875
+ }.to_json(*)
876
+ end
877
+
878
+ def pxe_kernel_params
879
+ return kernel_params if kernel_params.any?
880
+
881
+ [
882
+ "init=#{toplevel}/init",
883
+ 'loglevel=7'
884
+ ]
858
885
  end
859
886
 
860
887
  protected
861
888
 
889
+ def ensure_nixos_init_param
890
+ return unless machine.spin == 'nixos'
891
+ return if @kernel_params.any? { |v| v.start_with?('init=') }
892
+
893
+ @kernel_params.unshift("init=#{toplevel}/init")
894
+ end
895
+
862
896
  def extract_kernel_version
863
897
  link = File.readlink(File.join(toplevel, 'kernel'))
864
898
  return unless %r{\A/nix/store/[^-]+-linux-([^/]+)} =~ link
@@ -893,8 +927,8 @@ class BootFile
893
927
  @url = url
894
928
  end
895
929
 
896
- def to_json(*args)
897
- url.to_json(*args)
930
+ def to_json(*)
931
+ url.to_json(*)
898
932
  end
899
933
  end
900
934
 
@@ -950,12 +984,12 @@ class Variant
950
984
  @kernel_params = kernel_params
951
985
  end
952
986
 
953
- def to_json(*args)
987
+ def to_json(*)
954
988
  {
955
989
  name:,
956
990
  label:,
957
991
  kernel_params:
958
- }.to_json(*args)
992
+ }.to_json(*)
959
993
  end
960
994
  end
961
995