Class: Mt::Wall::CLI
- Inherits:
-
Object
- Object
- Mt::Wall::CLI
- Defined in:
- lib/mt/wall/cli.rb
Overview
Command-line entry point driving the GitOps loop:
mt-wall validate <paths...> # load + compile the DSL, no device
mt-wall plan <paths...> [--device] # show the diff per device (read-only)
mt-wall apply <paths...> [--device] # converge each device to desired
PATHS may be ‘*.rb` files and/or DIRECTORIES (a directory contributes every `*.rb` under it, recursively, in sorted order) — see Mt::Wall.load.
FLEET: plan/apply operate on EVERY device in the loaded Configuration by default. ‘–device NAME` may be REPEATED to target a subset. Output is a per-device section followed by a rollup summary line.
Typical CI wiring: ‘validate` + `plan` on every PR, `apply` on merge.
EXIT CODES (CI-friendly, Terraform-style; aggregated across the fleet):
0 success / no device has changes
1 error (invalid DSL, unknown device, transport/plan failure, bad args,
apply aborted/refused, any device failed during apply)
2 `plan` ONLY: success, but at least one device has pending changes
SECRETS: credentials are NEVER passed on the command line. The per-device transport adapter (selected by the DSL ‘transport:`) reads them from ENV.
Constant Summary collapse
- EXIT_OK =
rubocop:disable Metrics/ClassLength
0- EXIT_ERROR =
1- EXIT_CHANGES =
‘plan` returns this when the diff is non-empty so CI can branch on “there is work to apply” without parsing stdout.
2- ACTION_GLYPHS =
Glyphs prefixing each operation in a printed plan (Terraform-style).
{ create: "+", update: "~", delete: "-", move: "»" }.freeze
- USAGE =
<<~USAGE Usage: mt-wall {validate|plan|apply} [options] <paths...> validate <paths...> Load and compile the DSL; no device access. plan <paths...> [--device] Show the per-device diff (read-only). apply <paths...> [--device] Converge each device to the desired state. PATHS may be DSL files or directories (a directory loads every *.rb under it, recursively, in sorted order). plan/apply target ALL devices by default. Options: --device NAME Limit plan/apply to device NAME (repeatable; default: all). --json plan/validate: emit machine-readable JSON instead of text. --auto-approve apply: skip the interactive confirmation (required for CI). -h, --help Show this help. apply prompts for confirmation ('yes' to proceed) and REFUSES on a non-interactive stdin unless --auto-approve is given. Exit codes: 0 = success/no changes, 1 = error, 2 = plan has changes. USAGE
Class Method Summary collapse
-
.start(argv = ARGV) ⇒ Integer
Process exit status.
Instance Method Summary collapse
-
#initialize(out: $stdout, err: $stderr, input: $stdin, transport_factory: nil) ⇒ CLI
constructor
A new instance of CLI.
-
#run(argv) ⇒ Integer
Process exit status.
Constructor Details
#initialize(out: $stdout, err: $stderr, input: $stdin, transport_factory: nil) ⇒ CLI
Returns a new instance of CLI.
75 76 77 78 79 80 |
# File 'lib/mt/wall/cli.rb', line 75 def initialize(out: $stdout, err: $stderr, input: $stdin, transport_factory: nil) @out = out @err = err @input = input @transport_factory = transport_factory || method(:build_transport) end |
Class Method Details
.start(argv = ARGV) ⇒ Integer
Returns process exit status.
64 65 66 |
# File 'lib/mt/wall/cli.rb', line 64 def self.start(argv = ARGV) new.run(argv) end |
Instance Method Details
#run(argv) ⇒ Integer
Returns process exit status.
83 84 85 86 87 88 89 |
# File 'lib/mt/wall/cli.rb', line 83 def run(argv) dispatch(argv.dup) rescue ConfigurationError, TransportError, PlanError, OptionParser::ParseError => e # Known, user-facing failures: a concise message, never a backtrace. @err.puts("Error: #{e.}") EXIT_ERROR end |