Merge pull request #231 from fsquillace/new-junest

New junest
This commit is contained in:
Filippo Squillace 2019-10-22 22:27:52 +02:00 committed by GitHub
commit 97d19da268
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 663 additions and 368 deletions

View file

@ -10,8 +10,10 @@ before_install:
install:
- PATH=$PWD/bin:$PATH
- junest setup
- junest -- echo "Installing JuNest (\$(uname -m))"
- JUNEST_HOME=~/.junest-arm junest -a arm -- echo "Installing JuNest (\$(uname -m))"
- JUNEST_HOME=~/.junest-arm junest setup --arch arm
- JUNEST_HOME=~/.junest-arm junest proot --fakeroot -- echo "Installing JuNest (\$(uname -m))"
script:
- bash --version
@ -19,12 +21,11 @@ script:
- bash ./tests/unit-tests/unit-tests.sh
# Multiple tests against different execution modes:
# TODO AUR installation check is currently disabled
- junest -f -- ${PWD}/lib/checks/check.sh
- junest -u -- ${PWD}/lib/checks/check.sh
- sudo -E ${PWD}/bin/junest -g -- ${PWD}/lib/checks/check.sh
- yes | junest --delete
- junest proot --fakeroot -- ${PWD}/lib/checks/check.sh
- junest ns -- ${PWD}/lib/checks/check.sh
- sudo -E ${PWD}/bin/junest groot -- ${PWD}/lib/checks/check.sh --run-root-tests
- yes | junest setup --delete
# Disable arm because it fails when exiting from check.sh for apparent no reason
#- JUNEST_HOME=~/.junest-arm junest -f -- ./lib/checks/check.sh --skip-aur-tests
#- yes | JUNEST_HOME=~/.junest-arm junest --delete
#- JUNEST_HOME=~/.junest-arm junest proot -f -- ./lib/checks/check.sh --skip-aur-tests
#- yes | JUNEST_HOME=~/.junest-arm junest setup --delete

193
README.md
View file

