oxidized 0.25.1 → 0.26.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -9
  3. data/.rubocop_todo.yml +16 -637
  4. data/.travis.yml +2 -3
  5. data/CHANGELOG.md +14 -0
  6. data/Dockerfile +7 -5
  7. data/README.md +18 -14
  8. data/Rakefile +2 -2
  9. data/bin/console +1 -1
  10. data/bin/oxidized +2 -2
  11. data/docs/Configuration.md +6 -0
  12. data/docs/Model-Notes/README.md +1 -0
  13. data/docs/Model-Notes/SmartAX-Huawei.md +35 -0
  14. data/docs/Supported-OS-Types.md +12 -0
  15. data/extra/nagios_check_failing_nodes.rb +1 -1
  16. data/extra/rest_client.rb +6 -8
  17. data/extra/syslog.rb +33 -33
  18. data/lib/oxidized/cli.rb +25 -26
  19. data/lib/oxidized/config.rb +9 -9
  20. data/lib/oxidized/config/vars.rb +3 -7
  21. data/lib/oxidized/core.rb +4 -7
  22. data/lib/oxidized/hook.rb +16 -17
  23. data/lib/oxidized/hook/awssns.rb +4 -4
  24. data/lib/oxidized/hook/exec.rb +16 -20
  25. data/lib/oxidized/hook/githubrepo.rb +8 -14
  26. data/lib/oxidized/hook/noophook.rb +1 -1
  27. data/lib/oxidized/hook/xmppdiff.rb +1 -1
  28. data/lib/oxidized/input/cli.rb +12 -12
  29. data/lib/oxidized/input/ftp.rb +8 -8
  30. data/lib/oxidized/input/http.rb +37 -14
  31. data/lib/oxidized/input/input.rb +6 -6
  32. data/lib/oxidized/input/ssh.rb +31 -31
  33. data/lib/oxidized/input/telnet.rb +24 -24
  34. data/lib/oxidized/input/tftp.rb +9 -10
  35. data/lib/oxidized/jobs.rb +7 -7
  36. data/lib/oxidized/manager.rb +13 -13
  37. data/lib/oxidized/model/acos.rb +2 -2
  38. data/lib/oxidized/model/aireos.rb +3 -3
  39. data/lib/oxidized/model/aos7.rb +1 -1
  40. data/lib/oxidized/model/aosw.rb +12 -14
  41. data/lib/oxidized/model/apc_aos.rb +1 -1
  42. data/lib/oxidized/model/aricentiss.rb +6 -8
  43. data/lib/oxidized/model/asa.rb +1 -1
  44. data/lib/oxidized/model/audiocodesmp.rb +28 -0
  45. data/lib/oxidized/model/awplus.rb +9 -9
  46. data/lib/oxidized/model/boss.rb +1 -1
  47. data/lib/oxidized/model/ciscosmb.rb +1 -1
  48. data/lib/oxidized/model/ciscovpn3k.rb +11 -0
  49. data/lib/oxidized/model/comware.rb +1 -1
  50. data/lib/oxidized/model/cumulus.rb +3 -1
  51. data/lib/oxidized/model/dellx.rb +5 -5
  52. data/lib/oxidized/model/edgeos.rb +1 -1
  53. data/lib/oxidized/model/edgeswitch.rb +1 -1
  54. data/lib/oxidized/model/fabricos.rb +1 -1
  55. data/lib/oxidized/model/fortios.rb +5 -5
  56. data/lib/oxidized/model/ftos.rb +1 -1
  57. data/lib/oxidized/model/gcombnps.rb +7 -7
  58. data/lib/oxidized/model/grandstream.rb +9 -0
  59. data/lib/oxidized/model/hatteras.rb +8 -8
  60. data/lib/oxidized/model/ios.rb +22 -40
  61. data/lib/oxidized/model/ironware.rb +1 -1
  62. data/lib/oxidized/model/junos.rb +1 -1
  63. data/lib/oxidized/model/mlnxos.rb +1 -1
  64. data/lib/oxidized/model/model.rb +32 -38
  65. data/lib/oxidized/model/netgearxs716.rb +23 -0
  66. data/lib/oxidized/model/netonix.rb +1 -1
  67. data/lib/oxidized/model/netscaler.rb +1 -1
  68. data/lib/oxidized/model/nos.rb +2 -2
  69. data/lib/oxidized/model/nxos.rb +1 -1
  70. data/lib/oxidized/model/openbsd.rb +3 -2
  71. data/lib/oxidized/model/outputs.rb +4 -4
  72. data/lib/oxidized/model/planet.rb +4 -4
  73. data/lib/oxidized/model/powerconnect.rb +8 -8
  74. data/lib/oxidized/model/procurve.rb +2 -1
  75. data/lib/oxidized/model/quantaos.rb +3 -3
  76. data/lib/oxidized/model/raisecom.rb +19 -0
  77. data/lib/oxidized/model/siklu.rb +1 -1
  78. data/lib/oxidized/model/slxos.rb +1 -1
  79. data/lib/oxidized/model/smartax.rb +25 -0
  80. data/lib/oxidized/model/sros.rb +4 -4
  81. data/lib/oxidized/model/tdre.rb +30 -0
  82. data/lib/oxidized/model/tmos.rb +3 -0
  83. data/lib/oxidized/model/trango.rb +17 -37
  84. data/lib/oxidized/model/voltaire.rb +1 -1
  85. data/lib/oxidized/model/voss.rb +1 -1
  86. data/lib/oxidized/model/vyatta.rb +1 -1
  87. data/lib/oxidized/model/xos.rb +1 -1
  88. data/lib/oxidized/model/zhoneolt.rb +1 -1
  89. data/lib/oxidized/node.rb +42 -46
  90. data/lib/oxidized/node/stats.rb +6 -6
  91. data/lib/oxidized/nodes.rb +42 -42
  92. data/lib/oxidized/output/file.rb +16 -20
  93. data/lib/oxidized/output/git.rb +68 -78
  94. data/lib/oxidized/output/gitcrypt.rb +77 -91
  95. data/lib/oxidized/output/http.rb +17 -19
  96. data/lib/oxidized/output/output.rb +1 -1
  97. data/lib/oxidized/source/csv.rb +3 -3
  98. data/lib/oxidized/source/http.rb +11 -14
  99. data/lib/oxidized/source/source.rb +3 -3
  100. data/lib/oxidized/source/sql.rb +16 -18
  101. data/lib/oxidized/string.rb +10 -10
  102. data/lib/oxidized/version.rb +4 -4
  103. data/lib/oxidized/worker.rb +15 -15
  104. data/oxidized.gemspec +6 -9
  105. metadata +32 -25
