oxidized 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +5 -5
  2. data/.github/no-response.yml +13 -0
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +37 -0
  5. data/.rubocop_todo.yml +714 -0
  6. data/.travis.yml +7 -1
  7. data/CHANGELOG.md +341 -243
  8. data/Dockerfile +44 -16
  9. data/LICENSE +201 -0
  10. data/README.md +114 -82
  11. data/Rakefile +19 -0
  12. data/TODO.md +29 -23
  13. data/bin/oxidized +1 -2
  14. data/docs/Configuration.md +71 -31
  15. data/docs/Creating-Models.md +78 -0
  16. data/docs/Hooks.md +145 -41
  17. data/docs/Model-Notes/AireOS.md +12 -0
  18. data/docs/Model-Notes/ArbOS.md +12 -0
  19. data/docs/Model-Notes/Comware.md +14 -0
  20. data/docs/Model-Notes/EOS.md +9 -0
  21. data/docs/Model-Notes/JunOS.md +34 -0
  22. data/docs/Model-Notes/Netgear.md +68 -0
  23. data/docs/Model-Notes/README.md +19 -0
  24. data/docs/{VRP-Huawei.md → Model-Notes/VRP-Huawei.md} +10 -2
  25. data/docs/Model-Notes/XGS4600-Zyxel.md +39 -0
  26. data/docs/Outputs.md +27 -28
  27. data/docs/Ruby-API.md +38 -18
  28. data/docs/Sources.md +78 -16
  29. data/docs/Supported-OS-Types.md +171 -148
  30. data/extra/oxidized.logrotate +7 -0
  31. data/extra/oxidized.service +1 -1
  32. data/extra/rest_client.rb +4 -5
  33. data/extra/syslog.rb +16 -16
  34. data/lib/oxidized/cli.rb +3 -3
  35. data/lib/oxidized/config.rb +7 -4
  36. data/lib/oxidized/core.rb +3 -3
  37. data/lib/oxidized/hook.rb +64 -65
  38. data/lib/oxidized/hook/awssns.rb +2 -3
  39. data/lib/oxidized/hook/ciscosparkdiff.rb +49 -0
  40. data/lib/oxidized/hook/exec.rb +5 -5
  41. data/lib/oxidized/hook/githubrepo.rb +20 -14
  42. data/lib/oxidized/hook/slackdiff.rb +38 -19
  43. data/lib/oxidized/hook/xmppdiff.rb +58 -0
  44. data/lib/oxidized/input/cli.rb +5 -6
  45. data/lib/oxidized/input/ftp.rb +8 -7
  46. data/lib/oxidized/input/http.rb +39 -0
  47. data/lib/oxidized/input/ssh.rb +24 -22
  48. data/lib/oxidized/input/telnet.rb +38 -32
  49. data/lib/oxidized/jobs.rb +3 -4
  50. data/lib/oxidized/manager.rb +9 -4
  51. data/lib/oxidized/model/acos.rb +15 -16
  52. data/lib/oxidized/model/acsw.rb +3 -8
  53. data/lib/oxidized/model/aen.rb +1 -2
  54. data/lib/oxidized/model/aireos.rb +3 -5
  55. data/lib/oxidized/model/alteonos.rb +16 -18
  56. data/lib/oxidized/model/alvarion.rb +0 -4
  57. data/lib/oxidized/model/aos.rb +2 -4
  58. data/lib/oxidized/model/aos7.rb +2 -3
  59. data/lib/oxidized/model/aosw.rb +13 -15
  60. data/lib/oxidized/model/apc_aos.rb +0 -3
  61. data/lib/oxidized/model/arbos.rb +26 -0
  62. data/lib/oxidized/model/aricentiss.rb +51 -0
  63. data/lib/oxidized/model/asa.rb +33 -35
  64. data/lib/oxidized/model/asyncos.rb +41 -44
  65. data/lib/oxidized/model/audiocodes.rb +4 -8
  66. data/lib/oxidized/model/awplus.rb +84 -0
  67. data/lib/oxidized/model/boss.rb +6 -5
  68. data/lib/oxidized/model/br6910.rb +43 -45
  69. data/lib/oxidized/model/c4cmts.rb +3 -5
  70. data/lib/oxidized/model/cambium.rb +22 -0
  71. data/lib/oxidized/model/catos.rb +0 -2
  72. data/lib/oxidized/model/cisconga.rb +1 -3
  73. data/lib/oxidized/model/ciscosma.rb +37 -40
  74. data/lib/oxidized/model/ciscosmb.rb +7 -4
  75. data/lib/oxidized/model/comnetms.rb +43 -0
  76. data/lib/oxidized/model/comware.rb +9 -9
  77. data/lib/oxidized/model/coriant8600.rb +3 -5
  78. data/lib/oxidized/model/coriantgroove.rb +3 -5
  79. data/lib/oxidized/model/corianttmos.rb +1 -3
  80. data/lib/oxidized/model/cumulus.rb +26 -32
  81. data/lib/oxidized/model/datacom.rb +0 -2
  82. data/lib/oxidized/model/dcnos.rb +46 -0
  83. data/lib/oxidized/model/dlink.rb +1 -1
  84. data/lib/oxidized/model/dnos.rb +9 -5
  85. data/lib/oxidized/model/edgecos.rb +45 -0
  86. data/lib/oxidized/model/edgeos.rb +5 -3
  87. data/lib/oxidized/model/edgeswitch.rb +1 -3
  88. data/lib/oxidized/model/enterasys.rb +1 -3
  89. data/lib/oxidized/model/eos.rb +6 -8
  90. data/lib/oxidized/model/fabricos.rb +3 -5
  91. data/lib/oxidized/model/firewareos.rb +2 -5
  92. data/lib/oxidized/model/fortios.rb +21 -17
  93. data/lib/oxidized/model/ftos.rb +2 -4
  94. data/lib/oxidized/model/fujitsupy.rb +2 -4
  95. data/lib/oxidized/model/gaiaos.rb +6 -10
  96. data/lib/oxidized/model/gcombnps.rb +82 -0
  97. data/lib/oxidized/model/hatteras.rb +8 -5
  98. data/lib/oxidized/model/hirschmann.rb +8 -10
  99. data/lib/oxidized/model/hpebladesystem.rb +19 -17
  100. data/lib/oxidized/model/hpemsa.rb +0 -3
  101. data/lib/oxidized/model/ios.rb +54 -55
  102. data/lib/oxidized/model/iosxe.rb +5 -0
  103. data/lib/oxidized/model/iosxr.rb +1 -3
  104. data/lib/oxidized/model/ipos.rb +1 -3
  105. data/lib/oxidized/model/ironware.rb +12 -15
  106. data/lib/oxidized/model/isam.rb +4 -5
  107. data/lib/oxidized/model/junos.rb +8 -7
  108. data/lib/oxidized/model/masteros.rb +1 -3
  109. data/lib/oxidized/model/mlnxos.rb +3 -4
  110. data/lib/oxidized/model/model.rb +15 -7
  111. data/lib/oxidized/model/mtrlrfs.rb +1 -4
  112. data/lib/oxidized/model/ndms.rb +24 -0
  113. data/lib/oxidized/model/netgear.rb +3 -4
  114. data/lib/oxidized/model/netscaler.rb +0 -2
  115. data/lib/oxidized/model/nos.rb +1 -3
  116. data/lib/oxidized/model/nxos.rb +13 -3
  117. data/lib/oxidized/model/oneos.rb +6 -8
  118. data/lib/oxidized/model/openbsd.rb +76 -0
  119. data/lib/oxidized/model/opengear.rb +3 -5
  120. data/lib/oxidized/model/openwrt.rb +77 -0
  121. data/lib/oxidized/model/opnsense.rb +19 -0
  122. data/lib/oxidized/model/outputs.rb +1 -3
  123. data/lib/oxidized/model/panos.rb +1 -2
  124. data/lib/oxidized/model/pfsense.rb +9 -5
  125. data/lib/oxidized/model/planet.rb +8 -12
  126. data/lib/oxidized/model/powerconnect.rb +6 -9
  127. data/lib/oxidized/model/procurve.rb +18 -4
  128. data/lib/oxidized/model/quantaos.rb +3 -5
  129. data/lib/oxidized/model/routeros.rb +3 -2
  130. data/lib/oxidized/model/saos.rb +0 -1
  131. data/lib/oxidized/model/screenos.rb +3 -5
  132. data/lib/oxidized/model/sgos.rb +2 -3
  133. data/lib/oxidized/model/siklu.rb +0 -2
  134. data/lib/oxidized/model/slxos.rb +59 -0
  135. data/lib/oxidized/model/sros.rb +117 -0
  136. data/lib/oxidized/model/stoneos.rb +32 -0
  137. data/lib/oxidized/model/supermicro.rb +6 -41
  138. data/lib/oxidized/model/timos.rb +6 -114
  139. data/lib/oxidized/model/tmos.rb +1 -3
  140. data/lib/oxidized/model/tplink.rb +7 -11
  141. data/lib/oxidized/model/trango.rb +6 -7
  142. data/lib/oxidized/model/ucs.rb +0 -1
  143. data/lib/oxidized/model/voltaire.rb +3 -6
  144. data/lib/oxidized/model/voss.rb +1 -2
  145. data/lib/oxidized/model/vrp.rb +4 -5
  146. data/lib/oxidized/model/vyatta.rb +6 -4
  147. data/lib/oxidized/model/weos.rb +1 -3
  148. data/lib/oxidized/model/xos.rb +6 -5
  149. data/lib/oxidized/model/zhoneolt.rb +2 -2
  150. data/lib/oxidized/model/zynos.rb +1 -3
  151. data/lib/oxidized/model/zynoscli.rb +36 -0
  152. data/lib/oxidized/node.rb +11 -11
  153. data/lib/oxidized/node/stats.rb +15 -2
  154. data/lib/oxidized/nodes.rb +8 -8
  155. data/lib/oxidized/output/file.rb +41 -42
  156. data/lib/oxidized/output/git.rb +113 -115
  157. data/lib/oxidized/output/gitcrypt.rb +241 -242
  158. data/lib/oxidized/output/http.rb +23 -27
  159. data/lib/oxidized/output/output.rb +1 -2
  160. data/lib/oxidized/source/csv.rb +44 -45
  161. data/lib/oxidized/source/http.rb +52 -49
  162. data/lib/oxidized/source/source.rb +6 -7
  163. data/lib/oxidized/source/sql.rb +55 -51
  164. data/lib/oxidized/string.rb +3 -4
  165. data/lib/oxidized/version.rb +17 -1
  166. data/lib/oxidized/worker.rb +12 -3
  167. data/oxidized.gemspec +19 -13
  168. metadata +139 -51
  169. data/.ruby-version +0 -1
  170. data/Gemfile.lock +0 -44