@ -11,7 +11,7 @@ The lightweight Arch Linux based distro that runs upon any Linux distros without
|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/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) |
| [![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) | [![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) [![RSS](https://img.shields.io/badge/RSS-News-orange.svg)](http://fsquillace.github.io/junest-site/feed.xml) |
**Table of Contents**
- [Description](#description)
@ -23,7 +23,7 @@ The lightweight Arch Linux based distro that runs upon any Linux distros without
- [Troubleshooting](#troubleshooting)
- [More documentation](#more-documentation)
- [Contributing](#contributing)
- [Author](#author)
- [Authors](#authors)
Description
===========
@ -32,7 +32,7 @@ an isolated GNU/Linux environment inside any generic host GNU/Linux OS
and without the need to have root privileges for installing packages.
JuNest contains mainly the package managers (called [pacman](https://wiki.archlinux.org/index.php/Pacman)
and a simple [yaourt](https://wiki.archlinux.org/index.php/Yaourt) wrapper called yogurt) that allows to access
that allows to access
to a wide range of packages from the Arch Linux repositories.
The main advantages on using JuNest are:
@ -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,24 +63,56 @@ 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).
JuNest provides a modified version of `makepkg` in `/opt/makepkg/bin` that
allows you to build packages from [AUR](https://aur.archlinux.org/) repository.
Remember that in order to build packages, `base-devel` package group is required
first:
```sh
pacman -Sy --ignore sudo base-devel
```
Installation
============
@ -92,8 +124,8 @@ Before installing JuNest be sure that all dependencies are properly installed in
- [bash (>=4.0)](https://www.gnu.org/software/bash/)
- [GNU coreutils](https://www.gnu.org/software/coreutils/)
The minimum recommended Linux kernel of the host OS is 2.6.32 on x86 (32-bit
and 64 bit) and ARM architectures. It is still possible to run JuNest on lower
The minimum recommended Linux kernel of the host OS is 2.6.32 on x86 (64 bit)
and ARM architectures. It is still possible to run JuNest on lower
2.6.x host OS kernels but errors may appear, and some applications may
crash. For further information, read the [Troubleshooting](#troubleshooting)
section below.
@ -106,15 +138,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=<one of "x86_64", "x86", "arm">
ARCH=<one of "x86_64", "arm">
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,52 +153,56 @@ 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
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.
[Proot](https://wiki.archlinux.org/index.php/Proot) 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 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
------------
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
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 `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
----------------
@ -176,8 +210,8 @@ The following table shows the capabilities that each backend program is able to
| | QEMU | Root privileges required | Manage Official Packages | Manage AUR Packages | Portability | Support | User modes |
| --- | ---- | ------------------------ | ------------------------ | ------------------- | ----------- | ------- | ---------- |
| **Proot** | YES | NO | YES | YES | YES | Poor | Normal user and `fakeroot` |
| **Linux Namespaces** | NO | NO | YES | YES | Poor | YES | `fakeroot` only |
| **Proot** | YES | NO | YES | YES | YES | Poor | Normal user and `fakeroot` |
| **Chroot** | NO | YES | YES | YES | YES | YES | `root` only |
Advanced usage
@ -185,18 +219,22 @@ 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).
files in order to make JuNest working properly (such as `pacman` and `proot`).
The option `-n` will skip the final validation tests if they are not needed.
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 +247,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 `x86_64` architecture:
$> JUNEST_HOME=~/.junest-arm junest -a arm -- uname -m
armv7l
```sh
$> export JUNEST_HOME=~/.junest-arm
$> junest setup -a arm
$> junest proot -- 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 +280,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 +298,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 +307,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
@ -280,12 +330,12 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht
## Cannot use AUR repository ##
> **Q**: Why do I get the following error when I try to install a package with yogurt?
> **Q**: Why do I get the following error when I try to install a package?
Cannot find the gzip binary required for compressing man and info pages.
> **A**: JuNest comes with a very basic number of packages.
> In order to install AUR packages via yogurt you need to install the package group `base-devel` first
> In order to install AUR packages you need to install the package group `base-devel` first
> that contains all the essential packages for compiling from source code (such as gcc, make, patch, etc):
#> pacman -S --ignore sudo base-devel
@ -343,7 +393,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 +483,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 +496,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
@ -462,13 +512,16 @@ There are additional tutorials in the
Contributing
============
You could help improving JuNest in the following ways:
Contributions are welcome! You could help improving JuNest in the following ways:
- [Reporting Bugs](CONTRIBUTING.md#reporting-bugs)
- [Suggesting Enhancements](CONTRIBUTING.md#suggesting-enhancements)
- [Writing Code](CONTRIBUTING.md#your-first-code-contribution)
Author
======
Filippo Squillace <feel.sqoox@gmail.com>
Authors
=======
JuNest was originally created in late 2014 by [Filippo Squillace (feel.sqoox@gmail.com)](https://github.com/fsquillace).
Here is a list of [**really appreciated contributors**](https://github.com/fsquillace/junest/graphs/contributors)!
[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/0)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/0)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/1)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/1)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/2)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/2)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/3)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/3)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/4)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/4)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/5)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/5)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/6)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/6)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/7)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/7)

View file

@ -1 +1 @@
6.0.10
7.0.0

View file

@ -13,148 +13,116 @@ 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"
###################################
### 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 <image> Setup the $NAME image in ${JUNEST_HOME}"
echo -e "-a, --arch <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 <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] Setup $NAME in ${JUNEST_HOME} either from repo or from file"
echo -e " -i, --from-file <image> Setup the $NAME image in ${JUNEST_HOME}"
echo -e " -a, --arch <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 <args> Arguments for GRoot backend program"
echo -e " ($CMD groot -p \"--help\" to check out the GRoot options)"
echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment"
echo
echo -e " p[root] Access via PRoot"
echo -e " -f, --fakeroot Run $NAME with fakeroot privileges"
echo -e " -b, --backend-args <args> Arguments for PRoot backend program"
echo -e " ($CMD proot -p \"--help\" to check out the PRoot options)"
echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment"
echo
echo -e " g[root] Access with root privileges via GRoot"
echo -e " -b, --backend-args <args> Arguments for GRoot backend program"
echo -e " ($CMD groot -p \"--help\" to check out the GRoot options)"
echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment"
echo
echo -e " r[oot] Access with root privileges via classic chroot"
echo -e " -b, --backend-args <args> Arguments for chroot backend program"
echo -e " ($CMD root -p \"--help\" to check out the chroot options)"
echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment"
echo
echo -e " b[uild] Build a $NAME image (must run in ArchLinux)"
echo -e " -n, --disable-check Disable the $NAME image check"
echo
echo -e "General options:"
echo -e "-h, --help Show this help message"
echo -e "-V, --version Show the $NAME version"
}
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_ns_opts "$@"
elif $ACT_PROOT
then
_parse_proot_opts "$@"
elif $ACT_GROOT
then
_parse_root_opts "$@"
elif $ACT_ROOT
then
_parse_root_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_root_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 "$@"
OPT_NO_COPY_FILES=false
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 ;;
-b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;;
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
--) shift ; break ;;
-*) die "Invalid option $1" ;;
*) break ;;
@ -168,53 +136,139 @@ function parse_arguments(){
done
}
function execute_operation(){
$OPT_HELP && usage && return
$OPT_VERSION && version && return
function _parse_ns_opts() {
# Options:
OPT_BACKEND_ARGS=false
BACKEND_ARGS=""
OPT_NO_COPY_FILES=false
if $OPT_BUILD_IMAGE; then
build_image_env $OPT_DISABLE_VALIDATION
return
elif $OPT_DELETE; then
delete_env
while [[ -n "$1" ]]
do
case "$1" in
-b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;;
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
--) shift ; break ;;
-*) die "Invalid option $1" ;;
*) break ;;
esac
done
ARGS=()
for arg in "$@"
do
ARGS+=("$arg")
done
}
function _parse_proot_opts() {
# Options:
OPT_FAKEROOT=false
OPT_BACKEND_ARGS=false
BACKEND_ARGS=""
OPT_NO_COPY_FILES=false
while [[ -n "$1" ]]
do
case "$1" in
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
-b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;;
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
--) shift ; break ;;
-*) die "Invalid option $1" ;;
*) break ;;
esac
done
ARGS=()
for arg in "$@"
do
ARGS+=("$arg")
done
}
function _parse_build_opts() {
OPT_DISABLE_CHECK=false
while [[ -n "$1" ]]
do
case "$1" in
-n|--disable-check) OPT_DISABLE_CHECK=true ; shift ;;
*) die "Invalid option $1" ;;
esac
done
}
function _parse_setup_opts() {
OPT_FROM_FILE=false
IMAGE_FILE=""
OPT_ARCH=false
ARCH_ARG=""
OPT_DELETE=false
while [[ -n "$1" ]]
do
case "$1" in
-i|--from-file) OPT_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_CHECK
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_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[@]}"
$run_env "${BACKEND_ARGS}" $OPT_NO_COPY_FILES "${ARGS[@]}"
}
function main() {
parse_arguments "$@"
check_cli
execute_operation
}

