From 857e4ad770d9c2911242a09d567730e99dfd7ec8 Mon Sep 17 00:00:00 2001 From: Hari Dara Date: Wed, 8 Apr 2026 11:18:33 +0530 Subject: [PATCH] HBASE-30065: Address existing Rubocop errors/warning --- hbase-shell/src/main/ruby/hbase/hbase.rb | 10 +- hbase-shell/src/main/ruby/hbase_constants.rb | 156 +++++++++--------- hbase-shell/src/main/ruby/irb/hirb.rb | 4 +- hbase-shell/src/main/ruby/jar-bootstrap.rb | 4 +- hbase-shell/src/main/ruby/shell.rb | 113 +++++++------ hbase-shell/src/main/ruby/shell/commands.rb | 76 +++++---- .../test/ruby/shell/general_test_cluster.rb | 2 +- .../ruby/shell/noninteractive_test_cluster.rb | 2 +- hbase-shell/src/test/ruby/test_helper.rb | 2 +- 9 files changed, 191 insertions(+), 178 deletions(-) diff --git a/hbase-shell/src/main/ruby/hbase/hbase.rb b/hbase-shell/src/main/ruby/hbase/hbase.rb index a9b35ed1de21..3c4b3ea42c8b 100644 --- a/hbase-shell/src/main/ruby/hbase/hbase.rb +++ b/hbase-shell/src/main/ruby/hbase/hbase.rb @@ -17,10 +17,6 @@ # limitations under the License. # -include Java -java_import org.apache.hadoop.hbase.client.ConnectionFactory -java_import org.apache.hadoop.hbase.HBaseConfiguration - require 'hbase/admin' require 'hbase/table' require 'hbase/taskmonitor' @@ -28,7 +24,13 @@ require 'hbase/security' require 'hbase/visibility_labels' +# HBase module containing the main connection and admin classes module Hbase + include Java + java_import org.apache.hadoop.hbase.client.ConnectionFactory + java_import org.apache.hadoop.hbase.HBaseConfiguration + + # Main HBase class for connection and admin operations class Hbase attr_accessor :configuration diff --git a/hbase-shell/src/main/ruby/hbase_constants.rb b/hbase-shell/src/main/ruby/hbase_constants.rb index d4df1f8f5821..0f3282575082 100644 --- a/hbase-shell/src/main/ruby/hbase_constants.rb +++ b/hbase-shell/src/main/ruby/hbase_constants.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # # # Licensed to the Apache Software Foundation (ASF) under one @@ -25,89 +27,92 @@ # the hirb.rb HBase Shell script; they don't make much sense elsewhere. # For example, the exists method on Admin class prints to the formatter # whether the table exists and returns nil regardless. -include Java - -java_import('java.lang.Integer') { |_package, name| "J#{name}" } -java_import('java.lang.Long') { |_package, name| "J#{name}" } -java_import('java.lang.Boolean') { |_package, name| "J#{name}" } +# HBase constants module providing access to HBase Java constants and +# dynamically loading column family and table descriptor constants module HBaseConstants - ALLOW_PARTIAL_RESULTS = 'ALLOW_PARTIAL_RESULTS'.freeze - ALL_METRICS = 'ALL_METRICS'.freeze - ATTRIBUTES = 'ATTRIBUTES'.freeze - AUTHORIZATIONS = 'AUTHORIZATIONS'.freeze - BATCH = 'BATCH'.freeze - CACHE = 'CACHE'.freeze - CACHE_BLOCKS = 'CACHE_BLOCKS'.freeze - CLASSNAME = 'CLASSNAME'.freeze - CLONE_SFT = 'CLONE_SFT'.freeze - CLUSTER_KEY = 'CLUSTER_KEY'.freeze - COLUMN = 'COLUMN'.freeze - COLUMNS = 'COLUMNS'.freeze - CONFIG = 'CONFIG'.freeze + include Java + + java_import('java.lang.Integer') { |_package, name| "J#{name}" } + java_import('java.lang.Long') { |_package, name| "J#{name}" } + java_import('java.lang.Boolean') { |_package, name| "J#{name}" } + + ALLOW_PARTIAL_RESULTS = 'ALLOW_PARTIAL_RESULTS' + ALL_METRICS = 'ALL_METRICS' + ATTRIBUTES = 'ATTRIBUTES' + AUTHORIZATIONS = 'AUTHORIZATIONS' + BATCH = 'BATCH' + CACHE = 'CACHE' + CACHE_BLOCKS = 'CACHE_BLOCKS' + CLASSNAME = 'CLASSNAME' + CLONE_SFT = 'CLONE_SFT' + CLUSTER_KEY = 'CLUSTER_KEY' + COLUMN = 'COLUMN' + COLUMNS = 'COLUMNS' + CONFIG = 'CONFIG' CONFIGURATION = org.apache.hadoop.hbase.HConstants::CONFIGURATION - CONSISTENCY = 'CONSISTENCY'.freeze - COPROCESSOR = 'COPROCESSOR'.freeze - DATA = 'DATA'.freeze - ENDPOINT_CLASSNAME = 'ENDPOINT_CLASSNAME'.freeze - FILTER = 'FILTER'.freeze + CONSISTENCY = 'CONSISTENCY' + COPROCESSOR = 'COPROCESSOR' + DATA = 'DATA' + ENDPOINT_CLASSNAME = 'ENDPOINT_CLASSNAME' + FILTER = 'FILTER' FOREVER = org.apache.hadoop.hbase.HConstants::FOREVER - FORMATTER = 'FORMATTER'.freeze - FORMATTER_CLASS = 'FORMATTER_CLASS'.freeze - INTERVAL = 'INTERVAL'.freeze + FORMATTER = 'FORMATTER' + FORMATTER_CLASS = 'FORMATTER_CLASS' + INTERVAL = 'INTERVAL' IN_MEMORY = org.apache.hadoop.hbase.HConstants::IN_MEMORY IN_MEMORY_COMPACTION = org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder::IN_MEMORY_COMPACTION - ISOLATION_LEVEL = 'ISOLATION_LEVEL'.freeze - IS_ROOT = 'IS_ROOT'.freeze - JAR_PATH = 'JAR_PATH'.freeze - LIMIT = 'LIMIT'.freeze - LOCALITY_THRESHOLD = 'LOCALITY_THRESHOLD'.freeze - MAXLENGTH = 'MAXLENGTH'.freeze - MAX_RESULT_SIZE = 'MAX_RESULT_SIZE'.freeze + ISOLATION_LEVEL = 'ISOLATION_LEVEL' + IS_ROOT = 'IS_ROOT' + JAR_PATH = 'JAR_PATH' + LIMIT = 'LIMIT' + LOCALITY_THRESHOLD = 'LOCALITY_THRESHOLD' + MAXLENGTH = 'MAXLENGTH' + MAX_RESULT_SIZE = 'MAX_RESULT_SIZE' METADATA = org.apache.hadoop.hbase.HConstants::METADATA - METHOD = 'METHOD'.freeze - METRICS = 'METRICS'.freeze + METHOD = 'METHOD' + METRICS = 'METRICS' NAME = org.apache.hadoop.hbase.HConstants::NAME - NAMESPACE = 'NAMESPACE'.freeze - NAMESPACES = 'NAMESPACES'.freeze - NONE = 'NONE'.freeze - NUMREGIONS = 'NUMREGIONS'.freeze - POLICY = 'POLICY'.freeze - PRIORITY = 'PRIORITY'.freeze - PROPERTIES = 'PROPERTIES'.freeze - RAW = 'RAW'.freeze - READ_TYPE = 'READ_TYPE'.freeze - REGEX = 'REGEX'.freeze - REGIONSERVER = 'REGIONSERVER'.freeze - REGION_REPLICATION = 'REGION_REPLICATION'.freeze - REGION_REPLICA_ID = 'REGION_REPLICA_ID'.freeze - REMOTE_WAL_DIR = 'REMOTE_WAL_DIR'.freeze - REPLICATION_SCOPE = 'REPLICATION_SCOPE'.freeze + NAMESPACE = 'NAMESPACE' + NAMESPACES = 'NAMESPACES' + NONE = 'NONE' + NUMREGIONS = 'NUMREGIONS' + POLICY = 'POLICY' + PRIORITY = 'PRIORITY' + PROPERTIES = 'PROPERTIES' + RAW = 'RAW' + READ_TYPE = 'READ_TYPE' + REGEX = 'REGEX' + REGIONSERVER = 'REGIONSERVER' + REGION_REPLICATION = 'REGION_REPLICATION' + REGION_REPLICA_ID = 'REGION_REPLICA_ID' + REMOTE_WAL_DIR = 'REMOTE_WAL_DIR' + REPLICATION_SCOPE = 'REPLICATION_SCOPE' REPLICATION_SCOPE_BYTES = org.apache.hadoop.hbase.client.ColumnFamilyDescriptor::REPLICATION_SCOPE_BYTES - RESTORE_ACL = 'RESTORE_ACL'.freeze - REVERSED = 'REVERSED'.freeze - ROWPREFIXFILTER = 'ROWPREFIXFILTER'.freeze - SERIAL = 'SERIAL'.freeze - SERVER_NAME = 'SERVER_NAME'.freeze - SKIP_FLUSH = 'SKIP_FLUSH'.freeze - SPLITALGO = 'SPLITALGO'.freeze - SPLITS = 'SPLITS'.freeze - SPLITS_FILE = 'SPLITS_FILE'.freeze - STARTROW = 'STARTROW'.freeze - STATE = 'STATE'.freeze - STOPROW = 'STOPROW'.freeze - TABLE = 'TABLE'.freeze - TABLE_CFS = 'TABLE_CFS'.freeze - TABLE_NAME = 'TABLE_NAME'.freeze - TABLE_NAMES = 'TABLE_NAMES'.freeze - TIMERANGE = 'TIMERANGE'.freeze - TIMESTAMP = 'TIMESTAMP'.freeze - TYPE = 'TYPE'.freeze - USER = 'USER'.freeze - VALUE = 'VALUE'.freeze + RESTORE_ACL = 'RESTORE_ACL' + REVERSED = 'REVERSED' + ROWPREFIXFILTER = 'ROWPREFIXFILTER' + SERIAL = 'SERIAL' + SERVER_NAME = 'SERVER_NAME' + SKIP_FLUSH = 'SKIP_FLUSH' + SPLITALGO = 'SPLITALGO' + SPLITS = 'SPLITS' + SPLITS_FILE = 'SPLITS_FILE' + STARTROW = 'STARTROW' + STATE = 'STATE' + STOPROW = 'STOPROW' + TABLE = 'TABLE' + TABLE_CFS = 'TABLE_CFS' + TABLE_NAME = 'TABLE_NAME' + TABLE_NAMES = 'TABLE_NAMES' + TIMERANGE = 'TIMERANGE' + TIMESTAMP = 'TIMESTAMP' + TYPE = 'TYPE' + USER = 'USER' + VALUE = 'VALUE' VERSIONS = org.apache.hadoop.hbase.HConstants::VERSIONS - VISIBILITY = 'VISIBILITY'.freeze - REOPEN_REGIONS = 'REOPEN_REGIONS'.freeze + VISIBILITY = 'VISIBILITY' + REOPEN_REGIONS = 'REOPEN_REGIONS' # aliases ENDKEY = STOPROW @@ -119,8 +124,9 @@ def self.promote_constants(constants) # The constants to import are all in uppercase constants.each do |c| next if c =~ /DEFAULT_.*/ || c != c.upcase - next if eval("defined?(#{c})") - eval("#{c} = '#{c}'") + next if const_defined?(c) + + const_set(c, c.to_s) end end diff --git a/hbase-shell/src/main/ruby/irb/hirb.rb b/hbase-shell/src/main/ruby/irb/hirb.rb index 34638f228a9e..a77c1b1feef9 100644 --- a/hbase-shell/src/main/ruby/irb/hirb.rb +++ b/hbase-shell/src/main/ruby/irb/hirb.rb @@ -72,7 +72,7 @@ def output_value(omit = false) super(omit) unless @context.last_value.nil? end - # Copied from https://github.com/ruby/irb/blob/v1.4.2/lib/irb.rb + # Copied from https://github.com/ruby/irb/blob/v1.4.2/lib/irb.rb # We override the rescue Exception block so the # Shell::exception_handler can deal with the exceptions. def eval_input @@ -186,7 +186,7 @@ def eval_input warn "WARN: '#{var}' is a reserved HBase command. Local variable assignment ignored." end - new_binding = @context.workspace.main.get_binding + new_binding = @context.workspace.main.to_binding (workspace_binding.local_variables - shadowing_vars).each do |var| new_binding.local_variable_set(var, workspace_binding.local_variable_get(var)) end diff --git a/hbase-shell/src/main/ruby/jar-bootstrap.rb b/hbase-shell/src/main/ruby/jar-bootstrap.rb index e9844cfb223f..06779a07d942 100644 --- a/hbase-shell/src/main/ruby/jar-bootstrap.rb +++ b/hbase-shell/src/main/ruby/jar-bootstrap.rb @@ -172,7 +172,7 @@ def add_to_configuration(c, arg) @hbase = conf_from_cli.nil? ? Hbase::Hbase.new : Hbase::Hbase.new(conf_from_cli) # Setup console -@shell = Shell::Shell.new(@hbase, interactive) +@shell = Shell::Shell.new(@hbase, interactive: interactive) @shell.debug = @shell_debug ## @@ -227,7 +227,7 @@ def debug? IRB.conf[:USE_COLORIZE] = colorize # Create a workspace we'll use across sessions. -workspace = @shell.get_workspace +workspace = @shell.workspace # If script2run, try running it. If we're in interactive mode, will go on to run the shell unless # script calls 'exit' or 'exit 0' or 'exit errcode'. diff --git a/hbase-shell/src/main/ruby/shell.rb b/hbase-shell/src/main/ruby/shell.rb index 81baaf76d306..5774ff3073b9 100644 --- a/hbase-shell/src/main/ruby/shell.rb +++ b/hbase-shell/src/main/ruby/shell.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # # # Licensed to the Apache Software Foundation (ASF) under one @@ -24,7 +26,8 @@ # in our HBase shell. This will hold all the commands we want in our shell. # class HBaseReceiver < Object - def get_binding + # Returns the binding context for this receiver object + def to_binding binding end end @@ -39,38 +42,37 @@ def encoding end end - # Shell commands module module Shell - @@commands = {} - def self.commands - @@commands + class << self + attr_accessor :commands, :command_groups end - @@command_groups = {} - def self.command_groups - @@command_groups - end + @commands = {} + @command_groups = {} + # rubocop:disable Metrics/AbcSize def self.load_command(name, group, aliases = []) return if commands[name] # Register command in the group raise ArgumentError, "Unknown group: #{group}" unless command_groups[group] + command_groups[group][:commands] << name # Load command begin require "shell/commands/#{name}" klass_name = name.to_s.gsub(/(?:^|_)(.)/) { Regexp.last_match(1).upcase } # camelize - commands[name] = eval("Commands::#{klass_name}") + commands[name] = Commands.const_get(klass_name) aliases.each do |an_alias| commands[an_alias] = commands[name] end - rescue => e + rescue StandardError => e raise "Can't load hbase shell command: #{name}. Error: #{e}\n#{e.backtrace.join("\n")}" end end + # rubocop:enable Metrics/AbcSize def self.load_command_group(group, opts) raise ArgumentError, "No :commands for group #{group}" unless opts[:commands] @@ -93,17 +95,9 @@ def self.load_command_group(group, opts) #---------------------------------------------------------------------- # rubocop:disable Metrics/ClassLength class Shell - attr_accessor :hbase - attr_accessor :interactive + attr_accessor :hbase, :interactive, :debug, :exit_code alias interactive? interactive - @debug = false - attr_accessor :debug - - # keep track of the passed exit code. nil means never called. - @exit_code = nil - attr_accessor :exit_code - alias __exit__ exit # exit the interactive shell and save that this # happend via a call to exit @@ -112,7 +106,7 @@ def exit(ret = 0) IRB.irb_exit(IRB.CurrentContext.irb, ret) end - def initialize(hbase, interactive = true) + def initialize(hbase, interactive: true) self.hbase = hbase self.interactive = interactive end @@ -147,7 +141,7 @@ def hbase_quotas_admin end def hbase_rsgroup_admin - @rsgroup_admin ||= hbase.rsgroup_admin + @hbase_rsgroup_admin ||= hbase.rsgroup_admin end ## @@ -161,7 +155,7 @@ def export_commands(target) shell_inst = self # Define each method as a lambda. We need to use a lambda (rather than a Proc or block) for # its properties: preservation of local variables and return - ::Shell.commands.keys.each do |cmd| + ::Shell.commands.each_key do |cmd| target.send :define_singleton_method, cmd.to_sym, lambda { |*args| ret = shell_inst.command(cmd.to_s, *args) puts @@ -245,10 +239,12 @@ def help_group(group_name) nil end + # rubocop:disable Metrics/AbcSize def help(command = nil) if command return help_command(command) if ::Shell.commands[command.to_s] return help_group(command) if ::Shell.command_groups[command.to_s] + puts "ERROR: Invalid command or command group name: #{command}" puts end @@ -257,8 +253,8 @@ def help(command = nil) puts puts 'COMMAND GROUPS:' ::Shell.command_groups.each do |name, group| - puts ' Group name: ' + name - puts ' Commands: ' + group[:command_names].sort.join(', ') + puts " Group name: #{name}" + puts " Commands: #{group[:command_names].sort.join(', ')}" puts end unless command @@ -267,14 +263,19 @@ def help(command = nil) end nil end + # rubocop:enable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize def help_header "HBase Shell, version #{org.apache.hadoop.hbase.util.VersionInfo.getVersion}, " \ - "r#{org.apache.hadoop.hbase.util.VersionInfo.getRevision}, " \ - "#{org.apache.hadoop.hbase.util.VersionInfo.getDate}" + "\n" \ - "Type 'help \"COMMAND\"', (e.g. 'help \"get\"' -- the quotes are necessary) for help on a specific command.\n" \ - "Commands are grouped. Type 'help \"COMMAND_GROUP\"', (e.g. 'help \"general\"') for help on a command group." + "r#{org.apache.hadoop.hbase.util.VersionInfo.getRevision}, " \ + "#{org.apache.hadoop.hbase.util.VersionInfo.getDate}\n" \ + "Type 'help \"COMMAND\"', (e.g. 'help \"get\"' -- the quotes are necessary) " \ + "for help on a specific command.\n" \ + "Commands are grouped. Type 'help \"COMMAND_GROUP\"', " \ + "(e.g. 'help \"general\"') for help on a command group." end + # rubocop:enable Metrics/AbcSize def help_footer puts <<-HERE @@ -302,10 +303,9 @@ def help_footer HERE end - @irb_workspace = nil ## # Returns an IRB Workspace for this shell instance with all the IRB and HBase commands installed - def get_workspace + def workspace return @irb_workspace unless @irb_workspace.nil? hbase_receiver = HBaseReceiver.new @@ -320,12 +320,11 @@ def get_workspace } at_exit do # Non-deamon Netty threadpool in ZK ClientCnxnSocketNetty cannot be shut down otherwise - begin - hbase.shutdown - rescue Exception - end + hbase.shutdown + rescue StandardError + # Intentionally suppressed - cleanup on exit, allow system signals to propagate end - ::IRB::WorkSpace.new(hbase_receiver.get_binding) + ::IRB::WorkSpace.new(hbase_receiver.to_binding) end ## @@ -334,24 +333,21 @@ def get_workspace # @param [Boolean] hide_traceback if true, Exceptions will be converted to # a SystemExit so that the traceback is not printed def self.exception_handler(hide_traceback) - begin - yield - rescue Exception => e - message = e.to_s - # exception unwrapping in shell means we'll have to handle Java exceptions - # as a special case in order to format them properly. - if e.is_a? java.lang.Exception - warn 'java exception' - message = e.get_message - end - # Include the 'ERROR' string to try to make transition easier for scripts that - # may have already been relying on grepping output. - puts "ERROR #{e.class}: #{message}" - raise e unless hide_traceback - - exit 1 + yield + rescue StandardError => e + message = e.to_s + # exception unwrapping in shell means we'll have to handle Java exceptions + # as a special case in order to format them properly. + if e.is_a? java.lang.Exception + warn 'java exception' + message = e.get_message end - nil + # Include the 'ERROR' string to try to make transition easier for scripts that + # may have already been relying on grepping output. + puts "ERROR #{e.class}: #{message}" + raise e unless hide_traceback + + exit 1 end end # rubocop:enable Metrics/ClassLength @@ -586,7 +582,8 @@ def self.exception_handler(hide_traceback) Shell.load_command_group( 'security', full_name: 'SECURITY TOOLS', - comment: 'NOTE: Above commands are only applicable if running with the AccessController coprocessor', + comment: 'NOTE: Above commands are only applicable if running with the ' \ + 'AccessController coprocessor', commands: %w[ list_security_capabilities grant @@ -607,7 +604,8 @@ def self.exception_handler(hide_traceback) Shell.load_command_group( 'visibility labels', full_name: 'VISIBILITY LABEL TOOLS', - comment: 'NOTE: Above commands are only applicable if running with the VisibilityController coprocessor', + comment: 'NOTE: Above commands are only applicable if running with the ' \ + 'VisibilityController coprocessor', commands: %w[ add_labels list_labels @@ -621,8 +619,9 @@ def self.exception_handler(hide_traceback) Shell.load_command_group( 'rsgroup', full_name: 'RSGroups', - comment: "NOTE: The rsgroup Coprocessor Endpoint must be enabled on the Master else commands fail with: - UnknownProtocolException: No registered Master Coprocessor Endpoint found for RSGroupAdminService", + comment: 'NOTE: The rsgroup Coprocessor Endpoint must be enabled on the Master else ' \ + 'commands fail with: UnknownProtocolException: No registered Master ' \ + 'Coprocessor Endpoint found for RSGroupAdminService', commands: %w[ list_rsgroups get_rsgroup diff --git a/hbase-shell/src/main/ruby/shell/commands.rb b/hbase-shell/src/main/ruby/shell/commands.rb index a40f737e7908..29405b6df9b9 100644 --- a/hbase-shell/src/main/ruby/shell/commands.rb +++ b/hbase-shell/src/main/ruby/shell/commands.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # # # Licensed to the Apache Software Foundation (ASF) under one @@ -22,6 +24,7 @@ module Shell module Commands # rubocop:disable Metrics/ClassLength + # Base class for all HBase shell commands class Command def initialize(shell) @shell = shell @@ -31,15 +34,14 @@ def initialize(shell) def command_name klass_name = self.class.name.split('::').last - command = klass_name.gsub(/([^\^])([A-Z])/, '\1_\2').downcase - command + klass_name.gsub(/([^\^])([A-Z])/, '\1_\2').downcase end # wrap an execution of cmd to catch hbase exceptions # cmd - command name to execute # args - arguments to pass to the command - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity def command_safe(debug, cmd = :command, *args) # Commands can overwrite start_time to skip time used in some kind of setup. # See count.rb for example. @@ -47,29 +49,28 @@ def command_safe(debug, cmd = :command, *args) # send is internal ruby method to call 'cmd' with *args # (everything is a message, so this is just the formal semantics to support that idiom) translate_hbase_exceptions(*args) { send(cmd, *args) } - rescue => e - rootCause = e + rescue StandardError => e + root_cause = e # JRuby9000 made RubyException respond to cause, ignore it for back compat - while !rootCause.is_a?(Exception) && rootCause.respond_to?(:cause) && !rootCause.cause.nil? - rootCause = rootCause.cause - end - if @shell.interactive? - puts - puts "ERROR: #{rootCause}" - puts "Backtrace: #{rootCause.backtrace.join("\n ")}" if debug - puts - puts "For usage try 'help \"#{command_name}\"'" - puts - else - raise rootCause + while !root_cause.is_a?(Exception) && root_cause.respond_to?(:cause) && + !root_cause.cause.nil? + root_cause = root_cause.cause end + return raise root_cause unless @shell.interactive? + + puts + puts "ERROR: #{root_cause}" + puts "Backtrace: #{root_cause.backtrace.join("\n ")}" if debug + puts + puts "For usage try 'help \"#{command_name}\"'" + puts ensure # If end_time is not already set by the command, use current time. @end_time ||= Time.now formatter.output_str(format('Took %.4f seconds', @end_time - @start_time)) end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity # Convenience functions to get different admins # Returns HBase::Admin ruby class. @@ -112,22 +113,22 @@ def formatter end # for testing purposes to catch the output of the commands - def set_formatter(formatter) - @formatter = formatter - end + attr_writer :formatter - # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity + # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def translate_hbase_exceptions(*args) yield - rescue => cause + rescue StandardError => e + cause = e # let individual command handle exceptions first cause = cause.getCause if cause.is_a? java.io.UncheckedIOException + handle_exceptions(cause, *args) if respond_to?(:handle_exceptions) # Global HBase exception handling below if not handled by respective command above if cause.is_a?(org.apache.hadoop.hbase.TableNotFoundException) strs = cause.to_s.split(' ') raise "Unknown table #{strs[0]}!" if strs.size == 1 + raise "Unknown table #{args.first}!" end if cause.is_a?(org.apache.hadoop.hbase.TableNotEnabledException) @@ -136,32 +137,38 @@ def translate_hbase_exceptions(*args) if cause.is_a?(org.apache.hadoop.hbase.TableNotDisabledException) raise "Table #{cause.message} should be disabled!" end - if cause.is_a?(org.apache.hadoop.hbase.UnknownRegionException) - raise cause.message - end + + raise cause.message if cause.is_a?(org.apache.hadoop.hbase.UnknownRegionException) + if cause.is_a?(org.apache.hadoop.hbase.exceptions.MergeRegionException) strs = cause.message.split("\n") - raise(strs[0]).to_s unless strs.empty? + raise strs[0].to_s unless strs.empty? end + if cause.is_a?(org.apache.hadoop.hbase.NamespaceNotFoundException) s = /.*NamespaceNotFoundException: (?[^\n]+).*/.match(cause.message) + raise "Unknown namespace #{s['namespace']}!" end if cause.is_a?(org.apache.hadoop.hbase.snapshot.SnapshotDoesNotExistException) raise "Unknown snapshot #{args.first}!" end + if cause.is_a?(org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException) exceptions = cause.getCauses exceptions.each do |exception| - if exception.is_a?(org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException) - valid_cols = table(args.first).get_all_columns.map { |c| c + '*' } - raise "Unknown column family! Valid column names: #{valid_cols.join(', ')}" - end + next unless exception.is_a?( + org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException + ) + + valid_cols = table(args.first).get_all_columns.map { |c| "#{c}*" } + raise "Unknown column family! Valid column names: #{valid_cols.join(', ')}" end end if cause.is_a?(org.apache.hadoop.hbase.TableExistsException) strs = cause.to_s.split(' ') raise "Table already exists: #{strs[0]}!" if strs.size == 1 + raise "Table already exists: #{args.first}!" end # To be safe, here only AccessDeniedException is considered. In future @@ -171,7 +178,7 @@ def translate_hbase_exceptions(*args) # Error message is merged with stack trace, reference StringUtils.stringifyException # This is to parse and get the error message from the whole. strs = str.split("\n") - raise (strs[0]).to_s unless strs.empty? + raise strs[0].to_s unless strs.empty? end if cause.is_a?(org.apache.hadoop.hbase.quotas.SpaceLimitingException) strs = cause.message.split("\n") @@ -193,8 +200,7 @@ def translate_hbase_exceptions(*args) # Throw the other exception which hasn't been handled above raise cause end - # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity - # rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity + # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity end # rubocop:enable Metrics/ClassLength end diff --git a/hbase-shell/src/test/ruby/shell/general_test_cluster.rb b/hbase-shell/src/test/ruby/shell/general_test_cluster.rb index e49dd6e2aaf0..8c1687dea019 100644 --- a/hbase-shell/src/test/ruby/shell/general_test_cluster.rb +++ b/hbase-shell/src/test/ruby/shell/general_test_cluster.rb @@ -174,7 +174,7 @@ def readable_after_eof? end define_test 'Shell::Shell should prevent HBase commands from being shadowed by local variables (HBASE-28660)' do - workspace = @shell.get_workspace + workspace = @shell.workspace IRB.setup(__FILE__) unless IRB.conf[:IRB_NAME] lines = [ diff --git a/hbase-shell/src/test/ruby/shell/noninteractive_test_cluster.rb b/hbase-shell/src/test/ruby/shell/noninteractive_test_cluster.rb index fa8dd333be0d..6a0b28a4dbdb 100644 --- a/hbase-shell/src/test/ruby/shell/noninteractive_test_cluster.rb +++ b/hbase-shell/src/test/ruby/shell/noninteractive_test_cluster.rb @@ -20,7 +20,7 @@ class NonInteractiveTest < Test::Unit::TestCase def setup @hbase = ::Hbase::Hbase.new($TEST_CLUSTER.getConfiguration) - @shell = Shell::Shell.new(@hbase, false) + @shell = Shell::Shell.new(@hbase, interactive: false) end define_test "Shell::Shell noninteractive mode should throw" do diff --git a/hbase-shell/src/test/ruby/test_helper.rb b/hbase-shell/src/test/ruby/test_helper.rb index db014f502787..a2559451429c 100644 --- a/hbase-shell/src/test/ruby/test_helper.rb +++ b/hbase-shell/src/test/ruby/test_helper.rb @@ -43,7 +43,7 @@ module TestHelpers def setup_hbase hbase = ::Hbase::Hbase.new($TEST_CLUSTER.getConfiguration) - @shell = ::Shell::Shell.new(hbase, interactive = false) + @shell = ::Shell::Shell.new(hbase, interactive: false) end def shutdown