data/Rakefile CHANGED
@@ -1,9 +1,22 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
+ require_relative 'lib/oxidized/version'
3
4
 
4
5
  gemspec = eval(File.read(Dir['*.gemspec'].first))
5
6
  file = [gemspec.name, gemspec.version].join('-') + '.gem'
6
7
 
8
+ # Integrate Rubocop if available
9
+ begin
10
+ require 'rubocop/rake_task'
11
+
12
+ RuboCop::RakeTask.new
13
+ task(:default).prerequisites << task(:rubocop)
14
+ rescue LoadError
15
+ task :rubocop do
16
+ puts 'Install rubocop to run its rake tasks'
17
+ end
18
+ end
19
+
7
20
  desc 'Validate gemspec'
8
21
  task :gemspec do
9
22
  gemspec.validate
@@ -19,6 +32,12 @@ task :test do
19
32
  end
20
33
  end
21
34
 
35
+ task :build => :version_set
36
+ task :version_set do
37
+ Oxidized.version_set
38
+ Bundler::GemHelper.instance.gemspec.version = Oxidized::VERSION
39
+ end
40
+
22
41
  ## desc 'Install gem'
23
42
  ## task :install => :build do
24
43
  ## system "sudo -Es sh -c \'umask 022; gem install gems/#{file}\'"