View file

@ -52,7 +52,7 @@ pacman --noconfirm -S $(pacman -Sg base-devel | cut -d ' ' -f 2 | grep -v sudo)
info "Checking basic executables work..."
pacman -Qi pacman 1> /dev/null
yogurt -V 1> /dev/null
/opt/makepkg/bin/makepkg --help 1> /dev/null
/opt/proot/proot-$ARCH --help 1> /dev/null
repo_package1=tree
@ -71,7 +71,13 @@ if ! $SKIP_AUR_TESTS
then
aur_package=aurutils
info "Checking ${aur_package} package from AUR repo..."
yogurt -A --noconfirm -S ${aur_package}
maindir=$(mktemp -d -t ${CMD}.XXXXXXXXXX)
builtin cd ${maindir}
curl -L -J -O -k "https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=${aur_package}"
curl -L -J -O -k "https://aur.archlinux.org/cgit/aur.git/plain/${aur_package}.install?h=${aur_package}"
/opt/makepkg/bin/makepkg -sfcd
pacman --noconfirm -U ${aur_package}*.pkg.tar.xz
aur search aur 1> /dev/null
pacman --noconfirm -Rsn ${aur_package}
fi

View file

@ -54,30 +54,26 @@ function build_image_env(){
info "Installing pacman and its dependencies..."
# The archlinux-keyring and libunistring are due to missing dependencies declaration in ARM archlinux
# All the essential executables (ln, mkdir, chown, etc) are in coreutils
# yaourt requires sed
# localedef (called by locale-gen) requires gzip
# unshare command belongs to util-linux
sudo pacstrap -G -M -d ${maindir}/root pacman coreutils libunistring archlinux-keyring sed gzip util-linux
sudo pacstrap -G -M -d ${maindir}/root pacman coreutils libunistring archlinux-keyring util-linux
sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist"
sudo mkdir -p ${maindir}/root/run/lock
# AUR packages requires non-root user to be compiled. proot fakes the user to 10
info "Compiling and installing yaourt..."
_install_pkg_from_aur ${maindir} "package-query"
_install_pkg_from_aur ${maindir} "yaourt"
_install_pkg ${maindir} "$JUNEST_BASE/pkgs/sudo-fake"
info "Install ${NAME} script..."
sudo pacman --noconfirm --root ${maindir}/root -S git
_install_pkg_from_aur ${maindir} "${CMD}-git" "${CMD}.install"
sudo pacman --noconfirm --root ${maindir}/root -Rsn git
info "Generating the locales..."
# sed command is required for locale-gen
# localedef (called by locale-gen) requires gzip
sudo pacman --noconfirm --root ${maindir}/root -S sed gzip
sudo ln -sf /usr/share/zoneinfo/posix/UTC ${maindir}/root/etc/localtime
sudo bash -c "echo 'en_US.UTF-8 UTF-8' >> ${maindir}/root/etc/locale.gen"
sudo ${maindir}/root/opt/junest/bin/groot ${maindir}/root locale-gen
sudo bash -c "echo LANG=\"en_US.UTF-8\" >> ${maindir}/root/etc/locale.conf"
sudo pacman --noconfirm --root ${maindir}/root -Rsn sed gzip
info "Setting up the pacman keyring (this might take a while!)..."
sudo ${maindir}/root/opt/junest/bin/groot -b /dev ${maindir}/root bash -c \
@ -95,8 +91,9 @@ function build_image_env(){
then
mkdir -p ${maindir}/root_test
$TAR -zxpf ${imagefile} -C "${maindir}/root_test"
JUNEST_HOME="${maindir}/root_test" ${maindir}/root_test/opt/${CMD}/bin/${CMD} -f ${JUNEST_BASE}/lib/checks/check.sh
JUNEST_HOME="${maindir}/root_test" sudo -E ${maindir}/root_test/opt/${CMD}/bin/${CMD} -g ${JUNEST_BASE}/lib/checks/check.sh --run-root-tests
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} proot -f ${JUNEST_BASE}/lib/checks/check.sh
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} ns ${JUNEST_BASE}/lib/checks/check.sh
JUNEST_HOME="${maindir}/root_test" sudo -E ${JUNEST_BASE}/bin/${CMD} groot ${JUNEST_BASE}/lib/checks/check.sh --run-root-tests
fi
sudo cp ${maindir}/output/${imagefile} ${ORIGIN_WD}

