From 81f4c56c14a99b17470f3116dfb671ee791b9438 Mon Sep 17 00:00:00 2001 From: Jakub Heger Date: Oct 02 2017 08:05:54 +0000 Subject: added sos/utils and yum/common-functions libs --- diff --git a/sos/utils/Makefile b/sos/utils/Makefile new file mode 100644 index 0000000..8a29132 --- /dev/null +++ b/sos/utils/Makefile @@ -0,0 +1,55 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Makefile of /CoreOS/sos/Library/utils +# Description: Library with various utility functions for sos tests +# Author: David Kutalek +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2013 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +export TEST=/CoreOS/sos/Library/utils +export TESTVERSION=1.0 + +BUILT_FILES= + +FILES=$(METADATA) lib.sh Makefile + +.PHONY: all install download clean + +build: $(BUILT_FILES) + +clean: + rm -f *~ $(BUILT_FILES) + +-include /usr/share/rhts/lib/rhts-make.include + +$(METADATA): Makefile + @echo "Owner: David Kutalek " > $(METADATA) + @echo "Name: $(TEST)" >> $(METADATA) + @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) + @echo "Path: $(TEST_DIR)" >> $(METADATA) + @echo "Description: Library with various utility functions for sos tests" >> $(METADATA) + @echo "Type: Library" >> $(METADATA) + @echo "TestTime: 5m" >> $(METADATA) + @echo "Requires: sos" >> $(METADATA) + @echo "Provides: library(sos/utils)" >> $(METADATA) + @echo "License: GPLv2" >> $(METADATA) + + rhts-lint $(METADATA) diff --git a/sos/utils/lib.sh b/sos/utils/lib.sh new file mode 100644 index 0000000..26aae82 --- /dev/null +++ b/sos/utils/lib.sh @@ -0,0 +1,619 @@ +#!/bin/bash +# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# lib.sh of /CoreOS/sos/Library/utils +# Description: Library with various utility functions for sos tests +# Author: David Kutalek +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2012 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# library-prefix = sos +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head1 NAME + +sos/utils + +=head1 DESCRIPTION + +Library with various utility functions for sos tests. + + - sosFakeCmd - enqueue reversible install of given 'fake' command needed by the test + + - sosFakeFile - enqueue reversible install of given tar tree of files + + - sosFakeTree - enqueue reversible install of given tar tree of files + + - sosUnfake - immediately uninstalls all previous fakes, if executed + + - sosReport - generate reusable sosreport with given params and namespace, + or just return already created one if possible, ie. it has: + - same namespace + - same params + - same fakes + + Will execute queued fake installs before generating sosreport. + Calls unfake after sos generation, if not exlicitely asked to not do it. + + - sosReportList - printout of present, already generated sosreports, + with some stats like number of reuse. + + - sosReportPurge - deletes all previously generated and stored sosreports + + +How it is supposed to work: + + Lib user setups fakes as needed and asks for sosreport. +Given namespace, sosreport params and queued fakes are considered - +if exactly same sosreport already exists in lib data store, +it will be reused. + + In case lib user wants to generate more different sosreports with same fakes, +he can pass optional param to sosReport to not unfake immediately. + + It is possible to list and delete all already generated sosreports. + + Fake queue is being cleared everytime library loads, so far I do not see +any scenario for multi-test queues. + +=cut + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Variables +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Functions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head1 FUNCTIONS + +=head2 sosLog + +Simply logs a message into library specific log file. + + sosLog message params + +=over + +==item message params + +Any number of parameters to be logged. Please avoid special chars like new lines. + +=back + +Logs a message, returns 0 when successfull. + +=cut + +sosLog() { + echo $(date '+%Y-%m-%d %H:%M %z') "$*" >> $sos_LOG + return $? +} + +true <<'=cut' +=pod + +=head1 FUNCTIONS + +=head2 sosFakeCmd + +Enqueue reversible install of given 'fake' command needed by the test + + sosFakeCmd fake destination + +=over + +==item fake + +File name of faked command to be installed. + +==item destination + +Destination file name where fake is to be installed. + +=back + +Adds CMD:fake:destination entry into fakelist. + +Returns 0 when successfull. + +=cut + +sosFakeCmd() { + + [ $# -eq 2 ] || { sosLog "sosFakeCmd: bad usage"; return 1; } + + local fake=$1 + local destination=$2 + + fake=$(readlink -fn $fake) +# FIXME: readlink does not work for unexistant destinations. +# use combination of pwd and basename? +# destination=$(readlink -fn $destination) + echo "CMD:$fake:$destination" >> $sos_FAKELIST + + sosLog "enqueued fake '$fake' as '$destination'" +} + + +true <<'=cut' +=pod + +=head2 sosFakeFile + +Enqueue reversible install of given 'fake' file needed by the test + + sosFakeFile fake destination + +=over + +==item fake + +File name of faked file to be installed. + +==item destination + +Destination file name where fake is to be installed. + +=back + +Adds FILE:fake:destination entry into fakelist. + +Returns 0 when successfull. + +=cut + +sosFakeFile() { + + [ $# -eq 2 ] || { sosLog "sosFakeFile: bad usage"; return 1; } + + local fake=$1 + local destination=$2 + + fake=$(readlink -fn $fake) +# FIXME: readlink does not work for unexistant destinations. +# use combination of pwd and basename? +# destination=$(readlink -fn $destination) + echo "FILE:$fake:$destination" >> $sos_FAKELIST + + sosLog "sosFakeFile: enqueued fake '$fake' as '$destination'" +} + + +true <<'=cut' +=head2 sosFakeTree + +Enqueue reversible install of given 'fake' tar tree of files needed by the test + + sosFakeTree fake-archive + +=over + +==item fake-archive + +Archive with faked filesystem tree to be enqueued. +It should be extractable by tar (eg. tar.gz). +To be extracted, hopefully safely, into root (/). + +=back + +Adds TREE:fake-archive entry into fakelist. + +Returns 0 when successfull. + +=cut + +sosFakeTree() { + + [ $# -eq 1 ] || { sosLog "sosFakeTree: bad usage"; return 1; } + + local fake_archive=$1 + + fake_archive=$(readlink -fn $fake_archive) + echo "TREE:$fake_archive" >> $sos_FAKELIST + + sosLog "sosFakeTree: enqueued fake archive '$fake_archive'" +} + +true <<'=cut' +=head2 sosUnfake + +Immediately uninstalls all previous fakes, if executed. + + sosUnfake + +=over + +=back + +Uninstalls faked commands, files and file trees via rlFileRestore. +Clears previously created fakelist. + +Returns 0 when successfull. + +=cut + +sosUnfake() { + + [ $# -eq 0 ] || { sosLog "sosUnfake: bad usage"; return 1; } + + echo -n '' > $sos_FAKELIST + + if rlFileRestore --namespace $sos_BACKUP_NAMESPACE; then + sosLog "sosUnfake: fakes successfully uninstalled" + return 0 + else + sosLog "sosUnfake: uninstall error" + return 1 + fi +} + +true <<'=cut' +=head2 sosReport + +Generates reusable sosreport with given params and namespace, +or just return already created one if possible. + + sosReport "sosreport params" [namespace] [no-unfake] + +Notes: + + * This will execute queued fake installs before generating sosreport. + * Calls sosUnfake after sos generation by default + * Previously generated sosreport can be reused if all of these apply: + * same namespace + * same params + * same fakes + +=over + +=item "sosreport params" + +This is a string with parameters for sosreport itself. +It has to be formally one parameter, therefore usually quotes needed. + +=item namespace + +Namespace can be used to differentiate even sosreports with same args. +This can be used eg. for cases with specifically altered environment +before running sosreport. By using new namespace, you can be sure +new sosreport will be generated. + +Defaults to 'default'. Do not use whitespace. + +=item no-unfake + +Use no-unfake keyword to not run sosUnfake after sosreport generation. +This can be usefull eg. when you need to make more different sosreports +with same fake setup. + +=back + +When successfull, populates sos_REPORT with full path to valid sosreport +and returns 0. +=cut + +sosReport() { + + [ $# -lt 1 ] && { sosLog "sosReport: bad usage"; return 1; } + [ $# -gt 3 ] && { sosLog "sosReport: bad usage"; return 1; } + + local params="$1" + local namespace="$2" ; [ "_$namespace" = "_" ] && namespace='default' + local unfake=1 + if [ "_$3" = "_no-unfake" ]; then + unfake=0 + fi + + sosLog "sosReport: Tree fakes not yet implemented, will be skipped!!!" + + local fakesum=$(cat $sos_FAKELIST | grep -v '^TREE' | sha1sum | sed 's/ .*//') + local paramsum=$(echo "$params" | tr ' ' '\n' | sort | grep -v '^\s*$' | sha1sum | sed 's/ .*//') + + local report_id="$paramsum $namespace $fakesum" + + sosLog "sosReport: was asked for <$report_id>" + + # decide whether to use older report + + # TODO: already generated sosreport detection and usage + # - detect based on report_id and sos_DB + # - incrementing sosreport usage count in sos_DB + # - no fake execution, therefore also no unfake + # - returning report + + + # otherwise, lets install fakes and generate new sosreport + + local fakelist + local IFS_backup="$IFS" ; IFS=':' + local row + + cat $sos_FAKELIST | while read -a row; do + + if [ ${#row[@]} -lt 2 ]; then + sosLog "sosReport: skipping wrongly formatted fake (${row[@]})" + continue; + fi + + # FILE:/path/to/fake:/path/to/destination + if [ ${row[0]} = 'FILE' ]; then + if [ -e "${row[2]}" ]; then + rlFileBackup --namespace $sos_BACKUP_NAMESPACE ${row[2]} || { + sosLog "sosReport: cannot backup '${row[2]}', skipping" + continue + } + else + mkdir -p $(dirname "${row[2]}") + fi + + /bin/cp -f "${row[1]}" "${row[2]}" || { + sosLog "sosReport: cannot install FILE fake '${row[1]}' to '${row[2]}'" + } + # FIXME: file fake install - something more needed besides cp? + + # CMD:/path/to/cmd:/path/to/destination + elif [ ${row[0]} = 'CMD' ]; then + if [ -e "${row[2]}" ]; then + rlFileBackup --namespace $sos_BACKUP_NAMESPACE ${row[2]} || { + sosLog "sosReport: cannot backup '${row[2]}', skipping" + continue + } + else + mkdir -p $(dirname "${row[2]}") + fi + + /bin/cp -f "${row[1]}" "${row[2]}" || { + sosLog "sosReport: cannot install CMD fake '${row[1]}' to '${row[2]}'" + continue + } + chmod a+x "${row[2]}" + + # TREE:/path/to/tree/archive + elif [ "${row[0]}" = 'TREE' ]; then + sosLog "sosReport: Skipping unimplemented TREE fake entry (${row[1]})" + # TODO: implement TREE fake install + continue + + else + sosLog "sosReport: unknown fake type (${row[0]})" + continue + fi + + done + + IFS="$IFS_backup" + + # TODO: implement handling of unpacked reports generated with --build option + # hint: grep 'sosreport build tree is located at *:' | sed 's/^.*: //' + echo "$params" | grep -- '--build' && { + sosLog "sosReport: --build parameter detected but not supported yet, bailing out" + return 10 + } + + # may need to handle rhel 5/6/7 differencies + # would be nice to use RUNPTY if such env variable exists? + local sos_output=$(mktemp) + set -o pipefail + # choose a way of running sosreport + if echo "$params" | grep -- '--batch'; then + local sos_cmd="sosreport $params < /dev/null 2>&1 | tee $sos_output" + else + local sos_cmd="echo -e '\ntester\n123\n' | sosreport $params 2>&1 | tee $sos_output" + fi + sosLog "sosReport: Executing \"$sos_cmd\"" + rlRun "$sos_cmd" 0 "sosReport: generating new report" + sos_REPORT=$(cat $sos_output | sed -n '/Your sosreport has been generated and saved in:/,+1p' | grep '/sosreport-.*tar.*' | sed 's/^ *//') + [ $? = 0 ] || { + sosLog "sosReport: Generated sosreport not recognized from sosreport output!" + sos_REPORT='' + return 20 + } + sos_SUM="$sos_REPORT.md5" + set +o pipefail + + # move the report to our library storage place + mv "$sos_REPORT" "$sos_SUM" "$sos_STORAGE" + sos_REPORT="$sos_STORAGE/$(basename $sos_REPORT)" + sos_SUM="$sos_STORAGE/$(basename $sos_SUM)" + # used to hack over rlWatchdog; rlWatchdog hack + ln -fs "$sos_REPORT" $sos_STORAGE/lastreport + + # append new entry into our sosreport db + echo "1 $report_id $(basename $sos_REPORT)" >> $sos_DB + + # store full additional info for this report + /bin/cp -f "$sos_FAKELIST" "$sos_REPORT.fakelist" + echo "$params" > "$sos_REPORT.params" + /bin/cp -f "$sos_output" "$sos_REPORT.output" + rlRun "tar tf $sos_REPORT | tee '$sos_REPORT.listing' |wc -l" 0 "sosReport: listing generated report" + + sosLog "sos_REPORT=$sos_REPORT" + + ls -l "$sos_REPORT"* + + # unfake if wanted + if [ "_$unfake" = "_1" -a $(wc -l < $sos_FAKELIST) -gt 0 ]; then + sosUnfake + fi + + # so to not return unfake result actually, FIXME ? + return 0 +} + +true <<'=cut' +=head2 sosAssertFileIncluded + +Assert presence of given filename in laste generated report ($sos_REPORT.listing). + + sosAssertFileIncluded regexp + +=over + +=item regexp + +Regular expression for matching filename, including path. + +=back + +Asserts and returns 0 when successfull. + +=cut + +sosAssertFileIncluded() { + + [ $# -eq 1 ] || { sosLog "sosAssertFileIncluded: bad usage"; return 1; } + + rlRun "grep '$1' '$sos_REPORT.listing' < /dev/null" 0 "sosAssertFileIncluded '$1'" + + return $? +} + +true <<'=cut' +=head2 sosAssertFileNotIncluded + +Assert absence of given filename in laste generated report ($sos_REPORT.listing). + + sosAssertFileNotIncluded regexp + +=over + +=item regexp + +Regular expression for matching filename, including path. + +=back + +Asserts and returns 0 when successfull. + +=cut + +sosAssertFileNotIncluded() { + + [ $# -eq 1 ] || { sosLog "sosAssertFileNotIncluded: bad usage"; return 1; } + + rlRun "grep '$1' '$sos_REPORT.listing' < /dev/null" 1 "sosAssertFileNotIncluded '$1'" + + return $? +} + +true <<'=cut' +=head2 sosReportList + +Printout of already generated sosreports with some stats like number of reuse. + + sosReportList + +=over + +=back + +Returns 0 when successfull. + +=cut + +sosReportList() { + + [ $# -eq 0 ] || { sosLog "sosReportList: bad usage"; return 1; } + + ls -l $sos_STORAGE + cat $sos_DB + + sosLog "sosReportList: listed $(wc -l $sos_DB) already generated reports" + + return 0 +} + + +true <<'=cut' +=head2 sosReportPurge + +Deletes all previously generated and stored sosreports, cleans reports db. + + sosReportPurge + +=over + +=back + +Returns 0 when successfull. + +=cut + +sosReportPurge() { + + [ $# -eq 0 ] || { sosLog "sosReportPurge: bad usage"; return 1; } + + rm -f "$sos_STORAGE/sosreport*" + echo -n '' > $sos_DB + + sosLog "sosReportPurge: deleted all previously generated reports" + + return 0 +} + + +sosLibraryLoaded () { + + # plugin directory + sos_PLUGINDIR=$(rpm -ql sos | grep 'general.py$') + sos_PLUGINDIR=$(dirname $sos_PLUGINDIR) + + # used for faked files backup + sos_BACKUP_NAMESPACE='sosutils' + + # setup lib dir variable, root dir used for various storage + sos_LIBDIR=$( readlink -fn $( dirname ${BASH_SOURCE[0]} ) ) + + # fake list is meant to be temporary, always just for one test + # note: no easy way to cleanly unfake after previous test + + sos_FAKELIST="$sos_LIBDIR/fakelist.txt" + + echo -n '' > "$sos_FAKELIST" + + # setup report storage dir variable and subdir friends; + # storage is meant to be permanent for multiple tests, + # until purged by sosReportPurge + + sos_STORAGE="$sos_LIBDIR/storage" + sos_LOG="$sos_STORAGE/log.txt" + sos_DB="$sos_STORAGE/db.txt" + + touch "$sos_LOG" > /dev/null 2>&1 || mkdir $sos_STORAGE || return 1 + touch "$sos_DB" + + local details="${TEST:-user}" + sosLog '---' + sosLog "library loaded by: $details" + + # FIXME: only with DEBUG? + rlRun "set | grep '^sos_.*'" 0 "sos/utils library loaded, variables defined" + + return 0 +} diff --git a/yum/common-functions/Makefile b/yum/common-functions/Makefile new file mode 100644 index 0000000..e12499d --- /dev/null +++ b/yum/common-functions/Makefile @@ -0,0 +1,64 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Makefile of /CoreOS/yum/Library/common-functions +# Description: Provides various yum and rpm related functions +# Author: Karel Srot +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2014 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +export TEST=/CoreOS/yum/Library/common-functions +export TESTVERSION=1.0 + +BUILT_FILES= + +FILES=$(METADATA) runtest.sh Makefile lib.sh + +.PHONY: all install download clean + +run: $(FILES) build + ./runtest.sh + +build: $(BUILT_FILES) + test -x runtest.sh || chmod a+x runtest.sh + +clean: + rm -f *~ $(BUILT_FILES) + + +-include /usr/share/rhts/lib/rhts-make.include + +$(METADATA): Makefile + @echo "Owner: Karel Srot " > $(METADATA) + @echo "Name: $(TEST)" >> $(METADATA) + @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) + @echo "Path: $(TEST_DIR)" >> $(METADATA) + @echo "Description: Provides various yum and rpm related functions" >> $(METADATA) + @echo "Type: Library" >> $(METADATA) + @echo "TestTime: 5m" >> $(METADATA) + @echo "RunFor: yum" >> $(METADATA) + @echo "RhtsRequires: yum createrepo rpm-build yum-utils" >> $(METADATA) + @echo "Provides: library(yum/common-functions)" >> $(METADATA) + @echo "Priority: Normal" >> $(METADATA) + @echo "License: GPLv2" >> $(METADATA) + @echo "Confidential: no" >> $(METADATA) + @echo "Destructive: no" >> $(METADATA) + + rhts-lint $(METADATA) diff --git a/yum/common-functions/lib.sh b/yum/common-functions/lib.sh new file mode 100644 index 0000000..325b016 --- /dev/null +++ b/yum/common-functions/lib.sh @@ -0,0 +1,651 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# lib.sh of /CoreOS/yum/Library/common-functions +# Description: Provides various yum and rpm related functions +# Author: Karel Srot +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2014 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# library-prefix = yumlib +# library-version = 2 +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head1 NAME + +yum/common-functions - Provides various yum and rpm related functions + +=head1 DESCRIPTION + +This library contain various functions shared across yum* and rpm* tests. + +=cut + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Variables +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#true <<'=cut' +#=pod +# +#=head1 VARIABLES +# +#Below is the list of global variables. When writing a new library, +#please make sure that all global variables start with the library +#prefix to prevent collisions with other libraries. +# +#=over +# +#=item fileFILENAME +# +#Default file name to be used when no provided ('foo'). +# +#=back +# +#=cut + +#fileFILENAME="foo" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Functions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head1 FUNCTIONS + +=head2 yumlibDisableYumPlugin + +Makes backup of the respective *.conf file and disables the plugin. +If the plugin provides a *.repo file(s) (such as yum-plugin-local) also +repositories in this *.repo file(s) are disabled. +Use yumlibYumPluginRestore to restore the original *.conf and *.repo files. + + yumlibDisableYumPlugin [--ignoremissing] package [package2 ...] + +=over + +=item package + +Name of the rpm package providing the plugin, e.g. yum-plugin-local. + +=item --ignoremissing + +Ignore not installed plugins + +=back + +Returns 0 when plugins are successfully disabled. +Returns 1 when some plugin isn't installed +Returns 2 when an installed plugin couldn't be disabled +Returns 3 when a *.repo file couldn't be disabled + +=cut + +yumlibDisableYumPlugin() { + local RET + local PKG + local CONF + local REPO + local IGNOREMISSING + IGNOREMISSING=0 + RET=0 + if [ "$1" == "--ignoremissing" ]; then + IGNOREMISSING=1 + shift + fi + while [ -n "$1" ]; do + PKG="$1" + if rpm -q $PKG &> /dev/null; then + CONF=`rpm -ql $PKG | grep /etc/yum/pluginconf.d/ | xargs echo` + rlFileBackup --namespace yumlibPluginBackup $CONF + rlLogInfo "Disabling plugin $PKG in $CONF" + sed -i 's/enabled.*=.*/enabled=0/g' $CONF || RET=2 + # for plugin provides a repo disable also repo + REPO=`rpm -ql $PKG | grep '/etc/yum.repos.d/.*\.repo' | xargs echo` + if [ -n "$REPO" ]; then + if [ -f $REPO ]; then + rlFileBackup --namespace yumlibPluginBackup $REPO + rlLogInfo "Disabling repos in $REPO" + sed -i 's/enabled.*=.*/enabled=0/g' $REPO || RET=3 + elif [ $IGNOREMISSING == "1" ]; then + rlLogInfo "Could not find repo $REPO from $PKG, ignoring" + else + rlLogWarning "Could not find repo $REPO from $PKG" + fi + fi + elif [ $IGNOREMISSING == "1" ]; then + rlLogInfo "Ignoring missing plugin $PKG" + else + rlLogWarning "No such package $PKG" + RET=1 + fi + shift + done + rlFileBackup --namespace yumlibPluginBackup /var/tmp/yumlibLoaded # just a placeholder so we backup at least something + return $RET +} + + +true <<'=cut' +=pod + +=head2 yumlibYumPluginRestore + +Restore *.conf files previously backed up by yumlibDisableYumPlugin calls. + + yumlibYumPluginRestore + +=over + +=back + +Returns 0 when the restore is successfull, 1 otherwise. + +=cut + +yumlibYumPluginRestore() { + rlFileRestore --namespace yumlibPluginBackup || return 1 +} + + +########################################################################################### + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# yumlibDisableRepos +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head2 yumlibDisableRepos + +Disable, backup and delete all repositories. (All repositories are stored in /etc/yum.repos.d-yumlib.backup/) + + yumlibDisableRepos + +=over + +=back + +Returns 0 when the disabled successfully. +Returns 1 when moving files is unsuccessfull. +Returns 2 when dir with backup already exists. + +=cut + +yumlibDisableRepos(){ + if [ ! -d "/etc/yum.repos.d-yumlib.backup" ]; then + rlLogInfo "Make dir /etc/yum.repos.d-yumlib.backup/ for backup" + mkdir /etc/yum.repos.d-yumlib.backup + rlLogInfo "Moving /etc/yum.repos.d/ to /etc/yum.repos.d-yumlib.backup/" + mv /etc/yum.repos.d/* /etc/yum.repos.d-yumlib.backup/ || { + rlLogWarning "Moving files to yum.repos.d-yumlib.backup failed, stopping yumlibDisableRepos" + return 1; + } + rlLogInfo "Removing files frome /etc/yum.repos.d/" + rm -rf /etc/yum.repos.d/* + else + rlLogWarning "Repositories have been already disabled." + rlLogDebug "Dir /etc/yum.repos.d-yumlib.backup is already created, check if there are necessary repos" + return 2; + fi +} + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# yumlibRestoreRepos +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head2 yumlibRestoreRepos + +Restore repositories previously backed up by yumlibDisableRepos. + + yumlibRestoreRepos + +=over + +=back + +Returns 0 when the restored successfully. +Returns 1 when backup dir doesn't exist. +Returns 2 when removing files from /etc/yum.repos.d/ failed +Returns 3 when moving backup to /etc/yum.repos.d/ failed. +Returns 4 when removing backup failed. + +=cut + +yumlibRestoreRepos(){ + + if [ -f /var/tmp/yumlibRepoSetupLocal.repos ]; then + rlLogWarning "You should call yumlibRepoCleanup() function! I am calling it for you!" + yumlibRepoCleanup + fi + + if [ -d "/etc/yum.repos.d-yumlib.backup" ]; then + rlLogInfo "Removing files from /etc/yum.repos.d/" + rm -rf /etc/yum.repos.d/* || { rlLogWarning "Removing files from /etc/yum.repos.d/ failed, stopping" + return 2 + } + rlLogInfo "Moving /etc/yum.repos.d-yumlib.backup/ back to /etc/yum.repos.d/" + mv /etc/yum.repos.d-yumlib.backup/* /etc/yum.repos.d/ || { rlLogWarning "Moving failed, stopping" + return 3 + } + rlLogInfo "Removing /etc/yum.repos.d-yumlib.backup/" + rm -rf /etc/yum.repos.d-yumlib.backup/ || { rlLogWarning "Removing backup failed, stopping" + return 4 + } + else + rlLogWarning "There are no repositories to restore." + rlLogDebug "Dir /etc/yum.repos.d-yumlib.backup does not exist, did you run yumlibDisableRepos before executing this?" + return 1 + fi +} + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# yumlibRepoSetupLocal +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head2 yumlibRepoSetupLocal + +Create repositories ,add them to yum repolist, and enable them. + + yumlibRepoSetupLocal repo_path1 [repo_path2 ...] + +=over + +=item repo_path1 + +Path to desired local repository. Can be existing or nonexisting directory. Base directory names can't be duplicit. + +=back + +Returns 0 when the setup is successfull, 1 otherwise. + +=cut + +yumlibRepoSetupLocal(){ + #Parse arguments, they should be only directory paths + for arg in "$@" + do + rlLogDebug "Path to repository is $arg" + local NAME=$(basename $arg) + rlLogDebug "Name for repo is $NAME" + + #If base dirnames are equeal => error + if [ -e "/etc/yum.repos.d/$NAME.repo" ]; then + rlLogError "$NAME.repo already exists, you should use different name." + return 1; + fi + + #Create dir for repo if not exist + if [ ! -e $arg ]; then + mkdir -p $arg + rlLogInfo "Created dir $arg" + fi + + #if arg is not realpath to dir, get realpath + if [[ ! $arg =~ ^[\/].* ]]; then + arg=$(readlink -f $arg) + fi + + #Create repo + cat > /etc/yum.repos.d/$NAME.repo <<_EOF +[$NAME] +name=My Local Repo $NAME +baseurl=file://$arg/ +enabled=1 +gpgcheck=0 +_EOF + + createrepo $arg + rlLogInfo "Created and added repository $NAME to /etc/yum.repos.d/" + + #Write created repo paths to tmp + echo "$arg" >> /var/tmp/yumlibRepoSetupLocal.repos + done +} #end of yumlibRepoSetupLocal() + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# yumlibRepoCleanup +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head2 yumlibRepoCleanup + +Clean up specified repositories or all repositories created by yumlibRepoSetupLocal. +It removes also yum metadata of specified repositories. +You should use this function every time you use yumlibRepoSetupLocal() in order to cleanup. +This should be called before yumlibRestoreRepos(). + + yumlibRepoCleanup [repo_path1 ...] + +=over + +=item repo_path1 + +Path to local repository. + +=back + +Returns 0 when the cleanup is successfull, 1 otherwise. + +=cut + +#add parameter for cleanup of user defined repos. +yumlibRepoCleanup(){ + #If there are some files specified in arguments, proccess them + if [[ $# > 0 ]]; then + repos=$@ + else + local repos=$(cat "/var/tmp/yumlibRepoSetupLocal.repos") + fi + + for arg in $repos + do + local NAME=$(basename $arg) + echo \"$arg\" + rlRun "yum --disablerepo=\* --enablerepo=$NAME* clean all" + if [ -d "$arg" ]; then + rm -rf $arg + rlLogInfo "deleting $arg" + fi + #Mby not needed, it wil be cleand with yumlibRestoreRepos + if [ -e "/etc/yum.repos.d/$NAME.repo" ]; then + rm -rf /etc/yum.repos.d/$NAME.repo + rlLogInfo "deleting $NAME.repo" + fi + done + + #There wasn't any arguments, we can delete /var/tmp/yumlibRepoSetupLocal.repos + if [[ $# < 1 ]]; then + rm -f /var/tmp/yumlibRepoSetupLocal.repos + rlLogInfo "Deleting /var/tmp/yumlibRepoSetupLocal.repos" + fi + +} #end of yumlibRepoCleanup + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# yumlibMakeDummyPKG +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#TODO: pridat parameter ci zmazat alebo nie tmp subor +true <<'=cut' +=pod + +=head2 yumlibMakeDummyPKG + +Create dummy package for testing. + + yumlibMakeDummyPKG [--keepPKGTMP] [-s SPEC] [--requires FOO] [--provides FOO] [--obsoletes FOO] [--conflicts FOO] [PKGNAME] [[EPOCH:]VERSION] [RELEASE] [SIZE_IN_kB] + +=over + +=item --keepPKGTMP + +Do not remove PKG.tmp from /tmp (which is removed by default). + +=item --requires FOO + +Add a pkg dependency. + +=item --provides FOO + +Adds pkg provides. + +=item --obsoletes FOO + +Adds pkg obsoletes. + +=item --conflicts FOO + +Adds pkg conflicts. + +=back + +Returns 0 when created successfully. +Returns 1 when build of the package failed. +Returns 2 when the path of the built package cannot be determined. +Returns 3 when moving the package into the current directory failed. + +=cut + +yumlibMakeDummyPKG(){ + + if [ "$1" = "--keepPKGTMP" ]; then + #if set, the /tmp/$PKGNAME.tmp won't be deleted + local keepPKGTMP=1 + shift 1 + fi + +# if I have a spec file, no need to create it + if [ "$1" = "-s" ]; then + local SPECFILE=$2 + #shift 2 + + else + local PKGNAME=dummy + local VERSION=1.0 + local RELEASE=1 + local SIZE=0 + + # process parameters and store them in a file + local PARAMFILE=`mktemp` + while [ "${1:0:1}" = "-" ]; do + if [ "$1" = "--requires" ]; then + echo "Requires: $2" >> $PARAMFILE + shift 2 + fi + if [ "$1" = "--provides" ]; then + echo "Provides: $2" >> $PARAMFILE + shift 2 + fi + if [ "$1" = "--obsoletes" ]; then + echo "Obsoletes: $2" >> $PARAMFILE + shift 2 + fi + if [ "$1" = "--conflicts" ]; then + echo "Conflicts: $2" >> $PARAMFILE + shift 2 + fi + done + + [ -n "$1" ] && PKGNAME=$1 + [ -n "$2" ] && EPOCH_VERSION=$2 + [ -n "$3" ] && RELEASE=$3 + [ -n "$4" ] && SIZE=$4 + local SPECFILE=$PKGNAME.spec + + if echo $EPOCH_VERSION | grep -q ':'; then + EPOCH=${EPOCH_VERSION%%:*} + VERSION=${EPOCH_VERSION#*:} + else + EPOCH="" + if [ -n "$EPOCH_VERSION" ]; then VERSION=$EPOCH_VERSION; fi + fi + + cat > $SPECFILE <<_EOF1 +Summary: $PKGNAME Package +Name: $PKGNAME +_EOF1 + + if [ "x$EPOCH" != "x" ]; then echo "Epoch: $EPOCH" >> $SPECFILE; fi + + cat >> $SPECFILE <<_EOF2 +Version: $VERSION +Release: $RELEASE +Group: System Environment/Base +License: GPL +BuildArch: noarch +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) +_EOF2 + + # include the PARAMFILE + cat $PARAMFILE >> $SPECFILE + + # and continue + cat >> $SPECFILE <<_EOF +%description + +This is a $PKGNAME test package created by make_dummy_package.sh script + +%build +_EOF + + # for SIZE>0 prepare a file of sufficient size + rm -f $PKGNAME.tmp + if [ $SIZE -gt 0 ]; then + for file in /usr/bin/*; do + gzip -c $file >> $PKGNAME.tmp + [ `du $PKGNAME.tmp | awk '{ print \$1 }'` -gt $SIZE ] && break + done + tar -cf /tmp/$PKGNAME.tmp $PKGNAME.tmp + rm -f $PKGNAME.tmp + fi + + cat >> $SPECFILE <<_EOF +touch /tmp/$PKGNAME.tmp # create it if not present +cp /tmp/$PKGNAME.tmp . # just copy so it can be used in future rebuilds + +%install +mkdir -p %{buildroot}/usr/local/ +mv $PKGNAME.tmp %{buildroot}/usr/local/ + +%files +/usr/local/$PKGNAME.tmp +_EOF + + fi + +local TmpFile=`mktemp` +if ! rpmbuild -ba $SPECFILE &> $TmpFile; then + cat $TmpFile + return 1 +fi +local PkgPath=`grep 'Wrote:' $TmpFile | cut -d ' ' -f 2` || return 2 +local PKGrpm=`grep 'Wrote:' $TmpFile | cut -d ' ' -f 2 | grep -v 'src.rpm'` || return 2 +local PKGNames="" +local PKG + +# print built packages (except srpm) to stdout - RHEL-6 basename doesn't know --multiple +for PKG in $PKGrpm; do + PKGNames="$PKGNames $( basename $PKG )" +done +echo $PKGNames + +mv $PkgPath . || return 3 # move built file to a current directory +rm $TmpFile +if [ -e "$PARAMFILE" ]; then + rm $PARAMFILE +fi + +[[ $keepPKGTMP -eq 1 ]] || rm -rf /tmp/$PKGNAME.tmp +} #end of yumlibMakeDummyPKG + +########################################################################################### + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Execution +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#true <<'=cut' +#=pod +# +#=head1 EXECUTION +# +#This library supports direct execution. When run as a task, phases +#provided in the PHASE environment variable will be executed. +#Supported phases are: +# +#=over +# +#=item Create +# +#Create a new empty file. Use FILENAME to provide the desired file +#name. By default 'foo' is created in the current directory. +# +#=item Test +# +#Run the self test suite. +# +#=back +# +#=cut + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Verification +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# This is a verification callback which will be called by +# rlImport after sourcing the library to make sure everything is +# all right. It makes sense to perform a basic sanity test and +# check that all required packages are installed. The function +# should return 0 only when the library is ready to serve. + +yumlibLibraryLoaded() { + if [ -f /var/tmp/yumlibRepoSetupLocal.repos ]; then + rm -f /var/tmp/yumlibRepoSetupLocal.repos + rlLogInfo "One of previously running tests didn't call yumlibRepoCleanup() function" + fi + rpm -q rpm yum yum-utils + touch /var/tmp/yumlibLoaded || return 1 + return 0 +} + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Authors +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +true <<'=cut' +=pod + +=head1 AUTHORS + +=over + +=item * + +Karel Srot +Marek Marusic + +=back + +=cut diff --git a/yum/common-functions/runtest.sh b/yum/common-functions/runtest.sh new file mode 100755 index 0000000..467b80e --- /dev/null +++ b/yum/common-functions/runtest.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# runtest.sh of /CoreOS/yum/Library/common-functions +# Description: Provides various yum and rpm related functions +# Author: Karel Srot +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2014 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Include Beaker environment +[ -e /usr/bin/rhts-environment.sh ] && . /usr/bin/rhts-environment.sh +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGE="yum" +PHASE=${PHASE:-Test} + +rlJournalStart + rlPhaseStartSetup + rlRun "rlImport yum/common-functions" + rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" + rlRun "pushd $TmpDir" + rlPhaseEnd + +# # Create file +# if [[ "$PHASE" =~ "Create" ]]; then +# rlPhaseStartTest "Create" +# fileCreate +# rlPhaseEnd +# fi + + # Self test + if [[ "$PHASE" =~ "Test" ]]; then + rlPhaseStartTest "Test yumlibDisableYumPlugin and yumlibYumPluginRestore" + PLUGIN=yum-plugin-security + if rpm -q $PLUGIN &> /dev/null; then + CONF=/etc/yum/pluginconf.d/security.conf + rlFileBackup $CONF + rlRun "sed -i 's/enabled=.*/enabled=1/g' $CONF" + rlRun "yumlibDisableYumPlugin $PLUGIN" + rlAssertGrep 'enabled=0' $CONF + rlRun "yumlibYumPluginRestore" + rlAssertGrep 'enabled=1' $CONF + rlFileRestore + else + rlLogWarning "$PLUGIN is not installed, I cannot run the test" + fi + rlPhaseEnd +# rlPhaseStartTest "Test filename in parameter" +# fileCreate "parameter-file" +# rlAssertExists "parameter-file" +# rlPhaseEnd +# rlPhaseStartTest "Test filename in variable" +# FILENAME="variable-file" fileCreate +# rlAssertExists "variable-file" +# rlPhaseEnd + fi + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r $TmpDir" 0 "Removing tmp directory" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd