confctl 1.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 (130) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.gitignore +8 -0
  4. data/.overcommit.yml +6 -0
  5. data/.rubocop.yml +67 -0
  6. data/.rubocop_todo.yml +5 -0
  7. data/.ruby-version +1 -0
  8. data/CHANGELOG.md +2 -0
  9. data/Gemfile +2 -0
  10. data/LICENSE.txt +674 -0
  11. data/README.md +522 -0
  12. data/Rakefile +40 -0
  13. data/bin/confctl +4 -0
  14. data/confctl.gemspec +33 -0
  15. data/example/.gitignore +2 -0
  16. data/example/README.md +38 -0
  17. data/example/cluster/cluster.nix +7 -0
  18. data/example/cluster/module-list.nix +3 -0
  19. data/example/cluster/nixos-machine/config.nix +15 -0
  20. data/example/cluster/nixos-machine/hardware.nix +4 -0
  21. data/example/cluster/nixos-machine/module.nix +8 -0
  22. data/example/cluster/vpsadminos-container/config.nix +22 -0
  23. data/example/cluster/vpsadminos-container/module.nix +8 -0
  24. data/example/cluster/vpsadminos-machine/config.nix +22 -0
  25. data/example/cluster/vpsadminos-machine/hardware.nix +4 -0
  26. data/example/cluster/vpsadminos-machine/module.nix +8 -0
  27. data/example/cluster/vpsfreecz-vps/config.nix +25 -0
  28. data/example/cluster/vpsfreecz-vps/module.nix +8 -0
  29. data/example/configs/confctl.nix +10 -0
  30. data/example/configs/swpins.nix +28 -0
  31. data/example/data/default.nix +5 -0
  32. data/example/data/ssh-keys.nix +7 -0
  33. data/example/environments/base.nix +13 -0
  34. data/example/modules/module-list.nix +13 -0
  35. data/example/shell.nix +11 -0
  36. data/example/swpins/channels/nixos-unstable.json +35 -0
  37. data/example/swpins/channels/vpsadminos-staging.json +35 -0
  38. data/lib/confctl/cli/app.rb +551 -0
  39. data/lib/confctl/cli/attr_filters.rb +51 -0
  40. data/lib/confctl/cli/cluster.rb +1248 -0
  41. data/lib/confctl/cli/command.rb +206 -0
  42. data/lib/confctl/cli/configuration.rb +296 -0
  43. data/lib/confctl/cli/gen_data.rb +97 -0
  44. data/lib/confctl/cli/generation.rb +335 -0
  45. data/lib/confctl/cli/log_view.rb +267 -0
  46. data/lib/confctl/cli/output_formatter.rb +288 -0
  47. data/lib/confctl/cli/swpins/base.rb +40 -0
  48. data/lib/confctl/cli/swpins/channel.rb +73 -0
  49. data/lib/confctl/cli/swpins/cluster.rb +80 -0
  50. data/lib/confctl/cli/swpins/core.rb +86 -0
  51. data/lib/confctl/cli/swpins/utils.rb +55 -0
  52. data/lib/confctl/cli/swpins.rb +5 -0
  53. data/lib/confctl/cli/tag_filters.rb +30 -0
  54. data/lib/confctl/cli.rb +5 -0
  55. data/lib/confctl/conf_cache.rb +105 -0
  56. data/lib/confctl/conf_dir.rb +88 -0
  57. data/lib/confctl/erb_template.rb +37 -0
  58. data/lib/confctl/exceptions.rb +3 -0
  59. data/lib/confctl/gcroot.rb +30 -0
  60. data/lib/confctl/generation/build.rb +145 -0
  61. data/lib/confctl/generation/build_list.rb +106 -0
  62. data/lib/confctl/generation/host.rb +35 -0
  63. data/lib/confctl/generation/host_list.rb +81 -0
  64. data/lib/confctl/generation/unified.rb +117 -0
  65. data/lib/confctl/generation/unified_list.rb +63 -0
  66. data/lib/confctl/git_repo_mirror.rb +79 -0
  67. data/lib/confctl/health_checks/base.rb +66 -0
  68. data/lib/confctl/health_checks/run_command.rb +179 -0
  69. data/lib/confctl/health_checks/systemd/properties.rb +84 -0
  70. data/lib/confctl/health_checks/systemd/property_check.rb +31 -0
  71. data/lib/confctl/health_checks/systemd/property_list.rb +20 -0
  72. data/lib/confctl/health_checks.rb +5 -0
  73. data/lib/confctl/hook.rb +35 -0
  74. data/lib/confctl/line_buffer.rb +53 -0
  75. data/lib/confctl/logger.rb +151 -0
  76. data/lib/confctl/machine.rb +107 -0
  77. data/lib/confctl/machine_control.rb +172 -0
  78. data/lib/confctl/machine_list.rb +108 -0
  79. data/lib/confctl/machine_status.rb +135 -0
  80. data/lib/confctl/module_options.rb +95 -0
  81. data/lib/confctl/nix.rb +382 -0
  82. data/lib/confctl/nix_build.rb +108 -0
  83. data/lib/confctl/nix_collect_garbage.rb +64 -0
  84. data/lib/confctl/nix_copy.rb +49 -0
  85. data/lib/confctl/nix_format.rb +124 -0
  86. data/lib/confctl/nix_literal_expression.rb +15 -0
  87. data/lib/confctl/parallel_executor.rb +43 -0
  88. data/lib/confctl/pattern.rb +9 -0
  89. data/lib/confctl/settings.rb +50 -0
  90. data/lib/confctl/std_line_buffer.rb +40 -0
  91. data/lib/confctl/swpins/change_set.rb +151 -0
  92. data/lib/confctl/swpins/channel.rb +62 -0
  93. data/lib/confctl/swpins/channel_list.rb +47 -0
  94. data/lib/confctl/swpins/cluster_name.rb +94 -0
  95. data/lib/confctl/swpins/cluster_name_list.rb +15 -0
  96. data/lib/confctl/swpins/core.rb +137 -0
  97. data/lib/confctl/swpins/deployed_info.rb +23 -0
  98. data/lib/confctl/swpins/spec.rb +20 -0
  99. data/lib/confctl/swpins/specs/base.rb +184 -0
  100. data/lib/confctl/swpins/specs/directory.rb +51 -0
  101. data/lib/confctl/swpins/specs/git.rb +135 -0
  102. data/lib/confctl/swpins/specs/git_rev.rb +24 -0
  103. data/lib/confctl/swpins.rb +17 -0
  104. data/lib/confctl/system_command.rb +10 -0
  105. data/lib/confctl/user_script.rb +13 -0
  106. data/lib/confctl/user_scripts.rb +41 -0
  107. data/lib/confctl/utils/file.rb +21 -0
  108. data/lib/confctl/version.rb +3 -0
  109. data/lib/confctl.rb +43 -0
  110. data/man/man8/confctl-options.nix.8 +1334 -0
  111. data/man/man8/confctl-options.nix.8.md +1340 -0
  112. data/man/man8/confctl.8 +660 -0
  113. data/man/man8/confctl.8.md +654 -0
  114. data/nix/evaluator.nix +160 -0
  115. data/nix/lib/default.nix +83 -0
  116. data/nix/lib/machine/default.nix +74 -0
  117. data/nix/lib/machine/info.nix +5 -0
  118. data/nix/lib/swpins/eval.nix +71 -0
  119. data/nix/lib/swpins/options.nix +94 -0
  120. data/nix/machines.nix +31 -0
  121. data/nix/modules/cluster/default.nix +459 -0
  122. data/nix/modules/confctl/cli.nix +21 -0
  123. data/nix/modules/confctl/generations.nix +84 -0
  124. data/nix/modules/confctl/nix.nix +28 -0
  125. data/nix/modules/confctl/swpins.nix +55 -0
  126. data/nix/modules/module-list.nix +19 -0
  127. data/shell.nix +42 -0
  128. data/template/confctl-options.nix/main.erb +45 -0
  129. data/template/confctl-options.nix/options.erb +15 -0
  130. metadata +353 -0