@@ -36,7 +36,7 @@ module Oxidized
36
36
  end
37
37
  end
38
38
 
39
- def crypt_init repo
39
+ def crypt_init(repo)
40
40
  repo.chdir do
41
41
  system(@gitcrypt_init)
42
42
  @cfg.users.each do |user|
@@ -48,22 +48,22 @@ module Oxidized
48
48
  end
49
49
  end
50
50
 
51
- def lock repo
51
+ def lock(repo)
52
52
  repo.chdir do
53
53
  system(@gitcrypt_lock)
54
54
  end
55
55
  end
56
56
 
57
- def unlock repo
57
+ def unlock(repo)
58
58
  repo.chdir do
59
59
  system(@gitcrypt_unlock)
60
60
  end
61
61
  end
62
62
 
63
- def store file, outputs, opt = {}
63
+ def store(file, outputs, opt = {})
64
64
  @msg = opt[:msg]
65
- @user = (opt[:user] or @cfg.user)
66
- @email = (opt[:email] or @cfg.email)
65
+ @user = (opt[:user] || @cfg.user)
66
+ @email = (opt[:email] || @cfg.email)
67
67
  @opt = opt
68
68
  @commitref = nil
69
69
  repo = @cfg.repo
@@ -72,7 +72,7 @@ module Oxidized
72
72
  type_cfg = ''
73
73
  type_repo = File.join(File.dirname(repo), type + '.git')
