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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 869735b23809f8bef14f7e1e39b57e7bcaf4a90a37c7e5f4c03064a526cc1c46
4
- data.tar.gz: 1badf4f41f9183cbc5c716d436d89b3ccae96519e2f37bf0b67c4ffe7fde89e7
3
+ metadata.gz: 94823b33bdeb90ed8aa1a2aa835e8a3f48300c116ee951c3d41e8c433e9ea1ed
4
+ data.tar.gz: 7ec55e71a411a0844a687047d797c0324efeeb2b2f2fd1dd5efa3261ede6a184
5
5
  SHA512:
6
- metadata.gz: 889dc492d0996711bff26a442532cb955dc5fcf5f25c281e25475b7a9e657f64270cc6c839e81b4a3880ab250c50e7a817c30bbfc6c8a37e0b5d7fb755bad212
7
- data.tar.gz: b894f7b1720684ad93af743e8fc55f221876c7665d7302682f8354865fdc9c54f17acb990d088981d6638d908624e4687e412dda141eede57556f03bf7f741d7
6
+ metadata.gz: 83cf4e6ef92ec1cf76f2b260e689a45b52dc3653c35d82bdddabb3246e37b0ddb5d056ad60ebed5506e72612f235e7a283d9eecd29b1822482013ffa1562037a
7
+ data.tar.gz: aa12794664afe5a91595f91da89e8fe7d8e7205ad4428918bf0e0047ea2f1603244f3fb7aec458d0d0f2e5fdef21add41d431136b6872ec2ae26fe401258111e
data/.editorconfig CHANGED
@@ -5,7 +5,7 @@ root = true
5
5
  charset = utf-8
6
6
  end_of_line = lf
7
7
 
8
- [*.{rb,erb,nix}]
8
+ [*.{rb,erb,md,nix}]
9
9
  indent_size = 2
10
10
  indent_style = space
11
11
  trim_trailing_whitespace = true
data/.gitignore CHANGED
@@ -5,4 +5,5 @@ man/*.html
5
5
  man/**/*.html
