HBase Client Check
Check the HBase client installation by creating a table, inserting a cell and scanning the table.
module.exports = header: 'HBase Client Check', handler: ({options}) ->
Register
@registry.register 'ranger_policy', 'ryba/ranger/actions/ranger_policy'
Wait
Wait for the HBase master to be started.
@call once: true, 'ryba/hbase/master/wait', options.wait_hbase_master
@call once: true, 'ryba/hbase/regionserver/wait', options.wait_hbase_regionserver
Ranger Policy
Ranger HBase plugin try to mimics grant/revoke by shell.
@call
header: 'Ranger'
if: -> !!options.ranger_admin
, ->
@call 'ryba/ranger/admin/wait', once: true, options.wait_ranger_admin
@wait.execute
header: 'Wait Service'
cmd: """
curl --fail -H \"Content-Type: application/json\" -k -X GET \
-u #{options.ranger_admin.username}:#{options.ranger_admin.password} \
\"#{options.ranger_install['POLICY_MGR_URL']}/service/public/v2/api/service/name/#{options.ranger_install['REPOSITORY_NAME']}\"
"""
code_skipped: 22
@ranger_policy
header: 'Create Policy'
username: options.ranger_admin.username
password: options.ranger_admin.password
url: options.ranger_install['POLICY_MGR_URL']
policy:
"name": "ryba-client-check-#{options.hostname}"
'description': 'Ryba policy used to check the HBase client'
"service": options.ranger_install['REPOSITORY_NAME']
"resources":
"column":
"values": ["*"]
"isExcludes": false
"isRecursive": false
"column-family":
"values": ["*"]
"isExcludes": false
"isRecursive": false
"table":
"values": [
"#{options.test.namespace}:#{options.test.table}",
"#{options.test.namespace}:check_#{options.hostname}_test_splits",
"#{options.test.namespace}:check_#{options.hostname}_ha"
]
"isExcludes": false
"isRecursive": false
"isEnabled": true
"isAuditEnabled": true
'policyItems': [
"accesses": [
'type': 'read'
'isAllowed': true
,
'type': 'write'
'isAllowed': true
,
'type': 'create'
'isAllowed': true
,
'type': 'admin'
'isAllowed': true
],
'users': [options.test.user.name]
'groups': []
'conditions': []
'delegateAdmin': true
]
Shell
Create a "ryba" namespace and set full permission to the "ryba" user. This
namespace is used by other modules as a testing environment.
Namespace and permissions are implemented and illustrated in HBASE-8409.
Permissions is either zero or more letters from the set READ('R'), WRITE('W'), EXEC('X'), CREATE('C'), ADMIN('A'). Create and admin only apply to tables.
grant <user|@system.group> <permissions> <table> [ <column family> [ <column qualifier> ] ]
Groups and users access are revoked in the same way, but groups are prefixed with an '@' character. In the same way, tables and namespaces are specified, but namespaces are prefixed with an '@' character.
@system.execute
header: 'Grant Permissions'
cmd: mkcmd.hbase options.admin, """
force_check='#{if options.force_check then '1' else ''}'
if hbase shell 2>/dev/null <<< "list_namespace_tables '#{options.test.namespace}'" | egrep '[0-9]+ row'; then
if [ ! -z "$force_check" ]; then
echo [DEBUG] Cleanup existing table and namespace
hbase shell 2>/dev/null << ' CMD' | sed -e 's/^ //';
disable '#{options.test.namespace}:#{options.test.table}'
drop '#{options.test.namespace}:#{options.test.table}'
drop_namespace '#{options.test.namespace}'
CMD
else
echo [INFO] Test is skipped
exit 2;
fi
fi
echo '[DEBUG] Namespace level'
hbase shell 2>/dev/null <<-CMD
create_namespace '#{options.test.namespace}'
grant '#{options.test.user.name}', 'RWC', '@#{options.test.namespace}'
CMD
echo '[DEBUG] Table Level'
hbase shell 2>/dev/null <<-CMD
create '#{options.test.namespace}:#{options.test.table}', 'family1'
grant '#{options.test.user.name}', 'RWC', '#{options.test.namespace}:#{options.test.table}'
CMD
"""
code_skipped: 2
trap: true
Check Shell
Note, we are re-using the namespace created above.
@call header: 'Shell', ->
@wait.execute
cmd: mkcmd.test options.test_krb5_user, "hbase shell 2>/dev/null <<< \"exists '#{options.test.namespace}:#{options.test.table}'\" | grep 'Table #{options.test.namespace}:#{options.test.table} does exist'"
@system.execute
cmd: mkcmd.test options.test_krb5_user, """
hbase shell 2>/dev/null <<-CMD
alter '#{options.test.namespace}:#{options.test.table}', {NAME => '#{options.hostname}'}
put '#{options.test.namespace}:#{options.test.table}', 'my_row', '#{options.hostname}:my_column', 10
scan '#{options.test.namespace}:#{options.test.table}', {COLUMNS => '#{options.hostname}'}
CMD
"""
unless_exec: unless options.force_check then mkcmd.test options.test_krb5_user, "hbase shell 2>/dev/null <<< \"scan '#{options.test.namespace}:#{options.test.table}', {COLUMNS => '#{options.hostname}'}\" | egrep '[0-9]+ row'"
, (err, {status, stdout}) ->
isRowCreated = RegExp("column=#{options.hostname}:my_column, timestamp=\\d+, value=10").test stdout
throw Error 'Invalid command output' if status and not isRowCreated
Check MapReduce
@call header: 'MapReduce', ->
@system.execute
cmd: mkcmd.test options.test_krb5_user, """
hdfs dfs -rm -skipTrash check-#{options.hostname}-hbase-mapred
echo -e '1,toto\\n2,tata\\n3,titi\\n4,tutu' | hdfs dfs -put -f - /user/ryba/test_import.csv
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator=, -Dimporttsv.columns=HBASE_ROW_KEY,family1:value #{options.test.namespace}:#{options.test.table} /user/ryba/test_import.csv
hdfs dfs -touchz check-#{options.hostname}-hbase-mapred
"""
unless_exec: unless options.force_check then mkcmd.test options.test_krb5_user, "hdfs dfs -test -f check-#{options.hostname}-hbase-mapred"
Check Splits
@call header: 'Splits', ->
table = "#{options.test.namespace}:check_#{options.hostname}_test_splits"
@system.execute
cmd: mkcmd.hbase options.admin, """
if hbase shell 2>/dev/null <<< "list_namespace_tables '#{options.test.namespace}'" | grep 'test_splits'; then echo "disable '#{table}'; drop '#{table}'" | hbase shell 2>/dev/null; fi
echo "create '#{table}', 'cf1', SPLITS => ['1', '2', '3']" | hbase shell 2>/dev/null;
echo "scan 'hbase:meta', {COLUMNS => 'info:regioninfo', FILTER => \\"PrefixFilter ('#{table}')\\"}" | hbase shell 2>/dev/null
"""
unless_exec: unless options.force_check then mkcmd.test options.test_krb5_user, "hbase shell 2>/dev/null <<< \"list '#{options.test.namespace}'\" | grep -w 'test_splits'"
, (err, data) ->
throw err if err
return unless data.executed
lines = string.lines data.stdout
count = 0
pattern = new RegExp "^ #{table},"
for line in lines
count++ if pattern.test line
throw Error 'Invalid Splits Count' unless count is 4
# Note: inspiration for when namespace are functional
# cmd = mkcmd.test options.test_krb5_user, "hbase shell 2>/dev/null <<< \"list_namespace_tables 'ryba'\" | egrep '[0-9]+ row'"
# @waitForExecution cmd, (err) ->
# return err if err
# @system.execute
# cmd: mkcmd.test options.test_krb5_user, """
# if hbase shell 2>/dev/null <<< "list_namespace_tables 'ryba'" | egrep '[0-9]+ row'; then exit 2; fi
# hbase shell 2>/dev/null <<-CMD
# create 'ryba.#{options.hostname}', 'family1'
# put 'ryba.#{options.hostname}', 'my_row', 'family1:my_column', 10
# scan 'ryba.#{options.hostname}'
# CMD
# """
# code_skipped: 2
# , (err, executed, stdout) ->
# isRowCreated = /column=family1:my_column10, timestamp=\d+, value=10/.test stdout
# return Error 'Invalid command output' if executed and not isRowCreated
# return err, executed
Check HA
This check is only executed if more than two HBase Master are declared.
@call header: 'Check HA', if: options.is_ha, ->
table = "#{options.test.namespace}:check_#{options.hostname}_ha"
@system.execute
cmd: mkcmd.hbase options.admin, """
# Create new table
echo "disable '#{table}'; drop '#{table}'" | hbase shell 2>/dev/null
echo "create '#{table}', 'cf1', {REGION_REPLICATION => 2}" | hbase shell 2>/dev/null;
# Insert records
echo "put '#{table}', 'my_row', 'cf1:my_column', 10" | hbase shell 2>/dev/null
echo "scan '#{table}', { CONSISTENCY => 'STRONG' }" | hbase shell 2>/dev/null
echo "scan '#{table}', { CONSISTENCY => 'TIMELINE' }" | hbase shell 2>/dev/null
"""
# unless_exec: unless options.force_check then mkcmd.test options.test_krb5_user, "hbase shell 2>/dev/null <<< \"list '#{table}'\" | grep -w '#{table}'"
Dependencies
mkcmd = require '../../lib/mkcmd'
string = require '@nikitajs/core/lib/misc/string'