74
74
  outputs.type(type).each do |output|
75
- (type_cfg << output; next) if not output.name
75
+ (type_cfg << output; next) unless output.name # rubocop:disable Style/Semicolon
76
76
  type_file = file + '--' + output.name
77
77
  if @cfg.type_as_directory?
78
78
  type_file = type + '/' + type_file
@@ -86,97 +86,85 @@ module Oxidized
86
86
  update repo, file, outputs.to_cfg
87
87
  end
88
88
 
89
- def fetch node, group
90
- begin
91
- repo, path = yield_repo_and_path(node, group)
92
- repo = Git.open repo
93
- unlock repo
94
- index = repo.index
95
- # Empty repo ?
96
- empty = File.exists? index.path
97
- if empty
98
- raise 'Empty git repo'
99
- else
100
- File.read path
101
- end
102
-
103
- lock repo
104
- rescue
105
- 'node not found'
106
- end
89
+ def fetch(node, group)
90
+ repo, path = yield_repo_and_path(node, group)
91
+ repo = Git.open repo
92
+ unlock repo
93
+ index = repo.index
94
+ # Empty repo ?
95
+ raise 'Empty git repo' if File.exist?(index.path)
96
+
97
+ File.read path
98
+ lock repo
99
+ rescue StandardError
100
+ 'node not found'
107
101
  end
108
102
 
109
103
  # give a hash of all oid revision for the given node, and the date of the commit
110
- def version node, group
111
- begin
112
- repo, path = yield_repo_and_path(node, group)
113
-
114
- repo = Git.open repo
115
- unlock repo
116
- walker = repo.log.path(path)
117
- i = -1
118
- tab = []
119
- walker.each do |commit|
120
- hash = {}
121
- hash[:date] = commit.date.to_s
122
- hash[:oid] = commit.objectish
123
- hash[:author] = commit.author
124
- hash[:message] = commit.message
125
- tab[i += 1] = hash
126
- end
127
- walker.reset
128
- tab
129
- rescue
130
- 'node not found'
104
+ def version(node, group)
105
+ repo, path = yield_repo_and_path(node, group)
106
+
107
+ repo = Git.open repo
108
+ unlock repo
109
+ walker = repo.log.path(path)
110
+ i = -1
111
+ tab = []
112
+ walker.each do |commit|
113
+ hash = {}
114
+ hash[:date] = commit.date.to_s
115
+ hash[:oid] = commit.objectish
116
+ hash[:author] = commit.author
117
+ hash[:message] = commit.message
118
+ tab[i += 1] = hash
131
119
  end
120
+ walker.reset
121
+ tab
122
+ rescue StandardError
123
+ 'node not found'
132
124
  end
133
125
 
134
126
  # give the blob of a specific revision
135
- def get_version node, group, oid
136
- begin
137
- repo, path = yield_repo_and_path(node, group)
138
- repo = Git.open repo
139
- unlock repo
140
- repo.gtree(oid).files[path].contents
141
- rescue
142
- 'version not found'
143
- ensure
144
- lock repo
145
- end
127
+ def get_version(node, group, oid)
128
+ repo, path = yield_repo_and_path(node, group)
129
+ repo = Git.open repo
130
+ unlock repo
131
+ repo.gtree(oid).files[path].contents
132
+ rescue StandardError
133
+ 'version not found'
134
+ ensure
135
+ lock repo
146
136
  end
147
137
 
148
138
  # give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