View file

@ -11,7 +11,8 @@
function _run_env_as_xroot(){
local cmd=$1
local backend_args="$2"
shift 2
local no_copy_files="$3"
shift 3
check_same_arch
@ -26,7 +27,10 @@ function _run_env_as_xroot(){
trap - QUIT EXIT ABRT KILL TERM INT
trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT KILL TERM INT
copy_common_files
if ! $no_copy_files
then
copy_common_files
fi
JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "${main_cmd}"
}
@ -41,8 +45,10 @@ function _run_env_as_xroot(){
# 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.
# backend_args ($1) : The arguments to pass to backend program
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
@ -53,13 +59,14 @@ function run_env_as_groot(){
check_nested_env
local backend_args="$1"
shift
local no_copy_files="$2"
shift 2
provide_common_bindings
local bindings=${RESULT}
unset RESULT
_run_env_as_xroot "$GROOT $bindings" "$backend_args" "$@"
_run_env_as_xroot "$GROOT $bindings" "$backend_args" "$no_copy_files" "$@"
}
#######################################
@ -72,8 +79,10 @@ function run_env_as_groot(){
# 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.
# backend_args ($1) : The arguments to pass to backend program
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
@ -84,7 +93,8 @@ function run_env_as_chroot(){
check_nested_env
local backend_args="$1"
shift
local no_copy_files="$2"
shift 2
_run_env_as_xroot chroot_cmd "$backend_args" "$@"
_run_env_as_xroot chroot_cmd "$backend_args" "$no_copy_files" "$@"
}

View file

@ -84,8 +84,10 @@ function _run_env_with_namespace(){
# 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.
# backend_args ($1) : The arguments to pass to groot
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
@ -97,18 +99,23 @@ function run_env_with_namespace() {
check_nested_env
local backend_args="$1"
shift
local no_copy_files="$2"
shift 2
_check_user_namespace
check_same_arch
copy_common_files
copy_file /etc/hosts.equiv
copy_file /etc/netgroup
copy_file /etc/networks
# No need for localtime as it is setup during the image build
#copy_file /etc/localtime
copy_passwd_and_group
if ! $no_copy_files
then
copy_common_files
copy_file /etc/hosts.equiv
copy_file /etc/netgroup
copy_file /etc/networks
# No need for localtime as it is setup during the image build
#copy_file /etc/localtime
copy_passwd_and_group
fi
_run_env_with_namespace "$backend_args" "$@"
}

View file

@ -49,7 +49,9 @@ function _run_env_with_qemu(){
# 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.
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ROOT_ACCESS_ERROR : If the user is the real root.
@ -62,9 +64,13 @@ function run_env_as_fakeroot(){
check_nested_env
local backend_args="$1"
shift
local no_copy_files="$2"
shift 2
copy_common_files
if ! $no_copy_files
then
copy_common_files
fi
provide_common_bindings
local bindings=${RESULT}
@ -84,7 +90,9 @@ function run_env_as_fakeroot(){
# 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.
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ROOT_ACCESS_ERROR : If the user is the real root.
@ -97,19 +105,23 @@ function run_env_as_user(){
check_nested_env
local backend_args="$1"
shift
local no_copy_files="$2"
shift 2
# Files to bind are visible in `proot --help`.
# This function excludes /etc/mtab file so that
# it will not give conflicts with the related
# symlink in the Arch Linux image.
copy_common_files
copy_file /etc/hosts.equiv
copy_file /etc/netgroup
copy_file /etc/networks
# No need for localtime as it is setup during the image build
#copy_file /etc/localtime
copy_passwd_and_group
if ! $no_copy_files
then
# Files to bind are visible in `proot --help`.
# This function excludes /etc/mtab file so that
# it will not give conflicts with the related
# symlink in the Arch Linux image.
copy_common_files
copy_file /etc/hosts.equiv
copy_file /etc/netgroup
copy_file /etc/networks
# No need for localtime as it is setup during the image build
#copy_file /etc/localtime
copy_passwd_and_group
fi
provide_common_bindings
local bindings=${RESULT}

View file

@ -35,44 +35,72 @@ function init_mocks() {
}
function test_run_env_as_groot_cmd(){
assertCommandSuccess run_env_as_groot "" pwd
assertCommandSuccess run_env_as_groot "" "false" 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_groot_no_cmd(){
assertCommandSuccess run_env_as_groot ""
assertCommandSuccess run_env_as_groot "" "false" ""
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_no_copy(){
assertCommandSuccess run_env_as_groot "" "true" pwd
assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/host.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/nsswitch.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/resolv.conf ]]
assertEquals 0 $?
}
function test_run_env_as_groot_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_groot ""
assertCommandFailOnStatus 106 run_env_as_groot "" "false" ""
unset JUNEST_ENV
}
function test_run_env_as_groot_cmd_with_backend_args(){
assertCommandSuccess run_env_as_groot "-n -b /home/blah" pwd
assertCommandSuccess run_env_as_groot "-n -b /home/blah" "false" 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
assertCommandSuccess run_env_as_chroot "" "false" 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 ""
assertCommandSuccess run_env_as_chroot "" "false" ""
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c /bin/sh --login" "$(cat $STDOUTF)"
}
function test_run_env_as_chroot_no_copy(){
assertCommandSuccess run_env_as_chroot "" "true" pwd
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/host.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/nsswitch.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/resolv.conf ]]
assertEquals 0 $?
}
function test_run_env_as_choot_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_chroot ""
assertCommandFailOnStatus 106 run_env_as_chroot "" "false" ""
unset JUNEST_ENV
}
function test_run_env_as_chroot_cmd_with_backend_args(){
assertCommandSuccess run_env_as_chroot "-n -b /home/blah" pwd
assertCommandSuccess run_env_as_chroot "-n -b /home/blah" "false" pwd
assertEquals "chroot_cmd -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)"
}

View file

@ -25,8 +25,8 @@ function version(){
echo "version"
}
function build_image_env(){
local disable_validation=$1
echo "build_image_env($disable_validation)"
local disable_check=$1
echo "build_image_env($disable_check)"
}
function delete_env(){
echo "delete_env"
@ -39,24 +39,33 @@ function setup_env(){
}
function run_env_as_fakeroot(){
local backend_args="$1"
shift
echo "run_env_as_fakeroot($backend_args,$@)"
local no_copy_files="$2"
shift 2
echo "run_env_as_fakeroot($backend_args,$no_copy_files,$@)"
}
function run_env_as_groot(){
echo "run_env_as_groot $@"
local backend_args="$1"
local no_copy_files="$2"
shift 2
echo "run_env_as_groot($backend_args,$no_copy_files,$@)"
}
function run_env_as_chroot(){
echo "run_env_as_chroot $@"
local backend_args="$1"
local no_copy_files="$2"
shift 2
echo "run_env_as_chroot($backend_args,$no_copy_files,$@)"
}
function run_env_as_user(){
local backend_args="$1"
shift
echo "run_env_as_user($backend_args,$@)"
local no_copy_files="$2"
shift 2
echo "run_env_as_user($backend_args,$no_copy_files,$@)"
}
function run_env_with_namespace(){
local backend_args="$1"
shift
echo "run_env_with_namespace($backend_args,$@)"
local no_copy_files="$2"
shift 2
echo "run_env_with_namespace($backend_args,$no_copy_files,$@)"
}
function test_help(){
@ -72,118 +81,181 @@ 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-check
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
assertEquals "run_env_as_fakeroot(,)" "$(cat $STDOUTF)"
assertCommandSuccess main --fakeroot
assertEquals "run_env_as_fakeroot(,)" "$(cat $STDOUTF)"
assertCommandSuccess main p -f
assertEquals "run_env_as_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot --fakeroot
assertEquals "run_env_as_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main p -f -n
assertEquals "run_env_as_fakeroot(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main -f -p "-b arg"
assertEquals "run_env_as_fakeroot(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess main -f -p "-b arg" -- command -kv
assertEquals "run_env_as_fakeroot(-b arg,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main -f command --as
assertEquals "run_env_as_fakeroot(,command --as)" "$(cat $STDOUTF)"
assertCommandFail main -a "myarch" -f command --as
assertCommandSuccess main proot -f -b "-b arg"
assertEquals "run_env_as_fakeroot(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f -b "-b arg" -- command -kv
assertEquals "run_env_as_fakeroot(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f command --as
assertEquals "run_env_as_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f -- command --as
assertEquals "run_env_as_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
is_env_installed(){
return 1
}
assertCommandFail main proot -f
}
function test_run_env_as_user(){
assertCommandSuccess main
assertEquals "run_env_as_user(,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot
assertEquals "run_env_as_user(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main p -n
assertEquals "run_env_as_user(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main -p "-b arg"
assertEquals "run_env_as_user(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess main -p "-b arg" -- command -ll
assertEquals "run_env_as_user(-b arg,command -ll)" "$(cat $STDOUTF)"
assertCommandSuccess main command -ls
assertEquals "run_env_as_user(,command -ls)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -b "-b arg"
assertEquals "run_env_as_user(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -b "-b arg" -- command -ll
assertEquals "run_env_as_user(-b arg,false,command -ll)" "$(cat $STDOUTF)"
assertCommandSuccess main proot command -ls
assertEquals "run_env_as_user(,false,command -ls)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -- command -ls
assertEquals "run_env_as_user(,false,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
assertEquals "run_env_as_groot " "$(cat $STDOUTF)"
assertCommandSuccess main -g command
assertEquals "run_env_as_groot command" "$(cat $STDOUTF)"
assertCommandSuccess main g
assertEquals "run_env_as_groot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main g -n
assertEquals "run_env_as_groot(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main g -b "-b arg"
assertEquals "run_env_as_groot(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main groot command
assertEquals "run_env_as_groot(,false,command)" "$(cat $STDOUTF)"
assertCommandSuccess main groot -- command
assertEquals "run_env_as_groot(,false,command)" "$(cat $STDOUTF)"
is_env_installed(){
return 1
}
assertCommandFail main groot
}
function test_run_env_as_chroot(){
assertCommandSuccess main -r
assertEquals "run_env_as_chroot " "$(cat $STDOUTF)"
assertCommandSuccess main -r command
assertEquals "run_env_as_chroot command" "$(cat $STDOUTF)"
assertCommandSuccess main r
assertEquals "run_env_as_chroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main r -b "-b arg"
assertEquals "run_env_as_chroot(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main root command
assertEquals "run_env_as_chroot(,false,command)" "$(cat $STDOUTF)"
assertCommandSuccess main root -- command
assertEquals "run_env_as_chroot(,false,command)" "$(cat $STDOUTF)"
is_env_installed(){
return 1
}
assertCommandFail main root -f
}
function test_run_env_with_namespace(){
assertCommandSuccess main -u -f
assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess main --namespace --fakeroot
assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess main n
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -n
assertEquals "run_env_with_namespace(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -f -p "-b arg"
assertEquals "run_env_with_namespace(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -f -p "-b arg" -- command -kv
assertEquals "run_env_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main -u -f command --as
assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -b "-b arg"
assertEquals "run_env_with_namespace(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -b "-b arg" -- command -kv
assertEquals "run_env_with_namespace(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main ns command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -- command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -b "-b arg"
assertEquals "run_env_with_namespace(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -b "-b arg" -- command -kv
assertEquals "run_env_with_namespace(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main -- command --as
assertEquals "run_env_with_namespace(,false,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

View file

@ -100,15 +100,41 @@ function test_is_user_namespace_enabled_with_userns_clone_file_enabled(){
}
function test_run_env_with_namespace() {
assertCommandSuccess run_env_with_namespace "" ""
assertCommandSuccess run_env_with_namespace "" "false" ""
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -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_with_namespace_no_copy() {
assertCommandSuccess run_env_with_namespace "" "true" ""
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/host.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/nsswitch.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/resolv.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/hosts.equiv ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/netgroup ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/networks ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/passwd ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/group ]]
assertEquals 0 $?
}
function test_run_env_with_namespace_with_bindings() {
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" ""
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "false" ""
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -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
@ -116,7 +142,7 @@ function test_run_env_with_namespace_with_bindings() {
}
function test_run_env_with_namespace_with_command() {
assertCommandSuccess run_env_with_namespace "" "ls -la"
assertCommandSuccess run_env_with_namespace "" "false" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
@ -124,7 +150,7 @@ function test_run_env_with_namespace_with_command() {
}
function test_run_env_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "false" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -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
@ -133,7 +159,7 @@ function test_run_env_with_namespace_with_bindings_and_command() {
function test_run_env_with_namespace_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_with_namespace ""
assertCommandFailOnStatus 106 run_env_with_namespace "" "false" ""
unset JUNEST_ENV
}

View file

@ -51,20 +51,49 @@ function test_run_env_as_user(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_user "-k 3.10" "/usr/bin/mkdir" "-v" "/newdir2"
assertCommandSuccess run_env_as_user "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
SH=("/usr/bin/echo")
assertCommandSuccess run_env_as_user "-k 3.10"
assertCommandSuccess run_env_as_user "-k 3.10" "false"
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_user_no_copy(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_user "-k 3.10" "true" "/usr/bin/mkdir" "-v" "/newdir2"
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/host.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/nsswitch.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/resolv.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/hosts.equiv ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/netgroup ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/networks ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/passwd ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/group ]]
assertEquals 0 $?
}
function test_run_env_as_user_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_user ""
assertCommandFailOnStatus 106 run_env_as_user "" "false"
unset JUNEST_ENV
}
@ -72,11 +101,11 @@ function test_run_env_as_fakeroot(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_fakeroot "-k 3.10" "/usr/bin/mkdir" "-v" "/newdir2"
assertCommandSuccess run_env_as_fakeroot "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
SH=("/usr/bin/echo")
assertCommandSuccess run_env_as_fakeroot "-k 3.10"
assertCommandSuccess run_env_as_fakeroot "-k 3.10" "false"
assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)"
_test_copy_common_files
@ -84,7 +113,7 @@ function test_run_env_as_fakeroot(){
function test_run_env_as_fakeroot_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_fakeroot ""
assertCommandFailOnStatus 106 run_env_as_fakeroot "" "false" ""
unset JUNEST_ENV
}
@ -92,7 +121,7 @@ function test_run_env_with_quotes(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_user "-k 3.10" "bash" "-c" "/usr/bin/mkdir -v /newdir2"
assertCommandSuccess run_env_as_user "-k 3.10" "false" "bash" "-c" "/usr/bin/mkdir -v /newdir2"
assertEquals "-b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 bash -c /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
}