diff options
Diffstat (limited to 'lib/oxidized')
-rw-r--r-- | lib/oxidized/hook/xmppdiff.rb | 86 | ||||
-rw-r--r-- | lib/oxidized/manager.rb | 4 | ||||
-rw-r--r-- | lib/oxidized/model/aosw.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/asa.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/asyncos.rb | 88 | ||||
-rw-r--r-- | lib/oxidized/model/ciscosma.rb | 80 | ||||
-rw-r--r-- | lib/oxidized/model/comware.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/cumulus.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/firewareos.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/netgear.rb | 5 | ||||
-rw-r--r-- | lib/oxidized/model/powerconnect.rb | 4 | ||||
-rw-r--r-- | lib/oxidized/model/procurve.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/routeros.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/vrp.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/zhoneolt.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/output/gitcrypt.rb | 484 | ||||
-rw-r--r-- | lib/oxidized/source/csv.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/source/http.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/source/sql.rb | 2 |
19 files changed, 387 insertions, 388 deletions
diff --git a/lib/oxidized/hook/xmppdiff.rb b/lib/oxidized/hook/xmppdiff.rb index 396d1b3..52cc0e0 100644 --- a/lib/oxidized/hook/xmppdiff.rb +++ b/lib/oxidized/hook/xmppdiff.rb @@ -7,54 +7,52 @@ class XMPPDiff < Oxidized::Hook raise KeyError, 'hook.password is required' unless cfg.has_key?('password') raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel') raise KeyError, 'hook.nick is required' unless cfg.has_key?('nick') - end + end def run_hook(ctx) - if ctx.node - if ctx.event.to_s == "post_store" - begin - Timeout::timeout(15) do - gitoutput = ctx.node.output.new - diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil - - interesting = diff[:patch].lines.to_a[4..-1].any? { |line| - ["+", "-"].include?(line[0]) and not ["#", "!"].include?(line[1]) - } - interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '-' } - interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '+' } - - if interesting - log "Connecting to XMPP" - client = Jabber::Client.new(Jabber::JID.new(cfg.jid)) - client.connect - sleep 1 - client.auth(cfg.password) - sleep 1 - - log "Connected" - - m = Jabber::MUC::SimpleMUCClient.new(client) - m.join(cfg.channel + "/" + cfg.nick) - - log "Joined" - - title = "#{ctx.node.name.to_s} #{ctx.node.group.to_s} #{ctx.node.model.class.name.to_s.downcase}" - log "Posting diff as snippet to #{cfg.channel}" - - m.say(title + "\n\n" + diff[:patch].lines.to_a[4..-1].join) - - sleep 1 - - client.close - - log "Finished" - - end - end - rescue Timeout::Error - log "timed out" + return unless ctx.node + return unless ctx.event.to_s == "post_store" + begin + Timeout.timeout(15) do + gitoutput = ctx.node.output.new + diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil + + interesting = diff[:patch].lines.to_a[4..-1].any? do |line| + ["+", "-"].include?(line[0]) and not ["#", "!"].include?(line[1]) + end + interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '-' } + interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '+' } + + if interesting + log "Connecting to XMPP" + client = Jabber::Client.new(Jabber::JID.new(cfg.jid)) + client.connect + sleep 1 + client.auth(cfg.password) + sleep 1 + + log "Connected" + + m = Jabber::MUC::SimpleMUCClient.new(client) + m.join(cfg.channel + "/" + cfg.nick) + + log "Joined" + + title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}" + log "Posting diff as snippet to #{cfg.channel}" + + m.say(title + "\n\n" + diff[:patch].lines.to_a[4..-1].join) + + sleep 1 + + client.close + + log "Finished" + end end + rescue Timeout::Error + log "timed out" end end end diff --git a/lib/oxidized/manager.rb b/lib/oxidized/manager.rb index bf28ae7..d2ef4d2 100644 --- a/lib/oxidized/manager.rb +++ b/lib/oxidized/manager.rb @@ -49,13 +49,13 @@ module Oxidized @model.merge! _model end def add_source _source - return nil if @source.key? _source + return nil if @source.has_key? _source _source = Manager.load Config::SourceDir, _source return false if _source.empty? @source.merge! _source end def add_hook _hook - return nil if @hook.key? _hook + return nil if @hook.has_key? _hook name = _hook _hook = Manager.load File.join(Config::Root, 'hook'), name _hook = Manager.load Config::HookDir, name if _hook.empty? diff --git a/lib/oxidized/model/aosw.rb b/lib/oxidized/model/aosw.rb index 71fde2e..3397305 100644 --- a/lib/oxidized/model/aosw.rb +++ b/lib/oxidized/model/aosw.rb @@ -40,7 +40,7 @@ class AOSW < Oxidized::Model end cmd 'show version' do |cfg| - cfg = cfg.each_line.select { |line| not line.match /(Switch|AP) uptime/i } + cfg = cfg.each_line.reject { |line| line.match /(Switch|AP) uptime/i } rstrip_cfg comment cfg.join end diff --git a/lib/oxidized/model/asa.rb b/lib/oxidized/model/asa.rb index 9df4206..bea0705 100644 --- a/lib/oxidized/model/asa.rb +++ b/lib/oxidized/model/asa.rb @@ -27,7 +27,7 @@ class ASA < Oxidized::Model cmd 'show version' do |cfg| # avoid commits due to uptime / ixo-router01 up 2 mins 28 secs / ixo-router01 up 1 days 2 hours - cfg = cfg.each_line.select { |line| not line.match /(\s+up\s+\d+\s+)|(.*days.*)/ } + cfg = cfg.each_line.reject { |line| line.match /(\s+up\s+\d+\s+)|(.*days.*)/ } cfg = cfg.join comment cfg end diff --git a/lib/oxidized/model/asyncos.rb b/lib/oxidized/model/asyncos.rb index 875690b..ac19e34 100644 --- a/lib/oxidized/model/asyncos.rb +++ b/lib/oxidized/model/asyncos.rb @@ -1,49 +1,49 @@ class AsyncOS < Oxidized::Model - # ESA prompt "(mail.example.com)> " - prompt /^\r*([(][\w. ]+[)][#>]\s+)$/ - comment '! ' - - # Select passphrase display option - expect /\[\S+\]>\s/ do |data, re| - send "3\n" - data.sub re, '' - end - - # handle paging - expect /-Press Any Key For More-+.*$/ do |data, re| - send " " - data.sub re, '' - end - - cmd 'version' do |cfg| - comment cfg - end + # ESA prompt "(mail.example.com)> " + prompt /^\r*([(][\w. ]+[)][#>]\s+)$/ + comment '! ' + + # Select passphrase display option + expect /\[\S+\]>\s/ do |data, re| + send "3\n" + data.sub re, '' + end + + # handle paging + expect /-Press Any Key For More-+.*$/ do |data, re| + send " " + data.sub re, '' + end + + cmd 'version' do |cfg| + comment cfg + end - cmd 'showconfig' do |cfg| - #Delete hour and date which change each run - #cfg.gsub! /\sCurrent Time: \S+\s\S+\s+\S+\s\S+\s\S+/, ' Current Time:' - # Delete select passphrase display option - cfg.gsub! /Choose the passphrase option:/, '' - cfg.gsub! /1. Mask passphrases \(Files with masked passphrases cannot be loaded using/, '' - cfg.gsub! /loadconfig command\)/, '' - cfg.gsub! /2. Encrypt passphrases/, '' - cfg.gsub! /3. Plain passphrases/, '' - cfg.gsub! /^3$/, '' - #Delete space - cfg.gsub! /\n\s{25,26}/, '' - #Delete after line - cfg.gsub! /([-\\\/,.\w><@]+)(\s{25,27})/,"\\1" - # Add a carriage return - cfg.gsub! /([-\\\/,.\w><@]+)(\s{6})([-\\\/,.\w><@]+)/,"\\1\n\\2\\3" - # Delete prompt - cfg.gsub! /^\r*([(][\w. ]+[)][#>]\s+)$/, '' - cfg + cmd 'showconfig' do |cfg| + #Delete hour and date which change each run + #cfg.gsub! /\sCurrent Time: \S+\s\S+\s+\S+\s\S+\s\S+/, ' Current Time:' + # Delete select passphrase display option + cfg.gsub! /Choose the passphrase option:/, '' + cfg.gsub! /1. Mask passphrases \(Files with masked passphrases cannot be loaded using/, '' + cfg.gsub! /loadconfig command\)/, '' + cfg.gsub! /2. Encrypt passphrases/, '' + cfg.gsub! /3. Plain passphrases/, '' + cfg.gsub! /^3$/, '' + #Delete space + cfg.gsub! /\n\s{25,26}/, '' + #Delete after line + cfg.gsub! /([-\\\/,.\w><@]+)(\s{25,27})/,"\\1" + # Add a carriage return + cfg.gsub! /([-\\\/,.\w><@]+)(\s{6})([-\\\/,.\w><@]+)/,"\\1\n\\2\\3" + # Delete prompt + cfg.gsub! /^\r*([(][\w. ]+[)][#>]\s+)$/, '' + cfg - end - - cfg :ssh do - pre_logout "exit" - end - + end + + cfg :ssh do + pre_logout "exit" + end + end diff --git a/lib/oxidized/model/ciscosma.rb b/lib/oxidized/model/ciscosma.rb index a52e38a..6777ad5 100644 --- a/lib/oxidized/model/ciscosma.rb +++ b/lib/oxidized/model/ciscosma.rb @@ -1,45 +1,45 @@ class CiscoSMA < Oxidized::Model - # SMA prompt "mail.example.com> " - prompt /^\r*([-\w. ]+\.[-\w. ]+\.[-\w. ]+[#>]\s+)$/ - comment '! ' - - # Select passphrase display option - expect /using loadconfig command\. \[Y\]\>/ do |data, re| - send "y\n" - data.sub re, '' - end - - # handle paging - expect /-Press Any Key For More-+.*$/ do |data, re| - send " " - data.sub re, '' - end - - cmd 'version' do |cfg| - comment cfg - end + # SMA prompt "mail.example.com> " + prompt /^\r*([-\w. ]+\.[-\w. ]+\.[-\w. ]+[#>]\s+)$/ + comment '! ' + + # Select passphrase display option + expect /using loadconfig command\. \[Y\]\>/ do |data, re| + send "y\n" + data.sub re, '' + end + + # handle paging + expect /-Press Any Key For More-+.*$/ do |data, re| + send " " + data.sub re, '' + end + + cmd 'version' do |cfg| + comment cfg + end - cmd 'showconfig' do |cfg| - #Delete hour and date which change each run - #cfg.gsub! /\sCurrent Time: \S+\s\S+\s+\S+\s\S+\s\S+/, ' Current Time:' - # Delete select passphrase display option - cfg.gsub! /Do you want to mask the password\? Files with masked passwords cannot be loaded/, '' - cfg.gsub! /^\s+y/, '' - # Delete space - cfg.gsub! /\n\s{25}/, '' - # Delete after line - cfg.gsub! /([\/\-,.\w><@]+)(\s{27})/,"\\1" - # Add a carriage return - cfg.gsub! /([\/\-,.\w><@]+)(\s{6,8})([\/\-,.\w><@]+)/,"\\1\n\\2\\3" - # Delete prompt - cfg.gsub! /^\r*([-\w. ]+\.[-\w. ]+\.[-\w. ]+[#>]\s+)$/, '' - cfg + cmd 'showconfig' do |cfg| + #Delete hour and date which change each run + #cfg.gsub! /\sCurrent Time: \S+\s\S+\s+\S+\s\S+\s\S+/, ' Current Time:' + # Delete select passphrase display option + cfg.gsub! /Do you want to mask the password\? Files with masked passwords cannot be loaded/, '' + cfg.gsub! /^\s+y/, '' + # Delete space + cfg.gsub! /\n\s{25}/, '' + # Delete after line + cfg.gsub! /([\/\-,.\w><@]+)(\s{27})/,"\\1" + # Add a carriage return + cfg.gsub! /([\/\-,.\w><@]+)(\s{6,8})([\/\-,.\w><@]+)/,"\\1\n\\2\\3" + # Delete prompt + cfg.gsub! /^\r*([-\w. ]+\.[-\w. ]+\.[-\w. ]+[#>]\s+)$/, '' + cfg - end - - cfg :ssh do - pre_logout "exit" - end - + end + + cfg :ssh do + pre_logout "exit" + end + end diff --git a/lib/oxidized/model/comware.rb b/lib/oxidized/model/comware.rb index a5b7190..0ba26d5 100644 --- a/lib/oxidized/model/comware.rb +++ b/lib/oxidized/model/comware.rb @@ -47,7 +47,7 @@ class Comware < Oxidized::Model end cmd 'display version' do |cfg| - cfg = cfg.each_line.select {|l| not l.match /uptime/i }.join + cfg = cfg.each_line.reject { |l| l.match /uptime/i }.join comment cfg end diff --git a/lib/oxidized/model/cumulus.rb b/lib/oxidized/model/cumulus.rb index 20acb8a..09f3955 100644 --- a/lib/oxidized/model/cumulus.rb +++ b/lib/oxidized/model/cumulus.rb @@ -68,7 +68,7 @@ class Cumulus < Oxidized::Model cfg += add_comment 'TRAFFIC' cfg += cmd 'cat /etc/cumulus/datapath/traffic.conf' - + cfg += add_comment 'ACL' cfg += cmd 'iptables -L -n' diff --git a/lib/oxidized/model/firewareos.rb b/lib/oxidized/model/firewareos.rb index 1b3d07c..31770dc 100644 --- a/lib/oxidized/model/firewareos.rb +++ b/lib/oxidized/model/firewareos.rb @@ -15,7 +15,7 @@ class FirewareOS < Oxidized::Model cmd 'show sysinfo' do |cfg| # avoid commits due to uptime - cfg = cfg.each_line.select { |line| not line.match /(.*time.*)|(.*memory.*)|(.*cpu.*)/ } + cfg = cfg.each_line.reject { |line| line.match /(.*time.*)|(.*memory.*)|(.*cpu.*)/ } cfg = cfg.join comment cfg end diff --git a/lib/oxidized/model/netgear.rb b/lib/oxidized/model/netgear.rb index 0ab1349..a32eb66 100644 --- a/lib/oxidized/model/netgear.rb +++ b/lib/oxidized/model/netgear.rb @@ -1,15 +1,16 @@ class Netgear < Oxidized::Model comment '!' - prompt /^(\([\w\-.]+\)\s[#>])$/ + prompt /^(\([\w\s\-.]+\)\s[#>])$/ cmd :secret do |cfg| cfg.gsub!(/password (\S+)/, 'password <hidden>') + cfg.gsub!(/encrypted (\S+)/, 'encrypted <hidden>') cfg end cfg :telnet do - username /^User:/ + username /^(User:|Applying Interface configuration, please wait ...)/ end cfg :telnet, :ssh do diff --git a/lib/oxidized/model/powerconnect.rb b/lib/oxidized/model/powerconnect.rb index f602a36..ca91e60 100644 --- a/lib/oxidized/model/powerconnect.rb +++ b/lib/oxidized/model/powerconnect.rb @@ -22,7 +22,7 @@ class PowerConnect < Oxidized::Model if (@stackable.nil?) @stackable = true if cfg.match /(U|u)nit\s/ end - cfg = cfg.split("\n").select { |line| not line[/Up\sTime/] } + cfg = cfg.split("\n").reject { |line| line[/Up\sTime/] } comment cfg.join("\n") + "\n" end @@ -72,7 +72,7 @@ class PowerConnect < Oxidized::Model end out << line.strip end - out = out.select { |line| not line[/Up\sTime/] } + out = out.reject { |line| line[/Up\sTime/] } out = comment out.join "\n" out << "\n" end diff --git a/lib/oxidized/model/procurve.rb b/lib/oxidized/model/procurve.rb index 444fb5b..705a814 100644 --- a/lib/oxidized/model/procurve.rb +++ b/lib/oxidized/model/procurve.rb @@ -67,7 +67,7 @@ class Procurve < Oxidized::Model # not supported on all models cmd 'show system information' do |cfg| - cfg = cfg.each_line.select { |line| not line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/ } + cfg = cfg.each_line.reject { |line| line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/ } cfg = cfg.join comment cfg end diff --git a/lib/oxidized/model/routeros.rb b/lib/oxidized/model/routeros.rb index 6717446..b62a3be 100644 --- a/lib/oxidized/model/routeros.rb +++ b/lib/oxidized/model/routeros.rb @@ -20,7 +20,7 @@ class RouterOS < Oxidized::Model cfg.gsub! /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/, '' # strip ANSI colours cfg.gsub! /\\\r\n\s+/, '' # strip new line cfg.gsub! /# inactive time\r\n/, '' # Remove time based system comment - cfg = cfg.split("\n").select { |line| not line[/^\#\s\w{3}\/\d{2}\/\d{4}.*$/] } + cfg = cfg.split("\n").reject { |line| line[/^\#\s\w{3}\/\d{2}\/\d{4}.*$/] } cfg.join("\n") + "\n" end end diff --git a/lib/oxidized/model/vrp.rb b/lib/oxidized/model/vrp.rb index 98229c3..e44f69e 100644 --- a/lib/oxidized/model/vrp.rb +++ b/lib/oxidized/model/vrp.rb @@ -25,7 +25,7 @@ class VRP < Oxidized::Model end cmd 'display version' do |cfg| - cfg = cfg.each_line.select {|l| not l.match /uptime/ }.join + cfg = cfg.each_line.reject { |l| l.match /uptime/ }.join comment cfg end diff --git a/lib/oxidized/model/zhoneolt.rb b/lib/oxidized/model/zhoneolt.rb index b60edb2..c50680c 100644 --- a/lib/oxidized/model/zhoneolt.rb +++ b/lib/oxidized/model/zhoneolt.rb @@ -39,7 +39,7 @@ class ZhoneOLT < Oxidized::Model end cmd 'dump console' do |cfg| - cfg = cfg.each_line.select { |line| not line.match /To Abort the operation enter Ctrl-C/ }.join + cfg = cfg.each_line.reject { |line| line.match /To Abort the operation enter Ctrl-C/ }.join end # zhone technically supports ssh, but it locks up a ton. Especially when diff --git a/lib/oxidized/output/gitcrypt.rb b/lib/oxidized/output/gitcrypt.rb index b0d80f2..0567458 100644 --- a/lib/oxidized/output/gitcrypt.rb +++ b/lib/oxidized/output/gitcrypt.rb @@ -1,244 +1,244 @@ module Oxidized - class GitCrypt < Output - class GitCryptError < OxidizedError; end - begin - require 'git' - rescue LoadError - raise OxidizedError, 'git not found: sudo gem install ruby-git' - end - - attr_reader :commitref - - def initialize - @cfg = Oxidized.config.output.gitcrypt - @gitcrypt_cmd = "/usr/bin/git-crypt" - @gitcrypt_init = @gitcrypt_cmd + " init" - @gitcrypt_unlock = @gitcrypt_cmd + " unlock" - @gitcrypt_lock = @gitcrypt_cmd + " lock" - @gitcrypt_adduser = @gitcrypt_cmd + " add-gpg-user --trusted " - end - - def setup - if @cfg.empty? - Oxidized.asetus.user.output.gitcrypt.user = 'Oxidized' - Oxidized.asetus.user.output.gitcrypt.email = 'o@example.com' - Oxidized.asetus.user.output.gitcrypt.repo = File.join(Config::Root, 'oxidized.git') - Oxidized.asetus.save :user - raise NoConfig, 'no output git config, edit ~/.config/oxidized/config' - end - - if @cfg.repo.respond_to?(:each) - @cfg.repo.each do |group, repo| - @cfg.repo["#{group}="] = File.expand_path repo - end - else - @cfg.repo = File.expand_path @cfg.repo - end - end - - def crypt_init repo - repo.chdir do - system(@gitcrypt_init) - @cfg.users.each do |user| - system("#{@gitcrypt_adduser} #{user}") - end - File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff") - repo.add(".gitattributes") - repo.commit("Initial commit: crypt all config files") - end - end - - def lock repo - repo.chdir do - system(@gitcrypt_lock) - end - end - - def unlock repo - repo.chdir do - system(@gitcrypt_unlock) - end - end - - def store file, outputs, opt={} - @msg = opt[:msg] - @user = (opt[:user] or @cfg.user) - @email = (opt[:email] or @cfg.email) - @opt = opt - @commitref = nil - repo = @cfg.repo - - outputs.types.each do |type| - type_cfg = '' - type_repo = File.join(File.dirname(repo), type + '.git') - outputs.type(type).each do |output| - (type_cfg << output; next) if not output.name - type_file = file + '--' + output.name - if @cfg.type_as_directory? - type_file = type + '/' + type_file - type_repo = repo - end - update type_repo, type_file, output - end - update type_repo, file, type_cfg - end - - update repo, file, outputs.to_cfg - end - - - def fetch node, group - begin - repo, path = yield_repo_and_path(node, group) - repo = Git.open repo - unlock repo - index = repo.index - # Empty repo ? - empty = File.exists? index.path - if empty - raise 'Empty git repo' - else - File.read path - end - lock repo - rescue - 'node not found' - end - end - - # give a hash of all oid revision for the given node, and the date of the commit - def version node, group - begin - repo, path = yield_repo_and_path(node, group) - - repo = Git.open repo - unlock repo - walker = repo.log.path(path) - i = -1 - tab = [] - walker.each do |commit| - hash = {} - hash[:date] = commit.date.to_s - hash[:oid] = commit.objectish - hash[:author] = commit.author - hash[:message] = commit.message - tab[i += 1] = hash - end - walker.reset - tab - rescue - 'node not found' - end - end - - #give the blob of a specific revision - def get_version node, group, oid - begin - repo, path = yield_repo_and_path(node, group) - repo = Git.open repo - unlock repo - repo.gtree(oid).files[path].contents - rescue - 'version not found' - ensure - lock repo - end - end - - #give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines) - def get_diff node, group, oid1, oid2 - begin - diff_commits = nil - repo, path = yield_repo_and_path(node, group) - repo = Git.open repo - unlock repo - commit = repo.gcommit(oid1) - - if oid2 - commit_old = repo.gcommit(oid2) - diff = repo.diff(commit_old, commit) - stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]] - diff.each do |patch| - if /#{node.name}\s+/.match(patch.patch.to_s.lines.first) - diff_commits = {:patch => patch.patch.to_s, :stat => stats} - break - end - end - else - stat = commit.parents[0].diff(commit).stats - stat = [stat[:files][node.name][:insertions],stat[:files][node.name][:deletions]] - patch = commit.parents[0].diff(commit).patch - diff_commits = {:patch => patch, :stat => stat} - end - lock repo - diff_commits - rescue - 'no diffs' - ensure - lock repo - end - end - - private - - def yield_repo_and_path(node, group) - repo, path = node.repo, node.name - - if group and @cfg.single_repo? - path = "#{group}/#{node.name}" - end - - [repo, path] - end - - def update repo, file, data - return if data.empty? - - if @opt[:group] - if @cfg.single_repo? - file = File.join @opt[:group], file - else - repo = if repo.is_a?(::String) - File.join File.dirname(repo), @opt[:group] + '.git' - else - repo[@opt[:group]] - end - end - end - - begin - update_repo repo, file, data, @msg, @user, @email - rescue Git::GitExecuteError, ArgumentError => open_error - Oxidized.logger.debug "open_error #{open_error} #{file}" - begin - grepo = Git.init repo - crypt_init grepo - rescue => create_error - raise GitCryptError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo" - end - retry - end - end - - def update_repo repo, file, data, msg, user, email - grepo = Git.open repo - grepo.config('user.name', user) - grepo.config('user.email', email) - grepo.chdir do - unlock grepo - File.write(file, data) - grepo.add(file) - if grepo.status[file].nil? - grepo.commit(msg) - @commitref = grepo.log(1).first.objectish - true - elsif !grepo.status[file].type.nil? - grepo.commit(msg) - @commitref = grepo.log(1).first.objectish - true - end - lock grepo - end - end - end + class GitCrypt < Output + class GitCryptError < OxidizedError; end + begin + require 'git' + rescue LoadError + raise OxidizedError, 'git not found: sudo gem install ruby-git' + end + + attr_reader :commitref + + def initialize + @cfg = Oxidized.config.output.gitcrypt + @gitcrypt_cmd = "/usr/bin/git-crypt" + @gitcrypt_init = @gitcrypt_cmd + " init" + @gitcrypt_unlock = @gitcrypt_cmd + " unlock" + @gitcrypt_lock = @gitcrypt_cmd + " lock" + @gitcrypt_adduser = @gitcrypt_cmd + " add-gpg-user --trusted " + end + + def setup + if @cfg.empty? + Oxidized.asetus.user.output.gitcrypt.user = 'Oxidized' + Oxidized.asetus.user.output.gitcrypt.email = 'o@example.com' + Oxidized.asetus.user.output.gitcrypt.repo = File.join(Config::Root, 'oxidized.git') + Oxidized.asetus.save :user + raise NoConfig, 'no output git config, edit ~/.config/oxidized/config' + end + + if @cfg.repo.respond_to?(:each) + @cfg.repo.each do |group, repo| + @cfg.repo["#{group}="] = File.expand_path repo + end + else + @cfg.repo = File.expand_path @cfg.repo + end + end + + def crypt_init repo + repo.chdir do + system(@gitcrypt_init) + @cfg.users.each do |user| + system("#{@gitcrypt_adduser} #{user}") + end + File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff") + repo.add(".gitattributes") + repo.commit("Initial commit: crypt all config files") + end + end + + def lock repo + repo.chdir do + system(@gitcrypt_lock) + end + end + + def unlock repo + repo.chdir do + system(@gitcrypt_unlock) + end + end + + def store file, outputs, opt={} + @msg = opt[:msg] + @user = (opt[:user] or @cfg.user) + @email = (opt[:email] or @cfg.email) + @opt = opt + @commitref = nil + repo = @cfg.repo + + outputs.types.each do |type| + type_cfg = '' + type_repo = File.join(File.dirname(repo), type + '.git') + outputs.type(type).each do |output| + (type_cfg << output; next) if not output.name + type_file = file + '--' + output.name + if @cfg.type_as_directory? + type_file = type + '/' + type_file + type_repo = repo + end + update type_repo, type_file, output + end + update type_repo, file, type_cfg + end + + update repo, file, outputs.to_cfg + end + + + def fetch node, group + begin + repo, path = yield_repo_and_path(node, group) + repo = Git.open repo + unlock repo + index = repo.index + # Empty repo ? + empty = File.exists? index.path + if empty + raise 'Empty git repo' + else + File.read path + end + lock repo + rescue + 'node not found' + end + end + + # give a hash of all oid revision for the given node, and the date of the commit + def version node, group + begin + repo, path = yield_repo_and_path(node, group) + + repo = Git.open repo + unlock repo + walker = repo.log.path(path) + i = -1 + tab = [] + walker.each do |commit| + hash = {} + hash[:date] = commit.date.to_s + hash[:oid] = commit.objectish + hash[:author] = commit.author + hash[:message] = commit.message + tab[i += 1] = hash + end + walker.reset + tab + rescue + 'node not found' + end + end + + #give the blob of a specific revision + def get_version node, group, oid + begin + repo, path = yield_repo_and_path(node, group) + repo = Git.open repo + unlock repo + repo.gtree(oid).files[path].contents + rescue + 'version not found' + ensure + lock repo + end + end + + #give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines) + def get_diff node, group, oid1, oid2 + begin + diff_commits = nil + repo, path = yield_repo_and_path(node, group) + repo = Git.open repo + unlock repo + commit = repo.gcommit(oid1) + + if oid2 + commit_old = repo.gcommit(oid2) + diff = repo.diff(commit_old, commit) + stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]] + diff.each do |patch| + if /#{node.name}\s+/.match(patch.patch.to_s.lines.first) + diff_commits = {:patch => patch.patch.to_s, :stat => stats} + break + end + end + else + stat = commit.parents[0].diff(commit).stats + stat = [stat[:files][node.name][:insertions],stat[:files][node.name][:deletions]] + patch = commit.parents[0].diff(commit).patch + diff_commits = {:patch => patch, :stat => stat} + end + lock repo + diff_commits + rescue + 'no diffs' + ensure + lock repo + end + end + + private + + def yield_repo_and_path(node, group) + repo, path = node.repo, node.name + + if group and @cfg.single_repo? + path = "#{group}/#{node.name}" + end + + [repo, path] + end + + def update repo, file, data + return if data.empty? + + if @opt[:group] + if @cfg.single_repo? + file = File.join @opt[:group], file + else + repo = if repo.is_a?(::String) + File.join File.dirname(repo), @opt[:group] + '.git' + else + repo[@opt[:group]] + end + end + end + + begin + update_repo repo, file, data, @msg, @user, @email + rescue Git::GitExecuteError, ArgumentError => open_error + Oxidized.logger.debug "open_error #{open_error} #{file}" + begin + grepo = Git.init repo + crypt_init grepo + rescue => create_error + raise GitCryptError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo" + end + retry + end + end + + def update_repo repo, file, data, msg, user, email + grepo = Git.open repo + grepo.config('user.name', user) + grepo.config('user.email', email) + grepo.chdir do + unlock grepo + File.write(file, data) + grepo.add(file) + if grepo.status[file].nil? + grepo.commit(msg) + @commitref = grepo.log(1).first.objectish + true + elsif !grepo.status[file].type.nil? + grepo.commit(msg) + @commitref = grepo.log(1).first.objectish + true + end + lock grepo + end + end + end end diff --git a/lib/oxidized/source/csv.rb b/lib/oxidized/source/csv.rb index 4814bd7..b61525e 100644 --- a/lib/oxidized/source/csv.rb +++ b/lib/oxidized/source/csv.rb @@ -36,7 +36,7 @@ class CSV < Source @cfg.map.each do |key, position| keys[key.to_sym] = node_var_interpolate data[position] end - keys[:model] = map_model keys[:model] if keys.key? :model + keys[:model] = map_model keys[:model] if keys.has_key? :model # map node specific vars vars = {} diff --git a/lib/oxidized/source/http.rb b/lib/oxidized/source/http.rb index 6c12f29..56a575b 100644 --- a/lib/oxidized/source/http.rb +++ b/lib/oxidized/source/http.rb @@ -43,7 +43,7 @@ class HTTP < Source want_positions = want_position.split('.') keys[key.to_sym] = node_var_interpolate node.dig(*want_positions) end - keys[:model] = map_model keys[:model] if keys.key? :model + keys[:model] = map_model keys[:model] if keys.has_key? :model # map node specific vars vars = {} diff --git a/lib/oxidized/source/sql.rb b/lib/oxidized/source/sql.rb index 13fc39b..ca3bcc3 100644 --- a/lib/oxidized/source/sql.rb +++ b/lib/oxidized/source/sql.rb @@ -27,7 +27,7 @@ class SQL < Source # map node parameters keys = {} @cfg.map.each { |key, sql_column| keys[key.to_sym] = node_var_interpolate node[sql_column.to_sym] } - keys[:model] = map_model keys[:model] if keys.key? :model + keys[:model] = map_model keys[:model] if keys.has_key? :model # map node specific vars vars = {} |