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,7 +1,21 @@
1
- { config, lib, pkgs, confMachine, ... }:
1
+ {
2
+ config,
3
+ lib,
4
+ pkgs,
5
+ confMachine,
6
+ ...
7
+ }:
2
8
  let
3
- inherit (lib) concatStringsSep flip mkOption mkEnableOption mkIf
4
- optional optionalString types;
9
+ inherit (lib)
10
+ concatStringsSep
11
+ flip
12
+ mkOption
13
+ mkEnableOption
14
+ mkIf
15
+ optional
16
+ optionalString
17
+ types
18
+ ;
5
19
 
6
20
  concatNl = concatStringsSep "\n";
7
21
 
@@ -46,13 +60,16 @@ let
46
60
  httpUrl = "http://${cfg.host}";
47
61
  memtest =
48
62
  if cfg.memtest86.enable then
49
- { package = pkgs.memtest86plus; params = cfg.memtest86.params; }
63
+ {
64
+ package = pkgs.memtest86plus;
65
+ params = cfg.memtest86.params;
66
+ }
50
67
  else
51
68
  null;
52
69
  isoImages = cfg.isoImages;
53
70
  };
54
71
 
55
- builder = pkgs.confReplaceVarsWith {
72
+ builder = pkgs.replaceVarsWith {
56
73
  src = ./build-netboot-server.rb;
57
74
  name = "build-netboot-server";
58
75
  dir = "bin";
@@ -62,7 +79,8 @@ let
62
79
  jsonConfig = pkgs.writeText "netboot-server.json" builderConfig;
63
80
  };
64
81
  };
