net-connector 0.14.0 → 0.15.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -0
- data/CONTRIBUTING.md +4 -4
- data/README.md +2 -2
- data/README.zh-CN.md +2 -2
- data/docs/VERIFICATION.md +20 -11
- data/docs/architecture.md +45 -36
- data/docs/netdisco.md +40 -11
- data/docs/netdisco.zh-CN.md +31 -15
- data/docs/templates.md +2 -2
- data/docs/usage.md +19 -3
- data/docs/usage.zh-CN.md +19 -7
- data/docs/vendors.md +12 -1
- data/examples/{backup.yml → backup.example.yml} +1 -1
- data/examples/inventory.yml +1 -1
- data/lib/net/connector/device/base.rb +24 -6
- data/lib/net/connector/device/{topology → interfaces}/audit.rb +21 -7
- data/lib/net/connector/device/{topology → interfaces}/change.rb +3 -1
- data/lib/net/connector/device/{topology → interfaces}/immediate_strategy.rb +3 -1
- data/lib/net/connector/device/{topology → interfaces}/interface_blocks.rb +2 -1
- data/lib/net/connector/device/{topology → interfaces}/interface_description.rb +15 -1
- data/lib/net/connector/device/{topology → interfaces}/interface_name.rb +6 -4
- data/lib/net/connector/device/{topology → interfaces}/neighbor.rb +18 -1
- data/lib/net/connector/device/{topology → interfaces}/plan.rb +4 -1
- data/lib/net/connector/device/{topology → interfaces}/quoted_text.rb +2 -1
- data/lib/net/connector/device/{topology → interfaces}/stages.rb +3 -2
- data/lib/net/connector/device/{topology → interfaces}/strategy.rb +5 -1
- data/lib/net/connector/device/{topology.rb → interfaces.rb} +68 -74
- data/lib/net/connector/device/local_backup.rb +5 -0
- data/lib/net/connector/device/profile/builder.rb +2 -0
- data/lib/net/connector/device/profile.rb +1 -0
- data/lib/net/connector/device/remote_backup/receipt.rb +3 -0
- data/lib/net/connector/device/remote_backup/target.rb +2 -0
- data/lib/net/connector/device/remote_backup.rb +3 -0
- data/lib/net/connector/device/running_config/strategy.rb +11 -1
- data/lib/net/connector/device/running_config.rb +19 -7
- data/lib/net/connector/device/scope.rb +5 -1
- data/lib/net/connector/device/tftp/file_upload.rb +3 -2
- data/lib/net/connector/device/tftp/receipt.rb +3 -0
- data/lib/net/connector/device/tftp/strategy.rb +4 -1
- data/lib/net/connector/device/tftp/target.rb +1 -0
- data/lib/net/connector/engine/command/result.rb +1 -0
- data/lib/net/connector/engine/command.rb +1 -0
- data/lib/net/connector/engine/configuration.rb +2 -0
- data/lib/net/connector/engine/dialogue.rb +1 -0
- data/lib/net/connector/engine/error/metadata.rb +15 -2
- data/lib/net/connector/engine/errors.rb +6 -2
- data/lib/net/connector/engine/execution.rb +26 -16
- data/lib/net/connector/engine/interaction.rb +1 -0
- data/lib/net/connector/engine/known_hosts.rb +52 -21
- data/lib/net/connector/engine/log/event.rb +6 -0
- data/lib/net/connector/engine/log/formatter.rb +1 -0
- data/lib/net/connector/engine/log/redacting_writer.rb +4 -0
- data/lib/net/connector/engine/log/transcript.rb +4 -0
- data/lib/net/connector/engine/log.rb +5 -1
- data/lib/net/connector/engine/redactor.rb +3 -4
- data/lib/net/connector/engine/response.rb +1 -0
- data/lib/net/connector/engine/result.rb +1 -0
- data/lib/net/connector/engine/script.rb +1 -0
- data/lib/net/connector/engine/session.rb +11 -2
- data/lib/net/connector/engine/terminal/text.rb +3 -0
- data/lib/net/connector/engine/transports.rb +17 -20
- data/lib/net/connector/netdisco/{address_filter.rb → address_set.rb} +5 -1
- data/lib/net/connector/netdisco/batch.rb +9 -6
- data/lib/net/connector/netdisco/cli/backup.rb +36 -25
- data/lib/net/connector/netdisco/cli/credentials.rb +1 -0
- data/lib/net/connector/netdisco/cli/help.rb +10 -6
- data/lib/net/connector/netdisco/cli/options.rb +17 -12
- data/lib/net/connector/netdisco/cli/setup.rb +136 -0
- data/lib/net/connector/netdisco/cli/topology.rb +117 -46
- data/lib/net/connector/netdisco/cli.rb +5 -7
- data/lib/net/connector/netdisco/config/defaults.rb +68 -0
- data/lib/net/connector/netdisco/config/initializer.rb +26 -9
- data/lib/net/connector/netdisco/config.rb +4 -3
- data/lib/net/connector/netdisco/device/access.rb +1 -0
- data/lib/net/connector/netdisco/device/policy.rb +6 -0
- data/lib/net/connector/netdisco/device.rb +1 -0
- data/lib/net/connector/netdisco/fleet/options.rb +17 -10
- data/lib/net/connector/netdisco/fleet.rb +108 -30
- data/lib/net/connector/netdisco/inventory/budget.rb +3 -0
- data/lib/net/connector/netdisco/inventory/cache.rb +14 -0
- data/lib/net/connector/netdisco/inventory/http.rb +55 -23
- data/lib/net/connector/netdisco/inventory/postgres.rb +6 -0
- data/lib/net/connector/netdisco/inventory.rb +3 -0
- data/lib/net/connector/netdisco/{operations → operation}/batch.rb +21 -10
- data/lib/net/connector/netdisco/{operations → operation}/outcome.rb +17 -10
- data/lib/net/connector/netdisco/{operations.rb → operation.rb} +89 -46
- data/lib/net/connector/netdisco/plan.rb +4 -0
- data/lib/net/connector/netdisco/planner.rb +1 -0
- data/lib/net/connector/netdisco/progress.rb +53 -22
- data/lib/net/connector/netdisco/report/files.rb +4 -3
- data/lib/net/connector/netdisco/report/text.rb +17 -6
- data/lib/net/connector/netdisco/report.rb +13 -2
- data/lib/net/connector/netdisco/resources.rb +36 -0
- data/lib/net/connector/netdisco/rules.rb +7 -3
- data/lib/net/connector/netdisco/settings.rb +39 -13
- data/lib/net/connector/netdisco/ssh/archive/client.rb +320 -0
- data/lib/net/connector/netdisco/ssh/archive/pool.rb +71 -0
- data/lib/net/connector/netdisco/ssh/archive/worker.py +269 -0
- data/lib/net/connector/netdisco/ssh/archive.rb +4 -0
- data/lib/net/connector/netdisco/ssh/authentication.rb +33 -0
- data/lib/net/connector/netdisco/tftp/archive.rb +20 -1
- data/lib/net/connector/netdisco/tftp/policy.rb +14 -1
- data/lib/net/connector/netdisco/tftp/root.rb +48 -0
- data/lib/net/connector/netdisco/tftp/verifier.rb +8 -1
- data/lib/net/connector/netdisco/topology/files.rb +59 -0
- data/lib/net/connector/netdisco/topology/options.rb +38 -9
- data/lib/net/connector/netdisco/topology/presentation.rb +59 -0
- data/lib/net/connector/netdisco/worker.rb +37 -11
- data/lib/net/connector/{concurrency → parallel}/observer.rb +5 -1
- data/lib/net/connector/{concurrency → parallel}/pool.rb +18 -14
- data/lib/net/connector/parallel.rb +8 -0
- data/lib/net/connector/storage/atomic_file.rb +9 -0
- data/lib/net/connector/storage/backup_lock.rb +12 -0
- data/lib/net/connector/storage/file_reader.rb +4 -0
- data/lib/net/connector/storage/saved_config.rb +2 -0
- data/lib/net/connector/textfsm.rb +1 -1
- data/lib/net/connector/vendor/centec/running_config.rb +22 -0
- data/lib/net/connector/vendor/centec/tftp.rb +46 -0
- data/lib/net/connector/vendor/centec.rb +33 -0
- data/lib/net/connector/vendor/cisco/topology.rb +3 -3
- data/lib/net/connector/vendor/cisco_ios/tftp.rb +2 -0
- data/lib/net/connector/vendor/cisco_ios.rb +1 -1
- data/lib/net/connector/vendor/cisco_nxos/tftp.rb +2 -0
- data/lib/net/connector/vendor/cisco_nxos/topology.rb +3 -0
- data/lib/net/connector/vendor/cisco_nxos.rb +1 -1
- data/lib/net/connector/vendor/fortinet/tftp.rb +4 -0
- data/lib/net/connector/vendor/fortinet/topology.rb +10 -3
- data/lib/net/connector/vendor/h3c/tftp.rb +3 -0
- data/lib/net/connector/vendor/h3c/topology.rb +3 -3
- data/lib/net/connector/vendor/hillstone/tftp.rb +1 -0
- data/lib/net/connector/vendor/hillstone/topology.rb +3 -3
- data/lib/net/connector/vendor/huawei/topology.rb +11 -4
- data/lib/net/connector/vendor/juniper/remote_backup.rb +2 -0
- data/lib/net/connector/vendor/juniper/topology.rb +10 -3
- data/lib/net/connector/vendor/palo_alto/tftp.rb +3 -1
- data/lib/net/connector/vendor/palo_alto/topology.rb +3 -3
- data/lib/net/connector/vendor/radware/tftp.rb +23 -1
- data/lib/net/connector/vendor/radware/topology.rb +4 -3
- data/lib/net/connector/vendor.rb +3 -1
- data/lib/net/connector/version.rb +1 -1
- metadata +59 -44
- /data/lib/net/connector/{templates → textfsm}/cisco/show_cdp_neighbors_detail.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/cisco/show_running_config.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/cisco_ios/show_ip_interface_brief.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/cisco_nxos/show_cdp_neighbors_detail.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/cisco_nxos/show_ip_interface_brief.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/cisco_nxos/show_running_config.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/fortinet/diagnose_lldp_rx_neighbor.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/fortinet/show_full_configuration.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/h3c/display_current_configuration.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/h3c/display_lldp_neighbor_information_list.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/hillstone/show_configuration_running.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/hillstone/show_lldp_neighbor_information.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/huawei/display_current_configuration.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/huawei/display_lldp_neighbor_brief.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/index +0 -0
- /data/lib/net/connector/{templates → textfsm}/juniper/show_configuration_display_set.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/juniper/show_lldp_neighbors_detail.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/palo_alto/show.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/palo_alto/show_lldp_neighbors_all.textfsm +0 -0
- /data/lib/net/connector/{templates → textfsm}/radware/cfg_dump.textfsm +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7834c1a83cf57694959a803bfe20d69ac11b6acba8b7d0e869d331983d73f766
|
|
4
|
+
data.tar.gz: 0d5d5d735508b56194abe68cac9c2f982e24f3f8a031f2003dd46781ceae070e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 14e385a0beb987446e825306460bfeaa3b1231676a8e776ab9bfa9bdcf89c2ba1123f8f8b4ad860906e356dfd84e83f298097c36ee9fecc6dee54324fa784a64
|
|
7
|
+
data.tar.gz: 5ade1fafd24e2bb15f139916d71ca1749c19a3762f9868650995f193334a0dfb05561750ec7a080083de92f877c87a7a86bbb992c3ba483a1b038beebf64a2a5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# 更新记录
|
|
2
2
|
|
|
3
|
+
## 未发布
|
|
4
|
+
|
|
5
|
+
## 0.15.0 - 2026-10-19
|
|
6
|
+
|
|
7
|
+
- SSH 归档主连接保持到批次结束,避免空闲超时后密码认证失效;关闭后释放退出清理登记,收尾取消保留原始失败与已完成回执。
|
|
8
|
+
- 使用 Ruby 内置的 IO 等待接口,移除已弃用的 io-wait 依赖,避免示例和命令行输出弃用警告。
|
|
9
|
+
|
|
10
|
+
- `prepare_command` 仅接受 `Command` 或 `nil`;非法返回值在替代命令发送前转为带原脚本位置的 `ScriptError`,保留此前完成步骤且不展开返回值。
|
|
11
|
+
- 拓扑 CLI 在交付异步取消前固定完成回执或同步失败,避免已完成应用被记成状态不明的中断;阻塞操作仍可取消。
|
|
12
|
+
- PTY 输出预算直接使用 expect-pty 的公开 `buffer_bytesize` 查询,减少大输出背压时的累计正文复制;输出上限不受日志开关影响。
|
|
13
|
+
- **不兼容**:要求 Ruby 3.4+ 与 expect-pty 0.9.4+;PTY 传输和 SSH 归档认证统一使用 `Session`、`transcript`、`spawn(raw: true)` 与 `expect`,移除旧接口分支及旧依赖能力探测,CI 与文档同步更新。
|
|
14
|
+
|
|
15
|
+
- 单设备接口业务收敛为 `device.interfaces.neighbors/descriptions/plan/audit/apply/sync`;直接迁移原 Topology 实现至 `Interfaces` 与 `device/interfaces/`,移除旧设备平铺入口、常量和加载路径。计划、审计、策略及 CLI/批量调用同步迁移,Netdisco 多设备方法和 Batch 返回值不变。
|
|
16
|
+
- 接口规划、审计与同步统一在设备访问前校验格式选项;规划的邻居和描述采集全程持有会话租约,接口对象复用时仍重新读取现场证据。
|
|
17
|
+
|
|
18
|
+
- 配置与接口描述批次复用 Worker 的结果发布机制;取消后保留已完成回执,区分执行中断与未启动任务,提供 `Operation#last_batch` 和 `Fleet#last_operation_batch`,原始中断仍传播且不重放命令。
|
|
19
|
+
- 文本报告与终端进度共用诊断白名单,未知错误码和类型不再作为自由文本输出。
|
|
20
|
+
- 追加敏感命令的脱敏范围覆盖提示符回调及异常归一化;无秘密规则的日志脱敏跳过过滤器分配,保留独立二进制返回值。
|
|
21
|
+
|
|
22
|
+
- 地址成员集合改名为 `Netdisco::AddressSet`,文件为 `netdisco/address_set.rb`;移除 `AddressFilter` 旧名称。
|
|
23
|
+
|
|
24
|
+
- Netdisco 多设备描述动作使用 `plan_descriptions`、`apply_descriptions`、`sync_descriptions`,移除更早的长方法名,更新批次操作名称;单设备入口见上方 `device.interfaces` 迁移。
|
|
25
|
+
|
|
26
|
+
- 设备批次操作统一为单数 `Netdisco::Operation` 与 `netdisco/operation/`,同步入口、结果对象及 Fleet 调用,移除复数旧接口。
|
|
27
|
+
|
|
28
|
+
- SSH 归档集中到 `netdisco/ssh/archive/`,统一为 `SSH::Archive::Client/Pool` 与 `worker.py`;认证独立为 `SSH::Authentication`,移除旧加载路径及常量。
|
|
29
|
+
|
|
30
|
+
- 拓扑默认输出中文分类摘要和实际配置来源,区分待核实证据与执行失败,取消重复的逐设备刷屏;详细模式仍显示每台原因,JSON 保留状态码并增加统计。
|
|
31
|
+
|
|
32
|
+
- 拓扑计划按设备导出 `scripts/设备名-IP.cfg` 和 `devices/设备名-IP.txt`,命名与备份一致;索引记录路径及命令文件 SHA-256,导出失败阻止应用,无变更不生成空命令文件。
|
|
33
|
+
|
|
34
|
+
- 拓扑规划、同步和下发前重验共用未知邻居身份校验;占位符名称或端口不生成描述命令,逐接口保留问题和可核实的其他变更。
|
|
35
|
+
- 描述比较保留语义一致的旧值,忽略大小写和同类型端口别名差异;补齐 G、SE/Smartrate-Ethernet,Netdisco 可用 `topology.neighbor_name_prefixes` 声明既有名称前缀,仍按当前模板生成真正需要修改的描述。
|
|
36
|
+
|
|
37
|
+
- 高并发执行前为 SSH 管道、设备伪终端、日志和锁预留文件描述符额度,必要时在本进程硬上限内提高软额度;不能满足时先拒绝整批,资源耗尽类型保留在受控诊断中。
|
|
38
|
+
- SSH 主连接预检最多四条并行,失败或取消时回收全部连接;多服务器按各自选中设备数分配连接,避免小服务器按整批并发过量建连。
|
|
39
|
+
|
|
40
|
+
- 批次、拓扑和通用线程池的最大并发统一提高至 500,CLI、YAML、环境配置及交互提示共用相同范围。
|
|
41
|
+
|
|
42
|
+
- 不兼容调整:并发参数统一为 `parallel:`,YAML 使用 `parallel`、环境变量使用 `NC_PARALLEL`、命令行使用 `--parallel`;移除旧名称,不提供兼容别名。
|
|
43
|
+
|
|
44
|
+
- SSH 归档按批次并发分配多个主连接,保留单连接会话上限及跨连接目标锁,修复并发 50 实际被压缩为 4 的吞吐下降。
|
|
45
|
+
|
|
46
|
+
- SSH 归档在设备任务前使用实际服务器进程预检私有目录和写权限;公共目录故障只报一次,避免整批逐设备归档失败。
|
|
47
|
+
|
|
48
|
+
- SSH 归档预检区分密码未配置与已配置但连接失败,提示 `.env` 特殊字符引用规则,避免误导用户重复设置密码。
|
|
49
|
+
|
|
50
|
+
- 不兼容调整:并行入口统一为 `Parallel` 和 `parallel/`,内置 TextFSM 资源改为 `textfsm/`;旧并发常量及加载路径移除。
|
|
51
|
+
- 增加 Centec 配置采集、保存与原生 TFTP 导出;修复 Centec、Cisco IOS/NX-OS 接受 `>` 登录但普通命令无法完成的问题,不隐式提权。
|
|
52
|
+
- Radware 核对设备回显中的实际上传目标,目标不一致时保留完成回执并明确报错,不再伪造请求路径成功。
|
|
53
|
+
- 拒绝全空白 YAML 筛选项及单主机参数中的网段,统一重复主机校验;清单预览过滤终端控制符。
|
|
54
|
+
- 备份取消时保留已完成产物和回执,区分中断与未开始任务并保存摘要;任务返回交接及多服务器关闭故障不覆盖原始中断,也不自动重放设备命令。
|
|
55
|
+
- TFTP 支持无密码 URI 的 SSH 双端归档及非交互认证;服务器目录和锁通过权限、所有者及固定描述符保护,认证取消时回收临时目录。
|
|
56
|
+
- 修复 SSH 归档独立加载缺失错误依赖,以及路径中的查询、片段、百分号字符被 URI 重新解释的问题;明确使用路径编解码规则,避免默认解析器弃用警告。
|
|
57
|
+
- 配置采集在安全提示符场景复用渲染结果,保留正文完整性与重绘边界;补齐库方法的中文用途和复杂逻辑说明。
|
|
58
|
+
- 发布包使用独立公开模板 `backup.example.yml`,排除运行中的现场配置;同步加载路径、贡献指南与迁移说明。
|
|
59
|
+
|
|
60
|
+
## 0.14.1 - 2026-10-18
|
|
61
|
+
|
|
62
|
+
- HTTP 清单在每次调用内复用认证和分页的连接及期限观察线程,保留总预算、逐块限额和禁用隐式请求重试的规则。
|
|
63
|
+
- known_hosts 合并以条目索引避免重复扫描,并复用原子写入和父目录同步;持久化未确认及不安全文件使用明确错误码。
|
|
64
|
+
- 修复设备作用域中同步关闭故障被延迟取消覆盖、callable 结果回调被隐式数组转换忽略,以及错误构造冻结调用方输出缓冲的问题。
|
|
65
|
+
- 必需提示符或抽象设备命令缺失时抛出 `ConfigurationError`,普通批次故障隔离可继续处理其他设备。
|
|
66
|
+
- 诊断复制校验内置错误的类身份,防止自定义异常伪装类名后保留未脱敏的私有字段。
|
|
67
|
+
|
|
3
68
|
## 0.14.0 - 2026-10-18
|
|
4
69
|
|
|
5
70
|
- 不兼容调整:Netdisco 配置与策略入口整理为 `Config`、`Config::Initializer`、`Device::Policy`、`Topology::Options`,原常量和加载路径已移除,直接引用者需更新。
|
data/CONTRIBUTING.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 本地检查
|
|
8
8
|
|
|
9
|
-
需要 Ruby 3.
|
|
9
|
+
需要 Ruby 3.4 及以上版本、POSIX 环境和 Git。安装依赖后运行完整预检:
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
12
|
bundle install
|
|
@@ -43,7 +43,7 @@ bundle exec rake lint
|
|
|
43
43
|
|
|
44
44
|
### Ruby 范式与语法边界
|
|
45
45
|
|
|
46
|
-
- 语法保持 Ruby 3.
|
|
46
|
+
- 语法保持 Ruby 3.4 兼容:双引号、两空格缩进、冻结字符串;不强制 80 列或统一尾随逗号,不以 10 行/3 参数为拆分目标。
|
|
47
47
|
- 方法按公开入口、protected 扩展点、private 实现组织。步骤提取必须表达独立职责,保留原锁、脱敏、rescue/ensure 和计时范围。
|
|
48
48
|
- 命名沿用领域词:`connect`/`close`、`execute_command`/`execute_script`、`running_config`。纯抛错校验统一用 `validate_*!`,不混用 `check_*`;构造用 `build_*`,资源作用域用 `with_*`;不因方法有副作用就追加 `!`。
|
|
49
49
|
- 转换用 `map`、筛选用 `select`、副作用用 `each`。`filter_map` 会丢弃 false/nil;`to_h` 的重复键会覆盖;有条件累计用 `each_with_object`。替换前确认内容、顺序和返回值等价。
|
|
@@ -51,7 +51,7 @@ bundle exec rake lint
|
|
|
51
51
|
- 外部输入先校验再转换,不用 `to_i`、`Array()` 等掩盖非法输入。保留缺失、显式 nil、false 的区别及必要哨兵;不扩大配置来源或改变优先级。
|
|
52
52
|
- 模式匹配只用于稳定结构,并明确未知结构行为;不批量替换分支。Guard clause 保持返回值及预检顺序。完整透传可用匿名块参数,调整参数时显式传递,保留 `super` 的继承语义。
|
|
53
53
|
- Data 用于稳定值对象,Hash 用于配置和外部协议;不为缩短参数列表增加对象。freeze 不会递归冻结,复制规则按对象所有权与现有契约决定。
|
|
54
|
-
- Data 的自定义初始化涉及校验、复制冻结或诊断白名单时,`with`
|
|
54
|
+
- Data 的自定义初始化涉及校验、复制冻结或诊断白名单时,`with` 更新也须执行同一构造边界;回归必须在最低支持的 Ruby 版本验证。
|
|
55
55
|
- 普通失败通过已有错误边界归一化;保留 `cause: nil` 和脱敏先于截断的顺序。资源清理处的 `rescue Exception` 是有理由的例外,清理后保留原中断,Worker 可抑制次级清理异常;不能转换成业务成功。
|
|
56
56
|
- 不自动重放设备命令;只有现有连接恢复允许重试。路径锁在会话锁外,完成步骤和持久化回执不能因后续失败丢失。ensure 中不能新增覆盖原异常或返回值的控制流。
|
|
57
57
|
|
|
@@ -66,7 +66,7 @@ RuboCop 启用 Naming 及 GuardClause、SafeNavigation、RedundantSelf、Redunda
|
|
|
66
66
|
|
|
67
67
|
1. 在 `lib/net/connector/vendor/<厂商>.rb` 声明提示符、命令、交互及策略绑定,并在设备注册入口登记厂商键。已有规则可直接复用,差异逻辑放在该厂商目录中。
|
|
68
68
|
2. 只声明实际实现并经过验证的能力。配置采集覆盖登录、分页、完整提示符、失败响应、空配置和视图恢复;TFTP 需要明确的上传完成证据;拓扑变更还需要计划重验与回读。
|
|
69
|
-
3. 新 TextFSM 模板放入 `lib/net/connector/
|
|
69
|
+
3. 新 TextFSM 模板放入 `lib/net/connector/textfsm/`,按需更新 `index`。提供脱敏的正常、空表、畸形与部分输出样本,验证字段和完整性判断;注明样本的设备系列、固件及来源许可。
|
|
70
70
|
4. 补齐对应测试及能力矩阵,运行完整预检,确认模板进入实际构建的 gem。现场验证应在 PR 中注明环境和结果,模拟传输测试不能代替现场证据。
|
|
71
71
|
|
|
72
72
|
PR 请说明具体问题、修改后的行为、验证命令及仍未验证的范围。仓库的 PR 模板和[发布文档](docs/RELEASING.md)提供交付约定。
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Ruby sessions for network device CLIs over SSH or Telnet. Collect configurations, save private backups, run interactive scripts, parse output with TextFSM, and back up fleets from Netdisco inventories.
|
|
6
6
|
|
|
7
|
-
Requires Ruby 3.
|
|
7
|
+
Requires Ruby 3.4+, expect-pty 0.9.4+ and a POSIX system. SSH uses local OpenSSH; Telnet requires a local `telnet` executable and explicit configuration.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -41,7 +41,7 @@ net-backup --config config.yml --plan
|
|
|
41
41
|
net-backup --config config.yml
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Start with [backup.yml](examples/backup.yml) or [inventory.yml](examples/inventory.yml). Configure inventory and device credentials in the environment; YAML contains non-sensitive settings. See the [Netdisco guide](docs/netdisco.md) for HTTP/PostgreSQL inventories, success policies, TFTP verification, and batch examples.
|
|
44
|
+
Start with [backup.example.yml](examples/backup.example.yml) or [inventory.yml](examples/inventory.yml). Configure inventory and device credentials in the environment; YAML contains non-sensitive settings. See the [Netdisco guide](docs/netdisco.md) for HTTP/PostgreSQL inventories, success policies, TFTP verification, and batch examples.
|
|
45
45
|
|
|
46
46
|
## Documentation
|
|
47
47
|
|
data/README.zh-CN.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
通过 SSH 或 Telnet 操作网络设备的 Ruby 库。支持配置采集、私有备份、交互脚本、TextFSM 解析,以及基于 Netdisco 清单的批量备份。
|
|
6
6
|
|
|
7
|
-
需要 Ruby 3.
|
|
7
|
+
需要 Ruby 3.4+、expect-pty 0.9.4+ 和 POSIX 系统。SSH 使用本机 OpenSSH;Telnet 需要本机安装 `telnet` 并显式配置。
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
|
@@ -41,7 +41,7 @@ net-backup --config config.yml --plan
|
|
|
41
41
|
net-backup --config config.yml
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
从 [backup.yml](examples/backup.yml) 或 [inventory.yml](examples/inventory.yml) 开始配置。清单与设备凭据放在环境变量中,YAML 只保存非敏感设置。HTTP/PostgreSQL 清单、成功策略、TFTP 核验和批量示例见 [Netdisco 指南](docs/netdisco.zh-CN.md)。
|
|
44
|
+
从 [backup.example.yml](examples/backup.example.yml) 或 [inventory.yml](examples/inventory.yml) 开始配置。清单与设备凭据放在环境变量中,YAML 只保存非敏感设置。HTTP/PostgreSQL 清单、成功策略、TFTP 核验和批量示例见 [Netdisco 指南](docs/netdisco.zh-CN.md)。
|
|
45
45
|
|
|
46
46
|
## 文档
|
|
47
47
|
|
data/docs/VERIFICATION.md
CHANGED
|
@@ -97,7 +97,7 @@ debug Logger 计数目标样本;不关闭协议检查、丢弃步骤或共享
|
|
|
97
97
|
| --- | --- | --- |
|
|
98
98
|
| 核心引擎 | `lib/net/connector/engine/**/*.rb` | 80% / 80% |
|
|
99
99
|
| 脱敏与错误处理 | `lib/net/connector/engine/errors.rb`,包含 `Redactor` | 80% / 80% |
|
|
100
|
-
| 批量并发 | `lib/net/connector/
|
|
100
|
+
| 批量并发 | `lib/net/connector/parallel/observer.rb`、`lib/net/connector/parallel/pool.rb`、`lib/net/connector/device/scope.rb`、`netdisco/worker.rb` | 80% / 80% |
|
|
101
101
|
|
|
102
102
|
关键组为空、任一关键文件未测量或组内没有可执行行时均失败。没有分支的组
|
|
103
103
|
不需要分支命中,但仍须通过行覆盖率及文件加载检查。
|
|
@@ -128,7 +128,7 @@ NC-00 未保存逐文件数据,因此本轮不伪造逐文件历史下限;
|
|
|
128
128
|
|
|
129
129
|
## 平台与工具
|
|
130
130
|
|
|
131
|
-
CI 矩阵为 Ubuntu 24.04 / macOS 15 × Ruby 3.
|
|
131
|
+
CI 矩阵为 Ubuntu 24.04 / macOS 15 × Ruby 3.4、4.0。
|
|
132
132
|
GitHub Actions 固定提交 SHA;Gitleaks 与 actionlint 固定版本和各平台归档
|
|
133
133
|
SHA-256,首次使用时从官方 GitHub Release 下载,缓存到 `tmp/tools/`。
|
|
134
134
|
已有工具归档和可执行文件也会再次校验。初次安装依赖和下载工具需要联网;
|
|
@@ -155,17 +155,17 @@ SHA-256,首次使用时从官方 GitHub Release 下载,缓存到 `tmp/tools/
|
|
|
155
155
|
|
|
156
156
|
运行依赖写在 `net-connector.gemspec`,包括直接使用的、可能从 Ruby 默认
|
|
157
157
|
安装中拆出的标准库 gem。开发工具只写在 Gemfile,不进入运行依赖。
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
PTY 与共享脱敏直接依赖 expect-pty 0.9.4+ 的公开 `Session`、`buffer_bytesize` 和 `Expect::Redactor` 接口。
|
|
159
|
+
开发用 `parallel` 保持 1.x。升级 expect-pty 时先验证源码集成,再用本次构建的 gem 验证隔离安装;
|
|
160
|
+
新依赖版本发布前不得将本地构建验证记成已发布版本验收,也不能退回旧接口掩盖依赖缺失。
|
|
161
161
|
|
|
162
162
|
本项目是库,`Gemfile.lock` 仅作本地开发记录并被忽略;各 Ruby 版本的 CI
|
|
163
163
|
分别解析兼容依赖。应用使用者应在自己的应用中提交 lockfile。测试和打包
|
|
164
164
|
脚本通过隔离安装检查运行依赖,避免依赖开发环境里偶然存在的 gem。
|
|
165
165
|
|
|
166
|
-
`gemfiles/minimum.gemfile`
|
|
166
|
+
`gemfiles/minimum.gemfile` 固定受支持的依赖下界 expect-pty 0.9.4、textfsm 0.2.0;
|
|
167
167
|
标准库和开发工具仍按主 Gemfile 的兼容范围解析。普通矩阵检查允许版本的正常解析,
|
|
168
|
-
另在 Ubuntu / Ruby 3.
|
|
168
|
+
另在 Ubuntu / Ruby 3.4、4.0 检查这组版本的全量测试与隔离安装。本地复现:
|
|
169
169
|
|
|
170
170
|
```sh
|
|
171
171
|
BUNDLE_GEMFILE=gemfiles/minimum.gemfile bundle install
|
|
@@ -173,8 +173,8 @@ BUNDLE_GEMFILE=gemfiles/minimum.gemfile bundle exec rake test package:verify
|
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
这不是所有传递依赖最旧版本的笛卡尔积,也不声称本地 macOS 运行证明远端矩阵通过。
|
|
176
|
-
|
|
177
|
-
开发锁文件均忽略;gemspec
|
|
176
|
+
报告记录实际解析版本,便于比较默认组合和受支持的最低组合。
|
|
177
|
+
开发锁文件均忽略;gemspec 声明必要的接口版本下界,基准、夹具、兼容 Gemfile 和审阅报告均不进 gem。
|
|
178
178
|
|
|
179
179
|
gem 只收录库代码、TextFSM 模板、CLI、双语设备/Netdisco 指南、架构/验证/发布文档、双语 README、LICENSE、
|
|
180
180
|
CHANGELOG、SECURITY 和 CONTRIBUTING。仅两个非敏感 YAML 示例随包分发;测试、示例脚本、发布工具、工作流、本地评审快照、本地配置和备份不进入包。
|
|
@@ -211,7 +211,7 @@ Gitleaks 默认规则之外,还检查网络设备密码/SNMP community 配置
|
|
|
211
211
|
默认及最低依赖任务验证实际发布依赖。TextFSM 0.2.0 的公开声明仍为 `json ~> 2.0`;
|
|
212
212
|
本地同版本 gem 的修订不能证明普通消费者能安装 JSON 3。
|
|
213
213
|
|
|
214
|
-
CI 的 `json3-source-compatibility` 在 Ruby 3.
|
|
214
|
+
CI 的 `json3-source-compatibility` 在 Ruby 3.4 / 4.0 检出固定 TextFSM commit
|
|
215
215
|
`733340de378f2d7fbe530b48f2cf1dd6c30c69b0`,应用仓库内
|
|
216
216
|
`script/compatibility/textfsm-json3.patch`,只放宽依赖声明,再执行完整测试和真实打包隔离安装。
|
|
217
217
|
该任务明确代表尚未发布依赖声明下的源码兼容性;不自动发布、替换正式依赖或修改用户的全局 gem。
|
|
@@ -245,7 +245,7 @@ TFTP 远端未核验回执以及自定义日志目录;离线复核同时支持
|
|
|
245
245
|
实施记录使用当前工作区文件和方法可见性快照,区别已有改动与本轮增量,不以 Git HEAD 冒充修改前基线。
|
|
246
246
|
源码根目录 `RENAMES.md` 记录批准的改名与兼容边界。完整验收仍运行 `bundle exec rake ci`;
|
|
247
247
|
临时 PostgreSQL 使用 `bundle exec rake test:postgres`,可通过 `NC_TEST_PG_BINDIR` 指定服务端工具目录。
|
|
248
|
-
最低 Ruby 3.
|
|
248
|
+
最低 Ruby 3.4 必须在对应解释器中运行 lint/test;RuboCop 的 TargetRubyVersion 和 Ruby 4.0 测试不能替代此项。
|
|
249
249
|
|
|
250
250
|
## 报告统计基准
|
|
251
251
|
|
|
@@ -255,6 +255,15 @@ bundle exec ruby script/benchmarks/report_workload.rb 100000 20
|
|
|
255
255
|
|
|
256
256
|
脚本分别输出批次构造、首次统计及重复统计的单调时钟耗时与对象分配数;合成结果的创建不计入测量。比较两个源码版本时,在同一 Ruby 与主机上各运行至少三次。批次构造会复制结果容器并累计状态,重复统计复用计数;不读取报告的调用方也承担构造成本。TFTP 文件核验与逐设备明细仍有线性成本,此基准不测网络吞吐或现场设备性能。
|
|
257
257
|
|
|
258
|
+
## 清单连接与信任文件合并基准
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
bundle exec ruby script/benchmarks/http_workload.rb 200 5
|
|
262
|
+
bundle exec ruby script/benchmarks/known_hosts_workload.rb 30000 3000 5
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
HTTP 基准使用本地 TCP 服务返回 200 页和空结束页,记录总耗时、分配数和连接数,并验证清单内容与顺序;known_hosts 基准包含真实 ssh-keygen 检查和文件提交,验证旧条目及新增条目完整保序。两者均不包含设备登录或现场网络吞吐,比较时须保持相同 Ruby、主机、输入和运行次数。`test/netdisco_budget_test.rb` 另覆盖认证和重连共用总期限、慢速响应头、超额正文及取消后的 socket/观察线程回收。
|
|
266
|
+
|
|
258
267
|
## 厂商能力与模板一致性
|
|
259
268
|
|
|
260
269
|
`test/capabilities_test.rb` 离线核对全部已注册平台的能力;`test/vendor_topology_parity_test.rb` 覆盖 Huawei LLDP 简表与接口描述、FortiOS 顶层接口描述/嵌套表隔离,以及 Junos 物理接口和逻辑单元描述。`test/textfsm_test.rb` 同时检查 H3C 两种列序在通用命令解析入口中的语义、内置厂商/命令的完整匹配,以及各配置方言的索引入口。完整性拒绝路径覆盖缺失表头、残缺记录、未闭合接口表/引号、VDOM 作用域不明和没有值的 Junos description。
|
data/docs/architecture.md
CHANGED
|
@@ -11,23 +11,25 @@
|
|
|
11
11
|
| 设备入口 | 能力组合、会话代理、通用脚本钩子 | `device/base.rb` |
|
|
12
12
|
| 设备档案 | 不可变规则与策略接口校验;Builder 负责声明 DSL | `device/profile.rb`、`device/profile/` |
|
|
13
13
|
| 配置采集与保存 | 采集策略生命周期、完整性校验、显式保存 | `device/running_config.rb`、`device/running_config/`、`device/save_config.rb` |
|
|
14
|
-
| 并发与观察 | 有限并发、后台观察线程的停止与回收 | `
|
|
14
|
+
| 并发与观察 | 有限并发、后台观察线程的停止与回收 | `parallel/pool.rb`、`parallel/observer.rb` |
|
|
15
15
|
| 设备作用域 | 创建连接器、执行任务、关闭并分别交付值与故障 | `device/scope.rb` |
|
|
16
16
|
| 本地备份 | 采集、摘要比较、文件持久化和完成回执 | `device/local_backup.rb` |
|
|
17
17
|
| TFTP | 参数预检、上传、完成证据、目标和回执 | `device/tftp.rb`、`device/tftp/` |
|
|
18
|
-
| 拓扑 | 邻居发现、接口名称/描述、变更计划与分阶段执行 | `device/
|
|
18
|
+
| 拓扑 | 邻居发现、接口名称/描述、变更计划与分阶段执行 | `device/interfaces.rb`、`device/interfaces/` |
|
|
19
19
|
| 厂商差异 | 档案组装及各项能力的厂商策略 | `vendor/<厂商>.rb`、`vendor/<厂商>/` |
|
|
20
20
|
| 文件存储 | 路径锁、安全读取、私有原子写入、离线配置 | `storage.rb`、`storage/` |
|
|
21
|
-
| 解析 | TextFSM 模板选择、记录转换及异常映射 | `textfsm.rb`、`
|
|
21
|
+
| 解析 | TextFSM 模板选择、记录转换及异常映射 | `textfsm.rb`、`textfsm/` |
|
|
22
22
|
| 终端文本 | 严格 UTF-8 字节验证和终端渲染 | `engine/terminal/text.rb`、`engine/terminal/renderer.rb` |
|
|
23
23
|
| 清单来源 | 公共字段、预算与错误;HTTP、PostgreSQL 及缓存 | `netdisco/inventory.rb`、`netdisco/inventory/` |
|
|
24
24
|
| 设备接入 | 动态凭据与批次连接策略的合并 | `netdisco/device/access.rb` |
|
|
25
25
|
| 批量编排 | 策略快照、计划校验、工作线程和报告 | `netdisco/` |
|
|
26
26
|
| 命令行入口 | 转交给 CLI,参数处理与业务流程由库负责 | `bin/net-backup` |
|
|
27
27
|
|
|
28
|
-
`Base` 引入 `RunningConfig::Capability`、`LocalBackup::Capability`、`Tftp::Capability`、`
|
|
28
|
+
`Base` 引入 `RunningConfig::Capability`、`LocalBackup::Capability`、`Tftp::Capability`、`Interfaces::Capability`、`TextFSM::Capability` 及 `SaveConfig`。能力入口与实现共置,Base 不再重复业务包装。配置采集的临时策略绑定也由 RunningConfig 管理;备份与拓扑通过 `device.running_config` 复用同一流程。
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
`Interfaces::Capability` 只提供 `device.interfaces`。集合对象复用解析入口和厂商策略,绑定原设备会话,不缓存现场邻居、描述或计划。资源获取不执行设备 I/O;`neighbors`、`descriptions`、`plan`、`audit`、`apply`、`sync` 集中在 `Interfaces`,计划及审计证据仍为独立的不可变值对象。Netdisco 批量 API 保留显式的 `*_descriptions` 名称与 Batch 返回值,内部统一调用该集合。
|
|
31
|
+
|
|
32
|
+
文件名表达本文件的主要职责,领域归属通过命名空间表达。Netdisco 的清单预算与缓存位于 `inventory/`,分别为 `Inventory::Budget` 和 `Inventory::Cache`;配置操作的批次与逐台结果位于 `operation/`,分别为 `Operation::Batch` 和 `Operation::Outcome`。`Report::Store` 只持久化报告,Fleet 通过 `report_store:` 接收写入器。服务器上传核验与归档分别为 `Tftp::Verifier` 和 `Tftp::Archive`。
|
|
31
33
|
|
|
32
34
|
引擎的 `Command`、`Script`、`Interaction`、`Dialogue`、`Response`、`Command::Result`、`Result` 各有同名文件;传输事件在 `event.rb`,适配器集合在 `transports.rb`。日志的 `RedactingWriter` 与 `Transcript` 位于 `log/` 下各自的同名文件。存储边界使用 `FileReader` 表示受控读取,`AtomicFile` 表示带阶段回执的原子替换;权限和持久性约束仍由这些组件维护。
|
|
33
35
|
|
|
@@ -45,10 +47,11 @@
|
|
|
45
47
|
| `backup(path:)` | `Backup`,含 path、bytes、sha256、collected_at、change、previous_sha256 | 采集/文件错误直接抛出;已 rename 后的持久性错误携带完成回执,不能视为未写入 |
|
|
46
48
|
| `tftp_backup` | `TftpReceipt`,直接包含 server、path、时间、来源、格式及核验等级 | 参数先校验;失败/未确认直接抛出。完成后故障为 `TftpCompletionError`,保留回执 |
|
|
47
49
|
| `parse_command`、`parse_config` | TextFSM 记录数组 | 命令失败、模板错误、严格 UTF-8/解析错误直接抛出,不用空数组代替未知输出 |
|
|
48
|
-
| `neighbors`、`
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
50
|
+
| `interfaces.neighbors`、`interfaces.descriptions` | `Neighbor` 数组、接口到描述的 Hash | 不支持、未知/部分输出或读取失败直接抛出;明确空表才允许空结果 |
|
|
51
|
+
| `interfaces.sync` | `Result` | 显式同步请求在同一租约内完成发现、重验、修改、读回、保存;无变化不写入或保存 |
|
|
52
|
+
| `interfaces.plan` | 冻结的 `Interfaces::Plan` | 格式参数在 I/O 前校验;采集全程持有租约;PAN-OS 当前拒绝自动改写计划,无隐式 commit |
|
|
53
|
+
| `interfaces.audit` | 冻结的 `Interfaces::Audit` | 逐接口记录问题,仅为已核实的接口生成计划;只读平台标记人工处理 |
|
|
54
|
+
| `interfaces.apply(plan, confirmed:)` | `Result`,包括变更后已完成的读回/保存步骤 | 未确认、错误设备/旧命令序列、能力不足及重验失败在写入前直接抛出;`stale_plan` 是 `DeviceError`。开始变更后的领域失败保留步骤 |
|
|
52
55
|
| `SavedConfig#read/#parse/#export` | 原始字节、记录数组;export 返回目标路径或 stdout 模式的 nil | 纯本地,只读取规范地址文件;缺失、不安全文件、解析或写入错误直接抛出 |
|
|
53
56
|
| `Fleet#backup_all/#tftp_backup_all` | 统一 `Report`,内部包含原始执行快照 `Batch` | 设置、外部计划和清单错误在派发前抛出;设备/关闭/回调/报告普通故障保留在批次中,线程中断仍清理后传播 |
|
|
54
57
|
|
|
@@ -79,6 +82,8 @@ Fleet 在规范目标校验、凭据解析及连接器构造之前加同一把
|
|
|
79
82
|
|
|
80
83
|
`Storage::AtomicFile.write` 统一返回 `Receipt`,执行临时文件写入、flush/fsync、rename、父目录 fsync,并跟踪 not_committed/committed/durable 和出错阶段。rename 前失败保留旧文件;之后失败保留新文件。目录 fsync 的 EINVAL/ENOSYS/ENOTSUP/EOPNOTSUPP/NotImplementedError 单独表示不支持;其他错误不能降级为成功。durable 只表示同步调用成功,未变内容不补验过去写入,断电恢复也未在本地测试中验证。
|
|
81
84
|
|
|
85
|
+
`KnownHosts` 在跨进程锁内重读和合并已认证的会话密钥,条目索引保留原顺序及已有重复行,新增行只登记一次。提交复用 `AtomicFile`;目录同步失败保留已替换文件并报告 `file_persistence_unconfirmed`,不能触发再次登记。不安全的非普通共享信任文件报告 `known_hosts_unsafe`,strict 模式仍由 OpenSSH 管理。写入器仅在实际提交时加载,纯会话引擎加载不引入存储层。
|
|
86
|
+
|
|
82
87
|
提交后的 `BackupPersistenceError` 只携带原 `Backup` 元数据和受控写入回执,Fleet 保留产物并使用已有 saved_with_error 分类。只接受库定义的具体完成错误及匹配产物类型,第三方异常的 backup 属性或自定义 WriteError 子类不作为完成证据。报告保留已提交位置,导出错误说明 committed;设备命令不会自动重放。
|
|
83
88
|
|
|
84
89
|
直接备份在路径锁退出前保存完成元数据,锁关闭的普通故障转换为 `BackupFinalizeError`,其中 `backup` 保留结果,`underlying_type` 经过类型白名单。该错误只确认备份操作已完成,不制造文件同步回执;未变文件的历史持久性仍未补验。Fleet 的外层路径锁及 TFTP 归档锁同样保存最新结果,退出故障转为 saved_with_error 或 reported_with_error,已有设备诊断优先,中断继续传播。
|
|
@@ -95,7 +100,7 @@ TFTP 内置策略的 `validate_options!` 是纯参数校验,执行于 H3C 源
|
|
|
95
100
|
|
|
96
101
|
明确完成证据先生成最小回执,再执行路径提取、元数据钩子及事件记录。已完成步骤之后的清理错误同样保留回执;路径不可用时保留 nil,不把请求文件名冒充实际目标。`TftpCompletionError` 只含受控码、类型和回执,不带原始消息、输出或 cause。Fleet 仅信任库定义的精确错误类及匹配产物;第三方异常上的 receipt 字段和错误子类不能供应完成事实。已上传但收尾失败使用 reported_with_error/partial 分类。
|
|
97
102
|
|
|
98
|
-
`
|
|
103
|
+
`device.interfaces` 默认通过显式 `sync` 调用在同一连接与租约内完成发现到保存,调用方无须传递计划。独立规划/应用流程仍冻结计划并要求显式确认;两条路径共用写入前证据重验和命令核对。`ImmediateStrategy` 将即时生效设备的修改/退出视图、运行配置读回、保存拆开:读回未确认或有未识别接口块时停止,不发送保存。重验、下发、读回、保存及阶段间隙都持有原有会话租约;只有所属线程和 Fiber 能顺序执行脚本,其他线程或 Fiber 的调用、关闭请求和脚本回调重入均返回 `SessionBusy`。同一线程和 Fiber 可在命令结束后于租约内关闭异常的嵌套会话;关闭回调不能执行脚本或递归关闭,关闭期间仍保持原租约,标记清理后才交付取消。租约不隔离其他设备会话或管理员。
|
|
99
104
|
|
|
100
105
|
```mermaid
|
|
101
106
|
flowchart LR
|
|
@@ -119,6 +124,8 @@ PAN-OS 使用候选配置模型。[官方提交说明](https://docs.paloaltonetw
|
|
|
119
124
|
|
|
120
125
|
`Worker` 按线程完成顺序接收终止通知,设备结果仍写入原清单槽位。任一线程中断时,调用方无需等待先创建的慢线程;创建后续线程失败时,也会停止并等待已启动的任务清理资源。普通设备故障继续转换为逐台结果,回调故障单独记录。
|
|
121
126
|
|
|
127
|
+
拓扑 CLI 在任务返回交接时先登记完成结果或同步故障,再交付待处理的异步取消;中断摘要保留已确认的 applied 状态和完成步骤。阻塞 I/O 仍可被取消,未取得结果的任务标记为 interrupted,不重放配置。
|
|
128
|
+
|
|
122
129
|
设备耗时由 CLOCK_MONOTONIC 度量,包含 on_start、设备任务及关闭,截止于 on_result 前。报告的总耗时覆盖目录准备和全部 worker/callback,截止于报告写入前;两者不以 UTC 时间相减。Outcome 的 duration_ms 和 Diagnostic 直接声明为 Data 成员,未测量的耗时为 nil。Backup 的路径、摘要及采集时间与 Outcome 的审计时间均复制冻结,构造和 `with` 更新遵守同一所有权边界;结果回调不能原地改写已保存文件的证据。`with` 替换审计时间时清除原计时,替换错误字段时清除原诊断;显式提供的新值仍经过验证。
|
|
123
130
|
|
|
124
131
|
Fleet 始终返回 Report,委托 Batch 的执行结果及严格 success?/status,单独提供 policy 和 policy_success?。默认 strict 要求非空且全部成功;selected 必须至少包含一个成功结果,其他状态只能为 filtered/sample_limit,且 callback_errors 为空、report_error 为 nil。部分成功、任何其他跳过和未知状态都阻止策略成功。
|
|
@@ -135,7 +142,7 @@ Diagnostic 只保存固定词表中的码、类型、阶段和受控产物状态
|
|
|
135
142
|
|
|
136
143
|
`CLI::Backup` 在创建批次目录和读取凭据前固定并验证策略。已固定的 `Settings#with_overrides` 只复制非敏感快照上的覆盖值,不重新读取环境中的策略字段;后续 `snapshot(mode:)` 继续按当前业务模式校验,离线导出不会隐式转成网络备份校验。原凭据来源仍保持动态。
|
|
137
144
|
|
|
138
|
-
`Inventory::HTTP#devices` 每次持有独立 `Inventory::Budget`,认证、分页、QueryRequired 查询共同累计正文字节和去重前记录数,并共享单调时钟 deadline
|
|
145
|
+
`Inventory::HTTP#devices` 每次持有独立 `Inventory::Budget`,认证、分页、QueryRequired 查询共同累计正文字节和去重前记录数,并共享单调时钟 deadline。每次调用独占一个 HTTP 连接作用域和期限观察线程,认证与分页复用连接;服务端关闭 keep-alive 后,后续请求可以重新建连,但失败请求不自动重试。连接不存入来源实例,并发调用不共用传输状态。默认 HTTP 使用 `read_body`,先检查实际接收字节再追加,不信任 Content-Length。每阶段缩短原生连接/读/写超时;总期限还覆盖慢速响应头。期限观察线程只关闭本次拥有的 HTTP 连接,防止 chunked 的收尾读取拖延返回,调用结束即唤醒并 join。默认 HTTP 不做隐式 GET 重试;这一机制不进入设备命令路径。
|
|
139
146
|
|
|
140
147
|
注入的 `requester` 接收 URI 和 request。它返回后才接受长度和期限检查,不在任意用户 Ruby 回调中注入异步异常。解析和集合操作完成后也检查期限,但这不构成任意 CPU 回调的抢占保证。预算失败仅报告错误码与安全类型,没有部分清单、响应正文或底层 cause。HTTPS 的标准证书检查不变;默认允许明文 HTTP,可通过显式策略禁止。
|
|
141
148
|
|
|
@@ -156,7 +163,7 @@ Diagnostic 只保存固定词表中的码、类型、阶段和受控产物状态
|
|
|
156
163
|
| 变化 | 调用方需要保留的约定 |
|
|
157
164
|
| --- | --- |
|
|
158
165
|
| 配置采集默认输出敏感 | 所有日志模式及错误正文隐藏配置;Result.config/steps 和备份仍保留原数据。自定义敏感业务需声明 output_sensitive,不以注册登录密码代替正文保护 |
|
|
159
|
-
| 共享脱敏依赖 |
|
|
166
|
+
| 共享脱敏依赖 | 使用 expect-pty 0.9.4+;字节匹配使用公开 Expect::Redactor,连接器只维护作用域及输出策略 |
|
|
160
167
|
| 拓扑分阶段计划 | 新计划包含真实读回命令;旧/篡改序列重新生成并批准。PAN-OS 暂拒绝自动改写,不引入未经验证的锁或 commit job 命令 |
|
|
161
168
|
| 文件锁及持久性 | 备份前获取稳定的私有锁文件,调用方不要按目录文件总数推断备份数或在运行中删除锁文件;已提交但收尾失败仍有产物,不自动覆盖重试 |
|
|
162
169
|
| 清单和脚本预算 | 清单预算默认有界;max_script_output_bytes 默认为 nil、显式启用。两者都不是整批设备执行的硬 deadline,累计脚本超限不表示命令未执行 |
|
|
@@ -165,7 +172,7 @@ Diagnostic 只保存固定词表中的码、类型、阶段和受控产物状态
|
|
|
165
172
|
| 解析 | 只在解析副本上严格检查 UTF-8;非法数据直接报错。原始备份/导出不转码,其他设备编码等待真实样本再扩展 |
|
|
166
173
|
|
|
167
174
|
任务书 NC-12(协作取消和整批 deadline)为后置可选项,本轮 **deferred**:没有新增
|
|
168
|
-
|
|
175
|
+
协作取消令牌、主动取消入口或“停止后不派发”的公开保证。操作批次的中断回执只记录已观察到的异常取消,不实现协作取消。现有 Worker 的异常 kill/join、
|
|
169
176
|
任务 ensure 和 Session 超时仍保留;任意用户回调应自行保证返回,不能承诺非合作
|
|
170
177
|
回调的硬期限。清单获取 deadline 只约束 Inventory::HTTP#devices,不覆盖整个 Fleet 任务。
|
|
171
178
|
|
|
@@ -195,6 +202,10 @@ Fleet 可把回执与本地普通文件的时间、稳定性、摘要及目录
|
|
|
195
202
|
|
|
196
203
|
提示符和交互标记是 Ruby 正则表达式,应短到能放入未匹配尾部;流式适配器不支持需要无限长历史的模式。收集输出的上限与匹配窗口上限不同。终端渲染器只处理常见行编辑控制符,不是完整屏幕终端模拟器。`Profile#terminal_size` 使用 `[宽, 高]`,PTY 适配器转换为 Ruby 的 `[行, 列]`。
|
|
197
204
|
|
|
205
|
+
PTY 输出上限直接读取信道公开的 `buffer_bytesize` 标量,避免正常分片反复取得累计正文副本;只有实际超限时才获取错误正文,关闭日志也不会关闭上限检查。传输与 SSH 归档认证统一使用当前 `Session`、`transcript`、`spawn(raw: true)` 和 `expect` 契约,不探测或回退到旧接口。运行要求为 expect-pty 0.9.4+、Ruby 3.4+。
|
|
206
|
+
|
|
207
|
+
`prepare_command` 钩子返回 `Command` 表示继续执行,返回 nil 表示跳过。其他返回值在替代命令发送前以 `ScriptError` 拒绝,保留原脚本位置和此前完成步骤,诊断不展开非法值。钩子内部主动执行的查询仍遵循原有执行与输出预算边界。
|
|
208
|
+
|
|
198
209
|
`max_script_output_bytes` 为正 Integer 或 nil。计数属于每个 Execution,主命令以及准备、提示符和后处理钩子的 `Execution#execute_command` 共用计数,包含原始分页标记和最终提示符,不能用 `capture: false` 绕过。登录和提权认证保留各自原有单响应上限。每次脚本新建计数器;一次租约中的多个脚本、多个设备和多个批次不共用它。
|
|
199
210
|
|
|
200
211
|
累计等于上限时当前脚本可正常结束,但下一条查询在发送前失败;超过上限的完整主响应先进入 steps,再返回 `ScriptOutputLimitExceeded`,后处理和下一命令不会继续。追加查询不进入主脚本的公开 steps,但计入预算并在错误中保留实际查询命令。吞掉查询预算异常的钩子不能让超额脚本报告成功。已执行命令不重放;确认的 TFTP 完成行仍可构造带收尾错误的回执。
|
|
@@ -205,19 +216,14 @@ Ruby 对象显式拥有资源并使用关键字参数。`Profile` 提供有限
|
|
|
205
216
|
|
|
206
217
|
## 关键依赖的维护状态与替代方案
|
|
207
218
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
最新为 0.2.0(2026-09-12 发布)。源码分别位于
|
|
219
|
+
关键业务依赖为 [`expect-pty`](https://rubygems.org/gems/expect-pty) 和
|
|
220
|
+
[`textfsm`](https://rubygems.org/gems/textfsm),源码分别位于
|
|
211
221
|
[`gatework/expect-ruby`](https://github.com/gatework/expect-ruby) 和
|
|
212
222
|
[`gatework/textfsm`](https://github.com/gatework/textfsm),与本项目同属 gatework。
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
当前使用 `expect-pty ~> 0.5.0`(允许 `>= 0.5.0, < 0.6.0`)和
|
|
217
|
-
`textfsm ~> 0.2.0`(允许 `>= 0.2.0, < 0.3.0`),没有锁死补丁版本。
|
|
218
|
-
共享脱敏使用 0.5.0 起公开的 `Expect::Redactor`:完整文本、字节流匹配及分片
|
|
223
|
+
当前要求 `expect-pty >= 0.9.4`,其公开 `buffer_bytesize` 与 `Session` 契约是直接依赖;
|
|
224
|
+
不兼容旧版接口。TextFSM 由宿主选择并锁定版本,最低依赖测试仍覆盖 0.2.0。
|
|
225
|
+
共享脱敏直接使用公开的 `Expect::Redactor`:完整文本、字节流匹配及分片
|
|
219
226
|
缓冲由依赖负责,连接器保留秘密作用域、`[REDACTED]` 标记与输出敏感性策略。
|
|
220
|
-
缺少公共接口时明确拒绝初始化脱敏作用域。
|
|
221
227
|
本地 lockfile 固定本地实际解析结果;本项目不提交该文件,CI 按各 Ruby 版本
|
|
222
228
|
重新解析依赖,应用使用者则应提交自己的 lockfile。升级前检查上游变更和
|
|
223
229
|
安全通告,并运行本项目的本地 PTY、错误脱敏、模板样本及隔离安装检查。
|
|
@@ -290,7 +296,7 @@ router.supports?(:tftp_backup) # => true,不连接设备
|
|
|
290
296
|
|
|
291
297
|
配置采集可把 `running_config_strategy` 绑定到 `Net::Connector::RunningConfig::Strategy` 子类。策略实现 `clean`、`result_step`、`prompt_text` 和 `validate_response!`;PAN-OS 候选差异只影响配置采集,直接 `execute_command("show config diff")` 返回该命令输出。静态命令列表留在档案中。`clean_config` 和受保护的 `config_result_step` 钩子可覆盖并调用 `super`。Base 负责通用脚本与锁内回调,不决定配置是否完整。
|
|
292
298
|
|
|
293
|
-
拓扑策略通过 `topology_strategy YourStrategy` 绑定。类方法和实例方法 `supports?` 声明三种拓扑能力,其余方法提供命令、模板、输出完整性和接口拼写。Profile 校验完整接口,包括 `description_key`、`validate_descriptions!`、`change_error_code`、`enter_configuration_command`、`leave_configuration_commands`、`verification_commands`、`persistence_commands` 和 `persistence_confirmed?`。只读策略继承默认空阶段;可写策略必须明确每个阶段,不能用合并的收尾命令推断保存边界。即时生效且使用 interface 块的设备可继承 `
|
|
299
|
+
拓扑策略通过 `topology_strategy YourStrategy` 绑定。类方法和实例方法 `supports?` 声明三种拓扑能力,其余方法提供命令、模板、输出完整性和接口拼写。Profile 校验完整接口,包括 `description_key`、`validate_descriptions!`、`change_error_code`、`enter_configuration_command`、`leave_configuration_commands`、`verification_commands`、`persistence_commands` 和 `persistence_confirmed?`。只读策略继承默认空阶段;可写策略必须明确每个阶段,不能用合并的收尾命令推断保存边界。即时生效且使用 interface 块的设备可继承 `Interfaces::ImmediateStrategy`。自定义采集必须执行已列入计划的命令并返回完成步骤;自定义厂商标签通过 `neighbor_template` 提供模板。
|
|
294
300
|
|
|
295
301
|
业务操作针对单个连接器构造,并提供 `call`。TFTP 策略只处理厂商传输差异,公共操作统一成功和失败规则。生成的文件名经过 `TftpTarget` 校验及长度限制;带作用域的 IPv6 地址会转为安全 ASCII 标记,特别长的地址使用稳定 SHA-256 标记。原本合法的文件名保留拼写,只有整体过长才缩短清单名称。TFTP 返回值表示设备报告上传完成,服务器文件核对仍由调用方负责。
|
|
296
302
|
|
|
@@ -328,7 +334,7 @@ TFTP 策略必须实现 `validate_options!(target, source_file:, vrf:)`、`recei
|
|
|
328
334
|
|
|
329
335
|
Netdisco 的 Settings、Planner、Fleet、CLI 等文件各自声明实际依赖,单独 require 后即可调用,不依赖 `netdisco.rb` 的预设加载顺序。总入口组合 CLI、CLI::Backup 和 CLI::Topology;Batch 通过 autoload 创建 Report,避免两者循环加载。内部清单预算 `Inventory::Budget` 由 Inventory 清单适配器加载。Progress 的终端显示、Fleet 的设备执行、Report 的结果解释和 Storage 的文件持久化保持独立职责。
|
|
330
336
|
|
|
331
|
-
公共策略位于 `RunningConfig::Strategy` / `Rendered`、`Tftp::Strategy` / `FileUpload`、`
|
|
337
|
+
公共策略位于 `RunningConfig::Strategy` / `Rendered`、`Tftp::Strategy` / `FileUpload`、`Interfaces::Strategy` / `ImmediateStrategy`。厂商文件直接依赖公共策略,由 Profile 绑定;没有反向加载和厂商转发别名。
|
|
332
338
|
|
|
333
339
|
`Vendor` 持有平台注册表并按需加载平台类。平台本身就是连接器,例如 `Vendor::CiscoIos`,不再套一层同名 Connector。IOS 与 NX-OS 继承 `Vendor::Cisco` 的运行配置采集、CDP 拓扑和复制确认规则;各平台分别声明提示符、分页、诊断及保存命令;NX-OS 拓扑子类绑定独立的 CDP、接口配置模板。NX-OS 不再保留空的配置清理子类。H3C Wireless 继续继承 H3C 的 Comware 流程;Huawei 与 H3C 的视图和特权语义独立,不因部分命令相似而共用整份档案。
|
|
334
340
|
|
|
@@ -359,10 +365,11 @@ RunningConfig 的两处受控 `send` 保留,用于私有策略绑定与 protec
|
|
|
359
365
|
| 清单预算与缓存 | `Netdisco::Inventory::Budget/Cache`,位于 `netdisco/inventory/` |
|
|
360
366
|
| 配置解析与初始化 | `Netdisco::Config` 和 `Config::Initializer`,位于 `netdisco/config.rb` 和 `netdisco/config/initializer.rb` |
|
|
361
367
|
| 逐设备策略 | `Netdisco::Device::Policy`,位于 `netdisco/device/policy.rb`,按厂商默认和设备地址选取参数 |
|
|
362
|
-
| 拓扑批次参数 | `Netdisco::Topology::Options`,位于 `netdisco/topology/options.rb`;设备拓扑能力仍为 `Net::Connector::
|
|
363
|
-
| 配置操作结果 | `Netdisco::
|
|
368
|
+
| 拓扑批次参数 | `Netdisco::Topology::Options`,位于 `netdisco/topology/options.rb`;设备拓扑能力仍为 `Net::Connector::Interfaces` |
|
|
369
|
+
| 配置操作结果 | `Netdisco::Operation::Batch/Outcome`,位于 `netdisco/operation/` |
|
|
364
370
|
| 报告存储 | `Netdisco::Report::Store`,位于 `netdisco/report/store.rb`,通过 `report_store:` 注入 |
|
|
365
371
|
| 服务器上传证据 | `Netdisco::Tftp::Verifier/Archive`,位于 `netdisco/tftp/` |
|
|
372
|
+
| SSH 归档 | `Netdisco::SSH::Archive::Client/Pool` 与服务器端 `worker.py`,位于 `netdisco/ssh/archive/`;密码交互为 `SSH::Authentication` |
|
|
366
373
|
| 厂商平台 | `Vendor::CiscoIos` 等平台类直接继承 Base 或协议家族类;策略位于平台类下 |
|
|
367
374
|
| 文件边界 | `Storage::FileReader` 与 `Storage::AtomicFile`,分别负责受控读取与原子替换 |
|
|
368
375
|
| 终端应用 | `Netdisco::CLI::Backup/Topology/Credentials/Options`,位于 `netdisco/cli/` |
|
|
@@ -371,13 +378,13 @@ RunningConfig 的两处受控 `send` 保留,用于私有策略绑定与 protec
|
|
|
371
378
|
|
|
372
379
|
## 接口描述规则
|
|
373
380
|
|
|
374
|
-
原始 `Neighbor` 字段和计划证据完整保留发现值。`
|
|
381
|
+
原始 `Neighbor` 字段和计划证据完整保留发现值。`Interfaces::InterfaceName.key` 用于匹配本机接口别名与运行配置名称;`Interfaces::InterfaceName.configuration` 保留配置命令的接口展开规则。`Interfaces::InterfaceName.short` 只决定描述里对端接口的显示形式,绝不替换本机下发命令中的接口名。
|
|
375
382
|
|
|
376
|
-
`
|
|
383
|
+
`Interfaces::InterfaceDescription.format(neighbor, abbreviate: true, lowercase: false)` 是各厂商同步与计划共用的纯函数,生成 `To_<名称>_<接口简称>`。接口族的全称、简称和大小写统一,端口、拆分通道与子接口后缀保持不变;H3C 二层和三层聚合身份不合并。完整规则及厂商命名依据见[设备指南](usage.zh-CN.md#邻居发现与接口描述)。
|
|
377
384
|
|
|
378
385
|
`abbreviate: false` 保留接口原拼写,`lowercase: true` 仅将对端接口改为小写。自定义代码块拿到原始邻居,可生成完整描述。输出仍须经过 80 字节及字符校验、证据复核和回读;同步调用表达写入意图,独立计划应用仍要求确认。
|
|
379
386
|
|
|
380
|
-
`
|
|
387
|
+
`Interfaces::InterfaceDescription.commands(interface:, description:, leave: "exit")` 为 IOS/NX-OS 和山石分别生成 `interface`、`description`、退出命令;H3C 使用 `leave: "quit"`。进入、退出全局配置视图和保存完成证据由厂商负责。各阶段命令分别由策略声明,PAN-OS 的命令构造/超时辅助方法不会启用未经验证的候选提交。命令构造器本身不连接设备,也不能绕开已审核的拓扑计划。
|
|
381
388
|
|
|
382
389
|
## 敏感命令的生命周期
|
|
383
390
|
|
|
@@ -409,7 +416,7 @@ RunningConfig 的两处受控 `send` 保留,用于私有策略绑定与 protec
|
|
|
409
416
|
|
|
410
417
|
业务执行与完成事件的异常范围分开:完成事件只尝试一次,观察者失败不能触发第二次相同通知。已有登录、命令或业务错误优先于失败日志的错误;脚本最终处理已生成的 Result.config 与 steps 不因日志收尾丢失。日志上下文刷新和传输接线恢复仍执行清理,但保留正在传播的主错误及 Interrupt。TFTP 的失败证据同样先决定错误码,再尝试记录失败事件。
|
|
411
418
|
|
|
412
|
-
错误归一化通过 `Error#with_diagnostics` 保留内置错误的业务回执,并新建异常的原生状态,避免复制原 cause
|
|
419
|
+
错误归一化通过 `Error#with_diagnostics` 保留内置错误的业务回执,并新建异常的原生状态,避免复制原 cause 或调用栈。复制还要求实际类与白名单常量身份一致,不能只凭可重写的类名取得信任。自定义错误子类使用脱敏后的参数重新构造,不能复制可能参与消息呈现的原始私有字段。错误输出持有独立冻结副本,不冻结调用方的原始缓冲。缺少必需设备提示符或抽象命令抛出 `ConfigurationError`,属于可隔离的普通故障。会话租约退出时若日志收尾失败,已返回的 Result 仍保留步骤、配置和原业务错误;仅在原操作成功时附加日志错误。
|
|
413
420
|
|
|
414
421
|
单条命令的完整响应在输出日志和完成事件之前保存;即使这些日志处理失败,Session 仍在脱敏作用域退出前把响应交给 Execution,保留已完成步骤与输出预算。TFTP 可从失败结果的完成步骤构造设备回执,再报告日志错误;不会据此重放命令。
|
|
415
422
|
|
|
@@ -443,22 +450,24 @@ end
|
|
|
443
450
|
|
|
444
451
|
## 公共并发、配置批次与清单缓存
|
|
445
452
|
|
|
446
|
-
`
|
|
453
|
+
`Parallel::Pool` 只持有线程、启动闸门和完成事件,按输入顺序交付块结果。普通设备失败如何转成结果由业务适配负责;创建并登记线程时延迟异步中断,登记完成后恢复,启动失败不执行任何设备块。工作线程捕获异常并由调用线程同步传播,避免宿主全局线程策略影响无关线程。`Netdisco::Worker` 为备份与配置操作共用计时、结果槽位和通知适配,不再自行管理线程;设备结果先写入槽位,再执行通知回调。
|
|
454
|
+
|
|
455
|
+
`Device::Scope` 持有单台任务连接器,分别交付业务值与普通故障,收尾不覆盖先前错误或中断。`Netdisco::Operation` 为配置脚本与接口描述同步、规划/应用提供全批预检、固定策略、动态凭据和安全摘要;它保留领域 `Result`、计划和完成步骤,使用独立 `Operation::Batch`,不借用备份路径或上传状态。应用审批计划必须走原拓扑重验、变更、回读、保存流程;有限并发不代表跨设备事务或自动重试安全。
|
|
447
456
|
|
|
448
|
-
`
|
|
457
|
+
操作中断后,`Operation#last_batch` 和 `Fleet#last_operation_batch` 保留已完成回执、已启动但结果未知的 `interrupted` 槽位及 `not_started` 槽位。批次仍抛出原始 `Interrupt`,并明确标记整体中断;下一次操作开始即清除旧回执,预检失败也不能读到上一次结果。取消任务不补造耗时,未启动任务不补造起止时间,结果未知不代表可以重放配置。
|
|
449
458
|
|
|
450
459
|
`Device::Access` 为备份与配置操作统一解析逐设备连接设置:每台设备重新读取凭据,自定义设置覆盖本批固定连接策略,批次日志目录决定日志路径。它不缓存凭据或创建连接;缺少凭据返回 nil,调用入口保留各自的结果分类。`CLI::Credentials` 负责清单客户端与凭据来源的组装,两者不共享设备会话生命周期。
|
|
451
460
|
|
|
452
461
|
`Settings#inventory` 为原始清单适配器包裹 `Inventory::Cache`,默认三天有效。缓存仅保存完整白名单 rows,Rules 和重复地址判定每次重做。身份、SQL 及绑定参数只参与摘要分区,不写入文件;凭据缺失仍在缓存读取前拒绝。过期刷新在有界、按身份的跨进程文件锁内完成,成功后原子替换;失败使用原时间的已验证历史,成功空清单替换旧值。最新查询成功与本地缓存持久化成功是两个事实,不能因写盘失败回退旧数据或重复查询。强刷跳过有效期,不跳过身份、限额、文件校验和失败回退边界。
|
|
453
462
|
|
|
454
|
-
后台心跳和 HTTP 超时观察使用内部 `
|
|
463
|
+
后台心跳和 HTTP 超时观察使用内部 `Parallel::Observer` 作用域,前台保留主业务值和原始故障;观察线程的异常同步交付所有者,不受宿主全局线程异常策略影响。创建至登记期间延后中断,停止和等待期间保证线程回收;心跳普通故障转换为显示诊断,正常 HTTP 请求的未知观察故障仍传播。
|
|
455
464
|
|
|
456
465
|
## 领域值与更新边界
|
|
457
466
|
|
|
458
|
-
`
|
|
467
|
+
`Interfaces::Neighbor`、`Interfaces::Change`、`Interfaces::Plan` 各有同名文件,构造时复制并冻结自己拥有的字符串与容器。不可变子对象可在单设备、批次和结果之间共享;调用方的原始容器与格式化回调返回的字符串仍归调用方所有。计划构造校验数据形状,执行边界继续负责地址规范化、命令预检、现场证据重验及读回。
|
|
459
468
|
|
|
460
469
|
`Netdisco::Batch` 复制结果数组和回调诊断,在构造时累计状态计数;`counts` 返回可修改的独立 Hash。未知状态不能满足成功策略。更新结果集合须使用 `with`,它重新计算计数。上述领域值和远程备份目标、回执的 `with` 显式经过构造函数,避免依赖不同 Ruby 版本中原生 `Data#with` 的初始化行为。
|
|
461
470
|
|
|
462
471
|
拓扑的 `InterfaceBlocks` 模块集中核对 interface 块与解析记录的完整性,由立即生效的变更策略和 Huawei 的只读策略共同组合,读取能力不必继承写入流程。`description_key(row)` 把描述记录映射为领域身份;Junos 逻辑单元使用 `<物理接口>.<单元号>`,保留物理接口描述。FortiOS 读取当前视图顶层 `config system interface`,接口 `description` 与显示 `alias` 分开处理,嵌套 IPv6 表不产生接口记录;无法确认作用域、闭合或记录数量时拒绝结果。
|
|
463
472
|
|
|
464
|
-
`
|
|
473
|
+
`Interfaces::QuotedText` 是描述字段的纯解码边界,不接触设备会话;厂商策略选择无引号文本的处理规则,解析异常统一携带 host、parse 阶段和 unrecognized_output 代码,不携带字段原文或底层异常 cause。配置模板保留完整带引号字段供业务层解码,不能先删外层引号而留下未还原的转义字符。
|