@@ -0,0 +1,551 @@
1
+ require 'gli'
2
+
3
+ module ConfCtl::Cli
4
+ class App
5
+ include GLI::App
6
+
7
+ def self.get
8
+ cli = new
9
+ cli.setup
10
+ cli
11
+ end
12
+
13
+ def self.run
14
+ cli = get
15
+ exit(cli.run(ARGV))
16
+ end
17
+
18
+ def setup
19
+ Thread.abort_on_exception = true
20
+
21
+ program_desc 'Nix deployment configuration management tool'
22
+ subcommand_option_handling :normal
23
+ preserve_argv true
24
+ arguments :strict
25
+ hide_commands_without_desc true
26
+
27
+ desc 'Toggle color mode'
28
+ flag %i[c color], must_match: %w[always never auto], default_value: 'auto'
29
+
30
+ desc 'Create a new configuration'
31
+ command :init do |c|
32
+ c.action(&Command.run(c, Configuration, :init))
33
+ end
34
+
35
+ desc 'Add a new machine'
36
+ arg_name '<name>'
37
+ command :add do |c|
38
+ c.action(&Command.run(c, Configuration, :add))
39
+ end
40
+
41
+ desc 'Rename an existing machine'
42
+ arg_name '<old-name> <new-name>'
43
+ command :rename do |c|
44
+ c.action(&Command.run(c, Configuration, :rename))
45
+ end
46
+
47
+ desc 'Update cluster machine list with contents of cluster/'
48
+ command :rediscover do |c|
49
+ c.action(&Command.run(c, Configuration, :rediscover))
50
+ end
51
+
52
+ desc 'Manage software pins'
53
+ command :swpins do |pins|
54
+ pins.desc 'Manage software pins channels'
55
+ pins.command :channel do |ch|
56
+ ch.desc 'List configured sw pins'
57
+ ch.arg_name '[channel [sw]]'
58
+ ch.command :ls do |c|
59
+ c.action(&Command.run(c, Swpins::Channel, :list))
60
+ end
61
+
62
+ swpins_commands(ch, Swpins::Channel, 'channel')
63
+ end
64
+
65
+ pins.desc 'Manage cluster software pins'
66
+ pins.command :cluster do |cl|
67
+ cl.desc 'List configured sw pins'
68
+ cl.arg_name '[cluster-name [sw]]'
69
+ cl.command :ls do |c|
70
+ c.action(&Command.run(c, Swpins::Cluster, :list))
71
+ end
72
+
73
+ swpins_commands(cl, Swpins::Cluster, 'name')
74
+ end
75
+
76
+ pins.desc 'Manage core software pins'
77
+ pins.command :core do |core|
78
+ core.desc 'List configured sw pins'
79
+ core.arg_name '[sw]'
80
+ core.command :ls do |c|
81
+ c.action(&Command.run(c, Swpins::Core, :list))
82
+ end
83
+
84
+ core.desc 'Set to specific version'
85
+ core.arg_name '<sw> <ref>'
86
+ core.command :set do |c|
87
+ c.desc 'Commit changes to git'
88
+ c.switch :commit, default_value: false
89
+
90
+ c.desc 'Include changelog in the commit message'
91
+ c.switch :changelog, default_value: true
92
+
93
+ c.desc 'Generate changelog for downgrade'
94
+ c.switch %i[d downgrade], default_value: false
95
+
96
+ c.action(&Command.run(c, Swpins::Core, :set))
97
+ end
98
+
99
+ core.desc 'Update to newest version'
100
+ core.arg_name '[<sw> [<version...>]]]'
101
+ core.command :update do |c|
102
+ c.desc 'Commit changes to git'
103
+ c.switch :commit, default_value: false
104
+
105
+ c.desc 'Include changelog in the commit message'
106
+ c.switch :changelog, default_value: true
107
+
108
+ c.desc 'Generate changelog for downgrade'
109
+ c.switch %i[d downgrade], default_value: false
110
+
111
+ c.action(&Command.run(c, Swpins::Core, :update))
112
+ end
113
+ end
114
+
115
+ pins.desc 'Update all swpins'
116
+ pins.command :update do |c|
117
+ c.desc 'Commit changes to git'
118
+ c.switch :commit, default_value: false
119
+
120
+ c.desc 'Include changelog in the commit message'
121
+ c.switch :changelog, default_value: true
122
+
123
+ c.desc 'Generate changelog for downgrade'
124
+ c.switch %i[d downgrade], default_value: false
125
+
126
+ c.action(&Command.run(c, Swpins::Base, :update))
127
+ end
128
+
129
+ pins.desc 'Generate confctl-managed JSON files for configured swpins'
130
+ pins.command :reconfigure do |c|
131
+ c.action(&Command.run(c, Swpins::Base, :reconfigure))
132
+ end
133
+ end
134
+
135
+ desc 'List configured machines'
136
+ arg_name '[machine-pattern]'
137
+ command :ls do |c|
138
+ c.desc 'Enable traces in Nix'
139
+ c.switch 'show-trace'
140
+
141
+ c.desc 'Filter (un)managed machines'
142
+ c.flag :managed, must_match: %w[y yes n no a all]
143
+
144
+ c.desc 'List possible attributes to output'
145
+ c.switch %i[L list], negatable: false
146
+
147
+ c.desc 'Select attributes to output'
148
+ c.flag %i[o output]
149
+
150
+ c.desc 'Do not show the header'
151
+ c.switch %i[H hide-header]
152
+
153
+ c.desc 'Filter by attribute'
154
+ c.flag %i[a attr], multiple: true
155
+
156
+ c.desc 'Filter by tag'
157
+ c.flag %i[t tag], multiple: true
158
+
159
+ c.action(&Command.run(c, Cluster, :list))
160
+ end
161
+
162
+ desc 'Build target systems'
163
+ arg_name '[machine-pattern]'
164
+ command :build do |c|
165
+ c.desc 'Enable traces in Nix'
166
+ c.switch 'show-trace'
167
+
168
+ c.desc 'Filter by attribute'
169
+ c.flag %i[a attr], multiple: true
170
+
171
+ c.desc 'Filter by tag'
172
+ c.flag %i[t tag], multiple: true
173
+
174
+ c.desc 'Assume the answer to confirmations is yes'
175
+ c.switch %w[y yes]
176
+
177
+ nix_build_options(c)
178
+
179
+ c.action(&Command.run(c, Cluster, :build))
180
+ end
181
+
182
+ desc 'Deploy target systems'
183
+ arg_name '[machine-pattern [switch-action]]'
184
+ command :deploy do |c|
185
+ c.desc 'Enable traces in Nix'
186
+ c.switch 'show-trace'
187
+
188
+ c.desc 'Filter by attribute'
189
+ c.flag %i[a attr], multiple: true
190
+
191
+ c.desc 'Filter by tag'
192
+ c.flag %i[t tag], multiple: true
193
+
194
+ c.desc 'Assume the answer to confirmations is yes'
195
+ c.switch %w[y yes]
196
+
197
+ c.desc 'Deploy selected generation'
198
+ c.flag %i[g generation]
199
+
200
+ c.desc 'Ask for confirmation before activation'
201
+ c.switch %w[i interactive]
202
+
203
+ c.desc 'Try to dry-activate before the real switch'
204
+ c.switch 'dry-activate-first'
205
+
206
+ c.desc 'Copy and deploy machines one by one'
207
+ c.switch 'one-by-one'
208
+
209
+ c.desc 'Max number of concurrent nix-copy-closure processes'
210
+ c.flag 'max-concurrent-copy', arg_name: 'n', type: Integer,
211
+ default_value: 5
212
+
213
+ c.desc 'Do not activate copied closures'
214
+ c.switch 'copy-only', negatable: false
215
+
216
+ c.desc 'Reboot target systems after deployment'
217
+ c.switch :reboot
218
+
219
+ c.desc 'Wait for the machine to boot'
220
+ c.flag 'wait-online', default_value: '600'
221
+
222
+ nix_build_options(c)
223
+
224
+ c.desc 'Toggle health checks'
225
+ c.switch 'health-checks', default_value: true
226
+
227
+ c.desc 'Do not abourt on failed health checks'
228
+ c.switch 'keep-going', default_value: false
229
+
230
+ c.action(&Command.run(c, Cluster, :deploy))
231
+ end
232
+
233
+ desc 'Run machine health-checks'
234
+ arg_name '[machine-pattern]'
235
+ command :'health-check' do |c|
236
+ c.desc 'Filter by attribute'
237
+ c.flag %i[a attr], multiple: true
238
+
239
+ c.desc 'Filter by tag'
240
+ c.flag %i[t tag], multiple: true
241
+
242
+ c.desc 'Assume the answer to confirmations is yes'
243
+ c.switch %w[y yes]
244
+
245
+ c.desc 'Maximum number of health-check jobs'
246
+ c.flag %w[j max-jobs], arg_name: 'number', type: Integer, default_value: 5
247
+
248
+ c.action(&Command.run(c, Cluster, :health_check))
249
+ end
250
+
251
+ desc 'Check machine status'
252
+ arg_name '[machine-pattern]'
253
+ command :status do |c|
254
+ c.desc 'Filter by attribute'
255
+ c.flag %i[a attr], multiple: true
256
+
257
+ c.desc 'Filter by tag'
258
+ c.flag %i[t tag], multiple: true
259
+
260
+ c.desc 'Assume the answer to confirmations is yes'
261
+ c.switch %w[y yes]
262
+
263
+ c.desc 'Check status against selected generation'
264
+ c.flag %i[g generation]
265
+
266
+ c.action(&Command.run(c, Cluster, :status))
267
+ end
268
+
269
+ desc 'Changelog between deployed and configured swpins'
270
+ arg_name '[machine-pattern [sw-pattern]]'
271
+ command :changelog do |c|
272
+ c.desc 'Filter by attribute'
273
+ c.flag %i[a attr], multiple: true
274
+
275
+ c.desc 'Filter by tag'
276
+ c.flag %i[t tag], multiple: true
277
+
278
+ c.desc 'Assume the answer to confirmations is yes'
279
+ c.switch %w[y yes]
280
+
281
+ c.desc 'Show changelog against swpins from selected generation'
282
+ c.flag %i[g generation]
283
+
284
+ c.desc 'Show a changelog for downgrade'
285
+ c.switch %i[d downgrade]
286
+
287
+ c.desc 'Show full-length changelog descriptions'
288
+ c.switch %i[v verbose]
289
+
290
+ c.desc 'Show patches'
291
+ c.switch %i[p patch]
292
+
293
+ nix_build_options(c)
294
+
295
+ c.action(&Command.run(c, Cluster, :changelog))
296
+ end
297
+
298
+ desc 'Diff between deployed and configured swpins'
299
+ arg_name '[machine-pattern [sw-pattern]]'
300
+ command :diff do |c|
301
+ c.desc 'Filter by attribute'
302
+ c.flag %i[a attr], multiple: true
303
+
304
+ c.desc 'Filter by tag'
305
+ c.flag %i[t tag], multiple: true
306
+
307
+ c.desc 'Assume the answer to confirmations is yes'
308
+ c.switch %w[y yes]
309
+
310
+ c.desc 'Show diff against swpins from selected generation'
311
+ c.flag %i[g generation]
312
+
313
+ c.desc 'Show a changelog for downgrade'
314
+ c.switch %i[d downgrade]
315
+
316
+ nix_build_options(c)
317
+
318
+ c.action(&Command.run(c, Cluster, :diff))
319
+ end
320
+
321
+ desc 'Test SSH connection'
322
+ arg_name '[machine-pattern]'
323
+ command :'test-connection' do |c|
324
+ c.desc 'Filter (un)managed machines'
325
+ c.flag :managed, must_match: %w[y yes n no a all]
326
+
327
+ c.desc 'Filter by attribute'
328
+ c.flag %i[a attr], multiple: true
329
+
330
+ c.desc 'Filter by tag'
331
+ c.flag %i[t tag], multiple: true
332
+
333
+ c.desc 'Assume the answer to confirmations is yes'
334
+ c.switch %w[y yes]
335
+
336
+ c.action(&Command.run(c, Cluster, :test_connection))
337
+ end
338
+
339
+ desc 'Run command over SSH'
340
+ arg_name '[machine-pattern [command [arguments...]]]'
341
+ command :ssh do |c|
342
+ c.desc 'Filter (un)managed machines'
343
+ c.flag :managed, must_match: %w[y yes n no a all]
344
+
345
+ c.desc 'Filter by attribute'
346
+ c.flag %i[a attr], multiple: true
347
+
348
+ c.desc 'Filter by tag'
349
+ c.flag %i[t tag], multiple: true
350
+
351
+ c.desc 'Assume the answer to confirmations is yes'
352
+ c.switch %w[y yes]
353
+
354
+ c.desc 'Run command in parallel on all machines at once'
355
+ c.switch %i[p parallel]
356
+
357
+ c.desc 'Aggregate identical command output'
358
+ c.switch %i[g aggregate]
359
+
360
+ c.desc 'Data passed to standard input'
361
+ c.flag %i[i input-string]
362
+
363
+ c.desc 'File passed to standard input'
364
+ c.flag %i[f input-file]
365
+
366
+ c.action(&Command.run(c, Cluster, :ssh))
367
+ end
368
+
369
+ desc 'Open ClusterSSH'
370
+ arg_name '[machine-pattern]'
371
+ command :cssh do |c|
372
+ c.desc 'Filter (un)managed machines'
373
+ c.flag :managed, must_match: %w[y yes n no a all]
374
+
375
+ c.desc 'Filter by attribute'
376
+ c.flag %i[a attr], multiple: true
377
+
378
+ c.desc 'Filter by tag'
379
+ c.flag %i[t tag], multiple: true
380
+
381
+ c.desc 'Assume the answer to confirmations is yes'
382
+ c.switch %w[y yes]
383
+
384
+ c.action(&Command.run(c, Cluster, :cssh))
385
+ end
386
+
387
+ desc 'Manage built machine generations'
388
+ command :generation do |gen|
389
+ gen.desc 'List machine generations'
390
+ gen.arg_name '[machine-pattern [generation-pattern]]'
391
+ gen.command :ls do |c|
392
+ c.desc 'Filter by attribute'
393
+ c.flag %i[a attr], multiple: true
394
+
395
+ c.desc 'Filter by tag'
396
+ c.flag %i[t tag], multiple: true
397
+
398
+ c.desc 'List local build generations'
399
+ c.switch %i[l local]
400
+
401
+ c.desc 'List remote machine generations'
402
+ c.switch %i[r remote]
403
+
404
+ c.action(&Command.run(c, Generation, :list))
405
+ end
406
+
407
+ gen.desc 'Remove machine generations'
408
+ gen.arg_name '[machine-pattern [generation-pattern|old]]'
409
+ gen.command :rm do |c|
410
+ c.desc 'Filter by attribute'
411
+ c.flag %i[a attr], multiple: true
412
+
413
+ c.desc 'Filter by tag'
414
+ c.flag %i[t tag], multiple: true
415
+
416
+ c.desc 'List local build generations'
417
+ c.switch %i[l local]
418
+
419
+ c.desc 'List remote machine generations'
420
+ c.switch %i[r remote]
421
+
422
+ c.desc 'Run nix-collect-garbage to delete unreachable store paths'
423
+ c.switch %i[gc collect-garbage], default_value: true
424
+
425
+ c.desc 'Max number of concurrent nix-collect-garbage processes'
426
+ c.flag 'max-concurrent-gc', arg_name: 'n', type: Integer,
427
+ default_value: 5
428
+
429
+ c.desc 'Assume the answer to confirmations is yes'
430
+ c.switch %w[y yes]
431
+
432
+ c.action(&Command.run(c, Generation, :remove))
433
+ end
434
+
435
+ gen.desc 'Auto-remove old machine generations'
436
+ gen.arg_name '[machine-pattern]'
437
+ gen.command :rotate do |c|
438
+ c.desc 'Filter by attribute'
439
+ c.flag %i[a attr], multiple: true
440
+
441
+ c.desc 'Filter by tag'
442
+ c.flag %i[t tag], multiple: true
443
+
444
+ c.desc 'List local build generations'
445
+ c.switch %i[l local]
446
+
447
+ c.desc 'List remote machine generations'
448
+ c.switch %i[r remote]
449
+
450
+ c.desc 'Max number of concurrent nix-collect-garbage processes'
451
+ c.flag 'max-concurrent-gc', arg_name: 'n', type: Integer,
452
+ default_value: 5
453
+
454
+ c.desc 'Assume the answer to confirmations is yes'
455
+ c.switch %w[y yes]
456
+
457
+ c.action(&Command.run(c, Generation, :rotate))
458
+ end
459
+ end
460
+
461
+ desc 'Run nix-collect-garbage to deleted unreachable store paths'
462
+ arg_name '[machine-pattern]'
463
+ command 'collect-garbage' do |c|
464
+ c.desc 'Filter by attribute'
465
+ c.flag %i[a attr], multiple: true
466
+
467
+ c.desc 'Filter by tag'
468
+ c.flag %i[t tag], multiple: true
469
+
470
+ c.desc 'Max number of concurrent nix-collect-garbage processes'
471
+ c.flag 'max-concurrent-gc', arg_name: 'n', type: Integer,
472
+ default_value: 5
473
+
474
+ c.desc 'Assume the answer to confirmations is yes'
475
+ c.switch %w[y yes]
476
+
477
+ c.action(&Command.run(c, Generation, :collect_garbage))
478
+ end
479
+
480
+ desc 'Generate data files'
481
+ command 'gen-data' do |gen|
482
+ gen.desc 'Fetch data from vpsAdmin'
483
+ gen.command :vpsadmin do |vpsa|
484
+ vpsa.desc 'Generate all data files'
485
+ vpsa.command :all do |c|
486
+ c.action(&Command.run(c, GenData, :vpsadmin_all))
487
+ end
488
+
489
+ vpsa.desc 'Generate container data files'
490
+ vpsa.command :containers do |c|
491
+ c.action(&Command.run(c, GenData, :vpsadmin_containers))
492
+ end
493
+
494
+ vpsa.desc 'Generate network data files'
495
+ vpsa.command :network do |c|
496
+ c.action(&Command.run(c, GenData, :vpsadmin_network))
497
+ end
498
+ end
499
+ end
500
+
501
+ ConfCtl::UserScripts.each do |script|
502
+ script.setup_cli(self)
503
+ end
504
+
505
+ on_error do |_exception|
506
+ log = ConfCtl::Logger.instance
507
+ warn "\nLog file: #{log.path}" if log.open?
508
+ true
509
+ end
510
+ end
511
+
512
+ protected
513
+
514
+ def swpins_commands(cmd, klass, arg_name)
515
+ cmd.desc 'Set to specific version'
516
+ cmd.arg_name "<#{arg_name}> <sw> <ref>"
517
+ cmd.command :set do |c|
518
+ c.desc 'Commit changes to git'
519
+ c.switch :commit, default_value: false
520
+
521
+ c.desc 'Include changelog in the commit message'
522
+ c.switch :changelog, default_value: true
523
+
524
+ c.desc 'Generate changelog for downgrade'
525
+ c.switch %i[d downgrade], default_value: false
526
+
527
+ c.action(&Command.run(c, klass, :set))
528
+ end
529
+
530
+ cmd.desc 'Update to newest version'
531
+ cmd.arg_name "[<#{arg_name}> [<sw> [<version...>]]]"
532
+ cmd.command :update do |c|
533
+ c.desc 'Commit changes to git'
534
+ c.switch :commit, default_value: false
535
+
536
+ c.desc 'Include changelog in the commit message'
537
+ c.switch :changelog, default_value: true
538
+
539
+ c.desc 'Generate changelog for downgrade'
540
+ c.switch %i[d downgrade], default_value: false
541
+
542
+ c.action(&Command.run(c, klass, :update))
543
+ end
544
+ end
545
+
546
+ def nix_build_options(cmd)
547
+ cmd.desc 'Maximum number of build jobs (see nix-build)'
548
+ cmd.flag %w[j max-jobs], arg_name: 'number'
549
+ end
550
+ end
551
+ end
@@ -0,0 +1,51 @@
1
+ module ConfCtl::Cli
2
+ class AttrFilters
3
+ # @param str_filters [Array<String>]
4
+ def initialize(str_filters)
5
+ @filters = parse_all(str_filters)
6
+ end
7
+
8
+ # @param machine [ConfCtl::Machine]
9
+ def pass?(machine)
10
+ filters.all? { |f| f.call(machine) }
11
+ end
12
+
13
+ protected
14
+
15
+ attr_reader :filters
16
+
17
+ def parse_all(str_filters)
18
+ ret = []
19
+
20
+ str_filters.each do |s|
21
+ k, v = parse_one(s, '!=')
22
+ if k
23
+ ret << proc do |machine|
24
+ machine[k].to_s != v
25
+ end
26
+ next
27
+ end
28
+
29
+ k, v = parse_one(s, '=')
30
+ if k
31
+ ret << proc do |machine|
32
+ machine[k].to_s == v
33
+ end
34
+ next
35
+ end
36
+
37
+ raise GLI::BadCommandLine, "Invalid filter '#{v}'"
38
+ end
39
+
40
+ ret
41
+ end
42
+
43
+ def parse_one(v, sep)
44
+ i = v.index(sep)
45
+ return false unless i
46
+
47
+ len = sep.length
48
+ [v[0..i - 1], v[i + len..]]
49
+ end
50
+ end
51
+ end