149
- def get_diff node, group, oid1, oid2
150
- begin
151
- diff_commits = nil
152
- repo, path = yield_repo_and_path(node, group)
153
- repo = Git.open repo
154
- unlock repo
155
- commit = repo.gcommit(oid1)
156
-
157
- if oid2
158
- commit_old = repo.gcommit(oid2)
159
- diff = repo.diff(commit_old, commit)
160
- stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]]
161
- diff.each do |patch|
162
- if /#{node.name}\s+/.match(patch.patch.to_s.lines.first)
163
- diff_commits = { :patch => patch.patch.to_s, :stat => stats }
164
- break
165
- end
139
+ def get_diff(node, group, oid1, oid2)
140
+ diff_commits = nil
141
+ repo, _path = yield_repo_and_path(node, group)
142
+ repo = Git.open repo
143
+ unlock repo
144
+ commit = repo.gcommit(oid1)
145
+
146
+ if oid2
147
+ commit_old = repo.gcommit(oid2)
148
+ diff = repo.diff(commit_old, commit)
149
+ stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]]
150
+ diff.each do |patch|
151
+ if /#{node.name}\s+/ =~ patch.patch.to_s.lines.first
152
+ diff_commits = { patch: patch.patch.to_s, stat: stats }
153
+ break
166
154
  end
167
- else
168
- stat = commit.parents[0].diff(commit).stats
169
- stat = [stat[:files][node.name][:insertions], stat[:files][node.name][:deletions]]
170
- patch = commit.parents[0].diff(commit).patch
171
- diff_commits = { :patch => patch, :stat => stat }
172
155
  end
173
- lock repo
174
- diff_commits
175
- rescue
176
- 'no diffs'
177
- ensure
178
- lock repo
156
+ else
157
+ stat = commit.parents[0].diff(commit).stats
158
+ stat = [stat[:files][node.name][:insertions], stat[:files][node.name][:deletions]]
159
+ patch = commit.parents[0].diff(commit).patch
160
+ diff_commits = { patch: patch, stat: stat }
179
161
  end
162
+ lock repo
163
+ diff_commits
164
+ rescue StandardError
165
+ 'no diffs'
166
+ ensure
167
+ lock repo
180
168
  end
181
169
 
182
170
  private
@@ -184,14 +172,12 @@ module Oxidized
184
172
  def yield_repo_and_path(node, group)
185
173
  repo, path = node.repo, node.name
186
174
 
187
- if group and @cfg.single_repo?
188
- path = "#{group}/#{node.name}"
189
- end
175
+ path = "#{group}/#{node.name}" if group && @cfg.single_repo?
190
176
 
191
177
  [repo, path]
192
178
  end
193
179
 
194
- def update repo, file, data
180
+ def update(repo, file, data)
195
181
  return if data.empty?
196
182
 
197
183
  if @opt[:group]
@@ -213,14 +199,14 @@ module Oxidized
213
199
  begin
214
200
  grepo = Git.init repo
215
201
  crypt_init grepo
216
- rescue => create_error
202
+ rescue StandardError => create_error
217
203
  raise GitCryptError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
218
204
  end
219
205
  retry
220
206
  end
221
207
  end
222
208
 
223
- def update_repo repo, file, data, msg, user, email
209
+ def update_repo(repo, file, data, msg, user, email)
224
210
  grepo = Git.open repo
225
211
  grepo.config('user.name', user)
226
212
  grepo.config('user.email', email)
@@ -6,25 +6,25 @@ module Oxidized
6
6
  end
7
7
 
8
8
  def setup
9
- if @cfg.empty?
10
- CFGS.user.output.http.user = 'Oxidized'
11
- CFGS.user.output.http.pasword = 'secret'
12
- CFGS.user.output.http.url = 'http://localhost/web-api/oxidized'
13
- CFGS.save :user
14
- raise NoConfig, 'no output http config, edit ~/.config/oxidized/config'
15
- end
9
+ return unless @cfg.empty?
10
+
11
+ CFGS.user.output.http.user = 'Oxidized'
12
+ CFGS.user.output.http.pasword = 'secret'
13
+ CFGS.user.output.http.url = 'http://localhost/web-api/oxidized'
14
+ CFGS.save :user
15
+ raise NoConfig, 'no output http config, edit ~/.config/oxidized/config'
16
16
  end
17
17
 
18
18
  require "net/http"
19
19
  require "uri"
20
20
  require "json"
21
21
 
22
- def store node, outputs, opt = {}
22
+ def store(node, outputs, opt = {})
23
23
  @commitref = nil
24
24
  uri = URI.parse @cfg.url
25
25
  http = Net::HTTP.new uri.host, uri.port
