diff --git a/README.md b/README.md index a9c7f62..159a1e9 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The main advantages on using JuNest are: - Install packages without root privileges. - Partial isolated environment which you can install packages without affecting a production system. - Access to a wide range of packages in particular on GNU/Linux distros that may contain limited repositories (such as CentOS and RedHat). -- Available for x86\_64, x86 (deprecating) and ARM architectures but you can build your own image from scratch too! +- Available for x86\_64 and ARM architectures but you can build your own image from scratch too! - Run on a different architecture from the host OS via QEMU - All Arch Linux lovers can have their favourite distro everywhere! @@ -63,20 +63,43 @@ any processes belonging to the host OS. Quickstart ========== -The basic way to run JuNest is via the [Proot](https://wiki.archlinux.org/index.php/Proot) as the backend program: -- As normal user - Allow to make basic operations: ```junest``` +Setup environment +----------------- -- As fakeroot - Allow to install/remove packages: ```junest -f``` +The first operation required is to install the JuNest environment in the +location of your choice (by default `~/.junest`, configurable via the environment variable `JUNEST_HOME`): +```sh +junest setup +``` + +The script will download the image from the repository and will place it to the default directory `~/.junest`. + +Access to environment +--------------------- + +By default, JuNest run via the Linux namespaces (aka `ns`) as the backend program. To access via `ns` just type: + +```sh +junest +``` + +Another execution mode is via [Proot](https://wiki.archlinux.org/index.php/Proot): + +```sh +junest proot [-f] +``` + +Where `-f` allow fakeroot access to install/remove packages. + +There are multiple backend programs, each with its own pros/cons. To know more about the JuNest execution modes depending on the backend program used, see the [Usage](#usage) section below. -After running JuNest --------------------- -If the JuNest image has not been downloaded yet, the script will download -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`. + +Have fun! +--------- 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). @@ -106,15 +129,13 @@ Just clone the JuNest repo somewhere (for example in ~/.local/share/junest): export PATH=~/.local/share/junest/bin:$PATH ### 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/): - - yaourt -S junest-git - export PATH=/opt/junest/bin:$PATH +If you are using an Arch Linux system you can, alternatively, install JuNest from the [AUR repository](https://aur.archlinux.org/packages/junest-git/). +After installing junest will be located in `/opt/junest/` ## Method two ## -Alternatively, another installation method would be to directly download the JuNest image and place it to the default directory ~/.junest: +Alternatively, another installation method would be to directly download the JuNest image and place it to the default directory `~/.junest`: - ARCH= + ARCH= mkdir ~/.junest curl https://s3-eu-west-1.amazonaws.com/junest-repo/junest/junest-${ARCH}.tar.gz | tar -xz -C ~/.junest export PATH=~/.junest/opt/junest/bin:$PATH @@ -123,6 +144,27 @@ Usage ===== There are three different ways you can run JuNest depending on the backend program you decide to use. +Linux namespaces based +---------------------- +The [Linux namespaces](http://man7.org/linux/man-pages/man7/namespaces.7.html) +represents the default backend program for JuNest. +The requirements for having Linux namespaces working are: + +1. Kernel starting from Linux 3.8 allows unprivileged processes to create +user and mount namespaces. +1. The Linux kernel distro must have the user namespace enabled. + +In the last years, the majority of GNU/Linux distros have the user namespace +enabled by default. This means that you do not need to have root privileges to +access to the JuNest environment via this method. +This +[wiki](https://github.com/fsquillace/junest/wiki/Linux-distros-with-user-namespace-enabled-by-default) +provides the state of the user namespace on several GNU/Linux distros. + +In order to run JuNest via Linux namespaces: + +- As fakeroot - Allow to install/remove packages: `junest ns` or `junest` + PRoot based ----------- [Proot](https://wiki.archlinux.org/index.php/Proot) represents the default @@ -134,24 +176,9 @@ 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 normal user - Allow to make basic operations: `junest proot` -- As fakeroot - Allow to install/remove packages: ```junest -f``` - -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 12.04+) already has such feature enabled. - -In order to run JuNest via Linux namespaces: - -- As fakeroot - Allow to install/remove packages: ```junest -u``` +- As fakeroot - Allow to install/remove packages: `junest proot -f` Chroot based ------------ @@ -159,16 +186,16 @@ 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 +`/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 `GRoot` - Allow to have fully root privileges inside JuNest environment (you need to be root for executing this): `junest groot` -- As root via `chroot` - Allow to have fully root privileges inside JuNest environment (you need to be root for executing this): ```junest -r``` +- As root via `chroot` - Allow to have fully root privileges inside JuNest environment (you need to be root for executing this): `junest root` Execution modes comparison table ---------------- @@ -185,7 +212,9 @@ Advanced usage ## Build image ## You can build a new JuNest image from scratch by running the following command: - junest -b [-n] +```sh +junest build [-n] +``` The script will create a directory containing all the essentials files in order to make JuNest working properly (such as pacman, yogurt and proot). @@ -194,9 +223,11 @@ Remember that the script to build the image must run in an Arch Linux OS with arch-install-scripts and the base-devel packages installed. To change the build directory just use the `JUNEST_TEMPDIR` (by default /tmp). -After creating the image junest-x86\_64.tar.gz you can install it by running: +After creating the image `junest-x86_64.tar.gz` you can install it by running: - junest -i junest-x86_64.tar.gz +```sh +junest setup -i junest-x86_64.tar.gz +``` For more details, you can also take a look at [junest-builder](https://github.com/fsquillace/junest-builder) @@ -209,20 +240,28 @@ Related wiki page: ## Run JuNest using a different architecture via QEMU ## The following command will download the ARM JuNest image and will run QEMU in -case the host OS runs on either x86\_64 or x86 architectures: +case the host OS runs on either `x86_64` or `x86` architectures: - $> JUNEST_HOME=~/.junest-arm junest -a arm -- uname -m - armv7l +```sh +$> export JUNEST_HOME=~/.junest-arm +$> junest setup -a arm +$> junest -- uname -m +armv7l +``` ## Bind directories ## To bind a host directory to a guest location, you can use proot arguments: - junest -p "-b /mnt/mydata:/home/user/mydata" +```sh +junest proot `-b` "-b /mnt/mydata:/home/user/mydata" +``` -This will works with PRoot, Namespace and GRoot backend programs. +The option `-b` to provide options to the backeng program will work with PRoot, Namespace and GRoot backend programs. Check out the backend program options by passing `--help` option: - junest [-u|-g] -p "--help" +```sh +junest [u|g|p] -b "--help" +``` ## Systemd integration ## Although JuNest has not been designed to be a complete container, it is even possible to @@ -234,7 +273,9 @@ and the container can only be executed using root privileges. To boot a JuNest container: - sudo systemd-nspawn -bD ~/.junest +```sh +sudo systemd-nspawn -bD ~/.junest +``` Related wiki page: @@ -250,7 +291,7 @@ allows unprivileged users to execute programs inside a sandbox and GRoot, a small and portable version of [arch-chroot](https://wiki.archlinux.org/index.php/Chroot) which is an enhanced chroot for privileged users that mounts the primary directories -(i.e. /proc, /sys, /dev and /run) before executing any programs inside +(i.e. `/proc`, `/sys`, `/dev` and `/run`) before executing any programs inside the sandbox. ## Automatic fallback to classic chroot ## @@ -259,14 +300,16 @@ mount one of the directories), JuNest automatically tries to fallback to the classic chroot. ## Automatic fallback for all the dependent host OS executables ## -JuNest attempt first to run the executables in the host OS located in different -positions (/usr/bin, /bin, /usr/sbin and /sbin). +JuNest attempts first to run the executables in the host OS located in different +positions (`/usr/bin`, `/bin`, `/usr/sbin` and `/sbin`). As a fallback it tries to run the same executable if it is available in the JuNest -image. +environment. ## Automatic building of the JuNest images ## There is not periodic automation build of the JuNest images yet. This was due to the difficulty to automate builds for arm architecture. +The JuNest image for the `x86_64` is built periodically every once every three +months. ## Static QEMU binaries ## There are static QEMU binaries included in JuNest image that allows to run JuNest @@ -343,7 +386,7 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht > on to PRoot when *-p* is prepended. For example, to fake a kernel version of > 3.10, issue the following command: - $> junest -p "-k 3.10" + $> junest proot -b "-k 3.10" > As Arch Linux ships binaries for kernel version 2.6.32, the above error is > not unique to the precompiled package from JuNest. It will also appear when @@ -433,7 +476,7 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht > **Q**: Why do I get this warning when I run JuNest via Linux namespaces? - $> junest -u + $> junest ns Unprivileged user namespace is disabled at kernel compile time or kernel too old (<3.8). Proceeding anyway... > **A**: This means that JuNest detected that the host OS either @@ -446,7 +489,7 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht > **Q**: Why do I get this warning when I run JuNest via Linux namespaces? - $> junest -u + $> junest ns Unprivileged user namespace disabled. Root permissions are required to enable it: sudo sysctl kernel.unprivileged_userns_clone=1 > **A**: This means that JuNest detected that the host OS either diff --git a/VERSION b/VERSION index c7d48f0..66ce77b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.10 +7.0.0 diff --git a/bin/junest b/bin/junest index a2b96e5..20a7243 100755 --- a/bin/junest +++ b/bin/junest @@ -13,148 +13,112 @@ source "${JUNEST_BASE}/lib/utils/utils.sh" source "${JUNEST_BASE}/lib/core/common.sh" source "${JUNEST_BASE}/lib/core/build.sh" +source "${JUNEST_BASE}/lib/core/setup.sh" source "${JUNEST_BASE}/lib/core/chroot.sh" source "${JUNEST_BASE}/lib/core/namespace.sh" source "${JUNEST_BASE}/lib/core/proot.sh" -source "${JUNEST_BASE}/lib/core/setup.sh" +# TODO give more flexibility for userns to allow not to copy passwd/grops file, etc +# TODO think about removing yaourt + ################################### ### General functions ### ################################### - usage() { echo -e "$NAME (v$(cat $JUNEST_BASE/VERSION)): $DESCRIPTION" echo - echo -e "Usage: $CMD [options] [--] [command]" + echo -e "Usage: $CMD [action] [options] [--] [command]" echo - echo -e "Setup options:" - echo -e "-i, --setup-from-file Setup the $NAME image in ${JUNEST_HOME}" - echo -e "-a, --arch $NAME architecture to download (x86_64, x86, arm)" - echo -e " Defaults to the host architecture ($ARCH)" - echo -e "-d, --delete Delete $NAME from ${JUNEST_HOME}" + echo -e "General:" + echo -e "-h, --help Show this help message" + echo -e "-V, --version Show the $NAME version" echo - echo -e "Access options:" - echo -e "-f, --fakeroot Run $NAME with fakeroot privileges" - 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 Arguments for backend program (PRoot or GRoot)" - echo -e " ($CMD -p \"--help\" to check out the PRoot options" - 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 -e "Actions and options:" + echo -e " [s]etup " + echo -e " -i, --from-file Setup the $NAME image in ${JUNEST_HOME}" + echo -e " -a, --arch $NAME architecture to download (x86_64, arm)" + echo -e " Defaults to the host architecture ($ARCH)" + echo -e " -d, --delete Delete $NAME from ${JUNEST_HOME}" 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 " [n]s Access via Linux Namespaces using GRoot (Default action)" + echo -e " -b, --backend-args Arguments for GRoot backend program" + echo -e " ($CMD groot -p \"--help\" to check out the GRoot options)" echo - echo -e "General options:" - echo -e "-h, --help Show this help message" - echo -e "-V, --version Show the $NAME version" + echo -e " [p]root Access via PRoot" + echo -e " -f, --fakeroot Run $NAME with fakeroot privileges" + echo -e " -b, --backend-args Arguments for PRoot backend program" + echo -e " ($CMD proot -p \"--help\" to check out the PRoot options)" + echo + echo -e " [g]root Access with root privileges via GRoot" + echo -e " -b, --backend-args Arguments for GRoot backend program" + echo -e " ($CMD groot -p \"--help\" to check out the GRoot options)" + echo + echo -e " [r]oot Access with root privileges via classic chroot" + echo -e " -b, --backend-args Arguments for chroot backend program" + echo -e " ($CMD root -p \"--help\" to check out the chroot options)" + echo + echo -e " [b]uild Build a $NAME image (must run in ArchLinux)" + echo -e " -n, --disable-validation Disable the $NAME image validation" } version() { echo -e "$NAME $(cat $JUNEST_BASE/VERSION)" } -check_cli(){ - if $OPT_BUILD_IMAGE - then - if $OPT_DELETE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \ - $OPT_FAKEROOT || $OPT_ROOT - then - 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 - then - die "The disable validation option must be used with the build image option only" - fi - fi - if $OPT_DELETE - then - if $OPT_BUILD_IMAGE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \ - $OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION - then - die "The $NAME delete option must be used exclusively" - fi - fi - if $OPT_HELP - then - if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \ - $OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION - then - die "The $NAME help option must be used exclusively" - fi - fi - if $OPT_VERSION - then - if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \ - $OPT_FAKEROOT || $OPT_ROOT || $OPT_DISABLE_VALIDATION - then - die "The $NAME version option must be used exclusively" - fi - fi - if $OPT_FAKEROOT && $OPT_ROOT - then - die "You must access to $NAME with either fakeroot or root permissions" - fi - if $OPT_BACKEND_ARGS || $OPT_ARCH - then - if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || \ - $OPT_ROOT || $OPT_VERSION || $OPT_DISABLE_VALIDATION - then - die "Invalid syntax: Proot and arch args are not allowed with the other options" - fi - fi - if [ "$ARGS" != "" ] - then - if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \ - $OPT_VERSION || $OPT_DISABLE_VALIDATION - then - die "No arguments are needed. For the CLI syntax run: $CMD --help" - fi - fi +function parse_arguments(){ + # Actions + ACT_SETUP=false + ACT_BUILD=false + ACT_NAMESPACE=false + ACT_PROOT=false + ACT_GROOT=false + ACT_ROOT=false + ACT_HELP=false + ACT_VERSION=false - return 0 + case "$1" in + s|setup) ACT_SETUP=true ; shift ;; + b|build) ACT_BUILD=true ; shift ;; + n|ns) ACT_NAMESPACE=true ; shift ;; + p|proot) ACT_PROOT=true ; shift ;; + g|groot) ACT_GROOT=true ; shift ;; + r|root) ACT_ROOT=true ; shift ;; + -h|--help) ACT_HELP=true ; shift ;; + -V|--version) ACT_VERSION=true ; shift ;; + *) ACT_NAMESPACE=true ;; + esac + + if $ACT_SETUP + then + _parse_setup_opts "$@" + elif $ACT_BUILD + then + _parse_build_opts "$@" + elif $ACT_NAMESPACE + then + _parse_general_opts "$@" + elif $ACT_PROOT + then + _parse_proot_opts "$@" + elif $ACT_GROOT + then + _parse_general_opts "$@" + elif $ACT_ROOT + then + _parse_general_opts "$@" + fi } - -function parse_arguments(){ - OPT_SETUP_FROM_FILE=false - IMAGE_FILE="" - OPT_FAKEROOT=false - OPT_ROOT=false - OPT_GROOT=false - OPT_USER_NAMESPACE=false +function _parse_general_opts() { + # Options: OPT_BACKEND_ARGS=false BACKEND_ARGS="" - OPT_ARCH=false - ARCH_ARG="" - OPT_BUILD_IMAGE=false - OPT_DISABLE_VALIDATION=false - CHECK_ARG="" - OPT_DELETE=false - OPT_HELP=false - OPT_VERSION=false - for opt in "$@" + + while [[ -n "$1" ]] do case "$1" in - -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 ;; - -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 ;; - -d|--delete) OPT_DELETE=true ; shift ;; - -h|--help) OPT_HELP=true ; shift ;; - -V|--version) OPT_VERSION=true ; shift ;; --) shift ; break ;; -*) die "Invalid option $1" ;; *) break ;; @@ -168,44 +132,105 @@ function parse_arguments(){ done } -function execute_operation(){ - $OPT_HELP && usage && return - $OPT_VERSION && version && return +function _parse_proot_opts() { + # Options: + OPT_FAKEROOT=false + OPT_BACKEND_ARGS=false + BACKEND_ARGS="" - if $OPT_BUILD_IMAGE; then + while [[ -n "$1" ]] + do + case "$1" in + -f|--fakeroot) OPT_FAKEROOT=true ; shift ;; + -p|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;; + --) shift ; break ;; + -*) die "Invalid option $1" ;; + *) break ;; + esac + done + + ARGS=() + for arg in "$@" + do + ARGS+=("$arg") + done +} + +function _parse_build_opts() { + OPT_DISABLE_VALIDATION=false + while [[ -n "$1" ]] + do + case "$1" in + -n|--disable-validation) OPT_DISABLE_VALIDATION=true ; shift ;; + *) die "Invalid option $1" ;; + esac + done +} + +function _parse_setup_opts() { + OPT_SETUP_FROM_FILE=false + IMAGE_FILE="" + OPT_ARCH=false + ARCH_ARG="" + OPT_DELETE=false + while [[ -n "$1" ]] + do + case "$1" in + -i|--from-file) OPT_SETUP_FROM_FILE=true ; shift ; IMAGE_FILE=$1 ; shift ;; + -a|--arch) OPT_ARCH=true ; shift ; ARCH_ARG=$1; shift ;; + -d|--delete) OPT_DELETE=true ; shift ;; + *) die "Invalid option $1" ;; + esac + done +} + +function execute_operation() { + $ACT_HELP && usage && return + $ACT_VERSION && version && return + + if $ACT_BUILD; then build_image_env $OPT_DISABLE_VALIDATION return - elif $OPT_DELETE; then - delete_env - return + fi + + if $ACT_SETUP; then + if $OPT_DELETE; then + delete_env + else + if is_env_installed + then + die "Error: The image cannot be installed since $JUNEST_HOME is not empty." + fi + + if $OPT_SETUP_FROM_FILE; then + setup_env_from_file $IMAGE_FILE + else + setup_env $ARCH_ARG + fi + fi + + return fi + if ! is_env_installed then - if $OPT_SETUP_FROM_FILE; then - setup_env_from_file $IMAGE_FILE - else - setup_env $ARCH_ARG - unset ARCH_ARG - fi - elif $OPT_SETUP_FROM_FILE; then - die "Error: The image cannot be installed since $JUNEST_HOME is not empty." + die "Error: The image is still not installed in $JUNEST_HOME. Run this first: $CMD setup" fi - [ -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 $ACT_NAMESPACE; then 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 + elif $ACT_PROOT; then + if $OPT_FAKEROOT; then + run_env=run_env_as_fakeroot + else + run_env=run_env_as_user + fi + elif $ACT_GROOT; then run_env=run_env_as_groot - else - run_env=run_env_as_user + elif $ACT_ROOT; then + run_env=run_env_as_chroot fi $run_env "${BACKEND_ARGS}" "${ARGS[@]}" @@ -214,7 +239,6 @@ function execute_operation(){ function main() { parse_arguments "$@" - check_cli execute_operation } diff --git a/tests/unit-tests/test-junest.sh b/tests/unit-tests/test-junest.sh index 2176cea..a3dee83 100755 --- a/tests/unit-tests/test-junest.sh +++ b/tests/unit-tests/test-junest.sh @@ -72,118 +72,169 @@ function test_version(){ assertEquals "version" "$(cat $STDOUTF)" } function test_build_image_env(){ - assertCommandSuccess main -b + assertCommandSuccess main b assertEquals "build_image_env(false)" "$(cat $STDOUTF)" - assertCommandSuccess main --build-image + assertCommandSuccess main build assertEquals "build_image_env(false)" "$(cat $STDOUTF)" - assertCommandSuccess main -b -n + assertCommandSuccess main b -n assertEquals "build_image_env(true)" "$(cat $STDOUTF)" - assertCommandSuccess main --build-image --disable-validation + assertCommandSuccess main build --disable-validation assertEquals "build_image_env(true)" "$(cat $STDOUTF)" } + function test_delete_env(){ - assertCommandSuccess main -d + assertCommandSuccess main s -d assertEquals "delete_env" "$(cat $STDOUTF)" - assertCommandSuccess main --delete + assertCommandSuccess main setup --delete assertEquals "delete_env" "$(cat $STDOUTF)" } function test_setup_env_from_file(){ is_env_installed(){ return 1 } - assertCommandSuccess main -i myimage - assertEquals "$(echo -e "setup_env_from_file(myimage)\nrun_env_as_user(,)")" "$(cat $STDOUTF)" - assertCommandSuccess main --setup-from-file myimage - assertEquals "$(echo -e "setup_env_from_file(myimage)\nrun_env_as_user(,)")" "$(cat $STDOUTF)" + assertCommandSuccess main s -i myimage + assertEquals "setup_env_from_file(myimage)" "$(cat $STDOUTF)" + assertCommandSuccess main setup --from-file myimage + assertEquals "setup_env_from_file(myimage)" "$(cat $STDOUTF)" is_env_installed(){ return 0 } - assertCommandFail main -i myimage + assertCommandFail main setup -i myimage } function test_setup_env(){ is_env_installed(){ return 1 } - assertCommandSuccess main -a arm - assertEquals "$(echo -e "setup_env(arm)\nrun_env_as_user(,)")" "$(cat $STDOUTF)" - assertCommandSuccess main --arch arm - assertEquals "$(echo -e "setup_env(arm)\nrun_env_as_user(,)")" "$(cat $STDOUTF)" - assertCommandSuccess main - assertEquals "$(echo -e "setup_env()\nrun_env_as_user(,)")" "$(cat $STDOUTF)" + assertCommandSuccess main s + assertEquals "setup_env()" "$(cat $STDOUTF)" + assertCommandSuccess main setup + assertEquals "setup_env()" "$(cat $STDOUTF)" + assertCommandSuccess main s -a arm + assertEquals "setup_env(arm)" "$(cat $STDOUTF)" + assertCommandSuccess main setup --arch arm + assertEquals "setup_env(arm)" "$(cat $STDOUTF)" is_env_installed(){ return 0 } - assertCommandFail main -a arm + assertCommandFail main setup -a arm } + function test_run_env_as_fakeroot(){ - assertCommandSuccess main -f + assertCommandSuccess main p -f assertEquals "run_env_as_fakeroot(,)" "$(cat $STDOUTF)" - assertCommandSuccess main --fakeroot + assertCommandSuccess main proot --fakeroot assertEquals "run_env_as_fakeroot(,)" "$(cat $STDOUTF)" - assertCommandSuccess main -f -p "-b arg" + assertCommandSuccess main proot -f -p "-b arg" assertEquals "run_env_as_fakeroot(-b arg,)" "$(cat $STDOUTF)" - assertCommandSuccess main -f -p "-b arg" -- command -kv + assertCommandSuccess main proot -f -p "-b arg" -- command -kv assertEquals "run_env_as_fakeroot(-b arg,command -kv)" "$(cat $STDOUTF)" - assertCommandSuccess main -f command --as + assertCommandSuccess main proot -f command --as assertEquals "run_env_as_fakeroot(,command --as)" "$(cat $STDOUTF)" - assertCommandFail main -a "myarch" -f command --as + assertCommandSuccess main proot -f -- command --as + assertEquals "run_env_as_fakeroot(,command --as)" "$(cat $STDOUTF)" + + is_env_installed(){ + return 1 + } + assertCommandFail main proot -f } + function test_run_env_as_user(){ - assertCommandSuccess main + assertCommandSuccess main proot assertEquals "run_env_as_user(,)" "$(cat $STDOUTF)" - assertCommandSuccess main -p "-b arg" + assertCommandSuccess main proot -p "-b arg" assertEquals "run_env_as_user(-b arg,)" "$(cat $STDOUTF)" - assertCommandSuccess main -p "-b arg" -- command -ll + assertCommandSuccess main proot -p "-b arg" -- command -ll assertEquals "run_env_as_user(-b arg,command -ll)" "$(cat $STDOUTF)" - assertCommandSuccess main command -ls + assertCommandSuccess main proot command -ls + assertEquals "run_env_as_user(,command -ls)" "$(cat $STDOUTF)" + assertCommandSuccess main proot -- command -ls assertEquals "run_env_as_user(,command -ls)" "$(cat $STDOUTF)" - assertCommandFail main -a "myarch" -- command -ls + is_env_installed(){ + return 1 + } + assertCommandFail main proot } + function test_run_env_as_groot(){ - assertCommandSuccess main -g + assertCommandSuccess main g assertEquals "run_env_as_groot " "$(cat $STDOUTF)" - assertCommandSuccess main -g command + assertCommandSuccess main groot command assertEquals "run_env_as_groot command" "$(cat $STDOUTF)" + assertCommandSuccess main groot -- command + assertEquals "run_env_as_groot command" "$(cat $STDOUTF)" + + is_env_installed(){ + return 1 + } + assertCommandFail main groot } + function test_run_env_as_chroot(){ - assertCommandSuccess main -r + assertCommandSuccess main r assertEquals "run_env_as_chroot " "$(cat $STDOUTF)" - assertCommandSuccess main -r command + assertCommandSuccess main root command assertEquals "run_env_as_chroot command" "$(cat $STDOUTF)" + assertCommandSuccess main root -- command + assertEquals "run_env_as_chroot command" "$(cat $STDOUTF)" + + is_env_installed(){ + return 1 + } + assertCommandFail main root -f } function test_run_env_with_namespace(){ - assertCommandSuccess main -u -f + assertCommandSuccess main n assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)" - assertCommandSuccess main --namespace --fakeroot + assertCommandSuccess main ns assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)" - assertCommandSuccess main -u -f -p "-b arg" + assertCommandSuccess main ns -p "-b arg" assertEquals "run_env_with_namespace(-b arg,)" "$(cat $STDOUTF)" - assertCommandSuccess main -u -f -p "-b arg" -- command -kv + assertCommandSuccess main ns -p "-b arg" -- command -kv assertEquals "run_env_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)" - assertCommandSuccess main -u -f command --as + assertCommandSuccess main ns command --as assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)" + assertCommandSuccess main ns -- command --as + assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)" + + assertCommandSuccess main + assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)" + assertCommandSuccess main + assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)" + + assertCommandSuccess main -p "-b arg" + assertEquals "run_env_with_namespace(-b arg,)" "$(cat $STDOUTF)" + assertCommandSuccess main -p "-b arg" -- command -kv + assertEquals "run_env_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)" + assertCommandSuccess main command --as + assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)" + assertCommandSuccess main -- command --as + assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)" + + is_env_installed(){ + return 1 + } + assertCommandFail main ns } -function test_check_cli(){ - assertCommandFail main -b -h - assertCommandFail main -b -c - assertCommandFail main -d -s - assertCommandFail main -n -v - assertCommandFail main -d -r - assertCommandFail main -h -f - assertCommandFail main -v -i fsd - assertCommandFail main -f -r - assertCommandFail main -p args -v - assertCommandFail main -a arch -v - assertCommandFail main -d args +function test_invalid_option(){ + assertCommandFail main --no-option + assertCommandFail main n --no-option + assertCommandFail main g --no-option + assertCommandFail main r --no-option + + assertCommandFail main p --no-option + + assertCommandFail main b --no-option + assertCommandFail main s --no-option } source $(dirname $0)/../utils/shunit2