data/TODO.md CHANGED
@@ -1,23 +1,29 @@
1
- # refactor core
2
- * move state from memory to disk, sqlite probably
3
- * allows us to retain stats etc over restart
4
- * simplifies code
5
- * keep only running nodes in memory
6
- * negligible I/O cost, as majority is I/O wait getting config
7
-
8
- # separate login to owon package
9
- * oxidized-script is not only use-case
10
- * it would be good to have minimal package used to login to routers
11
- * oxidized just one consumer of that functionality
12
- * what to do with models, we need model to know how to login. Should models be separated to another package? oxidized-core, oxidized-models and oxidized-login?
13
- * how can we allow interactive login in oxidized-login? With functional VTY etc? REPL loop in input/ssh and input/telnet?
14
-
15
- # thread number
16
- * think about algo
17
- * if job ended later than now-iteration have rand(node.size) == 0 to add thread
18
- * if now is less than job_ended+iteration same chance to remove thread?
19
- * should we try to avoid max threads from being hit? (like maybe non-success thread is pulling average?)
20
-
21
- # docs, testing
22
- * yard docs
23
- * minitest tests
1
+ # To Do
2
+
3
+ ## refactor core
4
+
5
+ * move state from memory to disk, sqlite probably
6
+ * allows us to retain stats etc over restart
7
+ * simplifies code
8
+ * keep only running nodes in memory
9
+ * negligible I/O cost, as majority is I/O wait getting config
10
+
11
+ ## separate login to own package
12
+
13
+ * oxidized-script is not only use-case
14
+ * it would be good to have minimal package used to login to routers
15
+ * oxidized just one consumer of that functionality
16
+ * what to do with models, we need model to know how to login. Should models be separated to another package? oxidized-core, oxidized-models and oxidized-login?
17
+ * how can we allow interactive login in oxidized-login? With functional VTY etc? REPL loop in input/ssh and input/telnet?
18
+
19
+ ## thread number
20
+
21
+ * think about algo
22
+ * if job ended later than now-iteration have rand(node.size) == 0 to add thread
23
+ * if now is less than job_ended+iteration same chance to remove thread?
24
+ * should we try to avoid max threads from being hit? (like maybe non-success thread is pulling average?)
25
+
26
+ ## docs, testing
27
+
28
+ * yard docs
29
+ * minitest tests
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
-
4
3
  # FIX ME, killing oxidized needs -9
5
4
  trap("INT") { exit } # sinatra will otherwise steal this from us
6
5
 
