#!/bin/bash shellfu import jat_dump shellfu import preupg shellfu import preupg_fupath shellfu import xcase PACKAGE="preupgrade-assistant" #shellcheck disable=SC2034 PREUPG__RULE=xccdf_preupg_rule_api_deploy_hook_check HOOKS_ROOT="/root/preupgrade/hooks" HOOK_DIRNAME="api_deploy_hook" # mute ShellCheck Beh= CallSeq= assert_deployed() { # # Assert our hooks were deployed # local call local arg local hookdir for call in "${CallSeq[@]}"; do debug -v call case $call in pre.*) hookdir="$HOOKS_ROOT/$HOOK_DIRNAME/preupgrade" ;; post.*) hookdir="$HOOKS_ROOT/$HOOK_DIRNAME/postupgrade" ;; #FIXME: structure unclear at the time of this writing *) xcase__id_error CallSeq esac jat__cmd -h "hook dir exists" \ test -d "$hookdir" for arg in $(tr . '\n' <<<"${call#*.}"); do debug -v arg case $arg in s*|as*) jat__cmd -h "hook script content is correct" \ grep "echo hi I am script_$arg.sh" "$hookdir/run_hook" ;; f*|af*) jat__cmd -h "auxiliary file content is correct" \ grep "text of file_$arg" "$hookdir/file_$arg.conf" ;; d*) jat__cmd -h "file_a from auxiliary dir is present" \ test -s "$hookdir/dir_$arg/file_a" jat__cmd -h "file_b from auxiliary dir is present" \ test -s "$hookdir/dir_$arg/file_b" ;; *) warn "assert_deployed() arg unhandled by assert: $arg" ;; esac done done } rtoken() { head -c 1000 /dev/urandom \ | md5sum \ | head -c 7 } mktree() { # # Create tree (ini for fupath) for deployment # local call local arg for call in "${CallSeq[@]}"; do for arg in ${call//./ }; do debug -v arg case $arg in post|pre|badtype|X) true ;; as*) echo "echo hi I am script_$arg.sh; find" >"script_$arg.sh" ;; af*) echo "text of file_$arg" >"file_$arg.conf" ;; s*) echo "script_$arg.sh = echo hi I am script_$arg.sh; find" ;; f*) echo "file_$arg.conf = text of file_$arg" ;; d*) echo "dir_$arg/file_a = text of dir_$arg/file_a" echo "dir_$arg/file_b = text of dir_$arg/file_b" ;; *) xcase__id_error CallSeq ;; esac done done } mkcalls() { # # Create deploy_hook call (ini for fupath) # local call local arg for call in "${CallSeq[@]}"; do debug -v call echo -n "CODE = deploy_hook" case $lang:$call in py:pre.*) echo -n "('preupgrade'" ;; py:post.*) echo -n "('postupgrade'" ;; py:badtype.*) echo -n "('badtype'" ;; sh:pre.*) echo -n " preupgrade" ;; sh:post.*) echo -n " postupgrade" ;; sh:badtype.*) echo -n " badtype" ;; *) xcase__id_error lang CallSeq ;; esac for arg in $(tr . '\n' <<<"${call#*.}"); do debug -v arg case $lang:$arg in py:as*) echo -n ",'$PWD/script_$arg.sh'" ;; py:af*) echo -n ",'$PWD/file_$arg.conf'" ;; py:s*) echo -n ",'script_$arg.sh'" ;; py:f*) echo -n ",'file_$arg.conf'" ;; py:d*) echo -n ",'dir_$arg'" ;; py:X) echo -n ",'nonexistent_file_$(rtoken)'" ;; sh:as*) echo -n " $PWD/script_$arg.sh" ;; sh:af*) echo -n " $PWD/file_$arg.conf" ;; sh:s*) echo -n " script_$arg.sh" ;; sh:f*) echo -n " file_$arg.conf" ;; sh:d*) echo -n " dir_$arg" ;; sh:X) echo -n " nonexistent_file_$(rtoken)" ;; *) xcase__id_error lang CallSeq ;; esac done case $lang in py) echo ')';; sh) echo ;; esac done echo "CODE = exit_fixed$(test "$lang" = py && echo '()')" } XCASE__ARRAYS=CallSeq xcase__enum() { # # Enumerate subtest ids # # Parameters are 'Beh', behavior hint (to help simplify test phase), # and 'CallSeq' - plus-separated list of deploy_hook() calls in this # form: # # TYPE[.ARG][.ARG].. # # where TYPE is either 'post' or 'pre', and ARG are symbols for the # arguments deploy_hook() is called with: # # * sN means script N (1, 2, ...), # * fN means file N (1, 2, ...), # * asN and afN mean the same as sN and fN, but will be called by # absolute path # * dN means directory N (1, 2, ...), # * X means non-existent file # # Actual module code as well as all necessary files are created during # setup phase. # { # normal cases # # simplest echo Beh=OK,CallSeq=post.s1 echo Beh=OK,CallSeq=post.s1.f1 echo Beh=OK,CallSeq=post.s1.f1.d1 echo Beh=OK,CallSeq=pre.s1 echo Beh=OK,CallSeq=pre.s1.f1 echo Beh=OK,CallSeq=pre.s1.f1.d1 echo Beh=OK,CallSeq=pre.as1 echo Beh=OK,CallSeq=pre.s1.af1 # pre and post echo Beh=OK,CallSeq=pre.s1+post.s2 echo Beh=OK,CallSeq=pre.s1.f1.d1+post.s2.f2.d2 echo Beh=OK,CallSeq=post.s1.f1.d1+pre.s2.f2.d2 # bad cases # # deploy twice: same, smaller, bigger echo Beh=BAD,CallSeq=post.s1+post.s1 echo Beh=BAD,CallSeq=post.s1.f1.d1+post.s1 echo Beh=BAD,CallSeq=post.s1+post.s1.f1.d1 # bad args: no script, script is dir, nonexistent, double arg, bad type echo Beh=BAD,CallSeq=post. echo Beh=BAD,CallSeq=post.d1 echo Beh=BAD,CallSeq=post.X echo Beh=BAD,CallSeq=post.X.X echo Beh=BAD,CallSeq=post.s1.X.X # echo Beh=BAD,CallSeq=post.s1.f1.f1 # not sure if we can/need to catch this echo Beh=BAD,CallSeq=post.s1.d1.X echo Beh=BAD,CallSeq=badtype.s1 } | xcase__per lang sh py } #shellcheck disable=SC2154 xcase__setup() { # # Prepare for subtest # { echo "[MODULE]" echo "GROUP = api" echo "NAME = deploy_hook" echo "LANG = $lang" mkcalls echo "[FILES]" mktree } > module.ini preupg_fupath RHEL6_7 module.ini PREUPG__UPATH="RHEL6_7/all-xccdf.xml" \ preupg__run1 --skip-common } xcase__test() { # # Do the work # jat__eval -S 0,1 -h "store hook file list" \ "find '$HOOKS_ROOT' -type f | grep deploy_hook > hooks" case $Beh in OK) assert_deployed jat__eval -S 1 -h "no errors were logged" \ "preupg__get_messages ERROR | grep ." ;; BAD) jat__eval -S 0 -h "error was logged" \ "preupg__get_messages ERROR | grep ." preupg__assert result 'error' ;; *) xcase__id_error Beh ;; esac } xcase__diag() { # # Burp up some diag # jat_dump__file module.ini hooks preupg__get_node | jat_dump__pipe NODE preupg__get_messages | jat_dump__pipe LOG_MESSAGES } xcase__cleanup() { # # Clean up after subtest # preupg__rmresult } PREUPG__UPATH=@pass \ preupg__Run1 xcase__run -v preupg__Cleanup