confctl 1.0.0 → 2.1.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +1 -1
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +1 -0
  5. data/CHANGELOG.md +30 -1
  6. data/README.md +4 -9
  7. data/confctl.gemspec +14 -14
  8. data/docs/carrier.md +150 -0
  9. data/lib/confctl/cli/app.rb +19 -0
  10. data/lib/confctl/cli/cluster.rb +214 -49
  11. data/lib/confctl/cli/configuration.rb +7 -2
  12. data/lib/confctl/cli/gen_data.rb +19 -1
  13. data/lib/confctl/cli/generation.rb +47 -16
  14. data/lib/confctl/generation/build.rb +42 -1
  15. data/lib/confctl/generation/build_list.rb +10 -0
  16. data/lib/confctl/generation/host.rb +9 -5
  17. data/lib/confctl/generation/host_list.rb +22 -7
  18. data/lib/confctl/generation/unified.rb +5 -0
  19. data/lib/confctl/generation/unified_list.rb +10 -0
  20. data/lib/confctl/git_repo_mirror.rb +2 -2
  21. data/lib/confctl/machine.rb +105 -11
  22. data/lib/confctl/machine_control.rb +10 -2
  23. data/lib/confctl/machine_list.rb +18 -1
  24. data/lib/confctl/machine_status.rb +51 -4
  25. data/lib/confctl/nix.rb +90 -22
  26. data/lib/confctl/nix_copy.rb +5 -5
  27. data/lib/confctl/null_logger.rb +7 -0
  28. data/lib/confctl/swpins/specs/git.rb +1 -1
  29. data/lib/confctl/swpins/specs/git_rev.rb +1 -1
  30. data/lib/confctl/system_command.rb +3 -2
  31. data/lib/confctl/version.rb +1 -1
  32. data/libexec/auto-rollback.rb +106 -0
  33. data/man/man8/confctl-options.nix.8 +165 -1
  34. data/man/man8/confctl-options.nix.8.md +165 -1
  35. data/man/man8/confctl.8 +109 -73
  36. data/man/man8/confctl.8.md +86 -55
  37. data/nix/evaluator.nix +26 -7
  38. data/nix/lib/default.nix +64 -17
  39. data/nix/lib/machine/default.nix +14 -11
  40. data/nix/lib/machine/info.nix +3 -3
  41. data/nix/modules/cluster/default.nix +162 -3
  42. data/nix/modules/confctl/carrier/base.nix +35 -0
  43. data/nix/modules/confctl/carrier/carrier-env.rb +81 -0
  44. data/nix/modules/confctl/carrier/netboot/build-netboot-server.rb +962 -0
  45. data/nix/modules/confctl/carrier/netboot/nixos.nix +185 -0
  46. data/nix/modules/confctl/kexec-netboot/default.nix +36 -0
  47. data/nix/modules/confctl/kexec-netboot/kexec-netboot.8.adoc +62 -0
  48. data/nix/modules/confctl/kexec-netboot/kexec-netboot.rb +455 -0
  49. data/nix/modules/system-list.nix +10 -0
  50. metadata +17 -7
  51. data/.ruby-version +0 -1
data/lib/confctl/nix.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'confctl/utils/file'
2
+ require 'digest'
2
3
  require 'etc'
3
4
  require 'json'
4
5
  require 'securerandom'
@@ -15,10 +16,11 @@ module ConfCtl
15
16
 
16
17
  include Utils::File
17
18
 
18
- def initialize(conf_dir: nil, show_trace: false, max_jobs: nil)
19
+ def initialize(conf_dir: nil, show_trace: false, max_jobs: nil, cores: nil)
19
20
  @conf_dir = conf_dir || ConfDir.path
20
21
  @show_trace = show_trace
21
22
  @max_jobs = max_jobs || Settings.instance.max_jobs
23
+ @cores = cores
22
24
  @cmd = SystemCommand.new
23
25
  end
24
26
 