@@ -9,6 +8,6 @@ begin
9
8
  Oxidized::CLI.new.run
10
9
  rescue => error
11
10
  warn "#{error}"
12
- debug = Oxidied.config.debug rescue true
11
+ debug = Oxidized.config.debug rescue true
13
12
  raise if debug
14
13
  end
@@ -1,10 +1,12 @@
1
- ## Configuration
2
- ### Debugging
1
+ # Configuration
2
+
3
+ ## Debugging
4
+
3
5
  In case a model plugin doesn't work correctly (ios, procurve, etc.), you can enable live debugging of SSH/Telnet sessions. Just add a `debug` option containing the value true to the `input` section. The log files will be created depending on the parent directory of the logfile option.
4
6
 
5
- The following example will log an active ssh/telnet session `/home/oxidized/.config/oxidized/log/<IP-Adress>-<PROTOCOL>`. The file will be truncated on each consecutive ssh/telnet session, so you need to put a `tailf` or `tail -f` on that file!
7
+ The following example will log an active ssh/telnet session `/home/oxidized/.config/oxidized/log/<IP-Address>-<PROTOCOL>`. The file will be truncated on each consecutive ssh/telnet session, so you need to put a `tailf` or `tail -f` on that file!
6
8
 
7
- ```
9
+ ```yaml
8
10
  log: /home/oxidized/.config/oxidized/log
9
11
 
10
12
  ...
@@ -16,54 +18,68 @@ input:
16
18
  secure: false
17
19
  ```
18
20
 
19
- ### Privileged mode
21
+ ## Privileged mode
20
22
 
21
23
  To start privileged mode before pulling the configuration, Oxidized needs to send the enable command. You can globally enable this, by adding the following snippet to the global section of the configuration file.
22
24
 
23
- ```
25
+ ```yaml
24
26
  vars:
25
27
  enable: S3cre7
26
28
  ```
27
29
 
28
- ### Removing secrets
30
+ ## Removing secrets
29
31
 
30
- To strip out secrets from configurations before storing them, Oxidized needs the the remove_secrets flag. You can globally enable this by adding the following snippet to the global sections of the configuration file.
32
+ To strip out secrets from configurations before storing them, Oxidized needs the `remove_secret` flag. You can globally enable this by adding the following snippet to the global section of the configuration file.
31
33
 
32
- ```
34
+ ```yaml
33
35
  vars:
34
36
  remove_secret: true
35
37
  ```
36
38
 
37
- Device models can contain substitution filters to remove potentially sensitive data from configs.
39
+ Device models that contain substitution filters to remove sensitive data will now be run on any fetched configuration.
38
40
 
39
41
  As a partial example from ios.rb:
40
42
 
41
- ```
43
+ ```ruby
42
44
  cmd :secret do |cfg|
43
45
  cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
44
46
  (...)
45
47
  cfg
46
48
  end
47
49
  ```
50
+
48
51
  The above strips out snmp community strings from your saved configs.
49
52
 
50
53
  **NOTE:** Removing secrets reduces the usefulness as a full configuration backup, but it may make sharing configs easier.
51
54
 
52
- ### Disabling SSH exec channels
55
+ ## Disabling SSH exec channels
53
56
 
54
- Oxidized uses exec channels to make information extraction simpler, but there are some situations where this doesn't work well, e.g. configuring devices. This feature can be turned off by setting the `ssh_no_exec`
57
+ Oxidized uses exec channels to make information extraction simpler, but there are some situations where this doesn't work well, e.g. configuring devices. This feature can be turned off by setting the `ssh_no_exec`
55
58
  variable.
56
59
 
57
- ```
60
+ ```yaml
58
61
  vars:
59
62
  ssh_no_exec: true
60
63
  ```
61
64
 
62
- ### SSH Proxy Command
65
+ ## SSH Auth Methods
63
66
 
64
- Oxidized can `ssh` through a proxy as well. To do so we just need to set `ssh_proxy` variable.
67
+ By default, Oxidized registers the following auth methods: `none`, `publickey` and `password`. However you can configure this globally, by groups, models or nodes.
65
68
 
66
69
  ```
70
+ vars:
71
+ auth_methods: none, publickey, password, keyboard-interactive
72
+ ```
73
+
74
+ ## SSH Proxy Command
75
+
76
+ Oxidized can `ssh` through a proxy as well. To do so we just need to set `ssh_proxy` variable with the proxy host information.
77
+
78
+ This can be provided on a per-node basis by mapping the proper fields from your source.
79
+
80
+ An example for a `csv` input source that maps the 4th field as the `ssh_proxy` value.
81
+
82
+ ```yaml
67
83
  ...
68
84
  map:
69
85
  name: 0
@@ -74,16 +90,26 @@ vars_map:
74
90
  ...
