oxidized 0.34.1 → 0.34.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/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +25 -0
- data/docs/Configuration.md +20 -161
- data/docs/Hooks.md +2 -2
- data/docs/Inputs.md +205 -0
- data/docs/Release.md +11 -8
- data/extra/device2yaml.rb +1 -1
- data/extra/syslog.rb +1 -1
- data/lib/oxidized/config/vars.rb +25 -14
- data/lib/oxidized/config.rb +1 -0
- data/lib/oxidized/hook/slackdiff.rb +18 -5
- data/lib/oxidized/input/scp.rb +35 -6
- data/lib/oxidized/input/ssh.rb +4 -3
- data/lib/oxidized/input/telnet.rb +2 -1
- data/lib/oxidized/job.rb +14 -6
- data/lib/oxidized/model/model.rb +1 -0
- data/lib/oxidized/model/mtrlrfs.rb +1 -0
- data/lib/oxidized/nodes.rb +2 -0
- data/lib/oxidized/source/csv.rb +1 -1
- data/lib/oxidized/source/jsonfile.rb +1 -1
- data/lib/oxidized/source/sql.rb +1 -1
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +3 -3
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f51898465cc98bf27a9bb2259b1e359f7f52f2c31b23eac63e7730f0eabbb8b8
|
4
|
+
data.tar.gz: 6c45f1b142609bc44b99025b4485b25fde43844738bd489dc2994df77ecf47d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c613a1c2c21144f6c064cb2dfaf94e7fa88248c499c43d3408cbce0e286bee477b09623c6432852b839c8c7f2c3a1511f9634d07ebc3bcbba5037032157f991a
|
7
|
+
data.tar.gz: 2cb4692eab7ebbd916264bae356d08b6f437a6f514da5a815bd1c79242d9a2cd558fcef13ad0f56eb6bb9ba74f054deba661a46b563c4a805ad4be4ede34808d
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2025-
|
3
|
+
# on 2025-08-01 14:00:10 UTC using RuboCop version 1.79.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
6
6
|
|
7
|
+
## [0.34.2 – 2025-08-01]
|
8
|
+
This release mainly fixes a bug in input/scp that made ssh raise an error when
|
9
|
+
closing a closed connection (Issue #3583).
|
10
|
+
|
11
|
+
A fix for config vars (Issue #3536) changes the way oxidized stores its
|
12
|
+
vars internally (symblos => strings). Libraries depending on oxidized internal
|
13
|
+
structures may have problem with this. oxidized-web was fixed in Release 0.17.1.
|
14
|
+
|
15
|
+
### Added
|
16
|
+
- Absolute time limit for a fetch job (default: 300 seconds) (@robertcheramy)
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
- slackdiff: Attempt to join the channel if Errors::NotInChannel is encountered (@varesa)
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
- SSH raises error when closing a closed connection. Fixes #3583 (@ytti)
|
23
|
+
- Config vars will not fall back to less specific. Fixes #3536 (@ytti)
|
24
|
+
- input/scp: make common errors produce a warning, not a crashfile (@robertcheramy)
|
25
|
+
- input/scp: implement timeouts. Fixes #3590 (@robertcheramy, @ytti)
|
26
|
+
- model/mtrlrfs: add missing prompt (@R3thos)
|
27
|
+
- slackdiff: Respect the HTTP proxy configuration while uploading the file. Fixes #3534 (@varesa)
|
28
|
+
- logging (syslog): do not write two timestamps (Fixed in semanticlogger) (@robertcheramy)
|
29
|
+
|
30
|
+
|
7
31
|
## [0.34.1 - 2025-07-18]
|
8
32
|
This release contains small fixes and will include the new version of oxidized-web (0.17.0) in the docker container.
|
9
33
|
|
@@ -15,6 +39,7 @@ This release contains small fixes and will include the new version of oxidized-w
|
|
15
39
|
- junos: fix unfrozen literal strings (@robertcheramy)
|
16
40
|
- spec/model: fix unfrozen literal strings and set a default prompt (@robertcheramy)
|
17
41
|
|
42
|
+
|
18
43
|
## [0.34.0 - 2025-07-15]
|
19
44
|
:warning: This release introduces a [new logging system](docs/Configuration.md#logging),
|
20
45
|
based on [semantic logger](https://logger.rocketjob.io/). The old configuration
|
data/docs/Configuration.md
CHANGED
@@ -1,30 +1,11 @@
|
|
1
1
|
# Configuration
|
2
2
|
|
3
|
-
##
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
The following example will log an active ssh/telnet session
|
11
|
-
`/home/oxidized/.config/oxidized/log/<IP-Address>-<PROTOCOL>`. The file will be
|
12
|
-
truncated on each consecutive ssh/telnet session, so you need to put a `tailf`
|
13
|
-
or `tail -f` on that file!
|
14
|
-
|
15
|
-
```yaml
|
16
|
-
log: /home/oxidized/.config/oxidized/log
|
17
|
-
|
18
|
-
# ...
|
19
|
-
|
20
|
-
input:
|
21
|
-
default: ssh, telnet
|
22
|
-
debug: true
|
23
|
-
ssh:
|
24
|
-
secure: false
|
25
|
-
http:
|
26
|
-
ssl_verify: true
|
27
|
-
```
|
3
|
+
## Modules
|
4
|
+
The configuration of each module is described in its respective sub-configuration file:
|
5
|
+
* [Inputs.md](Inputs.md)
|
6
|
+
* [Outputs.md](Outputs.md)
|
7
|
+
* [Sources.md](Sources.md)
|
8
|
+
* [Hooks.md](Hooks.md)
|
28
9
|
|
29
10
|
## Privileged mode
|
30
11
|
|
@@ -65,142 +46,22 @@ The above strips out snmp community strings from your saved configs.
|
|
65
46
|
|
66
47
|
**NOTE:** Removing secrets reduces the usefulness as a full configuration backup, but it may make sharing configs easier.
|
67
48
|
|
68
|
-
##
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
feature can be turned off by setting the `ssh_no_exec`
|
73
|
-
variable.
|
74
|
-
|
75
|
-
```yaml
|
76
|
-
vars:
|
77
|
-
ssh_no_exec: true
|
78
|
-
```
|
79
|
-
|
80
|
-
## Disabling SSH keepalives
|
81
|
-
|
82
|
-
Oxidized SSH input makes use of SSH keepalives to prevent timeouts from slower
|
83
|
-
devices and to quickly tear down stale sessions in larger deployments. There
|
84
|
-
have been reports of SSH keepalives breaking compatibility with certain OS
|
85
|
-
types. They can be disabled using the `ssh_no_keepalive` variable on a per-node
|
86
|
-
basis (by specifying it in the source) or configured application-wide.
|
87
|
-
|
88
|
-
```yaml
|
89
|
-
vars:
|
90
|
-
ssh_no_keepalive: true
|
91
|
-
```
|
92
|
-
|
93
|
-
## SSH Auth Methods
|
94
|
-
|
95
|
-
By default, Oxidized registers the following auth methods: `none`, `publickey` and `password`. However you can configure this globally, by groups, models or nodes.
|
96
|
-
|
97
|
-
```yaml
|
98
|
-
vars:
|
99
|
-
auth_methods: [ "none", "publickey", "password", "keyboard-interactive" ]
|
100
|
-
```
|
101
|
-
|
102
|
-
## Public Key Authentication with SSH
|
103
|
-
|
104
|
-
Instead of password-based login, Oxidized can make use of key-based SSH
|
105
|
-
authentication.
|
49
|
+
## Timeout and Time limit
|
50
|
+
You can configure when oxidized will `timeout` while fetching a configuration
|
51
|
+
(default: 20 seconds), and how much absolute time (`timelimit`) the fetching
|
52
|
+
is allowed to last (default: 300 seconds, or 5 minutes):
|
106
53
|
|
107
|
-
|
108
|
-
|
109
|
-
`
|
54
|
+
* `timeout`: Maximum time to wait for a single operation during config fetching.
|
55
|
+
Not every input module has an implemented timeout.
|
56
|
+
* `timelimit`: Maximum total time allowed for the entire fetch job. It is
|
57
|
+
independent of input modules and will always be enforced.
|
110
58
|
|
111
|
-
|
59
|
+
If `timelimit`is reached, the fetch job will be killed and will produce a
|
60
|
+
warning. The job status will be set to `timelimit`.
|
112
61
|
|
113
62
|
```yaml
|
114
|
-
|
115
|
-
|
116
|
-
```
|
117
|
-
|
118
|
-
Per-Node:
|
119
|
-
|
120
|
-
```yaml
|
121
|
-
# ...
|
122
|
-
map:
|
123
|
-
name: 0
|
124
|
-
model: 1
|
125
|
-
vars_map:
|
126
|
-
enable: 2
|
127
|
-
ssh_keys: 3
|
128
|
-
# ...
|
129
|
-
```
|
130
|
-
|
131
|
-
If you are using a non-standard path, especially when copying the private key
|
132
|
-
via a secured channel, make sure that the permissions are set correctly:
|
133
|
-
|
134
|
-
```bash
|
135
|
-
foo@bar:~$ ls -la ~/.ssh/
|
136
|
-
total 20
|
137
|
-
drwx------ 2 oxidized oxidized 4096 Mar 13 17:03 .
|
138
|
-
drwx------ 5 oxidized oxidized 4096 Mar 13 21:40 ..
|
139
|
-
-r-------- 1 oxidized oxidized 103 Mar 13 17:03 authorized_keys
|
140
|
-
-rw------- 1 oxidized oxidized 399 Mar 13 17:02 id_ed25519
|
141
|
-
-rw-r--r-- 1 oxidized oxidized 94 Mar 13 17:02 id_ed25519.pub
|
142
|
-
```
|
143
|
-
|
144
|
-
Finally, multiple private keys can be specified as an array of file paths, such
|
145
|
-
as `["~/.ssh/id_rsa", "~/.ssh/id_another_rsa"]`.
|
146
|
-
|
147
|
-
## SSH Proxy Command
|
148
|
-
|
149
|
-
Oxidized can `ssh` through a proxy as well. To do so we just need to set
|
150
|
-
`ssh_proxy` variable with the proxy host information and optionally set the
|
151
|
-
`ssh_proxy_port` with the SSH port if it is not listening on port 22.
|
152
|
-
|
153
|
-
This can be provided on a per-node basis by mapping the proper fields from your
|
154
|
-
source.
|
155
|
-
|
156
|
-
An example for a `csv` input source that maps the 4th field as the `ssh_proxy`
|
157
|
-
value and the 5th field as `ssh_proxy_port`.
|
158
|
-
|
159
|
-
```yaml
|
160
|
-
# ...
|
161
|
-
map:
|
162
|
-
name: 0
|
163
|
-
model: 1
|
164
|
-
vars_map:
|
165
|
-
enable: 2
|
166
|
-
ssh_proxy: 3
|
167
|
-
ssh_proxy_port: 4
|
168
|
-
# ...
|
169
|
-
```
|
170
|
-
|
171
|
-
## SSH enabling legacy algorithms
|
172
|
-
|
173
|
-
When connecting to older firmware over SSH, it is sometimes necessary to enable
|
174
|
-
legacy/disabled settings like KexAlgorithms, HostKeyAlgorithms, MAC or the
|
175
|
-
Encryption.
|
176
|
-
|
177
|
-
These settings can be provided on a per-node basis by mapping the ssh_kex,
|
178
|
-
ssh_host_key, ssh_hmac and the ssh_encryption fields from you source.
|
179
|
-
|
180
|
-
```yaml
|
181
|
-
# ...
|
182
|
-
map:
|
183
|
-
name: 0
|
184
|
-
model: 1
|
185
|
-
vars_map:
|
186
|
-
enable: 2
|
187
|
-
ssh_kex: 3
|
188
|
-
ssh_host_key: 4
|
189
|
-
ssh_hmac: 5
|
190
|
-
ssh_encryption: 6
|
191
|
-
# ...
|
192
|
-
```
|
193
|
-
|
194
|
-
## FTP Passive Mode
|
195
|
-
|
196
|
-
Oxidized uses ftp passive mode by default. Some devices require passive mode to
|
197
|
-
be disabled. To do so, we can set `input.ftp.passive` to false - this will make
|
198
|
-
use of FTP active mode.
|
199
|
-
|
200
|
-
```yaml
|
201
|
-
input:
|
202
|
-
ftp:
|
203
|
-
passive: false
|
63
|
+
timeout: 20
|
64
|
+
timelimit: 300
|
204
65
|
```
|
205
66
|
|
206
67
|
## Advanced Configuration
|
@@ -230,6 +91,7 @@ threads: 30 # maximum number of threads
|
|
230
91
|
# true - always use the maximum number of threads
|
231
92
|
use_max_threads: false
|
232
93
|
timeout: 20
|
94
|
+
timelimit: 300
|
233
95
|
retries: 3
|
234
96
|
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
|
235
97
|
crash:
|
@@ -372,7 +234,7 @@ models:
|
|
372
234
|
password: pass
|
373
235
|
```
|
374
236
|
|
375
|
-
|
237
|
+
## Options (credentials, vars, etc.) precedence:
|
376
238
|
From least to most important:
|
377
239
|
- global options
|
378
240
|
- model specific options
|
@@ -513,9 +375,6 @@ following appenders are currently supported:
|
|
513
375
|
> `stderr` and `stdout` are mutually exclusive and will produce a warning if used
|
514
376
|
> simultaneously.
|
515
377
|
|
516
|
-
> Note: `syslog` currently produces two timestamps because of an issue in
|
517
|
-
> [Sematic Logger](https://github.com/reidmorrison/semantic_logger/issues/316).
|
518
|
-
|
519
378
|
> You can configure as many file appenders as you wish.
|
520
379
|
|
521
380
|
You can set a log level globally and/or for each appender.
|
data/docs/Hooks.md
CHANGED
@@ -249,7 +249,7 @@ Your AWS credentials should be stored in `~/.aws/credentials`.
|
|
249
249
|
|
250
250
|
## Hook type: slackdiff
|
251
251
|
|
252
|
-
The `slackdiff` hook posts colorized config diffs to a [Slack](https://www.slack.com) channel of your choice. It only triggers for `post_store` events.
|
252
|
+
The `slackdiff` hook posts colorized config diffs to a [Slack](https://www.slack.com) channel of your choice. It only triggers for `post_store` events. The used output must be capable of generating a diff. E.g. file output is not usable while git/gitcrypt will work.
|
253
253
|
|
254
254
|
You will need to manually install the `slack-ruby-client` gem on your system:
|
255
255
|
|
@@ -270,7 +270,7 @@ hooks:
|
|
270
270
|
channel: "CHANNEL_ID"
|
271
271
|
```
|
272
272
|
|
273
|
-
The token parameter is a Slack API token that can be generated following [this tutorial](https://api.slack.com/tutorials/tracks/getting-a-token). Until Slack stops supporting them, legacy tokens can also be used.
|
273
|
+
The token parameter is a Slack API token that can be generated following [this tutorial](https://api.slack.com/tutorials/tracks/getting-a-token). Until Slack stops supporting them, legacy tokens can also be used. If the token has channels:join permission, the bot will attempt to automatically join the configured channel if necessary.
|
274
274
|
|
275
275
|
Optionally you can disable snippets and post a formatted message, for instance linking to a commit in a git repo. Named parameters `%{node}`, `%{group}`, `%{model}` and `%{commitref}` are available.
|
276
276
|
|
data/docs/Inputs.md
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
# Inputs
|
2
|
+
## Index
|
3
|
+
* Configuration
|
4
|
+
* [SSH](#ssh)
|
5
|
+
* [SCP](#scp)
|
6
|
+
* [FTP](#ftp)
|
7
|
+
* telnet
|
8
|
+
* http
|
9
|
+
* tftp
|
10
|
+
* exec
|
11
|
+
* [Debugging](#debugging)
|
12
|
+
|
13
|
+
## SSH
|
14
|
+
### Disabling SSH exec channels
|
15
|
+
|
16
|
+
Oxidized uses exec channels to make information extraction simpler, but there
|
17
|
+
are some situations where this doesn't work well, e.g. configuring devices. This
|
18
|
+
feature can be turned off by setting the `ssh_no_exec`
|
19
|
+
variable.
|
20
|
+
|
21
|
+
```yaml
|
22
|
+
vars:
|
23
|
+
ssh_no_exec: true
|
24
|
+
```
|
25
|
+
|
26
|
+
### Disabling SSH keepalives
|
27
|
+
|
28
|
+
Oxidized SSH input makes use of SSH keepalives to prevent timeouts from slower
|
29
|
+
devices and to quickly tear down stale sessions in larger deployments. There
|
30
|
+
have been reports of SSH keepalives breaking compatibility with certain OS
|
31
|
+
types. They can be disabled using the `ssh_no_keepalive` variable on a per-node
|
32
|
+
basis (by specifying it in the source) or configured application-wide.
|
33
|
+
|
34
|
+
```yaml
|
35
|
+
vars:
|
36
|
+
ssh_no_keepalive: true
|
37
|
+
```
|
38
|
+
|
39
|
+
### SSH Auth Methods
|
40
|
+
|
41
|
+
By default, Oxidized registers the following auth methods: `none`, `publickey` and `password`. However you can configure this globally, by groups, models or nodes.
|
42
|
+
|
43
|
+
```yaml
|
44
|
+
vars:
|
45
|
+
auth_methods: [ "none", "publickey", "password", "keyboard-interactive" ]
|
46
|
+
```
|
47
|
+
|
48
|
+
### Public Key Authentication with SSH
|
49
|
+
|
50
|
+
Instead of password-based login, Oxidized can make use of key-based SSH
|
51
|
+
authentication.
|
52
|
+
|
53
|
+
You can tell Oxidized to use one or more private keys globally, or specify the
|
54
|
+
key to be used on a per-node basis. The latter can be done by mapping the
|
55
|
+
`ssh_keys` variable through the active source.
|
56
|
+
|
57
|
+
Global:
|
58
|
+
|
59
|
+
```yaml
|
60
|
+
vars:
|
61
|
+
ssh_keys: "~/.ssh/id_rsa"
|
62
|
+
```
|
63
|
+
|
64
|
+
Per-Node:
|
65
|
+
|
66
|
+
```yaml
|
67
|
+
# ...
|
68
|
+
map:
|
69
|
+
name: 0
|
70
|
+
model: 1
|
71
|
+
vars_map:
|
72
|
+
enable: 2
|
73
|
+
ssh_keys: 3
|
74
|
+
# ...
|
75
|
+
```
|
76
|
+
|
77
|
+
If you are using a non-standard path, especially when copying the private key
|
78
|
+
via a secured channel, make sure that the permissions are set correctly:
|
79
|
+
|
80
|
+
```bash
|
81
|
+
foo@bar:~$ ls -la ~/.ssh/
|
82
|
+
total 20
|
83
|
+
drwx------ 2 oxidized oxidized 4096 Mar 13 17:03 .
|
84
|
+
drwx------ 5 oxidized oxidized 4096 Mar 13 21:40 ..
|
85
|
+
-r-------- 1 oxidized oxidized 103 Mar 13 17:03 authorized_keys
|
86
|
+
-rw------- 1 oxidized oxidized 399 Mar 13 17:02 id_ed25519
|
87
|
+
-rw-r--r-- 1 oxidized oxidized 94 Mar 13 17:02 id_ed25519.pub
|
88
|
+
```
|
89
|
+
|
90
|
+
Finally, multiple private keys can be specified as an array of file paths, such
|
91
|
+
as `["~/.ssh/id_rsa", "~/.ssh/id_another_rsa"]`.
|
92
|
+
|
93
|
+
### SSH Proxy Command
|
94
|
+
|
95
|
+
Oxidized can `ssh` through a proxy as well. To do so we just need to set
|
96
|
+
`ssh_proxy` variable with the proxy host information and optionally set the
|
97
|
+
`ssh_proxy_port` with the SSH port if it is not listening on port 22.
|
98
|
+
|
99
|
+
This can be provided on a per-node basis by mapping the proper fields from your
|
100
|
+
source.
|
101
|
+
|
102
|
+
An example for a `csv` input source that maps the 4th field as the `ssh_proxy`
|
103
|
+
value and the 5th field as `ssh_proxy_port`.
|
104
|
+
|
105
|
+
```yaml
|
106
|
+
# ...
|
107
|
+
map:
|
108
|
+
name: 0
|
109
|
+
model: 1
|
110
|
+
vars_map:
|
111
|
+
enable: 2
|
112
|
+
ssh_proxy: 3
|
113
|
+
ssh_proxy_port: 4
|
114
|
+
# ...
|
115
|
+
```
|
116
|
+
|
117
|
+
### SSH enabling legacy algorithms
|
118
|
+
|
119
|
+
When connecting to older firmware over SSH, it is sometimes necessary to enable
|
120
|
+
legacy/disabled settings like KexAlgorithms, HostKeyAlgorithms, MAC or the
|
121
|
+
Encryption.
|
122
|
+
|
123
|
+
These settings can be provided on a per-node basis by mapping the ssh_kex,
|
124
|
+
ssh_host_key, ssh_hmac and the ssh_encryption fields from you source.
|
125
|
+
|
126
|
+
```yaml
|
127
|
+
# ...
|
128
|
+
map:
|
129
|
+
name: 0
|
130
|
+
model: 1
|
131
|
+
vars_map:
|
132
|
+
enable: 2
|
133
|
+
ssh_kex: 3
|
134
|
+
ssh_host_key: 4
|
135
|
+
ssh_hmac: 5
|
136
|
+
ssh_encryption: 6
|
137
|
+
# ...
|
138
|
+
```
|
139
|
+
|
140
|
+
### Custom SSH port
|
141
|
+
Set the variable `ssh_port` to the desired value (default is 22).
|
142
|
+
|
143
|
+
### SSH Host key verification
|
144
|
+
With the configuration `secure', you can set the ssh key verification:
|
145
|
+
- `true`: strict host verification, looking up the known host files
|
146
|
+
- `false` (default): disable host verification, accept any ssh key
|
147
|
+
|
148
|
+
```
|
149
|
+
input:
|
150
|
+
ssh:
|
151
|
+
secure: true
|
152
|
+
```
|
153
|
+
|
154
|
+
## SCP
|
155
|
+
### SSH Host key verification (SCP)
|
156
|
+
Same as for [SSH host key verification](#ssh-host-key-verification)
|
157
|
+
|
158
|
+
```
|
159
|
+
input:
|
160
|
+
scp:
|
161
|
+
secure: true
|
162
|
+
```
|
163
|
+
|
164
|
+
### Custom SCP port
|
165
|
+
Set the variable `ssh_port` to the desired value (default is 22).
|
166
|
+
|
167
|
+
## FTP
|
168
|
+
### FTP Passive Mode
|
169
|
+
|
170
|
+
Oxidized uses ftp passive mode by default. Some devices require passive mode to
|
171
|
+
be disabled. To do so, we can set `input.ftp.passive` to false - this will make
|
172
|
+
use of FTP active mode.
|
173
|
+
|
174
|
+
```yaml
|
175
|
+
input:
|
176
|
+
ftp:
|
177
|
+
passive: false
|
178
|
+
```
|
179
|
+
|
180
|
+
|
181
|
+
## Debugging
|
182
|
+
|
183
|
+
In case a model plugin doesn't work correctly (ios, procurve, etc.), you can
|
184
|
+
enable live debugging of SSH/Telnet sessions. Just add a `debug` option
|
185
|
+
containing the value true to the `input` section. The log files will be created
|
186
|
+
depending on the parent directory of the logfile option.
|
187
|
+
|
188
|
+
The following example will log an active ssh/telnet session
|
189
|
+
`/home/oxidized/.config/oxidized/log/<IP-Address>-<PROTOCOL>`. The file will be
|
190
|
+
truncated on each consecutive ssh/telnet session, so you need to put a `tailf`
|
191
|
+
or `tail -f` on that file!
|
192
|
+
|
193
|
+
```yaml
|
194
|
+
log: /home/oxidized/.config/oxidized/log
|
195
|
+
|
196
|
+
# ...
|
197
|
+
|
198
|
+
input:
|
199
|
+
default: ssh, telnet
|
200
|
+
debug: true
|
201
|
+
ssh:
|
202
|
+
secure: false
|
203
|
+
http:
|
204
|
+
ssl_verify: true
|
205
|
+
```
|
data/docs/Release.md
CHANGED
@@ -7,12 +7,17 @@ Oxidized versions are numbered like major.minor.patch
|
|
7
7
|
- minor is incremented when releasing new features.
|
8
8
|
- patch is incremented when releasing fixes only.
|
9
9
|
|
10
|
+
## Create a release branch
|
11
|
+
Name the release branch `release/0.xx.yy`
|
12
|
+
|
10
13
|
## Review changes
|
11
14
|
Run `git diff 0.30.0` (where `0.30.0` is to be changed to the last release) and review
|
12
15
|
all the changes that have been done. Have a specific look at changes you don't understand.
|
13
16
|
|
14
17
|
For a graphical compare, use `git difftool -d 0.30.0`.
|
15
18
|
|
19
|
+
Commit fixes to the release branch
|
20
|
+
|
16
21
|
## Update the gem dependencies to the latest versions
|
17
22
|
```
|
18
23
|
bundle outdated
|
@@ -29,9 +34,11 @@ If you change some code => Restart the release process at the beginning ;-)
|
|
29
34
|
## Make sure the file permissions are correct
|
30
35
|
Run `bundle exec rake chmod`
|
31
36
|
|
32
|
-
##
|
33
|
-
|
37
|
+
## Test !
|
38
|
+
Test the git code and the container against as much device types and
|
39
|
+
environments as you can.
|
34
40
|
|
41
|
+
## Bump the version
|
35
42
|
Update CHANGELOG.md:
|
36
43
|
- review it
|
37
44
|
- add release notes
|
@@ -42,16 +49,12 @@ Change the version in `lib/oxidized/version.rb`
|
|
42
49
|
Upload the branch to github, make a Pull Request for it.
|
43
50
|
|
44
51
|
## Make sure you pass all GitHub CI
|
45
|
-
They test different ruby versions
|
46
|
-
|
47
|
-
## Test !
|
48
|
-
Test the git code and the container against as much device types and
|
49
|
-
environments as you can.
|
52
|
+
They test different ruby versions an run security checks on the code (codeql).
|
50
53
|
|
51
54
|
## Prepare the release in your working repository
|
52
55
|
1. Merge the Pull Request into master with the commit message
|
53
56
|
`chore(release): release version 0.3x.y`
|
54
|
-
2. `git pull` master
|
57
|
+
2. `git pull` on master
|
55
58
|
3. Tag the commit with `git tag -a 0.xx.yy -m "Release 0.xx.yy"` or `rake tag`
|
56
59
|
4. Build the gem with ‘rake build’
|
57
60
|
5. Run `git diff` to check if there have been more changes (there shouldn't)
|
data/extra/device2yaml.rb
CHANGED
data/extra/syslog.rb
CHANGED
@@ -141,7 +141,7 @@ module Oxidized
|
|
141
141
|
if Oxidized::CFG.syslogd.resolve == false
|
142
142
|
ipaddr
|
143
143
|
else
|
144
|
-
name = (Resolv.getname ipaddr.to_s rescue ipaddr)
|
144
|
+
name = (Resolv.getname ipaddr.to_s rescue ipaddr) # rubocop:disable Style/RedundantParentheses
|
145
145
|
Oxidized::CFG.syslogd.dns_map.each { |re, sub| name.sub! Regexp.new(re.to_s), sub }
|
146
146
|
name
|
147
147
|
end
|
data/lib/oxidized/config/vars.rb
CHANGED
@@ -4,21 +4,32 @@ module Oxidized
|
|
4
4
|
# convenience method for accessing node, group or global level user variables
|
5
5
|
def vars(name)
|
6
6
|
model_name = @node.model.class.name.to_s.downcase
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
Oxidized.config.
|
19
|
-
|
20
|
-
|
7
|
+
groups = Oxidized.config.groups
|
8
|
+
models = Oxidized.config.models
|
9
|
+
group = groups[@node.group] if groups.has_key?(@node.group)
|
10
|
+
model = models[model_name] if models.has_key?(model_name)
|
11
|
+
group_model = group.models[model_name] if group&.models&.has_key?(model_name)
|
12
|
+
|
13
|
+
scopes = {
|
14
|
+
node: @node.vars,
|
15
|
+
group_model: group_model&.vars,
|
16
|
+
group: group&.vars,
|
17
|
+
model: model&.vars,
|
18
|
+
vars: Oxidized.config.vars
|
19
|
+
}
|
20
|
+
|
21
|
+
scopes.each do |scope_name, scope|
|
22
|
+
next unless scope&.has_key?(name.to_s)
|
23
|
+
|
24
|
+
val = scope[name.to_s]
|
25
|
+
if val.nil?
|
26
|
+
Oxidized.logger.debug "vars.rb: scope #{scope_name} has key #{name} with value nil, ignoring scope"
|
27
|
+
else
|
28
|
+
Oxidized.logger.debug "vars.rb: scope #{scope_name} has key #{name} with value #{val}, using scope"
|
29
|
+
return val
|
30
|
+
end
|
21
31
|
end
|
32
|
+
nil
|
22
33
|
end
|
23
34
|
end
|
24
35
|
end
|
data/lib/oxidized/config.rb
CHANGED
@@ -32,6 +32,7 @@ module Oxidized
|
|
32
32
|
asetus.default.threads = 30
|
33
33
|
asetus.default.use_max_threads = false
|
34
34
|
asetus.default.timeout = 20
|
35
|
+
asetus.default.timelimit = 300
|
35
36
|
asetus.default.retries = 3
|
36
37
|
asetus.default.prompt = /^([\w.@-]+[#>]\s?)$/
|
37
38
|
asetus.default.next_adds_job = false # if true, /next adds job, so device is fetched immmeiately
|
@@ -11,14 +11,20 @@ class SlackDiff < Oxidized::Hook
|
|
11
11
|
raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
|
12
12
|
end
|
13
13
|
|
14
|
-
def slack_upload(client, title, content, channel)
|
14
|
+
def slack_upload(client, title, content, channel, proxy)
|
15
15
|
logger.info "Posting diff as snippet to #{channel}"
|
16
16
|
upload_dest = client.files_getUploadURLExternal(filename: "change",
|
17
17
|
length: content.length,
|
18
18
|
snippet_type: "diff")
|
19
19
|
file_uri = URI.parse(upload_dest[:upload_url])
|
20
20
|
|
21
|
-
|
21
|
+
proxy_uri = URI.parse(proxy) if proxy
|
22
|
+
proxy_address = proxy_uri ? proxy_uri.host : :ENV
|
23
|
+
proxy_port = proxy_uri&.port
|
24
|
+
proxy_user = proxy_uri&.user
|
25
|
+
proxy_pass = proxy_uri&.password
|
26
|
+
|
27
|
+
http = Net::HTTP.new(file_uri.host, file_uri.port, proxy_address, proxy_port, proxy_user, proxy_pass)
|
22
28
|
http.use_ssl = true
|
23
29
|
|
24
30
|
request = Net::HTTP::Post.new(file_uri.request_uri, { Host: file_uri.host })
|
@@ -31,8 +37,15 @@ class SlackDiff < Oxidized::Hook
|
|
31
37
|
id: upload_dest[:file_id],
|
32
38
|
title: title
|
33
39
|
}]
|
34
|
-
|
35
|
-
|
40
|
+
begin
|
41
|
+
client.files_completeUploadExternal(channel_id: channel,
|
42
|
+
files: files.to_json)
|
43
|
+
rescue Slack::Web::Api::Errors::NotInChannel
|
44
|
+
logger.info "Not in specified channel, attempting to join"
|
45
|
+
client.conversations_join(channel: channel)
|
46
|
+
client.files_completeUploadExternal(channel_id: channel,
|
47
|
+
files: files.to_json)
|
48
|
+
end
|
36
49
|
end
|
37
50
|
|
38
51
|
def run_hook(ctx)
|
@@ -53,7 +66,7 @@ class SlackDiff < Oxidized::Hook
|
|
53
66
|
unless diff == "no diffs"
|
54
67
|
title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
|
55
68
|
content = diff[:patch].lines.to_a[4..-1].join
|
56
|
-
slack_upload(client, title, content, cfg.channel)
|
69
|
+
slack_upload(client, title, content, cfg.channel, cfg.has_key?('proxy') ? cfg.proxy : nil)
|
57
70
|
end
|
58
71
|
end
|
59
72
|
# message custom formatted - optional
|
data/lib/oxidized/input/scp.rb
CHANGED
@@ -7,11 +7,14 @@ module Oxidized
|
|
7
7
|
class SCP < Input
|
8
8
|
RESCUE_FAIL = {
|
9
9
|
debug: [
|
10
|
-
|
10
|
+
Net::SSH::Disconnect,
|
11
|
+
Net::SSH::ConnectionTimeout
|
11
12
|
],
|
12
13
|
warn: [
|
13
|
-
|
14
|
-
|
14
|
+
Net::SCP::Error,
|
15
|
+
Net::SSH::HostKeyUnknown,
|
16
|
+
Net::SSH::AuthenticationFailed,
|
17
|
+
Timeout::Error
|
15
18
|
]
|
16
19
|
}.freeze
|
17
20
|
include Input::CLI
|
@@ -20,17 +23,39 @@ module Oxidized
|
|
20
23
|
@node = node
|
21
24
|
@node.model.cfg['scp'].each { |cb| instance_exec(&cb) }
|
22
25
|
@log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-scp", 'w') if Oxidized.config.input.debug?
|
23
|
-
@ssh = Net::SSH.start(@node.ip, @node.auth[:username],
|
26
|
+
@ssh = Net::SSH.start(@node.ip, @node.auth[:username], make_ssh_opts)
|
24
27
|
connected?
|
25
28
|
end
|
26
29
|
|
30
|
+
def make_ssh_opts
|
31
|
+
secure = Oxidized.config.input.scp.secure?
|
32
|
+
ssh_opts = {
|
33
|
+
number_of_password_prompts: 0,
|
34
|
+
verify_host_key: secure ? :always : :never,
|
35
|
+
append_all_supported_algorithms: true,
|
36
|
+
password: @node.auth[:password],
|
37
|
+
timeout: Oxidized.config.timeout,
|
38
|
+
port: (vars(:ssh_port) || 22).to_i,
|
39
|
+
forward_agent: false
|
40
|
+
}
|
41
|
+
|
42
|
+
# Use our logger for Net::SSH
|
43
|
+
ssh_logger = SemanticLogger[Net::SSH]
|
44
|
+
ssh_logger.level = Oxidized.config.input.debug? ? :debug : :fatal
|
45
|
+
ssh_opts[:logger] = ssh_logger
|
46
|
+
|
47
|
+
ssh_opts
|
48
|
+
end
|
49
|
+
|
27
50
|
def connected?
|
28
51
|
@ssh && (not @ssh.closed?)
|
29
52
|
end
|
30
53
|
|
31
54
|
def cmd(file)
|
32
55
|
logger.debug "SCP: #{file} @ #{@node.name}"
|
33
|
-
|
56
|
+
Timeout.timeout(Oxidized.config.timeout) do
|
57
|
+
@ssh.scp.download!(file)
|
58
|
+
end
|
34
59
|
end
|
35
60
|
|
36
61
|
def send(my_proc)
|
@@ -44,7 +69,11 @@ module Oxidized
|
|
44
69
|
private
|
45
70
|
|
46
71
|
def disconnect
|
47
|
-
|
72
|
+
Timeout.timeout(Oxidized.config.timeout) do
|
73
|
+
@ssh.close
|
74
|
+
end
|
75
|
+
rescue Timeout::Error
|
76
|
+
logger.debug "#{@node.name} timed out while disconnecting"
|
48
77
|
ensure
|
49
78
|
@log.close if Oxidized.config.input.debug?
|
50
79
|
end
|
data/lib/oxidized/input/ssh.rb
CHANGED
@@ -14,6 +14,7 @@ module Oxidized
|
|
14
14
|
]
|
15
15
|
}.freeze
|
16
16
|
include Input::CLI
|
17
|
+
|
17
18
|
class NoShell < OxidizedError; end
|
18
19
|
|
19
20
|
def connect(node) # rubocop:disable Naming/PredicateMethod
|
@@ -81,12 +82,12 @@ module Oxidized
|
|
81
82
|
Timeout.timeout(Oxidized.config.timeout) { @ssh.loop }
|
82
83
|
rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError => e
|
83
84
|
logger.debug 'The other side closed the connection while ' \
|
84
|
-
"disconnecting,
|
85
|
+
"disconnecting, raising #{e.class} with #{e.message}"
|
85
86
|
rescue Timeout::Error
|
86
87
|
logger.debug "#{@node.name} timed out while disconnecting"
|
87
88
|
ensure
|
88
89
|
@log.close if Oxidized.config.input.debug?
|
89
|
-
(@ssh.close rescue true) unless @ssh.closed?
|
90
|
+
(@ssh.close rescue true) unless @ssh.closed? # rubocop:disable Style/RedundantParentheses
|
90
91
|
end
|
91
92
|
|
92
93
|
def shell_open(ssh)
|
@@ -162,7 +163,7 @@ module Oxidized
|
|
162
163
|
ssh_opts[:host_key] = vars(:ssh_host_key).split(/,\s*/) if vars(:ssh_host_key)
|
163
164
|
ssh_opts[:hmac] = vars(:ssh_hmac).split(/,\s*/) if vars(:ssh_hmac)
|
164
165
|
|
165
|
-
# Use our logger for Net
|
166
|
+
# Use our logger for Net::SSH
|
166
167
|
ssh_logger = SemanticLogger[Net::SSH]
|
167
168
|
ssh_logger.level = Oxidized.config.input.debug? ? :debug : :fatal
|
168
169
|
ssh_opts[:logger] = ssh_logger
|
@@ -4,6 +4,7 @@ module Oxidized
|
|
4
4
|
class Telnet < Input
|
5
5
|
RESCUE_FAIL = {}.freeze
|
6
6
|
include Input::CLI
|
7
|
+
|
7
8
|
attr_reader :telnet
|
8
9
|
|
9
10
|
def connect(node) # rubocop:disable Naming/PredicateMethod
|
@@ -67,7 +68,7 @@ module Oxidized
|
|
67
68
|
# This exception is intented and therefore not handled here
|
68
69
|
ensure
|
69
70
|
@log.close if Oxidized.config.input.debug?
|
70
|
-
(@telnet.close rescue true) unless @telnet.sock.closed?
|
71
|
+
(@telnet.close rescue true) unless @telnet.sock.closed? # rubocop:disable Style/RedundantParentheses
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
data/lib/oxidized/job.rb
CHANGED
@@ -7,13 +7,21 @@ module Oxidized
|
|
7
7
|
def initialize(node)
|
8
8
|
@node = node
|
9
9
|
@start = Time.now.utc
|
10
|
-
self.name = "
|
10
|
+
self.name = "Job '#{@node.name}'"
|
11
11
|
super do
|
12
|
-
logger.debug "Starting fetching process for #{@node.name}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
logger.debug "Starting fetching process for #{@node.name}"
|
13
|
+
begin
|
14
|
+
Timeout.timeout(Oxidized.config.timelimit) do
|
15
|
+
@status, @config = @node.run
|
16
|
+
end
|
17
|
+
logger.debug "Config fetched for #{@node.name}"
|
18
|
+
rescue Timeout::Error
|
19
|
+
logger.warn "Job timelimit reached for #{@node.name}"
|
20
|
+
@status = :timelimit
|
21
|
+
ensure
|
22
|
+
@end = Time.now.utc
|
23
|
+
@time = @end - @start
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
19
27
|
end
|
data/lib/oxidized/model/model.rb
CHANGED
data/lib/oxidized/nodes.rb
CHANGED
@@ -38,8 +38,10 @@ module Oxidized
|
|
38
38
|
def node_want?(node_want, node)
|
39
39
|
return true unless node_want
|
40
40
|
|
41
|
+
# rubocop:disable Style/RedundantParentheses
|
41
42
|
node_want_ip = (IPAddr.new(node_want) rescue false)
|
42
43
|
name_is_ip = (IPAddr.new(node[:name]) rescue false)
|
44
|
+
# rubocop:enable Style/RedundantParentheses
|
43
45
|
# rubocop:todo Lint/DuplicateBranch
|
44
46
|
if name_is_ip && (node_want_ip == node[:name])
|
45
47
|
true
|
data/lib/oxidized/source/csv.rb
CHANGED
@@ -43,7 +43,7 @@ module Oxidized
|
|
43
43
|
# map node specific vars
|
44
44
|
vars = {}
|
45
45
|
@cfg.vars_map.each do |key, position|
|
46
|
-
vars[key.
|
46
|
+
vars[key.to_s] = node_var_interpolate data[position]
|
47
47
|
end
|
48
48
|
keys[:vars] = vars unless vars.empty?
|
49
49
|
|
@@ -50,7 +50,7 @@ module Oxidized
|
|
50
50
|
# map node specific vars
|
51
51
|
vars = {}
|
52
52
|
@cfg.vars_map.each do |key, want_position|
|
53
|
-
vars[key.
|
53
|
+
vars[key.to_s] = node_var_interpolate string_navigate_object(node, want_position)
|
54
54
|
end
|
55
55
|
keys[:vars] = vars unless vars.empty?
|
56
56
|
|
data/lib/oxidized/source/sql.rb
CHANGED
@@ -42,7 +42,7 @@ module Oxidized
|
|
42
42
|
# map node specific vars
|
43
43
|
vars = {}
|
44
44
|
@cfg.vars_map.each do |key, sql_column|
|
45
|
-
vars[key.
|
45
|
+
vars[key.to_s] = node_var_interpolate node[sql_column.to_sym]
|
46
46
|
end
|
47
47
|
keys[:vars] = vars unless vars.empty?
|
48
48
|
|
data/lib/oxidized/version.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Oxidized
|
4
|
-
VERSION = '0.34.
|
5
|
-
VERSION_FULL = '0.34.
|
4
|
+
VERSION = '0.34.2'
|
5
|
+
VERSION_FULL = '0.34.2'
|
6
6
|
def self.version_set
|
7
7
|
version_full = %x(git describe --tags).chop rescue ""
|
8
8
|
version = %x(git describe --tags --abbrev=0).chop rescue ""
|
data/oxidized.gemspec
CHANGED
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.add_dependency 'net-telnet', '~> 0.2'
|
42
42
|
s.add_dependency 'psych', '~> 5.0'
|
43
43
|
s.add_dependency 'rugged', '~> 1.6'
|
44
|
-
s.add_dependency 'semantic_logger', '~> 4.
|
44
|
+
s.add_dependency 'semantic_logger', '~> 4.17.0'
|
45
45
|
s.add_dependency 'slop', '~> 4.6'
|
46
46
|
s.add_dependency 'syslog', '~> 0.3.0'
|
47
47
|
s.add_dependency 'syslog_protocol', '~> 0.9.2'
|
@@ -53,13 +53,13 @@ Gem::Specification.new do |s|
|
|
53
53
|
s.add_development_dependency 'mocha', '~> 2.1'
|
54
54
|
s.add_development_dependency 'pry', '~> 0.15.0'
|
55
55
|
s.add_development_dependency 'rake', '~> 13.0'
|
56
|
-
s.add_development_dependency 'rubocop', '~> 1.
|
56
|
+
s.add_development_dependency 'rubocop', '~> 1.79.1'
|
57
57
|
s.add_development_dependency 'rubocop-minitest', '~> 0.38.0'
|
58
58
|
s.add_development_dependency 'rubocop-rake', '~> 0.7.0'
|
59
59
|
s.add_development_dependency 'rubocop-sequel', '~> 0.4.0'
|
60
60
|
s.add_development_dependency 'simplecov', '~> 0.22.0'
|
61
61
|
|
62
62
|
# Dependencies on optional libraries, used for unit tests & development
|
63
|
-
s.add_development_dependency 'oxidized-web', '~> 0.
|
63
|
+
s.add_development_dependency 'oxidized-web', '~> 0.17.1'
|
64
64
|
s.add_development_dependency 'sequel', '>= 5.63.0', '<= 5.94.0'
|
65
65
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oxidized
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.34.
|
4
|
+
version: 0.34.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Saku Ytti
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2025-
|
13
|
+
date: 2025-08-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: asetus
|
@@ -158,14 +158,14 @@ dependencies:
|
|
158
158
|
requirements:
|
159
159
|
- - "~>"
|
160
160
|
- !ruby/object:Gem::Version
|
161
|
-
version:
|
161
|
+
version: 4.17.0
|
162
162
|
type: :runtime
|
163
163
|
prerelease: false
|
164
164
|
version_requirements: !ruby/object:Gem::Requirement
|
165
165
|
requirements:
|
166
166
|
- - "~>"
|
167
167
|
- !ruby/object:Gem::Version
|
168
|
-
version:
|
168
|
+
version: 4.17.0
|
169
169
|
- !ruby/object:Gem::Dependency
|
170
170
|
name: slop
|
171
171
|
requirement: !ruby/object:Gem::Requirement
|
@@ -304,14 +304,14 @@ dependencies:
|
|
304
304
|
requirements:
|
305
305
|
- - "~>"
|
306
306
|
- !ruby/object:Gem::Version
|
307
|
-
version: 1.
|
307
|
+
version: 1.79.1
|
308
308
|
type: :development
|
309
309
|
prerelease: false
|
310
310
|
version_requirements: !ruby/object:Gem::Requirement
|
311
311
|
requirements:
|
312
312
|
- - "~>"
|
313
313
|
- !ruby/object:Gem::Version
|
314
|
-
version: 1.
|
314
|
+
version: 1.79.1
|
315
315
|
- !ruby/object:Gem::Dependency
|
316
316
|
name: rubocop-minitest
|
317
317
|
requirement: !ruby/object:Gem::Requirement
|
@@ -374,14 +374,14 @@ dependencies:
|
|
374
374
|
requirements:
|
375
375
|
- - "~>"
|
376
376
|
- !ruby/object:Gem::Version
|
377
|
-
version:
|
377
|
+
version: 0.17.1
|
378
378
|
type: :development
|
379
379
|
prerelease: false
|
380
380
|
version_requirements: !ruby/object:Gem::Requirement
|
381
381
|
requirements:
|
382
382
|
- - "~>"
|
383
383
|
- !ruby/object:Gem::Version
|
384
|
-
version:
|
384
|
+
version: 0.17.1
|
385
385
|
- !ruby/object:Gem::Dependency
|
386
386
|
name: sequel
|
387
387
|
requirement: !ruby/object:Gem::Requirement
|
@@ -440,6 +440,7 @@ files:
|
|
440
440
|
- docs/DeviceSimulation.md
|
441
441
|
- docs/Docker.md
|
442
442
|
- docs/Hooks.md
|
443
|
+
- docs/Inputs.md
|
443
444
|
- docs/Issues.md
|
444
445
|
- docs/Model-Notes/ADVA.md
|
445
446
|
- docs/Model-Notes/APC_AOS.md
|