From 57a8f4bc04b4f87ad0d7028dcbf29b96d49eaffd Mon Sep 17 00:00:00 2001 From: Saku Ytti Date: Mon, 14 Apr 2014 16:28:23 +0300 Subject: Use 'asetus' for configuration files Main benefits a) we get support for system wide configs b) we don't use symbols in config file, they're confusing to non-rubyist --- lib/oxidized/cli.rb | 48 ++++++++++++++++++++++++++++++++++++++++ lib/oxidized/config.rb | 44 ++++++++++++++++++++++++++++++++++++ lib/oxidized/config/bootstrap.rb | 33 --------------------------- lib/oxidized/config/core.rb | 33 --------------------------- lib/oxidized/config/defaults.rb | 14 ------------ lib/oxidized/core.rb | 2 +- lib/oxidized/input/ssh.rb | 14 ++++++------ lib/oxidized/input/telnet.rb | 2 +- lib/oxidized/node.rb | 4 ++-- lib/oxidized/nodes.rb | 2 +- lib/oxidized/output/file.rb | 15 ++++++------- lib/oxidized/output/git.rb | 23 +++++++++---------- lib/oxidized/output/output.rb | 1 + lib/oxidized/source/csv.rb | 27 ++++++++++------------ lib/oxidized/source/source.rb | 1 + lib/oxidized/source/sql.rb | 29 +++++++++++------------- 16 files changed, 149 insertions(+), 143 deletions(-) create mode 100644 lib/oxidized/cli.rb create mode 100644 lib/oxidized/config.rb delete mode 100644 lib/oxidized/config/bootstrap.rb delete mode 100644 lib/oxidized/config/core.rb delete mode 100644 lib/oxidized/config/defaults.rb (limited to 'lib') diff --git a/lib/oxidized/cli.rb b/lib/oxidized/cli.rb new file mode 100644 index 0000000..720f405 --- /dev/null +++ b/lib/oxidized/cli.rb @@ -0,0 +1,48 @@ +module Oxidized + class CLI + require 'oxidized' + require 'slop' + class CLIError < OxidizedError; end + class NoConfig < CLIError; end + + def run + Process.daemon unless CFG.debug + begin + Oxidized.new + rescue => error + crash error + raise + end + end + + private + + def initialize + if CFGS.system.empty? and CFGS.user.empty? + CFGS.user = CFGS.default + CFGS.save :user + raise NoConfig, 'edit ~/.config/oxidized/config' + end + _args, opts = parse_opts + CFG.debug = true if opts[:debug] + end + + def crash error + open Config::Crash, 'w' do |file| + file.puts '-' * 50 + file.puts Time.now.utc + file.puts error.message + ' [' + error.class.to_s + ']' + file.puts '-' * 50 + file.puts error.backtrace + file.puts '-' * 50 + end + end + + def parse_opts + opts = Slop.new(:help=>true) do + on 'd', 'debug', 'turn on debugging' + end + [opts.parse!, opts] + end + end +end diff --git a/lib/oxidized/config.rb b/lib/oxidized/config.rb new file mode 100644 index 0000000..475ae14 --- /dev/null +++ b/lib/oxidized/config.rb @@ -0,0 +1,44 @@ +module Oxidized + require 'asetus' + class Config + Root = File.join ENV['HOME'], '.config', 'oxidized' + Crash = File.join Root, 'crash' + InputDir = File.join Directory, %w(lib oxidized input) + OutputDir = File.join Directory, %w(lib oxidized output) + ModelDir = File.join Directory, %w(lib oxidized model) + SourceDir = File.join Directory, %w(lib oxidized source) + Sleep = 1 + end + class << self + attr_accessor :mgr + end + CFGS = Asetus.new :name=>'oxidized', :load=>false, :key_to_s=>true + CFGS.default.username = 'username' + CFGS.default.password = 'password' + CFGS.default.model = 'junos' + CFGS.default.interval = 3600 + CFGS.default.log = File.join Config::Root, 'log' + CFGS.default.debug = false + CFGS.default.threads = 30 + CFGS.default.timeout = 30 + CFGS.default.prompt = /^([\w.@-]+[#>]\s?)$/ + CFGS.default.rest = '0.0.0.0:8888' # or false to disable + CFGS.default.vars = {} # could be 'enable'=>'enablePW' + + CFGS.default.input.default = 'ssh, telnet' + CFGS.default.input.ssh.secure = false + + CFGS.default.output.default = 'git' + CFGS.default.source.default = 'csv' + + CFGS.default.model_map = { + 'cisco' => 'ios', + 'juniper' => 'junos', + } + + CFGS.load # load system+user configs, merge to Config.cfg + CFG = CFGS.cfg # convenienence, instead of Config.cfg.password, CFG.password + + Log.level = Logger::INFO unless CFG.debug + Log.file = CFG.log if CFG.log +end diff --git a/lib/oxidized/config/bootstrap.rb b/lib/oxidized/config/bootstrap.rb deleted file mode 100644 index 008d88a..0000000 --- a/lib/oxidized/config/bootstrap.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Oxidized - require 'fileutils' - FileUtils.mkdir_p Config::Root - CFG.username = 'username' - CFG.password = 'password' - CFG.model = 'junos' - CFG.interval = 3600 - CFG.log = File.join Config::Root, 'log' - CFG.debug = false - CFG.threads = 30 - CFG.timeout = 30 - CFG.prompt = /^([\w.@-]+[#>]\s?)$/ - CFG.rest = '0.0.0.0:8888' - CFG.vars = { - #:enable => 'enablePW', - } - CFG.input = { - :default => 'ssh, telnet', - :ssh => { - :secure => false, - } - } - CFG.output = { - :default => 'git', - } - CFG.source = { - :default => 'csv', - } - CFG.model_map = { - 'cisco' => 'ios', - 'juniper' => 'junos', - } -end diff --git a/lib/oxidized/config/core.rb b/lib/oxidized/config/core.rb deleted file mode 100644 index 59ada3a..0000000 --- a/lib/oxidized/config/core.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Oxidized - require 'ostruct' - require 'yaml' - class Config < OpenStruct - require 'oxidized/config/defaults' - # @param file [string] configuration file location - def initialize file=File.join(Config::Root, 'config') - super() - @file = file.to_s - end - # load config from file or bootstrap with built-ins - def load - if File.exists? @file - cfg = YAML.load_file @file - marshal_load marshal_dump.merge(cfg) - else - save - end - end - def defaults - require 'oxidized/config/bootstrap' - end - # save config to file - def save - File.write @file, YAML.dump(marshal_dump) - end - end - CFG = Config.new - CFG.defaults - CFG.load - Log.level = Logger::INFO unless CFG.debug - Log.file = CFG.log if CFG.log -end diff --git a/lib/oxidized/config/defaults.rb b/lib/oxidized/config/defaults.rb deleted file mode 100644 index c30143f..0000000 --- a/lib/oxidized/config/defaults.rb +++ /dev/null @@ -1,14 +0,0 @@ -module Oxidized - class Config - Root = File.join ENV['HOME'], '.config', 'oxidized' - Crash = File.join Root, 'crash' - InputDir = File.join Directory, %w(lib oxidized input) - OutputDir = File.join Directory, %w(lib oxidized output) - ModelDir = File.join Directory, %w(lib oxidized model) - SourceDir = File.join Directory, %w(lib oxidized source) - Sleep = 1 - end - class << self - attr_accessor :mgr - end -end diff --git a/lib/oxidized/core.rb b/lib/oxidized/core.rb index 14de9ab..3c728b6 100644 --- a/lib/oxidized/core.rb +++ b/lib/oxidized/core.rb @@ -1,6 +1,6 @@ module Oxidized require 'oxidized/log' - require 'oxidized/config/core' + require 'oxidized/config' require 'oxidized/worker' require 'oxidized/nodes' require 'oxidized/manager' diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index dae1d74..570f8a8 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -12,14 +12,14 @@ module Oxidized Net::SSH::AuthenticationFailed, ], } - include CLI + include Input::CLI class NoShell < OxidizedError; end def connect node @node = node @output = '' @node.model.cfg['ssh'].each { |cb| instance_exec(&cb) } - secure = CFG.input[:ssh][:secure] + secure = CFG.input.ssh.secure @ssh = Net::SSH.start @node.ip, @node.auth[:username], :password => @node.auth[:password], :timeout => CFG.timeout, :paranoid => secure @@ -64,14 +64,14 @@ module Oxidized def shell_open ssh @ses = ssh.open_channel do |ch| - ch.on_data do |ch, data| + ch.on_data do |_ch, data| @output << data @output = @node.model.expects @output end - ch.request_pty do |ch, success| - raise NoShell, "Can't get PTY" unless success - ch.send_channel_request 'shell' do |ch, success| - raise NoShell, "Can't get shell" unless success + ch.request_pty do |_ch, success_pty| + raise NoShell, "Can't get PTY" unless success_pty + ch.send_channel_request 'shell' do |_ch, success_shell| + raise NoShell, "Can't get shell" unless success_shell end end end diff --git a/lib/oxidized/input/telnet.rb b/lib/oxidized/input/telnet.rb index 4e80ceb..218b13c 100644 --- a/lib/oxidized/input/telnet.rb +++ b/lib/oxidized/input/telnet.rb @@ -3,7 +3,7 @@ module Oxidized require 'oxidized/input/cli' class Telnet < Input RescueFail = {} - include CLI + include Input::CLI attr_reader :telnet def connect node diff --git a/lib/oxidized/node.rb b/lib/oxidized/node.rb index 0cb5cb3..3ac1c90 100644 --- a/lib/oxidized/node.rb +++ b/lib/oxidized/node.rb @@ -106,7 +106,7 @@ module Oxidized end def resolve_input opt - inputs = (opt[:input] or CFG.input[:default]) + inputs = (opt[:input] or CFG.input.default) inputs.split(/\s*,\s*/).map do |input| if not Oxidized.mgr.input[input] Oxidized.mgr.add_input input or raise MethodNotFound, "#{input} not found for node #{ip}" @@ -116,7 +116,7 @@ module Oxidized end def resolve_output opt - output = (opt[:output] or CFG.output[:default]) + output = (opt[:output] or CFG.output.default) if not Oxidized.mgr.output[output] Oxidized.mgr.add_output output or raise MethodNotFound, "#{output} not found for node #{ip}" end diff --git a/lib/oxidized/nodes.rb b/lib/oxidized/nodes.rb index 8dadaef..213f534 100644 --- a/lib/oxidized/nodes.rb +++ b/lib/oxidized/nodes.rb @@ -10,7 +10,7 @@ module Oxidized with_lock do new = [] node_want_ip = (IPAddr.new(node_want) rescue nil) if node_want - @source = CFG.source[:default] + @source = CFG.source.default Oxidized.mgr.add_source @source Oxidized.mgr.source[@source].new.load.each do |node| diff --git a/lib/oxidized/output/file.rb b/lib/oxidized/output/file.rb index ee8a9a6..f3443b4 100644 --- a/lib/oxidized/output/file.rb +++ b/lib/oxidized/output/file.rb @@ -3,20 +3,19 @@ class OxFile < Output require 'fileutils' def initialize - @cfg = CFG.output[:file] + @cfg = CFG.output.file end def setup - if not @cfg - CFG.output[:file] = { - :directory => File.join(Config::Root, 'configs') - } - CFG.save + if @cfg.empty? + CFGS.user.output.file.directory = File.join(Config::Root, 'configs') + CFGS.save :user + raise NoConfig, 'no output file config, edit ~/.config/oxidized/config' end end def store node, data, opt={} - file = @cfg[:directory] + file = @cfg.directory if opt[:group] file = File.join File.dirname(file), opt[:group] end @@ -26,7 +25,7 @@ class OxFile < Output end def fetch node, group - cfg_dir = @cfg[:directory] + cfg_dir = @cfg.directory if group # group is explicitly defined by user IO.readlines File.join(cfg_dir, group, node) else diff --git a/lib/oxidized/output/git.rb b/lib/oxidized/output/git.rb index b4fa4a8..ff9237b 100644 --- a/lib/oxidized/output/git.rb +++ b/lib/oxidized/output/git.rb @@ -5,25 +5,24 @@ class Git < Output include Grit def initialize - @cfg = CFG.output[:git] + @cfg = CFG.output.git end def setup - if not @cfg - CFG.output[:git] = { - :user => 'Oxidized', - :email => 'o@example.com', - :repo => File.join(Config::Root, 'oxidized.git') - } - CFG.save + if @cfg.empty? + CFGS.user.output.git.user = 'Oxidized' + CFGS.user.output.git.email = 'o@example.com' + CFGS.user.output.git.repo = File.join(Config::Root, 'oxidized.git') + CFGS.save :user + raise NoConfig, 'no output git config, edit ~/.config/oxidized/config' end end def store file, data, opt={} msg = opt[:msg] - user = (opt[:user] or @cfg[:user]) - email = (opt[:email] or @cfg[:email]) - repo = @cfg[:repo] + user = (opt[:user] or @cfg.user) + email = (opt[:email] or @cfg.email) + repo = @cfg.repo if opt[:group] repo = File.join File.dirname(repo), opt[:group] + '.git' end @@ -41,7 +40,7 @@ class Git < Output def fetch node, group begin - repo = Repo.new(@cfg[:repo]) + repo = Repo.new(@cfg.repo) (repo.tree / node).data rescue 'node not found' diff --git a/lib/oxidized/output/output.rb b/lib/oxidized/output/output.rb index 61cb2b5..54d616c 100644 --- a/lib/oxidized/output/output.rb +++ b/lib/oxidized/output/output.rb @@ -1,5 +1,6 @@ module Oxidized class Output + class NoConfig < OxidizedError; end class << self def inherited klass Oxidized.mgr.loader = { :class => klass } diff --git a/lib/oxidized/source/csv.rb b/lib/oxidized/source/csv.rb index cf73fc8..9d291c7 100644 --- a/lib/oxidized/source/csv.rb +++ b/lib/oxidized/source/csv.rb @@ -1,31 +1,28 @@ module Oxidized class CSV < Source def initialize - @cfg = CFG.source[:csv] + @cfg = CFG.source.csv super end def setup - if not @cfg - CFG.source[:csv] = { - :file => File.join(Config::Root, 'router.db'), - :delimiter => /:/, - :map => { - :name => 0, - :model => 1, - } - } - CFG.save + if @cfg.empty? + CFGS.user.source.csv.file = File.join(Config::Root, 'router.db') + CFGS.user.source.csv.delimiter = /:/ + CFGS.user.source.csv.map.name = 0 + CFGS.user.source.csv.map.model = 1 + CFGS.save :user + raise NoConfig, 'no source csv config, edit ~/.config/oxidized/config' end end def load nodes = [] - open(@cfg[:file]).each_line do |line| - data = line.chomp.split @cfg[:delimiter] + open(@cfg.file).each_line do |line| + data = line.chomp.split @cfg.delimiter keys = {} - @cfg[:map].each do |key, position| - keys[key] = data[position] + @cfg.map.each do |key, position| + keys[key.to_sym] = data[position] end keys[:model] = map_model keys[:model] if keys.key? :model nodes << keys diff --git a/lib/oxidized/source/source.rb b/lib/oxidized/source/source.rb index f5976a0..93c9b6f 100644 --- a/lib/oxidized/source/source.rb +++ b/lib/oxidized/source/source.rb @@ -1,5 +1,6 @@ module Oxidized class Source + class NoConfig < OxidizedError; end class << self def inherited klass Oxidized.mgr.loader = { :class => klass } diff --git a/lib/oxidized/source/sql.rb b/lib/oxidized/source/sql.rb index 385f632..f84a7a8 100644 --- a/lib/oxidized/source/sql.rb +++ b/lib/oxidized/source/sql.rb @@ -4,34 +4,31 @@ class SQL < Source def initialize super - @cfg = CFG.source[:sql] + @cfg = CFG.source.sql end def setup - if not @cfg - CFG.source[:sql] = { - :adapter => 'sqlite', - :file => File.join(Config::Root, 'sqlite.db'), - :table => 'devices', - :map => { - :name => 'name', - :model => 'rancid', - } - } - CFG.save + if @cfg.empty? + CFGS.user.source.sql.adapter = 'sqlite' + CFGS.user.source.sql.file = File.join(Config::Root, 'sqlite.db') + CFGS.user.source.sql.table = 'devices' + CFGS.user.source.sql.map.name = 'name' + CFGS.user.source.sql.map.model = 'rancid' + CFGS.save :user + raise NoConfig, 'no source sql config, edit ~/.config/oxidized/config' end end def load nodes = [] - db = case @cfg[:adapter] + db = case @cfg.adapter when 'sqlite' require 'sqlite3' - Sequel.sqlite @cfg[:file] + Sequel.sqlite @cfg.file end - db[@cfg[:table].to_sym].each do |node| + db[@cfg.table.to_sym].each do |node| keys = {} - @cfg[:map].each { |key, sql_column| keys[key] = node[sql_column.to_sym] } + @cfg.map.each { |key, sql_column| keys[key.to_sym] = node[sql_column.to_sym] } keys[:model] = map_model keys[:model] if keys.key? :model nodes << keys end -- cgit v1.2.1