75
91
  ```
76
92
 
77
- ### Advanced Configuration
93
+ ## FTP Passive Mode
78
94
 
79
- Below is an advanced example configuration. You will be able to (optionally) override options per device. The router.db format used is `hostname:model:username:password:enable_password`. Hostname and model will be the only required options, all others override the global configuration sections.
95
+ Oxidized uses ftp passive mode by default. Some devices require passive mode to be disabled. To do so, we can set `input.ftp.passive` to false - this will make use of FTP active mode.
80
96
 
97
+ ```yaml
98
+ input:
99
+ ftp:
100
+ passive: false
81
101
  ```
102
+
103
+ ## Advanced Configuration
104
+
105
+ Below is an advanced example configuration. You will be able to (optionally) override options per device. The router.db format used is `hostname:model:username:password:enable_password`. Hostname and model will be the only required options, all others override the global configuration sections.
106
+
107
+ ```yaml
82
108
  ---
83
109
  username: oxidized
84
110
  password: S3cr3tx
85
111
  model: junos
86
- interval: 3600
112
+ interval: 3600 #interval in seconds
87
113
  log: ~/.config/oxidized/log
88
114
  debug: false
89
115
  threads: 30
@@ -121,14 +147,13 @@ source:
121
147
  model_map:
122
148
  cisco: ios
123
149
  juniper: junos
124
-
125
150
  ```
126
151
 
127
- ### Advanced Group Configuration
152
+ ## Advanced Group Configuration
128
153
 
129
154
  For group specific credentials
130
155
 
131
- ```
156
+ ```yaml
132
157
  groups:
133
158
  mikrotik:
134
159
  username: admin
@@ -137,16 +162,19 @@ groups:
137
162
  username: ubnt
138
163
  password: ubnt
139
164
  ```
165
+
140
166
  and add group mapping
141
- ```
167
+
168
+ ```yaml
142
169
  map:
143
170
  model: 0
144
171
  name: 1
145
172
  group: 2
146
173
  ```
174
+
147
175
  For model specific credentials
148
176
 
149
- ```
177
+ ```yaml
150
178
  models:
151
179
  junos:
152
180
  username: admin
@@ -161,26 +189,38 @@ models:
161
189
  password: password
162
190
  ```
163
191
 
164
- ### RESTful API and Web Interface
192
+ ## RESTful API and Web Interface
165
193
 
166
194
  The RESTful API and Web Interface is enabled by configuring the `rest:` parameter in the config file. This parameter can optionally contain a relative URI.
167
195
 
168
- ```
196
+ ```yaml
169
197
  # Listen on http://127.0.0.1:8888/
170
198
  rest: 127.0.0.1:8888
171
199
  ```
172
200
 
173
- ```
201
+ ```yaml
174
202
  # Listen on http://10.0.0.1:8000/oxidized/
175
203
  rest: 10.0.0.1:8000/oxidized
176
204
  ```
177
205
 
178
- ### Triggered backups
206
+ ## Triggered backups
179
207
 
180
- A node can be moved to head-of-queue via the REST API `GET/POST /node/next/[NODE]`.
208
+ A node can be moved to head-of-queue via the REST API `GET/POST /node/next/[NODE]`. This can be useful to immediately schedule a fetch of the configuration after some other event such as a syslog message indicating a configuration update on the device.
181
209
 
182
- In the default configuration this node will be processed when the next job worker becomes available, it could take some time if existing backups are in progress. To execute moved jobs immediately a new job can be added:
210
+ In the default configuration this node will be processed when the next job worker becomes available, it could take some time if existing backups are in progress. To execute moved jobs immediately a new job can be added automatically:
183
211
 
184
- ```
212
+ ```yaml
185
213
  next_adds_job: true