@@ -40,6 +42,7 @@ module ConfCtl
40
42
  '--out-link', out_link,
41
43
  (show_trace ? '--show-trace' : nil),
42
44
  (max_jobs ? ['--max-jobs', max_jobs.to_s] : nil),
45
+ (cores ? ['--cores', cores.to_s] : nil),
43
46
  ConfCtl.nix_asset('evaluator.nix')
44
47
  ].flatten.compact
45
48
 
@@ -88,6 +91,7 @@ module ConfCtl
88
91
  '--out-link', out_link,
89
92
  (show_trace ? '--show-trace' : nil),
90
93
  (max_jobs ? ['--max-jobs', max_jobs.to_s] : nil),
94
+ (cores ? ['--cores', cores.to_s] : nil),
91
95
  ConfCtl.nix_asset('evaluator.nix')
92
96
  ].flatten.compact
93
97
 
@@ -124,6 +128,7 @@ module ConfCtl
124
128
  '--out-link', out_link,
125
129
  (show_trace ? '--show-trace' : nil),
126
130
  (max_jobs ? ['--max-jobs', max_jobs.to_s] : nil),
131
+ (cores ? ['--cores', cores.to_s] : nil),
127
132
  ConfCtl.nix_asset('evaluator.nix')
128
133
  ].flatten.compact
129
134
 
@@ -133,19 +138,19 @@ module ConfCtl
133
138
  end
134
139
  end
135
140
 
136
- # Evaluate swpins for host
137
- # @param host [String]
138
- # @return [Hash]
139
- def eval_host_swpins(host)
141
+ # Evaluate swpins for hosts
142
+ # @param hosts [Array<String>]
143
+ # @return [Hash] host => swpins
144
+ def eval_host_swpins(hosts)
140
145
  with_argument({
141
146
  confDir: conf_dir,
142
147
  build: :evalHostSwpins,
143
- machines: [host]
148
+ machines: hosts
144
149
  }, core_swpins: true) do |arg|
145
150
  out_link = File.join(
146
151
  cache_dir,
147
152
  'build',
148
- "#{ConfCtl.safe_host_name(host)}.swpins"
153
+ "#{Digest::SHA256.hexdigest(hosts.join(','))[0..11]}.swpins"
149
154
  )
150
155
 
151
156
  cmd_args = [
@@ -154,18 +159,19 @@ module ConfCtl
154
159
  '--out-link', out_link,
155
160
  (show_trace ? '--show-trace' : nil),
156
161
  (max_jobs ? ['--max-jobs', max_jobs.to_s] : nil),
162
+ (cores ? ['--cores', cores.to_s] : nil),
157
163
  ConfCtl.nix_asset('evaluator.nix')
158
164
  ].flatten.compact
159
165
 
160
166
  out, = cmd.run(*cmd_args)
161
167
 
162
- JSON.parse(File.read(out.strip))[host]
168
+ JSON.parse(File.read(out.strip))
163
169
  end
164
170
  end
165
171
 
166
172
  # Build config.system.build.toplevel for selected hosts
167
173
  #
168
- # @param hosts [Array<String>]
174
+ # @param hosts [Array<Machine>]
169
175
  # @param swpin_paths [Hash]
170
176
  # @param host_swpin_specs [Hash]
171
177
  # @param time [Time]
@@ -176,7 +182,7 @@ module ConfCtl
176
182
  # @yieldparam path [String]
177
183
  #
178
184
  # @return [Hash<String, Generation::Build>]