6
6
  man/man?/*.?
7
7
  html_doc
8
+ .gems
8
9
  .yardoc
data/.rubocop.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
3
  AllCops:
4
+ TargetRubyVersion: 3.1.0
4
5
  NewCops: enable
5
6
  Exclude:
6
7
  - '*.rb'
data/CHANGELOG.md CHANGED
@@ -1,2 +1,31 @@
1
- # Sat Feb 17 2023 -- version 1.0.0
1
+ # Sun May 11 2025 -- version 2.1.0
2
+ - Support for referring to generations by their offset
3
+ - Resolved generations are printed on build/deploy/etc.
4
+ - Automatically rollback faulty configurations
5
+ - Interleave copying of carried machine generations
6
+ - Add `confctl.programs.kexec-netboot`
7
+ - Let the user retry dry activation in interactive mode
8
+ - Fix listing, deletion and garbage collection of carried machines' generations
9
+ - Read and display kernel version for each generation
10
+ - Option to disable the garbage collection in `confctl generation rotate`
11
+ - Shorten titles and entries in netboot menus
12
+
13
+ # Sun Nov 17 2024 -- version 2.0.0
14
+ - Distinguish machine `config` and `metaConfig` (breaking change)
15
+ - Support for machine carriers and netboot servers
16
+ - Optimized git fetch calls when updating software pins
17
+ - Added option `--cores` that is passed to nix-build
18
+ - Added RuboCop
19
+ - Bug fixes
20
+
21
+ ## Transition to `metaConfig`
22
+ The use of `config` has been ambiguous, it could either mean machine
23
+ configuration, i.e. the result of all configured NixOS/vpsAdminOS options,
24
+ or it could mean machine metadata from `module.nix`. Machine metadata
25
+ is now accessible as `metaConfig`.
26
+
27
+ - `confLib.findConfig` has been renamed to `confLib.findMetaConfig`
28
+ - `confLib.getClusterMachines` returns a list of machines with `metaConfig` attribute
29
+
30
+ # Sat Feb 17 2024 -- version 1.0.0
2
31
  - Initial release
data/README.md CHANGED
@@ -13,6 +13,8 @@ machines.
13
13
  configurations)
14
14
  * Query machine state, view changelogs and diffs
15
15
  * Run health checks
16
+ * Automatically roll back faulty configurations
17
+ * Support for creating netboot servers with option to kexec, see [docs/carrier.md](docs/carrier.md)
16
18
 
17
19
  ## Requirements
18
20
 
@@ -40,19 +42,12 @@ stored:
40
42
  ```
41
43
  mkdir cluster-configuration
42
44
  ```
43
- 3. Prepare `shell.nix` in the new directory:
44
- - Create a `shell.nix` and import the same file from confctl:
45
+ 3. Create `shell.nix` and import the same file from confctl:
45
46
  ```
46
47
  cd cluster-configuration
47
48
  cat > shell.nix <<EOF
48
49
  import ../confctl/shell.nix
49
50
  EOF
50
- ```
51
-
52
- - Alternatively, you can symlink `shell.nix` from the confctl repository:
53
- ```
54
- cd cluster-configuration
55
- ln -s ../confctl/shell.nix shell.nix
56
51
  ```
57
52
 
58
53
  4. Enter the `nix-shell`. This will make confctl available and install its
@@ -489,7 +484,7 @@ Then you can use it in machine module as:
489
484
  Note that these modules are self-contained. They are not evaluated with the full
490
485
  set of NixOS modules. You have to import modules that you need.
491
486
 
492
- ## User-defined confctl commands
487
+ ## User-defined confctl commands
493
488
  User-defined Ruby scripts can be placed in directory `scripts`. Each script
494
489
  should create a subclass of `ConfCtl::UserScript` and call class-method `register`.
495
490
  Scripts can define their own `confctl` subcommands.
data/confctl.gemspec CHANGED
@@ -15,19 +15,19 @@ Gem::Specification.new do |s|
15
15
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
16
  s.license = 'GPL-3.0-only'
17
17
 
18
- s.required_ruby_version = ">= #{File.read('.ruby-version').strip}"
18
+ s.required_ruby_version = '>= 3.1.0'
19
19
 
20
- s.add_runtime_dependency 'curses'
21
- s.add_runtime_dependency 'gli', '~> 2.21.0'
22
- s.add_runtime_dependency 'json'
23
- s.add_runtime_dependency 'md2man'
24
- s.add_runtime_dependency 'rainbow', '~> 3.1.1'
25
- s.add_runtime_dependency 'rake'
26
- s.add_runtime_dependency 'require_all', '~> 2.0.0'
27
- s.add_runtime_dependency 'tty-command', '~> 0.10.1'
28
- s.add_runtime_dependency 'tty-cursor', '~> 0.7.1'
29
- s.add_runtime_dependency 'tty-pager', '~> 0.14.0'
30
- s.add_runtime_dependency 'tty-progressbar', '~> 0.18.2'
31
- s.add_runtime_dependency 'tty-spinner', '~> 0.9.3'
32
- s.add_runtime_dependency 'vpsfree-client', '~> 0.18.0'
20
+ s.add_dependency 'curses'
21
+ s.add_dependency 'gli', '~> 2.22.0'
22
+ s.add_dependency 'json'
23
+ s.add_dependency 'md2man'
24
+ s.add_dependency 'rainbow', '~> 3.1.1'
25
+ s.add_dependency 'rake'
26
+ s.add_dependency 'require_all', '~> 2.0.0'
27
+ s.add_dependency 'tty-command', '~> 0.10.1'
28
+ s.add_dependency 'tty-cursor', '~> 0.7.1'
29
+ s.add_dependency 'tty-pager', '~> 0.14.0'
30
+ s.add_dependency 'tty-progressbar', '~> 0.18.2'
31
+ s.add_dependency 'tty-spinner', '~> 0.9.3'
32
+ s.add_dependency 'vpsfree-client', '~> 0.19.0'
33
33
  end
data/docs/carrier.md ADDED
@@ -0,0 +1,150 @@
1
+ # confctl carriers
2
+ Carrier is a machine that can carry other machines. The concept was created
3
+ for the purpose of building netboot servers, but can be used in other settings
4
+ as well.
5
+
6
+ All machines must be defined within the cluster as usual. We can then designate
7
+ a machine that will serve as a carrier and provide a list of machines that it
8
+ will carry, e.g.:
9
+
10
+ ```nix
11
+ # File cluster/pxe-server/module.nix
12
+ cluster.pxe-server = {
13
+ # ...
14
+ carrier = {
15
+ enable = true;
16
+
17
+ # A list of machines found in the cluster/ directory that will be
18
+ # available on the netboot server. Note that you will have to create
19
+ # your own buildAttribute, so that the resulting path contains bzImage,
20
+ # initrd and possibly a machine.json file.
21
+ machines = [
22
+ {
23
+ machine = "node1";
24
+ buildAttribute = [ "system" "build" "dist" ];
25
+ }
26
+ ];
27
+ };
28
+ };
29
+ ```
30
+
31
+ Now the `node1` machine is available as two machines within the cluster:
32
+ `node1` and `pxe-server#node1`. We can build and deploy both:
33
+
34
+ * `confctl deploy node1` will deploy the target machine as defined by the configuration
35
+ * `confctl deploy pxe-server#node1` will build the machine and copy the result to `pxe-server`, its carrier
36
+
37
+ We need both commands to build a slightly different output, but based on the same
38
+ configuration. When deploying `node1`, confctl will build attribute
39
+ `config.system.build.toplevel`, where as deploying `pxe-server#node1` will build
40
+ attribute `config.system.build.dist`. This attribute is configured in `buildAttribute`
41
+ option in the example above. `config.system.build.dist` is defined within vpsAdminOS,
42
+ its output is a directory with kernel bzImage, initrd and the root filesystem
43
+ in a squashfs image, i.e. what we need for booting from network.
44
+
45
+ Custom build attributes can be created by the user. For example, this is how
46
+ `config.system.build.dist` would be defined for NixOS:
47
+
48
+ ```nix
49
+ # File cluster/nixos/config.nix
50
+ { config, pkgs, lib, confMachine, swpinsInfo, ... }:
51
+ let
52
+ # machine.json contains metadata about the machine that the carrier uses
53
+ # to assemble the netboot server
54
+ machineJson = pkgs.writeText "machine-${config.networking.hostName}.json" (builtins.toJSON {
55
+ # machine spin, nixos/vpsadminos
56
+ spin = "nixos";
57
+
58
+ # fully qualified domain name
59
+ fqdn = confMachine.host.fqdn;
60
+
61
+ # label used e.g. in user menus
62
+ label = confMachine.host.fqdn;
63
+
64
+ # path to the top-level derivation, needed for system boot
65
+ toplevel = builtins.unsafeDiscardStringContext config.system.build.toplevel;
66
+
67
+ # NixOS version and git revision
68
+ version = config.system.nixos.version;
69
+ revision = config.system.nixos.revision;
70
+
71
+ # MAC addresses for auto-detection
72
+ macs = confMachine.netboot.macs;
73
+
74
+ # Information used by confctl status
75
+ swpins-info = swpinsInfo;
76
+ });
77
+ in {
78
+ imports = [
79
+ <nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix>
80
+ ];
81
+
82
+ # Define custom build attribute
83
+ system.build.dist = pkgs.symlinkJoin {
84
+ name = "nixos-netboot";
85
+ paths = [
86
+ config.system.build.netbootRamdisk
87
+ config.system.build.kernel
88
+ config.system.build.netbootIpxeScript
89
+ ];
90
+
91
+ # Install machine.json
92
+ postBuild = ''
93
+ ln -s ${machineJson} $out/machine.json
94
+ '';
95
+ };
96
+
97
+ # other NixOS configuration
98
+ }
99
+ ```
100
+
101
+ The carrier must be configured to handle the carried machines. Netboot server
102
+ support is integrated within confctl and it only has to be enabled.
103
+
104
+ ```nix
105
+ # File cluster/pxe-server/config.nix
106
+ { config, ... }:
107
+ {
108
+ confctl.carrier.netboot = {
109
+ enable = true;
110
+
111
+ # IP address or hostname the netboot server will be available on
112
+ host = "192.168.100.5";
113
+
114
+ # IP ranges that will have access to the server
115
+ allowedIPv4Ranges = [
116
+ "192.168.100.0/24"
117
+ ];
118
+ };
119
+ }
120
+ ```
121
+
122
+ The netboot server is rebuilt whenever a machine is deployed to it.
123
+ The rebuild can be also run manually using command `build-netboot-server`.
124
+
125
+ ## Other uses
126
+ You can define your own commands to be run on the carrier machine when
127
+ images are deployed to it:
128
+
129
+ ```nix
130
+ # File cluster/pxe-server/config.nix
131
+ { config, ... }:
132
+ {
133
+ confctl.carrier.onChangeCommands = ''
134
+ # List profiles of carried machines
135
+ ls -l /nix/var/nix/profiles/confctl-*
136
+ '';
137
+ }
138
+ ```
139
+
140
+ ## kexec from the netboot server
141
+ Set `confctl.programs.kexec-netboot.enable = true;` within your netbooted machine
142
+ configurations. This will add program `kexec-netboot` to your system path.
143
+
144
+ This program can be used to load kernel and initrd from the netboot server for kexec.
145
+ It automatically discovers the netboot server it was booted from, by default it uses
146
+ the latest generation found on the netboot server at the moment of execution. Use
147
+ `kexec-netboot --interactive` to select which machine/generation/variant should be
148
+ loaded. See `kexec-netboot --help` for all available options.
149
+
150
+ The loaded kernel can be run either by `kexec-netboot -e` or `kexec -e` directly.
@@ -11,6 +11,13 @@ module ConfCtl::Cli
11
11
  end
12
12
 
13
13
  def self.run
14
+ # Workaround for nix-build error:
15
+ # error: creating directory '/tmp/nix-shell-5100-0/nix-build-1986594-0': No such file or directory
16
+ if ENV['IN_NIX_SHELL']
17
+ ENV['TMP'] = '/tmp'
18
+ ENV['TMPDIR'] = '/tmp'
19
+ end
20
+
14
21
  cli = get
15
22
  exit(cli.run(ARGV))
16
23
  end
@@ -213,6 +220,12 @@ module ConfCtl::Cli
213
220
  c.desc 'Do not activate copied closures'
214
221
  c.switch 'copy-only', negatable: false
215
222
 
223
+ c.desc 'Enable auto-rollback'
224
+ c.switch 'enable-auto-rollback', default_value: false, negatable: false
225
+
226
+ c.desc 'Disable auto-rollback'
227
+ c.switch 'disable-auto-rollback', default_value: false, negatable: false
228
+
216
229
  c.desc 'Reboot target systems after deployment'
217
230
  c.switch :reboot
218
231
 
@@ -447,6 +460,9 @@ module ConfCtl::Cli
447
460
  c.desc 'List remote machine generations'
448
461
  c.switch %i[r remote]
449
462
 
463
+ c.desc 'Do not run the garbage collector if enabled in configuration'
464
+ c.switch %i[gc collect-garbage], default_value: true
465
+
450
466
  c.desc 'Max number of concurrent nix-collect-garbage processes'
451
467
  c.flag 'max-concurrent-gc', arg_name: 'n', type: Integer,
452
468
  default_value: 5
@@ -546,6 +562,9 @@ module ConfCtl::Cli
546
562
  def nix_build_options(cmd)
547
563
  cmd.desc 'Maximum number of build jobs (see nix-build)'
548
564
  cmd.flag %w[j max-jobs], arg_name: 'number'
565
+
566
+ cmd.desc 'Number of CPU cores to be used (see nix-build)'
567
+ cmd.flag :cores, arg_name: 'number'
549
568
  end
550
569
  end
551
570
  end