oxidized 0.35.0 → 0.37.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.coderabbit.yaml +21 -0
  3. data/.github/workflows/publishdocker.yml +11 -9
  4. data/.github/workflows/ruby.yml +1 -3
  5. data/.rubocop.yml +16 -2
  6. data/.rubocop_todo.yml +21 -2
  7. data/CHANGELOG.md +76 -3
  8. data/README.md +2 -3
  9. data/Rakefile +1 -1
  10. data/docs/Configuration.md +40 -2
  11. data/docs/Creating-Models.md +129 -14
  12. data/docs/Docker.md +2 -1
  13. data/docs/Hooks.md +92 -67
  14. data/docs/Inputs.md +44 -12
  15. data/docs/Model-Notes/APC.md +72 -0
  16. data/docs/Model-Notes/ExaLink.md +43 -0
  17. data/docs/Model-Notes/Fortinet.md +75 -0
  18. data/docs/Model-Notes/GrandstreamHT8xx.md +8 -0
  19. data/docs/Model-Notes/IvantiConnectSecure.md +59 -0
  20. data/docs/Model-Notes/RouterOS.md +13 -0
  21. data/docs/Model-Notes/TrueNAS.md +23 -0
  22. data/docs/ModelUnitTests.md +23 -0
  23. data/docs/Outputs.md +18 -4
  24. data/docs/Release.md +7 -2
  25. data/docs/Ruby-API.md +86 -5
  26. data/docs/Supported-OS-Types.md +21 -9
  27. data/docs/Troubleshooting.md +1 -1
  28. data/extra/device2yaml.rb +2 -3
  29. data/extra/hooks/modelrules.rb +55 -0
  30. data/extra/hooks/modelrulesadvanced.rb +167 -0
  31. data/extra/hooks/srcipmap.rb +54 -0
  32. data/lib/oxidized/cli/support.rb +152 -0
  33. data/lib/oxidized/cli.rb +9 -0
  34. data/lib/oxidized/hook/githubrepo.rb +2 -1
  35. data/lib/oxidized/hook.rb +58 -8
  36. data/lib/oxidized/input/debugtext.rb +40 -0
  37. data/lib/oxidized/input/debugyaml.rb +82 -0
  38. data/lib/oxidized/input/exec.rb +1 -10
  39. data/lib/oxidized/input/ftp.rb +0 -17
  40. data/lib/oxidized/input/http.rb +39 -21
  41. data/lib/oxidized/input/input.rb +33 -13
  42. data/lib/oxidized/input/scp.rb +10 -64
  43. data/lib/oxidized/input/ssh.rb +36 -79
  44. data/lib/oxidized/input/sshbase.rb +102 -0
  45. data/lib/oxidized/input/telnet.rb +12 -13
  46. data/lib/oxidized/input/tftp.rb +7 -7
  47. data/lib/oxidized/model/aoscx.rb +18 -12
  48. data/lib/oxidized/model/aosw.rb +10 -11
  49. data/lib/oxidized/model/apc_aos.rb +4 -0
  50. data/lib/oxidized/model/apcaos.rb +39 -0
  51. data/lib/oxidized/model/arubainstant.rb +11 -20
  52. data/lib/oxidized/model/asa.rb +7 -7
  53. data/lib/oxidized/model/comware.rb +3 -1
  54. data/lib/oxidized/model/cumulus.rb +3 -3
  55. data/lib/oxidized/model/defacto.rb +26 -0
  56. data/lib/oxidized/model/dlinknextgen.rb +1 -0
  57. data/lib/oxidized/model/dslcommands.rb +93 -0
  58. data/lib/oxidized/model/dslsetup.rb +102 -0
  59. data/lib/oxidized/model/efos.rb +5 -5
  60. data/lib/oxidized/model/exalink.rb +36 -0
  61. data/lib/oxidized/model/fastiron.rb +2 -2
  62. data/lib/oxidized/model/firelinuxos.rb +1 -3
  63. data/lib/oxidized/model/fortigate.rb +160 -0
  64. data/lib/oxidized/model/fortios.rb +28 -69
  65. data/lib/oxidized/model/fsos.rb +1 -3
  66. data/lib/oxidized/model/grandstreamht8xx.rb +19 -0
  67. data/lib/oxidized/model/h3c.rb +1 -1
  68. data/lib/oxidized/model/ios.rb +23 -15
  69. data/lib/oxidized/model/ironware.rb +5 -3
  70. data/lib/oxidized/model/ivanti.rb +54 -0
  71. data/lib/oxidized/model/junos.rb +2 -2
  72. data/lib/oxidized/model/linuxgeneric.rb +4 -2
  73. data/lib/oxidized/model/macros.rb +60 -0
  74. data/lib/oxidized/model/mlnxos.rb +11 -7
  75. data/lib/oxidized/model/model.rb +28 -126
  76. data/lib/oxidized/model/ndms.rb +6 -0
  77. data/lib/oxidized/model/netgear.rb +5 -3
  78. data/lib/oxidized/model/nxos.rb +6 -3
  79. data/lib/oxidized/model/outputs.rb +5 -0
  80. data/lib/oxidized/model/perle.rb +14 -8
  81. data/lib/oxidized/model/routeros.rb +4 -0
  82. data/lib/oxidized/model/smartbyte.rb +48 -0
  83. data/lib/oxidized/model/tplink.rb +4 -6
  84. data/lib/oxidized/model/truenas.rb +63 -3
  85. data/lib/oxidized/model/voss.rb +3 -0
  86. data/lib/oxidized/model/vyos.rb +4 -1
  87. data/lib/oxidized/node.rb +25 -23
  88. data/lib/oxidized/nodes.rb +2 -0
  89. data/lib/oxidized/output/file.rb +7 -1
  90. data/lib/oxidized/output/git.rb +11 -1
  91. data/lib/oxidized/output/gitcrypt.rb +1 -1
  92. data/lib/oxidized/output/http.rb +12 -3
  93. data/lib/oxidized/source/csv.rb +5 -0
  94. data/lib/oxidized/source/jsonfile.rb +5 -0
  95. data/lib/oxidized/source/sql.rb +5 -0
  96. data/lib/oxidized/version.rb +2 -2
  97. data/lib/oxidized/worker.rb +36 -15
  98. data/lib/refinements.rb +18 -0
  99. data/oxidized.gemspec +28 -24
  100. metadata +103 -55
  101. data/docs/Model-Notes/APC_AOS.md +0 -65
  102. data/docs/Model-Notes/FortiOS.md +0 -44
