oxidized 0.31.0 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -3
- data/.rubocop.yml +1 -2
- data/.rubocop_todo.yml +6 -6
- data/CHANGELOG.md +32 -0
- data/Dockerfile +5 -2
- data/Rakefile +28 -0
- data/docs/Configuration.md +14 -2
- data/docs/Creating-Models.md +52 -22
- data/docs/DeviceSimulation.md +184 -0
- data/docs/Hooks.md +5 -5
- data/docs/Issues.md +15 -9
- data/docs/Model-Notes/APC_AOS.md +29 -16
- data/docs/Model-Notes/FSOS.md +1 -0
- data/docs/ModelUnitTests.md +186 -0
- data/docs/Supported-OS-Types.md +3 -2
- data/examples/podman-compose/Makefile +1 -2
- data/{examples/device-simulation → extra}/device2yaml.rb +32 -12
- data/extra/gitdiff-msteams.sh +32 -5
- data/extra/nagios_check_failing_nodes.rb +1 -1
- data/extra/rest_client.rb +1 -1
- data/lib/oxidized/config.rb +1 -1
- data/lib/oxidized/input/ssh.rb +13 -5
- data/lib/oxidized/model/aos7.rb +2 -0
- data/lib/oxidized/model/aosw.rb +1 -1
- data/lib/oxidized/model/apc_aos.rb +1 -1
- data/lib/oxidized/model/arubainstant.rb +1 -1
- data/lib/oxidized/model/asa.rb +2 -1
- data/lib/oxidized/model/asyncos.rb +1 -1
- data/lib/oxidized/model/cumulus.rb +16 -2
- data/lib/oxidized/model/enterprise_sonic.rb +46 -0
- data/lib/oxidized/model/fsos.rb +5 -1
- data/lib/oxidized/model/garderos.rb +4 -4
- data/lib/oxidized/model/junos.rb +1 -1
- data/lib/oxidized/model/kornfeldos.rb +33 -0
- data/lib/oxidized/model/model.rb +2 -2
- data/lib/oxidized/model/sonicos.rb +8 -2
- data/lib/oxidized/model/tplink.rb +1 -0
- data/lib/oxidized/model/xos.rb +1 -1
- data/lib/oxidized/source/source.rb +32 -2
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +7 -6
- metadata +33 -35
- data/examples/device-simulation/README.md +0 -173
- data/examples/device-simulation/cmdsets/aoscx +0 -9
- data/examples/device-simulation/cmdsets/arubainstant +0 -5
- data/examples/device-simulation/cmdsets/asa +0 -7
- data/examples/device-simulation/cmdsets/ios +0 -7
- data/examples/device-simulation/cmdsets/nxos +0 -5
- data/examples/device-simulation/cmdsets/routeros +0 -5
- data/examples/device-simulation/cmdsets/srosmd +0 -11
- data/examples/device-simulation/yaml/aoscx_R0X25A-6410_FL.10.10.1100.yaml +0 -2281
- data/examples/device-simulation/yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml +0 -451
- data/examples/device-simulation/yaml/arubainstant_IAP515_8.10.0.6_VWLC.yaml +0 -213
- data/examples/device-simulation/yaml/asa_5512_9.12-4-67_single-context.yaml +0 -531
- data/examples/device-simulation/yaml/asr920_16.8.1b.yaml +0 -1122
- data/examples/device-simulation/yaml/garderos_R7709_003_006_068.yaml +0 -101
- data/examples/device-simulation/yaml/iosxe_C9200L-24P-4G_17.09.04a.yaml +0 -514
- data/examples/device-simulation/yaml/iosxe_C9800-L-F-K9_17.06.05.yaml +0 -417
- data/examples/device-simulation/yaml/riverbed_915.yaml +0 -123
- data/examples/device-simulation/yaml/routeros_CHR_7.10.1.yaml +0 -145
- data/examples/device-simulation/yaml/routeros_CHR_7.16.yaml +0 -79
- data/examples/device-simulation/yaml/routeros_L009UiGS_7.15.2.yaml +0 -353
data/docs/Model-Notes/FSOS.md
CHANGED
@@ -7,6 +7,7 @@ This has been tested against the following models and OS versions
|
|
7
7
|
|S3400-48T4SP |Version 2.0.2J Build 81736 |
|
8
8
|
|S3400-48T4SP |Version 2.0.2J Build 95262 |
|
9
9
|
|S3400-48T6SP |Version 2.2.0F Build 109661 |
|
10
|
+
|S3400-48T4SP |Version 2.0.2J Build 120538 |
|
10
11
|
|S3410-24TS-P |S3410_FSOS 11.4(1)B74S5 |
|
11
12
|
|S5850-48T4Q |Version 7.0.4.34 |
|
12
13
|
|S5800-48MBQ |Version 7.0.4.21 |
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# Model Unit Tests
|
2
|
+
Oxidized includes automated unit tests for its models, which require very little
|
3
|
+
effort to use. There are three different default unit tests for models:
|
4
|
+
- [Device Simulation](ModelUnitTests.md#device-simulation)
|
5
|
+
- [Device Prompt](ModelUnitTests.md#device-prompt)
|
6
|
+
- [Secrets](ModelUnitTests.md#secrets)
|
7
|
+
|
8
|
+
You only need to provide test files under [/spec/model/data](/spec/model/data),
|
9
|
+
and the tests will be run automatically with `rake test`. See
|
10
|
+
[CONTRIBUTING.md](/CONTRIBUTING.md) for explanations on how to set up a
|
11
|
+
development environment. In the following examples, we use
|
12
|
+
[Bundler](https://bundler.io/) and prefix all commands with `bundle exec`.
|
13
|
+
|
14
|
+
In addition, you can write [custom unit tests](ModelUnitTests.md#custom-tests)
|
15
|
+
for your model
|
16
|
+
|
17
|
+
## Device Simulation
|
18
|
+
### YAML Simulation File
|
19
|
+
You need a [YAML simulation file](/docs/DeviceSimulation.md) for your device.
|
20
|
+
See the link for instructions on how to produce it.
|
21
|
+
|
22
|
+
The YAML simulation files are stored under
|
23
|
+
[/spec/model/data/](/spec/model/data/), with the naming convention
|
24
|
+
`<model>:<description>:simulation.yaml`, where `<model>` is the lowercase name
|
25
|
+
of the Oxidized model and `<description>` is the name of the test case.
|
26
|
+
`<description>` is generally formatted as `<hardware>_<software>` or
|
27
|
+
`<hardware>_<software>_<information>`.
|
28
|
+
|
29
|
+
Using a correct name for the file is important to ensure it is included in
|
30
|
+
automatic model unit tests.
|
31
|
+
|
32
|
+
### Expected Output
|
33
|
+
You need a second file that contains the expected output, which has the same
|
34
|
+
name as the YAML simulation file but ends with `:output.txt` instead of
|
35
|
+
`:simulation.yaml`.
|
36
|
+
|
37
|
+
You can automatically produce an output file based on the current model for all
|
38
|
+
YAML simulation files missing an `:output.txt`:
|
39
|
+
```shell
|
40
|
+
bundle exec ruby spec/model/atoms_generate.rb
|
41
|
+
```
|
42
|
+
|
43
|
+
In the following example,
|
44
|
+
`spec/model/data/aoscx:R8N85A-C6000-48G-CL4_PL.10.08.1010:output.txt` (the
|
45
|
+
second file in the list) was missing:
|
46
|
+
|
47
|
+
```shell
|
48
|
+
oxidized$ bundle exec ruby spec/model/atoms_generate.rb
|
49
|
+
Run options: --seed 57811
|
50
|
+
|
51
|
+
# Running:
|
52
|
+
|
53
|
+
Generating output file for aoscx:R0X25A-6410_FL.10.10.1100:simulation... SKIP, output already exists
|
54
|
+
Generating output file for aoscx:R8N85A-C6000-48G-CL4_PL.10.08.1010:simulation... OK
|
55
|
+
Generating output file for arubainstant:IAP515_8.10.0.6_VWLC:simulation... SKIP, output already exists
|
56
|
+
Generating output file for asa:5512_9.12-4-67_single-context:simulation... SKIP, output already exists
|
57
|
+
Generating output file for garderos:R7709_003_006_068:simulation... SKIP, output already exists
|
58
|
+
Generating output file for ios:C8200L_16.12.1:simulation... FAIL, no simulation file
|
59
|
+
Generating output file for ios:C9200L-24P-4G_17.09.04a:simulation... SKIP, output already exists
|
60
|
+
Generating output file for ios:C9800-L-F-K9_17.06.05:simulation... SKIP, output already exists
|
61
|
+
Generating output file for ios:asr920_16.8.1b:simulation... SKIP, output already exists
|
62
|
+
Generating output file for junos:srx300_22.4:simulation... SKIP, output already exists
|
63
|
+
Generating output file for opnsense:nano_23.7:simulation... SKIP, output already exists
|
64
|
+
Generating output file for pfsense:CE_2.7.2:simulation... SKIP, output already exists
|
65
|
+
Generating output file for routeros:CHR_7.10.1:simulation... SKIP, output already exists
|
66
|
+
Generating output file for routeros:CHR_7.16:simulation... SKIP, output already exists
|
67
|
+
Generating output file for routeros:L009UiGS_7.15.2:simulation... SKIP, output already exists
|
68
|
+
.
|
69
|
+
|
70
|
+
Finished in 0.904792s, 1.1052 runs/s, 0.0000 assertions/s.
|
71
|
+
|
72
|
+
1 runs, 0 assertions, 0 failures, 0 errors, 0 skips
|
73
|
+
Coverage report generated for RSpec to /home/xxx/oxidized/coverage/coverage.xml. 651 / 1122 LOC (58.02%) covered
|
74
|
+
Coverage report generated for RSpec to /home/xxx/oxidized/coverage.
|
75
|
+
Line Coverage: 58.02% (651 / 1122)
|
76
|
+
```
|
77
|
+
|
78
|
+
### Running the Tests
|
79
|
+
You can modify the `:output.txt` file to match your expectations and modify the
|
80
|
+
model accordingly. Run `bundle exec rake` to run the tests.
|
81
|
+
|
82
|
+
Here is an example when the output of the VTP command is missing in the expected
|
83
|
+
output:
|
84
|
+
|
85
|
+
```
|
86
|
+
oxidized$ bundle exec rake test
|
87
|
+
/usr/bin/ruby3.1 -I"lib:spec" /home/xxx/oxidized/vendor/bundle/ruby/3.1.0/gems/rake-13.2.1/lib/rake/rake_test_loader.rb "spec/cli_spec.rb" "spec/config_spec.rb" "spec/hook/githubrepo_spec.rb" "spec/input/ssh_spec.rb" "spec/manager_spec.rb" "spec/model/apc_aos_spec.rb" "spec/model/model_atoms_spec.rb" "spec/model/model_helper_spec.rb" "spec/node_spec.rb" "spec/nodes_spec.rb" "spec/output/file_spec.rb" "spec/output/git_spec.rb" "spec/refinements_spec.rb" "spec/source/csv_spec.rb" "spec/source/http_spec.rb" "spec/source/jsonfile_spec.rb" "spec/source/sql_spec.rb"
|
88
|
+
Run options: --seed 31447
|
89
|
+
|
90
|
+
# Running:
|
91
|
+
|
92
|
+
...............................................................SS..................F.............................SS..
|
93
|
+
|
94
|
+
Finished in 7.963602s, 14.6918 runs/s, 48.7217 assertions/s.
|
95
|
+
|
96
|
+
1) Failure:
|
97
|
+
ATOMS tests#test_0006_ios:C9200L-24P-4G_17.09.04a:output has expected output [spec/model/model_atoms_spec.rb:12]:
|
98
|
+
--- expected
|
99
|
+
+++ actual
|
100
|
+
@@ -9,6 +9,21 @@
|
101
|
+
! CPU: ARM64
|
102
|
+
! Memory: nvram 2048K
|
103
|
+
!
|
104
|
+
+! VTP: VTP Version capable : 1 to 3
|
105
|
+
+! VTP: VTP version running : 1
|
106
|
+
+! VTP: VTP Domain Name : Oxidized
|
107
|
+
+! VTP: VTP Pruning Mode : Disabled (Operationally Disabled)
|
108
|
+
+! VTP: VTP Traps Generation : Disabled
|
109
|
+
+! VTP: Device ID : 40f0.7800.0000
|
110
|
+
+! VTP: Feature VLAN:
|
111
|
+
+! VTP: --------------
|
112
|
+
+! VTP: VTP Operating Mode : Transparent
|
113
|
+
+! VTP: Maximum VLANs supported locally : 1005
|
114
|
+
+! VTP: Number of existing VLANs : 10
|
115
|
+
+! VTP: Configuration Revision : 0
|
116
|
+
+! VTP: MD5 digest : 0x35 0x00 0x00 0x00 0x00 0x00 0x7F 0xB4
|
117
|
+
+! VTP: 0x07 0x00 0x00 0x00 0x00 0x00 0x09 0x6D
|
118
|
+
+!
|
119
|
+
! NAME: \"c92xxL Stack\", DESCR: \"c92xxL Stack\"
|
120
|
+
! PID: C9200L-24P-4G , VID: V01 , SN: JAE24FFFFFF
|
121
|
+
!
|
122
|
+
|
123
|
+
|
124
|
+
117 runs, 388 assertions, 1 failures, 0 errors, 4 skips
|
125
|
+
|
126
|
+
You have skipped tests. Run with --verbose for details.
|
127
|
+
Coverage report generated for RSpec to /home/xxx/oxidized/coverage/coverage.xml. 2167 / 3131 LOC (69.21%) covered
|
128
|
+
Coverage report generated for RSpec to /home/xxx/oxidized/coverage.
|
129
|
+
Line Coverage: 69.21% (2167 / 3131)
|
130
|
+
rake aborted!
|
131
|
+
Command failed with status (1): [ruby -I"lib:spec" /home/xxx/oxidized/vendor/bundle/ruby/3.1.0/gems/rake-13.2.1/lib/rake/rake_test_loader.rb "spec/cli_spec.rb" "spec/config_spec.rb" "spec/hook/githubrepo_spec.rb" "spec/input/ssh_spec.rb" "spec/manager_spec.rb" "spec/model/apc_aos_spec.rb" "spec/model/model_atoms_spec.rb" "spec/model/model_helper_spec.rb" "spec/node_spec.rb" "spec/nodes_spec.rb" "spec/output/file_spec.rb" "spec/output/git_spec.rb" "spec/refinements_spec.rb" "spec/source/csv_spec.rb" "spec/source/http_spec.rb" "spec/source/jsonfile_spec.rb" "spec/source/sql_spec.rb" ]
|
132
|
+
/home/xxx/oxidized/vendor/bundle/ruby/3.1.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
|
133
|
+
Tasks: TOP => test
|
134
|
+
(See full trace by running task with --trace)
|
135
|
+
```
|
136
|
+
|
137
|
+
If you want to be sure that your model has been tested, run
|
138
|
+
`bundle exec rake test TESTOPTS="--verbose"` and search for your models unter
|
139
|
+
`ATOMS tests`
|
140
|
+
|
141
|
+
## Device Prompt
|
142
|
+
You can specify device prompts to test in a YAML file named
|
143
|
+
`spec/model/data/<model>:generic:prompt.yaml`.
|
144
|
+
|
145
|
+
The YAML file has three sections containing a list of prompts to test:
|
146
|
+
- pass: these prompts will pass the prompt regexp.
|
147
|
+
- pass_with_expect: these prompts will pass the prompt regexp after having been
|
148
|
+
cleaned by the expect commands.
|
149
|
+
- fail: these prompts will fail the prompt regexp.
|
150
|
+
|
151
|
+
Here is an example:
|
152
|
+
```yaml
|
153
|
+
pass:
|
154
|
+
- "LAB-R1234_Garderos# "
|
155
|
+
pass_with_expect:
|
156
|
+
- "\e[4m\rLAB-R1234_Garderos#\e[m "
|
157
|
+
fail:
|
158
|
+
- "\e[4m\rLAB-R1234_Garderos#\e[m "
|
159
|
+
- "#LAB#"
|
160
|
+
```
|
161
|
+
|
162
|
+
## Secrets
|
163
|
+
You can test if the model effectively removes secrets from your YAML simulation
|
164
|
+
file with a YAML file named like the YAML simulation, but with the suffix
|
165
|
+
`:secret.yaml`.
|
166
|
+
|
167
|
+
The YAML file has two sections containing a list of strings to test:
|
168
|
+
- fail: the test will fail if the output contains these strings.
|
169
|
+
- pass: the test will pass only if the output contains these strings.
|
170
|
+
|
171
|
+
```yaml
|
172
|
+
fail:
|
173
|
+
- 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCC'
|
174
|
+
pass:
|
175
|
+
- 'snmp-server host 10.10.42.12 version 2c <secret removed> inform'
|
176
|
+
- 'hash-mgmt-user oxidized password hash <secret removed>'
|
177
|
+
- 'hash-mgmt-user rocks password hash <secret removed> usertype read-only'
|
178
|
+
```
|
179
|
+
|
180
|
+
## Custom tests
|
181
|
+
When you write custom tests for your models, please do not use the filenames
|
182
|
+
mentioned above, as it will interfere with the standard tests. If you need to
|
183
|
+
store a custom simulation file, use `model:description:custom_simulation.yaml`.
|
184
|
+
|
185
|
+
The [cumulus test](/spec/model/cumulus_spec.rb) is an example of a custom
|
186
|
+
test.
|
data/docs/Supported-OS-Types.md
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
|AddPack |AddPack |[addpack](/lib/oxidized/model/addpack.rb)
|
9
9
|
|Adtran |Total Access (AOS) |[adtran](/lib/oxidized/model/adtran.rb)
|
10
10
|
| |ADVA |[adva](/lib/oxidized/model/adva.rb) | |[ADVA](Model-Notes/ADVA.md)
|
11
|
-
|Alcatel-Lucent |AOS |[aos](/lib/oxidized/model/aos.rb)
|
12
|
-
| |AOS7 |[aos7](/lib/oxidized/model/aos7.rb)
|
11
|
+
|Alcatel-Lucent |AOS |[aos](/lib/oxidized/model/aos.rb) | |AOS6 - vxworks-based
|
12
|
+
| |AOS7 |[aos7](/lib/oxidized/model/aos7.rb) | |AOS7 and AOS8 - linux-based
|
13
13
|
| |ISAM |[isam](/lib/oxidized/model/isam.rb)
|
14
14
|
| |SR OS (Formerly TiMOS) |[sros](/lib/oxidized/model/sros.rb)
|
15
15
|
| |Wireless |[aosw](/lib/oxidized/model/aosw.rb) | |Same model as Aruba Wireless
|
@@ -175,6 +175,7 @@
|
|
175
175
|
| |NSX Distributed Firewall |[nsxdfw](/lib/oxidized/model/nsxdfw.rb)
|
176
176
|
|Watchguard |Fireware OS |[firewareos](/lib/oxidized/model/firewareos.rb)
|
177
177
|
|Westell |Westell 8178G, Westell 8266G |[weos](/lib/oxidized/model/weos.rb)
|
178
|
+
|Yadro |KornfeldOS |[kornfeldos](/lib/oxidized/model/kornfeldos.rb)
|
178
179
|
|YAMAHA |YAMAHA NVR/RTX Series |[yamaha](/lib/oxidized/model/yamaha.rb)
|
179
180
|
|Zhone |Zhone (OLT and MX) |[zhoneolt](/lib/oxidized/model/zhoneolt.rb)
|
180
181
|
|ZPE |Nodegrid OS |[nodegrid](/lib/oxidized/model/nodegrid.rb)
|
@@ -71,8 +71,7 @@ images: model-image gitserver-image oxidized-image
|
|
71
71
|
|
72
72
|
# build the oxidized image from the curent repository
|
73
73
|
oxidized-image:
|
74
|
-
|
75
|
-
podman build -t local/oxidized ../../
|
74
|
+
podman build -t oxidized:`git describe --tags` -t oxidized:latest ../../
|
76
75
|
|
77
76
|
# removes the oxidized image
|
78
77
|
oxidized-image-clean:
|
@@ -8,6 +8,7 @@ require 'timeout'
|
|
8
8
|
|
9
9
|
# This scripts logs in a network device and outputs a yaml file that can be
|
10
10
|
# used for model unit tests in spec/model/
|
11
|
+
# For more information, see docs/DeviceSimulation.md
|
11
12
|
|
12
13
|
# This script is quick & dirty - it grew with the time an could be a project
|
13
14
|
# for its own. It works, and that should be enough ;-)
|
@@ -113,15 +114,29 @@ end
|
|
113
114
|
# Define options
|
114
115
|
options = {}
|
115
116
|
optparse = OptionParser.new do |opts|
|
116
|
-
opts.banner =
|
117
|
+
opts.banner = <<~HEREDOC
|
118
|
+
Usages:
|
119
|
+
- device2yaml.rb [user@]host -i file [options]
|
120
|
+
- device2yaml.rb [user@]host -c "command1
|
121
|
+
command2
|
122
|
+
command3" [options]
|
117
123
|
|
118
|
-
|
119
|
-
|
124
|
+
-i and -c are mutualy exclusive, one must be specified
|
125
|
+
|
126
|
+
[options]:
|
127
|
+
HEREDOC
|
128
|
+
|
129
|
+
opts.on('-c', '--commands "command list"', 'specify the commands to be run') do |cmds|
|
130
|
+
options[:commands] = cmds
|
131
|
+
end
|
132
|
+
opts.on('-i', '--input file', 'Specify an input file for commands to be run') do |file|
|
133
|
+
options[:input] = file
|
120
134
|
end
|
121
135
|
opts.on('-o', '--output file', 'Specify an output YAML-file') do |file|
|
122
136
|
options[:output] = file
|
123
137
|
end
|
124
|
-
opts.on('-t', '--timeout value', Integer,
|
138
|
+
opts.on('-t', '--timeout value', Integer,
|
139
|
+
'Specify the idle timeout beween commands (default: 5 seconds)') do |timeout|
|
125
140
|
options[:timeout] = timeout
|
126
141
|
end
|
127
142
|
opts.on('-e', '--exec-mode', 'Run ssh in exec mode (without tty)') { @exec_mode = true }
|
@@ -151,14 +166,22 @@ end
|
|
151
166
|
optparse.parse!
|
152
167
|
|
153
168
|
# Get the commands to be run against ssh_host
|
154
|
-
|
155
|
-
|
169
|
+
# ^ = xor = exclusive or
|
170
|
+
unless options[:commands].nil? ^ options[:input].nil?
|
171
|
+
puts "Please provide commands to be run against #{ssh_host} with either option -c or -i"
|
156
172
|
puts
|
157
173
|
puts optparse
|
158
174
|
exit 1
|
159
175
|
end
|
160
|
-
|
161
|
-
|
176
|
+
|
177
|
+
if options[:commands]
|
178
|
+
ssh_commands = []
|
179
|
+
options[:commands].each_line(chomp: true) { |command| ssh_commands << command }
|
180
|
+
elsif options[:input]
|
181
|
+
ssh_commands = File.read(options[:input]).split(/\n+|\r+/)
|
182
|
+
end
|
183
|
+
|
184
|
+
puts "Running #{ssh_commands} on #{ssh_user}@#{ssh_host}"
|
162
185
|
|
163
186
|
# Defaut idle timeout: 5 seconds, as tests showed that 2 seconds is too short
|
164
187
|
@idle_timeout = options[:timeout] || 5
|
@@ -209,7 +232,7 @@ else
|
|
209
232
|
yaml_output ' '
|
210
233
|
end
|
211
234
|
|
212
|
-
@output&.puts
|
235
|
+
@output&.puts 'commands:'
|
213
236
|
|
214
237
|
begin
|
215
238
|
ssh_commands.each do |cmd|
|
@@ -219,7 +242,4 @@ rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError => e
|
|
219
242
|
puts "### Connection closed with message: #{e.message}"
|
220
243
|
end
|
221
244
|
|
222
|
-
@output&.puts 'oxidized_output: |'
|
223
|
-
@output&.puts ' !! needs to be written by hand or copy & paste from model output'
|
224
|
-
|
225
245
|
cleanup
|
data/extra/gitdiff-msteams.sh
CHANGED
@@ -15,12 +15,31 @@
|
|
15
15
|
# timeout: 120
|
16
16
|
#
|
17
17
|
# Add webhook to your MS Teams channel and set the next variable to the full url
|
18
|
+
# If INCLUDE_GITHUB_LINK is set to true, there will be a button that links to GITURL in the bottom of each teams post. the commit id is added at the end of the url.
|
19
|
+
# MAXSIZE is set to respect the 28 KB limit for teams webhooks, but you might need to change it if you modify the Adaptive Card
|
18
20
|
|
19
21
|
weburl="https://contoso.webhook.office.com/webhookb2/etc etc etc"
|
22
|
+
GITURL="https://github.example.com/My-org/oxidized/commit/"
|
23
|
+
INCLUDE_GITHUB_LINK=false
|
24
|
+
# Max size for summary text.
|
25
|
+
MAXSIZE=24500
|
26
|
+
|
27
|
+
if [ "$INCLUDE_GITHUB_LINK" = true ]; then
|
28
|
+
github_action=",
|
29
|
+
{ \"type\": \"ActionSet\",
|
30
|
+
\"actions\":
|
31
|
+
[
|
32
|
+
{
|
33
|
+
\"type\": \"Action.OpenUrl\",
|
34
|
+
\"title\": \"Click to see diff in github\",
|
35
|
+
\"url\": \"${GITURL}${OX_REPO_COMMITREF}\"
|
36
|
+
}
|
37
|
+
]
|
38
|
+
}"
|
39
|
+
fi
|
20
40
|
|
21
41
|
postdata()
|
22
42
|
{
|
23
|
-
COMMIT=$(git --bare --git-dir="${OX_REPO_NAME}" show --pretty='' --no-color "${OX_REPO_COMMITREF}" | jq --raw-input --slurp --compact-output)
|
24
43
|
cat <<EOF
|
25
44
|
{
|
26
45
|
"type":"message",
|
@@ -77,7 +96,7 @@ postdata()
|
|
77
96
|
"size": "small"
|
78
97
|
}
|
79
98
|
]
|
80
|
-
}
|
99
|
+
}${github_action}
|
81
100
|
]
|
82
101
|
}
|
83
102
|
}
|
@@ -86,6 +105,14 @@ postdata()
|
|
86
105
|
EOF
|
87
106
|
}
|
88
107
|
|
89
|
-
|
90
|
-
|
91
|
-
|
108
|
+
COMMIT=$(git --bare --git-dir="${OX_REPO_NAME}" show --pretty='' --no-color "${OX_REPO_COMMITREF}" | jq --raw-input --slurp --compact-output)
|
109
|
+
URL=""
|
110
|
+
|
111
|
+
size=$(postdata | wc -c)
|
112
|
+
if [ "$size" -gt "$MAXSIZE" ]; then
|
113
|
+
COMMIT=$(git --bare --git-dir="${OX_REPO_NAME}" show --pretty='' --no-color "${OX_REPO_COMMITREF}" | head -c $MAXSIZE)
|
114
|
+
COMMIT+="$NEWLINE...$NEWLINE Shortened because of length"
|
115
|
+
COMMIT=$(echo "${COMMIT}" | jq --raw-input --slurp --compact-output )
|
116
|
+
fi
|
117
|
+
|
118
|
+
curl -i -H "Content-Type: application/json" -X POST --data "$(postdata)" "${weburl}"
|
@@ -10,7 +10,7 @@ pending = false
|
|
10
10
|
critical_nodes = []
|
11
11
|
pending_nodes = []
|
12
12
|
|
13
|
-
json = JSON.parse(
|
13
|
+
json = JSON.parse(URI("http://localhost:8888/nodes.json").open(&:read))
|
14
14
|
json.each do |node|
|
15
15
|
next if !ARGV.empty? && (ARGV[0] != node['name'])
|
16
16
|
|
data/extra/rest_client.rb
CHANGED
@@ -6,7 +6,7 @@ module Oxidized
|
|
6
6
|
require 'asetus'
|
7
7
|
|
8
8
|
class Config
|
9
|
-
Root =
|
9
|
+
Root = ENV['OXIDIZED_HOME'] || File.join(Dir.home, '.config', 'oxidized')
|
10
10
|
end
|
11
11
|
|
12
12
|
CFGS = Asetus.new name: 'oxidized', load: false, key_to_s: true
|
data/lib/oxidized/config.rb
CHANGED
@@ -19,7 +19,7 @@ module Oxidized
|
|
19
19
|
cfgfile = cmd_opts[:config_file] || 'config'
|
20
20
|
# configuration file with full path as a class instance variable
|
21
21
|
@configfile = File.join(usrdir, cfgfile)
|
22
|
-
asetus = Asetus.new(name: 'oxidized', load: false,
|
22
|
+
asetus = Asetus.new(name: 'oxidized', load: false, usrdir: usrdir, cfgfile: cfgfile)
|
23
23
|
Oxidized.asetus = asetus
|
24
24
|
|
25
25
|
asetus.default.username = 'username'
|
data/lib/oxidized/input/ssh.rb
CHANGED
@@ -18,10 +18,14 @@ module Oxidized
|
|
18
18
|
|
19
19
|
def connect(node)
|
20
20
|
@node = node
|
21
|
-
@output = ''
|
21
|
+
@output = String.new('')
|
22
22
|
@pty_options = { term: "vt100" }
|
23
23
|
@node.model.cfg['ssh'].each { |cb| instance_exec(&cb) }
|
24
|
-
|
24
|
+
if Oxidized.config.input.debug?
|
25
|
+
logfile = Oxidized::Config::LOG + "/#{@node.ip}-ssh"
|
26
|
+
@log = File.open(logfile, 'w')
|
27
|
+
Oxidized.logger.debug "lib/oxidized/input/ssh.rb: I/O Debuging to #{logfile}"
|
28
|
+
end
|
25
29
|
|
26
30
|
Oxidized.logger.debug "lib/oxidized/input/ssh.rb: Connecting to #{@node.name}"
|
27
31
|
@ssh = Net::SSH.start(@node.ip, @node.auth[:username], make_ssh_opts)
|
@@ -41,7 +45,11 @@ module Oxidized
|
|
41
45
|
end
|
42
46
|
|
43
47
|
def cmd(cmd, expect = node.prompt)
|
44
|
-
Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd} @ #{node.name} with expect: #{expect.inspect}"
|
48
|
+
Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd.dump} @ #{node.name} with expect: #{expect.inspect}"
|
49
|
+
if Oxidized.config.input.debug?
|
50
|
+
@log.puts "sent #{cmd.dump}"
|
51
|
+
@log.flush
|
52
|
+
end
|
45
53
|
cmd_output = if @exec
|
46
54
|
@ssh.exec! cmd
|
47
55
|
else
|
@@ -78,7 +86,7 @@ module Oxidized
|
|
78
86
|
@ses = ssh.open_channel do |ch|
|
79
87
|
ch.on_data do |_ch, data|
|
80
88
|
if Oxidized.config.input.debug?
|
81
|
-
@log.
|
89
|
+
@log.puts "received #{data.dump}"
|
82
90
|
@log.flush
|
83
91
|
end
|
84
92
|
@output << data
|
@@ -101,7 +109,7 @@ module Oxidized
|
|
101
109
|
end
|
102
110
|
|
103
111
|
def cmd_shell(cmd, expect_re)
|
104
|
-
@output = ''
|
112
|
+
@output = String.new('')
|
105
113
|
@ses.send_data cmd + "\n"
|
106
114
|
@ses.process
|
107
115
|
expect expect_re if expect_re
|
data/lib/oxidized/model/aos7.rb
CHANGED
data/lib/oxidized/model/aosw.rb
CHANGED
@@ -117,7 +117,7 @@ class AOSW < Oxidized::Model
|
|
117
117
|
next if line =~ /Output \d Config/i
|
118
118
|
next if line =~ /(Tachometers|Temperatures|Voltages)/
|
119
119
|
next if line =~ /((Card|CPU) Temperature|Chassis Fan|VMON1[0-9])/
|
120
|
-
next if line =~ /[0-9]+\s+(RPMS?|m?V|C)/i
|
120
|
+
next if line =~ /[0-9]+\s+(RPMS?|m?V|C|W)/i
|
121
121
|
|
122
122
|
out << line.strip
|
123
123
|
end
|
data/lib/oxidized/model/asa.rb
CHANGED
@@ -15,7 +15,7 @@ class ASA < Oxidized::Model
|
|
15
15
|
cfg.gsub! /enable password (\S+) (.*)/, 'enable password <secret hidden> \2'
|
16
16
|
cfg.gsub! /^passwd (\S+) (.*)/, 'passwd <secret hidden> \2'
|
17
17
|
cfg.gsub! /username (\S+) password (\S+) (.*)/, 'username \1 password <secret hidden> \3'
|
18
|
-
cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key) (\S+)/, '\1 <secret hidden>'
|
18
|
+
cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key( hex)?) (\S+)/, '\1 <secret hidden>'
|
19
19
|
cfg.gsub! /^(aaa-server TACACS\+? \(\S+\) host[^\n]*\n(\s+[^\n]+\n)*\skey) \S+$/mi, '\1 <secret hidden>'
|
20
20
|
cfg.gsub! /^(aaa-server \S+ \(\S+\) host[^\n]*\n(\s+[^\n]+\n)*\s+key) \S+$/mi, '\1 <secret hidden>'
|
21
21
|
cfg.gsub! /ldap-login-password (\S+)/, 'ldap-login-password <secret hidden>'
|
@@ -38,6 +38,7 @@ class ASA < Oxidized::Model
|
|
38
38
|
cfg = cfg.join
|
39
39
|
cfg.gsub! /^Configuration has not been modified since last system restart.*\n/, ''
|
40
40
|
cfg.gsub! /^Configuration last modified by.*\n/, ''
|
41
|
+
cfg.gsub! /^Start-up time.*\n/, ''
|
41
42
|
comment cfg
|
42
43
|
end
|
43
44
|
|
@@ -1,7 +1,19 @@
|
|
1
1
|
class Cumulus < Oxidized::Model
|
2
2
|
using Refinements
|
3
3
|
|
4
|
-
|
4
|
+
# Remove ANSI escape codes
|
5
|
+
expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
|
6
|
+
data.gsub re, ''
|
7
|
+
end
|
8
|
+
|
9
|
+
# The prompt contains ANSI escape codes, which have already been removed
|
10
|
+
# from the expect call above
|
11
|
+
# ^ : match begin of line, to have the most specific prompt
|
12
|
+
# [\w.-]+@[\w.-]+ : user@hostname
|
13
|
+
# (:mgmt)? : optional when logged in out of band
|
14
|
+
# :~[#$] $ : end of prompt, containing the linux path,
|
15
|
+
# which is always "~" in our context
|
16
|
+
prompt /^[\w.-]+@[\w.-]+(:mgmt)?:~[#$] $/
|
5
17
|
comment '# '
|
6
18
|
|
7
19
|
# add a comment in the final conf
|
@@ -79,7 +91,9 @@ class Cumulus < Oxidized::Model
|
|
79
91
|
cfg += cmd 'cat /etc/cumulus/switchd.conf'
|
80
92
|
|
81
93
|
cfg += add_comment 'PORTS'
|
82
|
-
|
94
|
+
# in some configurations, ports.conf has no trailing Line Feed,
|
95
|
+
# which breaks the prompt, so we add one
|
96
|
+
cfg += cmd "cat /etc/cumulus/ports.conf; echo"
|
83
97
|
|
84
98
|
cfg += add_comment 'TRAFFIC'
|
85
99
|
cfg += cmd 'cat /etc/cumulus/datapath/traffic.conf'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Enterprise_SONiC < Oxidized::Model # rubocop:disable Naming/ClassAndModuleCamelCase
|
2
|
+
using Refinements
|
3
|
+
|
4
|
+
# Remove ANSI escape codes
|
5
|
+
expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
|
6
|
+
data.gsub re, ''
|
7
|
+
end
|
8
|
+
|
9
|
+
# Matches both sonic-cli and linux terminal
|
10
|
+
prompt /^(?:[\w.-]+@[\w.-]+:[~\w\/-]+\$|[\w.-]+#)\s*/
|
11
|
+
comment "# "
|
12
|
+
|
13
|
+
def add_comment(comment)
|
14
|
+
"\n##### #{comment} #####\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
post do
|
18
|
+
cmd 'show running-configuration' do |cfg|
|
19
|
+
add_comment('CONFIGURATION') + cfg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
cmd 'show version' do |cfg|
|
24
|
+
cfg = cfg.each_line.reject { |line| line.match /Uptime/ }.join
|
25
|
+
add_comment('VERSION') + cfg
|
26
|
+
end
|
27
|
+
|
28
|
+
cmd 'show platform syseeprom' do |cfg|
|
29
|
+
add_comment('SYSEEPROM') + cfg
|
30
|
+
end
|
31
|
+
|
32
|
+
cmd :all do |cfg|
|
33
|
+
cfg.cut_both
|
34
|
+
end
|
35
|
+
|
36
|
+
cfg :ssh do
|
37
|
+
# if user logs in to linux == has admin rights
|
38
|
+
if vars(:admin) == true
|
39
|
+
post_login do
|
40
|
+
cmd "sonic-cli\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
post_login 'terminal length 0'
|
44
|
+
pre_logout 'exit'
|
45
|
+
end
|
46
|
+
end
|
data/lib/oxidized/model/fsos.rb
CHANGED
@@ -2,6 +2,7 @@ class FSOS < Oxidized::Model
|
|
2
2
|
# Fiberstore / fs.com
|
3
3
|
using Refinements
|
4
4
|
comment '! '
|
5
|
+
prompt /^([\w.@()-]+[#>]\s?)$/
|
5
6
|
|
6
7
|
# Handle paging
|
7
8
|
expect /^ --More--.*$/ do |data, re|
|
@@ -13,6 +14,9 @@ class FSOS < Oxidized::Model
|
|
13
14
|
cfg.gsub! /(secret \w+) (\S+).*/, '\\1 <secret hidden>'
|
14
15
|
cfg.gsub! /(password \d+) (\S+).*/, '\\1 <secret hidden>'
|
15
16
|
cfg.gsub! /(snmp-server community \d+) (\S+).*/, '\\1 <secret hidden>'
|
17
|
+
cfg.gsub! /^(snmp-server host \S+( udp-port \d+)?( permit|deny \d+)?( informs?)?( traps?)?(( version v3 (priv|auth|noauth))|( version (v1|v2c))?)) +\S+( .*)?$*/, '\\1 <secret hidden>'
|
18
|
+
cfg.gsub! /^(snmp-server user \S+ \S+ v3( priv (des|aes128|aes256|aes256-c))?( auth (md5|sha|sha256) \d+)) +\S+( .*)?$*/, '\\1 <secret hidden>'
|
19
|
+
cfg.gsub! /^(.*key \d+) (\S+).*/, '\\1 <secret hidden>'
|
16
20
|
cfg
|
17
21
|
end
|
18
22
|
|
@@ -37,7 +41,7 @@ class FSOS < Oxidized::Model
|
|
37
41
|
cfg :telnet, :ssh do
|
38
42
|
post_login 'enable'
|
39
43
|
post_login 'terminal length 0'
|
40
|
-
post_login 'terminal width
|
44
|
+
post_login 'terminal width 512'
|
41
45
|
pre_logout 'exit'
|
42
46
|
pre_logout 'exit'
|
43
47
|
end
|
@@ -4,12 +4,12 @@ class Garderos < Oxidized::Model
|
|
4
4
|
# Routers for harsh environments
|
5
5
|
# grs = Garderos Router Software
|
6
6
|
|
7
|
-
#
|
8
|
-
|
9
|
-
expect /\e\[\d*m\r?/ do |data, re|
|
7
|
+
# Remove ANSI escape codes
|
8
|
+
expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
|
10
9
|
data.gsub re, ''
|
11
10
|
end
|
12
11
|
|
12
|
+
# the prompt does not need to match escape codes, as they have been removed above
|
13
13
|
prompt /[\w-]+# /
|
14
14
|
comment '# '
|
15
15
|
|
@@ -29,7 +29,7 @@ class Garderos < Oxidized::Model
|
|
29
29
|
# If we have a radio modem installed, we'd like to list the SIM Card
|
30
30
|
cmd 'show hardware wwan wwan0 sim' do |cfg|
|
31
31
|
if cfg.start_with? 'Unknown command'
|
32
|
-
''
|
32
|
+
String.new('')
|
33
33
|
else
|
34
34
|
comment "#{cfg}\n"
|
35
35
|
end
|