net-connector 0.20.0 → 0.22.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 +9 -0
- data/README.md +5 -1
- data/README.zh-CN.md +1 -1
- data/docs/VERIFICATION.md +21 -6
- data/lib/net/connector/collect/progress.rb +1 -1
- data/lib/net/connector/device/interfaces/audit.rb +2 -2
- data/lib/net/connector/device/interfaces/description.rb +3 -3
- data/lib/net/connector/device/interfaces/neighbor.rb +6 -6
- data/lib/net/connector/device/interfaces.rb +5 -5
- data/lib/net/connector/engine/transports.rb +9 -2
- data/lib/net/connector/netdisco/ssh/authentication.rb +2 -2
- data/lib/net/connector/netdisco/topology/options.rb +3 -3
- data/lib/net/connector/version.rb +1 -1
- metadata +11 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d4fb0da3edb43705fb7cf6cf98d08748f1b5efe5e9c9ad1385ee773d42cafb6e
|
|
4
|
+
data.tar.gz: b7cf3167af1527683bee2e2ca9bd69a8750608168b069868f6e28dc56f2d54b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 238e37ad287e6c4dc61cf2924b5b1bf91a3899cb7c304258795f225182a9c814b033b07bca48a5c8986fd59673e2dade8af17787aa3ac74b7e96fdeacd5a77f5
|
|
7
|
+
data.tar.gz: c5da59c15251d4e0f5b7dce7cca4e4a4135962bd6708fa871cd86dd371679922a388af48ef8fb20843cb0372d24eba917c291ae16181096c445263fb1f6bdeaf
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.22.0 - 2026-10-30
|
|
6
|
+
|
|
7
|
+
- Require Ruby 4.0.6 and expect-pty 0.10.x. Adapt its explicit Result status and match_number in PTY transport and SSH authentication while retaining connector event semantics and zero-based indexes.
|
|
8
|
+
- Accept explicit expect-pty source and package candidates for integration and isolated installation checks; verify the installed candidate bytes.
|
|
9
|
+
|
|
10
|
+
## 0.21.0 - 2026-10-30
|
|
11
|
+
|
|
12
|
+
- Rename neighbor fields to `remote_name`, `remote_interface` and `remote_chassis_id`, retaining `local_interface`. Collection progress reads schema 4 `target`; require ctx_cli 0.5. No legacy accessor aliases.
|
|
13
|
+
|
|
5
14
|
## 0.20.0 - 2026-10-29
|
|
6
15
|
|
|
7
16
|
- Require the latest stable TextFSM 0.5.1, align the minimum dependency matrix, and verify JSON 3 with its original published package instead of a source metadata patch.
|
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
|
|
7
|
+
Requires Ruby 4.0.6+, expect-pty 0.10.x, ctx_cli 0.5.x, TextFSM 0.5.1+ and a POSIX system. SSH uses local OpenSSH; Telnet requires a local `telnet` executable and explicit configuration.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -85,3 +85,7 @@ credentials = Net::Connector::Credentials.new(env: ENV).resolve(platform: :cisco
|
|
|
85
85
|
Catalog owns inventory reading, normalization, duplicate marking and cache status (`#status`). It does not resolve device credentials, log into devices or create operation reports. Pass one policy snapshot throughout a run. Fleet delegates to Catalog and retains operation orchestration.
|
|
86
86
|
|
|
87
87
|
Credentials reads the injected environment on every `resolve`; it returns an independent frozen hash, or nil when no username is available. Platform-specific `NC_<PLATFORM>_USERNAME`, `_PASSWORD`, and `_ENABLE_PASSWORD` override `NC_DEVICE_USERNAME`, `NC_DEVICE_PASSWORD`, and `NC_ENABLE_PASSWORD` respectively. Blank values fall back. Secrets are never cached or included in object inspection.
|
|
88
|
+
|
|
89
|
+
## Domain contract migration (2026-10-30)
|
|
90
|
+
|
|
91
|
+
Rename neighbor fields to `remote_name`, `remote_interface` and `remote_chassis_id`, retaining `local_interface`. Collection progress reads schema 4 `target`; require ctx_cli 0.5. No legacy accessor aliases. See the [schema 4 migration and module contracts](https://github.com/gatework/ctx_runner/blob/main/docs/contracts-2026-10-30.md). Regenerate old collection reports and change plans; changing only their version number is not supported.
|
data/README.zh-CN.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
通过 SSH 或 Telnet 操作网络设备的 Ruby 库。支持配置采集、私有备份、交互脚本、TextFSM 解析,以及基于 Netdisco 清单的批量备份。
|
|
6
6
|
|
|
7
|
-
需要 Ruby
|
|
7
|
+
需要 Ruby 4.0.6+、expect-pty 0.10.x、ctx_cli 0.5.x、TextFSM 0.5.1+ 和 POSIX 系统。SSH 使用本机 OpenSSH;Telnet 需要本机安装 `telnet` 并显式配置。
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
data/docs/VERIFICATION.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# 验证、依赖与敏感数据
|
|
2
2
|
|
|
3
|
+
## 2026-10-30:expect-pty 0.10 候选联调
|
|
4
|
+
|
|
5
|
+
使用 RVM Ruby 4.0.6 / Bundler 4.0.16 / Linux x86_64,显式指定 `EXPECT_PTY_PATH=../expect-ruby` 和
|
|
6
|
+
`EXPECT_PTY_GEM=/absolute/path/expect-pty-0.10.0.gem` 运行完整 `bash script/ci`。
|
|
7
|
+
1,285 runs、12,997 assertions,零失败、错误或跳过;源码/历史/包扫描、307 文件 lint、工作流检查、
|
|
8
|
+
关键组覆盖率下限、基准 smoke、普通/Bundler 隔离安装通过,安装后逐文件核对候选包内容。
|
|
9
|
+
历史覆盖率基线的 Ruby 描述与本机不同,比较状态为 not_comparable,未改写历史基线。
|
|
10
|
+
|
|
11
|
+
PTY 适配显式映射 matched、timeout、eof、error 和 match_number;设备事件继续使用零基 index,
|
|
12
|
+
超时与 EOF 不会因为 Result#error 为 nil 被误判为成功。真实本地 PTY 测试覆盖流式读取、输出上限、关闭与认证。
|
|
13
|
+
最低业务依赖组合(expect-pty 0.10.0、ctx_cli 0.5.0、TextFSM 0.5.1、JSON 2)亦通过完整测试与普通/Bundler 隔离安装;
|
|
14
|
+
先安装候选包,再在未设置 EXPECT_PTY_PATH 的环境中解析 minimum.gemfile。
|
|
15
|
+
日志为 `tmp/lean-ci.log`;最低依赖记录保存在工作区 `.expect-review-20261030/minimum.log`。
|
|
16
|
+
远端 Actions、macOS 和真实设备未在本轮执行。
|
|
17
|
+
|
|
3
18
|
在项目根目录执行:
|
|
4
19
|
|
|
5
20
|
```sh
|
|
@@ -128,7 +143,7 @@ NC-00 未保存逐文件数据,因此本轮不伪造逐文件历史下限;
|
|
|
128
143
|
|
|
129
144
|
## 平台与工具
|
|
130
145
|
|
|
131
|
-
CI 矩阵为 Ubuntu 24.04 / macOS 15 × Ruby
|
|
146
|
+
CI 矩阵为 Ubuntu 24.04 / macOS 15 × Ruby 4.0.6、4.0。
|
|
132
147
|
GitHub Actions 固定提交 SHA;Gitleaks 与 actionlint 固定版本和各平台归档
|
|
133
148
|
SHA-256,首次使用时从官方 GitHub Release 下载,缓存到 `tmp/tools/`。
|
|
134
149
|
已有工具归档和可执行文件也会再次校验。初次安装依赖和下载工具需要联网;
|
|
@@ -155,7 +170,7 @@ SHA-256,首次使用时从官方 GitHub Release 下载,缓存到 `tmp/tools/
|
|
|
155
170
|
|
|
156
171
|
运行依赖写在 `net-connector.gemspec`,包括直接使用的、可能从 Ruby 默认
|
|
157
172
|
安装中拆出的标准库 gem。开发工具只写在 Gemfile,不进入运行依赖。
|
|
158
|
-
PTY 与共享脱敏直接依赖 expect-pty 0.
|
|
173
|
+
PTY 与共享脱敏直接依赖 expect-pty 0.10.x 的公开 `Session`、`buffer_bytesize` 和 `Expect::Redactor` 接口。
|
|
159
174
|
开发用 `parallel` 保持 1.x。升级 expect-pty 时先验证源码集成,再用本次构建的 gem 验证隔离安装;
|
|
160
175
|
新依赖版本发布前不得将本地构建验证记成已发布版本验收,也不能退回旧接口掩盖依赖缺失。
|
|
161
176
|
|
|
@@ -163,9 +178,9 @@ PTY 与共享脱敏直接依赖 expect-pty 0.9.6+ 的公开 `Session`、`buffer_
|
|
|
163
178
|
分别解析兼容依赖。应用使用者应在自己的应用中提交 lockfile。测试和打包
|
|
164
179
|
脚本通过隔离安装检查运行依赖,避免依赖开发环境里偶然存在的 gem。
|
|
165
180
|
|
|
166
|
-
`gemfiles/minimum.gemfile` 固定受支持的依赖下界 expect-pty 0.
|
|
181
|
+
`gemfiles/minimum.gemfile` 固定受支持的依赖下界 expect-pty 0.10.0、ctx_cli 0.5.0、textfsm 0.5.1;
|
|
167
182
|
标准库和开发工具仍按主 Gemfile 的兼容范围解析。普通矩阵检查允许版本的正常解析,
|
|
168
|
-
另在 Ubuntu / Ruby
|
|
183
|
+
另在 Ubuntu / Ruby 4.0.6、4.0 检查这组版本的全量测试与隔离安装。本地复现:
|
|
169
184
|
|
|
170
185
|
```sh
|
|
171
186
|
BUNDLE_GEMFILE=gemfiles/minimum.gemfile bundle install
|
|
@@ -211,7 +226,7 @@ Gitleaks 默认规则之外,还检查网络设备密码/SNMP community 配置
|
|
|
211
226
|
运行依赖要求 TextFSM 0.5.1 或更新版本;0.5.1 的公开 JSON 声明为 `>= 2.0`,
|
|
212
227
|
允许普通消费者选择 JSON 2 或 JSON 3。最低依赖任务固定 TextFSM 0.5.1 与 JSON 2。
|
|
213
228
|
|
|
214
|
-
CI 的 `json3-compatibility` 在 Ruby
|
|
229
|
+
CI 的 `json3-compatibility` 在 Ruby 4.0.6 / 4.0 使用已发布 TextFSM 0.5.1 与 JSON 3,
|
|
215
230
|
执行完整测试和真实打包隔离安装。脚本核对原始 gem 的 JSON 依赖声明,再将发布包缓存
|
|
216
231
|
交给隔离消费者;不再检出旧源码、修改 metadata 或重建同版本 TextFSM。
|
|
217
232
|
|
|
@@ -244,7 +259,7 @@ TFTP 远端未核验回执以及自定义日志目录;离线复核同时支持
|
|
|
244
259
|
实施记录使用当前工作区文件和方法可见性快照,区别已有改动与本轮增量,不以 Git HEAD 冒充修改前基线。
|
|
245
260
|
源码根目录 `RENAMES.md` 记录批准的改名与兼容边界。完整验收仍运行 `bundle exec rake ci`;
|
|
246
261
|
临时 PostgreSQL 使用 `bundle exec rake test:postgres`,可通过 `NC_TEST_PG_BINDIR` 指定服务端工具目录。
|
|
247
|
-
最低 Ruby
|
|
262
|
+
最低 Ruby 4.0.6 必须在对应解释器中运行 lint/test;RuboCop 的 TargetRubyVersion 和 Ruby 4.0 测试不能替代此项。
|
|
248
263
|
|
|
249
264
|
## 报告统计基准
|
|
250
265
|
|
|
@@ -27,7 +27,7 @@ module Net
|
|
|
27
27
|
when "partial" then "Partially complete (#{code})"
|
|
28
28
|
else "Incomplete (#{code})"
|
|
29
29
|
end
|
|
30
|
-
super(host: result.fetch("
|
|
30
|
+
super(host: result.fetch("target").fetch("host"), success: status == "complete",
|
|
31
31
|
duration_ms: result.fetch("duration_ms"), message: message, error_code: code&.to_sym)
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -64,7 +64,7 @@ module Net
|
|
|
64
64
|
def inspect_interface(interface, peers)
|
|
65
65
|
peer = peers.first
|
|
66
66
|
current = @descriptions[interface]
|
|
67
|
-
row = { interface: peer.local_interface, neighbor: peer.
|
|
67
|
+
row = { interface: peer.local_interface, neighbor: peer.remote_name, port: peer.remote_interface,
|
|
68
68
|
current: current, expected: nil, status: :unverified }
|
|
69
69
|
@comparisons << row
|
|
70
70
|
if peers.size != 1
|
|
@@ -78,7 +78,7 @@ module Net
|
|
|
78
78
|
local = @strategy.configuration_interface(peer.local_interface)
|
|
79
79
|
Description.validate_interface!(local)
|
|
80
80
|
row.merge!(expected: proposed, status: compare_status(current, proposed, peer))
|
|
81
|
-
@evidence[interface] = [peer.
|
|
81
|
+
@evidence[interface] = [peer.remote_name, peer.remote_interface, current]
|
|
82
82
|
return if row[:status] == :matches
|
|
83
83
|
|
|
84
84
|
@changes << Change.new(interface: local, old_description: current, new_description: proposed, neighbor: peer)
|
|
@@ -10,11 +10,11 @@ module Net
|
|
|
10
10
|
# 将邻居名称和接口拼成默认描述;统一邻居接口简称,原始发现记录保持不变。
|
|
11
11
|
def self.format(neighbor, abbreviate: true, lowercase: false)
|
|
12
12
|
port = if abbreviate
|
|
13
|
-
Name.short(neighbor.
|
|
13
|
+
Name.short(neighbor.remote_interface, lowercase: lowercase)
|
|
14
14
|
else
|
|
15
|
-
lowercase ? neighbor.
|
|
15
|
+
lowercase ? neighbor.remote_interface.downcase : neighbor.remote_interface
|
|
16
16
|
end
|
|
17
|
-
validate!("To_#{neighbor.
|
|
17
|
+
validate!("To_#{neighbor.remote_name.tr(" ", "_")}_#{port.tr(" ", "_")}")
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# 保留语义相同的旧描述;只归一末尾已知接口别名和大小写,不模糊匹配名称或端口编号。
|
|
@@ -4,11 +4,11 @@ module Net
|
|
|
4
4
|
module Connector
|
|
5
5
|
class Interfaces
|
|
6
6
|
# 邻居身份拥有独立字符串,格式化回调不能改写发现证据。
|
|
7
|
-
Neighbor = Data.define(:local_interface, :
|
|
7
|
+
Neighbor = Data.define(:local_interface, :remote_name, :remote_interface, :remote_chassis_id, :protocol) do
|
|
8
8
|
# 复制并冻结本地端口、邻居名称、远端端口及发现协议。
|
|
9
|
-
def initialize(local_interface:,
|
|
10
|
-
fields = { local_interface: local_interface,
|
|
11
|
-
|
|
9
|
+
def initialize(local_interface:, remote_name:, remote_interface:, remote_chassis_id:, protocol:)
|
|
10
|
+
fields = { local_interface: local_interface, remote_name: remote_name,
|
|
11
|
+
remote_interface: remote_interface, remote_chassis_id: remote_chassis_id }
|
|
12
12
|
raise ArgumentError, "neighbor fields must be Strings" unless fields.values.all?(String)
|
|
13
13
|
raise ArgumentError, "neighbor protocol must be a Symbol" unless protocol.is_a?(Symbol)
|
|
14
14
|
|
|
@@ -18,8 +18,8 @@ module Net
|
|
|
18
18
|
# 原始发现数据保留占位符;规划与下发重验共用身份校验,不能把未知名称写入描述。
|
|
19
19
|
# MAC 是合法的 LLDP Port ID,不凭地址形状猜测设备角色,也不拿 chassis ID 补造名称。
|
|
20
20
|
def identity_issue
|
|
21
|
-
return :unknown_neighbor_name if unknown_identity?(
|
|
22
|
-
return :unknown_neighbor_interface if unknown_identity?(
|
|
21
|
+
return :unknown_neighbor_name if unknown_identity?(remote_name)
|
|
22
|
+
return :unknown_neighbor_interface if unknown_identity?(remote_interface)
|
|
23
23
|
|
|
24
24
|
nil
|
|
25
25
|
end
|
|
@@ -88,9 +88,9 @@ module Net
|
|
|
88
88
|
|
|
89
89
|
rows.map do |row|
|
|
90
90
|
Neighbor.new(local_interface: row.fetch("LOCAL_INTERFACE").strip.freeze,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
remote_name: row.fetch("NEIGHBOR_NAME", "").strip.freeze,
|
|
92
|
+
remote_interface: row.fetch("NEIGHBOR_INTERFACE").strip.freeze,
|
|
93
|
+
remote_chassis_id: row.fetch("CHASSIS_ID", "").strip.freeze,
|
|
94
94
|
protocol: @strategy.protocol).freeze
|
|
95
95
|
end
|
|
96
96
|
end
|
|
@@ -272,7 +272,7 @@ module Net
|
|
|
272
272
|
plan.changes.each do |change|
|
|
273
273
|
Description.validate!(change.new_description)
|
|
274
274
|
unless evidence.fetch(@strategy.interface_key(change.interface)) ==
|
|
275
|
-
[change.neighbor.
|
|
275
|
+
[change.neighbor.remote_name, change.neighbor.remote_interface, change.old_description]
|
|
276
276
|
raise ArgumentError, "plan changes do not match its discovery evidence"
|
|
277
277
|
end
|
|
278
278
|
end
|
|
@@ -319,7 +319,7 @@ module Net
|
|
|
319
319
|
|
|
320
320
|
interfaces.transform_values do |peers|
|
|
321
321
|
peer = peers.fetch(0)
|
|
322
|
-
[peer.
|
|
322
|
+
[peer.remote_name, peer.remote_interface, current.fetch(@strategy.interface_key(peer.local_interface))].freeze
|
|
323
323
|
end.freeze
|
|
324
324
|
end
|
|
325
325
|
|
|
@@ -61,8 +61,15 @@ module Net
|
|
|
61
61
|
# 从信道读取下一事件,并把字符串字段转换为字节字符串。
|
|
62
62
|
def read(patterns, timeout:)
|
|
63
63
|
result = @channel.expect(*patterns, STREAM, timeout: timeout)
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
# 传输事件维持连接器的零基索引与事件协议;PTY 的等待状态和异常在适配边界明确转换。
|
|
65
|
+
error = case result.status
|
|
66
|
+
when :matched then nil
|
|
67
|
+
when :eof, :timeout then result.status
|
|
68
|
+
when :error then result.error
|
|
69
|
+
else raise ArgumentError, "unknown PTY result status"
|
|
70
|
+
end
|
|
71
|
+
Event.new(index: result.match_number && (result.match_number - 1), before: result.before.to_s,
|
|
72
|
+
match: result.match.to_s, error:)
|
|
66
73
|
end
|
|
67
74
|
|
|
68
75
|
# 临时设置写入超时,完成写入后恢复原设置。
|
|
@@ -17,11 +17,11 @@ module Net
|
|
|
17
17
|
Expect.spawn(*arguments, raw: true, buffer_limit: 65_536, write_timeout: 5) do |session|
|
|
18
18
|
deadline = Expect.monotonic + 15
|
|
19
19
|
challenge = session.expect(PASSWORD, REJECTED, timeout: [deadline - Expect.monotonic, 0].max)
|
|
20
|
-
next false unless challenge.
|
|
20
|
+
next false unless challenge.match_number == 1
|
|
21
21
|
|
|
22
22
|
session.write(password + "\n")
|
|
23
23
|
completion = session.expect(PASSWORD, REJECTED, timeout: [deadline - Expect.monotonic, 0].max)
|
|
24
|
-
completion.
|
|
24
|
+
completion.eof?
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
end
|
|
@@ -51,10 +51,10 @@ module Net
|
|
|
51
51
|
|
|
52
52
|
# 使用当前模板和端口展示策略生成缺失或确需修正的目标描述。
|
|
53
53
|
def description_for(neighbor)
|
|
54
|
-
port = neighbor.
|
|
54
|
+
port = neighbor.remote_interface
|
|
55
55
|
port = Net::Connector::Interfaces::Name.short(port) if abbreviate_ports
|
|
56
56
|
port = port.downcase if lowercase_ports
|
|
57
|
-
format(neighbor: neighbor.
|
|
57
|
+
format(neighbor: neighbor.remote_name, port: port)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
# 仅显式声明的旧名称前缀可保留;不把未知名称、包含匹配或不同编号当作同一邻居。
|
|
@@ -63,7 +63,7 @@ module Net
|
|
|
63
63
|
return true if comparison.equivalent?(current, expected)
|
|
64
64
|
|
|
65
65
|
neighbor_name_prefixes.any? do |prefix|
|
|
66
|
-
variant = neighbor.with(
|
|
66
|
+
variant = neighbor.with(remote_name: prefix + neighbor.remote_name)
|
|
67
67
|
comparison.equivalent?(current, description_for(variant))
|
|
68
68
|
end
|
|
69
69
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net-connector
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.22.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- net-connector contributors
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10-
|
|
10
|
+
date: 2026-10-30 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: ctx_cli
|
|
@@ -15,40 +15,40 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.5.0
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '0.
|
|
21
|
+
version: '0.6'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: 0.
|
|
28
|
+
version: 0.5.0
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: '0.
|
|
31
|
+
version: '0.6'
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: expect-pty
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
35
35
|
requirements:
|
|
36
36
|
- - ">="
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: 0.
|
|
38
|
+
version: 0.10.0
|
|
39
39
|
- - "<"
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: '0.
|
|
41
|
+
version: '0.11'
|
|
42
42
|
type: :runtime
|
|
43
43
|
prerelease: false
|
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
45
45
|
requirements:
|
|
46
46
|
- - ">="
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: 0.
|
|
48
|
+
version: 0.10.0
|
|
49
49
|
- - "<"
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
|
-
version: '0.
|
|
51
|
+
version: '0.11'
|
|
52
52
|
- !ruby/object:Gem::Dependency
|
|
53
53
|
name: textfsm
|
|
54
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -586,7 +586,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
586
586
|
requirements:
|
|
587
587
|
- - ">="
|
|
588
588
|
- !ruby/object:Gem::Version
|
|
589
|
-
version:
|
|
589
|
+
version: 4.0.6
|
|
590
590
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
591
591
|
requirements:
|
|
592
592
|
- - ">="
|