65
- in {
82
+ in
83
+ {
66
84
  options = {
67
85
  confctl.carrier.netboot = {
68
86
  enable = mkEnableOption ''
@@ -89,7 +107,7 @@ in {
89
107
 
90
108
  params = mkOption {
91
109
  type = types.listOf types.str;
92
- default = [];
110
+ default = [ ];
93
111
  example = [ "console=ttyS0,115200" ];
94
112
  description = "See {option}`boot.loader.grub.memtest86.params`";
95
113
  };
@@ -97,7 +115,7 @@ in {
97
115
 
98
116
  isoImages = mkOption {
99
117
  type = types.listOf (types.submodule isoImage);
100
- default = [];
118
+ default = [ ];
101
119
  description = "A list of ISO images to be included in boot menu";
102
120
  };
103
121
 
@@ -107,7 +125,7 @@ in {
107
125
  Allow HTTP access for these IP ranges, if not specified
108
126
  access is not restricted.
109
127
  '';
110
- default = [];
128
+ default = [ ];
111
129
  example = "10.0.0.0/24";
112
130
  };
113
131
 
@@ -135,13 +153,21 @@ in {
135
153
  environment.systemPackages = [ builder ];
136
154
 
137
155
  networking.firewall = {
138
- extraCommands = mkIf (cfg.allowedIPv4Ranges != []) (concatNl (map (net: ''
139
- # Allow access from ${net} for netboot
140
- iptables -A nixos-fw -p udp -s ${net} ${optionalString (!isNull cfg.tftp.bindAddress) "-d ${cfg.tftp.bindAddress}"} --dport 68 -j nixos-fw-accept
141
- iptables -A nixos-fw -p udp -s ${net} ${optionalString (!isNull cfg.tftp.bindAddress) "-d ${cfg.tftp.bindAddress}"} --dport 69 -j nixos-fw-accept
142
- iptables -A nixos-fw -p tcp -s ${net} --dport 80 -j nixos-fw-accept
143
- ${optionalString cfg.enableACME "iptables -A nixos-fw -p tcp -s ${net} --dport 443 -j nixos-fw-accept"}
144
- '') cfg.allowedIPv4Ranges));
156
+ extraCommands = mkIf (cfg.allowedIPv4Ranges != [ ]) (
157
+ concatNl (
158
+ map (net: ''
159
+ # Allow access from ${net} for netboot
160
+ iptables -A nixos-fw -p udp -s ${net} ${
161
+ optionalString (!isNull cfg.tftp.bindAddress) "-d ${cfg.tftp.bindAddress}"
162
+ } --dport 68 -j nixos-fw-accept
163
+ iptables -A nixos-fw -p udp -s ${net} ${
164
+ optionalString (!isNull cfg.tftp.bindAddress) "-d ${cfg.tftp.bindAddress}"
165
+ } --dport 69 -j nixos-fw-accept
166
+ iptables -A nixos-fw -p tcp -s ${net} --dport 80 -j nixos-fw-accept
167
+ ${optionalString cfg.enableACME "iptables -A nixos-fw -p tcp -s ${net} --dport 443 -j nixos-fw-accept"}
168
+ '') cfg.allowedIPv4Ranges
169
+ )
170
+ );
145
171
  };
146
172
 
147
173
  systemd.services.netboot-atftpd = {
@@ -149,12 +175,18 @@ in {
149
175
  after = [ "network.target" ];
150
176
  wantedBy = [ "multi-user.target" ];
151
177
  # runs as nobody
152
- serviceConfig.ExecStart = toString ([
153
- "${pkgs.atftp}/sbin/atftpd"
154
- "--daemon"
155
- "--no-fork"
156
- ] ++ (optional (!isNull cfg.tftp.bindAddress) [ "--bind-address" cfg.tftp.bindAddress ])
157
- ++ [ tftpRoot ]);
178
+ serviceConfig.ExecStart = toString (
179
+ [
180
+ "${pkgs.atftp}/sbin/atftpd"
181
+ "--daemon"
182
+ "--no-fork"
183
+ ]
184
+ ++ (optional (!isNull cfg.tftp.bindAddress) [
185
+ "--bind-address"
186
+ cfg.tftp.bindAddress
187
+ ])
188
+ ++ [ tftpRoot ]
189
+ );
158
190
  };
159
191
 
160
192
  services.nginx = {
@@ -173,7 +205,7 @@ in {
173
205
  "/" = {
174
206
  extraConfig = ''
175
207
  autoindex on;
176
- ${optionalString (cfg.allowedIPv4Ranges != []) ''
208
+ ${optionalString (cfg.allowedIPv4Ranges != [ ]) ''
177
209
  ${concatNl (flip map cfg.allowedIPv4Ranges (range: "allow ${range};"))}
178
210
  deny all;
179
211
  ''}
@@ -184,4 +216,4 @@ in {
184
216
  };
185
217
  };
186
218
  };
187
- }
219
+ }
@@ -0,0 +1,17 @@
1
+ { lib, config, ... }:
2
+ let
3
+ info = config._module.args.configurationInfo or null;
4
+ json = if info == null then null else builtins.toJSON info;
5
+ in
6
+ {
7
+ options.confctl.configurationInfo = lib.mkOption {
8
+ type = lib.types.nullOr lib.types.attrs;
9
+ default = info;
10
+ description = "Configuration source metadata written to /etc/confctl/configuration-info.json.";
11
+ readOnly = true;
12
+ };
13
+
14
+ config = lib.mkIf (json != null) {
15
+ environment.etc."confctl/configuration-info.json".text = json;
16
+ };
17
+ }
@@ -26,7 +26,7 @@ with lib;
26
26
 
27
27
  maxAge = mkOption {
28
28
  type = types.int;
29
- default = 180*24*60*60;
29
+ default = 180 * 24 * 60 * 60;
30
30
  description = ''
31
31
  Delete build generations older than
32
32
  <option>confctl.buildGenerations.maxAge</option> seconds. Old generations
@@ -61,7 +61,7 @@ with lib;
61
61
 
62
62
  maxAge = mkOption {
63
63
  type = types.int;
64
- default = 180*24*60*60;
64
+ default = 180 * 24 * 60 * 60;
65
65
  description = ''
66
66
  Delete generations older than
67
67
  <option>confctl.hostGenerations.maxAge</option> seconds from
@@ -0,0 +1,13 @@
1
+ { lib, confMachine, ... }:
2
+ let
3
+ host = confMachine.host;
4
+ in
5
+ {
6
+ networking.hostName = lib.mkIf (host != null && host ? name && host.name != null) (
7
+ lib.mkDefault host.name
8
+ );
9
+
10
+ networking.domain = lib.mkIf (host != null && host ? fullDomain && host.fullDomain != null) (
11
+ lib.mkDefault host.fullDomain
12
+ );
13
+ }
@@ -0,0 +1,21 @@
1
+ { lib, config, ... }:
2
+ let
3
+ # inputsInfo is provided by the config flake via specialArgs / _module.args
4
+ inputsInfo = config._module.args.inputsInfo or null;
5
+
6
+ info = inputsInfo;
7
+
8
+ json = if info == null then null else builtins.toJSON info;
9
+ in
10
+ {
11
+ options.confctl.inputsInfo = lib.mkOption {
12
+ type = lib.types.nullOr lib.types.attrs;
13
+ default = info;
14
+ description = "Flake input metadata written to /etc/confctl/inputs-info.json (provided via module args).";
15
+ readOnly = true;
16
+ };
17
+
18
+ config = lib.mkIf (json != null) {
19
+ environment.etc."confctl/inputs-info.json".text = json;
20
+ };
21
+ }
@@ -1,10 +1,16 @@
1
- { config, lib, pkgs, confMachine, ... }:
1
+ {
2
+ config,
3
+ lib,
4
+ pkgs,
5
+ confMachine,
6
+ ...
7
+ }:
2
8
  let
3
9
  inherit (lib) mkEnableOption mkIf;
4
10
 
5
11
  cfg = config.confctl.programs.kexec-netboot;
6
12
 
7
- kexecNetboot = pkgs.confReplaceVarsWith {
13
+ kexecNetboot = pkgs.replaceVarsWith {
8
14
  name = "kexec-netboot";
9
15
  src = ./kexec-netboot.rb;
10
16
  isExecutable = true;
@@ -15,7 +21,7 @@ let
15
21
  };
16
22
  };
17
23
 
18
- kexecNetbootBin = pkgs.runCommand "kexec-netboot-bin" {} ''
24
+ kexecNetbootBin = pkgs.runCommand "kexec-netboot-bin" { } ''
19
25
  mkdir -p $out/bin
20
26
  ln -s ${kexecNetboot} $out/bin/kexec-netboot
21
27
 
@@ -25,8 +31,9 @@ let
25
31
  -D $out/share/man/man8 \
26
32
  ${./kexec-netboot.8.adoc}
27
33
  '';
28
- in {
29
- options = {
34
+ in
35
+ {
36
+ options = {
30
37
  confctl.programs.kexec-netboot = {
31
38
  enable = mkEnableOption "Enable kexec-netboot utility";
32
39
  };
@@ -35,4 +42,4 @@ in {
35
42
  config = mkIf cfg.enable {
36
43
  environment.systemPackages = [ kexecNetbootBin ];
37
44
  };
38
- }
45
+ }
@@ -53,6 +53,9 @@ The following options are understood:
53
53
  *-e*, *--exec*::
54
54
  Run the currently loaded kernel.
55
55
 
56
+ *-y*, *--no-sync*::
57
+ Skip syncing filesystems with *--exec*.
58
+
56
59
  == Bugs
57
60
 
58
61
  Report bugs to https://github.com/vpsfreecz/confctl/issues.
@@ -20,6 +20,7 @@ class KexecNetboot
20
20
  @append_params = ''
21
21
  @exec = false
22
22
  @unload = false
23
+ @sync = false
23
24
  @machines_json = nil
24
25
  @tmp_files = []
25
26
  end
@@ -151,6 +152,10 @@ class KexecNetboot
151
152
  opts.on('-u', '--unload', 'Unload the current kexec target kernel and exit') do
152
153
  @unload = true
153
154
  end
155
+
156
+ opts.on('-y', '--no-sync', 'Skip syncing filesystems') do
157
+ @sync = false
158
+ end
154
159
  end
155
160
 
156
161
  opt_parser.parse!(ARGV)
@@ -374,18 +379,21 @@ class KexecNetboot
374
379
  uri = URI.parse(url)
375
380
  basename = File.basename(uri.path)
376
381
  tmp_file = Tempfile.new(basename)
382
+ tmp_file.binmode
377
383
 
378
384
  puts "Downloading #{url} -> #{tmp_file.path}"
379
385
 
380
386
  Net::HTTP.start(uri.host, uri.port) do |http|
381
- resp = http.get(uri.request_uri)
387
+ http.request_get(uri.request_uri) do |resp|
388
+ unless resp.is_a?(Net::HTTPSuccess)
389
+ warn "ERROR: Could not download #{url}, HTTP #{resp.code}"
390
+ exit 1
391
+ end
382
392
 
383
- unless resp.is_a?(Net::HTTPSuccess)
384
- warn "ERROR: Could not download #{url}, HTTP #{resp.code}"
385
- exit 1
393
+ resp.read_body do |chunk|
394
+ tmp_file.write(chunk)
395
+ end
386
396
  end
387
-
388
- tmp_file.write(resp.body)
389
397
  end
390
398
 
391
399
  tmp_file.close
@@ -397,47 +405,48 @@ class KexecNetboot
397
405
  def load_kexec(kernel_path, initrd_path, kernel_params_string)
398
406
  cmd = [
399
407
  KEXEC,
400
- '-l',
408
+ '--load',
401
409
  kernel_path,
402
410
  "--initrd=#{initrd_path}",
403
- "--append=\"#{kernel_params_string}\""
411
+ "--append=\"#{kernel_params_string}\"",
412
+ '--no-sync'
404
413
  ].join(' ')
405
414
 
406
415
  puts "Executing: #{cmd}"
407
416
  system(cmd)
408
417
 
409
418
  if $?.exitstatus == 0
410
- puts 'kexec -l completed successfully.'
419
+ puts 'kexec --load completed successfully.'
411
420
  else
412
- warn 'ERROR: kexec -l failed!'
421
+ warn 'ERROR: kexec --load failed!'
413
422
  exit 1
414
423
  end
415
424
  end
416
425
 
417
426
  def exec_kexec
418
- cmd = [KEXEC, '-e'].join(' ')
427
+ cmd = [KEXEC, '--exec', @sync ? nil : '--no-sync'].compact.join(' ')
419
428
 
420
429
  puts "Executing: #{cmd}"
421
430
  system(cmd)
422
431
 
423
432
  if $?.exitstatus == 0
424
- puts 'kexec -e completed successfully.'
433
+ puts 'kexec --exec completed successfully.'
425
434
  else
426
- warn 'ERROR: kexec -u failed!'
435
+ warn 'ERROR: kexec --exec failed!'
427
436
  exit 1
428
437
  end
429
438
  end
430
439
 
431
440
  def unload_kexec
432
- cmd = [KEXEC, '-u'].join(' ')
441
+ cmd = [KEXEC, '--unload', '--no-sync'].join(' ')
433
442
 
434
443
  puts "Executing: #{cmd}"
435
444
  system(cmd)
436
445
 
437
446
  if $?.exitstatus == 0
438
- puts 'kexec -u completed successfully.'
447
+ puts 'kexec --unload completed successfully.'
439
448
  else
440
- warn 'ERROR: kexec -u failed!'
449
+ warn 'ERROR: kexec --unload failed!'
441
450
  exit 1
442
451
  end
443
452
  end
@@ -15,13 +15,43 @@ with lib;
15
15
 
16
16
  nixPath = mkOption {
17
17
  type = types.listOf types.str;
18
- default = [];
18
+ default = [ ];
19
19
  description = ''
20
20
  List of extra paths added to environment variable
21
21
  <literal>NIX_PATH</literal> for all <literal>nix-build</literal>
22
22
  invokations
23
23
  '';
24
24
  };
25
+
26
+ impureEval = mkOption {
27
+ type = types.bool;
28
+ default = false;
29
+ description = ''
30
+ Enable impure evaluation/builds (allows reading host paths outside the Nix store when they are referenced as Nix paths).
31
+ '';
32
+ };
33
+
34
+ legacyNixPath = mkOption {
35
+ type = types.bool;
36
+ default = false;
37
+ description = ''
38
+ If true, confctl adds -I mappings for selected inputs during flake
39
+ builds to support legacy <nixpkgs> or <vpsadminos> imports.
40
+ '';
41
+ };
42
+
43
+ legacyNixPathMap = mkOption {
44
+ type = types.listOf types.str;
45
+ default = [
46
+ "nixpkgs"
47
+ "vpsadminos"
48
+ "vpsadmin"
49
+ ];
50
+ description = ''
51
+ List of input names that should be mapped to NIX_PATH when
52
+ legacyNixPath is enabled.
53
+ '';
54
+ };
25
55
  };
26
56
  };
27
57
  };
@@ -1,10 +1,17 @@
1
- { config, pkgs, lib, swpinsInfo, ... }:
1
+ {
2
+ config,
3
+ pkgs,
4
+ lib,
5
+ swpinsInfo,
6
+ ...
7
+ }:
2
8
  with lib;
3
9
  let
4
10
  swpinOptions = import ../../lib/swpins/options.nix { inherit lib; };
5
11
 
6
12
  machineSwpinsInfo = pkgs.writeText "swpins-info.json" (builtins.toJSON swpinsInfo);
7
- in {
13
+ in
14
+ {
8
15
  options = {
9
16
  confctl = {
10
17
  swpins.core = {
@@ -17,7 +24,7 @@ in {
17
24
  url = "https://github.com/NixOS/nixpkgs";
18
25
  update.ref = "refs/heads/nixos-unstable";
19
26
  update.auto = true;
20
- update.interval = 30*24*60*60; # 1 month
27
+ update.interval = 30 * 24 * 60 * 60; # 1 month
21
28
  };
22
29
  };
23
30
  };
@@ -31,7 +38,7 @@ in {
31
38
 
32
39
  channels = mkOption {
33
40
  type = types.listOf types.str;
34
- default = [];
41
+ default = [ ];
35
42
  description = ''
36
43
  List of channels from <option>confctl.swpins.channels</option>
37
44
  to use for core swpins
@@ -41,7 +48,7 @@ in {
41
48
 
42
49
  swpins.channels = mkOption {
43
50
  type = types.attrsOf (types.attrsOf (types.submodule swpinOptions.specModule));
44
- default = {};
51
+ default = { };
45
52
  description = ''
46
53
  Software pin channels
47
54
  '';
@@ -49,7 +56,7 @@ in {
49
56
  };
50
57
  };
51
58
 
52
- config = {
59
+ config = mkIf (config.confctl.inputsInfo == null) {
53
60
  environment.etc."confctl/swpins-info.json".source = machineSwpinsInfo;
54
61
  };
55
62
  }
@@ -4,8 +4,9 @@ let
4
4
  ./confctl/generations.nix
5
5
  ./confctl/cli.nix
6
6
  ./confctl/nix.nix
7
- ./confctl/overlays.nix
8
7
  ./confctl/swpins.nix
8
+ ./confctl/inputs-info.nix
9
+ ./confctl/configuration-info.nix
9
10
  ];
10
11
 
11
12
  nixos = [
@@ -13,7 +14,8 @@ let
13
14
 
14
15
  vpsadminos = [
15
16
  ];
16
- in {
17
+ in
18
+ {
17
19
  nixos = shared ++ nixos;
18
20
  vpsadminos = shared ++ vpsadminos;
19
21
  all = shared ++ nixos ++ vpsadminos;
@@ -2,9 +2,12 @@
2
2
  nixos = [
3
3
  ./confctl/carrier/base.nix
4
4
  ./confctl/carrier/netboot/nixos.nix
5
+ ./confctl/kexec-netboot
6
+ ./confctl/host.nix
5
7
  ];
6
8
 
7
9
  vpsadminos = [
8
10
  ./confctl/kexec-netboot
11
+ ./confctl/host.nix
9
12
  ];
10
- }
13
+ }
data/nix/package.nix ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ pkgs,
3
+ src ? ../.,
4
+ ruby ? (if pkgs ? ruby_3_4 then pkgs.ruby_3_4 else pkgs.ruby),
5
+ groups ? [ "default" ],
6
+ }:
7
+ let
8
+ lib = pkgs.lib;
9
+
10
+ deps = pkgs.bundlerEnv {
11
+ name = "confctl-deps";
12
+ inherit ruby;
13
+ gemdir = src;
14
+ lockfile = "${src}/Gemfile.lock";
15
+ inherit groups;
16
+ };
17
+
18
+ runtimePath = lib.makeBinPath [
19
+ pkgs.git
20
+ pkgs.openssh
21
+ pkgs.nix
22
+ pkgs.nix-prefetch-git
23
+ ];
24
+ in
25
+ (pkgs.writeShellScriptBin "confctl" ''
26
+ export GEM_HOME="${deps}/${ruby.gemPath}"
27
+ export GEM_PATH="${deps}/${ruby.gemPath}"
28
+ export RUBYLIB="${src}/lib"
29
+ export PATH="${runtimePath}:$PATH"
30
+
31
+ exec ${ruby}/bin/ruby ${src}/bin/confctl "$@"
32
+ '').overrideAttrs
33
+ (_old: {
34
+ passthru = {
35
+ inherit deps ruby src;
36
+ };
37
+ })
data/shell.nix CHANGED
@@ -1,14 +1,17 @@
1
1
  let
2
- pkgs = import <nixpkgs> {};
2
+ pkgs = import <nixpkgs> { };
3
3
  lib = pkgs.lib;
4
4
  stdenv = pkgs.stdenv;
5
- in stdenv.mkDerivation rec {
5
+ in
6
+ stdenv.mkDerivation rec {
6
7
  name = "confctl-shell";
7
8
 
8
9
  buildInputs = with pkgs; [
9
10
  git
10
11
  ncurses
11
12
  nix-prefetch-git
13
+ nixfmt
14
+ nixfmt-tree
12
15
  openssl
13
16
  ruby
14
17
  ];
@@ -16,23 +19,50 @@ in stdenv.mkDerivation rec {
16
19
  shellHook = ''
17
20
  CONFCTL="${toString ./.}"
18
21
  BASEDIR="$(realpath `pwd`)"
19
- export GEM_HOME="$(pwd)/.gems"
20
- BINDIR="$(ruby -e 'puts Gem.bindir')"
22
+ export GEM_ROOT="$(pwd)/.gems"
23
+ export GEM_HOME="$GEM_ROOT/ruby/$(ruby -e 'require "rbconfig"; print RbConfig::CONFIG["ruby_version"]')"
24
+ export GEM_PATH="$GEM_HOME"
25
+ export BUNDLE_PATH="$GEM_ROOT"
26
+ export BUNDLE_APP_CONFIG="$BASEDIR/.bundle"
27
+ export RUBOCOP_CACHE_ROOT="$CONFCTL/.rubocop_cache"
28
+ BINDIR="$GEM_HOME/bin"
21
29
  mkdir -p "$BINDIR"
22
30
 
23
31
  export PATH="$BINDIR:$PATH"
24
- export RUBYLIB="$GEM_HOME:$CONFCTL/lib"
32
+ export RUBYLIB="$CONFCTL/lib"
25
33
  export MANPATH="$CONFCTL/man:$(man --path)"
26
- gem install --no-document bundler
34
+
35
+ bundler_version=""
36
+ if [ -f "$CONFCTL/Gemfile.lock" ]; then
37
+ bundler_version="$(awk '/^BUNDLED WITH$/{getline; sub(/^[[:space:]]+/, "", $0); print; exit}' "$CONFCTL/Gemfile.lock")"
38
+ fi
39
+
40
+ if [ -n "$bundler_version" ]; then
41
+ export BUNDLER_VERSION="$bundler_version"
42
+ # Ruby can ship Bundler as a default gem without creating a wrapper in
43
+ # GEM_HOME/bin, but the shell below executes Bundler through that path.
44
+ if [ ! -x "$GEM_HOME/bin/bundle" ] \
45
+ || ! gem list -i bundler -v "$bundler_version" >/dev/null 2>&1; then
46
+ gem install --no-document bundler -v "$bundler_version"
47
+ fi
48
+ elif [ ! -x "$GEM_HOME/bin/bundle" ]; then
49
+ gem install --no-document bundler
50
+ fi
51
+ bundle_bin="$GEM_HOME/bin/bundle"
52
+
27
53
  pushd "$CONFCTL"
28
54
 
29
55
  # Purity disabled because of prism gem, which has a native extension.
30
56
  # The extension has its header files in .gems, which gets stripped but
31
57
  # cc wrapper in Nix. Without NIX_ENFORCE_PURITY=0, we get prism.h not found
32
58
  # error.
33
- NIX_ENFORCE_PURITY=0 bundle install
59
+ NIX_ENFORCE_PURITY=0 "$bundle_bin" install
34
60
 
35
- bundle exec rake md2man:man
61
+ "$bundle_bin" config set --local path "$BUNDLE_PATH"
62
+ "$bundle_bin" config set --local bin "$BINDIR"
63
+ "$bundle_bin" binstubs rubocop --force
64
+
65
+ "$bundle_bin" exec rake md2man:man
36
66
  popd
37
67
 
38
68
  cat <<EOF > "$BINDIR/confctl"
@@ -45,5 +75,6 @@ in stdenv.mkDerivation rec {
45
75
  load File.join('$CONFCTL', 'bin/confctl')
46
76
  EOF
47
77
  chmod +x "$BINDIR/confctl"
78
+
48
79
  '';
49
80
  }