vxlan 0.4.0 → 0.4.2
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/CHANGELOG.md +17 -4
- data/README.md +3 -1
- data/bin/README.md +4 -0
- data/docs/superpowers/plans/2026-10-22-ctx-cli.md +138 -0
- data/docs/superpowers/specs/2026-10-22-ctx-cli-design.md +123 -0
- data/lib/vxlan/change_plan.rb +1 -8
- data/lib/vxlan/cisco_nxos/parsers/show_bgp_l2vpn_evpn_summary.rb +2 -2
- data/lib/vxlan/cisco_nxos/parsers/show_interface_brief.rb +1 -1
- data/lib/vxlan/cisco_nxos/parsers/show_port_channel_summary.rb +1 -1
- data/lib/vxlan/cisco_nxos/parsers/show_running_config.rb +2 -2
- data/lib/vxlan/cisco_nxos/syntax/policies.rb +1 -1
- data/lib/vxlan/cisco_nxos/syntax/routing.rb +1 -1
- data/lib/vxlan/cli/apply.rb +10 -7
- data/lib/vxlan/cli/collect.rb +60 -125
- data/lib/vxlan/cli/options.rb +28 -42
- data/lib/vxlan/cli/parse.rb +13 -15
- data/lib/vxlan/cli/report.rb +3 -3
- data/lib/vxlan/cli/review/fabric.rb +4 -2
- data/lib/vxlan/cli/review/report.rb +3 -2
- data/lib/vxlan/cli/review.rb +30 -61
- data/lib/vxlan/cli.rb +27 -31
- data/lib/vxlan/collection_plan.rb +1 -1
- data/lib/vxlan/fabric/review.rb +1 -1
- data/lib/vxlan/version.rb +1 -1
- metadata +19 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d262e92c5f60d01b4acfbe457e3c8b6466354f97414e14f9eff3e7cff2472519
|
|
4
|
+
data.tar.gz: 888b2ac2fac38db10ff2b0511861d46f007ccdf47ef98528c4b431734729439a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 13cf4f4d999d82c923f0ae52143c271721ab23cdc24af24fef2bddfcac0f7f8b3517ad1686186b4961814cfbda65cd09e7ab50ceaee044fd4c71a6b8ccd17fa7
|
|
7
|
+
data.tar.gz: 7a63e8abd6569a3fc2de95089c42644f2a883d14fe4198f1c14eaa7a376ce14c213433da7950d7911e833a787f3fcda58f364c6ebdd68b9153088a62ba379d26
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
Changes to the public contract are recorded here. Versions follow Semantic Versioning.
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## 0.4.2 (2026-10-23)
|
|
8
|
+
|
|
9
|
+
- Migrate shared CLI entrypoints to ctx_cli 0.2.0 names without legacy aliases.
|
|
10
|
+
- Delegate offline review entrypoint orchestration to ctx_cli and bound external evidence, plan, checksum and Fabric policy reads.
|
|
11
|
+
- Share offline evidence validation and JSON conversion with Runner; reject missing snapshot target identities.
|
|
12
|
+
- Use explicit field separators and align CLI dependency floors with shared inventory support.
|
|
13
|
+
- Delegate shared command dispatch, option groups, initialization, terminal confirmation, offline IO and collection entrypoint flow to ctx_cli; retain domain and Runner responsibilities.
|
|
14
|
+
|
|
15
|
+
## 0.4.1 (2026-10-22)
|
|
16
|
+
|
|
17
|
+
- Delegate command dispatch, common options, initialization, terminal interaction, offline IO and collection entrypoint orchestration to ctx_cli 0.1.0.
|
|
18
|
+
- Keep domain policies, device capabilities and ctx_runner completion semantics in their existing layers.
|
|
19
|
+
|
|
20
|
+
- Delegate batch completion and cancellation/failure precedence to CtxRunner::Batch, keeping domain review and CLI presentation explicit.
|
|
21
|
+
|
|
5
22
|
## 0.4.0 (2026-10-22)
|
|
6
23
|
|
|
7
24
|
- Delegate batch completion and cancellation/failure precedence to CtxRunner::Batch, keeping domain review and CLI presentation explicit.
|
|
@@ -12,10 +29,6 @@ Changes to the public contract are recorded here. Versions follow Semantic Versi
|
|
|
12
29
|
- Delegate shared collection, evidence and execution contracts to ctx_runner.
|
|
13
30
|
- Preserve domain parsing, change policies, CLI layouts and connection ownership.
|
|
14
31
|
|
|
15
|
-
## Unreleased
|
|
16
|
-
|
|
17
|
-
- Delegate batch completion and cancellation/failure precedence to CtxRunner::Batch, keeping domain review and CLI presentation explicit.
|
|
18
|
-
|
|
19
32
|
## 0.3.1 (2026-10-21)
|
|
20
33
|
|
|
21
34
|
- Index Fabric address-group evidence by referenced object, preserving host order and missing dependencies without repeatedly searching every host's reference list.
|
data/README.md
CHANGED
|
@@ -59,7 +59,7 @@ The gem installs `vxlan`; its implementation lives in `lib/vxlan/cli/`. The scri
|
|
|
59
59
|
```sh
|
|
60
60
|
gem install vxlan
|
|
61
61
|
# Optional dependencies for live collection and .env files:
|
|
62
|
-
gem install net-connector -v '~> 0.
|
|
62
|
+
gem install net-connector -v '~> 0.17.1'
|
|
63
63
|
vxlan --help
|
|
64
64
|
vxlan collect --init --non-interactive
|
|
65
65
|
vxlan collect --inventory-only
|
|
@@ -136,3 +136,5 @@ MIT. See [LICENSE](LICENSE).
|
|
|
136
136
|
`vxlan collect` 默认输出逐设备诊断,使用 `--scripts` 可选导出配置建议;`vxlan review --batch DIR` 可离线补生成既有报告的候选配置、条件回退和只读验收命令。导出不会执行变更;独立 `apply --plan FILE --item ID` 必须在真实终端明确确认,配置漂移或失败即停止。详见[修复建议说明](docs/remediation.md)。 业务分层、会话所有权与执行边界见[架构说明](docs/architecture-zh.md)。
|
|
137
137
|
|
|
138
138
|
Review output follows the net-connector topology layout: `summary.txt`, `summary.json`, `devices/*.txt`, optional `scripts/*.cfg`, and a checksummed `plan.json`. Generated reports contain no Markdown. Select exactly one change with `vxlan apply --plan plan.json --item ID`; interactive confirmation remains mandatory.
|
|
139
|
+
|
|
140
|
+
Offline review requires `snapshot.target.host` to match the canonical device host. Reports without target identity must be collected again; the unbound legacy format is no longer accepted.
|
data/bin/README.md
CHANGED
|
@@ -213,3 +213,7 @@ vxlan collect --hosts 192.0.2.0/24 --name edge --exclude-name spare --model 'S68
|
|
|
213
213
|
IP 支持单地址、CIDR、范围;名称及型号支持 contains(默认)、prefix、glob,不区分大小写。`--vendor`/`--exclude-vendor` 使用连接器平台标识(如 cisco_nxos、h3c、h3c_wireless、huawei),不是原始厂商标签。同字段条件为 OR,跨字段为 AND,排除优先。缺失型号不命中包含规则。`--model`/`--exclude-model`、`--name-match`/`--model-match` 可组合;筛选只选择已有清单,不扫描地址、不扩大平台支持范围。
|
|
214
214
|
|
|
215
215
|
YAML 顶层对应 hosts/exclude_hosts、names/exclude_names、vendors/exclude_vendors、models/exclude_models、name_match/model_match。Netdisco inventory 段使用 include_hosts/include_names/include_vendors/include_models 及对应 exclude 字段。
|
|
216
|
+
|
|
217
|
+
## ctx_cli 公共入口
|
|
218
|
+
|
|
219
|
+
分发、公共选项、配置初始化、离线输入输出、终端确认和采集入口由 ctx_cli 组合提供;领域规则与 ctx_runner 业务状态保持各自职责。`CTX_CLI_PATH=../ctx_cli bundle exec rake` 用于源码联调;普通入口先安装 ctx_cli 候选包。
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# ctx_cli Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** Use executing-plans to implement this plan task-by-task. Preserve existing uncommitted changes; no commits or publication are authorized.
|
|
4
|
+
|
|
5
|
+
**Goal:** Extract shared CLI responsibilities into ctx_cli and migrate existing consumers without adding a baseline command.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Small Ruby objects composed by domain adapters. ctx_cli has no dependency on net-connector or ctx_runner; existing connector configuration policies and Runner business processes remain their owners' responsibilities.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Ruby >= 3.4, OptionParser, YAML, dotenv, RSpec, RuboCop Omakase. Development Ruby 4.0.6.
|
|
10
|
+
|
|
11
|
+
**Spec:** ../specs/2026-10-22-ctx-cli-design.md
|
|
12
|
+
|
|
13
|
+
## Global Constraints
|
|
14
|
+
|
|
15
|
+
- Preserve current CLI contracts, configuration discovery, precedence and source-relative paths.
|
|
16
|
+
- No new baseline executable; coverage.rb is the existing script integration.
|
|
17
|
+
- No automatic network I/O, ENV mutation, input consumption or directory creation on require.
|
|
18
|
+
- Preserve vendor parser names/layout, unrelated WIP, and existing ctx_runner/Inventory work.
|
|
19
|
+
- Chinese code comments, English RSpec/Changelog, explicit require and package allowlist.
|
|
20
|
+
- Keep net-connector Ruby >= 3.4; no dependency cycle or implicit sibling checkout loading.
|
|
21
|
+
|
|
22
|
+
## Review Focus
|
|
23
|
+
|
|
24
|
+
- Reused CLI objects must start a fresh batch and leave previous reports intact after preflight failure.
|
|
25
|
+
- Output or directory-sync failure after an external effect must not turn into success or replay.
|
|
26
|
+
- Missing/false/nil and overridden invalid values must retain existing configuration semantics.
|
|
27
|
+
- Non-TTY input and caller-owned IO must not be consumed/closed by help or preview.
|
|
28
|
+
- Installed packages must exercise actual candidate dependencies rather than workspace load paths.
|
|
29
|
+
|
|
30
|
+
### Task 1: Configuration and initialization
|
|
31
|
+
|
|
32
|
+
**Files:** Create ctx_cli gem engineering files; lib/ctx_cli/{version,configuration,initialization}.rb; spec/{configuration,initialization}_spec.rb. Modify net-connector-trunk/lib/net/connector/config.rb and netdisco/config/initializer.rb; Gemfile/gemspec.
|
|
33
|
+
|
|
34
|
+
**Interfaces:** Configuration.new(name:, config_env:, namespace:, names:, common_keys:, **existing_discovery_keywords), #load_environment, #load, #sources and existing Config readers; .merge/.copy/.freeze_tree/.dump. Initialization.new(prefix:).create(path:, contents:) returns :created/:exists and rejects nonregular existing targets.
|
|
35
|
+
|
|
36
|
+
- [x] Add generic-policy configuration tests, run RED for missing ctx_cli, implement extracted source reader with explicit host policy.
|
|
37
|
+
- [x] Add private-mode/no-overwrite/symlink/sync-failure initialization tests, implement existing durable publisher once.
|
|
38
|
+
- [x] Replace connector Config with policy adapter and initializer publisher with delegation; existing config and backup tests stay green.
|
|
39
|
+
|
|
40
|
+
### Task 2: Command, terminal, input/output and application
|
|
41
|
+
|
|
42
|
+
**Files:** Create lib/ctx_cli/{application,command,options,terminal,input,output}.rb and focused specs/examples.
|
|
43
|
+
|
|
44
|
+
**Interfaces:** Application.new(name:, version:, usage:, commands:, out:, error:).run(argv); Command.new(banner:, defaults:, out:) { |parser, values| ... }.parse(argv) and #informational?(examples:, details:); Options group registration; Terminal.new(input:, out:).tty?/#confirm(token:, prompt:)/#question(prompt)/#password(label:); Input.read(path:, input:); Output.new(out:, error:).json/.diagnostic.
|
|
45
|
+
|
|
46
|
+
- [x] Pin lazy help/version, no argv mutation, no IO ownership, exact confirmation, safe diagnostic and stdout failure behavior before implementing.
|
|
47
|
+
- [x] Keep the Command API simple: construct parser/value snapshot, configure through a block, parse through #parse, informational? short-circuit; domain execution and error policy remain explicit.
|
|
48
|
+
|
|
49
|
+
### Task 3: Existing terminal entrypoints
|
|
50
|
+
|
|
51
|
+
**Files:** VXLAN/Wireless cli.rb and cli/{options,parse,apply}.rb; backup CLI options/setup and config/initializer; baseline/script/coverage.rb; consumer Gemfiles/gemspecs.
|
|
52
|
+
|
|
53
|
+
**Interfaces:** Consume Tasks 1–2; preserve public constructor/run signatures.
|
|
54
|
+
|
|
55
|
+
- [x] Register shared options once; replace initialization and interaction copies; keep option descriptions and domain validation in host where necessary.
|
|
56
|
+
- [x] Share parse input/output and informational flow; retain domain dimension/platform dispatch.
|
|
57
|
+
- [x] Share apply terminal gate and exact confirmation; retain plan shape, hash, item and operation lease differences.
|
|
58
|
+
- [x] Move coverage script argument/output boundary to Command, keeping []/--check behavior and document bytes.
|
|
59
|
+
- [x] Run existing CLI suites and actual checkout help/examples; only add regression tests for uncovered changed boundaries.
|
|
60
|
+
|
|
61
|
+
### Task 4: Collection orchestration
|
|
62
|
+
|
|
63
|
+
**Files:** Create ctx_cli/lib/ctx_cli/collection.rb; migrate VXLAN/Wireless cli/collect.rb.
|
|
64
|
+
|
|
65
|
+
**Interfaces:** Collection.new(adapter:, options:, progress:, batch:, label:, report_error:, failure_code:, out:, error:, input:).run(argv); adapter implements inventory, prepare, report, execute, collect and after_collect. options/progress are callable factories; batch implements the current Runner Batch#run/Completion protocol. No runner/connector require in ctx_cli.
|
|
66
|
+
|
|
67
|
+
- [x] Use existing consumer tests for fresh state, preflight, empty targets, failure isolation, interruption, thread cleanup and report failures as characterization gates.
|
|
68
|
+
- [x] Move shared run/finish/output flow once, keep adapters responsible for inventory, credentials, network/resources and domain snapshots.
|
|
69
|
+
- [x] Ensure factories remain injectable and both ordinary and PTY regression tests pass.
|
|
70
|
+
|
|
71
|
+
### Task 5: Engineering and package integration
|
|
72
|
+
|
|
73
|
+
**Files:** ctx_cli/{README,AGENTS,CHANGELOG,Rakefile,.github/workflows,script/verify_package.rb,examples}; all touched consumer docs and package verifiers.
|
|
74
|
+
|
|
75
|
+
- [x] Add explicit CTX_CLI_PATH development override, candidate-package arguments and private installation checks; never auto-discover sibling code.
|
|
76
|
+
- [x] Add offline examples and smoke entrypoints, isolate loaded package paths and verify metadata/dependencies.
|
|
77
|
+
- [x] Mirror ctx_parser conventions with Ruby 3.4/4.0.6 matrix, explicit files and no remote release action.
|
|
78
|
+
|
|
79
|
+
### Task 6: Verify and report
|
|
80
|
+
|
|
81
|
+
- [x] Run ctx_cli rake/build/package verification and available Ruby matrix locally.
|
|
82
|
+
- [x] Run VXLAN/Wireless complete rake and consumer package checks; net-connector script/ci; baseline rake with original missing-script failures explicitly recorded.
|
|
83
|
+
- [x] Self-review cross-gem dependency, resource ownership, output and initialization failures; fix concrete findings and rerun affected gates.
|
|
84
|
+
- [x] Record migration size, exact verification results, unchanged prior failures and remaining unverified boundaries.
|
|
85
|
+
|
|
86
|
+
## Execution ledger
|
|
87
|
+
|
|
88
|
+
- Ruling: user continuation authorizes execution of the already described extraction; no extra approval cycle. Execute inline because the design-check subagent failed on workspace credits.
|
|
89
|
+
- Ruling: work in actual checkouts, preserving existing WIP, because current ctx_runner/Inventory changes are required inputs and checkout entrypoints must be verified. No reset/stash/branch switch/commit.
|
|
90
|
+
- Ruling: Command is a small parser object (#parse/#informational?) rather than a configurable rescue DSL; callers retain their current exit policy.
|
|
91
|
+
- Baseline before changes: VXLAN 128 CLI examples green, Wireless 108 green, connector 45 tests/476 assertions green; baseline coverage 33 metrics/8 platforms current; 4 existing backup replay spec failures from missing script.
|
|
92
|
+
- Preflight: Tasks 3–4 consume only explicitly injected components from Tasks 1–2. Runner Batch/Report and Inventory Filters remain existing collaborators, avoiding a connector → ctx_cli → connector cycle.
|
|
93
|
+
|
|
94
|
+
- Task 1: complete — generic configuration/initialization 7 examples green; connector original 45 tests/476 assertions green.
|
|
95
|
+
- Task 2: complete — command/terminal tests including standalone namespace regression: 14 examples green.
|
|
96
|
+
- Ruling: current Runner already exposes Batch#run/Completion; Collection delegates all finalization to that API and only maps terminal diagnostics/exit codes. Preserve the newer workspace implementation.
|
|
97
|
+
|
|
98
|
+
- Tasks 3–5: complete — all four consumers use the shared capabilities. baseline has no new command or runtime gem dependency. Candidate package arguments and explicit source overrides are documented.
|
|
99
|
+
- Task 6: complete for the authorized local scope — exact local evidence and existing failures are below. No commits, push, remote repository, CI run or release performed.
|
|
100
|
+
|
|
101
|
+
## Final local verification (2026-10-22)
|
|
102
|
+
|
|
103
|
+
Environment: macOS arm64, Ruby 4.0.6, Bundler 4.0.20. Ruby 3.4 is configured in CI but unavailable locally; the remote matrix has not run. All network-device evidence is synthetic/offline or local PTY.
|
|
104
|
+
|
|
105
|
+
| Check | Result |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| ctx_cli `bundle exec rake` | 20 examples, 0 failures; 25 Ruby files lint-clean; both offline examples pass |
|
|
108
|
+
| ctx_cli build / independent install | Candidate 0.1.0 built; plain Ruby and minimal Bundler app pass in independent GEM_HOME/GEM_PATH; root and each capability load without host libraries |
|
|
109
|
+
| ctx_cli workflow lint | actionlint passes for CI/release workflows; no workflow executed remotely |
|
|
110
|
+
| VXLAN `bundle exec rake` | 455 examples, 0 failures; lint and examples pass |
|
|
111
|
+
| Wireless `bundle exec rake` | Latest full run: 317 examples, 0 failures; lint and examples pass (earlier workspace snapshot had 318; unrelated tests changed concurrently) |
|
|
112
|
+
| net-connector `bash script/ci` | 1232 tests, 12503 assertions, 0 failures/errors/skips; source/history/package scan, lint/actionlint, coverage comparison, benchmark smoke, build and installed plain/Bundler PTY smoke pass |
|
|
113
|
+
| Final connector configuration regression | 10 tests, 180 assertions, 0 failures/errors/skips after selector snapshot hardening |
|
|
114
|
+
| baseline full rake | 1330 examples, 4 failures, all in pre-existing backup_verification_spec.rb because script/verify_backups.rb is absent |
|
|
115
|
+
| baseline remaining gates | 241 Ruby files lint-clean; all existing examples complete; coverage current at 33 metrics / 8 platforms |
|
|
116
|
+
| baseline changed script | Coverage CLI regression passes; ordinary `ruby script/coverage.rb --check` and Bundler invocation pass; redundant load-path-dependent require removed |
|
|
117
|
+
| Consumer package checks | VXLAN/Wireless install explicit ctx_cli, ctx_runner, connector and expect candidate gems; connector installs exact ctx_cli candidate; candidate CLI files compared byte-for-byte; all pass |
|
|
118
|
+
| Actual checkout entrypoints | Without CTX_CLI_PATH/RUBYLIB: VXLAN/Wireless help, apply help, unknown command status, JSON inventory and stdin parse pass; backup help/init/show-config pass from its actual examples directory |
|
|
119
|
+
|
|
120
|
+
Configuration, initialization and collection checks cover precedence, false/nil, source paths, YAML/.env rejection, IO ownership, preflight before reports, preview without credentials, cancellation and post-publication faults. Existing consumer suites supply real Runner/connector integration coverage. New tests cover standalone namespace loading, opaque/cyclic data rejection and caller mutation of environment selector/path keys. The selector mutation was reproduced red before the copy/freeze fix. Parallel defaults/help remain host policy through `parallel_help:`.
|
|
121
|
+
|
|
122
|
+
The original backup checkout-root `.env` still contains obsolete `NC_CONCURRENCY`; invoking backup show-config from that root returns the existing validation error. The private file was not modified. Running the actual example entrypoint from its examples directory and isolated installed-package checks passes. This is a local configuration limitation, not a relaxed validator.
|
|
123
|
+
|
|
124
|
+
All previous work was preserved. Additional unrelated domain/report/test changes appeared during execution and were left intact. The initial receipt is `/var/folders/1w/b2h7_3sn6733tshd4w6_vvnc0000gn/T/ctx-cli-before-prquajq5`; the latest package checks use explicit artifacts, not adjacent source discovery. Local ignored lockfiles were resolved back to installed gems after source integration checks.
|
|
125
|
+
|
|
126
|
+
## Extraction size
|
|
127
|
+
|
|
128
|
+
Compared against the pre-extraction receipt, counting only the migrated consumer source files (not all existing repository diffs):
|
|
129
|
+
|
|
130
|
+
| Consumer | Before | After | Removed |
|
|
131
|
+
| --- | ---: | ---: | ---: |
|
|
132
|
+
| VXLAN cli.rb + collect/options/parse/apply | 746 | 652 | 94 |
|
|
133
|
+
| Wireless same entrypoints | 788 | 695 | 93 |
|
|
134
|
+
| Connector Config + initializer + options/setup | 968 | 574 | 394 |
|
|
135
|
+
| baseline existing coverage script | 50 | 64 | -14 |
|
|
136
|
+
| Total | 2552 | 1985 | 567 |
|
|
137
|
+
|
|
138
|
+
This measures reduced consumer boilerplate, not total repository size. The new shared gem, tests, documentation and engineering scripts are additional code. Device protocol/command parsers, inventory selection and Runner state machines were not copied into ctx_cli.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# ctx_cli 公共命令行能力抽取设计
|
|
2
|
+
|
|
3
|
+
日期:2026-10-22。状态:本地实现与验证完成;实际接口见 ctx_cli/README.md,验证结果及原有缺口见实施计划。
|
|
4
|
+
|
|
5
|
+
## 目标与已确认范围
|
|
6
|
+
|
|
7
|
+
用户希望把 vxlan/lib/vxlan/cli 一类宿主入口中的公共能力抽到独立 ctx_cli,减少 baseline、vxlan、backup、wireless 的样板代码,代码范式与工程规范参照 ctx_parser。
|
|
8
|
+
|
|
9
|
+
用户已明确:baseline 只迁移现有脚本的公共逻辑,暂不增加 baseline 命令。此次不新增设备能力,不创建远程仓库,不提交、推送或发布。
|
|
10
|
+
|
|
11
|
+
成功标准是公共行为有一个实现,消费模块保留必要的领域声明和适配;既有命令、参数、配置优先级、报告语义及错误退出行为保持可验证。不能只建一个无人使用的工具库,也不能以统一命名为理由改厂商解析器。
|
|
12
|
+
|
|
13
|
+
## 当前依据
|
|
14
|
+
|
|
15
|
+
| 位置 | 已有职责及共性 |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| vxlan/lib/vxlan/cli.rb、wireless/lib/wireless/cli.rb | 懒加载分发、帮助、版本、参数错误、注入标准流 |
|
|
18
|
+
| 两个模块的 cli/options.rb | 文件发现、公开环境映射、默认值合并、公共参数、初始化、终端检查、领域校验 |
|
|
19
|
+
| 两个模块的 cli/parse.rb | 参数解析、帮助/示例、文件或 stdin、元数据/JSON 输出、完整性退出码 |
|
|
20
|
+
| 两个模块的 cli/collect.rb | 初始化和预览分支、全批预检、进度、调度、Runner 批次交付、失败和取消收尾 |
|
|
21
|
+
| 两个模块的 cli/apply.rb | 终端要求、精确确认及输出相同;计划格式、选择、校验、命令与会话租约不同 |
|
|
22
|
+
| net-connector-trunk/lib/net/connector/config.rb | 四类入口共用的配置发现、YAML/.env 安全读取、路径来源、配置快照 |
|
|
23
|
+
| net-connector-trunk/lib/net/connector/netdisco/cli/{options,setup}.rb | backup/TFTP/topology 公共选项、终端交互、初始化策略 |
|
|
24
|
+
| net-connector-trunk/lib/net/connector/netdisco/config/initializer.rb | 排他创建、私有权限、文件和目录同步,以及备份专有问答 |
|
|
25
|
+
| baseline/script/coverage.rb | 已有参数分支、输出和退出边界;矩阵生成属于 baseline |
|
|
26
|
+
| baseline/examples/*.rb | 大多直接演示领域 API,基本没有 CLI 框架代码,不能强行包装 |
|
|
27
|
+
|
|
28
|
+
设计开始时 ctx_runner 已有实现,承接 Collection/Query/Observation/Batch/Report/Execution;本次在它的现有契约上接入。net-connector-trunk 另有清单筛选未提交改动,Inventory::Selection/Filters 继续是唯一筛选实现。所有这些工作均保留,不回滚、不整体覆盖。
|
|
29
|
+
|
|
30
|
+
baseline/spec/backup_verification_spec.rb 是已有未跟踪测试,但对应 script/verify_backups.rb 当前不存在。它是实施前已存在的独立缺口,不以本次抽取名义补建备份回放产品,也不能把该仓库全套测试称为通过。
|
|
31
|
+
|
|
32
|
+
实施前已在各实际 checkout、Ruby 4.0.6、当前锁定/安装依赖下验证:VXLAN 的 cli_spec.rb + spec/cli 为 128 examples / 0 failures,Wireless 同范围为 108 / 0;net-connector 的 cli_backup、cli_setup、config_initializer、cli_config 为 45 tests / 476 assertions / 0 failures;baseline coverage --check 为 33 metrics / 8 platforms 且内容最新。baseline 的备份回放 spec 为 4 failures,根因仍是上述脚本缺失。这些是修改前基线,不是 ctx_cli 实现后的验证结果。
|
|
33
|
+
|
|
34
|
+
## 方案选择
|
|
35
|
+
|
|
36
|
+
采用独立小型 gem 加明确对象组合:CtxCli 命名空间、显式 require、构造参数注入、普通 OptionParser 扩展块;公共流程只有一个实现,领域策略作为协作者传入。
|
|
37
|
+
|
|
38
|
+
不采用复制模板作为主要复用方式:它会继续复制错误修复。不采用一个包含所有业务模式的万能 CLI 基类或工作流 DSL:它会让 backup 的成功策略、无线 AP 租约和 VXLAN Fabric 规则变成大量隐式开关。
|
|
39
|
+
|
|
40
|
+
工程以 ctx_parser 为参照:目录映射命名空间、中文代码注释、英文 RSpec/Changelog、RuboCop Omakase、显式打包清单、离线 examples、独立安装验证、固定 action 提交及发布前验证。明确差异是 ctx_cli 核心最低 Ruby 3.4,开发 Ruby 4.0.6,CI 覆盖两者;这是为了保持 net-connector 已有 Ruby 3.4 契约,而不是提高其最低版本。ctx_cli 不依赖 ctx_parser/ctx_runner,避免把它们的 Ruby 4.0.6 门槛传给 backup。
|
|
41
|
+
|
|
42
|
+
## 依赖和职责边界
|
|
43
|
+
|
|
44
|
+
- ctx_cli 只依赖自己直接使用的标准库 gem 和 dotenv。require 不读取配置、不修改 ENV、不消费 stdin、不建目录、不加载设备驱动或 Rails。
|
|
45
|
+
- net-connector 依赖 ctx_cli 的宿主配置和终端能力;ctx_cli 不反向依赖 net-connector,避免循环。
|
|
46
|
+
- VXLAN/Wireless 显式依赖 ctx_cli;领域核心 require 不加载 CLI,帮助与离线解析不加载网络传输。
|
|
47
|
+
- ctx_runner 保留采集、报告检查点、完成判定与执行记账。ctx_cli 仅编排终端入口;Runner/进度/调度器通过协作者注入。
|
|
48
|
+
- Inventory::Selection/Filters 保留在 net-connector;不在 ctx_cli 再实现地址、厂商、名称或型号选择。
|
|
49
|
+
- baseline 只在现有脚本的宿主入口使用 ctx_cli,核心 Baseline API 不依赖 CLI 行为。若只用于开发脚本,依赖放 Gemfile;不凭空增加核心运行时依赖。
|
|
50
|
+
|
|
51
|
+
## 公共能力和契约
|
|
52
|
+
|
|
53
|
+
### Application 与 Command
|
|
54
|
+
|
|
55
|
+
Application 负责命令分发、全局帮助和版本,命令通过惰性 callable 加载。返回退出码,不调用 exit;标准流与 argv 归调用方所有。入口只声明名称、版本、帮助正文和各子命令工厂。
|
|
56
|
+
|
|
57
|
+
Command 负责每次解析的新参数快照、OptionParser 调用及帮助/示例短路。构造块接收 parser 和 values,入口在其中追加领域参数;#parse 返回值容器,#informational? 处理信息分支。领域执行与错误退出码留在宿主,不通过继承搜索隐式 hook。
|
|
58
|
+
|
|
59
|
+
公共参数分组采用普通方法向 OptionParser 注册配置路径、并发、初始化、交互、JSON/进度、帮助等选项。字段名和选项说明可以显式注入。厂商、Fabric、AP、TFTP 和成功策略仍由宿主登记。列表按明确逗号分隔,拒绝空项,不依赖 Ruby 全局分隔符。
|
|
60
|
+
|
|
61
|
+
### Configuration
|
|
62
|
+
|
|
63
|
+
从当前 Net::Connector::Config 迁入通用文件加载实现。名称、配置环境键、共享文件名/目录、允许的共享命名空间与字段、路径字段及特殊字面量均由宿主显式给定;公共库不硬编码 vxlan、wireless、backup、topology 的业务字段。
|
|
64
|
+
|
|
65
|
+
保持 CLI > 进程环境 > YAML > .env > 默认值的有效优先级。文件读取与工具字段转换分开;领域 Options 保留 schema、环境编码和最终校验。数组整层替换,false/nil 与缺失分开;被覆盖的低优先级坏值不提前误报。YAML/.env 相对路径按各自来源解析,命令行路径按启动目录解析。显式文件缺失不能回退。保留来源路径与字段归属,不在 sources 中展示秘密。
|
|
66
|
+
|
|
67
|
+
保持批次快照、不修改 ENV、不冻结调用方输入、拒绝 YAML 别名/重复键/多文档/.env 命令替换等现有约束。Net::Connector::Config 保留原入口和配置政策作为薄适配,不保留第二份文件加载实现。既有 net-connector.yml、环境变量和默认搜索位置不改名。
|
|
68
|
+
|
|
69
|
+
### Initialization 与 Terminal
|
|
70
|
+
|
|
71
|
+
Initialization 只负责发布调用方已经校验的公开配置或模板:目录 0700、文件 0600,先写完并同步临时文件,再排他发布并同步父目录;不覆盖已有文件。普通已有文件、符号链接、目录、竞争创建、取消及发布后同步失败分别处理。发布后的持久性未确认不能返回成功;清理故障不能掩盖原始故障。
|
|
72
|
+
|
|
73
|
+
备份的逐字段问答和策略验证留在 net-connector 的 Initializer,底层文件发布委托给公共实现。VXLAN/Wireless 的初始化也使用同一实现;仍然在初始化后退出,不读取远端清单或连接设备,不把当前凭据保存进模板。
|
|
74
|
+
|
|
75
|
+
Terminal 封装真实终端检查、逐行读取、普通问答、隐藏密码和精确 token 确认;不拥有或关闭注入的 IO。默认自动化不读 stdin;backup 的 stdin-credentials 协议继续独占输入。apply 必须检查原有要求的全部终端流,并比较宿主提供的完整 token,不添加 --yes、不截断 token。
|
|
76
|
+
|
|
77
|
+
### Input 与 Output
|
|
78
|
+
|
|
79
|
+
Input 统一显式文件或调用方 stdin 的读取,仅关闭自行打开的文件。Output 提供显式 JSON 与文本输出及安全诊断;不推断任意对象的敏感性,不把异常 message/cause 自动串入输出,不把业务结果成功与输出成功混为一谈。
|
|
80
|
+
|
|
81
|
+
VXLAN/Wireless Parse 使用 Command/Input/Output;维度校验、配置/运行解析分支、平台与 AP 参数、健康说明仍在领域模块。baseline 的 coverage 脚本复用参数与输出边界,生成内容、--check、原退出码及默认写入目标保持一致;不把领域示例里的单句 puts 全部替换为无价值包装。
|
|
82
|
+
|
|
83
|
+
### Collection 入口编排
|
|
84
|
+
|
|
85
|
+
公共 Collection 承接 VXLAN/Wireless 已重复的入口顺序与失败收尾,但不实现 Runner 或连接器。它显式接收 adapter、options/progress 工厂、batch 类和标准流。Batch#run/Completion 负责业务收尾;CLI 只映射诊断和退出码。每次 run 创建独立状态,失败不能改写上次批次。
|
|
86
|
+
|
|
87
|
+
adapter 的协议为:
|
|
88
|
+
|
|
89
|
+
- inventory(options, progress:):返回 targets 和筛选前 total;不读取设备凭据。
|
|
90
|
+
- prepare(targets, options):预检全批凭据、端点与资源,返回仅本批使用的上下文;失败发生在报告创建和设备连接之前。
|
|
91
|
+
- report(options):创建领域报告;公共流程据此构造注入的 Runner Batch。
|
|
92
|
+
- execute(targets, options) { |target| ... }:使用注入调度器或现有连接器 Pool;返回前必须回收工作线程。
|
|
93
|
+
- collect(target, options, context:, progress:):返回领域 snapshot;每设备会话及 AP/Fabric 等策略仍属于领域。
|
|
94
|
+
- after_collect(report, options):明确的收尾接口;VXLAN 在这里执行现有 Fabric 汇总,Wireless 使用空实现。
|
|
95
|
+
|
|
96
|
+
options 工厂构造当前领域 Options;Options 暴露现有 informational?/validate_interaction!/load_environment/initialize_files/missing?/load/config/flags/values/sources/public_values 协议。
|
|
97
|
+
|
|
98
|
+
公共流程是:解析和信息短路 → 文件初始化/加载 → 公开配置或清单预览 → 空清单结束 → 全批预检 → 创建报告 → 调度采集并交付 Batch → 领域汇总 → Batch 收尾 → 输出。错误分类、取消优先级、已完成证据保留和摘要恢复行为以现有消费测试为准。无法保证已回收工作线程的调度器不能使用该协议。
|
|
99
|
+
|
|
100
|
+
backup/TFTP/topology 不强行接入此采集流程:其 Planner、BackupRun、成功策略、TFTP 回执和归档继续由 net-connector 负责;它们复用配置、选项、交互和初始化能力。apply 只复用终端/参数/展示组件,计划模式、哈希文件、单项选择、ChangePlan 验证与操作租约不移动。
|
|
101
|
+
|
|
102
|
+
## 实施顺序
|
|
103
|
+
|
|
104
|
+
1. 保存各仓库初始差异清单,跑现有定向契约,记录既有失败;建立 ctx_cli 的工程、公开边界测试和离线例子。
|
|
105
|
+
2. 迁移通用配置读取与安全初始化,保留 net-connector 的旧入口适配;先运行其配置、初始化及 backup CLI 测试。
|
|
106
|
+
3. 抽取参数、终端、输入输出和分发;接入 VXLAN/Wireless parse/options/apply,以及 backup/topology 的相应公共片段。
|
|
107
|
+
4. 抽取 VXLAN/Wireless Collection 的入口流程,保留领域适配,并使用既有失败、取消、并发和 PTY 回归验证。
|
|
108
|
+
5. baseline 只调整 coverage 脚本宿主边界;检查生成的 metric-coverage.md 字节不变及原退出行为。
|
|
109
|
+
6. 更新 README、AGENTS、Unreleased、Gemfile/gemspec、候选包校验与联调入口;实际 checkout 和隔离安装分别验证。
|
|
110
|
+
|
|
111
|
+
源码联调使用显式 CTX_CLI_PATH(沿用现有 CTX_RUNNER_PATH 约定),不自动把相邻源码加入加载路径。不改生产代码偷偷探测 ../ctx_cli。未发布版本先构建并安装候选包;隔离安装脚本显式接受候选 ctx_cli/ctx_runner 包,不假设公共索引已有它们。
|
|
112
|
+
|
|
113
|
+
## 验收与完成边界
|
|
114
|
+
|
|
115
|
+
- ctx_cli:RSpec、RuboCop、离线 examples、构建、隔离安装、Ruby 3.4/4.0.6 的可用本地检查;远程 CI 未实际运行时只交付配置,不称 CI 通过。
|
|
116
|
+
- 配置:各层覆盖、静态/动态清单优先级、来源路径、空 selector、未知字段、凭据隔离、可变输入和污染的 Ruby 全局分隔符。
|
|
117
|
+
- 初始化/终端:帮助零副作用、非 TTY 不消费输入、现有文件不覆盖、竞争/符号链接、私有权限、目录同步失败、精确确认与取消。
|
|
118
|
+
- 采集:预检先于副作用、预览不需要凭据、无目标非成功、单设备失败隔离、重复/零次会话回调、线程回收、报告/输出失败、取消优先级和重复运行状态隔离。
|
|
119
|
+
- 消费者:VXLAN/Wireless 完整 rake;net-connector script/ci;baseline 现有测试与 coverage --check,已有缺失回放脚本的失败单独报告;不得跳过后把全套称为通过。
|
|
120
|
+
- 打包:直接从当前 checkout 运行现有 bin/examples;独立 GEM_HOME/GEM_PATH 安装候选包,清理 Bundler/RUBYLIB 影响,确认加载来源与文件清单。
|
|
121
|
+
- 完成说明提供抽出能力、各消费者实际接入点、样板代码减少的前后差异、执行的验证和未验证边界。不声称真实设备效果,不发布版本。
|
|
122
|
+
|
|
123
|
+
接口内部的小型对象拆分、测试文件布局、必要的错误类型和方法命名由实施者根据现有测试决定;不得借此扩大业务功能、变更 CLI 契约、引入循环依赖或放宽失败判定。
|
data/lib/vxlan/change_plan.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "ctx_runner/fingerprint"
|
|
4
|
-
require "json"
|
|
5
4
|
require "ipaddr"
|
|
6
5
|
require "ctx_parser/immutable"
|
|
7
6
|
require_relative "acl_policy"
|
|
@@ -33,12 +32,6 @@ module Vxlan
|
|
|
33
32
|
nil
|
|
34
33
|
end
|
|
35
34
|
|
|
36
|
-
# 字符串键规范化后计算语义指纹;Hash 顺序不影响结果,数组保留业务顺序。
|
|
37
|
-
def self.fingerprint(value) = CtxRunner::Fingerprint.call(value)
|
|
38
|
-
|
|
39
|
-
# 兼容既有领域入口,配置身份协议仅由 Runner 实现。
|
|
40
|
-
def self.canonical(value) = CtxRunner::Fingerprint.canonical(value)
|
|
41
|
-
|
|
42
35
|
# 构造时一次校验和渲染,随后调用者不能改变已确认的参数或命令。
|
|
43
36
|
def initialize(change)
|
|
44
37
|
raise ArgumentError, "请使用 ChangePlan.build 构造业务增量" if instance_of?(ChangePlan)
|
|
@@ -112,7 +105,7 @@ module Vxlan
|
|
|
112
105
|
|
|
113
106
|
# 元数据与可推导事实不参与漂移比较;每种动作只移除其允许变化的字段。
|
|
114
107
|
def preserved_context(config)
|
|
115
|
-
context =
|
|
108
|
+
context = CtxRunner::Fingerprint.canonical(config).except("config_digest", "review_status", "review_findings", "segments", "unnumbered_addresses")
|
|
116
109
|
context.fetch("acls", {}).transform_values! { |entries| AclPolicy.rules(entries) }
|
|
117
110
|
remove_changed_fields(context)
|
|
118
111
|
context
|
|
@@ -70,13 +70,13 @@ module Vxlan
|
|
|
70
70
|
scope.merge!(router_id: match[1], local_as: match[2])
|
|
71
71
|
elsif (match = /\ANeighbor\s+T\s+AS\s+(?:(PfxRcd)\s+)?(Type-[1-9]\d*(?:\s+Type-[1-9]\d*)*)\z/.match(line))
|
|
72
72
|
prefix_total = !match[1].nil?
|
|
73
|
-
prefix_columns = match[2].split.map { |column| column.downcase.delete("-").to_sym }
|
|
73
|
+
prefix_columns = match[2].split(" ").map { |column| column.downcase.delete("-").to_sym }
|
|
74
74
|
if prefix_columns.uniq != prefix_columns || (prefix_columns - PREFIX_TYPES).any?
|
|
75
75
|
unparsed_records(number)
|
|
76
76
|
prefix_columns = nil
|
|
77
77
|
end
|
|
78
78
|
elsif prefix_columns
|
|
79
|
-
words = line.split
|
|
79
|
+
words = line.split(" ")
|
|
80
80
|
address = CtxParser::Values.ip_address(words[0], allow_zone: true) if ip_address?(words[0])
|
|
81
81
|
peer = peers[[ scope[:vrf], scope[:address_family], address ]]
|
|
82
82
|
offset = prefix_total ? 4 : 3
|
|
@@ -23,7 +23,7 @@ module Vxlan
|
|
|
23
23
|
elsif line.match?(/\AInterface(?:\s+Ch #)?\z/i)
|
|
24
24
|
next
|
|
25
25
|
else
|
|
26
|
-
words = line.split
|
|
26
|
+
words = line.split(" ")
|
|
27
27
|
state = words.index { |word| %w[up down connected notconnect disabled admin-down].include?(word.downcase) }
|
|
28
28
|
unless layout && state && INTERFACE.match?(words[0])
|
|
29
29
|
unparsed_records(number)
|
|
@@ -51,7 +51,7 @@ module Vxlan
|
|
|
51
51
|
# 将回显的聚合成员归一化为接口身份及状态标志。
|
|
52
52
|
def parse_members(text)
|
|
53
53
|
return [] if text.empty? || text == "--"
|
|
54
|
-
text.split.filter_map do |word|
|
|
54
|
+
text.split(" ").filter_map do |word|
|
|
55
55
|
match = /\A(Eth(?:ernet)?[\d\/]+)\(([^\s()]+)\)\z/i.match(word)
|
|
56
56
|
@issues << { code: :invalid_port_channel_member } unless match
|
|
57
57
|
{ interface: match[1], flags: match[2] } if match
|
|
@@ -239,7 +239,7 @@ module Vxlan
|
|
|
239
239
|
|
|
240
240
|
# 提取支持的键值配置对。
|
|
241
241
|
def parse_keyword_pairs(text, allowed)
|
|
242
|
-
words = text.split
|
|
242
|
+
words = text.split(" ")
|
|
243
243
|
raise ArgumentError unless words.size.even? && (words.each_slice(2).map(&:first) - allowed).empty?
|
|
244
244
|
values = words.each_slice(2).to_h.transform_keys(&:to_sym)
|
|
245
245
|
raise ArgumentError unless values.size == words.size / 2
|
|
@@ -250,7 +250,7 @@ module Vxlan
|
|
|
250
250
|
|
|
251
251
|
# 归一化静态路由及可选下一跳属性。
|
|
252
252
|
def static_route(block)
|
|
253
|
-
words = block.text.split
|
|
253
|
+
words = block.text.split(" ")
|
|
254
254
|
raise ArgumentError if words.size < 4
|
|
255
255
|
validate_static_next_hop(words.drop(3))
|
|
256
256
|
|
|
@@ -76,7 +76,7 @@ module Vxlan
|
|
|
76
76
|
analyze_children(block) do |child|
|
|
77
77
|
case child.text
|
|
78
78
|
when /\Amatch (ip|ipv6) (address|next-hop|route-source) prefix-list (.+)\z/
|
|
79
|
-
family, selector, names = $1 == "ip" ? "ipv4" : "ipv6", $2, $3.split
|
|
79
|
+
family, selector, names = $1 == "ip" ? "ipv4" : "ipv6", $2, $3.split(" ")
|
|
80
80
|
values[:prefix_lists].concat(names) if family == "ipv4" && selector == "address"
|
|
81
81
|
(values[:prefix_list_matches] ||= []) << { address_family: family, selector: selector, names: names }
|
|
82
82
|
when /\Amatch / then values[:additional_matches] << child.text
|
|
@@ -54,7 +54,7 @@ module Vxlan
|
|
|
54
54
|
next issue(child)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
(values[:networks] ||= []) << { prefix: network_prefix(subnet, family: family.split.first), route_map: route_map }.compact
|
|
57
|
+
(values[:networks] ||= []) << { prefix: network_prefix(subnet, family: family.split(" ").first), route_map: route_map }.compact
|
|
58
58
|
when /\Aredistribute (\S+)(?: (?!route-map\b)(\S+))?(?: route-map (\S+))?\z/
|
|
59
59
|
values[:redistribute] << { protocol: $1, process: $2, route_map: $3 }.compact
|
|
60
60
|
when /\Aretain route-target (all|route-map \S+)\z/ then assign(values, :retain_route_target, $1, child)
|
data/lib/vxlan/cli/apply.rb
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "optparse"
|
|
4
|
+
require "ctx_cli/terminal"
|
|
5
|
+
require "ctx_cli/input"
|
|
4
6
|
require "json"
|
|
7
|
+
require "ctx_runner/document"
|
|
5
8
|
require "digest"
|
|
6
9
|
require "ctx_runner/execution"
|
|
7
10
|
require "ipaddr"
|
|
@@ -25,7 +28,7 @@ module Vxlan
|
|
|
25
28
|
raise IOError, "配置回读失败" unless capture.success?
|
|
26
29
|
observation = Vxlan::Config.new.parse(capture.body, complete: true)
|
|
27
30
|
raise ArgumentError, "配置证据不完整" unless observation.complete? && observation.records.one?
|
|
28
|
-
|
|
31
|
+
CtxRunner::Document.call(observation.records.first)
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
# 每次只发一条命令;失败立即交还宿主,原始输出不进入终端和日志报告。
|
|
@@ -59,9 +62,10 @@ module Vxlan
|
|
|
59
62
|
end
|
|
60
63
|
rest = parser.parse(argv.dup)
|
|
61
64
|
return @out.puts(parser) || 0 if options[:help]
|
|
62
|
-
|
|
65
|
+
terminal = CtxCli::Terminal.new(input: @input, out: @out)
|
|
66
|
+
terminal.require_tty!(@error)
|
|
63
67
|
raise ArgumentError, "需要单个计划" unless rest.empty? && options[:plan] && options[:port].between?(1, 65_535)
|
|
64
|
-
body =
|
|
68
|
+
body = CtxCli::Input.read(path: options[:plan])
|
|
65
69
|
hash = Digest::SHA256.hexdigest(body)
|
|
66
70
|
plan = CtxParser::Immutable.copy(select_plan(JSON.parse(body), options, hash))
|
|
67
71
|
change = validate_plan(plan)
|
|
@@ -71,9 +75,8 @@ module Vxlan
|
|
|
71
75
|
@out.puts Array(plan["prerequisites"]).map { |value| "条件:#{value}" }
|
|
72
76
|
@out.puts "计划 SHA256:#{hash}\n拟执行命令:\n#{change.commands.join("\n")}\n条件回退(不自动执行):\n#{change.rollback.join("\n")}"
|
|
73
77
|
token = "APPLY #{host} #{hash[0, 12]} #{options[:item]}"
|
|
74
|
-
|
|
75
|
-
@out.
|
|
76
|
-
return @out.puts("已取消,未连接设备。") || 1 unless @input.gets&.strip == token
|
|
78
|
+
confirmed = terminal.confirm(token: token, prompt: "确认业务策略及维护窗口后输入 #{token};其他输入取消:")
|
|
79
|
+
return @out.puts("已取消,未连接设备。") || 1 unless confirmed
|
|
77
80
|
settings = credentials(options)
|
|
78
81
|
@store = Report.new(options[:directory])
|
|
79
82
|
@execution = CtxRunner::Execution.new(plan: plan, change: change, journal: @store, plan_sha256: hash, item: options[:item])
|
|
@@ -99,7 +102,7 @@ module Vxlan
|
|
|
99
102
|
id.is_a?(String) && id.match?(/\A[A-Za-z0-9_.-]+\z/) && document["changes"].key?(id)
|
|
100
103
|
raise ArgumentError, "需要批次计划及有效 --item"
|
|
101
104
|
end
|
|
102
|
-
raise ArgumentError, "计划校验失败" unless
|
|
105
|
+
raise ArgumentError, "计划校验失败" unless CtxCli::Input.read(path: "#{options[:plan]}.sha256", max_bytes: 128).strip == hash
|
|
103
106
|
document["changes"].fetch(id)
|
|
104
107
|
end
|
|
105
108
|
|