179
- def build_toplevels(hosts: [], swpin_paths: {}, host_swpin_specs: {}, time: nil, &block)
185
+ def build_attributes(hosts: [], swpin_paths: {}, host_swpin_specs: {}, time: nil, &block)
180
186
  with_argument({
181
187
  confDir: conf_dir,
182
188
  build: :toplevel,
@@ -191,6 +197,7 @@ module ConfCtl
191
197
  '--out-link', out_link,
192
198
  (show_trace ? '--show-trace' : nil),
193
199
  (max_jobs ? ['--max-jobs', max_jobs.to_s] : nil),
200
+ (cores ? ['--cores', cores.to_s] : nil),
194
201
  ConfCtl.nix_asset('evaluator.nix')
195
202
  ].flatten.compact
196
203
 
@@ -198,15 +205,16 @@ module ConfCtl
198
205
  nb.run(&block)
199
206
 
200
207
  begin
201
- host_toplevels = JSON.parse(File.read(out_link))
202
- host_toplevels.each do |host, toplevel|
208
+ host_results = JSON.parse(File.read(out_link))
209
+ host_results.each do |host, result|
203
210
  host_generations = Generation::BuildList.new(host)
204
- generation = host_generations.find(toplevel, swpin_paths)
211
+ generation = host_generations.find(result['attribute'], swpin_paths)
205
212
 
206
213
  if generation.nil?
207
214
  generation = Generation::Build.new(host)
208
215
  generation.create(
209
- toplevel,
216
+ result['attribute'],
217
+ result['autoRollback'],
210
218
  swpin_paths,
211
219
  host_swpin_specs[host],
212
220
  date: time
@@ -226,45 +234,104 @@ module ConfCtl
226
234
  end
227
235
 
228
236
  # @param machine [Machine]
229
- # @param toplevel [String]
237
+ # @param paths [Array<String>]
230
238
  #
231
239
  # @yieldparam progress [Integer]
232
240
  # @yieldparam total [Integer]
233
241
  # @yieldparam path [String]
234
242
  #
235
243
  # @return [Boolean]
236
- def copy(machine, toplevel, &)
244
+ def copy(machine, paths, &)
237
245
  if machine.localhost?
238
246
  true
247
+ elsif machine.carried?
248
+ cp = NixCopy.new(machine.carrier_machine.target_host, paths)
249
+ cp.run!(&).success?
239
250
  else
240
- cp = NixCopy.new(machine.target_host, toplevel)
251
+ cp = NixCopy.new(machine.target_host, paths)
241
252
  cp.run!(&).success?
242
253
  end
243
254
  end
244
255
 
245
256
  # @param machine [Machine]
246
- # @param toplevel [String]
257
+ # @param generation [Generation::Build]
247
258
  # @param action [String]
248
259
  # @return [Boolean]
249
- def activate(machine, toplevel, action)
250
- args = [File.join(toplevel, 'bin/switch-to-configuration'), action]
260
+ def activate(machine, generation, action)
261
+ args = [File.join(generation.toplevel, 'bin/switch-to-configuration'), action]
251
262
 
252
263
  MachineControl.new(machine).execute!(*args).success?
253
264
  end
254
265
 
266
+ # @param machine [Machine]
267
+ # @param generation [Generation::Build]
268
+ # @param action [String]
269
+ # @return [Boolean]
270
+ def activate_with_rollback(machine, generation, action)
271
+ check_file = File.join('/run', "confctl-confirm-#{SecureRandom.hex(3)}")
272
+ timeout = machine['autoRollback']['timeout']
273
+ logger = NullLogger.new
274
+
275
+ args = [
276
+ generation.auto_rollback,
277
+ '-t', timeout,
278
+ generation.toplevel,
279
+ action,
280
+ check_file
281
+ ]
282
+
283
+ activation_success = nil
284
+
285
+ activation_thread = Thread.new do
286
+ activation_success = MachineControl.new(machine).execute!(*args).success?
287
+ end
288
+
289
+ # Wait for the configuration to be switched
290
+ t = Time.now
291
+
292
+ loop do
293
+ out, = MachineControl.new(machine, logger:).execute!('cat', check_file, '2>/dev/null')
294
+ stripped = out.strip
295
+ break if stripped == 'switched' || ((t + timeout + 10) < Time.now && stripped != 'switching')
296
+
297
+ sleep(1)
298
+ end
299
+
300
+ # Confirm it
301
+ 10.times do
302
+ break if MachineControl.new(machine, logger:).execute!('sh', '-c', "'echo confirmed > #{check_file}'").success?
303
+ end
304
+
305
+ activation_thread.join
306
+ activation_success
307
+ end
308
+
255
309
  # @param machine [Machine]
256
310
  # @param toplevel [String]
257
311
  # @return [Boolean]
258
312
  def set_profile(machine, toplevel)
259
313
  args = [
260
314
  'nix-env',
261
- '-p', '/nix/var/nix/profiles/system',
315
+ '-p', machine.profile,
262
316
  '--set', toplevel
263
317
  ]
264
318
 
265
319
  MachineControl.new(machine).execute!(*args).success?
266
320
  end
267
321
 
322
+ # @param machine [Machine]
323
+ # @param toplevel [String]
324
+ # @return [Boolean]
325
+ def set_carried_profile(machine, toplevel)
326
+ args = [
327
+ 'carrier-env',
328
+ '-p', machine.profile,
329
+ '--set', toplevel
330
+ ]
331
+
332
+ MachineControl.new(machine.carrier_machine).execute!(*args).success?
333
+ end
334
+
268
335
  # @param packages [Array<String>]
269
336
  # @param command [String]
270
337
  # @return [Boolean]
@@ -292,7 +359,7 @@ module ConfCtl
292
359
 
293
360
  protected
294
361
 
295
- attr_reader :conf_dir, :show_trace, :max_jobs, :cmd
362
+ attr_reader :conf_dir, :show_trace, :max_jobs, :cores, :cmd
296
363
 
297
364
  # Execute block only if `out_link` does not exist or conf dir has changed
298
365
  # @param out_link [String] out link path
@@ -357,6 +424,7 @@ module ConfCtl
357
424
  '--arg', 'jsonArg', arg,
358
425
  (show_trace ? '--show-trace' : nil),
359
426
  (max_jobs ? ['--max-jobs', max_jobs.to_s] : nil),
427
+ (cores ? ['--cores', cores.to_s] : nil),
360
428
  ConfCtl.nix_asset('evaluator.nix')
361
429
  ].flatten.compact
362
430
 
@@ -1,10 +1,10 @@
1
1
  module ConfCtl
2
2
  class NixCopy
3
3
  # @param target [String]
4
- # @param store_path [String]
5
- def initialize(target, store_path)
4
+ # @param store_paths [Array<String>]
5
+ def initialize(target, store_paths)
6
6
  @target = target
7
- @store_path = store_path
7
+ @store_paths = store_paths
8
8
  @total = nil
9
9
  @progress = 0
10
10
  end
@@ -22,7 +22,7 @@ module ConfCtl
22
22
  ret = cmd.run!(
23
23
  'nix-copy-closure',
24
24
  '--to', "root@#{target}",
25
- store_path,
25
+ *store_paths,
26
26
  &line_buf.feed_block
27
27
  )
28
28
 
@@ -32,7 +32,7 @@ module ConfCtl
32
32
 
33
33
  protected
34
34
 
35
- attr_reader :target, :store_path
35
+ attr_reader :target, :store_paths
36
36
 
37
37
  def parse_line(line)
38
38
  if @total.nil? && /^copying (\d+) paths/ =~ line
@@ -0,0 +1,7 @@
1
+ module ConfCtl
2
+ class NullLogger
3
+ def <<(_str)
4
+ # do nothing
5
+ end
6
+ end
7
+ end
@@ -103,7 +103,7 @@ module ConfCtl
103
103
 
104
104
  def prefetch_github(ref)
105
105
  mirror = GitRepoMirror.new(nix_opts['url'])
106
- mirror.setup
106
+ mirror.setup(ref:)
107
107
 
108
108
  rev = mirror.revision_parse(ref)
109
109
  url = File.join(nix_opts['url'], 'archive', "#{rev}.tar.gz")
@@ -5,7 +5,7 @@ module ConfCtl
5
5
  handle :'git-rev'
6
6
 
7
7
  def prefetch_set(args)
8
- super(args)
8
+ super
9
9
  wrap_fetcher
10
10
  end
11
11
 
@@ -2,9 +2,10 @@ require 'tty-command'
2
2
 
3
3
  module ConfCtl
4
4
  module SystemCommand
5
+ # @param logger [#<<]
5
6
  # @return [TTY::Command]
6
- def self.new
7
- TTY::Command.new(output: Logger.instance, color: false)
7
+ def self.new(logger: nil)
8
+ TTY::Command.new(output: logger || Logger.instance, color: false)
8
9
  end
9
10
  end
10
11
  end
@@ -1,3 +1,3 @@
1
1
  module ConfCtl
2
- VERSION = '1.0.0'.freeze
2
+ VERSION = '2.1.0'.freeze
3
3
  end
@@ -0,0 +1,106 @@
1
+ #!@ruby@/bin/ruby
2
+ # Switch to a new system configuration and wait for confctl to confirm
3
+ # connectivity. If confctl is unable to reach the deployed machine, this
4
+ # script will roll back to the previous configuration.
5
+
6
+ require 'optparse'
7
+
8
+ class AutoRollback
9
+ def self.run
10
+ ar = new
11
+ ar.run
12
+ end
13
+
14
+ def run
15
+ puts 'Deploying with auto-rollback'
16
+
17
+ options = parse_options
18
+
19
+ current_system = File.readlink('/run/current-system')
20
+ puts " current system = #{current_system}"
21
+ puts " new system = #{options[:toplevel]}"
22
+ puts " action = #{options[:action]}"
23
+ puts " check file = #{options[:check_file]}"
24
+ puts " timeout = #{options[:timeout]} seconds"
25
+ puts
26
+
27
+ puts 'Switching to new configuration'
28
+ File.write(options[:check_file], 'switching')
29
+
30
+ pid = Process.spawn(
31
+ File.join(options[:toplevel], 'bin/switch-to-configuration'),
32
+ options[:action]
33
+ )
34
+
35
+ Process.wait(pid)
36
+
37
+ File.write(options[:check_file], 'switched')
38
+
39
+ puts 'Switch complete, waiting for confirmation'
40
+ t = Time.now
41
+
42
+ loop do
43
+ sleep(0.5)
44
+
45
+ if File.read(options[:check_file]).strip == 'confirmed'
46
+ puts 'Configuration confirmed'
47
+ File.unlink(options[:check_file])
48
+ exit
49
+ end
50
+
51
+ break if t + options[:timeout] < Time.now
52
+ end
53
+
54
+ puts 'Timeout occurred, rolling back'
55
+
56
+ pid = Process.spawn(
57
+ File.join(current_system, 'bin/switch-to-configuration'),
58
+ options[:action]
59
+ )
60
+
61
+ Process.wait(pid)
62
+
63
+ puts 'Rollback complete'
64
+ exit(false)
65
+ end
66
+
67
+ protected
68
+
69
+ def parse_options
70
+ options = {
71
+ timeout: 60,
72
+ toplevel: nil,
73
+ action: nil,
74
+ check_file: nil
75
+ }
76
+
77
+ opt_parser = OptionParser.new do |parser|
78
+ parser.banner = "Usage: #{$0} [options] <toplevel> <action> <check file>"
79
+
80
+ parser.on('-t', '--timeout TIMEOUT', Integer, 'Timeout in seconds') do |v|
81
+ options[:timeout] = v
82
+ end
83
+
84
+ parser.on('-h', '--help', 'Print help message and exit') do
85
+ puts parser
86
+ exit
87
+ end
88
+ end
89
+
90
+ opt_parser.parse!
91
+
92
+ if ARGV.length != 3
93
+ warn 'Invalid arguments'
94
+ warn opt_parser
95
+ exit(false)
96
+ end
97
+
98
+ options[:toplevel] = ARGV[0]
99
+ options[:action] = ARGV[1]
100
+ options[:check_file] = ARGV[2]
101
+
102
+ options
103
+ end
104
+ end
105
+
106
+ AutoRollback.run
@@ -1,4 +1,4 @@
1
- .TH confctl\-options.nix 8 2024\-02\-17 master
1
+ .TH confctl\-options.nix 8 2024\-05\-07 master
2
2
  .SH NAME
3
3
  .PP
4
4
  \fB\fCconfctl\-options.nix\fR \- confctl configuration documentation
@@ -599,6 +599,22 @@ Address with prefix as string
599
599
  .PP
600
600
  \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
601
601
  .TP
602
+ \fB\fCcluster.<name>.buildAttribute\fR
603
+ Path to the attribute in machine system config that should be built
604
+ .IP
605
+ For example, \fB\fC[ "system" "build" "toplevel" ]\fR will select attribute
606
+ \fB\fCconfig.system.build.toplevel\fR\&.
607
+ .PP
608
+ \fIType:\fP list of string
609
+ .PP
610
+ \fIDefault:\fP \fB\fC[
611
+ "system"
612
+ "build"
613
+ "toplevel"
614
+ ]\fR
615
+ .PP
616
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
617
+ .TP
602
618
  \fB\fCcluster.<name>.buildGenerations.max\fR
603
619
  The maximum number of build generations to be kept on the build
604
620
  machine.
@@ -632,6 +648,151 @@ machine.
632
648
  .PP
633
649
  \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
634
650
  .TP
651
+ \fB\fCcluster.<name>.carrier.enable\fR
652
+ Whether to enable This machine is a carrier for other machines.
653
+ .PP
654
+ \fIType:\fP boolean
655
+ .PP
656
+ \fIDefault:\fP \fB\fCfalse\fR
657
+ .PP
658
+ \fIExample:\fP \fB\fCtrue\fR
659
+ .PP
660
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
661
+ .TP
662
+ \fB\fCcluster.<name>.carrier.machines\fR
663
+ List of carried machines
664
+ .PP
665
+ \fIType:\fP list of (submodule)
666
+ .PP
667
+ \fIDefault:\fP \fB\fC[ ]\fR
668
+ .PP
669
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
670
+ .TP
671
+ \fB\fCcluster.<name>.carrier.machines.*.alias\fR
672
+ Alias for carried machine name
673
+ .PP
674
+ \fIType:\fP null or string
675
+ .PP
676
+ \fIDefault:\fP \fB\fCnull\fR
677
+ .PP
678
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
679
+ .TP
680
+ \fB\fCcluster.<name>.carrier.machines.*.buildAttribute\fR
681
+ Path to the attribute in machine system config that should be built
682
+ .IP
683
+ For example, \fB\fC[ "system" "build" "toplevel" ]\fR will select attribute
684
+ \fB\fCconfig.system.build.toplevel\fR\&.
685
+ .PP
686
+ \fIType:\fP list of string
687
+ .PP
688
+ \fIDefault:\fP \fB\fC[
689
+ "system"
690
+ "build"
691
+ "toplevel"
692
+ ]\fR
693
+ .PP
694
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
695
+ .TP
696
+ \fB\fCcluster.<name>.carrier.machines.*.buildGenerations.max\fR
697
+ The maximum number of build generations to be kept on the build
698
+ machine.
699
+ .PP
700
+ \fIType:\fP null or signed integer
701
+ .PP
702
+ \fIDefault:\fP \fB\fCnull\fR
703
+ .PP
704
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
705
+ .TP
706
+ \fB\fCcluster.<name>.carrier.machines.*.buildGenerations.maxAge\fR
707
+ Delete build generations older than
708
+ \fB\fCcluster.<name>.carrier.machines.*.buildGenerations.maxAge\fR
709
+ seconds from the build machine. Old generations are deleted even
710
+ if \fB\fCcluster.<name>.carrier.machines.*.buildGenerations.max\fR is
711
+ not reached.
712
+ .PP
713
+ \fIType:\fP null or signed integer
714
+ .PP
715
+ \fIDefault:\fP \fB\fCnull\fR
716
+ .PP
717
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
718
+ .TP
719
+ \fB\fCcluster.<name>.carrier.machines.*.buildGenerations.min\fR
720
+ The minimum number of build generations to be kept on the build
721
+ machine.
722
+ .PP
723
+ \fIType:\fP null or signed integer
724
+ .PP
725
+ \fIDefault:\fP \fB\fCnull\fR
726
+ .PP
727
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
728
+ .TP
729
+ \fB\fCcluster.<name>.carrier.machines.*.extraModules\fR
730
+ A list of additional NixOS modules to be imported for this machine
731
+ .PP
732
+ \fIType:\fP list of path
733
+ .PP
734
+ \fIDefault:\fP \fB\fC[ ]\fR
735
+ .PP
736
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
737
+ .TP
738
+ \fB\fCcluster.<name>.carrier.machines.*.hostGenerations.max\fR
739
+ The maximum number of generations to be kept on the machine.
740
+ .PP
741
+ \fIType:\fP null or signed integer
742
+ .PP
743
+ \fIDefault:\fP \fB\fCnull\fR
744
+ .PP
745
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
746
+ .TP
747
+ \fB\fCcluster.<name>.carrier.machines.*.hostGenerations.maxAge\fR
748
+ Delete generations older than
749
+ \fB\fCcluster.<name>.carrier.machines.*.hostGenerations.maxAge\fR
750
+ seconds from the machine. Old generations are deleted even
751
+ if \fB\fCcluster.<name>.carrier.machines.*.hostGenerations.max\fR is
752
+ not reached.
753
+ .PP
754
+ \fIType:\fP null or signed integer
755
+ .PP
756
+ \fIDefault:\fP \fB\fCnull\fR
757
+ .PP
758
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
759
+ .TP
760
+ \fB\fCcluster.<name>.carrier.machines.*.hostGenerations.min\fR
761
+ The minimum number of generations to be kept on the machine.
762
+ .PP
763
+ \fIType:\fP null or signed integer
764
+ .PP
765
+ \fIDefault:\fP \fB\fCnull\fR
766
+ .PP
767
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
768
+ .TP
769
+ \fB\fCcluster.<name>.carrier.machines.*.labels\fR
770
+ Optional user\-defined labels to classify the machine
771
+ .PP
772
+ \fIType:\fP attribute set
773
+ .PP
774
+ \fIDefault:\fP \fB\fC{ }\fR
775
+ .PP
776
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
777
+ .TP
778
+ \fB\fCcluster.<name>.carrier.machines.*.machine\fR
779
+ Machine name
780
+ .PP
781
+ \fIType:\fP string
782
+ .PP
783
+ \fIDefault:\fP \fB\fCnull\fR
784
+ .PP
785
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
786
+ .TP
787
+ \fB\fCcluster.<name>.carrier.machines.*.tags\fR
788
+ Optional user\-defined tags to classify the machine
789
+ .PP
790
+ \fIType:\fP list of string
791
+ .PP
792
+ \fIDefault:\fP \fB\fC[ ]\fR
793
+ .PP
794
+ \fIDeclared by:\fP \fB\fC<confctl/nix/modules/cluster>\fR
795
+ .TP
635
796
  \fB\fCcluster.<name>.healthChecks.builderCommands\fR
636
797
  Check commands run on the build machine
637
798
  .PP
@@ -1032,6 +1193,9 @@ Host name
1032
1193
  .TP
1033
1194
  \fB\fCcluster.<name>.host.target\fR
1034
1195
  Address/host to which the configuration is deployed to
1196
+ .IP
1197
+ Set to null if the machine is not deployable, e.g. when it is only used
1198
+ as a carried machine.
1035
1199
  .PP
1036
1200
  \fIType:\fP null or string
1037
1201
  .PP