26
26
  # http.use_ssl = true if uri.scheme = 'https'
27
- req = Net::HTTP::Post.new(uri.request_uri, initheader = { 'Content-Type' => 'application/json' })
27
+ req = Net::HTTP::Post.new(uri.request_uri, 'Content-Type' => 'application/json')
28
28
  req.basic_auth @cfg.user, @cfg.password
29
29
  req.body = generate_json(node, outputs, opt)
30
30
  response = http.request req
@@ -44,17 +44,15 @@ module Oxidized
44
44
 
45
45
  private
46
46
 
47
- def generate_json node, outputs, opt
47
+ def generate_json(node, outputs, opt)
48
48
  JSON.pretty_generate(
49
- {
50
- 'msg' => opt[:msg],
51
- 'user' => opt[:user],
52
- 'email' => opt[:email],
53
- 'group' => opt[:group],
54
- 'node' => node,
55
- 'config' => outputs.to_cfg,
56
- # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
57
- }
49
+ 'msg' => opt[:msg],
50
+ 'user' => opt[:user],
51
+ 'email' => opt[:email],
52
+ 'group' => opt[:group],
53
+ 'node' => node,
54
+ 'config' => outputs.to_cfg
55
+ # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
58
56
  )
59
57
  end
60
58
  end
@@ -2,7 +2,7 @@ module Oxidized
2
2
  class Output
3
3
  class NoConfig < OxidizedError; end
4
4
 
5
- def cfg_to_str cfg
5
+ def cfg_to_str(cfg)
6
6
  cfg.select { |h| h[:type] == 'cfg' }.map { |h| h[:data] }.join
7
7
  end
8
8
  end
@@ -18,10 +18,10 @@ module Oxidized
18
18
  require 'gpgme' if @cfg.gpg?
19
19
  end
20
20
 
21
- def load _node_want = nil
21
+ def load(_node_want = nil)
22
22
  nodes = []
23
23
  open_file.each_line do |line|
