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.
- checksums.yaml +4 -4
- data/.editorconfig +1 -1
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +30 -1
- data/README.md +4 -9
- data/confctl.gemspec +14 -14
- data/docs/carrier.md +150 -0
- data/lib/confctl/cli/app.rb +19 -0
- data/lib/confctl/cli/cluster.rb +214 -49
- data/lib/confctl/cli/configuration.rb +7 -2
- data/lib/confctl/cli/gen_data.rb +19 -1
- data/lib/confctl/cli/generation.rb +47 -16
- data/lib/confctl/generation/build.rb +42 -1
- data/lib/confctl/generation/build_list.rb +10 -0
- data/lib/confctl/generation/host.rb +9 -5
- data/lib/confctl/generation/host_list.rb +22 -7
- data/lib/confctl/generation/unified.rb +5 -0
- data/lib/confctl/generation/unified_list.rb +10 -0
- data/lib/confctl/git_repo_mirror.rb +2 -2
- data/lib/confctl/machine.rb +105 -11
- data/lib/confctl/machine_control.rb +10 -2
- data/lib/confctl/machine_list.rb +18 -1
- data/lib/confctl/machine_status.rb +51 -4
- data/lib/confctl/nix.rb +90 -22
- data/lib/confctl/nix_copy.rb +5 -5
- data/lib/confctl/null_logger.rb +7 -0
- data/lib/confctl/swpins/specs/git.rb +1 -1
- data/lib/confctl/swpins/specs/git_rev.rb +1 -1
- data/lib/confctl/system_command.rb +3 -2
- data/lib/confctl/version.rb +1 -1
- data/libexec/auto-rollback.rb +106 -0
- data/man/man8/confctl-options.nix.8 +165 -1
- data/man/man8/confctl-options.nix.8.md +165 -1
- data/man/man8/confctl.8 +109 -73
- data/man/man8/confctl.8.md +86 -55
- data/nix/evaluator.nix +26 -7
- data/nix/lib/default.nix +64 -17
- data/nix/lib/machine/default.nix +14 -11
- data/nix/lib/machine/info.nix +3 -3
- data/nix/modules/cluster/default.nix +162 -3
- data/nix/modules/confctl/carrier/base.nix +35 -0
- data/nix/modules/confctl/carrier/carrier-env.rb +81 -0
- data/nix/modules/confctl/carrier/netboot/build-netboot-server.rb +962 -0
- data/nix/modules/confctl/carrier/netboot/nixos.nix +185 -0
- data/nix/modules/confctl/kexec-netboot/default.nix +36 -0
- data/nix/modules/confctl/kexec-netboot/kexec-netboot.8.adoc +62 -0
- data/nix/modules/confctl/kexec-netboot/kexec-netboot.rb +455 -0
- data/nix/modules/system-list.nix +10 -0
- metadata +17 -7
- data/.ruby-version +0 -1
@@ -46,7 +46,7 @@ let
|
|
46
46
|
|
47
47
|
addresses = mkOption {
|
48
48
|
type = types.nullOr (types.submodule addresses);
|
49
|
-
default =
|
49
|
+
default = {};
|
50
50
|
description = ''
|
51
51
|
IP addresses
|
52
52
|
'';
|
@@ -63,6 +63,29 @@ let
|
|
63
63
|
};
|
64
64
|
};
|
65
65
|
|
66
|
+
buildAttribute = mkOption {
|
67
|
+
type = types.listOf types.str;
|
68
|
+
default = [ "system" "build" "toplevel" ];
|
69
|
+
description = ''
|
70
|
+
Path to the attribute in machine system config that should be built
|
71
|
+
|
72
|
+
For example, `[ "system" "build" "toplevel" ]` will select attribute
|
73
|
+
`config.system.build.toplevel`.
|
74
|
+
'';
|
75
|
+
};
|
76
|
+
|
77
|
+
carrier = {
|
78
|
+
enable = mkEnableOption "This machine is a carrier for other machines";
|
79
|
+
|
80
|
+
machines = mkOption {
|
81
|
+
type = types.listOf (types.submodule carriedMachine);
|
82
|
+
default = [];
|
83
|
+
description = ''
|
84
|
+
List of carried machines
|
85
|
+
'';
|
86
|
+
};
|
87
|
+
};
|
88
|
+
|
66
89
|
host = mkOption {
|
67
90
|
type = types.nullOr (types.submodule host);
|
68
91
|
default = null;
|
@@ -163,6 +186,26 @@ let
|
|
163
186
|
};
|
164
187
|
};
|
165
188
|
|
189
|
+
autoRollback = {
|
190
|
+
enable = mkOption {
|
191
|
+
type = types.bool;
|
192
|
+
default = true;
|
193
|
+
description = ''
|
194
|
+
Enable automatic rollback in case the machine is unresponsive after
|
195
|
+
deploy
|
196
|
+
'';
|
197
|
+
};
|
198
|
+
|
199
|
+
timeout = mkOption {
|
200
|
+
type = types.int;
|
201
|
+
default = 60;
|
202
|
+
description = ''
|
203
|
+
Number of seconds after which if the machine is unreachable, auto-rollback
|
204
|
+
is initiated
|
205
|
+
'';
|
206
|
+
};
|
207
|
+
};
|
208
|
+
|
166
209
|
healthChecks = {
|
167
210
|
systemd = {
|
168
211
|
enable = mkOption {
|
@@ -321,11 +364,11 @@ let
|
|
321
364
|
Host FQDN
|
322
365
|
'';
|
323
366
|
apply = v:
|
324
|
-
if isNull v && !isNull config.name
|
367
|
+
if isNull v && !isNull config.name then
|
325
368
|
concatStringsSep "." (
|
326
369
|
[ config.name ]
|
327
370
|
++ (optional (!isNull config.location) config.location)
|
328
|
-
++
|
371
|
+
++ (optional (!isNull config.domain) config.domain)
|
329
372
|
)
|
330
373
|
else
|
331
374
|
v;
|
@@ -336,8 +379,124 @@ let
|
|
336
379
|
default = config.fqdn;
|
337
380
|
description = ''
|
338
381
|
Address/host to which the configuration is deployed to
|
382
|
+
|
383
|
+
Set to null if the machine is not deployable, e.g. when it is only used
|
384
|
+
as a carried machine.
|
385
|
+
'';
|
386
|
+
};
|
387
|
+
};
|
388
|
+
};
|
389
|
+
|
390
|
+
carriedMachine =
|
391
|
+
{ config, ... }:
|
392
|
+
{
|
393
|
+
options = {
|
394
|
+
machine = mkOption {
|
395
|
+
type = types.str;
|
396
|
+
description = "Machine name";
|
397
|
+
};
|
398
|
+
|
399
|
+
alias = mkOption {
|
400
|
+
type = types.nullOr types.str;
|
401
|
+
description = "Alias for carried machine name";
|
402
|
+
};
|
403
|
+
|
404
|
+
labels = mkOption {
|
405
|
+
type = types.attrs;
|
406
|
+
default = {};
|
407
|
+
description = ''
|
408
|
+
Optional user-defined labels to classify the machine
|
409
|
+
'';
|
410
|
+
};
|
411
|
+
|
412
|
+
tags = mkOption {
|
413
|
+
type = types.listOf types.str;
|
414
|
+
default = [];
|
415
|
+
description = ''
|
416
|
+
Optional user-defined tags to classify the machine
|
417
|
+
'';
|
418
|
+
};
|
419
|
+
|
420
|
+
extraModules = mkOption {
|
421
|
+
type = types.listOf types.path;
|
422
|
+
default = [];
|
423
|
+
description = ''
|
424
|
+
A list of additional NixOS modules to be imported for this machine
|
425
|
+
'';
|
426
|
+
};
|
427
|
+
|
428
|
+
buildAttribute = mkOption {
|
429
|
+
type = types.listOf types.str;
|
430
|
+
default = [ "system" "build" "toplevel" ];
|
431
|
+
description = ''
|
432
|
+
Path to the attribute in machine system config that should be built
|
433
|
+
|
434
|
+
For example, `[ "system" "build" "toplevel" ]` will select attribute
|
435
|
+
`config.system.build.toplevel`.
|
339
436
|
'';
|
340
437
|
};
|
438
|
+
|
439
|
+
buildGenerations = {
|
440
|
+
min = mkOption {
|
441
|
+
type = types.nullOr types.int;
|
442
|
+
default = null;
|
443
|
+
description = ''
|
444
|
+
The minimum number of build generations to be kept on the build
|
445
|
+
machine.
|
446
|
+
'';
|
447
|
+
};
|
448
|
+
|
449
|
+
max = mkOption {
|
450
|
+
type = types.nullOr types.int;
|
451
|
+
default = null;
|
452
|
+
description = ''
|
453
|
+
The maximum number of build generations to be kept on the build
|
454
|
+
machine.
|
455
|
+
'';
|
456
|
+
};
|
457
|
+
|
458
|
+
maxAge = mkOption {
|
459
|
+
type = types.nullOr types.int;
|
460
|
+
default = null;
|
461
|
+
description = ''
|
462
|
+
Delete build generations older than
|
463
|
+
<option>cluster.<name>.carrier.machines.*.buildGenerations.maxAge</option>
|
464
|
+
seconds from the build machine. Old generations are deleted even
|
465
|
+
if <option>cluster.<name>.carrier.machines.*.buildGenerations.max</option> is
|
466
|
+
not reached.
|
467
|
+
'';
|
468
|
+
};
|
469
|
+
};
|
470
|
+
|
471
|
+
hostGenerations = {
|
472
|
+
min = mkOption {
|
473
|
+
type = types.nullOr types.int;
|
474
|
+
default = null;
|
475
|
+
description = ''
|
476
|
+
The minimum number of generations to be kept on the machine.
|
477
|
+
'';
|
478
|
+
};
|
479
|
+
|
480
|
+
max = mkOption {
|
481
|
+
type = types.nullOr types.int;
|
482
|
+
default = null;
|
483
|
+
description = ''
|
484
|
+
The maximum number of generations to be kept on the machine.
|
485
|
+
'';
|
486
|
+
};
|
487
|
+
|
488
|
+
maxAge = mkOption {
|
489
|
+
type = types.nullOr types.int;
|
490
|
+
default = null;
|
491
|
+
description = ''
|
492
|
+
Delete generations older than
|
493
|
+
<option>cluster.<name>.carrier.machines.*.hostGenerations.maxAge</option>
|
494
|
+
seconds from the machine. Old generations are deleted even
|
495
|
+
if <option>cluster.<name>.carrier.machines.*.hostGenerations.max</option> is
|
496
|
+
not reached.
|
497
|
+
'';
|
498
|
+
};
|
499
|
+
};
|
341
500
|
};
|
342
501
|
};
|
343
502
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
{ config, pkgs, lib, confMachine, ... }:
|
2
|
+
let
|
3
|
+
inherit (lib) mkIf mkOption types;
|
4
|
+
|
5
|
+
cfg = config.confctl.carrier;
|
6
|
+
|
7
|
+
carrier-env = pkgs.substituteAll {
|
8
|
+
src = ./carrier-env.rb;
|
9
|
+
name = "carrier-env";
|
10
|
+
isExecutable = true;
|
11
|
+
dir = "bin";
|
12
|
+
ruby = pkgs.ruby;
|
13
|
+
onChangeCommands = pkgs.writeScript "carrier-on-change-commands.sh" ''
|
14
|
+
#!${pkgs.bash}/bin/bash
|
15
|
+
${cfg.onChangeCommands}
|
16
|
+
'';
|
17
|
+
};
|
18
|
+
in {
|
19
|
+
options = {
|
20
|
+
confctl.carrier.onChangeCommands = mkOption {
|
21
|
+
type = types.lines;
|
22
|
+
default = "";
|
23
|
+
description = ''
|
24
|
+
Extra commands executed on a carrier machine when carried machine
|
25
|
+
is deployed or removed
|
26
|
+
'';
|
27
|
+
};
|
28
|
+
};
|
29
|
+
|
30
|
+
config = mkIf confMachine.carrier.enable {
|
31
|
+
environment.systemPackages = [
|
32
|
+
carrier-env
|
33
|
+
];
|
34
|
+
};
|
35
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!@ruby@/bin/ruby
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
class CarrierEnv
|
5
|
+
ON_CHANGE_COMMANDS = '@onChangeCommands@'.freeze
|
6
|
+
|
7
|
+
def self.run(args)
|
8
|
+
env = new
|
9
|
+
env.run(args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@action = nil
|
14
|
+
@profile = nil
|
15
|
+
@generation = nil
|
16
|
+
|
17
|
+
@optparser = OptionParser.new do |parser|
|
18
|
+
parser.banner = "Usage: #{$0} <options>"
|
19
|
+
|
20
|
+
parser.on('-p', '--profile PROFILE', 'Profile path') do |v|
|
21
|
+
@profile = v
|
22
|
+
end
|
23
|
+
|
24
|
+
parser.on('--set GENERATION', 'Set profile to generation') do |v|
|
25
|
+
@action = :set
|
26
|
+
@generation = v
|
27
|
+
end
|
28
|
+
|
29
|
+
parser.on('--delete-generations GENERATIONS', 'Delete generations') do |v|
|
30
|
+
@action = :delete
|
31
|
+
@generation = v
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def run(args)
|
37
|
+
@optparser.parse!(args)
|
38
|
+
|
39
|
+
if args.any?
|
40
|
+
warn 'Too many arguments'
|
41
|
+
puts parser
|
42
|
+
exit(false)
|
43
|
+
elsif @action.nil?
|
44
|
+
warn 'No action specified'
|
45
|
+
exit(false)
|
46
|
+
elsif @profile.nil?
|
47
|
+
warn 'Profile not set'
|
48
|
+
exit(false)
|
49
|
+
end
|
50
|
+
|
51
|
+
send(:"run_#{@action}")
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def run_set
|
57
|
+
nix_env('--set', @generation)
|
58
|
+
on_change_commands
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_delete
|
62
|
+
nix_env('--delete-generations', @generation)
|
63
|
+
on_change_commands
|
64
|
+
end
|
65
|
+
|
66
|
+
def nix_env(*args)
|
67
|
+
system_command('nix-env', '-p', @profile, *args)
|
68
|
+
end
|
69
|
+
|
70
|
+
def on_change_commands
|
71
|
+
system_command(ON_CHANGE_COMMANDS)
|
72
|
+
end
|
73
|
+
|
74
|
+
def system_command(*args)
|
75
|
+
return if Kernel.system(*args)
|
76
|
+
|
77
|
+
raise "#{args.join(' ')} failed"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
CarrierEnv.run(ARGV)
|