#!/bin/bash # # preupgrade-assistant testing utilities # # This ASRT module contains various functions to support testing of # preupgrade-assistant and its modules. Refer to specific functions # for details. # shellfu import dist shellfu import jat_dump shellfu import preupg_fupath shellfu import pxpath # # Default rule id (XCCDF) to parse data from # PREUPG__RULE=${PREUPG__RULE:-} # # Regex to filter rules (XCCDF ids) to only run by preupg__run1() # PREUPG__RULE_REGEX=${PREUPG__RULE_REGEX:-.} # # Upgrade path # # This can be one of following: # # * To test with packaged upgrade paths, set this to the module # package suffix, e.g. el6toel7. # # * To test with own generated upgrade path, set this to path # to 'all-xccdf.xml' in the root of the upgrade path tree. # # * You can also use '@BUILTIN' alias to test with quick&trivial # upgrade path, e.g. '@pass' to test with an upgrade path that # simply passes. For details in built-in paths, see # `library(preupgrade-assistant/fupath)` # PREUPG__UPATH=${PREUPG__UPATH:-el6toel7} # # Valid exit statuses from preupg (ES_EX syntax) # # preupg__run1() will raise test failure if exit status does not # match this expression. Format is described in jat documentation. # (See `sfdoc jat`.) # PREUPG__VALID_ES=${PREUPG__VALID_ES:-0-2} # FIXME: ^^^ Holy mess; see http://post-office.corp.redhat.com/archives/rhel-inplaceupgrades/2016-September/msg00011.html # # Override what packages are considered as native # # See preupg__run1() for details. # PREUPG__DISTNATIVE=${PREUPG__DISTNATIVE:-} # # Strip control characters from preupg stdout # # When TESTOUT.log et al. are acccessed using browsers, the control # characters in preupg will make many browsers treat the file as # binary, i.e. offer download instead of opening it. # # Set this variable to 'false' to keep the output verbatim. # PREUPG__STRIPCTL=${PREUPG__STRIPCTL:-true} preupg__assert() { # # Assert value of rule (module) result property # # Usage: # preupg__assert [-r RULE] [-N] FLD VALUE [[-N] FLD VALUE] # # In order for assert to pass, FLD must match VALUE. If -N is passed, # the meaning of assert is reversed, i.e. assert will fail if condition # is satisfied. Passing multiple pairs of FLD and VALUE performs # multiple independent asserts with the added value of better log # readability. # # For numeric fields, VALUE is matched for numeric equality. For string # fields, VALUE is matched as Basic Regular Expression. # # FLD can be: # # risk - risk # risk.slight - slight risk # risk.medium - medium risk # risk.high - high risk # risk.extreme - extreme risk # riskn - number of risks # riskn.slight - number of slight risks # riskn.medium - number of medium risks # riskn.high - number of high risks # riskn.extreme - number of extreme risks # msg - message # msg.debug - debug message # msg.info - info message # msg.warning - warning message # msg.error - error message # msgn - number of messages # msgn.debug - number of debug messages # msgn.info - number of info messages # msgn.warning - number of warning messages # msgn.error - number of error messages # solution - solution text # result - module result # # By default, rule $PREUPG__RULE is queried, but you can # override that using -r argument. (It's mandatory to use at least one # of these methods.) # local code local usage="usage: preupg__assert [-r RULE] [-N] FLD VALUE [[-N] FLD VALUE].." local Rule=$PREUPG__RULE local conds=() local Ellipsis=false local cond while true; do case $1 in -r|--rule) Rule=$2; shift 2 || { jat__log_error "$usage"; return 2; } ;; *) break ;; esac done test -n "$Rule" || { jat__log_error "which rule to assert? set \$PREUPG__RULE or use -r|--rule argument" return 2 } while true; do case $1 in "") break ;; -N) conds+=("neg:${2,,}:$3") shift 3 || { jat__log_error "$usage" return 2 } ;; *) conds+=("pos:${1,,}:$2") shift 2 || { jat__log_error "$usage" return 2 } ;; esac done case ${#conds[@]} in 0) jat__log_error "$usage" return 2 ;; 1) __preupg__assert1 "${conds[0]}" return $? ;; *) jat__log_info "rule $Rule has:" for cond in "${conds[@]}"; do Ellipsis=true __preupg__assert1 "$cond" done ;; esac } preupg__dump_node() { # # Dump node of $PREUPG__RULE # preupg__get_node \ | jat_dump__pipe "NODE-${PREUPG__RULE}" } preupg__get_fixtext() { # # Get solution text (fixtext) of rule id $PREUPG__RULE # __preupg__resultxpath \ "//ns0:Rule[@id='$PREUPG__RULE']/ns0:fixtext/text()" } preupg__get_node() { # # Get whole result node from rule $PREUPG__RULE # __preupg__resultxpath \ "//ns0:rule-result[@idref='$PREUPG__RULE']" } preupg__get_result() { # # Get 'result' field from rule $PREUPG__RULE # __preupg__resultxpath \ "//ns0:rule-result[@idref='$PREUPG__RULE']/ns0:result/text()" } preupg__get_risks() { # # Get risks of severity $1 or all # # 'preupg.risk.' prefix is removed. If severity is given, get only those # risks and also that part of prefix is removed. # # For example, # # $ PREUPG__RULE=xccdf_blah # $ preupg__get_risks # HIGH: foo # MEDIUM: bar # MEDIUM: baz # $ preupg__get_risks HIGH # foo # $ # local sev=${1^^} local outfn=preupg__get_stderr $__PREUPG__LOSCAP \ && outfn=preupg__get_stdout case $sev in "") $outfn \ | grep -E '^preupg\.risk\.(SLIGHT|MEDIUM|HIGH|EXTREME): ' \ | cut -d. -f3- ;; SLIGHT|MEDIUM|HIGH|EXTREME) $outfn \ | grep -E "^preupg\.risk\.$sev: " \ | cut -d. -f3- ;; *) jat__log_error "unknown risk severity: $sev" return 2 ;; esac } preupg__get_messages() { # # Get log messages of severity $1 or all # # 'preupg.log.' prefix is removed. If severity is given, get only those # messages and also that part of prefix is removed. # # For example, # # $ PREUPG__RULE=xccdf_blah # $ preupg__get_messages # INFO: hello # INFO: Joe # DEBUG: lalala lalalala # $ preupg__get_messages DEBUG # lalala lalalala # $ # local sev=${1^^} local outfn=preupg__get_stderr $__PREUPG__LOSCAP \ && outfn=preupg__get_stdout case $sev in "") $outfn \ | grep -E '^preupg\.log\.(ERROR|WARNING|INFO|DEBUG): ' \ | cut -d. -f3- ;; ERROR|WARNING|INFO|DEBUG) $outfn \ | grep -E "^preupg\.log\.$sev: " \ | cut -d. -f3- ;; *) jat__log_error "unknown log message severity: $sev" return 2 ;; esac } preupg__get_stdout() { # # Get stdout of rule $PREUPG__RULE (eg. for grepping risks) # __preupg__resultxpath \ "//ns0:rule-result[@idref='$PREUPG__RULE']/ns0:check/ns0:check-import[@import-name='stdout']/text()" } preupg__get_stderr() { # # Get stderr of rule $PREUPG__RULE (eg. for grepping risks) # preupg__haslim loscap __preupg__resultxpath \ "//ns0:rule-result[@idref='$PREUPG__RULE']/ns0:check/ns0:check-import[@import-name='stderr']/text()" } preupg__collect_stderrs() { # # Collect stderrs of all rules, prefix by rule id # local ruleid preupg__haslim loscap __preupg__lsrules_xml \ | while read -r ruleid; do __preupg__resultxpath \ "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stderr']/text()" \ | sed -e "s/^/$ruleid: /" done } preupg__collect_stray() { # # Collect stray outputs (ie. not risks or log messages), prefix by rule id # local tmp local ruleid preupg__haslim loscap && { __preupg__collect_stray_loscap return $? } tmp=$(mktemp -td preupg__collect_stray.XXXXXXXX) pushd "$tmp" >/dev/null __preupg__lsrules_xml \ | while read -r ruleid; do __preupg__resultxpath \ "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stdout']/text()" \ >"stdout" __preupg__resultxpath \ "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stderr']/text()" \ >"stderr" test -s "stdout" && sed -e "s/^/$ruleid:stdout: /" "stdout" test -s "stderr" || continue <"stderr" grep -v -E \ -e '^preupg\.log\.(ERROR|WARNING|INFO|DEBUG): ' \ -e '^preupg\.risk\.(SLIGHT|MEDIUM|HIGH|EXTREME): ' \ > "stderr.stray" grep -q . "stderr.stray" || continue sed -e "s/^/$ruleid:stderr: /" <"stderr.stray" done popd >/dev/null rm -r "$tmp" } preupg__lsrules_ast() { # # List selected rules from last asssessment result # __preupg__lsrules_xml } preupg__rmresult() { # # Remove assessment results # # Keeps cache and logs; use preupg__Cleanup() to clean # up after test. # jat__cmd rm -rf /root/preupgrade jat__cmd rm -rf /root/preupgrade-results } preupg__Run1() { # # Create phase and just run preupg__run1 $@ # # Wrapper around preupg__run1() with phase creation. # Call this before starting case loop such as xcase__run(), # where you would try out multiple cache-independent cases. # jat__pstarts "run preupg once" preupg__run1 "$@" jat__pend } preupg__Cleanup() { # # Create final cleanup phase (submit & full cleanup) # # If results (tarball) are found, jat__submit() them (tarball and # html and xml). Finally clean up results, logs and cache. # # Pass -n to skip submitting of the results. # local submit=true test "x$1" == "-n" && submit=false jat__pstartc # we assume that if tarball exists, html and xml both exist # as well. if $submit \ && test -n "$(preupg__get_latest_tar)"; then jat__submit "/root/preupgrade/result.html" "result.html" jat__submit "/root/preupgrade/result.xml" "result.xml" jat__submit "$(preupg__get_latest_tar)" fi preupg__rmresult jat__pend } preupg__run1() { # # Run preupg once without interaction; pass $@ down # # Runs preupg with --force argument (to suppress questions) and performs # additional checks on assessment. Any arguments to this function are # simply passed down to the preupg call (after any arguments needed # for overrides, see below). # # Exit status is normally same as exit status from preupg, but statuses # defined in $PREUPG__VALID_ES don't cause assert fail # (these normally represent upgrade risk level so are considered "normal"). # However, if additional checks done by this routine fail, exit status # is increased by 100. # # Several overrides can be specified via following global # variables: # # * If $PREUPG__RULE_REGEX was specified, modules # are selected using that regular expression and passed down # using --select-rules parameter. # # * If $PREUPG__DISTNATIVE is specified, preupg config # is altered for this run to override what packages are treated # as native. The variable may have following values: # # * `sign` - packages signed by vendor (default preupg behavior) # * `all` - all installed packages # * `-NAME1[,-NAME2,..]` - all currently installed packages # except NAME1, NAME2 and so on # * `/path/to/list` - only packages listed in the file (names) # # * If $PREUPG__UPATH points to path to all-xccdf.xml, # or has form of built-in fake path (`@*`) custom upgrade path is # used. (see `$PREUPG__UPATH` for details`) # # Note that these overrides only affect the single run; i.e. runs # outside this function work normally, and you can change mentioned # variables between run. # jat__log_info "PREUPG__UPATH='$PREUPG__UPATH'" jat__log_info "PREUPG__RULE_REGEX='$PREUPG__RULE_REGEX'" jat__log_info "PREUPG__DISTNATIVE='$PREUPG__DISTNATIVE'" local es=0 # exit status local run1tmp # our temporary dir run1tmp="$(mktemp -d -t preupg__run1.XXXXXXXX)" __preupg__mkfupath_builtin __preupg__dno_enable case "$PREUPG__RULE_REGEX" in .|"") __preupg__preupg "$@" es=$? ;; *) __preupg__preupg \ --select-rules "$(__preupg__lsrules_upath | paste -sd,)" \ "$@" es=$? ;; esac __preupg__dno_disable rm -r "$run1tmp" # Additional checks if preupg__collect_stray | grep -q .; then jat__fail "stray module output found" preupg__collect_stray \ | jat_dump__pipe -E STRAY_OUTPUT es=$((100 + es)) fi return $es } preupg__get_latest_tar() { # # Print path to latest tarball; false if there was none # test -d /root/preupgrade-results || { warn "no result found; has preupg been run?" return 3 } find /root/preupgrade-results \ -name "preupg_results-*.tar.gz" \ | sort -n \ | tail -1 \ | grep . # grep to normalize exit status } preupg__tar_extract() { # # Extract last tarball and print path to the extracted directory # local tarball_path local dirname tarball_path=$(preupg__get_latest_tar) dirname=${tarball_path##*/} dirname=${dirname%.tar.gz} { jat__cmd -h "tarball found" \ test -n "$tarball_path" \ || return 3 jat__cmd -h "tarball extracted" \ tar -xzf "$tarball_path" \ || return 3 jat__cmd -h "directory present" \ test -d "$dirname" \ || return 3 } >&2 echo "$dirname" } preupg__tar_list() { # # Print contents of latest tarball # local tarball_path local dirname tarball_path=$(preupg__get_latest_tar) || return 3 { jat__cmd -h "tarball found" \ test -n "$tarball_path" \ || return 3 jat__cmd -h "tarball listable" \ tar -tzf "$tarball_path" \ || return 3 } >&2 tar -tzf "$tarball_path" } __preupg__shellfu_init__() { # # Inialization check hook (called by shellfu) # dist__test ver vlt '6.9' && { jat__log_warning \ "=============================================================" \ " : Old buggy version of OpenSCAP is in use: :" \ " : :" \ " : $(rpm -q openscap) :" \ " : :" \ " : This means that capabilities of this test library will :" \ " : be limited, because stderr from module scripts will be :" \ " : always reported as empty, while its content will be :" \ " : into stdout. :" \ " : :" \ " : See https://bugzilla.redhat.com/show_bug.cgi?id=1309491 :" \ "=============================================================" __PREUPG__LOSCAP=true } case "$PREUPG__UPATH" in el5toel7|el6toel7) true ;; */all-xccdf.xml) true ;; @*) true ;; *) jat__log_error \ "unknown upgrade path: $PREUPG__UPATH" ;; esac } preupg__haslim() { # # True and emit warn test reader if limitation $1 is in place # # Usage: # # preupg__haslim LIM [EFFECT] # # If limitation LIM is in place, print warning and exit with zero # otherwise exit with one if LIM is not in place and 2 if LIM is not # known. # # Warning will mention calling function and describe limitation in # general; you can provide simple EFFECT (few words) to describe # how the limitation affects the particular test context. # # Known LIMs are: # # * `loscap` - legacy OpenSCAP: module stderr is merged into its # stdout. # local limitation=$1 local effect=$2 local parent=${FUNCNAME[1]} case $limitation in loscap) # legacy openscap $__PREUPG__LOSCAP || return 1 test -n "$effect" || effect="see bz1309491" jat__log_warning "$parent(): old openscap is in use; $effect" return 0 ;; esac jat__log_error "invalid limitation: $limitation" return 2 } # # there is something wrong with this world # # INTERNAL # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # # by crossing this line you are making it stronger # # # Have we touched preupg conf already? # __PREUPG__CFG_DIRTY=${__PREUPG__CFG_DIRTY:-false} # # True if we should work with legacy openscap # # Old openscap (pre openscap-1.2.13-2.el6) merges stderr into stdout so we need # to alter risk filtering. # __PREUPG__LOSCAP=false __preupg__preupg() { # # Run preupg with --force, maybe --contents and maybe other args # local args=() local hints=() local es=0 local valid_es=$PREUPG__VALID_ES args+=(--force) case $PREUPG__UPATH in */*) args+=(--contents "$PREUPG__UPATH") hints+=(" (custom content set)") ;; @*) args+=(--contents "$(<"$run1tmp/builtin_path")") \ || return 3 hints+=(" (built-in fake content set $PREUPG__UPATH)") ;; esac test -n "$*" \ && args+=("$@") \ && hints+=(" ($*)") jat__log_info "PWD='$PWD'" # help to hunt for things like bz1380120 jat__cmd -h "Run preupgrade assistant${hints[*]}" \ -S "$valid_es" \ -o "$run1tmp/out" -e "$run1tmp/err" \ preupg "${args[@]}" es=$? case $PREUPG__STRIPCTL in false) <"$run1tmp/out" jat_dump__pipe -l 400 -b 30000 PREUPG_OUT ;; true) <"$run1tmp/out" tr -dc '[:graph:]\n\t ' \ | jat_dump__pipe -l 400 -b 30000 PREUPG_OUT_STRIPPED ;; esac < "$run1tmp/err" jat_dump__pipe -E PREUPG_ERR return $es } __preupg__mkfupath_builtin() { # # Ad-hoc path using built-in preupg_fupath() template # # This whole process is heavily complicated by weird behavior of preupg # and its tools': # # * You can't just come up with any name for an upgrade path; this # means the directory name is basically prescribed depending on # source (and destination) distro. # # * The build tool will only generate prescribed path (the above, # suffixed by '-results'). # # * The same path *won't* work with preupg; you have to manually rename # it back to the "prescribed" # # In the end, `preupg_fupath()` has to use at least three # different paths and has no way of avoiding path conflict. Its API # partially avoids the problem by making the name a mandatory (=explicit) # argument and stating clearly in the docs that these paths would be # removed before generation. # # The point of this function, though, is to be easy on user; this means # we'll be implicit wherever we can, at the price of being relatively # fragile. # # Hence the unfunny and frustrating checks below. # test "${PREUPG__UPATH:0:1}" = @ || return 0 local name { dist__test ver.x eq 5 && name=RHEL5_7 dist__test ver.x eq 6 && name=RHEL6_7 test -n "$name" || { jat__log_error "could not choose fake upath name (this works only on RHEL5/RHEL6)" return 3 } test -e "$name" -o -e "$name-results" -o "$name-raw" || { jat__log_error "these must not exist for '@BUILTIN' form to work: $name, $name-results $name-raw" return 3 } preupg_fupath "$name" "$PREUPG__UPATH" } >&2 #FIXME: remove block andredirect after bz1171881 echo "$name/all-xccdf.xml" > "$run1tmp/builtin_path" } __preupg__mknatlist() { # # Make list of "native" packages to override and show the path # local ex # single expression from PREUPG__DISTNATIVE tr , '\n' <<<"$PREUPG__DISTNATIVE" \ | grep . \ | while read -r ex; do case "$ex" in -*) echo "${ex:1}" >> "$run1tmp/dno_exclude" ;; *) jat__log_error "invalid expression in PREUPG__DISTNATIVE: $ex" echo /dev/null return 1 ;; esac done rpm -qa --qf '%{N}\n' \ | sort \ | uniq \ | grep -vxFf "$run1tmp/dno_exclude" \ > "$run1tmp/dno_list" echo "$run1tmp/dno_list" } __preupg__dno_enable() { # # Enable "dist_native" override, if need be # test -n "$PREUPG__DISTNATIVE" || return 0 jat__eval -h "enable devel_mode" \ "mkdir -p /var/cache/preupgrade; touch /var/cache/preupgrade/devel_mode" __preupg__cfgbak { echo "[devel-mode]" echo -n "dist_mode=" case "$PREUPG__DISTNATIVE" in all|sign|*/*) echo "$PREUPG__DISTNATIVE" ;; *) __preupg__mknatlist ;; esac } >> /etc/preupgrade-assistant.conf } __preupg__dno_disable() { # # Disable "dist_native" override, if need be # test -n "$PREUPG__DISTNATIVE" || return 0 jat__cmd -h "disable devel_mode" \ rm -f /var/cache/preupgrade/devel_mode __preupg__cfgrest } __preupg__cfgbak() { # # Back up preupg conf # jat__filebackup -n "preupg__cfgbak" \ /etc/preupgrade-assistant.conf } __preupg__cfgrest() { # # Restore preupg conf, if needed # $__PREUPG__CFG_DIRTY || true jat__log_info "config before restoring:" jat_dump__file /etc/preupgrade-assistant.conf jat__filerestore -n "preupg__cfgbak" } __preupg__assert_mkcode() { # # Make Bash code for generating field values # echo -n "PREUPG__RULE=$Rule " case $Field in risk) echo "preupg__get_risks" ;; risk.slight) echo "preupg__get_risks SLIGHT" ;; risk.medium) echo "preupg__get_risks MEDIUM" ;; risk.high) echo "preupg__get_risks HIGH" ;; risk.extreme) echo "preupg__get_risks EXTREME" ;; riskn) echo "preupg__get_risks | wc -l" ;; riskn.slight) echo "preupg__get_risks SLIGHT | wc -l" ;; riskn.medium) echo "preupg__get_risks MEDIUM | wc -l" ;; riskn.high) echo "preupg__get_risks HIGH | wc -l" ;; riskn.extreme) echo "preupg__get_risks EXTREME | wc -l" ;; msg) echo "preupg__get_messages" ;; msg.debug) echo "preupg__get_messages DEBUG" ;; msg.info) echo "preupg__get_messages INFO" ;; msg.warning) echo "preupg__get_messages WARNING" ;; msg.error) echo "preupg__get_messages ERROR" ;; msgn) echo "preupg__get_messages | wc -l" ;; msgn.debug) echo "preupg__get_messages DEBUG | wc -l" ;; msgn.info) echo "preupg__get_messages INFO | wc -l" ;; msgn.warning) echo "preupg__get_messages WARNING | wc -l" ;; msgn.error) echo "preupg__get_messages ERROR | wc -l" ;; solution) echo "preupg__get_fixtext" ;; result) echo "preupg__get_result" ;; *) jat__log_error "unsupported field: $Field"; return 2 ;; esac } __preupg__assert_mkvalid_code() { # # Make Bash code, true if valid # local code code=$(__preupg__assert_mkcode) || return $? bash -n <<<"$code" && { echo "$code" return 0 } jat__log_error "bug: bad assert code generated: '$code'" return 3 } __preupg__assert_mkhint() { # # Compose hint for assert # local fphrase # English field phrase local s # 's' if $Value is plural, empty otherwise local a='a' # 'a' or 'an', based on what's proper test "$Value" = 1 || s="s" case $Field in result) fphrase="result" ;; risk|riskn) fphrase="risk" ;; msg|msgn) fphrase="message" ;; solution) fphrase="solution text" ;; risk.*|riskn.*) fphrase="${Field#*.} risk" ;; msg.*|msgn.*) fphrase="${Field#*.} message" ;; esac case ${Field#*.} in error|extreme|info) a='an' ;; esac case $Ellipsis in false) echo -n "rule $Rule has " ;; true) echo -n " ... " ;; esac case $Mode:$Type in pos:str) echo "$a $fphrase matching '$Value'" ;; neg:str) echo "no $fphrase matching '$Value'" ;; pos:int) echo "exactly $Value $fphrase$s" ;; neg:int) echo "other than $Value $fphrase$s" ;; esac } __preupg__assert1() { # # Perform one assertion with condition $1 with rule $Rule # # This does one iteration of preupg__assert # local Mode local Field local Value local es=0 local code local hint local Type local tmp=$1 # tmp='MODE:FIELD:VA:L:UE' Mode=${tmp%%:*} # 'MODE' tmp=${tmp#$Mode:} # tmp='FIELD:VA:L:UE' Field=${tmp%%:*} # 'FIELD' Value=${tmp#$Field:} # 'VA:L:UE' Type=$(__preupg__assert_op4fld) || return $? code=$(__preupg__assert_mkvalid_code) || return $? hint=$(__preupg__assert_mkhint) case $Mode in pos) es=0 ;; neg) es=1 ;; esac case $Type in int) jat__eval -S $es -h "$hint" "test $(eval "$code") -eq $Value" ;; str) jat__eval -S $es -h "$hint" "$code | grep '$Value'" ;; esac } __preupg__collect_stray_loscap() { # # Legacy version of preupg__collect_stray() # local tmp local ruleid tmp=$(mktemp -td preupg__collect_stray.XXXXXXXX) pushd "$tmp" >/dev/null __preupg__lsrules_xml \ | while read -r ruleid; do __preupg__resultxpath \ "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stdout']/text()" \ >"stdout" test -s "stdout" || continue <"stdout" grep -v -E \ -e '^preupg\.log\.(ERROR|WARNING|INFO|DEBUG): ' \ -e '^preupg\.risk\.(SLIGHT|MEDIUM|HIGH|EXTREME): ' \ > "stdout.stray" grep -q . "stdout.stray" || continue sed -e "s/^/$ruleid:stdout: /" <"stdout.stray" done popd >/dev/null rm -r "$tmp" } __preupg__assert_op4fld() { # # Print correct operator for field $Field # case $Field in result|risk|risk.*|msg|msg.*|solution) echo str ;; riskn|riskn.*|msgn|msgn.*) echo int ;; *) jat__log_error "unsupported field: $Field"; return 2 ;; esac } __preupg__lsrules_upath() { # # List preupg rule ids from upgrade path # local upname # upgrade path name case "$PREUPG__UPATH" in el6toel7) upname='RHEL6_7' ;; el5toel7) upname='RHEL5_7' ;; @*) upname="$(basename "$(dirname "$(<"$run1tmp/builtin_path")")")" ;; */all-xccdf.xml) upname="$(basename "$(dirname "$PREUPG__UPATH")")" ;; *) jat__log_error "unsupported upgrade path: $PREUPG__UPATH" ;; esac #FIXME: after bz1362708, use proper CLI --list-rules for both case "$PREUPG__UPATH" in @*) cat "$(dirname "$(<"$run1tmp/builtin_path")")/list_rules" ;; */all-xccdf.xml) cat "$(dirname "$PREUPG__UPATH")/list_rules" ;; *) preupg --list-rules ;; esac \ | grep "$PREUPG__RULE_REGEX" \ | sed -e "s/^$upname://" } __preupg__lsrules_xml() { # # List preupg rule ids from result.xml # __preupg__resultxpath \ "//ns0:rule-result[./ns0:result/text() != 'notselected']/@idref" } __preupg__resultxpath() { # # Run XPath query $1 on result.xml inside tarball $2 or latest # # Take XPath query $1, run it on result.xml and print output. # # Notes: libxml2-python was, as finally turns out, the only usable # implementation available on RHEL5 # local xpath=$1 local tarfile=$2 local inpath # path inside tarfile test -n "$xpath" || { jat__log_error "empty XPath query" return 2 } test -n "$tarfile" || tarfile=$(preupg__get_latest_tar) test -n "$tarfile" || { jat__log_error "No tarfile found. Either run preupg or provide tarfile on command line" return 2 } inpath=${tarfile##*/} inpath=${inpath%.tar.gz} tar -zf "$tarfile" -O -x "$inpath/result.xml" \ | pxpath \ "$xpath" - \ "xhtml:http://www.w3.org/1999/xhtml" \ "html:http://www.w3.org/1999/xhtml" \ "ns0:http://checklists.nist.gov/xccdf/1.2" } #shellfu module-version=__MKIT_PROJ_VERSION__