24
- next if line.match(/^\s*#/)
24
+ next if line =~ /^\s*#/
25
25
 
26
26
  data = line.chomp.split(@cfg.delimiter, -1)
27
27
  next if data.empty?
@@ -53,7 +53,7 @@ module Oxidized
53
53
  crypto = GPGME::Crypto.new password: @cfg.gpg_password
54
54
  crypto.decrypt(File.open(file)).to_s
55
55
  else
56
- open(file)
56
+ File.open(file)
57
57
  end
58
58
  end
59
59
  end
@@ -6,9 +6,9 @@ module Oxidized
6
6
  end
7
7
 
8
8
  def setup
9
- if @cfg.url.empty?
10
- raise NoConfig, 'no source http url config, edit ~/.config/oxidized/config'
11
- end
9
+ return unless @cfg.url.empty?
10
+
11
+ raise NoConfig, 'no source http url config, edit ~/.config/oxidized/config'
12
12
  end
13
13
 
14
14
  require "net/http"
@@ -16,7 +16,7 @@ module Oxidized
16
16
  require "uri"
17
17
  require "json"
18
18
 
19
- def load node_want = nil
19
+ def load(node_want = nil)
20
20
  nodes = []
21
21
  data = JSON.parse(read_http(node_want))
22
22
  data = string_navigate(data, @cfg.hosts_location) if @cfg.hosts_location?
@@ -44,17 +44,18 @@ module Oxidized
44
44
 
45
45
  private
46
46
 
47
- def string_navigate object, wants
48
- wants.split(".").map do |want|
47
+ def string_navigate(object, wants)
48
+ wants = wants.split(".").map do |want|
49
49
  head, match, _tail = want.partition(/\[\d+\]/)
50
50
  match.empty? ? head : [head, match[1..-2].to_i]
51
- end.flatten.each do |want|
51
+ end
52
+ wants.flatten.each do |want|
52
53
  object = object[want] if object.respond_to? :each
53
54
  end
54
55
  object
55
56
  end
56
57
 
57
- def read_http node_want
58
+ def read_http(node_want)
58
59
  uri = URI.parse(@cfg.url)
59
60
  http = Net::HTTP.new(uri.host, uri.port)
60
61
  http.use_ssl = true if uri.scheme == 'https'
@@ -67,13 +68,9 @@ module Oxidized
67
68
  end
68
69
 
69
70
  req_uri = uri.request_uri
70
- if node_want
71
- req_uri = "#{req_uri}/#{node_want}"
72
- end
71
+ req_uri = "#{req_uri}/#{node_want}" if node_want
73
72
  request = Net::HTTP::Get.new(req_uri, headers)
74
- if (@cfg.user? && @cfg.pass?)
75
- request.basic_auth(@cfg.user, @cfg.pass)
76
- end
73
+ request.basic_auth(@cfg.user, @cfg.pass) if @cfg.user? && @cfg.pass?
77
74
  http.request(request).body
78
75
  end
79
76
  end
@@ -3,14 +3,14 @@ module Oxidized
3
3
  class NoConfig < OxidizedError; end
4
4
 
5
5
  def initialize
6
- @map = (Oxidized.config.model_map or {})
6
+ @map = (Oxidized.config.model_map || {})
7
7
  end
8
8
 
9
- def map_model model
9
+ def map_model(model)
10
10
  @map.has_key?(model) ? @map[model] : model
11
11
  end
12
12
 
13
- def node_var_interpolate var
13
+ def node_var_interpolate(var)
14
14
  case var
15
15
  when "nil" then nil
16
16
  when "false" then false
@@ -7,26 +7,24 @@ module Oxidized
7
7
  end
8
8
 
9
9
  def setup
10
- if @cfg.empty?
11
- Oxidized.asetus.user.source.sql.adapter = 'sqlite'
12
- Oxidized.asetus.user.source.sql.database = File.join(Config::Root, 'sqlite.db')
13
- Oxidized.asetus.user.source.sql.table = 'devices'
14
- Oxidized.asetus.user.source.sql.map.name = 'name'
15
- Oxidized.asetus.user.source.sql.map.model = 'rancid'
16
- Oxidized.asetus.save :user
17
- raise NoConfig, 'no source sql config, edit ~/.config/oxidized/config'
18
- end
10
+ return unless @cfg.empty?
11
+
12
+ Oxidized.asetus.user.source.sql.adapter = 'sqlite'
13
+ Oxidized.asetus.user.source.sql.database = File.join(Config::Root, 'sqlite.db')
14
+ Oxidized.asetus.user.source.sql.table = 'devices'
15
+ Oxidized.asetus.user.source.sql.map.name = 'name'
16
+ Oxidized.asetus.user.source.sql.map.model = 'rancid'
17
+ Oxidized.asetus.save :user
18
+ raise NoConfig, 'no source sql config, edit ~/.config/oxidized/config'
19
19
  end
20
20
 
21
- def load node_want = nil
21
+ def load(node_want = nil)
22
22
  nodes = []
23
23
  db = connect
24
24
  query = db[@cfg.table.to_sym]
25
25
  query = query.with_sql(@cfg.query) if @cfg.query?
26
26
 
27
- if node_want
28
- query = query.where(@cfg.map.name.to_sym => node_want)
29
- end
27
+ query = query.where(@cfg.map.name.to_sym => node_want) if node_want
30
28
 
31
29
  query.each do |node|
32
30
  # map node parameters
@@ -55,11 +53,11 @@ module Oxidized
55
53
  end
56
54
 
57
55
  def connect
58
- Sequel.connect(:adapter => @cfg.adapter,
59
- :host => @cfg.host?,
60
- :user => @cfg.user?,
61
- :password => @cfg.password?,
62
- :database => @cfg.database)
56
+ Sequel.connect(adapter: @cfg.adapter,
57
+ host: @cfg.host?,
58
+ user: @cfg.user?,
59
+ password: @cfg.password?,
60
+ database: @cfg.database)
63
61
  rescue Sequel::AdapterNotFound => error
64
62
  raise OxidizedError, "SQL adapter gem not installed: " + error.message
65
63
  end