diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..c6842ef --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,87 @@ +AllCops: + TargetRubyVersion: '2.3' + +Layout/EmptyLineAfterGuardClause: + Enabled: false + +# allows nicer usage of private_class_method +Layout/EmptyLinesAroundArguments: + Enabled: false + +Layout/HashAlignment: + Enabled: false + +Layout/LeadingEmptyLines: + Enabled: false + +Layout/LineLength: + Max: 200 + +Layout/SpaceInsideHashLiteralBraces: + Enabled: false + +Metrics/AbcSize: + Enabled: false + +Metrics/BlockLength: + Enabled: false + +Metrics/ClassLength: + Enabled: false + +Metrics/CyclomaticComplexity: + Enabled: false + +Metrics/MethodLength: + Enabled: false + +Metrics/PerceivedComplexity: + Enabled: false + +Naming/MethodParameterName: + Enabled: false + +Naming/MemoizedInstanceVariableName: + Enabled: false + +Style/ConditionalAssignment: + Enabled: false + +Style/Documentation: + Enabled: false + +Style/FormatStringToken: + Enabled: false + +Style/FrozenStringLiteralComment: + Enabled: false + +Style/GuardClause: + Enabled: false + +Style/HashEachMethods: + Enabled: true + +Style/HashTransformKeys: + Enabled: true + +Style/HashTransformValues: + Enabled: true + +Style/IdenticalConditionalBranches: + Enabled: false + +Style/InverseMethods: + Enabled: false + +Style/NegatedIf: + Enabled: false + +Style/RescueModifier: + Enabled: false + +Style/Semicolon: + AllowAsExpressionSeparator: true + +Style/SymbolArray: + Enabled: false diff --git a/Rakefile b/Rakefile index d964e6a..ba57a1f 100644 --- a/Rakefile +++ b/Rakefile @@ -1,8 +1,10 @@ require 'bundler/gem_tasks' require 'rspec/core/rake_task' +require 'rubocop/rake_task' require 'bundler/audit/task' RSpec::Core::RakeTask.new(:spec) +RuboCop::RakeTask.new Bundler::Audit::Task.new desc 'Should be run by developer once to prepare initial solargraph usage (fill caches etc.)' @@ -15,6 +17,6 @@ task :'solargraph:tc' do sh 'solargraph typecheck' end -task :default => [:spec, 'bundle:audit'] +task default: [:rubocop, :spec, 'bundle:audit'] task travis: [:default, :'solargraph:tc'] diff --git a/lib/openvpn-status-web.rb b/lib/openvpn-status-web.rb old mode 100644 new mode 100755 index 3769aa1..838e823 --- a/lib/openvpn-status-web.rb +++ b/lib/openvpn-status-web.rb @@ -8,7 +8,7 @@ require 'yaml' require 'rack' require 'erb' require 'metriks' -require 'better_errors' if ENV['RACK_ENV'] == "development" +require 'better_errors' if ENV['RACK_ENV'] == 'development' require 'openvpn-status-web/status' require 'openvpn-status-web/parser/v1' @@ -27,8 +27,8 @@ module OpenVPNStatusWeb end class LogFormatter - def call(lvl, time, progname, msg) - "[%s] %-5s %s\n" % [Time.now.strftime('%Y-%m-%d %H:%M:%S'), lvl, msg.to_s] + def call(lvl, _time, _progname, msg) + format("[%s] %-5s %s\n", Time.now.strftime('%Y-%m-%d %H:%M:%S'), lvl, msg.to_s) end end @@ -40,29 +40,29 @@ module OpenVPNStatusWeb end def call(env) - return [405, {"Content-Type" => "text/plain"}, ["Method Not Allowed"]] if env["REQUEST_METHOD"] != "GET" - return [404, {"Content-Type" => "text/plain"}, ["Not Found"]] if env["PATH_INFO"] != "/" + return [405, {'Content-Type' => 'text/plain'}, ['Method Not Allowed']] if env['REQUEST_METHOD'] != 'GET' + return [404, {'Content-Type' => 'text/plain'}, ['Not Found']] if env['PATH_INFO'] != '/' # variables for template vpns = @vpns stati = {} - @vpns.each do |name,config| + @vpns.each do |name, config| stati[name] = parse_status_log(config) end # eval html = @main_tmpl.result(binding) - [200, {"Content-Type" => "text/html"}, [html]] + [200, {'Content-Type' => 'text/html'}, [html]] end def read_template(file) - text = File.open(file, 'rb') do |f| f.read end - + text = File.open(file, 'rb', &:read) + ERB.new(text) end - + def parse_status_log(vpn) - text = File.open(vpn['status_file'], 'rb') do |f| f.read end + text = File.open(vpn['status_file'], 'rb', &:read) case vpn['version'] when 1 @@ -78,21 +78,21 @@ module OpenVPNStatusWeb def self.run! if ARGV.length != 1 - puts "Usage: openvpn-status-web config_file" + puts 'Usage: openvpn-status-web config_file' exit 1 end config_file = ARGV[0] - if not File.file?(config_file) - puts "Config file not found!" + if !File.file?(config_file) + puts 'Config file not found!' exit 1 end - + puts "openvpn-status-web version #{OpenVPNStatusWeb::VERSION}" puts "Using config file #{config_file}" - config = YAML::load(File.open(config_file, 'r') { |f| f.read }) + config = YAML.safe_load(File.open(config_file, 'r', &:read)) if config['logfile'] OpenVPNStatusWeb.logger = Logger.new(config['logfile']) @@ -100,10 +100,10 @@ module OpenVPNStatusWeb OpenVPNStatusWeb.logger = Logger.new(STDOUT) end - OpenVPNStatusWeb.logger.progname = "openvpn-status-web" + OpenVPNStatusWeb.logger.progname = 'openvpn-status-web' OpenVPNStatusWeb.logger.formatter = LogFormatter.new - OpenVPNStatusWeb.logger.info "Starting..." + OpenVPNStatusWeb.logger.info 'Starting...' # drop privs (first change group than user) Process::Sys.setgid(Etc.getgrnam(config['group']).gid) if config['group'] @@ -111,21 +111,21 @@ module OpenVPNStatusWeb # configure rack app = Daemon.new(config['vpns']) - if ENV['RACK_ENV'] == "development" + if ENV['RACK_ENV'] == 'development' app = BetterErrors::Middleware.new(app) - BetterErrors.application_root = File.expand_path("..", __FILE__) + BetterErrors.application_root = File.expand_path(__dir__) end Signal.trap('INT') do - OpenVPNStatusWeb.logger.info "Quitting..." + OpenVPNStatusWeb.logger.info 'Quitting...' Rack::Handler::WEBrick.shutdown end Signal.trap('TERM') do - OpenVPNStatusWeb.logger.info "Quitting..." + OpenVPNStatusWeb.logger.info 'Quitting...' Rack::Handler::WEBrick.shutdown end - - Rack::Handler::WEBrick.run app, :Host => config['host'], :Port => config['port'] + + Rack::Handler::WEBrick.run app, Host: config['host'], Port: config['port'] end end end diff --git a/lib/openvpn-status-web/int_patch.rb b/lib/openvpn-status-web/int_patch.rb index 2e57f80..f8baf7b 100644 --- a/lib/openvpn-status-web/int_patch.rb +++ b/lib/openvpn-status-web/int_patch.rb @@ -1,16 +1,16 @@ class Integer def as_bytes - return "1 Byte" if self == 1 - - label = ["Bytes", "KiB", "MiB", "GiB", "TiB"] + return '1 Byte' if self == 1 + + label = %w[Bytes KiB MiB GiB TiB] i = 0 - num = self.to_f - while num >= 1024 do - num = num / 1024 + num = to_f + while num >= 1024 + num /= 1024 i += 1 end - + "#{format('%.2f', num)} #{label[i]}" end end diff --git a/lib/openvpn-status-web/parser/modern_stateless.rb b/lib/openvpn-status-web/parser/modern_stateless.rb index ab78dc9..84b8f56 100644 --- a/lib/openvpn-status-web/parser/modern_stateless.rb +++ b/lib/openvpn-status-web/parser/modern_stateless.rb @@ -10,29 +10,27 @@ module OpenVPNStatusWeb text.lines.each do |line| parts = line.strip.split(sep) - status.client_list << parse_client(parts[1..5]) if parts[0] == "CLIENT_LIST" - status.routing_table << parse_route(parts[1..4]) if parts[0] == "ROUTING_TABLE" - status.global_stats << parse_global(parts[1..2]) if parts[0] == "GLOBAL_STATS" + status.client_list << parse_client(parts[1..5]) if parts[0] == 'CLIENT_LIST' + status.routing_table << parse_route(parts[1..4]) if parts[0] == 'ROUTING_TABLE' + status.global_stats << parse_global(parts[1..2]) if parts[0] == 'GLOBAL_STATS' end status end - private - - def self.parse_client(client) + private_class_method def self.parse_client(client) client[2] = client[2].to_i client[3] = client[3].to_i client[4] = DateTime.strptime(client[4], '%a %b %d %k:%M:%S %Y') client end - def self.parse_route(route) + private_class_method def self.parse_route(route) route[3] = DateTime.strptime(route[3], '%a %b %d %k:%M:%S %Y') route end - def self.parse_global(global) + private_class_method def self.parse_global(global) global[1] = global[1].to_i global end diff --git a/lib/openvpn-status-web/parser/v1.rb b/lib/openvpn-status-web/parser/v1.rb index f3fb067..4eb2b4a 100644 --- a/lib/openvpn-status-web/parser/v1.rb +++ b/lib/openvpn-status-web/parser/v1.rb @@ -13,7 +13,7 @@ module OpenVPNStatusWeb (current_section = :rt; next) if line == "ROUTING TABLE\n" (current_section = :gs; next) if line == "GLOBAL STATS\n" (current_section = :end; next) if line == "END\n" - + case current_section when :cl client_list << line.strip.split(',') diff --git a/lib/openvpn-status-web/version.rb b/lib/openvpn-status-web/version.rb index 89ff39e..6ff45ad 100644 --- a/lib/openvpn-status-web/version.rb +++ b/lib/openvpn-status-web/version.rb @@ -1,4 +1,4 @@ module OpenVPNStatusWeb - VERSION = "2.0.0" + VERSION = '2.0.0'.freeze end diff --git a/openvpn-status-web.gemspec b/openvpn-status-web.gemspec index 62ba657..fdc33bb 100644 --- a/openvpn-status-web.gemspec +++ b/openvpn-status-web.gemspec @@ -26,9 +26,10 @@ Gem::Specification.new do |s| s.add_development_dependency 'better_errors' s.add_development_dependency 'binding_of_caller' s.add_development_dependency 'bundler' - s.add_development_dependency 'bundler-audit' + s.add_development_dependency 'bundler-audit', '~> 0.6.0' s.add_development_dependency 'rack-test' s.add_development_dependency 'rake' s.add_development_dependency 'rspec' + s.add_development_dependency 'rubocop', '~> 0.80.0' s.add_development_dependency 'solargraph' end diff --git a/spec/parser/modern_stateless_spec.rb b/spec/parser/modern_stateless_spec.rb index 1f3c512..8e2c52e 100644 --- a/spec/parser/modern_stateless_spec.rb +++ b/spec/parser/modern_stateless_spec.rb @@ -8,47 +8,56 @@ describe OpenVPNStatusWeb::Parser::ModernStateless do context "for status-version #{version}" do context 'for client list' do it 'parses common names' do - expect(status.client_list.map { |client| client[0] }).to eq(["foo", "bar"]) + expect(status.client_list.map { |client| client[0] }).to eq(%w[foo bar]) end it 'parses real addresses' do - expect(status.client_list.map { |client| client[1] }).to eq(["1.2.3.4:1234", "1.2.3.5:1235"]) + expect(status.client_list.map { |client| client[1] }).to eq(['1.2.3.4:1234', '1.2.3.5:1235']) end it 'parses received bytes' do - expect(status.client_list.map { |client| client[2] }).to eq([11811160064, 512]) + expect(status.client_list.map { |client| client[2] }).to eq([11_811_160_064, 512]) end it 'parses sent bytes' do - expect(status.client_list.map { |client| client[3] }).to eq([4194304, 2048]) + expect(status.client_list.map { |client| client[3] }).to eq([4_194_304, 2048]) end it 'parses connected since date' do - expect(status.client_list.map { |client| client[4] }).to eq([DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0)]) + expect(status.client_list.map { |client| client[4] }).to eq( + [ + DateTime.new(2012, 1, 1, 23, 42, 0), DateTime.new(2012, 1, 1, 23, 42, 0) + ] + ) end end context 'for routing table' do it 'parses virtual addresses' do - expect(status.routing_table.map { |route| route[0] }).to eq(["192.168.0.0/24", "192.168.66.2", "192.168.66.3", "2001:db8:0:0::1000"]) + expect(status.routing_table.map { |route| route[0] }).to eq(['192.168.0.0/24', '192.168.66.2', '192.168.66.3', '2001:db8:0:0::1000']) end it 'parses common names' do - expect(status.routing_table.map { |route| route[1] }).to eq(["foo", "bar", "foo", "bar"]) + expect(status.routing_table.map { |route| route[1] }).to eq(%w[foo bar foo bar]) end it 'parses real addresses' do - expect(status.routing_table.map { |route| route[2] }).to eq(["1.2.3.4:1234", "1.2.3.5:1235", "1.2.3.4:1234", "1.2.3.5:1235"]) + expect(status.routing_table.map { |route| route[2] }).to eq(['1.2.3.4:1234', '1.2.3.5:1235', '1.2.3.4:1234', '1.2.3.5:1235']) end it 'parses last ref date' do - expect(status.routing_table.map { |route| route[3] }).to eq([DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0)]) + expect(status.routing_table.map { |route| route[3] }).to eq( + [ + DateTime.new(2012, 1, 1, 23, 42, 0), DateTime.new(2012, 1, 1, 23, 42, 0), + DateTime.new(2012, 1, 1, 23, 42, 0), DateTime.new(2012, 1, 1, 23, 42, 0) + ] + ) end end it 'parses global stats' do expect(status.global_stats.size).to eq(1) - expect(status.global_stats.first).to eq(["Max bcast/mcast queue length", 42]) + expect(status.global_stats.first).to eq(['Max bcast/mcast queue length', 42]) end end end diff --git a/spec/parser/v1_spec.rb b/spec/parser/v1_spec.rb index 778fa03..9abfe9d 100644 --- a/spec/parser/v1_spec.rb +++ b/spec/parser/v1_spec.rb @@ -1,50 +1,61 @@ require 'spec_helper' describe OpenVPNStatusWeb::Parser::V1 do - def status; status_v1; end + def status + status_v1 + end context 'for client list' do it 'parses common names' do - expect(status.client_list.map { |client| client[0] }).to eq(["foo", "bar"]) + expect(status.client_list.map { |client| client[0] }).to eq(%w[foo bar]) end it 'parses real addresses' do - expect(status.client_list.map { |client| client[1] }).to eq(["1.2.3.4:1234", "1.2.3.5:1235"]) + expect(status.client_list.map { |client| client[1] }).to eq(['1.2.3.4:1234', '1.2.3.5:1235']) end it 'parses received bytes' do - expect(status.client_list.map { |client| client[2] }).to eq([11811160064, 512]) + expect(status.client_list.map { |client| client[2] }).to eq([11_811_160_064, 512]) end it 'parses sent bytes' do - expect(status.client_list.map { |client| client[3] }).to eq([4194304, 2048]) + expect(status.client_list.map { |client| client[3] }).to eq([4_194_304, 2048]) end it 'parses connected since date' do - expect(status.client_list.map { |client| client[4] }).to eq([DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0)]) + expect(status.client_list.map { |client| client[4] }).to eq( + [ + DateTime.new(2012, 1, 1, 23, 42, 0), DateTime.new(2012, 1, 1, 23, 42, 0) + ] + ) end end context 'for routing table' do it 'parses virtual addresses' do - expect(status.routing_table.map { |route| route[0] }).to eq(["192.168.0.0/24", "192.168.66.2", "192.168.66.3", "2001:db8:0:0::1000"]) + expect(status.routing_table.map { |route| route[0] }).to eq(['192.168.0.0/24', '192.168.66.2', '192.168.66.3', '2001:db8:0:0::1000']) end it 'parses common names' do - expect(status.routing_table.map { |route| route[1] }).to eq(["foo", "bar", "foo", "bar"]) + expect(status.routing_table.map { |route| route[1] }).to eq(%w[foo bar foo bar]) end it 'parses real addresses' do - expect(status.routing_table.map { |route| route[2] }).to eq(["1.2.3.4:1234", "1.2.3.5:1235", "1.2.3.4:1234", "1.2.3.5:1235"]) + expect(status.routing_table.map { |route| route[2] }).to eq(['1.2.3.4:1234', '1.2.3.5:1235', '1.2.3.4:1234', '1.2.3.5:1235']) end it 'parses last ref date' do - expect(status.routing_table.map { |route| route[3] }).to eq([DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0), DateTime.new(2012,1,1,23,42,0)]) + expect(status.routing_table.map { |route| route[3] }).to eq( + [ + DateTime.new(2012, 1, 1, 23, 42, 0), DateTime.new(2012, 1, 1, 23, 42, 0), + DateTime.new(2012, 1, 1, 23, 42, 0), DateTime.new(2012, 1, 1, 23, 42, 0) + ] + ) end end it 'parses global stats' do expect(status.global_stats.size).to eq(1) - expect(status.global_stats.first).to eq(["Max bcast/mcast queue length", 42]) + expect(status.global_stats.first).to eq(['Max bcast/mcast queue length', 42]) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4e66db5..ca9d8d4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,16 +6,16 @@ require 'rack/test' require 'openvpn-status-web' def status_v1 - text = File.open('examples/status.v1', 'rb') do |f| f.read end + text = File.open('examples/status.v1', 'rb', &:read) OpenVPNStatusWeb::Parser::V1.new.parse_status_log text end def status_v2 - text = File.open('examples/status.v2', 'rb') do |f| f.read end + text = File.open('examples/status.v2', 'rb', &:read) OpenVPNStatusWeb::Parser::V2.new.parse_status_log text end def status_v3 - text = File.open('examples/status.v3', 'rb') do |f| f.read end + text = File.open('examples/status.v3', 'rb', &:read) OpenVPNStatusWeb::Parser::V3.new.parse_status_log text end