Issue #174: Add -g option for Groot and integ tests for user namespace

This commit is contained in:
Filippo Squillace 2017-04-09 17:34:43 +01:00
parent fcb4a36f30
commit b817aa8445
15 changed files with 433 additions and 333 deletions

View file

@ -17,9 +17,14 @@ install:
script:
- bash --version
- bash ./tests/unit-tests/unit-tests.sh
- bash ./tests/checkstyle/checkstyle.sh
- junest --check ./bin/junest
- bash ./tests/unit-tests/unit-tests.sh
# Multiple tests against different execution modes:
- junest -f -- ${PWD}/lib/checks/check.sh
- junest -u -- ${PWD}/lib/checks/check.sh --skip-aur-tests
- sudo -E ${PWD}/bin/junest -g -- ${PWD}/lib/checks/check.sh --run-root-tests
- yes | junest --delete
- JUNEST_HOME=~/.junest-arm junest --check ./bin/junest --skip-root-tests
- JUNEST_HOME=~/.junest-arm junest -f -- ./lib/checks/check.sh
- yes | JUNEST_HOME=~/.junest-arm junest --delete

View file

@ -11,7 +11,7 @@ The Arch Linux based distro that runs upon any Linux distros without root access
|Project Status|Donation|Communication|
|:------------:|:------:|:-----------:|
| [![Build status](https://api.travis-ci.org/fsquillace/junest.png?branch=master)](https://travis-ci.org/fsquillace/junest) [![OpenHub](https://www.openhub.net/p/junest/widgets/project_thin_badge.gif)](https://www.openhub.net/p/junest) | [![PayPal](https://img.shields.io/badge/PayPal-Donate%20a%20beer-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8LEHQKBCYTACY) [![Gratipay](https://img.shields.io/badge/Gratipay-Donate%20to%20JuNest-green.svg)](https://gratipay.com/junest/) | [![Join the gitter chat at https://gitter.im/fsquillace/junest](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/fsquillace/junest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the IRC chat at https://webchat.freenode.net/?channels=junest](https://img.shields.io/badge/IRC-JuNest-yellow.svg)](https://webchat.freenode.net/?channels=junest) [![Join the group at https://groups.google.com/d/forum/junest](https://img.shields.io/badge/Google Groups-JuNest-red.svg)](https://groups.google.com/d/forum/junest) [![RSS](https://img.shields.io/badge/RSS-News-orange.svg)](http://fsquillace.github.io/junest-site/feed.xml) |
| [![Build status](https://api.travis-ci.org/fsquillace/junest.png?branch=master)](https://travis-ci.org/fsquillace/junest) [![OpenHub](https://www.openhub.net/p/junest/widgets/project_thin_badge.gif)](https://www.openhub.net/p/junest) | [![PayPal](https://img.shields.io/badge/PayPal-Donate%20a%20beer-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8LEHQKBCYTACY) [![Gratipay](https://img.shields.io/badge/Gratipay-Donate%20to%20JuNest-green.svg)](https://gratipay.com/junest/) | [![Join the gitter chat at https://gitter.im/fsquillace/junest](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/fsquillace/junest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the IRC chat at https://webchat.freenode.net/?channels=junest](https://img.shields.io/badge/IRC-JuNest-yellow.svg)](https://webchat.freenode.net/?channels=junest) [![Join the group at https://groups.google.com/d/forum/junest](https://img.shields.io/badge/GoogleGroups-JuNest-red.svg)](https://groups.google.com/d/forum/junest) [![RSS](https://img.shields.io/badge/RSS-News-orange.svg)](http://fsquillace.github.io/junest-site/feed.xml) |
**Table of Contents**
- [Description](#description)
@ -48,19 +48,62 @@ JuNest follows the [Arch Linux philosophy](https://wiki.archlinux.org/index.php/
Quickstart
==========
There are three different ways you can run JuNest:
Backend programs
----------------
There are three different ways you can run JuNest depending on the backend program you decide to use.
### PRoot based ###
[Proot](https://wiki.archlinux.org/index.php/Proot) represents the default
program used for accessing to the JuNest environments.
The main reason to choose Proot as default backend program is because
it represents a portable solution that works well in most of GNU/Linux distros available.
One of the major drawbacks is the fact that Proot is not officially
supported anymore, therefore, Proot bugs may no longer be fixed.
In order to run JuNest via Proot:
- As normal user - Allow to make basic operations: ```junest```
- As fakeroot - Allow to install/remove packages: ```junest -f```
- As root - Allow to have fully root privileges inside JuNest environment (you need to be root for executing this): ```junest -r```
### Linux namespaces based ###
The [Linux namespaces](http://man7.org/linux/man-pages/man7/namespaces.7.html)
represents the next generation backend program for JuNest.
The major drawback about the namespace is portability, as certain requirements
need to be satisfied: 1) Only starting from Linux 3.8, unprivileged processes can
create the required user and mount namespaces.
2) Moreover, the Linux kernel distro must have the user namespace enabled.
Hopefully, in the future the major GNU/Linux distros will start enabling such feature by default.
For instance, Ubuntu (version 14.04+) already has such feature enabled.
In order to run JuNest via Linux namespaces:
- As fakeroot - Allow to install/remove packages: ```junest -u```
### Chroot based ###
This solution suits only for privileged users. JuNest provides the possibility
to run the environment via `chroot` program.
In particular, it uses a special program called `GRoot`, an enhanced `chroot`
wrapper that allows to bind mount directories specified by the user, such as
/proc, /sys, /dev, /tmp and $HOME, before
executing any programs inside the JuNest sandbox. In case the mounting will not
work, JuNest is even providing the possibility to run the environment directly via
the pure `chroot` command.
In order to run JuNest via `chroot` solutions:
- As root via `GRoot` - Allow to have fully root privileges inside JuNest environment (you need to be root for executing this): ```junest -g```
- As root via `chroot` - Allow to have fully root privileges inside JuNest environment (you need to be root for executing this): ```junest -r```
After running JuNest
--------------------
If the JuNest image has not been downloaded yet, the script will download
the image and will place it to the default directory ~/.junest.
You can change the default directory by changing the environment variable *JUNEST\_HOME*.
the image from the repository and will place it to the default directory `~/.junest`.
You can change the default directory by changing the environment variable `JUNEST_HOME`.
If you are new on Archlinux and you are not familiar with *pacman* package manager
If you are new on Arch Linux and you are not familiar with `pacman` package manager
visit the [pacman rosetta page](https://wiki.archlinux.org/index.php/Pacman_Rosetta).
Installation
@ -90,7 +133,7 @@ Just clone the JuNest repo somewhere (for example in ~/.local/share/junest):
### Installation using AUR (Arch Linux only) ###
If you are using an Arch Linux system you can, alternatively, install JuNest from the [AUR repository](https://aur.archlinux.org/):
yogurt -S junest-git
yaourt -S junest-git
export PATH=/opt/junest/bin:$PATH
## Method two ##
@ -98,7 +141,7 @@ Alternatively, another installation method would be to directly download the JuN
ARCH=<one of "x86_64", "x86", "arm">
mkdir ~/.junest
curl https://dl.dropboxusercontent.com/u/42449030/junest/junest-${ARCH}.tar.gz | tar -xz -C ~/.junest
curl https://s3-eu-west-1.amazonaws.com/junest-repo/junest-${ARCH}.tar.gz | tar -xz -C ~/.junest
export PATH=~/.junest/opt/junest/bin:$PATH
Advanced usage
@ -141,12 +184,12 @@ To bind a host directory to a guest location, you can use proot arguments:
junest -p "-b /mnt/mydata:/home/user/mydata"
Check out the proot options with:
This will works with PRoot, Namespace and GRoot backend programs.
Check out the backend program options by passing `--help` option:
junest -p "--help"
junest [-u|-g] -p "--help"
## Systemd integration ##
Although JuNest has not been designed to be a complete container, it is even possible to
virtualize the process tree thanks to the [systemd container](https://wiki.archlinux.org/index.php/Systemd-nspawn).
The JuNest containter allows to run services inside the container that can be
@ -345,6 +388,18 @@ Troubleshooting
> since JuNest will try to preserve the JuNest environment by assigning ownership
> of the files to the real user.
## Not enabled User namespace or kernel too old ##
> **Q**: Why do I get warning when I run JuNest via Linux namespaces?
$> junest -u
User namespace is not enabled or Kernel too old (<3.8). Proceeding anyway...
> **A**: This means that JuNest detected that the host OS either
> does not have a newer Linux version or the user namespace is not enabled.
> JuNest does not stop the execution of the program but it attempts to run it
> anyway. Try to use Proot as backend program in case is not possible to invoke namespaces.
More documentation
==================
There are additional tutorials in the

View file

@ -56,7 +56,7 @@ function chroot_maybe_add_mount() {
}
function chroot_setup() {
$OPT_NO_UMOUNT || check_and_trap 'chroot_teardown' EXIT
$OPT_NO_UMOUNT || check_and_trap 'chroot_teardown' QUIT EXIT ABRT KILL TERM INT
if ! chroot_maybe_add_mount "! $MOUNTPOINT -q '$CHROOTDIR'" --bind "$CHROOTDIR" "$CHROOTDIR"
then

View file

@ -36,18 +36,17 @@ usage() {
echo
echo -e "Access options:"
echo -e "-f, --fakeroot Run $NAME with fakeroot privileges"
echo -e "-r, --root Run $NAME with root privileges via GRoot"
echo -e "-g, --groot Run $NAME with root privileges via GRoot"
echo -e "-r, --root Run $NAME with root privileges via classic chroot"
echo -e "-u, --namespace Use Linux Namespace (with GRoot) instead of PRoot"
echo -e "-p, --backend-args <args> Arguments for backend program (PRoot or GRoot)"
echo -e " ($CMD -p \"--help\" to check out the PRoot options"
echo -e " $CMD -u -p \"--help\" to check out the GRoot options)"
echo -e "-u, --user-namespace Use Linux User Namespace instead of PRoot"
echo -e " $CMD -g -p \"--help\" to check out the GRoot options"
echo -e " $CMD -r -p \"--help\" to check out the chroot options)"
echo
echo -e "Building options:"
echo -e "-b, --build-image Build a $NAME image (must run in ArchLinux)"
echo -e "-n, --disable-validation Disable the $NAME image validation"
echo -e "-c, --check <${CMD}_script> Validate the env located in ${JUNEST_HOME}"
echo -e " using ${CMD}_script. This will alterate the environment"
echo -e "-s, --skip-root-tests Skip the root tests during the validation process"
echo
echo -e "General options:"
echo -e "-h, --help Show this help message"
@ -60,33 +59,17 @@ version() {
check_cli(){
if $OPT_BUILD_IMAGE
then
if $OPT_DELETE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT || $OPT_CHECK
then
die "The build image option must be used exclusively"
fi
fi
if $OPT_SKIP_ROOT_TEST
then
if $OPT_DELETE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT
then
die "The skip root tests option must be used with either build image or check options"
fi
fi
if $OPT_CHECK
then
if $OPT_DELETE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT || $OPT_BUILD_IMAGE
then
die "The validation image option must be used exclusively"
die "The build image option must be used exclusively"
fi
fi
if $OPT_DISABLE_VALIDATION
then
if $OPT_DELETE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT || $OPT_CHECK
$OPT_FAKEROOT || $OPT_ROOT
then
die "The disable validation option must be used with the build image option only"
fi
@ -94,7 +77,7 @@ check_cli(){
if $OPT_DELETE
then
if $OPT_BUILD_IMAGE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION || $OPT_CHECK
$OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION
then
die "The $NAME delete option must be used exclusively"
fi
@ -102,7 +85,7 @@ check_cli(){
if $OPT_HELP
then
if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION || $OPT_CHECK
$OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION
then
die "The $NAME help option must be used exclusively"
fi
@ -110,7 +93,7 @@ check_cli(){
if $OPT_VERSION
then
if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION || $OPT_CHECK
$OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION
then
die "The $NAME version option must be used exclusively"
fi
@ -122,7 +105,7 @@ check_cli(){
if $OPT_BACKEND_ARGS || $OPT_ARCH
then
if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || \
$OPT_ROOT || $OPT_VERSION || $OPT_DISABLE_VALIDATION || $OPT_CHECK
$OPT_ROOT || $OPT_VERSION || $OPT_DISABLE_VALIDATION
then
die "Invalid syntax: Proot and arch args are not allowed with the other options"
fi
@ -130,7 +113,7 @@ check_cli(){
if [ "$ARGS" != "" ]
then
if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \
$OPT_VERSION || $OPT_DISABLE_VALIDATION || $OPT_CHECK
$OPT_VERSION || $OPT_DISABLE_VALIDATION
then
die "No arguments are needed. For the CLI syntax run: $CMD --help"
fi
@ -145,6 +128,7 @@ function parse_arguments(){
IMAGE_FILE=""
OPT_FAKEROOT=false
OPT_ROOT=false
OPT_GROOT=false
OPT_USER_NAMESPACE=false
OPT_BACKEND_ARGS=false
BACKEND_ARGS=""
@ -152,9 +136,7 @@ function parse_arguments(){
ARCH_ARG=""
OPT_BUILD_IMAGE=false
OPT_DISABLE_VALIDATION=false
OPT_CHECK=false
CHECK_ARG=""
OPT_SKIP_ROOT_TEST=false
OPT_DELETE=false
OPT_HELP=false
OPT_VERSION=false
@ -164,13 +146,12 @@ function parse_arguments(){
-i|--setup-from-file) OPT_SETUP_FROM_FILE=true ; shift ; IMAGE_FILE=$1 ; shift ;;
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
-r|--root) OPT_ROOT=true ; shift ;;
-u|--user-namespace) OPT_USER_NAMESPACE=true ; shift ;;
-g|--groot) OPT_GROOT=true ; shift ;;
-u|--namespace) OPT_USER_NAMESPACE=true ; shift ;;
-p|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;;
-a|--arch) OPT_ARCH=true ; shift ; ARCH_ARG=$1; shift ;;
-b|--build-image) OPT_BUILD_IMAGE=true ; shift ;;
-n|--disable-validation) OPT_DISABLE_VALIDATION=true ; shift ;;
-c|--check) OPT_CHECK=true ; shift ; CHECK_ARG=$1; shift ;;
-s|--skip-root-tests) OPT_SKIP_ROOT_TEST=true ; shift ;;
-d|--delete) OPT_DELETE=true ; shift ;;
-h|--help) OPT_HELP=true ; shift ;;
-V|--version) OPT_VERSION=true ; shift ;;
@ -192,14 +173,11 @@ function execute_operation(){
$OPT_VERSION && version && return
if $OPT_BUILD_IMAGE; then
build_image_env $OPT_DISABLE_VALIDATION $OPT_SKIP_ROOT_TEST
build_image_env $OPT_DISABLE_VALIDATION
return
elif $OPT_DELETE; then
delete_env
return
elif $OPT_CHECK; then
check_env "${JUNEST_HOME}" "${CHECK_ARG}" $OPT_SKIP_ROOT_TEST
return
fi
if ! is_env_installed
@ -217,22 +195,21 @@ function execute_operation(){
[ -z "${ARCH_ARG}" ] || \
die "The option --arch cannot be specified since JuNest has already been downloaded in $JUNEST_HOME"
local run_env
if $OPT_USER_NAMESPACE; then
if $OPT_FAKEROOT; then
run_env_as_fakeroot_with_namespace "${BACKEND_ARGS}" "${ARGS[@]}"
else
run_env_as_user_with_namespace "${BACKEND_ARGS}" "${ARGS[@]}"
fi
run_env=run_env_with_namespace
elif $OPT_FAKEROOT; then
run_env=run_env_as_fakeroot
elif $OPT_ROOT; then
run_env=run_env_as_chroot
elif $OPT_GROOT; then
run_env=run_env_as_groot
else
if $OPT_FAKEROOT; then
run_env_as_fakeroot "${BACKEND_ARGS}" "${ARGS[@]}"
elif $OPT_ROOT; then
run_env_as_root "${ARGS[@]}"
else
run_env_as_user "${BACKEND_ARGS}" "${ARGS[@]}"
fi
run_env=run_env_as_user
fi
$run_env "${BACKEND_ARGS}" "${ARGS[@]}"
}
function main() {

62
lib/checks/check.sh Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env bash
#
# This modules is used for:
# - Running checks against the building JuNest image
# - Integration tests on JuNest script against different execution modes (i.e. -f, -u, -r modes)
#
# Dependencies:
# - None
#
# vim: ft=sh
set -eu
OPT_RUN_ROOT_TESTS=${1:-false}
RUN_ROOT_TESTS=false
[[ ${OPT_RUN_ROOT_TESTS} == "--run-root-tests" ]] && RUN_ROOT_TESTS=true
OPT_SKIP_AUR_TESTS=${1:-false}
SKIP_AUR_TESTS=false
[[ ${OPT_SKIP_AUR_TESTS} == "--skip-aur-tests" ]] && SKIP_AUR_TESTS=true
JUNEST_HOME=${JUNEST_HOME:-$HOME/.junest}
# JUNEST_BASE can be overridden for testing purposes.
# There is no need for doing it for normal usage.
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/../..)}"
source "${JUNEST_BASE}/lib/utils/utils.sh"
source "${JUNEST_BASE}/lib/core/common.sh"
info "Validating JuNest located in ${JUNEST_HOME}..."
info "Initial JuNest setup..."
echo "Server = ${DEFAULT_MIRROR}" >> /etc/pacman.d/mirrorlist
pacman --noconfirm -Syy
pacman --noconfirm -S base-devel
info "Checking essential executables work..."
pacman -Qi pacman 1> /dev/null
yogurt -V 1> /dev/null
/opt/proot/proot-$ARCH --help 1> /dev/null
repo_package1=tree
echo "Checking ${repo_package1} package from official repo..."
pacman --noconfirm -S ${repo_package1}
tree -L 1
pacman --noconfirm -Rsn ${repo_package1}
repo_package2=iftop
info "Checking ${repo_package2} package from official repo..."
pacman --noconfirm -S ${repo_package2}
$RUN_ROOT_TESTS && iftop -t -s 5
pacman --noconfirm -Rsn ${repo_package2}
if ! $SKIP_AUR_TESTS
then
aur_package=tcptraceroute
info "Checking ${aur_package} package from AUR repo..."
yogurt -A --noconfirm -S ${aur_package}
$RUN_ROOT_TESTS && tcptraceroute localhost
pacman --noconfirm -Rsn ${aur_package}
fi

View file

@ -40,7 +40,6 @@ function build_image_env(){
_check_package git
local disable_validation=$1
local skip_root_tests=$2
local maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t ${CMD}.XXXXXXXXXX)
sudo mkdir -p ${maindir}/root
@ -88,7 +87,8 @@ function build_image_env(){
then
mkdir -p ${maindir}/root_test
$TAR -zxpf ${imagefile} -C "${maindir}/root_test"
check_env "${maindir}/root_test" "${maindir}/root_test/opt/${CMD}/bin/${CMD}" $skip_root_tests
JUNEST_HOME="${maindir}/root_test" ${maindir}/root_test/opt/${CMD}/bin/${CMD} -f ./lib/checks/check.sh
JUNEST_HOME="${maindir}/root_test" sudo -E ${maindir}/root_test/opt/${CMD}/bin/${CMD} -g ./lib/checks/check.sh --run-root-tests
fi
sudo cp ${maindir}/output/${imagefile} ${ORIGIN_WD}
@ -97,45 +97,3 @@ function build_image_env(){
trap - QUIT EXIT ABRT KILL TERM INT
sudo rm -fr "$maindir"
}
function check_env(){
local testdir=$1
local cmd=$2
local skip_root_tests=$3
info "Validating ${NAME} located in ${testdir} using the ${cmd} script..."
echo "Server = ${DEFAULT_MIRROR}" >> ${testdir}/etc/pacman.d/mirrorlist
JUNEST_HOME=${testdir} ${cmd} -f pacman --noconfirm -Syy
# Check most basic executables work
$skip_root_tests || JUNEST_HOME=${testdir} sudo -E ${cmd} -r pacman -Qi pacman 1> /dev/null
JUNEST_HOME=${testdir} ${cmd} -- pacman -Qi pacman 1> /dev/null
JUNEST_HOME=${testdir} ${cmd} -f -- pacman -Qi pacman 1> /dev/null
$skip_root_tests || JUNEST_HOME=${testdir} sudo -E ${cmd} -r yogurt -V 1> /dev/null
JUNEST_HOME=${testdir} ${cmd} -- yogurt -V 1> /dev/null
JUNEST_HOME=${testdir} ${cmd} -f -- yogurt -V 1> /dev/null
$skip_root_tests || JUNEST_HOME=${testdir} sudo -E ${cmd} -r /opt/proot/proot-$ARCH --help 1> /dev/null
JUNEST_HOME=${testdir} ${cmd} -- /opt/proot/proot-$ARCH --help 1> /dev/null
JUNEST_HOME=${testdir} ${cmd} -f -- /opt/proot/proot-$ARCH --help 1> /dev/null
local repo_package=tree
info "Installing ${repo_package} package from official repo using proot..."
JUNEST_HOME=${testdir} ${cmd} -f pacman --noconfirm -S ${repo_package}
JUNEST_HOME=${testdir} ${cmd} tree
JUNEST_HOME=${testdir} ${cmd} -f tree
local repo_package=iftop
info "Installing ${repo_package} package from official repo using root..."
JUNEST_HOME=${testdir} ${cmd} -f pacman --noconfirm -S ${repo_package}
$skip_root_tests || JUNEST_HOME=${testdir} sudo -E ${cmd} -r iftop -t -s 5
JUNEST_HOME=${testdir} ${cmd} -f pacman --noconfirm -S base-devel
local aur_package=tcptraceroute
info "Installing ${aur_package} package from AUR repo using proot..."
JUNEST_HOME=${testdir} ${cmd} -f -- yogurt -A --noconfirm -S ${aur_package}
$skip_root_tests || JUNEST_HOME=${testdir} sudo -E ${cmd} -r tcptraceroute localhost
info "Removing the previous packages..."
JUNEST_HOME=${testdir} ${cmd} -f pacman --noconfirm -Rsn tcptraceroute tree iftop
JUNEST_HOME=${testdir} ${cmd} -u -- ls -la
}

View file

@ -8,27 +8,12 @@
#
# vim: ft=sh
#######################################
# Run JuNest as real root.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# UID (RO) : The user ID.
# SUDO_USER (RO) : The sudo user ID.
# SUDO_GID (RO) : The sudo group ID.
# SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# cmd ($@?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Output:
# - : The command output.
#######################################
function run_env_as_root(){
source ${JUNEST_HOME}/etc/junest/info
[ "$JUNEST_ARCH" != "$ARCH" ] && \
die_on_status $ARCHITECTURE_MISMATCH "The host system architecture is not correct: $ARCH != $JUNEST_ARCH"
function _run_env_as_xroot(){
local cmd=$1
local backend_args="$2"
shift 2
check_same_arch
local uid=$UID
# SUDO_USER is more reliable compared to SUDO_UID
@ -41,5 +26,63 @@ function run_env_as_root(){
trap - QUIT EXIT ABRT KILL TERM INT
trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT KILL TERM INT
JUNEST_ENV=1 chroot_cmd "$JUNEST_HOME" "${SH[@]}" "-c" "${main_cmd}"
copy_common_files
check_nested_env
JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "${main_cmd}"
}
#######################################
# Run JuNest as real root via GRoot command.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# UID (RO) : The user ID.
# SUDO_USER (RO) : The sudo user ID.
# SUDO_GID (RO) : The sudo group ID.
# SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to proot
# cmd ($2-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Output:
# - : The command output.
#######################################
function run_env_as_groot(){
local backend_args="$1"
shift
provide_common_bindings
local bindings=${RESULT}
unset RESULT
_run_env_as_xroot "$GROOT $bindings" "$backend_args" "$@"
}
#######################################
# Run JuNest as real root via chroot command.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# UID (RO) : The user ID.
# SUDO_USER (RO) : The sudo user ID.
# SUDO_GID (RO) : The sudo group ID.
# SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to proot
# cmd ($2-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Output:
# - : The command output.
#######################################
function run_env_as_chroot(){
local backend_args="$1"
shift
_run_env_as_xroot chroot_cmd "$backend_args" "$@"
}

View file

@ -19,20 +19,9 @@ NESTED_ENVIRONMENT=106
VARIABLE_NOT_SET=107
NO_CONFIG_FOUND=108
if [ "$JUNEST_ENV" == "1" ]
then
die_on_status $NESTED_ENVIRONMENT "Error: Nested ${NAME} environments are not allowed"
elif [ ! -z $JUNEST_ENV ] && [ "$JUNEST_ENV" != "0" ]
then
die_on_status $VARIABLE_NOT_SET "The variable JUNEST_ENV is not properly set"
fi
[ -z ${JUNEST_HOME} ] && JUNEST_HOME=~/.${CMD}
[ -z ${JUNEST_BASE} ] && JUNEST_BASE=${JUNEST_HOME}/opt/junest
if [ -z ${JUNEST_TEMPDIR} ] || [ ! -d ${JUNEST_TEMPDIR} ]
then
JUNEST_TEMPDIR=/tmp
fi
JUNEST_HOME=${JUNEST_HOME:-~/.${CMD}}
JUNEST_BASE=${JUNEST_BASE:-${JUNEST_HOME}/opt/junest}
JUNEST_TEMPDIR=${JUNEST_TEMPDIR:-/tmp}
# The update of the variable PATH ensures that the executables are
# found on different locations
@ -99,36 +88,55 @@ LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
# image.
function ln_cmd(){
$LN $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$LN $@
$LN "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$LN "$@"
}
function getent_cmd(){
$GETENT $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$GETENT $@
$GETENT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$GETENT "$@"
}
function cp_cmd(){
$CP $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CP $@
$CP "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CP "$@"
}
function rm_cmd(){
$RM $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$RM $@
$RM "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$RM "$@"
}
function chown_cmd(){
$CHOWN $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CHOWN $@
$CHOWN "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CHOWN "$@"
}
function mkdir_cmd(){
$MKDIR $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$MKDIR $@
$MKDIR "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$MKDIR "$@"
}
function zgrep_cmd(){
# No need for LD_EXEC as zgrep is a POSIX shell script
$ZGREP $@ || ${JUNEST_HOME}/usr/bin/$ZGREP $@
$ZGREP "$@" || ${JUNEST_HOME}/usr/bin/$ZGREP "$@"
}
function download_cmd(){
$WGET "$@" || $CURL "$@"
}
function chroot_cmd(){
$CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CLASSIC_CHROOT "$@"
}
function unshare_cmd(){
$UNSHARE $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE $@
# Most of the distros do not have the `unshare` command updated
# with --user option available.
# Hence, give priority to the `unshare` executable in JuNest image.
if $LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE --user "${SH[@]}" "-c" ":"
then
$LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE "${@}"
elif $UNSHARE --user "${SH[@]}" "-c" ":"
then
$UNSHARE "$@"
else
die "Error: Something went wrong with unshare command. Exiting"
fi
}
function proot_cmd(){
@ -141,20 +149,60 @@ function proot_cmd(){
then
PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${@}"
else
die "Error: Check if the ${CMD} arguments are correct and if the kernel is too old use the option ${CMD} -p \"-k 3.10\""
die "Error: Something went wrong with proot command. Exiting"
fi
}
function download_cmd(){
$WGET $@ || $CURL $@
}
function chroot_cmd(){
$GROOT "$@" || $CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CLASSIC_CHROOT "$@"
}
############## COMMON FUNCTIONS ###############
#######################################
# Check if the executable is being running inside a JuNest environment.
#
# Globals:
# JUNEST_ENV (RO) : The boolean junest env check
# NESTED_ENVIRONMENT (RO) : The nest env exception
# VARIABLE_NOT_SET (RO) : The var not set exception
# NAME (RO) : The JuNest name
# Arguments:
# None
# Returns:
# VARIABLE_NOT_SET : If no JUNEST_ENV is not properly set
# NESTED_ENVIRONMENT : If the script is executed inside JuNest env
# Output:
# None
#######################################
function check_nested_env() {
if [[ $JUNEST_ENV == "1" ]]
then
die_on_status $NESTED_ENVIRONMENT "Error: Nested ${NAME} environments are not allowed"
elif [[ ! -z $JUNEST_ENV ]] && [[ $JUNEST_ENV != "0" ]]
then
die_on_status $VARIABLE_NOT_SET "The variable JUNEST_ENV is not properly set"
fi
}
#######################################
# Check if the architecture between Host OS and Guest OS is the same.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home path.
# ARCHITECTURE_MISMATCH (RO) : The arch mismatch exception
# ARCH (RO) : The host OS arch
# JUNEST_ARCH (RO) : The JuNest arch
# Arguments:
# None
# Returns:
# ARCHITECTURE_MISMATCH : If arch between host and guest is not the same
# Output:
# None
#######################################
function check_same_arch() {
source ${JUNEST_HOME}/etc/junest/info
[ "$JUNEST_ARCH" != "$ARCH" ] && \
die_on_status $ARCHITECTURE_MISMATCH "The host system architecture is not correct: $ARCH != $JUNEST_ARCH"
return 0
}
#######################################
# Provide the proot common binding options for both normal user and fakeroot.
# The list of bindings can be found in `proot --help`. This function excludes

View file

@ -46,6 +46,12 @@ function _run_env_with_namespace(){
local backend_args="$1"
shift
check_nested_env
provide_common_bindings
local bindings=${RESULT}
unset RESULT
# Use option -n in groot because umount do not work sometimes.
# As soon as the process terminates, the namespace
# will terminate too with its own mounted directories.
@ -59,7 +65,7 @@ function _run_env_with_namespace(){
#######################################
# Run JuNest as normal user via user namespace.
# Run JuNest as fakeroot user via user namespace.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
@ -70,15 +76,18 @@ function _run_env_with_namespace(){
# cmd ($2-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Depends on the unshare command outcome.
# Output:
# - : The command output.
#######################################
function run_env_as_user_with_namespace() {
function run_env_with_namespace() {
local backend_args="$1"
shift
_check_user_namespace
check_same_arch
copy_common_files
copy_file /etc/hosts.equiv
copy_file /etc/netgroup
@ -87,40 +96,5 @@ function run_env_as_user_with_namespace() {
#copy_file /etc/localtime
copy_passwd_and_group
provide_common_bindings
local bindings=${RESULT}
unset RESULT
# TODO make sure to run the environment as normal user
_run_env_with_namespace "$backend_args" "$@"
}
#######################################
# Run JuNest as fakeroot via user namespace.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# GROOT (RO) : The groot program.
# SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to proot
# cmd ($2-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# Depends on the unshare command outcome.
# Output:
# - : The command output.
#######################################
function run_env_as_fakeroot_with_namespace() {
local backend_args="$1"
shift
_check_user_namespace
copy_common_files
provide_common_bindings
local bindings=${RESULT}
unset RESULT
_run_env_with_namespace "$backend_args" "$@"
}

View file

@ -12,6 +12,7 @@ function _run_env_with_proot(){
local proot_args="$1"
shift
check_nested_env
if [ "$1" != "" ]
then
JUNEST_ENV=1 proot_cmd "${proot_args}" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
@ -58,7 +59,7 @@ function _run_env_with_qemu(){
#######################################
function run_env_as_fakeroot(){
(( EUID == 0 )) && \
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --root option instead."
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead."
local backend_args="$1"
shift
@ -91,7 +92,7 @@ function run_env_as_fakeroot(){
#######################################
function run_env_as_user(){
(( EUID == 0 )) && \
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --root option instead."
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead."
local backend_args="$1"
shift

View file

@ -18,6 +18,7 @@ function oneTimeSetUp(){
function setUp(){
cwdSetUp
junestSetUp
init_mocks
}
function tearDown(){
@ -25,28 +26,42 @@ function tearDown(){
cwdTearDown
}
function test_run_env_as_root_different_arch(){
echo "JUNEST_ARCH=XXX" > ${JUNEST_HOME}/etc/junest/info
assertCommandFailOnStatus 104 run_env_as_root pwd
}
function _test_run_env_as_root() {
function init_mocks() {
chroot_cmd() {
[ "$JUNEST_ENV" != "1" ] && return 1
echo $@
echo "chroot_cmd $@"
}
assertCommandSuccess run_env_as_root $@
GROOT=chroot_cmd
}
function test_run_env_as_root_cmd(){
_test_run_env_as_root pwd
assertEquals "$JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
function test_run_env_as_groot_cmd(){
assertCommandSuccess run_env_as_groot "" pwd
assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
}
function test_run_env_as_classic_root_no_cmd(){
_test_run_env_as_root
assertEquals "$JUNEST_HOME /bin/sh --login -c /bin/sh --login" "$(cat $STDOUTF)"
function test_run_env_as_groot_no_cmd(){
assertCommandSuccess run_env_as_groot ""
assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c /bin/sh --login" "$(cat $STDOUTF)"
}
function test_run_env_as_groot_cmd_with_backend_args(){
assertCommandSuccess run_env_as_groot "-n -b /home/blah" pwd
assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
}
function test_run_env_as_chroot_cmd(){
assertCommandSuccess run_env_as_chroot "" pwd
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
}
function test_run_env_as_chroot_no_cmd(){
assertCommandSuccess run_env_as_chroot ""
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c /bin/sh --login" "$(cat $STDOUTF)"
}
function test_run_env_as_chroot_cmd_with_backend_args(){
assertCommandSuccess run_env_as_chroot "-n -b /home/blah" pwd
assertEquals "chroot_cmd -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
}
source $JUNEST_ROOT/tests/utils/shunit2

View file

@ -20,10 +20,20 @@ function oneTimeTearDown(){
}
function setUp(){
ld_exec() {
ld_exec_mock() {
echo "ld_exec $@"
}
LD_EXEC=ld_exec
ld_exec_mock_false() {
echo "ld_exec $@"
return 1
}
LD_EXEC=ld_exec_mock
unshare_mock() {
echo "unshare $@"
}
UNSHARE=unshare_mock
}
function test_ln(){
@ -117,26 +127,23 @@ function test_zgrep(){
}
function test_unshare(){
UNSHARE=echo assertCommandSuccess unshare_cmd new_program
assertEquals "new_program" "$(cat $STDOUTF)"
assertCommandSuccess unshare_cmd new_program
assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE --user /bin/sh --login -c :\nld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE new_program")" "$(cat $STDOUTF)"
UNSHARE=false assertCommandSuccess unshare_cmd new_program
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false new_program" "$(cat $STDOUTF)"
LD_EXEC=ld_exec_mock_false assertCommandSuccess unshare_cmd new_program
assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/unshare_mock --user /bin/sh --login -c :\nunshare --user /bin/sh --login -c :\nunshare new_program")" "$(cat $STDOUTF)"
UNSHARE=false LD_EXEC=false assertCommandFail unshare_cmd new_program
}
function test_chroot(){
GROOT=echo assertCommandSuccess chroot_cmd root
CLASSIC_CHROOT=echo assertCommandSuccess chroot_cmd root
assertEquals "root" "$(cat $STDOUTF)"
GROOT=false CLASSIC_CHROOT=echo assertCommandSuccess chroot_cmd root
assertEquals "root" "$(cat $STDOUTF)"
GROOT=false CLASSIC_CHROOT=false assertCommandSuccess chroot_cmd root
CLASSIC_CHROOT=false assertCommandSuccess chroot_cmd root
assertEquals "ld_exec $JUNEST_HOME/usr/bin/false root" "$(cat $STDOUTF)"
GROOT=false CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
}
function test_proot_cmd_compat(){
@ -187,11 +194,22 @@ function test_copy_passwd_and_group_failure(){
}
function test_nested_env(){
JUNEST_ENV=1 assertCommandFailOnStatus 106 bash -c "source $JUNEST_ROOT/lib/utils/utils.sh; source $JUNEST_ROOT/lib/core/common.sh"
JUNEST_ENV=1 assertCommandFailOnStatus 106 check_nested_env
}
function test_nested_env_not_set_variable(){
JUNEST_ENV=aaa assertCommandFailOnStatus 107 bash -c "source $JUNEST_ROOT/lib/utils/utils.sh; source $JUNEST_ROOT/lib/core/common.sh"
JUNEST_ENV=aaa assertCommandFailOnStatus 107 check_nested_env
}
function test_check_same_arch_not_same(){
echo "JUNEST_ARCH=XXX" > ${JUNEST_HOME}/etc/junest/info
assertCommandFailOnStatus 104 check_same_arch
}
function test_check_same_arch(){
echo "JUNEST_ARCH=$ARCH" > ${JUNEST_HOME}/etc/junest/info
assertCommandSuccess check_same_arch
}
source $JUNEST_ROOT/tests/utils/shunit2

View file

@ -79,39 +79,39 @@ function test_groot_mountpoint_exist(){
}
MOUNTPOINT=mountpoint_mock
assertCommandSuccess main chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_mountpoint_does_not_exist(){
assertCommandSuccess main chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind(){
assertCommandSuccess main -b /tmp chrootdir
[[ -d chrootdir/tmp ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_file(){
touch file_src
assertCommandSuccess main -b ${PWD}/file_src:/file_src chrootdir
[[ -f chrootdir/file_src ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind ${PWD}/file_src chrootdir/file_src)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind ${PWD}/file_src chrootdir/file_src)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_not_existing_node(){
assertCommandFailOnStatus $NOT_EXISTING_FILE main -b ${PWD}/file_src:/file_src chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_not_absolute_path_node(){
touch file_src
assertCommandFailOnStatus $NOT_ABSOLUTE_PATH main -b file_src:/file_src chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_guest_host(){
assertCommandSuccess main -b /tmp:/home/tmp chrootdir
[[ -d chrootdir/home/tmp ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_multiple_bind(){
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir
@ -119,11 +119,11 @@ function test_groot_with_multiple_bind(){
assertEquals 0 $?
[[ -d chrootdir/dev ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_command(){
assertCommandSuccess main chrootdir ls -la -h
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_and_command(){
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir ls -la -h
@ -131,7 +131,7 @@ function test_groot_with_bind_and_command(){
assertEquals 0 $?
[[ -d chrootdir/dev ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_no_umount(){
assertCommandSuccess main -n chrootdir

View file

@ -26,14 +26,7 @@ function version(){
}
function build_image_env(){
local disable_validation=$1
local skip_root_tests=$2
echo "build_image_env($disable_validation,$skip_root_tests)"
}
function check_env(){
local env_home=$1
local cmd_script=$2
local skip_root_tests=$3
echo "check_env($env_home,$cmd_script,$skip_root_tests)"
echo "build_image_env($disable_validation)"
}
function delete_env(){
echo "delete_env"
@ -49,23 +42,21 @@ function run_env_as_fakeroot(){
shift
echo "run_env_as_fakeroot($backend_args,$@)"
}
function run_env_as_root(){
echo "run_env_as_root $@"
function run_env_as_groot(){
echo "run_env_as_groot $@"
}
function run_env_as_chroot(){
echo "run_env_as_chroot $@"
}
function run_env_as_user(){
local backend_args="$1"
shift
echo "run_env_as_user($backend_args,$@)"
}
function run_env_as_fakeroot_with_namespace(){
function run_env_with_namespace(){
local backend_args="$1"
shift
echo "run_env_as_fakeroot_with_namespace($backend_args,$@)"
}
function run_env_as_user_with_namespace(){
local backend_args="$1"
shift
echo "run_env_as_user_with_namespace($backend_args,$@)"
echo "run_env_with_namespace($backend_args,$@)"
}
function test_help(){
@ -82,27 +73,13 @@ function test_version(){
}
function test_build_image_env(){
assertCommandSuccess main -b
assertEquals "build_image_env(false,false)" "$(cat $STDOUTF)"
assertEquals "build_image_env(false)" "$(cat $STDOUTF)"
assertCommandSuccess main --build-image
assertEquals "build_image_env(false,false)" "$(cat $STDOUTF)"
assertCommandSuccess main -b -s
assertEquals "build_image_env(false,true)" "$(cat $STDOUTF)"
assertEquals "build_image_env(false)" "$(cat $STDOUTF)"
assertCommandSuccess main -b -n
assertEquals "build_image_env(true,false)" "$(cat $STDOUTF)"
assertCommandSuccess main -b -n -s
assertEquals "build_image_env(true,true)" "$(cat $STDOUTF)"
assertCommandSuccess main --build-image --disable-validation --skip-root-tests
assertEquals "build_image_env(true,true)" "$(cat $STDOUTF)"
}
function test_check_env(){
assertCommandSuccess main -c myscript
assertEquals "check_env(${JUNEST_HOME},myscript,false)" "$(cat $STDOUTF)"
assertCommandSuccess main --check myscript
assertEquals "check_env(${JUNEST_HOME},myscript,false)" "$(cat $STDOUTF)"
assertCommandSuccess main -c myscript -s
assertEquals "check_env(${JUNEST_HOME},myscript,true)" "$(cat $STDOUTF)"
assertCommandSuccess main --check myscript --skip-root-tests
assertEquals "check_env(${JUNEST_HOME},myscript,true)" "$(cat $STDOUTF)"
assertEquals "build_image_env(true)" "$(cat $STDOUTF)"
assertCommandSuccess main --build-image --disable-validation
assertEquals "build_image_env(true)" "$(cat $STDOUTF)"
}
function test_delete_env(){
assertCommandSuccess main -d
@ -168,36 +145,31 @@ function test_run_env_as_user(){
assertCommandFail main -a "myarch" -- command -ls
}
function test_run_env_as_root(){
function test_run_env_as_groot(){
assertCommandSuccess main -g
assertEquals "run_env_as_groot " "$(cat $STDOUTF)"
assertCommandSuccess main -g command
assertEquals "run_env_as_groot command" "$(cat $STDOUTF)"
}
function test_run_env_as_chroot(){
assertCommandSuccess main -r
assertEquals "run_env_as_root " "$(cat $STDOUTF)"
assertEquals "run_env_as_chroot " "$(cat $STDOUTF)"
assertCommandSuccess main -r command
assertEquals "run_env_as_root command" "$(cat $STDOUTF)"
assertEquals "run_env_as_chroot command" "$(cat $STDOUTF)"
}
function test_run_env_as_fakeroot_with_namespace(){
function test_run_env_with_namespace(){
assertCommandSuccess main -u -f
assertEquals "run_env_as_fakeroot_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess main --user-namespace --fakeroot
assertEquals "run_env_as_fakeroot_with_namespace(,)" "$(cat $STDOUTF)"
assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess main --namespace --fakeroot
assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -f -p "-b arg"
assertEquals "run_env_as_fakeroot_with_namespace(-b arg,)" "$(cat $STDOUTF)"
assertEquals "run_env_with_namespace(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -f -p "-b arg" -- command -kv
assertEquals "run_env_as_fakeroot_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)"
assertEquals "run_env_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -f command --as
assertEquals "run_env_as_fakeroot_with_namespace(,command --as)" "$(cat $STDOUTF)"
}
function test_run_env_as_user_with_namespace(){
assertCommandSuccess main -u
assertEquals "run_env_as_user_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -p "-b arg"
assertEquals "run_env_as_user_with_namespace(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -p "-b arg" -- command -ll
assertEquals "run_env_as_user_with_namespace(-b arg,command -ll)" "$(cat $STDOUTF)"
assertCommandSuccess main -u command -ls
assertEquals "run_env_as_user_with_namespace(,command -ls)" "$(cat $STDOUTF)"
assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)"
}
function test_check_cli(){

View file

@ -78,64 +78,36 @@ function test_is_user_namespace_enabled_with_config(){
assertCommandSuccess _is_user_namespace_enabled
}
function test_run_env_as_user_with_namespace() {
assertCommandSuccess run_env_as_user_with_namespace "" ""
function test_run_env_with_namespace() {
assertCommandSuccess run_env_with_namespace "" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_user_with_namespace_with_bindings() {
assertCommandSuccess run_env_as_user_with_namespace "-b /usr -b /lib:/tmp/lib" ""
function test_run_env_with_namespace_with_bindings() {
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_user_with_namespace_with_command() {
assertCommandSuccess run_env_as_user_with_namespace "" "ls -la"
function test_run_env_with_namespace_with_command() {
assertCommandSuccess run_env_with_namespace "" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_user_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_as_user_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
function test_run_env_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_fakeroot_with_namespace() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_with_namespace_with_bindings() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "-b /usr -b /lib:/tmp/lib" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_with_namespace_with_command() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
}
source $JUNEST_ROOT/tests/utils/shunit2