186
214
  ```
215
+
216
+ This will allow for a more timely fetch of the device configuration.
217
+
218
+ ## Disabling DNS resolution
219
+
220
+ In some instances it might not be desirable to attempt to resolve names of nodes. One such use case is when nodes are accessed through an SSH proxy, where the remote end resolves the names differently than the host on which Oxidized runs would.
221
+
222
+ Names can instead be passed verbatim to the input:
223
+
224
+ ```yaml
225
+ resolve_dns: false
226
+ ```
@@ -0,0 +1,78 @@
1
+ # Creating and Extending Models
2
+
3
+ Oxidized supports a growing list of [operating system types](Supported-OS-Types.md). Out of the box, most model implementations collect configuration data. Some implementations also include a conservative set of additional commands that collect basic device information (device make and model, software version, licensing information, ...) which are appended to the configuration as comments.
4
+
5
+ A user may wish to extend an existing model to collect the output of additional commands. Oxidized offers smart loading of models in order to facilitate this with ease, without the need to introduce changes to the upstream source code.
6
+
7
+ This methodology allows local site changes to be preserved during Oxidized version updates / gem updates.
8
+
9
+ ## Extending an existing model with a new command
10
+
11
+ The example below can be used to extend the `JunOS` model to collect the output of `show interfaces diagnostics optics` and append the output to the configuration file as a comment. This command retrieves DOM information on pluggable optics present in a `JunOS`-powered chassis.
12
+
13
+ Create the file `~/.config/oxidized/model/junos.rb` with the following contents:
14
+
15
+ ```ruby
16
+ require 'oxidized/model/junos.rb'
17
+
18
+
19
+ class JunOS
20
+
21
+
22
+ cmd 'show interfaces diagnostics optics' do |cfg|
23
+ comment cfg
24
+ end
25
+
26
+
27
+ end
28
+ ```
29
+
30
+ Due to smart loading, the user-supplied `~/.config/oxidized/model/junos.rb` file will take precedence over the model with the same name included in the Oxidized distribution.
31
+
32
+ The code then uses `require` to initially load the Oxidized-supplied model, and extends the class defined therein with an additional command.
33
+
34
+ Intuitively, it is also possible to:
35
+
36
+ * Completely re-define an existing model by creating a file in `~/.config/oxidized/model/` with the same name as an existing model, but not `require`-ing the upstream model file.
37
+ * Create a named variation of an existing model, by creating a file with a new name (such as `~/.config/oxidized/model/junos-extra.rb`), Then `require` the original model and extend its base class as in the above example. The named variation can then be specified as an OS type for specific devices that can benefit from the extra functionality. This allows for preservation of the base functionality for the default model types.
38
+ * Create a completely new model, with a new name, for a new operating system type.
39
+ * Testing/validation of an updated model from the [Oxidized GitHub repo models](https://github.com/ytti/oxidized/tree/master/lib/oxidized/model) by placing an updated model in the proper location without disrupting the gem-supplied model files.
40
+
41
+ ## Advanced features
42
+
43
+ The loosely-coupled architecture of Oxidized allows for easy extensibility in more advanced use cases as well.
44
+
45
+ The example below extends the functionality of the `JunOS` model further to collect `display set` formatted configuration from the device, and utilizes the multi-output functionality of the `git` output to place the returned configuration in a separate file within a git repository.
46
+
47
+ It is possible to configure the `git` output to create new subdirectories under an existing repository instead of creating new repositories for each new defined output type (the default) by including the following configuration in the `~/.config/oxidized/config` file:
48
+
49
+ ```yaml
50
+ output:
51
+ git:
52
+ type_as_directory: true
53
+ ```
54
+
55
+ Then, `~/.config/oxidized/model/junos.rb` is adapted as following:
56
+
57
+ ```ruby
58
+ require 'oxidized/model/junos.rb'
59
+
60
+
61
+ class JunOS
62
+
63
+
64
+ cmd 'show interface diagnostic optics' do |cfg|
65
+ comment cfg
66
+ end
67
+
68
+ cmd 'show configuration | display set' do |cfg|
69
+ cfg.type = "junos-set"
70
+ cfg.name = "set"
71
+ cfg
72
+ end
73
+
74
+
75
+ end
76
+ ```
77
+
78
+ The output of the `show configuration | display set` command is marked with a new arbitrary alternative output type, `junos-set`. The `git` output will use the output type to create a new subdirectory by the same name. In this subdirectory, the `git` output will create files with the name `<devicename>--set` that will contain the output of this command for each device.
@@ -1,46 +1,52 @@
1
1
  # Hooks
2
- You can define arbitrary number of hooks that subscribe different events. The hook system is modular and different kind of hook types can be enabled.
2
+
3
+ You can define an arbitrary number of hooks that subscribe to different events. The hook system is modular and different kind of hook types can be enabled.
3
4
 
4
5
  ## Configuration
6
+
5
7
  Following configuration keys need to be defined for all hooks:
6
8
 
7
- * `events`: which events to subscribe. Needs to be an array. See below for the list of available events.
8
- * `type`: what hook class to use. See below for the list of available hook types.
9
+ * `events`: which events to subscribe. Needs to be an array. See below for the list of available events.
10
+ * `type`: what hook class to use. See below for the list of available hook types.
9
11
 
10
- ### Events
11
- * `node_success`: triggered when configuration is succesfully pulled from a node and right before storing the configuration.
12
- * `node_fail`: triggered after `retries` amount of failed node pulls.
13
- * `post_store`: triggered after node configuration is stored (this is executed only when the configuration has changed).
14
- * `nodes_done`: triggered after finished fetching all nodes.
12
+ ## Events
13
+
14
+ * `node_success`: triggered when configuration is successfully pulled from a node and right before storing the configuration.
15
+ * `node_fail`: triggered after `retries` amount of failed node pulls.
16
+ * `post_store`: triggered after node configuration is stored (this is executed only when the configuration has changed).
17
+ * `nodes_done`: triggered after finished fetching all nodes.
15
18
 
16
19
  ## Hook type: exec
20
+
17
21
  The `exec` hook type allows users to run an arbitrary shell command or a binary when triggered.
18
22
 
19
23
  The command is executed on a separate child process either in synchronous or asynchronous fashion. Non-zero exit values cause errors to be logged. STDOUT and STDERR are currently not collected.
20
24
 
21
25
  Command is executed with the following environment:
22
- ```
26
+
27
+ ```text
23
28
  OX_EVENT
24
29
  OX_NODE_NAME
25
30
  OX_NODE_IP
26
31
  OX_NODE_FROM
27
32
  OX_NODE_MSG
28
33
  OX_NODE_GROUP
34
+ OX_NODE_MODEL
29
35
  OX_JOB_STATUS
30
36
  OX_JOB_TIME
31
37
  OX_REPO_COMMITREF
32
38
  OX_REPO_NAME
33
39
  ```
34
40
 
35
- Exec hook recognizes following configuration keys:
41
+ Exec hook recognizes the following configuration keys:
36
42
 
37
- * `timeout`: hard timeout for the command execution. SIGTERM will be sent to the child process after the timeout has elapsed. Default: 60
38
- * `async`: influences whether main thread will wait for the command execution. Set this true for long running commands so node pull is not blocked. Default: false
39
- * `cmd`: command to run.
43
+ * `timeout`: hard timeout (in seconds) for the command execution. SIGTERM will be sent to the child process after the timeout has elapsed. Default: `60`
44
+ * `async`: Execute the command in an asynchronous fashion. The main thread by default will wait for the hook command execution to complete. Set this to `true` for long running commands so node configuration pulls are not blocked. Default: `false`
45
+ * `cmd`: command to run.
40
46
 
47
+ ### exec hook configuration example
41
48
 
42
- ## Hook configuration example
43
- ```
49
+ ```yaml
44
50
  hooks:
45
51
  name_for_example_hook1:
46
52
  type: exec
@@ -54,21 +60,31 @@ hooks:
54
60
  timeout: 120
55
61
  ```
56
62
 
57
- ### githubrepo
63
+ ## Hook type: githubrepo
64
+
65
+ The `githubrepo` hook executes a `git push` to a configured `remote_repo` when the specified event is triggered.
58
66
 
59
- This hook configures the repository `remote` and _push_ the code when the specified event is triggerd. If the `username` and `password` are not provided, the `Rugged::Credentials::SshKeyFromAgent` will be used.
67
+ Several authentication methods are supported:
60
68
 
61
- `githubrepo` hook recognizes following configuration keys:
69
+ * Provide a `password` for username + password authentication
70
+ * Provide both a `publickey` and a `privatekey` for ssh key-based authentication
71
+ * Don't provide any credentials for ssh-agent authentication
62
72
 
63
- * `remote_repo`: the remote repository to be pushed to.
64
- * `username`: username for repository auth.
65
- * `password`: password for repository auth.
66
- * `publickey`: publickey for repository auth.
67
- * `privatekey`: privatekey for repository auth.
73
+ The username will be set to the relevant part of the `remote_repo` URI, with a fallback to `git`. It is also possible to provide one by setting the `username` configuration key.
68
74
 
69
- When using groups repositories, each group must have its own `remote` in the `remote_repo` config.
75
+ For ssh key-based authentication, it is possible to set the environment variable `OXIDIZED_SSH_PASSPHRASE` to a passphrase if the private key requires it.
70
76
 
71
- ``` yaml
77
+ `githubrepo` hook recognizes the following configuration keys:
78
+
79
+ * `remote_repo`: the remote repository to be pushed to.
80
+ * `username`: username for repository auth.
81
+ * `password`: password for repository auth.
82
+ * `publickey`: public key file path for repository auth.
83
+ * `privatekey`: private key file path for repository auth.
84
+
85
+ When using groups, each group must have a unique entry in the `remote_repo` config.
86
+
87
+ ```yaml
72
88
  hooks:
73
89
  push_to_remote:
74
90
  remote_repo:
@@ -77,10 +93,11 @@ hooks:
77
93
  firewalls: git@git.intranet:oxidized/firewalls.git
78
94
  ```
79
95
 
96
+ ### githubrepo hook configuration example
80
97
 
81
- ## Hook configuration example
98
+ Authenticate with a username and a password without groups in use:
82
99
 
83
- ``` yaml
100
+ ```yaml
84
101
  hooks:
85
102
  push_to_remote:
86
103
  type: githubrepo
@@ -90,20 +107,37 @@ hooks:
90
107
  password: pass