data/docs/Release.md CHANGED
@@ -61,7 +61,7 @@ They test different ruby versions an run security checks on the code (codeql).
61
61
  6. Install an test the gem locally
62
62
  ```shell
63
63
  gem install --user-install pkg/oxidized-0.xx.yy.gem
64
- ~/.local/share/gem/ruby/3.1.0/bin/oxidized
64
+ ~/.local/share/gem/ruby/3.3.0/bin/oxidized
65
65
  ```
66
66
 
67
67
  ## Release in github
@@ -71,9 +71,14 @@ git push origin 0.xx.yy
71
71
  ```
72
72
 
73
73
  Make a release from the tag in github.
74
- - Take the release notes frm CHANGELOG.md
74
+ - Name the release `0.xx.yy`
75
+ - Generate release notes
76
+ - Remove `## What's changed`
77
+ - Take the release notes from CHANGELOG.md
75
78
  - List new contributors (generated automatically)
76
79
  - Keep the Full Changelog (generated automatically)
80
+ - Preview
81
+ - Publish
77
82
 
78
83
  Close the corresponding milestone in github.
79
84
 
data/docs/Ruby-API.md CHANGED
@@ -10,11 +10,15 @@ The following objects exist in Oxidized.
10
10
  - [Model](#model)
11
11
  - [At the top level](#at-the-top-level)
12
12
  - [cfg](#cfg)
13
+ - [inputs](#inputs)
13
14
  - [cmd](#cmd)
14
15
  - [comment](#comment)
15
16
  - [prompt](#prompt)
16
17
  - [expect](#expect)
17
18
  - [pre / post](#pre--post)
19
+ - [macro :enable](#macro-enable)
20
+ - [clean :escape_codes](#clean-escape_codes)
21
+ - [clean :cut](#clean-cut)
18
22
  - [At the second level](#at-the-second-level)
19
23
  - [comment](#comment-1)
20
24
  - [password](#password)
@@ -26,9 +30,11 @@ The following objects exist in Oxidized.
26
30
  - [clear: true](#clear-true)
27
31
  - [prepend: true](#prepend-true)
28
32
  - [Refinements - String Convenience Methods](#refinements)
29
- - [cut_tail](#cut_tail)
30
- - [cut_head](#cut_head)
31
- - [cut_both](#cut_both)
33
+ - [cut_tail](#cut_tail)
34
+ - [cut_head](#cut_head)
35
+ - [cut_both](#cut_both)
36
+ - [keep_lines](#keep_lines)
37
+ - [reject_lines](#reject_lines)
32
38
 
33
39
  ## Input
34
40
 
@@ -87,6 +93,40 @@ The block may contain commands to change some behaviour for the given methods
87
93
 
88
94
  Supports [monkey patching](#monkey-patching).
89
95
 
96
+ #### 'inputs'
97
+ `inputs` can be used to specify multiple inputs to be run on the model. It
98
+ takes a list of either input symbols or lists of input symbols:
99
+ ```ruby
100
+ inputs [:ssh, %i[scp ftp]]
101
+ inputs [:ssh, :scp]
102
+ ```
103
+
104
+ Oxidized will run the model against each item of `inputs`. If an item is a
105
+ list of symbols (`%i[scp ftp]`), it will try each input in the order
106
+ configured in the `input/default` section of the oxidized configuration file.
107
+
108
+ If `inputs` is not specified, Oxidized will try each input that has a `cfg`
109
+ section in the model, in the order configured in the `input/default` section
110
+ of the oxidized configuration file.
111
+
112
+ To specify which command is to run against which input, use the `input`
113
+ parameter of the `cmd` configuration:
114
+ ```ruby
115
+ cmd 'upsabout', input: :ssh do |cfg|
116
+ comment cfg
117
+ end
118
+
119
+ cmd 'config.ini', input: %i[scp ftp] do |cfg|
120
+ "; ========== config.ini ==========\n" + cfg
121
+ end
122
+ ```
123
+
124
+ `cmd` without `input` parameter will run against every input.
125
+
126
+
127
+ See the [ApcAos model](/lib/oxidized/model/apcaos.rb) for a full example.
128
+
129
+
90
130
  #### `cmd`
91
131
 
92
132
  Is used to specify commands that should be executed on a model in order to
@@ -96,6 +136,7 @@ gather its configuration. It can be called with:
96
136
  * A string and a block
97
137
  * `:all` and a block
98
138
  * `:secret` and a block
139
+ * `:significant_changes` and a block
99
140
 
100
141
  The block takes a single parameter `cfg` containing the output of the command
101
142
  being processed.
@@ -116,14 +157,27 @@ given block before emitting it to hide secrets if secret hiding is enabled. The
116
157
  block should replace any secrets with `'<hidden>'` and return the resulting
117
158
  string.
118
159
 
160
+ Calling `cmd` with `:significant_changes` and a block will pass the final
161
+ configuration to the given block. The resulting string should contain
162
+ significant changes only and will be used to
163
+ [decide if the configuration should be stored](Configuration.md#store-configuration-only-on-significant-changes).
164
+
119
165
  Execution order is `:all`, `:secret`, and lastly the command specific block, if
120
166
  given.
121
167
 
122
- The `cmd "string"` method for accepts a lambda function via the `:if` argument
168
+ The `cmd "string"` method accepts a lambda function via the `:if` argument
123
169
  to execute the command only when the lambda evaluates to true.
124
170
  The lambda function is evaluated at runtime in the instance context.
125
171
  See [Conditional `cmd`](Creating-Models.md#conditional-cmd) for details.
126
172
 
173
+ The `cmd "string"` method accepts a list of supported inputs via the `:input`
174
+ argument to limit this command to specific inputs.
175
+ ```ruby
176
+ cmd 'config.ini', input: %i[scp ftp] do |cfg|
177
+ "; ========== config.ini ==========\n" + cfg
178
+ end
179
+ ```
180
+
127
181
  Supports [monkey patching](#monkey-patching).
128
182
 
129
183
  #### pre / post
@@ -167,6 +221,28 @@ it's further processed.
167
221
 
168
222
  Supports [monkey patching](#monkey-patching).
169
223
 
224
+ #### `macro :enable`
225
+ Implements an [handling of enable](Creating-Models.md#handling-enable-mode) for the model.
226
+
227
+ #### `clean :escape_codes`
228
+ [Remove ANSI escape codes](Creating-Models.md#remove-ansi-escape-codes) from the output.
229
+
230
+ #### `clean :cut`
231
+ Removes (default) the first and last line of the outputs (most of the time
232
+ command echo and prompt).
233
+ Arguments: head (default: 1), tail (default: 1)
234
+ ```ruby
235
+ clean :cut, head: 2, tail: 0
236
+ ```
237
+
238
+ Equivalent to:
239
+ ```ruby
240
+ cmd :all do |cfg|
241
+ cfg.cut_both(2, 0)
242
+ end
243
+ ```
244
+
245
+
170
246
  ### At the second level
171
247
 
172
248
  The following methods are available:
@@ -223,7 +299,6 @@ This functionality is supported by `cfg`, `cmd`, `pre_*`, `post_*`, and `expect`
223
299
  blocks.
224
300
 
225
301
  #### `clear: true`
226
-
227
302
  Resets the existing block, allowing the user to completely override its contents.
228
303
 
229
304
  #### `prepend: true`
@@ -253,3 +328,9 @@ single line was present.
253
328
 
254
329
  Returns a multi-line string without the first and last lines, or an empty string
255
330
  if fewer than three lines were present.
331
+
332
+ #### `keep_lines`
333
+ Returns a multi-line string with only the lines matching any pattern (String or Regexp) given in an array.
334
+
335
+ #### `reject_lines`
336
+ Returns a multi-line string without the lines matching any pattern (String or Regexp) given in an array.
@@ -2,6 +2,7 @@
2
2
 
3
3
  |Vendor |OS model |oxidized model |model maintainers|comment / model notes|
4
4
  |--------------------|------------------------------|-------------------------------------------------|-----------------|---------------------|
5
+ |-generic- |Cisco-like |[defacto](/lib/oxidized/model/defacto.rb) |@ytti, @robertcheramy|[The defacto model may work on cisco like CLIs](/docs/Creating-Models.md#use-the-defacto-model)|
5
6
  |6WIND |VSR |[sixwind](/lib/oxidized/model/sixwind.rb) |@hcaldicott |
6
7
  |A10 Networks |ACOS |[acos](/lib/oxidized/model/acos.rb) | |
7
8
  |Accedian Performance Elements (NIDs)|AEN |[aen](/lib/oxidized/model/aen.rb)
@@ -17,7 +18,7 @@
17
18
  |Allied Telesis |Alliedware Plus |[awplus](/lib/oxidized/model/awplus.rb)
18
19
  | |AT-8000S, AT-8000GS series |[powerconnect](/lib/oxidized/model/powerconnect.rb)
19
20
  |Alvarion |BreezeACCESS |[alvarion](/lib/oxidized/model/alvarion.rb)
20
- |APC |AOS |[apc_aos](/lib/oxidized/model/apc_aos.rb) |@robertcheramy |[APC AOS](Model-Notes/APC_AOS.md)
21
+ |APC |AOS |[apcaos](/lib/oxidized/model/apcaos.rb) |@robertcheramy |[APC](Model-Notes/APC.md)
21
22
  |Arbor Networks |ArbOS |[arbos](/lib/oxidized/model/arbos.rb) | |[ArbOS](Model-Notes/ArbOS.md)
22
23
  |Arista |EOS |[eos](/lib/oxidized/model/eos.rb) | |[EOS](Model-Notes/EOS.md)
23
24
  |Arris |C4CMTS |[c4cmts](/lib/oxidized/model/c4cmts.rb)
@@ -52,6 +53,7 @@
52
53
  | |AsyncOS |[asyncos](/lib/oxidized/model/asyncos.rb)
53
54
  | |CatOS |[catos](/lib/oxidized/model/catos.rb)
54
55
  | |Cisco Catalyst Express |[ciscoce](/lib/oxidized/model/ciscoce.rb)
56
+ | |ExaLink Fusion (Nexus 3550-F) |[exalink](/lib/oxidized/model/exalink.rb) |@obol89 |[ExaLink](Model-Notes/ExaLink.md)
55
57
  | |FireLinuxOS |[firelinuxos](/lib/oxidized/model/firelinuxos.rb)
56
58
  | |IOS |[ios](/lib/oxidized/model/ios.rb) |@robertcheramy |[IOS](Model-Notes/IOS.md)
57
59
  | |IOSXR |[iosxr](/lib/oxidized/model/iosxr.rb)
@@ -74,7 +76,7 @@
74
76
  |DELL |PowerConnect |[powerconnect](/lib/oxidized/model/powerconnect.rb)
75
77
  | |AOSW |[aosw](/lib/oxidized/model/aosw.rb) | |Same model as Aruba Wireless
76
78
  | |DellX |[dellx](/lib/oxidized/model/dellx.rb)
77
- | |Dell EMC Networking OS6 |[os6](/lib/oxidized/model/os6.rb) | |[Dell EMC Networking OS6](Model-Notes/OS6.md)
79
+ | |Dell EMC Networking OS6 |[os6](/lib/oxidized/model/os6.rb) | |[Dell EMC Networking OS6](Model-Notes/OS6.md)
78
80
  | |Dell EMC Networking OS10 |[os10](/lib/oxidized/model/os10.rb) | |[Dell EMC Networking OS10](Model-Notes/OS10.md)
79
81
  |D-Link |D-Link |[dlink](/lib/oxidized/model/dlink.rb)
80
82
  | |D-Link cisco like CLI |[dlinknextgen](/lib/oxidized/model/dlinknextgen.rb)
@@ -98,12 +100,15 @@
98
100
  |Firebrick |FBxxxx |[firebrick](/lib/oxidized/model/firebrick.rb)
99
101
  |Force10 |DNOS |[dnos](/lib/oxidized/model/dnos.rb)
100
102
  | |FTOS |[ftos](/lib/oxidized/model/ftos.rb)
101
- |FortiGate |FortiOS |[fortios](/lib/oxidized/model/fortios.rb) | |[FortiOS](Model-Notes/FortiOS.md)
102
- |FortiWLC |FortiWLC |[fortiwlc](/lib/oxidized/model/fortiwlc.rb)
103
+ |Fortinet |FortiGate |[fortigate](/lib/oxidized/model/fortigate.rb) |@robertcheramy |[Fortinet](Model-Notes/Fortinet.md)
104
+ | |FortiOS |[fortios](/lib/oxidized/model/fortios.rb) |@robertcheramy |[Fortinet](Model-Notes/Fortinet.md)
105
+ | |FortiWLC |[fortiwlc](/lib/oxidized/model/fortiwlc.rb)
103
106
  |Fujitsu |PRIMERGY Blade switch 1/10Gbe |[fujitsupy](/lib/oxidized/model/fujitsupy.rb)
104
107
  | |1FINITY Switches |[onefinity](/lib/oxidized/model/onefinity.rb)
108
+ |[Garderos](https://garderos.com/) |GRS (Garderos Router Software) |[garderos](/lib/oxidized/model/garderos.rb) | @robertcheramy |Routers for harsh environments
105
109
  |GCOM Technologies |Broadband Network Platform Software|[gcombnps](/lib/oxidized/model/gcombnps.rb)
106
110
  |Grandstream Networks|GSX |[grandstream](/lib/oxidized/model/grandstream.rb)
111
+ | |HT8xx |[grandstream](/lib/oxidized/model/grandstreamht8xx.rb) | @mklopocki | [Grandstream](Model-Notes/GrandstreamHT8xx.md)
107
112
  |Hatteras |Hatteras |[hatteras](/lib/oxidized/model/hatteras.rb)
108
113
  |Hillstone Networks |StoneOS |[stoneos](/lib/oxidized/model/stoneos.rb)
109
114
  |Hirschmann |Classic |[hirschmann](/lib/oxidized/model/hirschmann.rb)
@@ -119,6 +124,7 @@
119
124
  |Icotera |6400 series |[icotera](/lib/oxidized/model/icotera.rb)
120
125
  |Ingate |SIParator/Firewalls |[ingate](/lib/oxidized/model/ingate.rb) |@thanegill
121
126
  |IP Infusion |OcNOS |[ocnos](/lib/oxidized/model/ocnos.rb)
127
+ |Ivanti |Ivanti Connect Secure (ICS) |[ivanti](/lib/oxidized/model/ivanti.rb) |@candleflip |[ICS](Model-Notes/IvantiConnectSecure.md)
122
128
  |Juniper |JunOS |[junos](/lib/oxidized/model/junos.rb) | |[MX/QFX/EX/SRX/J Series](Model-Notes/JunOS.md)
123
129
  | |ScreenOS (Netscreen) |[screenos](/lib/oxidized/model/screenos.rb)
124
130
  |LANCOM Systems GmbH |LCOS |[lancom](/lib/oxidized/model/lancom.rb)
@@ -127,7 +133,7 @@
127
133
  |Linuxgeneric |CentOS |[linuxgeneric](/lib/oxidized/model/linuxgeneric.rb)| |[LinuxGeneric](Model-Notes/LinuxGeneric.md)
128
134
  |Mellanox |MLNX-OS |[mlnxos](/lib/oxidized/model/mlnxos.rb)
129
135
  | |Voltaire |[voltaire](/lib/oxidized/model/voltaire.rb)
130
- |Mikrotik |RouterOS |[routeros](/lib/oxidized/model/routeros.rb) | |[RouterOS](Model-Notes/RouterOS.md)
136
+ |Mikrotik |RouterOS |[routeros](/lib/oxidized/model/routeros.rb) | |[RouterOS](Model-Notes/RouterOS.md)
131
137
  | |SwOS and SwOS Lite |[swos](/lib/oxidized/model/swos.rb)
132
138
  |Mimosa |Mimosa (B11) |[mimosab11](/lib/oxidized/model/mimosab11.rb)
133
139
  |Motorola |RFS |[mtrlrfs](/lib/oxidized/model/mtrlrfs.rb)
@@ -138,6 +144,7 @@
138
144
  |Netgear |Netgear switches |[netgear](/lib/oxidized/model/netgear.rb) | |[Netgear](Model-Notes/Netgear.md)
139
145
  |Netonix |WISP Switch (As Netonix) |[netonix](/lib/oxidized/model/netonix.rb)
140
146
  |Nokia (formerly TiMetra, Alcatel, Alcatel-Lucent)|SR OS (TiMOS)|[sros](/lib/oxidized/model/sros.rb) | |[Nokia ISAM](Model-Notes/Nokia.md)
147
+ | |SR OS Model-Driven CLI (7705 SAR, 7210 SAS, 7450 ESS, 7750 SR, 7950 XRS, NSP) |[srosmd](/lib/oxidized/model/srosmd.rb) | |
141
148
  |OneAccess |OneOS |[oneos](/lib/oxidized/model/oneos.rb)
142
149
  | |TDRE |[tdre](/lib/oxidized/model/tdre.rb)
143
150
  |OpenBSD | |[openbsd](/lib/oxidized/model/openbsd.rb)
@@ -152,13 +159,16 @@
152
159
  |Pure Storage |PurityOS |[purityos](/lib/oxidized/model/purityos.rb)
153
160
  |Radware |AlteonOS |[alteonos](/lib/oxidized/model/alteonos.rb)
154
161
  |Raisecom |Raisecom |[raisecom](/lib/oxidized/model/raisecom.rb)
162
+ |Riverbed |SteelHead |[riverbed](/lib/oxidized/model/riverbed.rb)
155
163
  |Ruijie Networks |RGOS |[rgos](/lib/oxidized/model/rgos.rb)
156
164
  |QTECH |QSW-2800, QSW-3400, QSW-3450, QSW-3500|[qtech](/lib/oxidized/model/qtech.rb)
157
165
  |Quanta |Quanta / VxWorks 6.6 (1.1.0.8)|[quantaos](/lib/oxidized/model/quantaos.rb)
158
166
  |Siklu |EtherHaul |[siklu](/lib/oxidized/model/siklu.rb) |@bdg-robert
159
167
  | |Multihaul TG |[siklumhtg](/lib/oxidized/model/siklumhtg.rb) |@bdg-robert |[Siklu Multihaul TG](Model-Notes/SikluMHTG.md)
160
168
  |Seiko Solutions |SmartCS, SmartCS mini |[smartcs](/lib/oxidized/model/smartcs.rb)
169
+ |SmartByte |LT-S8228G series |[smartbyte](/lib/oxidized/model/smartbyte.rb) |@freddy36
161
170
  |SonicWALL |SonicOS |[sonicos](/lib/oxidized/model/sonicos.rb)
171
+ |[SONiC](https://sonicfoundation.dev/) |Enterprise SONiC |[enterprise_sonic](/lib/oxidized/model/enterprise_sonic.rb) | |
162
172
  |SNR |SNR-S300G, S2xxx, S3xxx, S4xxx|[dcnos](/lib/oxidized/model/dcnos.rb)
163
173
  |Speedtouch |Thomson Speedtouch |[speedtouch](/lib/oxidized/model/speedtouch.rb)
164
174
  |Supermicro |SSE-G2252, G2252P |[edgecos](/lib/oxidized/model/edgecos.rb)
@@ -176,14 +186,14 @@
176
186
  | |Edgeos |[edgeos](/lib/oxidized/model/edgeos.rb)
177
187
  | |EdgeSwitch |[edgeswitch](/lib/oxidized/model/edgeswitch.rb)
178
188
  | |AirFiber |[airfiber](/lib/oxidized/model/airfiber.rb)
179
- | |UnifiAP |[unifiap](/lib/oxidized/model/unifiap.rb) |@clifcox |Also suports AirOS, and some Unifi switches
180
- |Uplink |EP4440-DP |[EP4440](/lib/oxidized/model/uplinkolt.rb) | |Might support all EP4440 series
189
+ | |UnifiAP |[unifiap](/lib/oxidized/model/unifiap.rb) |@clifcox |Also suports AirOS, and some Unifi switches
190
+ |Uplink |EP4440-DP |[EP4440](/lib/oxidized/model/uplinkolt.rb) | |Might support all EP4440 series
181
191
  |VMWare |NSX Edge (configuration) |[nsxconfig](/lib/oxidized/model/nsxconfig.rb)
182
192
  | |NSX Edge (firewall rules) |[nsxfirewall](/lib/oxidized/model/nsxfirewall.rb)
183
193
  | |NSX Distributed Firewall |[nsxdfw](/lib/oxidized/model/nsxdfw.rb)
184
- |VYOS Networks |VYOS |[vyos](/lib/oxidized/model/vyos.rb)
185
- | |Fork of Vyatta, tracking the supported versions (>= 1.4.x)
194
+ |VYOS Networks |VYOS |[vyos](/lib/oxidized/model/vyos.rb) | |Fork of Vyatta, tracking the supported versions (>= 1.4.x)
186
195
  |Watchguard |Fireware OS |[firewareos](/lib/oxidized/model/firewareos.rb)
196
+ |Waystream (PacketFront)|iBOS (Intelligent Broadband OS)|[ibos](/lib/oxidized/model/ibos.rb)
187
197
  |Westell |Westell 8178G, Westell 8266G |[weos](/lib/oxidized/model/weos.rb)
188
198
  |Yadro |KornfeldOS |[kornfeldos](/lib/oxidized/model/kornfeldos.rb)
189
199
  |YAMAHA |YAMAHA NVR/RTX Series |[yamaha](/lib/oxidized/model/yamaha.rb)
@@ -193,5 +203,7 @@
193
203
  |Zyxel |ZyNOS |[zynos](/lib/oxidized/model/zynos.rb) | |[XGS4600 Series](Model-Notes/XGS4600-Zyxel.md)
194
204
  | |ZyNOS GS-series variant |[zynosgs](/lib/oxidized/model/zynosgs.rb)
195
205
  | |ZyNOS ADSL |[zynosadsl](/lib/oxidized/model/zynosadsl.rb)
206
+ | |ZyNOS CLI (DSLAMs, e.g. SAM1316)|[zynoscli](/lib/oxidized/model/zynoscli.rb)
207
+ | |ZyNOS MGS series |[zynosmgs](/lib/oxidized/model/zynosmgs.rb)
196
208
  | |NDMS |[ndms](/lib/oxidized/model/ndms.rb)
197
209
  | |1308 |[zy1308](/lib/oxidized/model/zy1308.rb)
@@ -86,7 +86,7 @@ ssh-keyscan gitserver.git.com >> ~/.ssh/known_hosts
86
86
 
87
87
  If you are running oxidized in a container, you need to map /home/oxidized/.ssh in the
88
88
  container to a local repository and save the known_hosts in the local repository. You can
89
- find an example how to do this under [examples/podman-compose](/examples/podman-compose/)
89
+ find an example how to do this under [Docker.md](Docker.md#store-the-ssh-keys-a-remote-git-repository)
90
90
 
91
91
  ## Oxidized ignores the changes I made to its git repository
92
92
  First of all: you shouldn't manipulate the git repository of oxidized. Don't
data/extra/device2yaml.rb CHANGED
@@ -91,9 +91,8 @@ def yaml_output(prepend = '')
91
91
 
92
92
  prepend = @sequence_prepend_output + prepend
93
93
 
94
- # as we want to prepend 'prepend' to each line, we need each_line and chomp
95
- # chomp removes the trainling \n
96
- @ssh_output.each_line(chomp: true) do |line|
94
+ # each_line(chomp: true) would remove \r\n, so we prefer split
95
+ @ssh_output.split("\n", -1).each do |line|
97
96
  # encode line and remove the first and the trailing double quote
98
97
  line = line.dump[1..-2]
99
98
  if firstline
@@ -0,0 +1,55 @@
1
+ ### script in ~/config/oxidized/hook/modelrules.rb ## or OXDIZED_HOME equivalent
2
+ ###
3
+ ### router.db:
4
+ ### router1:1.1.1.1:routeros::mikrotik
5
+ ### router2:2.2.2.2:ios:switch:cisco
6
+ ### router3:3.3.3.3:routeros:switch:mikrotik
7
+ ###
8
+ ### config:
9
+ ### source:
10
+ ### default: csv
11
+ ### csv:
12
+ ### file: "/Users/ytti/.config/oxidized/router.db"
13
+ ### delimiter: !ruby/regexp /:/
14
+ ### map:
15
+ ### name: 0
16
+ ### ip: 1
17
+ ### model: 2
18
+ ### group: 3
19
+ ### hooks:
20
+ ### somename:
21
+ ### type: modelrules
22
+ ### events: ["source_node_transform"]
23
+ ### rules:
24
+ ### - vendor: mikrotik
25
+ ### group: switch
26
+ ### model: eltex
27
+ ###
28
+ ### Nodes BEFORE script:
29
+ ### {name: "router1", ip: "1.1.1.1", model: "routeros", group: ""}
30
+ ### {name: "router2", ip: "2.2.2.2", model: "ios", group: "switch"}
31
+ ### {name: "router3", ip: "3.3.3.3", model: "routeros", group: "switch"}
32
+ ###
33
+ ### Nodes AFTER script:
34
+ ### {name: "router1", ip: "1.1.1.1", model: "routeros", group: ""}
35
+ ### {name: "router2", ip: "2.2.2.2", model: "ios", group: "switch"}
36
+ ### {name: "router3", ip: "3.3.3.3", model: "eltex", group: "switch"}
37
+ class ModelRules < Oxidized::Hook
38
+ def validate_cfg!
39
+ raise KeyError, 'hook.rules is required' unless cfg.has_key?('rules')
40
+ end
41
+
42
+ def run_hook(ctx)
43
+ # node is the node[key] that we'd return without manipulation
44
+ node = ctx.node ## e.g. node[:ip], node[:model] - what ever config maps
45
+
46
+ ## node_raw is source specific, in CSV it is just the field number, in HTTP it is JSON
47
+ vendor = ctx.node_raw[4]
48
+
49
+ cfg.rules.each do |rule|
50
+ node[:model] = rule['model'] if node[:group] == rule['group'] && vendor == rule['vendor']
51
+ end
52
+
53
+ node
54
+ end
55
+ end
@@ -0,0 +1,167 @@
1
+ # Advanced dynamic model selection hook for Oxidized
2
+ # --------------------------------------------------
3
+ # This hook allows you to assign Oxidized models based on any device attributes
4
+ # (name, vendor, group, type, IP, etc.) using flexible rules defined in the config.
5
+ # It uses the `source_node_transform` event and works with any source (CSV, HTTP, SQL).
6
+ #
7
+ # The hook is designed to be generic: you can specify any field that exists in the
8
+ # node data after source mapping (see `map` section in the source configuration).
9
+ # Rules are evaluated in order; the first matching rule assigns its `model`.
10
+ #
11
+ # ⚠️ IMPORTANT: For the hook to load correctly:
12
+ # - The filename must match the hook type (e.g., `modelrulesadvanced.rb`).
13
+ # - The class name must be the CamelCase version of the filename without underscores
14
+ # (e.g., filename `modelrulesadvanced.rb` → class `Modelrulesadvanced`).
15
+ # - In the Oxidized config, specify `type: modelrulesadvanced` (the filename without .rb).
16
+ #
17
+ # ⚠️ DOCKER NOTE: This hook was developed and tested in a Docker container.
18
+ # Ensure that your hooks directory inside the container is
19
+ # `/home/oxidized/.config/oxidized/hook` (singular "hook"), not "hooks".
20
+ # In docker-compose, mount your local hooks folder to this path, e.g.:
21
+ # volumes:
22
+ # - ./extra/hooks:/home/oxidized/.config/oxidized/hook
23
+ #
24
+ # Example scenario with NetBox:
25
+ # Suppose your NetBox instance returns devices with the following data (simplified):
26
+ # gw-001 | Mikrotik | RB750 | ro_ud | 192.168.0.167/24
27
+ # gw-002 | Mikrotik | RB750 | ro_ud | 192.168.0.177/24
28
+ # gw-003 | Mikrotik | RB750 | ro_bd | 192.168.0.178/24
29
+ # gw-004 | Mikrotik | RB750 | switch | 192.168.0.181/24
30
+ # gw-005 | Cisco | 2960 | switch | 192.168.0.179/24
31
+ # gw-006 | Mikrotik | RB750 | switch | 192.168.0.180/24
32
+ # gw-007 | Arista | 3456 | ro_ud | 192.168.0.190/24
33
+ #
34
+ # Desired model assignment:
35
+ # - gw-001 (exception by name) → asa
36
+ # - MikroTik in group `switch` with IP 192.168.0.180/24 → eltex
37
+ # - All other MikroTik → routeros
38
+ # - Cisco switches → ios
39
+ # - Arista devices → eos
40
+ #
41
+ # Example configuration (top-level in Oxidized config):
42
+ # ---
43
+ # username: oxidized_ssh_user
44
+ # password: oxidized_ssh_password
45
+ #
46
+ # hooks:
47
+ # modelrulesadvanced:
48
+ # type: modelrulesadvanced
49
+ # events: [source_node_transform]
50
+ # rules:
51
+ # - description: "Exception: gw-001 uses ASA model"
52
+ # name: gw-001
53
+ # model: asa
54
+ # - description: "Mikrotik switch with IP 192.168.0.180/24 uses eltex"
55
+ # vendor: Mikrotik
56
+ # group: switch
57
+ # ip: 192.168.0.180/24
58
+ # model: eltex
59
+ # - description: "All other Mikrotik devices"
60
+ # vendor: Mikrotik
61
+ # model: routeros
62
+ # - description: "Cisco switches"
63
+ # vendor: Cisco
64
+ # group: switch
65
+ # model: ios
66
+ # - description: "Arista devices"
67
+ # vendor: Arista
68
+ # model: eos
69
+ #
70
+ # resolve_dns: false
71
+ # interval: 3600
72
+ # rest: 0.0.0.0:8888
73
+ # debug: true # optional – enables detailed logging from the hook
74
+ #
75
+ # source:
76
+ # default: http
77
+ # http:
78
+ # url: http://netbox.test/api/dcim/devices/?status=active&has_primary_ip=true
79
+ # headers:
80
+ # Authorization: Token YOUR_API_TOKEN
81
+ # map:
82
+ # name: name
83
+ # vendor: device_type.manufacturer.name
84
+ # type: device_type.model
85
+ # group: role.slug
86
+ # ip: primary_ip.address
87
+ # secure: false
88
+ # hosts_location: results
89
+ # pagination: true
90
+ # pagination_key_name: next
91
+ #
92
+ # output:
93
+ # default: file
94
+ # file:
95
+ # directory: "/home/oxidized/.config/oxidized/configs"
96
+ #
97
+ # groups:
98
+ # ro_ud: {}
99
+ # ro_bd: {}
100
+ # switch: {}
101
+ #
102
+ # How it works:
103
+ # 1. Oxidized loads node data from the source (NetBox) and applies the `map`.
104
+ # 2. For each node, the `source_node_transform` event is triggered.
105
+ # 3. This hook receives a context object `ctx` containing:
106
+ # - `ctx.node` – the mapped node attributes (hash)
107
+ # - `ctx.node_raw` – the original source record (useful for unmapped fields)
108
+ # 4. The hook iterates through the rules defined in `cfg.rules`.
109
+ # 5. For each rule, it checks that every specified key (except `model` and `description`)
110
+ # matches the corresponding value in `ctx.node`. Comparison is case‑insensitive and
111
+ # strips surrounding spaces.
112
+ # 6. The first matching rule assigns its `model` to `ctx.node[:model]`.
113
+ # 7. If no rule matches, the node's `model` remains unchanged.
114
+ # 8. The modified (or original) node is returned; returning `nil` would exclude the node.
115
+ #
116
+ # Notes:
117
+ # - Rule order is crucial: place more specific rules (e.g., with IP or name) before generic ones.
118
+ # - The `description` field is optional and only appears in debug logs.
119
+ # - Any field present in `ctx.node` after mapping can be used as a match key.
120
+ # - For HTTP sources (NetBox), you can access additional fields via `ctx.node_raw["field"]`.
121
+ # - Debug logging requires `debug: true` in the global config.
122
+
123
+ class Modelrulesadvanced < Oxidized::Hook
124
+ # Validate that the hook configuration contains a 'rules' array.
125
+ def validate_cfg!
126
+ raise KeyError, "hook.rules is required" unless cfg.has_key?("rules")
127
+ end
128
+
129
+ # Main hook method – called for each node during source_node_transform event.
130
+ def run_hook(ctx)
131
+ node = ctx.node
132
+ rules = cfg.rules || []
133
+
134
+ matched_model = nil
135
+ rules.each_with_index do |rule, idx|
136
+ match = true
137
+ rule.each do |key, value|
138
+ next if %w[model description].include?(key)
139
+
140
+ # Retrieve the corresponding value from the node (symbol or string key)
141
+ node_value = node[key.to_sym] || node[key.to_s]
142
+ if node_value.to_s.strip.downcase != value.to_s.strip.downcase
143
+ match = false
144
+ break
145
+ end
146
+ end
147
+ next unless match
148
+
149
+ matched_model = rule["model"]
150
+ desc = rule["description"] ? " (#{rule['description']})" : ""
151
+ logger.debug "ModelRulesAdvanced: rule #{idx + 1}#{desc} matched -> #{matched_model}"
152
+ break
153
+ end
154
+
155
+ if matched_model
156
+ old_model = node[:model] || node["model"]
157
+ node[:model] = matched_model
158
+ logger.debug "ModelRulesAdvanced: changed model from #{old_model.inspect} to #{matched_model.inspect}"
159
+ else
160
+ # rubocop:disable Layout/LineLength
161
+ logger.debug "ModelRulesAdvanced: no rule matched, keeping existing model: #{node[:model] || node['model'].inspect}"
162
+ # rubocop:enable Layout/LineLength
163
+ end
164
+
165
+ node
166
+ end
167
+ end
@@ -0,0 +1,54 @@
1
+ ### script in ~/config/oxidized/hook/srcipmap.rb ## or OXDIZED_HOME equivalent
2
+ ###
3
+ ### router.db:
4
+ ### router1:1.1.1.1:cisco:c7200:10.10.10.1:somerole
5
+ ### router2:2.2.2.2:juniper:mx80:10.10.10.2:wlc
6
+ ### router3:3.3.3.3:juniper:mx2020:10.10.10.3:anotherrole
7
+ ###
8
+ ### config:
9
+ ### source:
10
+ ### default: csv
11
+ ### csv:
12
+ ### file: "/Users/ytti/.config/oxidized/router.db"
13
+ ### delimiter: !ruby/regexp /:/
14
+ ### map:
15
+ ### name: 0
16
+ ### ip: 1
17
+ ### model: 2
18
+ ### model_map:
19
+ ### juniper: junos
20
+ ### cisco: ios
21
+ ### hooks:
22
+ ### somename:
23
+ ### type: srcipmap
24
+ ### events: ["source_node_transform"]
25
+ ###
26
+ ###
27
+ ###
28
+ ### Nodes BEFORE script:
29
+ ### {name: "router1", ip: "1.1.1.1", model: "ios"}
30
+ ### {name: "router2", ip: "2.2.2.2", model: "junos"}
31
+ ### {name: "router3", ip: "3.3.3.3", model: "junos"
32
+ ###
33
+ ### Nodes AFTER script:
34
+ ### {name: "router1", ip: "1.1.1.1", model: "ios"}
35
+ ### {name: "router2", ip: "10.10.10.2", model: "junos"}
36
+ ### {name: "router3", ip: "3.3.3.3", model: "junos"}
37
+
38
+ class SrcIpMap < Oxidized::Hook
39
+ def run_hook(ctx)
40
+ # node is the node[key] that we'd return without manipulation
41
+ node = ctx.node
42
+
43
+ ## node_raw is source specific, in CSV it is just the field number
44
+ _platform = ctx.node_raw[3]
45
+ oob_ip = ctx.node_raw[4]
46
+ role = ctx.node_raw[5]
47
+
48
+ ### the magic
49
+ node[:ip] = oob_ip if role == 'wlc'
50
+
51
+ ### remember to return the manipulated object, nil if you want to ignore loading node
52
+ node
53
+ end
54
+ end