confctl 1.0.0 → 2.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.
@@ -46,7 +46,7 @@ let
46
46
 
47
47
  addresses = mkOption {
48
48
  type = types.nullOr (types.submodule addresses);
49
- default = null;
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;
@@ -321,11 +344,11 @@ let
321
344
  Host FQDN
322
345
  '';
323
346
  apply = v:
324
- if isNull v && !isNull config.name && !isNull config.domain then
347
+ if isNull v && !isNull config.name then
325
348
  concatStringsSep "." (
326
349
  [ config.name ]
327
350
  ++ (optional (!isNull config.location) config.location)
328
- ++ [ config.domain ]
351
+ ++ (optional (!isNull config.domain) config.domain)
329
352
  )
330
353
  else
331
354
  v;
@@ -336,11 +359,127 @@ let
336
359
  default = config.fqdn;
337
360
  description = ''
338
361
  Address/host to which the configuration is deployed to
362
+
363
+ Set to null if the machine is not deployable, e.g. when it is only used
364
+ as a carried machine.
339
365
  '';
340
366
  };
341
367
  };
342
368
  };
343
369
 
370
+ carriedMachine =
371
+ { config, ... }:
372
+ {
373
+ options = {
374
+ machine = mkOption {
375
+ type = types.str;
376
+ description = "Machine name";
377
+ };
378
+
379
+ alias = mkOption {
380
+ type = types.nullOr types.str;
381
+ description = "Alias for carried machine name";
382
+ };
383
+
384
+ labels = mkOption {
385
+ type = types.attrs;
386
+ default = {};
387
+ description = ''
388
+ Optional user-defined labels to classify the machine
389
+ '';
390
+ };
391
+
392
+ tags = mkOption {
393
+ type = types.listOf types.str;
394
+ default = [];
395
+ description = ''
396
+ Optional user-defined tags to classify the machine
397
+ '';
398
+ };
399
+
400
+ extraModules = mkOption {
401
+ type = types.listOf types.path;
402
+ default = [];
403
+ description = ''
404
+ A list of additional NixOS modules to be imported for this machine
405
+ '';
406
+ };
407
+
408
+ buildAttribute = mkOption {
409
+ type = types.listOf types.str;
410
+ default = [ "system" "build" "toplevel" ];
411
+ description = ''
412
+ Path to the attribute in machine system config that should be built
413
+
414
+ For example, `[ "system" "build" "toplevel" ]` will select attribute
415
+ `config.system.build.toplevel`.
416
+ '';
417
+ };
418
+
419
+ buildGenerations = {
420
+ min = mkOption {
421
+ type = types.nullOr types.int;
422
+ default = null;
423
+ description = ''
424
+ The minimum number of build generations to be kept on the build
425
+ machine.
426
+ '';
427
+ };
428
+
429
+ max = mkOption {
430
+ type = types.nullOr types.int;
431
+ default = null;
432
+ description = ''
433
+ The maximum number of build generations to be kept on the build
434
+ machine.
435
+ '';
436
+ };
437
+
438
+ maxAge = mkOption {
439
+ type = types.nullOr types.int;
440
+ default = null;
441
+ description = ''
442
+ Delete build generations older than
443
+ <option>cluster.&lt;name&gt;.carrier.machines.*.buildGenerations.maxAge</option>
444
+ seconds from the build machine. Old generations are deleted even
445
+ if <option>cluster.&lt;name&gt;.carrier.machines.*.buildGenerations.max</option> is
446
+ not reached.
447
+ '';
448
+ };
449
+ };
450
+
451
+ hostGenerations = {
452
+ min = mkOption {
453
+ type = types.nullOr types.int;
454
+ default = null;
455
+ description = ''
456
+ The minimum number of generations to be kept on the machine.
457
+ '';
458
+ };
459
+
460
+ max = mkOption {
461
+ type = types.nullOr types.int;
462
+ default = null;
463
+ description = ''
464
+ The maximum number of generations to be kept on the machine.
465
+ '';
466
+ };
467
+
468
+ maxAge = mkOption {
469
+ type = types.nullOr types.int;
470
+ default = null;
471
+ description = ''
472
+ Delete generations older than
473
+ <option>cluster.&lt;name&gt;.carrier.machines.*.hostGenerations.maxAge</option>
474
+ seconds from the machine. Old generations are deleted even
475
+ if <option>cluster.&lt;name&gt;.carrier.machines.*.hostGenerations.max</option> is
476
+ not reached.
477
+ '';
478
+ };
479
+ };
480
+ };
481
+ };
482
+
344
483
  systemdProperty =
345
484
  { config, ... }:
346
485
  {
@@ -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)