91
108
  ```
92
109
 
110
+ Authenticate with the username `git` and an ssh key:
111
+
112
+ ```yaml
113
+ hooks:
114
+ push_to_remote:
115
+ type: githubrepo
116
+ events: [post_store]
117
+ remote_repo: git@git.intranet:oxidized/test.git
118
+ publickey: /root/.ssh/id_rsa.pub
119
+ privatekey: /root/.ssh/id_rsa
120
+ ```
121
+
93
122
  ## Hook type: awssns
94
123
 
95
124
  The `awssns` hook publishes messages to AWS SNS topics. This allows you to notify other systems of device configuration changes, for example a config orchestration pipeline. Multiple services can subscribe to the same AWS topic.
96
125
 
97
126
  Fields sent in the message:
98
127
 
99
- * `event`: Event type (e.g. `node_success`)
100
- * `group`: Group name
101
- * `model`: Model name (e.g. `eos`)
102
- * `node`: Device hostname
128
+ * `event`: Event type (e.g. `node_success`)
129
+ * `group`: Group name
130
+ * `model`: Model name (e.g. `eos`)
131
+ * `node`: Device hostname
132
+
103
133
 
104
- Configuration example:
134
+ The AWS SNS hook requires the following configuration keys:
105
135
 
106
- ``` yaml
136
+ * `region`: AWS Region name
137
+ * `topic_arn`: ASN Topic reference
138
+ ### awssns hook configuration example
139
+
140
+ ```yaml
107
141
  hooks:
108
142
  hook_script:
109
143
  type: awssns
@@ -112,11 +146,6 @@ hooks:
112
146
  topic_arn: arn:aws:sns:us-east-1:1234567:oxidized-test-backup_events
113
147
  ```
114
148
 
115
- AWS SNS hook requires the following configuration keys:
116
-
117
- * `region`: AWS Region name
118
- * `topic_arn`: ASN Topic reference
119
-
120
149
  Your AWS credentials should be stored in `~/.aws/credentials`.
121
150
 
122
151
  ## Hook type: slackdiff
@@ -125,13 +154,13 @@ The `slackdiff` hook posts colorized config diffs to a [Slack](http://www.slack.
125
154
 
126
155
  You will need to manually install the `slack-api` gem on your system:
127
156
 
128
- ```
157
+ ```shell
129
158
  gem install slack-api
130
159
  ```
131
160
 
132
- Configuration example:
161
+ ### slackdiff hook configuration example
133
162
 
134
- ``` yaml
163
+ ```yaml
135
164
  hooks:
136
165
  slack:
137
166
  type: slackdiff
@@ -140,4 +169,79 @@ hooks:
140
169
  channel: "#network-changes"
141
170
  ```
142
171
 
172
+ 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.
173
+
174
+ ```yaml
175
+ hooks:
176
+ slack:
177
+ type: slackdiff
178
+ events: [post_store]
179
+ token: SLACK_BOT_TOKEN
180
+ channel: "#network-changes"
181
+ diff: false
182
+ message: "%{node} %{group} %{model} updated https://git.intranet/network-changes/commit/%{commitref}"
183
+ ```
184
+
185
+ Note the channel name must be in quotes.
186
+
187
+ ## Hook type: ciscosparkdiff
188
+
189
+ The `ciscosparkdiff` hook posts config diffs to a [Cisco Spark](https://www.ciscospark.com/) space of your choice. It only triggers for `post_store` events.
190
+
191
+ You will need to manually install the `cisco_spark` gem on your system (see [cisco_spark-ruby](https://github.com/NGMarmaduke/cisco_spark-ruby)) and generate either a [Bot or OAUTH access key](https://developer.ciscospark.com/apps.html), and retrieve the [Spark Space ID](https://developer.ciscospark.com/endpoint-rooms-get.html)
192
+
193
+ ```shell
194
+ gem install cisco_spark
195
+ ```
196
+
197
+ ### ciscosparkdiff hook configuration example
198
+
199
+ ```yaml
200
+ hooks:
201
+ ciscospark:
202
+ type: ciscosparkdiff
203
+ events: [post_store]
204
+ accesskey: SPARK_BOT_API_OR_OAUTH_KEY
205
+ space: SPARK_SPACE_ID
206
+ diff: true
207
+ ```
208
+
209
+ 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.
210
+
211
+ ```yaml
212
+ hooks:
213
+ ciscospark:
214
+ type: ciscosparkdiff
215
+ events: [post_store]
216
+ accesskey: SPARK_BOT_API_OR_OAUTH_KEY
217
+ space: SPARK_SPACE_ID
218
+ diff: false
219
+ message: "%{node} %{group} %{model} updated https://git.intranet/network-changes/commit/%{commitref}"
220
+ ```
221
+
222
+ Note the space and access tokens must be in quotes.
223
+
224
+ ## Hook type: xmppdiff
225
+
226
+ The `xmppdiff` hook posts config diffs to a [XMPP](https://en.wikipedia.org/wiki/XMPP) chatroom of your choice. It only triggers for `post_store` events.
227
+
228
+ You will need to manually install the `xmpp4r` gem on your system:
229
+
230
+ ```shell
231
+ gem install xmpp4r
232
+ ```
233
+
234
+ ### xmppdiff hook configuration example
235
+
236
+ ```yaml
237
+ hooks:
238
+ xmpp:
239
+ type: xmppdiff
240
+ events: [post_store]
241
+ jid: "user@server.tld/resource"
242
+ password: "password"
243
+ channel: "room@server.tld"
244
+ nick: "nickname"
245
+ ```
246
+
143
247
  Note the channel name must be in quotes.