mirror of
https://github.com/fsquillace/junest.git
synced 2026-01-23 10:35:36 +00:00
Compare commits
184 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0037f96e15 | ||
|
|
0242749f8e | ||
|
|
e2d9517a92 | ||
|
|
452a69cff3 | ||
|
|
7af01ba481 | ||
|
|
e68c24dec6 | ||
|
|
fd44972137 | ||
|
|
4d2d0fcb84 | ||
|
|
c91e013cd4 | ||
|
|
2eaf739a29 | ||
|
|
e680325f5a | ||
|
|
6ae9f72dd5 | ||
|
|
d19d2f07b6 | ||
|
|
2dd84efecb | ||
|
|
cc1287825d | ||
|
|
b3565e093d | ||
|
|
9a06d47f76 | ||
|
|
daa60b05e3 | ||
|
|
507502dc1a | ||
|
|
c440252f2a | ||
|
|
3742c16ce0 | ||
|
|
c2dae9021d | ||
|
|
39508ca8a9 | ||
|
|
ae365215fb | ||
|
|
874f52f0f8 | ||
|
|
71397b942b | ||
|
|
296c9e47b4 | ||
|
|
9b00c5c4c5 | ||
|
|
ba0ddcc524 | ||
|
|
4db85bcf1f | ||
|
|
369cda8dc6 | ||
|
|
b976f767d5 | ||
|
|
95f97a62b7 | ||
|
|
6048b43218 | ||
|
|
3fb7676277 | ||
|
|
978f64ea0a | ||
|
|
48b20848c8 | ||
|
|
632b416955 | ||
|
|
0b34458fb5 | ||
|
|
2492583877 | ||
|
|
a9174267b3 | ||
|
|
65c45517e1 | ||
|
|
20f42f6cb7 | ||
|
|
76c1644c63 | ||
|
|
1c16425b88 | ||
|
|
fab5b0df2e | ||
|
|
c052e660ee | ||
|
|
30967bc15f | ||
|
|
60c7d1c5d0 | ||
|
|
91f95ae4b5 | ||
|
|
2f6e137e7e | ||
|
|
991aa5d7fe | ||
|
|
e5f14c3735 | ||
|
|
f0e82bf8bf | ||
|
|
56761f6e63 | ||
|
|
77acbf5214 | ||
|
|
799d3bdd42 | ||
|
|
a9f5304279 | ||
|
|
df2fec0a36 | ||
|
|
73b8bec8db | ||
|
|
98775b538f | ||
|
|
0e6aa260ad | ||
|
|
21b5e3fabb | ||
|
|
0295f37758 | ||
|
|
e7d7056e9c | ||
|
|
e794a6150c | ||
|
|
2b9f1839f1 | ||
|
|
5630a0f035 | ||
|
|
bc543a9285 | ||
|
|
5f7eaff50e | ||
|
|
7d8c619ee0 | ||
|
|
e6bae0647c | ||
|
|
6efc4d0f52 | ||
|
|
de63bdf96a | ||
|
|
4a1c11d4ed | ||
|
|
a9d11fb4d5 | ||
|
|
5e97524338 | ||
|
|
14d51d9856 | ||
|
|
46cc4aad48 | ||
|
|
4036a7737b | ||
|
|
6e872c5f26 | ||
|
|
7fe9c0e9ec | ||
|
|
38ab252f98 | ||
|
|
9ecabcd524 | ||
|
|
86277fd589 | ||
|
|
e45d76651e | ||
|
|
fc3b54e97f | ||
|
|
e9406123b9 | ||
|
|
08553a447e | ||
|
|
6af7bae418 | ||
|
|
700b809fbe | ||
|
|
8e560b4a8a | ||
|
|
79e4107196 | ||
|
|
b8ad2182be | ||
|
|
6548e19eb5 | ||
|
|
8d4217492a | ||
|
|
f0b6f0962e | ||
|
|
4527297be1 | ||
|
|
6291e5cc83 | ||
|
|
f98fa897bf | ||
|
|
d3f9f13ccd | ||
|
|
2242585778 | ||
|
|
8844f7b5d8 | ||
|
|
d25ae30158 | ||
|
|
2aeb23b882 | ||
|
|
3d16ee2583 | ||
|
|
9d2e6e4bbf | ||
|
|
b75faac48f | ||
|
|
95479ba41f | ||
|
|
78c4f72bc1 | ||
|
|
26e58aaeec | ||
|
|
8609300b20 | ||
|
|
440dde6564 | ||
|
|
84f4d20370 | ||
|
|
98107ac07f | ||
|
|
7b3685941d | ||
|
|
6d7bc4efa4 | ||
|
|
b0169a8e5f | ||
|
|
12e6f6214e | ||
|
|
500546a0e2 | ||
|
|
09b9c644d9 | ||
|
|
348b73ce73 | ||
|
|
6592bc9bd2 | ||
|
|
d1285908ae | ||
|
|
1580ba9c8e | ||
|
|
628ac3c655 | ||
|
|
4b5b7b300b | ||
|
|
385dd8c68c | ||
|
|
6e55e0c648 | ||
|
|
121f2c74f6 | ||
|
|
9bfd7e047d | ||
|
|
538e87f036 | ||
|
|
5b60382ca4 | ||
|
|
7acf16cc73 | ||
|
|
11a439499b | ||
|
|
e0dd3257a8 | ||
|
|
4bb9b60638 | ||
|
|
606353047c | ||
|
|
493b105faa | ||
|
|
85aeda4ac9 | ||
|
|
2e8f5905c7 | ||
|
|
82b146a57e | ||
|
|
e12cd8d8ff | ||
|
|
8d91e18ab0 | ||
|
|
c5847b8583 | ||
|
|
27f92d0b3f | ||
|
|
97d19da268 | ||
|
|
632aad46bd | ||
|
|
de0bec9bc5 | ||
|
|
3341187cf6 | ||
|
|
ef4bf7cd79 | ||
|
|
00c60118fb | ||
|
|
30b743cb1b | ||
|
|
313ef30662 | ||
|
|
691369068d | ||
|
|
fbe49acc01 | ||
|
|
98c97ddfa7 | ||
|
|
6361522e40 | ||
|
|
cc351f419d | ||
|
|
bca7e565ca | ||
|
|
34f3458335 | ||
|
|
5172093fe2 | ||
|
|
5bc4cd245a | ||
|
|
0d7468b516 | ||
|
|
d858d577c8 | ||
|
|
f60bbb5c2a | ||
|
|
b2ba7f9d5b | ||
|
|
4b6fd63cf8 | ||
|
|
9cd13c88f6 | ||
|
|
797853bbb4 | ||
|
|
358f92d3e0 | ||
|
|
c3610ec86a | ||
|
|
22483b9ea9 | ||
|
|
3eada1e4f1 | ||
|
|
8fe650ce87 | ||
|
|
d6d6883e82 | ||
|
|
f9f7cbcaaa | ||
|
|
51f6765634 | ||
|
|
c2d5985fe3 | ||
|
|
7ebdf628cf | ||
|
|
35fce94c4e | ||
|
|
73b4b85399 | ||
|
|
bd0e9fbbcc | ||
|
|
137788a98a |
35 changed files with 2284 additions and 1392 deletions
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
github: fsquillace
|
||||||
|
custom: https://github.com/fsquillace/junest/blob/master/README.md#donating
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1 +1,4 @@
|
||||||
*.swp
|
*.swp
|
||||||
|
*pkg.tar.*
|
||||||
|
*.tar.gz
|
||||||
|
*.SRCINFO
|
||||||
|
|
|
||||||
60
.travis.yml
60
.travis.yml
|
|
@ -1,30 +1,62 @@
|
||||||
language: bash
|
|
||||||
|
|
||||||
sudo: required
|
sudo: required
|
||||||
|
os: linux
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- ~/.ccache
|
||||||
|
- ~/.pkg-cache
|
||||||
|
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
matrix:
|
||||||
- TRAVIS_BASH_VERSION="4.0"
|
- TRAVIS_BASH_VERSION="4.0"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- ./tests/integ-tests/install-bash.sh "$TRAVIS_BASH_VERSION"
|
- ./ci/install-bash.sh "$TRAVIS_BASH_VERSION"
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get -y install awscli
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- PATH=$PWD/bin:$PATH
|
- PATH=$PWD/bin:$PATH
|
||||||
- junest -- echo "Installing JuNest (\$(uname -m))"
|
|
||||||
- JUNEST_HOME=~/.junest-arm junest -a arm -- echo "Installing JuNest (\$(uname -m))"
|
|
||||||
# TODO: Remember to enable x86 tests when fixed
|
|
||||||
#- JUNEST_HOME=~/.junest-x86 junest -a x86 -- echo "Installing JuNest (\$(uname -m))"
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
#######################
|
||||||
|
# Unit Tests
|
||||||
|
#######################
|
||||||
- bash --version
|
- bash --version
|
||||||
- bash ./tests/checkstyle/checkstyle.sh
|
- bash ./tests/checkstyle/checkstyle.sh
|
||||||
- bash ./tests/unit-tests/unit-tests.sh
|
- bash ./tests/unit-tests/unit-tests.sh
|
||||||
|
- shellcheck bin/junest lib/**/*.sh ci/*.sh tests/**/*.sh
|
||||||
|
|
||||||
# Multiple tests against different execution modes:
|
# ARM with qemu does seem to work properly. Disabling integ tests for ARM for now.
|
||||||
- junest -f -- ${PWD}/lib/checks/check.sh
|
#- export JUNEST_HOME=~/.junest-arm
|
||||||
- junest -u -- ${PWD}/lib/checks/check.sh --skip-aur-tests
|
#- junest setup --arch arm
|
||||||
- sudo -E ${PWD}/bin/junest -g -- ${PWD}/lib/checks/check.sh --run-root-tests
|
#- junest proot --fakeroot -- echo "Installing JuNest (\$(uname -m))"
|
||||||
- yes | junest --delete
|
#- junest proot --fakeroot -- ${PWD}/lib/checks/check.sh --skip-aur-tests
|
||||||
|
#- junest proot -- ${PWD}/lib/checks/check.sh --skip-aur-tests --use-sudo
|
||||||
|
#- yes | junest setup --delete
|
||||||
|
|
||||||
- JUNEST_HOME=~/.junest-arm junest -f -- ./lib/checks/check.sh
|
#######################
|
||||||
- yes | JUNEST_HOME=~/.junest-arm junest --delete
|
# Build and validation
|
||||||
|
#######################
|
||||||
|
- echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin
|
||||||
|
- docker run --rm -v "$(pwd):/build" -v ~/.ccache:/home/travis/.ccache -v ~/.pkg-cache:/var/cache/pacman/pkg --privileged archlinux:latest bash /build/ci/build_image.sh
|
||||||
|
|
||||||
|
- "echo pacman pkg cache size: $(du -h ~/.pkg-cache|cut -f1) in $(ls ~/.pkg-cache|wc -l) files"
|
||||||
|
- ls -l
|
||||||
|
# Test the newly created JuNest image against Ubuntu host
|
||||||
|
- export JUNEST_HOME=~/.junest
|
||||||
|
- junest setup -i junest-x86_64.tar.gz
|
||||||
|
# TODO The check does not work at the moment: https://app.travis-ci.com/github/fsquillace/junest/builds/271706037
|
||||||
|
# Disabling it in order to avoid having stale version of junest images.
|
||||||
|
- ${PWD}/lib/checks/check_all.sh
|
||||||
|
- yes | junest setup --delete
|
||||||
|
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
#######################
|
||||||
|
# Deploy and validation
|
||||||
|
#######################
|
||||||
|
- ./ci/deploy.sh ./junest-x86_64.tar.gz
|
||||||
|
|
|
||||||
435
README.md
435
README.md
|
|
@ -1,6 +1,13 @@
|
||||||
JuNest
|
JuNest
|
||||||
======
|
======
|
||||||
The Arch Linux based distro that runs upon any Linux distros without root access.
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Starting from Ubuntu 23.10+, [unprivileged user namespaces has been restricted](https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces).
|
||||||
|
> If using JuNest within Ubuntu, you may need root privileges in order to enable it.
|
||||||
|
> Alternatively, you can access JuNest using the `proot` mode as described
|
||||||
|
> [below](#Proot-based).
|
||||||
|
|
||||||
|
The lightweight Arch Linux based distro that runs, without root privileges, on top of any other Linux distro.
|
||||||
|
|
||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
<a href="https://github.com/fsquillace/junest"><img
|
<a href="https://github.com/fsquillace/junest"><img
|
||||||
|
|
@ -11,7 +18,7 @@ The Arch Linux based distro that runs upon any Linux distros without root access
|
||||||
|
|
||||||
|Project Status|Donation|Communication|
|
|Project Status|Donation|Communication|
|
||||||
|:------------:|:------:|:-----------:|
|
|:------------:|:------:|:-----------:|
|
||||||
| [](https://travis-ci.org/fsquillace/junest) [](https://www.openhub.net/p/junest) | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8LEHQKBCYTACY) [](https://gratipay.com/junest/) | [](https://gitter.im/fsquillace/junest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://webchat.freenode.net/?channels=junest) [](https://groups.google.com/d/forum/junest) [](http://fsquillace.github.io/junest-site/feed.xml) |
|
| [](https://app.travis-ci.com/github/fsquillace/junest) [](https://www.openhub.net/p/junest) | [](https://github.com/sponsors/fsquillace) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8LEHQKBCYTACY) [](https://www.buymeacoffee.com/fsquillace) | [](https://discord.gg/ttfBT7MKve) |
|
||||||
|
|
||||||
**Table of Contents**
|
**Table of Contents**
|
||||||
- [Description](#description)
|
- [Description](#description)
|
||||||
|
|
@ -23,48 +30,45 @@ The Arch Linux based distro that runs upon any Linux distros without root access
|
||||||
- [Troubleshooting](#troubleshooting)
|
- [Troubleshooting](#troubleshooting)
|
||||||
- [More documentation](#more-documentation)
|
- [More documentation](#more-documentation)
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
- [Author](#author)
|
- [Donating](#donating)
|
||||||
|
- [Authors](#authors)
|
||||||
|
|
||||||
Description
|
Description
|
||||||
===========
|
===========
|
||||||
**JuNest** (Jailed User NEST) is a lightweight Arch Linux based distribution that allows to have
|
**JuNest** (Jailed User Nest) is a lightweight Arch Linux based distribution
|
||||||
an isolated GNU/Linux environment inside any generic host GNU/Linux OS
|
that allows the creation of disposable and partially isolated GNU/Linux environments
|
||||||
and without the need to have root privileges for installing packages.
|
within any generic GNU/Linux host OS and without requiring root
|
||||||
|
privileges to install packages.
|
||||||
|
|
||||||
JuNest contains mainly the package managers (called [pacman](https://wiki.archlinux.org/index.php/Pacman)
|
JuNest is built around [pacman](https://wiki.archlinux.org/index.php/Pacman),
|
||||||
and a simple wrapper of [yaourt](https://wiki.archlinux.org/index.php/Yaourt) called yogurt) that allows to access
|
the Arch Linux package manager, which allows access
|
||||||
to a wide range of packages from the Arch Linux repositories.
|
to a wide range of packages from the Arch Linux repositories.
|
||||||
|
|
||||||
The main advantages on using JuNest are:
|
The main advantages of using JuNest include:
|
||||||
|
|
||||||
- Install packages without root privileges.
|
- Install packages without root privileges.
|
||||||
- Isolated environment in which you can install packages without affecting a production system.
|
- Create partially isolated environments in which you can install packages without risking mishaps on production systems.
|
||||||
- Access to a wide range of packages in particular on GNU/Linux distros that may contain limited repositories (such as CentOS and RedHat).
|
- Access a wider range of packages, particularly on GNU/Linux distros with comparatively limited repositories (such as CentOS and Red Hat).
|
||||||
- Available for x86\_64, x86 and ARM architectures but you can build your own image from scratch too!
|
- Run on a different architecture from the host OS via QEMU.
|
||||||
- Run on a different architecture from the host OS via QEMU
|
- Available for `x86_64` and `arm` architectures but you can build your own image from scratch too!
|
||||||
- All Arch Linux lovers can have their favourite distro everywhere!
|
- All Arch Linux lovers can enjoy their favourite distro everywhere!
|
||||||
|
|
||||||
JuNest follows the [Arch Linux philosophy](https://wiki.archlinux.org/index.php/The_Arch_Way).
|
JuNest follows the [Arch Linux philosophy](https://wiki.archlinux.org/index.php/The_Arch_Way).
|
||||||
|
|
||||||
Quickstart
|
How different is JuNest from Docker and Vagrant?
|
||||||
==========
|
------------------------------------------------
|
||||||
The basic way to run JuNest is via the [Proot](https://wiki.archlinux.org/index.php/Proot) as the backend program:
|
Although JuNest sounds similar to a virtualisation/Linux container-like system,
|
||||||
|
JuNest is quite different from solutions like Docker or Vagrant.
|
||||||
|
In fact, the purpose of JuNest is **not** to
|
||||||
|
build a completely isolated environment but, conversely, to provide the ability to run
|
||||||
|
programs as if they were running natively from the host OS. Almost everything is shared
|
||||||
|
between the host OS and the JuNest sandbox (kernel, process subtree, network, mounting, etc)
|
||||||
|
and only the root filesystem gets isolated
|
||||||
|
(since the programs installed in JuNest need to reside elsewhere).
|
||||||
|
|
||||||
- As normal user - Allow to make basic operations: ```junest```
|
This allows interaction between processes belonging to both host OS and JuNest.
|
||||||
|
For example, you can install the `top` command in JuNest and use it to monitor
|
||||||
- As fakeroot - Allow to install/remove packages: ```junest -f```
|
processes belonging to the host OS.
|
||||||
|
|
||||||
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`.
|
|
||||||
|
|
||||||
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
|
Installation
|
||||||
============
|
============
|
||||||
|
|
@ -77,83 +81,208 @@ Before installing JuNest be sure that all dependencies are properly installed in
|
||||||
- [bash (>=4.0)](https://www.gnu.org/software/bash/)
|
- [bash (>=4.0)](https://www.gnu.org/software/bash/)
|
||||||
- [GNU coreutils](https://www.gnu.org/software/coreutils/)
|
- [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
|
## Installation from git repository ##
|
||||||
and 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.
|
|
||||||
|
|
||||||
|
|
||||||
## Method one (Recommended) ##
|
|
||||||
Just clone the JuNest repo somewhere (for example in ~/.local/share/junest):
|
Just clone the JuNest repo somewhere (for example in ~/.local/share/junest):
|
||||||
|
|
||||||
git clone git://github.com/fsquillace/junest ~/.local/share/junest
|
```sh
|
||||||
export PATH=~/.local/share/junest/bin:$PATH
|
git clone https://github.com/fsquillace/junest.git ~/.local/share/junest
|
||||||
|
export PATH=~/.local/share/junest/bin:$PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally you want to use the wrappers to run commands
|
||||||
|
installed in JuNest directly from host:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export PATH="$PATH:~/.junest/usr/bin_wrappers"
|
||||||
|
```
|
||||||
|
Update your `~/.bashrc` or `~/.zshrc` to get always the wrappers available.
|
||||||
|
|
||||||
### Installation using AUR (Arch Linux only) ###
|
### 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/):
|
If you are using an Arch Linux system you can, alternatively, install JuNest from the [AUR repository](https://aur.archlinux.org/packages/junest-git/).
|
||||||
|
JuNest will be located in `/opt/junest/`
|
||||||
|
|
||||||
yaourt -S junest-git
|
Quickstart
|
||||||
export PATH=/opt/junest/bin:$PATH
|
==========
|
||||||
|
|
||||||
## Method two ##
|
Setup environment
|
||||||
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">
|
The first operation required is to install the JuNest environment in the
|
||||||
mkdir ~/.junest
|
location of your choice via `JUNEST_HOME` environment variable
|
||||||
curl https://s3-eu-west-1.amazonaws.com/junest-repo/junest-${ARCH}.tar.gz | tar -xz -C ~/.junest
|
(it must contain an absolute path) which by
|
||||||
export PATH=~/.junest/opt/junest/bin:$PATH
|
default is `~/.junest`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
junest setup
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will download the image from the repository and will place it to the default directory `~/.junest`.
|
||||||
|
|
||||||
|
Access to environment
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
JuNest uses the Linux namespaces (aka `ns`) as the default backend program. To access via `ns` just type:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
junest
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the command `sudo` to acquire fakeroot privileges and
|
||||||
|
install/remove packages.
|
||||||
|
|
||||||
|
Alternatively, you can access fakeroot privileges without using `sudo` all the
|
||||||
|
time with the `-f` (or `--fakeroot`) option:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
junest -f
|
||||||
|
```
|
||||||
|
|
||||||
|
Another execution mode is via [Proot](https://wiki.archlinux.org/index.php/Proot):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
junest proot [-f]
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Run JuNest installed programs directly from host OS
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Programs installed within JuNest can be accessible directly from host machine
|
||||||
|
without entering into a JuNest session
|
||||||
|
(namely, no need to call `junest` command first).
|
||||||
|
For instance, supposing the host OS is an Ubuntu distro you can directly
|
||||||
|
run `pacman` by simply updating the `PATH` variable:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export PATH="$PATH:~/.junest/usr/bin_wrappers"
|
||||||
|
sudoj pacman -S htop
|
||||||
|
htop
|
||||||
|
```
|
||||||
|
|
||||||
|
By default the wrappers use `ns` mode. To use the `ns --fakeroot` you can use the convenient command helper `sudoj`.
|
||||||
|
For more control on backend modes you can use the `JUNEST_ARGS` environment variable too.
|
||||||
|
For instance, if you want to run `iftop` with real root privileges:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudoj pacman -S iftop
|
||||||
|
sudo JUNEST_ARGS="groot" iftop
|
||||||
|
```
|
||||||
|
|
||||||
|
Bin wrappers can be always recreated (e.g. in case for some reasons they get
|
||||||
|
corrupted) with:
|
||||||
|
|
||||||
|
```
|
||||||
|
junest create-bin-wrappers -f
|
||||||
|
```
|
||||||
|
|
||||||
|
Bin wrappers are automatically generated each time they get installed inside JuNest.
|
||||||
|
This only works for executables located in `/usr/bin` path.
|
||||||
|
For executables in other locations (say `/usr/mybinpath`) you can only create
|
||||||
|
wrappers manually by executing the command:
|
||||||
|
|
||||||
|
```
|
||||||
|
junest create-bin-wrappers --bin-path /usr/mybinpath
|
||||||
|
```
|
||||||
|
|
||||||
|
Obviously, to get access to the corresponding bin wrappers you will need to
|
||||||
|
update your `PATH` variable accordingly:
|
||||||
|
|
||||||
|
```
|
||||||
|
export PATH="$PATH:~/.junest/usr/mybinpath_wrappers"
|
||||||
|
```
|
||||||
|
|
||||||
|
Install packages from AUR
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
In `ns` mode, you can easily install package from [AUR](https://aur.archlinux.org/) repository
|
||||||
|
using the already available [`yay`](https://aur.archlinux.org/packages/yay/)
|
||||||
|
command. In `proot` mode, JuNest does no longer support the building of AUR packages.
|
||||||
|
|
||||||
|
**Remember** that in order to build packages from AUR, `base-devel` package group is required
|
||||||
|
first:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pacman -S base-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
JuNest uses a modified version of `sudo` provided by `junest/sudo-fake`. And the original `core/sudo`
|
||||||
|
package will be ignored **(and must not be installed)** during the installation of `base-devel`.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
There are three different ways you can run JuNest depending on the backend program you decide to use.
|
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```
|
|
||||||
|
|
||||||
Linux namespaces based
|
Linux namespaces based
|
||||||
----------------------
|
----------------------
|
||||||
The [Linux namespaces](http://man7.org/linux/man-pages/man7/namespaces.7.html)
|
The [Linux namespaces](http://man7.org/linux/man-pages/man7/namespaces.7.html)
|
||||||
represents the next generation backend program for JuNest.
|
represents the default backend program for JuNest.
|
||||||
The major drawback about the namespace is portability, as certain requirements
|
The requirements for having Linux namespaces working are:
|
||||||
need to be satisfied: 1) Only starting from Linux 3.8, unprivileged processes can
|
|
||||||
create the required user and mount namespaces.
|
1. Kernel starting from Linux 3.8 allows unprivileged processes to create
|
||||||
2) Moreover, the Linux kernel distro must have the user namespace enabled.
|
user and mount namespaces.
|
||||||
Hopefully, in the future the major GNU/Linux distros will start enabling such feature by default.
|
1. The Linux kernel distro must have the user namespace enabled.
|
||||||
For instance, Ubuntu (version 14.04+) already has such feature 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:
|
In order to run JuNest via Linux namespaces:
|
||||||
|
|
||||||
- As fakeroot - Allow to install/remove packages: ```junest -u```
|
- As normal user - Allow to make basic operations or install/remove packages
|
||||||
|
with `sudo` command: `junest ns` or `junest`
|
||||||
|
- As fakeroot - Allow to install/remove packages: `junest ns -f` or `junest -f`
|
||||||
|
|
||||||
|
This mode is based on the fantastic
|
||||||
|
[`bubblewrap`](https://github.com/containers/bubblewrap) command.
|
||||||
|
|
||||||
|
PRoot based
|
||||||
|
-----------
|
||||||
|
[Proot](https://wiki.archlinux.org/index.php/Proot) represents a portable
|
||||||
|
solution which allows unprivileged users to execute programs inside a sandbox
|
||||||
|
and works well in most of GNU/Linux distros available.
|
||||||
|
|
||||||
|
In order to run JuNest via Proot:
|
||||||
|
|
||||||
|
- As normal user - Allow to make basic operations: `junest proot`
|
||||||
|
|
||||||
|
- As fakeroot - Allow to install/remove packages: `junest proot -f`
|
||||||
|
|
||||||
|
In `proot` mode, the minimum recommended Linux kernel for 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.
|
||||||
|
|
||||||
Chroot based
|
Chroot based
|
||||||
------------
|
------------
|
||||||
This solution suits only for privileged users. JuNest provides the possibility
|
This solution suits only for privileged users. JuNest provides the possibility
|
||||||
to run the environment via `chroot` program.
|
to run the environment via `chroot` program.
|
||||||
In particular, it uses a special program called `GRoot`, an enhanced `chroot`
|
In particular, it uses a special program called `GRoot`, a small and portable
|
||||||
wrapper that allows to bind mount directories specified by the user, such as
|
version of
|
||||||
/proc, /sys, /dev, /tmp and $HOME, before
|
[arch-chroot](https://wiki.archlinux.org/index.php/Chroot)
|
||||||
|
wrapper, that allows to bind mount directories specified by the user, such as
|
||||||
|
`/proc`, `/sys`, `/dev`, `/tmp`, `/run/user/<id>` and `$HOME`, before
|
||||||
executing any programs inside the JuNest sandbox. In case the mounting will not
|
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
|
work, JuNest is even providing the possibility to run the environment directly via
|
||||||
the pure `chroot` command.
|
the pure `chroot` command.
|
||||||
|
|
||||||
In order to run JuNest via `chroot` solutions:
|
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
|
Execution modes comparison table
|
||||||
----------------
|
----------------
|
||||||
|
|
@ -161,8 +290,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 |
|
| | 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 | Normal user and `fakeroot` |
|
||||||
| **Linux Namespaces** | NO | NO | YES | NO | Poor | YES | `fakeroot` only |
|
| **Proot** | YES | NO | YES | NO | YES | YES | Normal user and `fakeroot` |
|
||||||
| **Chroot** | NO | YES | YES | YES | YES | YES | `root` only |
|
| **Chroot** | NO | YES | YES | YES | YES | YES | `root` only |
|
||||||
|
|
||||||
Advanced usage
|
Advanced usage
|
||||||
|
|
@ -170,18 +299,22 @@ Advanced usage
|
||||||
## Build image ##
|
## Build image ##
|
||||||
You can build a new JuNest image from scratch by running the following command:
|
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
|
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.
|
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
|
Remember that the script to build the image must run in an Arch Linux OS with
|
||||||
arch-install-scripts, package-query, git and the base-devel packages installed.
|
arch-install-scripts and the base-devel packages installed.
|
||||||
To change the build directory just use the `JUNEST_TEMPDIR` (by default /tmp).
|
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
|
For more details, you can also take a look at
|
||||||
[junest-builder](https://github.com/fsquillace/junest-builder)
|
[junest-builder](https://github.com/fsquillace/junest-builder)
|
||||||
|
|
@ -194,20 +327,34 @@ Related wiki page:
|
||||||
|
|
||||||
## Run JuNest using a different architecture via QEMU ##
|
## Run JuNest using a different architecture via QEMU ##
|
||||||
The following command will download the ARM JuNest image and will run QEMU in
|
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
|
```sh
|
||||||
armv7l
|
$> export JUNEST_HOME=~/.junest-arm
|
||||||
|
$> junest setup -a arm
|
||||||
|
$> junest proot -- uname -m
|
||||||
|
armv7l
|
||||||
|
```
|
||||||
|
|
||||||
## Bind directories ##
|
## Bind directories ##
|
||||||
To bind a host directory to a guest location, you can use proot arguments:
|
To bind a host directory to a guest location:
|
||||||
|
|
||||||
junest -p "-b /mnt/mydata:/home/user/mydata"
|
```sh
|
||||||
|
junest -b "--bind /home/user/mydata /mnt/mydata"
|
||||||
|
```
|
||||||
|
|
||||||
This will works with PRoot, Namespace and GRoot backend programs.
|
Or using proot arguments:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
junest proot -b "-b /mnt/mydata:/home/user/mydata"
|
||||||
|
```
|
||||||
|
|
||||||
|
The option `-b` to provide options to the backend program will work with PRoot, Namespace and GRoot backend programs.
|
||||||
Check out the backend program options by passing `--help` option:
|
Check out the backend program options by passing `--help` option:
|
||||||
|
|
||||||
junest [-u|-g] -p "--help"
|
```sh
|
||||||
|
junest [u|g|p] -b "--help"
|
||||||
|
```
|
||||||
|
|
||||||
## Systemd integration ##
|
## Systemd integration ##
|
||||||
Although JuNest has not been designed to be a complete container, it is even possible to
|
Although JuNest has not been designed to be a complete container, it is even possible to
|
||||||
|
|
@ -219,7 +366,9 @@ and the container can only be executed using root privileges.
|
||||||
|
|
||||||
To boot a JuNest container:
|
To boot a JuNest container:
|
||||||
|
|
||||||
sudo systemd-nspawn -bD ~/.junest
|
```sh
|
||||||
|
sudo systemd-nspawn -bD ~/.junest
|
||||||
|
```
|
||||||
|
|
||||||
Related wiki page:
|
Related wiki page:
|
||||||
|
|
||||||
|
|
@ -228,30 +377,17 @@ Related wiki page:
|
||||||
|
|
||||||
Internals
|
Internals
|
||||||
=========
|
=========
|
||||||
|
|
||||||
There are two main chroot jail used in JuNest.
|
|
||||||
The main one is [proot](https://wiki.archlinux.org/index.php/Proot) which
|
|
||||||
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
|
|
||||||
the sandbox.
|
|
||||||
|
|
||||||
## Automatic fallback to classic chroot ##
|
|
||||||
If GRoot fails for some reasons in the host system (i.e. it is not able to
|
|
||||||
mount one of the directories),
|
|
||||||
JuNest automatically tries to fallback to the classic chroot.
|
|
||||||
|
|
||||||
## Automatic fallback for all the dependent host OS executables ##
|
## Automatic fallback for all the dependent host OS executables ##
|
||||||
JuNest attempt first to run the executables in the host OS located in different
|
JuNest attempts first to run the executables in the host OS located in different
|
||||||
positions (/usr/bin, /bin, /usr/sbin and /sbin).
|
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
|
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 ##
|
## Automatic building of the JuNest images ##
|
||||||
The JuNest images are built every week so that you can always get the most
|
There is a periodic automation build of the JuNest images for `x86_64` arch
|
||||||
updated package versions.
|
only.
|
||||||
|
The JuNest image for `arm` architecture may not be always up to date because
|
||||||
|
the build is performed manually.
|
||||||
|
|
||||||
## Static QEMU binaries ##
|
## Static QEMU binaries ##
|
||||||
There are static QEMU binaries included in JuNest image that allows to run JuNest
|
There are static QEMU binaries included in JuNest image that allows to run JuNest
|
||||||
|
|
@ -261,18 +397,35 @@ directory.
|
||||||
Troubleshooting
|
Troubleshooting
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
For Arch Linux related FAQs take a look at the [General troubleshooting page](https://wiki.archlinux.org/index.php/General_troubleshooting).
|
||||||
|
|
||||||
## Cannot use AUR repository ##
|
## 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.
|
Cannot find the gzip binary required for compressing man and info pages.
|
||||||
|
|
||||||
> **A**: JuNest comes with a very basic number of packages.
|
> **A**: JuNest comes with a very basic number of packages.
|
||||||
> In order to install packages using yogurt you may need to install the package group **base-devel**
|
> In order to install AUR packages you need to install the package group `base-devel` first
|
||||||
> that contains all the essential packages for compiling source code (such as gcc, make, patch, etc):
|
> that contains all the essential packages for compiling from source code (such as gcc, make, patch, etc):
|
||||||
|
|
||||||
#> pacman -S base-devel
|
#> pacman -S base-devel
|
||||||
|
|
||||||
|
> Remember to not install `core/sudo` as it conflicts with `junest/sudo-fake` package.
|
||||||
|
|
||||||
|
## Can't set user and group as root
|
||||||
|
|
||||||
|
> **Q**: In ns mode when installing package I get the following error:
|
||||||
|
|
||||||
|
warning: warning given when extracting /usr/file... (Can't set user=0/group=0 for
|
||||||
|
/usr/file...)
|
||||||
|
|
||||||
|
> **A**: This is because as fakeroot is not possible to set the owner/group of
|
||||||
|
> files as root. The package will still be installed correctly even though this
|
||||||
|
> message is showed.
|
||||||
|
|
||||||
|
## Could not change the root directory in pacman
|
||||||
|
|
||||||
## No servers configured for repository ##
|
## No servers configured for repository ##
|
||||||
|
|
||||||
> **Q**: Why I cannot install packages?
|
> **Q**: Why I cannot install packages?
|
||||||
|
|
@ -308,6 +461,8 @@ Troubleshooting
|
||||||
$> pkgfile getop
|
$> pkgfile getop
|
||||||
core/util-linux
|
core/util-linux
|
||||||
|
|
||||||
|
> Alternatively, you can use directly `pacman` command only. Take a look [here](https://wiki.archlinux.org/index.php/General_troubleshooting#Message:_%22error_while_loading_shared_libraries%22).
|
||||||
|
|
||||||
## Kernel too old ##
|
## Kernel too old ##
|
||||||
|
|
||||||
> **Q**: Why do I get the error: "FATAL: kernel too old"?
|
> **Q**: Why do I get the error: "FATAL: kernel too old"?
|
||||||
|
|
@ -322,7 +477,7 @@ Troubleshooting
|
||||||
> on to PRoot when *-p* is prepended. For example, to fake a kernel version of
|
> on to PRoot when *-p* is prepended. For example, to fake a kernel version of
|
||||||
> 3.10, issue the following command:
|
> 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
|
> 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
|
> not unique to the precompiled package from JuNest. It will also appear when
|
||||||
|
|
@ -379,7 +534,7 @@ Troubleshooting
|
||||||
> have *suid* permission, you can list the commands from your JuNest environment
|
> have *suid* permission, you can list the commands from your JuNest environment
|
||||||
> with the following command:
|
> with the following command:
|
||||||
|
|
||||||
$> find /usr/bin -perm +4000
|
$> find /usr/bin -perm /4000
|
||||||
|
|
||||||
## No characters are visible on a graphic application ##
|
## No characters are visible on a graphic application ##
|
||||||
|
|
||||||
|
|
@ -408,17 +563,31 @@ Troubleshooting
|
||||||
> since JuNest will try to preserve the JuNest environment by assigning ownership
|
> since JuNest will try to preserve the JuNest environment by assigning ownership
|
||||||
> of the files to the real user.
|
> of the files to the real user.
|
||||||
|
|
||||||
## Not enabled User namespace or kernel too old ##
|
## Unprivileged user namespace disable at kernel compile time or kernel too old ##
|
||||||
|
|
||||||
> **Q**: Why do I get warning when I run JuNest via Linux namespaces?
|
> **Q**: Why do I get this warning when I run JuNest via Linux namespaces?
|
||||||
|
|
||||||
$> junest -u
|
$> junest ns
|
||||||
User namespace is not enabled or Kernel too old (<3.8). Proceeding anyway...
|
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
|
||||||
|
> does not have a newer kernel version or the unprivileged user namespace
|
||||||
|
> is not enabled at kernel compile time.
|
||||||
|
> 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.
|
||||||
|
|
||||||
|
## Unprivileged user namespace disabled
|
||||||
|
|
||||||
|
> **Q**: Why do I get this warning when I run JuNest via Linux namespaces?
|
||||||
|
|
||||||
|
$> 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
|
> **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.
|
> 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
|
> 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.
|
> anyway. If you have root permissions try to enable it, otherwise try to use
|
||||||
|
> Proot as backend program.
|
||||||
|
|
||||||
More documentation
|
More documentation
|
||||||
==================
|
==================
|
||||||
|
|
@ -427,13 +596,21 @@ There are additional tutorials in the
|
||||||
|
|
||||||
Contributing
|
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)
|
- [Reporting Bugs](CONTRIBUTING.md#reporting-bugs)
|
||||||
- [Suggesting Enhancements](CONTRIBUTING.md#suggesting-enhancements)
|
- [Suggesting Enhancements](CONTRIBUTING.md#suggesting-enhancements)
|
||||||
- [Writing Code](CONTRIBUTING.md#your-first-code-contribution)
|
- [Writing Code](CONTRIBUTING.md#your-first-code-contribution)
|
||||||
|
|
||||||
Author
|
Donating
|
||||||
======
|
========
|
||||||
Filippo Squillace <feel.sqoox@gmail.com>
|
To sustain the project please consider funding by donations through
|
||||||
|
the [GitHub Sponsors page](https://github.com/sponsors/fsquillace/).
|
||||||
|
|
||||||
|
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/links/0)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/1)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/2)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/3)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/4)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/5)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/6)[](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/7)
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
6.0.2
|
7.4.10
|
||||||
|
|
|
||||||
234
bin/groot
234
bin/groot
|
|
@ -1,234 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# This script is the simplified and portable version of arch-chroot
|
|
||||||
# (https://wiki.archlinux.org/index.php/Change_root#Using_arch-chroot)
|
|
||||||
#
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# 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"))/..)}"
|
|
||||||
NAME='GRoot'
|
|
||||||
CMD='groot'
|
|
||||||
DESCRIPTION="I am $NAME!"
|
|
||||||
CHROOTCMD=${CHROOTCMD:-chroot}
|
|
||||||
SHELL="/bin/sh"
|
|
||||||
MOUNT=mount
|
|
||||||
UMOUNT=umount
|
|
||||||
MOUNTPOINT=mountpoint
|
|
||||||
MKDIR=mkdir
|
|
||||||
TOUCH=touch
|
|
||||||
CUT=cut
|
|
||||||
SORT=sort
|
|
||||||
UNIQ=uniq
|
|
||||||
CAT=cat
|
|
||||||
READLINK=readlink
|
|
||||||
MOUNTS_FILE=/proc/self/mounts
|
|
||||||
|
|
||||||
NOT_EXISTING_FILE=103
|
|
||||||
NOT_ABSOLUTE_PATH=111
|
|
||||||
NO_ROOT_PRIVILEGES=110
|
|
||||||
|
|
||||||
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
|
||||||
|
|
||||||
|
|
||||||
################################ MAIN FUNCTIONS ###########################
|
|
||||||
|
|
||||||
function chroot_teardown() {
|
|
||||||
# Remove all mounts starting from the most nested ones.
|
|
||||||
# Suffix the CHROOTDIR with / to avoid umounting directories not belonging
|
|
||||||
# to CHROOTDIR.
|
|
||||||
local normalized_chrootdir="$($READLINK -f ${CHROOTDIR})/"
|
|
||||||
local final_res=0
|
|
||||||
for mp in $($CAT $MOUNTS_FILE | $CUT -f2 -d' ' | $SORT -r | $UNIQ)
|
|
||||||
do
|
|
||||||
if [[ $mp =~ ^${normalized_chrootdir}.* ]]
|
|
||||||
then
|
|
||||||
$UMOUNT $mp || final_res=$?
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
$UMOUNT ${CHROOTDIR%/}
|
|
||||||
|
|
||||||
return $final_res
|
|
||||||
}
|
|
||||||
|
|
||||||
function chroot_maybe_add_mount() {
|
|
||||||
local cond=$1
|
|
||||||
shift
|
|
||||||
if eval "$cond"; then
|
|
||||||
$MOUNT "$@"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function chroot_setup() {
|
|
||||||
$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
|
|
||||||
warn "Failed mount of directories. $CHROOTDIR is already a mountpoint. Skipping it..."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local re='(.*):(.*)'
|
|
||||||
for binds in ${BINDINGS[@]}
|
|
||||||
do
|
|
||||||
local host_path=""
|
|
||||||
local guest_path=""
|
|
||||||
if [[ $binds =~ $re ]]
|
|
||||||
then
|
|
||||||
local host_path="${BASH_REMATCH[1]}"
|
|
||||||
local guest_path="${BASH_REMATCH[2]}"
|
|
||||||
else
|
|
||||||
local host_path="$binds"
|
|
||||||
local guest_path="$binds"
|
|
||||||
fi
|
|
||||||
|
|
||||||
create_node "${host_path}" "${CHROOTDIR}${guest_path}"
|
|
||||||
mount_directory "${host_path}" "${guest_path}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function mount_directory() {
|
|
||||||
local host_path=$($READLINK -f "$1")
|
|
||||||
local guest_path="$2"
|
|
||||||
|
|
||||||
if ! $OPT_AVOID_BIND
|
|
||||||
then
|
|
||||||
$MOUNT $OPT_BIND "${host_path}" "${CHROOTDIR}${guest_path}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$host_path" in
|
|
||||||
/proc) $MOUNT proc "${CHROOTDIR}${guest_path}" -t proc ;;
|
|
||||||
/sys) $MOUNT sys "${CHROOTDIR}${guest_path}" -t sysfs ;;
|
|
||||||
/dev) $MOUNT udev "${CHROOTDIR}${guest_path}" -t devtmpfs; $MOUNT devpts "${guest_path}/pts" -t devpts; $MOUNT shm "${guest_path}/shm" -t tmpfs ;;
|
|
||||||
/run) $MOUNT run "${CHROOTDIR}${guest_path}" -t tmpfs ;;
|
|
||||||
/tmp) $MOUNT tmp "${CHROOTDIR}${guest_path}" -t tmpfs ;;
|
|
||||||
*) $MOUNT $OPT_BIND "${host_path}" "${CHROOTDIR}${guest_path}" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_node() {
|
|
||||||
local src="$1"
|
|
||||||
local dst="$2"
|
|
||||||
if [[ ! -e $src ]]
|
|
||||||
then
|
|
||||||
die_on_status $NOT_EXISTING_FILE "${src} does not exist."
|
|
||||||
elif [[ $src != /* ]]
|
|
||||||
then
|
|
||||||
die_on_status $NOT_ABSOLUTE_PATH "${src} is not an absolute path."
|
|
||||||
elif [[ -f $src ]]
|
|
||||||
then
|
|
||||||
$TOUCH "$dst"
|
|
||||||
elif [[ -d $src ]]
|
|
||||||
then
|
|
||||||
$MKDIR -p "$dst"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function usage() {
|
|
||||||
cat <<EOF
|
|
||||||
$NAME (v$(cat $JUNEST_BASE/VERSION)): $DESCRIPTION
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$CMD [options] [<chroot-dir> [command]]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-b, --bind <path>
|
|
||||||
Make the content of <path> accessible in the guest rootfs.
|
|
||||||
|
|
||||||
This option makes any file or directory of the host rootfs
|
|
||||||
accessible in the confined environment just as if it were part of
|
|
||||||
the guest rootfs. By default the host path is bound to the same
|
|
||||||
path in the guest rootfs but users can specify any other location
|
|
||||||
with the syntax: -b <host_path>:<guest_location>. This option can
|
|
||||||
be invoked multiple times and the paths specified must be absolutes.
|
|
||||||
|
|
||||||
-n, --no-umount
|
|
||||||
Do not umount after chroot session finished.
|
|
||||||
|
|
||||||
-r, --recursive
|
|
||||||
Use rbind instead of bind.
|
|
||||||
|
|
||||||
-i, --avoid-bind
|
|
||||||
Attempt to avoid mount --bind for common directories and use
|
|
||||||
proper mount fstype instead. Detected directories with
|
|
||||||
corresponding fstype are: /proc (proc), /sys (sysfs),
|
|
||||||
/dev (devtmpfs), /tmp (tmpfs), /run (tmpfs).
|
|
||||||
|
|
||||||
-h, --help Print this help message
|
|
||||||
|
|
||||||
-V, --version Show the $NAME version
|
|
||||||
|
|
||||||
If 'command' is unspecified, $CMD will launch $SHELL.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
version() {
|
|
||||||
echo -e "$NAME $(cat $JUNEST_BASE/VERSION)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse_arguments() {
|
|
||||||
BINDINGS=()
|
|
||||||
OPT_NO_UMOUNT=false
|
|
||||||
OPT_RECURSIVE=false
|
|
||||||
OPT_BIND="--bind"
|
|
||||||
OPT_AVOID_BIND=false
|
|
||||||
OPT_HELP=false
|
|
||||||
OPT_VERSION=false
|
|
||||||
for opt in "$@"
|
|
||||||
do
|
|
||||||
case "$1" in
|
|
||||||
-b|--bind) shift ; BINDINGS+=("$1") ; shift ;;
|
|
||||||
-n|--no-umount) OPT_NO_UMOUNT=true ; shift ;;
|
|
||||||
-r|--recursive) OPT_BIND="--rbind" ; shift ;;
|
|
||||||
-i|--avoid-bind) OPT_AVOID_BIND=true ; shift ;;
|
|
||||||
-h|--help) OPT_HELP=true ; shift ;;
|
|
||||||
-V|--version) OPT_VERSION=true ; shift ;;
|
|
||||||
-*) die "Invalid option $1" ;;
|
|
||||||
*) break ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ! -z $1 ]]
|
|
||||||
then
|
|
||||||
CHROOTDIR="$1"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
ARGS=()
|
|
||||||
for arg in "$@"
|
|
||||||
do
|
|
||||||
ARGS+=("$arg")
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_user_root() {
|
|
||||||
(( EUID == 0 ))
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_operation() {
|
|
||||||
$OPT_HELP && usage && return
|
|
||||||
$OPT_VERSION && version && return
|
|
||||||
|
|
||||||
is_user_root || die_on_status $NO_ROOT_PRIVILEGES 'This script must be run with root privileges'
|
|
||||||
|
|
||||||
[[ -d $CHROOTDIR ]] || die_on_status $NOT_EXISTING_FILE "Can't create chroot on non-directory $CHROOTDIR"
|
|
||||||
|
|
||||||
chroot_setup "$CHROOTDIR" || die "Failed to setup chroot $CHROOTDIR"
|
|
||||||
|
|
||||||
$CHROOTCMD "$CHROOTDIR" "${ARGS[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
parse_arguments "$@"
|
|
||||||
execute_operation
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
400
bin/junest
400
bin/junest
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
#
|
#
|
||||||
# This file is part of JuNest (https://github.com/fsquillace/junest).
|
# This file is part of JuNest (https://github.com/fsquillace/junest).
|
||||||
#
|
#
|
||||||
|
|
@ -7,154 +8,140 @@ set -e
|
||||||
|
|
||||||
# JUNEST_BASE can be overridden for testing purposes.
|
# JUNEST_BASE can be overridden for testing purposes.
|
||||||
# There is no need for doing it for normal usage.
|
# There is no need for doing it for normal usage.
|
||||||
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/..)}"
|
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f "$(dirname "$(readlink -f "$0")")"/..)}"
|
||||||
|
|
||||||
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
||||||
source "${JUNEST_BASE}/lib/core/common.sh"
|
source "${JUNEST_BASE}/lib/core/common.sh"
|
||||||
|
|
||||||
source "${JUNEST_BASE}/lib/core/build.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/chroot.sh"
|
||||||
source "${JUNEST_BASE}/lib/core/namespace.sh"
|
source "${JUNEST_BASE}/lib/core/namespace.sh"
|
||||||
source "${JUNEST_BASE}/lib/core/proot.sh"
|
source "${JUNEST_BASE}/lib/core/proot.sh"
|
||||||
source "${JUNEST_BASE}/lib/core/setup.sh"
|
source "${JUNEST_BASE}/lib/core/wrappers.sh"
|
||||||
|
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
### General functions ###
|
### General functions ###
|
||||||
###################################
|
###################################
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo -e "$NAME (v$(cat $JUNEST_BASE/VERSION)): $DESCRIPTION"
|
echo -e "$NAME (v$(cat "$JUNEST_BASE"/VERSION)): $DESCRIPTION"
|
||||||
echo
|
echo
|
||||||
echo -e "Usage: $CMD [options] [--] [command]"
|
echo -e "Usage: $CMD [action] [options] [--] [command]"
|
||||||
echo
|
echo
|
||||||
echo -e "Setup options:"
|
echo -e "General:"
|
||||||
echo -e "-i, --setup-from-file <image> Setup the $NAME image in ${JUNEST_HOME}"
|
echo -e "-h, --help Show this help message"
|
||||||
echo -e "-a, --arch <arch> $NAME architecture to download (x86_64, x86, arm)"
|
echo -e "-V, --version Show the $NAME version"
|
||||||
echo -e " Defaults to the host architecture ($ARCH)"
|
|
||||||
echo -e "-d, --delete Delete $NAME from ${JUNEST_HOME}"
|
|
||||||
echo
|
echo
|
||||||
echo -e "Access options:"
|
echo -e "Actions and options:"
|
||||||
echo -e "-f, --fakeroot Run $NAME with fakeroot privileges"
|
echo -e " s[etup] Setup $NAME in ${JUNEST_HOME} either from repo or from file"
|
||||||
echo -e "-g, --groot Run $NAME with root privileges via GRoot"
|
echo -e " -i, --from-file <image> Setup the $NAME image in ${JUNEST_HOME}"
|
||||||
echo -e "-r, --root Run $NAME with root privileges via classic chroot"
|
echo -e " -a, --arch <arch> $NAME architecture to download (x86_64, arm)"
|
||||||
echo -e "-u, --namespace Use Linux Namespace (with GRoot) instead of PRoot"
|
echo -e " Defaults to the host architecture ($ARCH)"
|
||||||
echo -e "-p, --backend-args <args> Arguments for backend program (PRoot or GRoot)"
|
echo -e " -d, --delete Delete $NAME from ${JUNEST_HOME}"
|
||||||
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
|
echo
|
||||||
echo -e "Building options:"
|
echo -e " n[s] Access via Linux Namespaces using BubbleWrap (Default action)"
|
||||||
echo -e "-b, --build-image Build a $NAME image (must run in ArchLinux)"
|
echo -e " -f, --fakeroot Run $NAME with fakeroot privileges"
|
||||||
echo -e "-n, --disable-validation Disable the $NAME image validation"
|
echo -e " --backend-command <cmd> Bwrap command to use"
|
||||||
|
echo -e " -b, --backend-args <args> Arguments for bwrap backend program"
|
||||||
|
echo -e " ($CMD ns -b \"--help\" to check out the bwrap 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 " --backend-command <cmd> PRoot command to use"
|
||||||
|
echo -e " -b, --backend-args <args> Arguments for PRoot backend program"
|
||||||
|
echo -e " ($CMD proot -b \"--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 " --backend-command <cmd> GRoot command to use"
|
||||||
|
echo -e " -b, --backend-args <args> Arguments for GRoot backend program"
|
||||||
|
echo -e " ($CMD groot -b \"--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 " --backend-command <cmd> Chroot command to use"
|
||||||
|
echo -e " -b, --backend-args <args> Arguments for chroot backend program"
|
||||||
|
echo -e " ($CMD root -b \"--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 " create-bin-wrappers Create a bin wrappers directory according to --bin-path option"
|
||||||
|
echo -e " Default path is $JUNEST_HOME/usr/bin_wrappers"
|
||||||
|
echo -e " -f, --force Create the wrapper files even if they already exist"
|
||||||
|
echo -e " -p, --bin-path The source directory where executable are located in JuNest"
|
||||||
|
echo -e " Default value is: /usr/bin"
|
||||||
echo
|
echo
|
||||||
echo -e "General options:"
|
|
||||||
echo -e "-h, --help Show this help message"
|
|
||||||
echo -e "-V, --version Show the $NAME version"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version() {
|
version() {
|
||||||
echo -e "$NAME $(cat $JUNEST_BASE/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
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function parse_arguments(){
|
function parse_arguments(){
|
||||||
OPT_SETUP_FROM_FILE=false
|
# Actions
|
||||||
IMAGE_FILE=""
|
ACT_SETUP=false
|
||||||
OPT_FAKEROOT=false
|
ACT_BUILD=false
|
||||||
OPT_ROOT=false
|
ACT_CREATE_WRAPPERS=false
|
||||||
OPT_GROOT=false
|
ACT_NAMESPACE=false
|
||||||
OPT_USER_NAMESPACE=false
|
ACT_PROOT=false
|
||||||
OPT_BACKEND_ARGS=false
|
ACT_GROOT=false
|
||||||
|
ACT_ROOT=false
|
||||||
|
ACT_HELP=false
|
||||||
|
ACT_VERSION=false
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
s|setup) ACT_SETUP=true ; shift ;;
|
||||||
|
b|build) ACT_BUILD=true ; shift ;;
|
||||||
|
create-bin-wrappers) ACT_CREATE_WRAPPERS=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_CREATE_WRAPPERS
|
||||||
|
then
|
||||||
|
_parse_create_wrappers_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_root_opts() {
|
||||||
|
# Options:
|
||||||
BACKEND_ARGS=""
|
BACKEND_ARGS=""
|
||||||
OPT_ARCH=false
|
OPT_NO_COPY_FILES=false
|
||||||
ARCH_ARG=""
|
BACKEND_COMMAND=""
|
||||||
OPT_BUILD_IMAGE=false
|
|
||||||
OPT_DISABLE_VALIDATION=false
|
while [[ -n "$1" ]]
|
||||||
CHECK_ARG=""
|
|
||||||
OPT_DELETE=false
|
|
||||||
OPT_HELP=false
|
|
||||||
OPT_VERSION=false
|
|
||||||
for opt in "$@"
|
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-i|--setup-from-file) OPT_SETUP_FROM_FILE=true ; shift ; IMAGE_FILE=$1 ; shift ;;
|
-b|--backend-args) shift ; BACKEND_ARGS=$1; shift ;;
|
||||||
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
|
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
|
||||||
-r|--root) OPT_ROOT=true ; shift ;;
|
--backend-command) shift; BACKEND_COMMAND="$1"; 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 ;;
|
--) shift ; break ;;
|
||||||
-*) die "Invalid option $1" ;;
|
-*) die "Invalid option $1" ;;
|
||||||
*) break ;;
|
*) break ;;
|
||||||
|
|
@ -168,53 +155,166 @@ function parse_arguments(){
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function execute_operation(){
|
function _parse_ns_opts() {
|
||||||
$OPT_HELP && usage && return
|
# Options:
|
||||||
$OPT_VERSION && version && return
|
OPT_FAKEROOT=false
|
||||||
|
BACKEND_ARGS=""
|
||||||
|
OPT_NO_COPY_FILES=false
|
||||||
|
BACKEND_COMMAND=""
|
||||||
|
|
||||||
if $OPT_BUILD_IMAGE; then
|
while [[ -n "$1" ]]
|
||||||
build_image_env $OPT_DISABLE_VALIDATION
|
do
|
||||||
return
|
case "$1" in
|
||||||
elif $OPT_DELETE; then
|
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
|
||||||
delete_env
|
-b|--backend-args) shift ; BACKEND_ARGS=$1; shift ;;
|
||||||
|
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
|
||||||
|
--backend-command) shift; BACKEND_COMMAND="$1"; 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
|
||||||
|
BACKEND_ARGS=""
|
||||||
|
OPT_NO_COPY_FILES=false
|
||||||
|
BACKEND_COMMAND=""
|
||||||
|
|
||||||
|
while [[ -n "$1" ]]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
|
||||||
|
-b|--backend-args) shift ; BACKEND_ARGS=$1; shift ;;
|
||||||
|
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
|
||||||
|
--backend-command) shift; BACKEND_COMMAND="$1"; shift ;;
|
||||||
|
--) shift ; break ;;
|
||||||
|
-*) die "Invalid option $1" ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
ARGS=("$@")
|
||||||
|
}
|
||||||
|
|
||||||
|
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_create_wrappers_opts() {
|
||||||
|
OPT_FORCE=false
|
||||||
|
OPT_BIN_PATH=""
|
||||||
|
while [[ -n "$1" ]]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-f|--force) OPT_FORCE=true ; shift ;;
|
||||||
|
-p|--bin-path) shift ; OPT_BIN_PATH="$1" ; shift ;;
|
||||||
|
*) die "Invalid option $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function _parse_setup_opts() {
|
||||||
|
OPT_FROM_FILE=false
|
||||||
|
IMAGE_FILE=""
|
||||||
|
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) 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
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
build_image_env $OPT_DISABLE_CHECK
|
||||||
return
|
return
|
||||||
fi
|
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
|
||||||
|
create_wrappers
|
||||||
|
fi
|
||||||
|
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if ! is_env_installed
|
if ! is_env_installed
|
||||||
then
|
then
|
||||||
if $OPT_SETUP_FROM_FILE; then
|
die "Error: The image is still not installed in $JUNEST_HOME. Run this first: $CMD setup"
|
||||||
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."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -z "${ARCH_ARG}" ] || \
|
if $ACT_CREATE_WRAPPERS; then
|
||||||
die "The option --arch cannot be specified since JuNest has already been downloaded in $JUNEST_HOME"
|
# shellcheck disable=SC2086
|
||||||
|
create_wrappers $OPT_FORCE "$OPT_BIN_PATH"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
local run_env
|
local run_env
|
||||||
if $OPT_USER_NAMESPACE; then
|
if $ACT_NAMESPACE; then
|
||||||
run_env=run_env_with_namespace
|
if $OPT_FAKEROOT; then
|
||||||
elif $OPT_FAKEROOT; then
|
run_env=run_env_as_bwrap_fakeroot
|
||||||
run_env=run_env_as_fakeroot
|
else
|
||||||
elif $OPT_ROOT; then
|
run_env=run_env_as_bwrap_user
|
||||||
run_env=run_env_as_chroot
|
fi
|
||||||
elif $OPT_GROOT; then
|
elif $ACT_PROOT; then
|
||||||
|
if $OPT_FAKEROOT; then
|
||||||
|
run_env=run_env_as_proot_fakeroot
|
||||||
|
else
|
||||||
|
run_env=run_env_as_proot_user
|
||||||
|
fi
|
||||||
|
elif $ACT_GROOT; then
|
||||||
run_env=run_env_as_groot
|
run_env=run_env_as_groot
|
||||||
else
|
elif $ACT_ROOT; then
|
||||||
run_env=run_env_as_user
|
run_env=run_env_as_chroot
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$run_env "${BACKEND_ARGS}" "${ARGS[@]}"
|
# Call create_wrappers in case new bin files have been created
|
||||||
|
# shellcheck disable=SC2064
|
||||||
|
trap "PATH=$PATH create_wrappers" EXIT QUIT TERM
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$run_env "$BACKEND_COMMAND" "${BACKEND_ARGS}" $OPT_NO_COPY_FILES "${ARGS[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
parse_arguments "$@"
|
parse_arguments "$@"
|
||||||
check_cli
|
|
||||||
execute_operation
|
execute_operation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
8
bin/sudoj
Executable file
8
bin/sudoj
Executable file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# This file is part of JuNest (https://github.com/fsquillace/junest).
|
||||||
|
#
|
||||||
|
|
||||||
|
export PATH="${PATH}:${JUNEST_HOME}/usr/bin_wrappers"
|
||||||
|
|
||||||
|
JUNEST_ARGS="ns --fakeroot" "$@"
|
||||||
15
ci/build_image.sh
Executable file
15
ci/build_image.sh
Executable file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
pacman -Sy --noconfirm sudo
|
||||||
|
|
||||||
|
# Create a travis user
|
||||||
|
echo "travis ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/travis
|
||||||
|
chmod 'u=r,g=r,o=' /etc/sudoers.d/travis
|
||||||
|
groupadd --gid "2000" "travis"
|
||||||
|
useradd --create-home --uid "2000" --gid "2000" --shell /usr/bin/false "travis"
|
||||||
|
|
||||||
|
# Here do not make any validation (-n) because it will be done later on in the Ubuntu host directly
|
||||||
|
cd /build
|
||||||
|
runuser -u travis -- /build/bin/junest build -n
|
||||||
48
ci/deploy.sh
Executable file
48
ci/deploy.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
IMG_PATH=$1
|
||||||
|
|
||||||
|
set -ux
|
||||||
|
|
||||||
|
MAX_OLD_IMAGES=5
|
||||||
|
ENDPOINT="https://8da1bcd84e423c9b013b69fe1e8b4675.r2.cloudflarestorage.com"
|
||||||
|
|
||||||
|
# ARCH can be one of: x86, x86_64, arm
|
||||||
|
HOST_ARCH=$(uname -m)
|
||||||
|
if [ "$HOST_ARCH" == "i686" ] || [ "$HOST_ARCH" == "i386" ]
|
||||||
|
then
|
||||||
|
ARCH="x86"
|
||||||
|
elif [ "$HOST_ARCH" == "x86_64" ]
|
||||||
|
then
|
||||||
|
ARCH="x86_64"
|
||||||
|
elif [[ $HOST_ARCH =~ .*(arm).* ]]
|
||||||
|
then
|
||||||
|
ARCH="arm"
|
||||||
|
else
|
||||||
|
echo "Unknown architecture ${HOST_ARCH}" >&2
|
||||||
|
exit 11
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$TRAVIS_BRANCH" == "master" ]]
|
||||||
|
then
|
||||||
|
|
||||||
|
export AWS_DEFAULT_REGION=auto
|
||||||
|
# Upload image
|
||||||
|
# The put is done via a temporary filename in order to prevent outage on the
|
||||||
|
# production file for a longer period of time.
|
||||||
|
img_name=$(basename "${IMG_PATH}")
|
||||||
|
aws s3 --endpoint-url="$ENDPOINT" cp "${IMG_PATH}" s3://junest-repo/junest/
|
||||||
|
|
||||||
|
DATE=$(date +'%Y-%m-%d-%H-%M-%S')
|
||||||
|
aws s3 --endpoint-url="$ENDPOINT" cp "${IMG_PATH}" "s3://junest-repo/junest/${img_name}.${DATE}"
|
||||||
|
|
||||||
|
# Cleanup old images
|
||||||
|
aws s3 --endpoint-url="$ENDPOINT" ls s3://junest-repo/junest/junest-${ARCH}.tar.gz. | awk '{print $4}' | head -n -${MAX_OLD_IMAGES} | xargs -I {} aws s3 --endpoint-url="$ENDPOINT" rm "s3://junest-repo/junest/{}"
|
||||||
|
|
||||||
|
# Test the newly deployed image can be downloaded correctly
|
||||||
|
junest setup
|
||||||
|
junest -- echo "Installed JuNest (\$(uname -m))"
|
||||||
|
yes | junest setup --delete
|
||||||
|
fi
|
||||||
13
ci/install-bash.sh
Executable file
13
ci/install-bash.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
wget "http://ftp.gnu.org/gnu/bash/bash-$VERSION.tar.gz"
|
||||||
|
|
||||||
|
tar -zxf "bash-$VERSION.tar.gz"
|
||||||
|
cd /tmp/bash-"$VERSION"*
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
#
|
#
|
||||||
# This modules is used for:
|
# This modules is used for:
|
||||||
# - Running checks against the building JuNest image
|
# - Running checks against the building JuNest image
|
||||||
|
|
@ -9,21 +10,32 @@
|
||||||
#
|
#
|
||||||
# vim: ft=sh
|
# vim: ft=sh
|
||||||
|
|
||||||
set -eu
|
set -ex
|
||||||
|
|
||||||
|
|
||||||
OPT_RUN_ROOT_TESTS=${1:-false}
|
|
||||||
RUN_ROOT_TESTS=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
|
SKIP_AUR_TESTS=false
|
||||||
[[ ${OPT_SKIP_AUR_TESTS} == "--skip-aur-tests" ]] && SKIP_AUR_TESTS=true
|
USE_SUDO=false
|
||||||
|
while [[ -n "$1" ]]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
--run-root-tests) RUN_ROOT_TESTS=true ; shift ;;
|
||||||
|
--skip-aur-tests) SKIP_AUR_TESTS=true ; shift ;;
|
||||||
|
--use-sudo) USE_SUDO=true ; shift ;;
|
||||||
|
*) die "Invalid option $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
SUDO=""
|
||||||
|
[[ -n $USE_SUDO ]] && SUDO="sudo"
|
||||||
|
|
||||||
JUNEST_HOME=${JUNEST_HOME:-$HOME/.junest}
|
JUNEST_HOME=${JUNEST_HOME:-$HOME/.junest}
|
||||||
|
|
||||||
# JUNEST_BASE can be overridden for testing purposes.
|
# JUNEST_BASE can be overridden for testing purposes.
|
||||||
# There is no need for doing it for normal usage.
|
# There is no need for doing it for normal usage.
|
||||||
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/../..)}"
|
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f "$(dirname "$(readlink -f "$0")")"/../..)}"
|
||||||
|
|
||||||
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
||||||
source "${JUNEST_BASE}/lib/core/common.sh"
|
source "${JUNEST_BASE}/lib/core/common.sh"
|
||||||
|
|
@ -31,32 +43,60 @@ source "${JUNEST_BASE}/lib/core/common.sh"
|
||||||
info "Validating JuNest located in ${JUNEST_HOME}..."
|
info "Validating JuNest located in ${JUNEST_HOME}..."
|
||||||
|
|
||||||
info "Initial JuNest setup..."
|
info "Initial JuNest setup..."
|
||||||
echo "Server = ${DEFAULT_MIRROR}" >> /etc/pacman.d/mirrorlist
|
# The following ensures that the gpg agent gets killed (if exists)
|
||||||
pacman --noconfirm -Syy
|
# otherwise it is not possible to exit from the session
|
||||||
pacman --noconfirm -S base-devel
|
trap "[[ -e /etc/pacman.d/gnupg/S.gpg-agent ]] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye" QUIT EXIT ABRT TERM INT
|
||||||
|
|
||||||
info "Checking essential executables work..."
|
prepare_archlinux "$SUDO"
|
||||||
pacman -Qi pacman 1> /dev/null
|
|
||||||
yogurt -V 1> /dev/null
|
PACMAN_OPTIONS="--noconfirm --disable-download-timeout"
|
||||||
/opt/proot/proot-$ARCH --help 1> /dev/null
|
# shellcheck disable=SC2086
|
||||||
|
$SUDO pacman $PACMAN_OPTIONS -S grep coreutils
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2046
|
||||||
|
$SUDO pacman $PACMAN_OPTIONS -Syu --ignore sudo base-devel
|
||||||
|
|
||||||
|
info "Checking basic executables work..."
|
||||||
|
$SUDO pacman -Qi pacman 1> /dev/null
|
||||||
|
/usr/bin/groot --help 1> /dev/null
|
||||||
|
|
||||||
|
# Test FAKEROOTDONTTRYCHOWN is set to true by default
|
||||||
|
set +u
|
||||||
|
if [[ -z $FAKEROOTKEY ]]
|
||||||
|
then
|
||||||
|
fakeroot chown root /tmp
|
||||||
|
else
|
||||||
|
chown root /tmp
|
||||||
|
fi
|
||||||
|
set -u
|
||||||
|
|
||||||
repo_package1=tree
|
repo_package1=tree
|
||||||
echo "Checking ${repo_package1} package from official repo..."
|
echo "Checking ${repo_package1} package from official repo..."
|
||||||
pacman --noconfirm -S ${repo_package1}
|
# shellcheck disable=SC2086
|
||||||
|
$SUDO pacman $PACMAN_OPTIONS -S ${repo_package1}
|
||||||
tree -L 1
|
tree -L 1
|
||||||
pacman --noconfirm -Rsn ${repo_package1}
|
# shellcheck disable=SC2086
|
||||||
|
$SUDO pacman $PACMAN_OPTIONS -Rsn ${repo_package1}
|
||||||
|
|
||||||
repo_package2=iftop
|
repo_package2=iftop
|
||||||
info "Checking ${repo_package2} package from official repo..."
|
info "Checking ${repo_package2} package from official repo..."
|
||||||
pacman --noconfirm -S ${repo_package2}
|
# shellcheck disable=SC2086
|
||||||
$RUN_ROOT_TESTS && iftop -t -s 5
|
$SUDO pacman $PACMAN_OPTIONS -S ${repo_package2}
|
||||||
pacman --noconfirm -Rsn ${repo_package2}
|
if $RUN_ROOT_TESTS
|
||||||
|
then
|
||||||
|
# Time it out given that sometimes it gets stuck after few seconds.
|
||||||
|
$SUDO timeout 10 iftop -t -s 5 || true
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$SUDO pacman $PACMAN_OPTIONS -Rsn ${repo_package2}
|
||||||
|
|
||||||
if ! $SKIP_AUR_TESTS
|
if ! $SKIP_AUR_TESTS
|
||||||
then
|
then
|
||||||
aur_package=tcptraceroute
|
aur_package=tcptraceroute
|
||||||
info "Checking ${aur_package} package from AUR repo..."
|
info "Checking ${aur_package} package from AUR repo..."
|
||||||
yogurt -A --noconfirm -S ${aur_package}
|
yay --noconfirm -S ${aur_package}
|
||||||
$RUN_ROOT_TESTS && tcptraceroute localhost
|
# shellcheck disable=SC2086
|
||||||
pacman --noconfirm -Rsn ${aur_package}
|
$SUDO pacman $PACMAN_OPTIONS -Rsn ${aur_package}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
|
||||||
31
lib/checks/check_all.sh
Executable file
31
lib/checks/check_all.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Multiple tests against different execution modes
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# 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")")"/../..)}"
|
||||||
|
|
||||||
|
JUNEST_SCRIPT=${JUNEST_SCRIPT:-${JUNEST_BASE}/bin/junest}
|
||||||
|
|
||||||
|
CHECK_SCRIPT=${JUNEST_BASE}/lib/checks/check.sh
|
||||||
|
|
||||||
|
$JUNEST_SCRIPT proot --fakeroot -- "$CHECK_SCRIPT" --skip-aur-tests
|
||||||
|
$JUNEST_SCRIPT proot -- "$CHECK_SCRIPT" --skip-aur-tests --use-sudo
|
||||||
|
# Test the backend command option
|
||||||
|
$JUNEST_SCRIPT proot --backend-command "$JUNEST_HOME/usr/bin/proot-x86_64" -- exit
|
||||||
|
$JUNEST_SCRIPT ns --fakeroot -- "$CHECK_SCRIPT" --skip-aur-tests
|
||||||
|
$JUNEST_SCRIPT ns -- "$CHECK_SCRIPT" --use-sudo
|
||||||
|
# Test the backend command option
|
||||||
|
$JUNEST_SCRIPT ns --backend-command "$JUNEST_HOME/usr/bin/bwrap" -- exit
|
||||||
|
sudo -E "$JUNEST_SCRIPT" groot -- "$CHECK_SCRIPT" --run-root-tests --skip-aur-tests
|
||||||
|
|
||||||
|
# Test the wrappers work
|
||||||
|
"$JUNEST_SCRIPT" create-bin-wrappers --force
|
||||||
|
"$JUNEST_HOME"/usr/bin_wrappers/pacman --help
|
||||||
|
|
||||||
|
"$JUNEST_SCRIPT" create-bin-wrappers --force --bin-path /usr/bin/core_perl/
|
||||||
|
"$JUNEST_HOME"/usr/bin/core_perl_wrappers/shasum --help
|
||||||
|
|
||||||
|
"${JUNEST_BASE}/bin/sudoj" pacman -Syu
|
||||||
|
|
@ -8,93 +8,134 @@
|
||||||
#
|
#
|
||||||
# vim: ft=sh
|
# vim: ft=sh
|
||||||
|
|
||||||
function _check_package(){
|
function _install_pkg(){
|
||||||
if ! pacman -Qq $1 > /dev/null
|
# This function allows to install packages from AUR.
|
||||||
then
|
# At the moment is not used.
|
||||||
die "Package $1 must be installed"
|
local maindir=$1
|
||||||
fi
|
local pkgbuilddir=$2
|
||||||
|
# Generate a working directory because sources will be downloaded to there
|
||||||
|
working_dir=$(TMPDIR=/tmp mktemp -d -t junest-wd.XXXXXXXXXX)
|
||||||
|
cp -R "$pkgbuilddir"/* "$working_dir"
|
||||||
|
builtin cd "${working_dir}" || return 1
|
||||||
|
makepkg -sfcd
|
||||||
|
makepkg --printsrcinfo > "${pkgbuilddir}"/.SRCINFO
|
||||||
|
sudo pacman --noconfirm --root "${maindir}"/root -U ./*.pkg.tar.*
|
||||||
}
|
}
|
||||||
|
|
||||||
function _install_from_aur(){
|
function _prepare() {
|
||||||
local maindir=$1
|
# ArchLinux System initialization
|
||||||
local pkgname=$2
|
prepare_archlinux
|
||||||
local installname=$3
|
# curl is used to download pacman.conf file
|
||||||
mkdir -p ${maindir}/packages/${pkgname}
|
sudo pacman -S --noconfirm git arch-install-scripts haveged curl
|
||||||
builtin cd ${maindir}/packages/${pkgname}
|
|
||||||
$CURL "https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=${pkgname}"
|
|
||||||
[ -z "${installname}" ] || $CURL "https://aur.archlinux.org/cgit/aur.git/plain/${installname}?h=${pkgname}"
|
|
||||||
makepkg -sfc
|
|
||||||
sudo pacman --noconfirm --root ${maindir}/root -U ${pkgname}*.pkg.tar.xz
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_image_env(){
|
function build_image_env(){
|
||||||
|
set -x
|
||||||
umask 022
|
umask 022
|
||||||
|
|
||||||
# The function must runs on ArchLinux with non-root privileges.
|
# The function must runs on ArchLinux with non-root privileges.
|
||||||
|
# This is because installing AUR packages can be done by normal users only.
|
||||||
(( EUID == 0 )) && \
|
(( EUID == 0 )) && \
|
||||||
die "You cannot build with root privileges."
|
die "You cannot build with root privileges."
|
||||||
|
|
||||||
_check_package arch-install-scripts
|
_prepare
|
||||||
_check_package gcc
|
|
||||||
_check_package package-query
|
|
||||||
_check_package git
|
|
||||||
|
|
||||||
local disable_validation=$1
|
local disable_validation=$1
|
||||||
|
|
||||||
local maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t ${CMD}.XXXXXXXXXX)
|
local maindir
|
||||||
sudo mkdir -p ${maindir}/root
|
maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t "${CMD}".XXXXXXXXXX)
|
||||||
trap - QUIT EXIT ABRT KILL TERM INT
|
sudo mkdir -p "${maindir}"/root
|
||||||
trap "sudo rm -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT KILL TERM INT
|
trap - QUIT EXIT ABRT TERM INT
|
||||||
|
# shellcheck disable=SC2064
|
||||||
|
trap "sudo rm -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT TERM INT
|
||||||
info "Installing pacman and its dependencies..."
|
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
|
# All the essential executables (ln, mkdir, chown, etc) are in coreutils
|
||||||
# yaourt requires sed
|
# bwrap command belongs to bubblewrap
|
||||||
# localedef (called by locale-gen) requires gzip
|
sudo pacstrap -G -M "${maindir}"/root pacman coreutils bubblewrap
|
||||||
# unshare command belongs to util-linux
|
|
||||||
sudo pacstrap -G -M -d ${maindir}/root pacman coreutils libunistring archlinux-keyring sed gzip 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
|
if [[ ${ARCH} != "arm" ]]
|
||||||
info "Compiling and installing yaourt..."
|
then
|
||||||
_install_from_aur ${maindir} "package-query"
|
# x86_64 does not have any mirror set by default...
|
||||||
_install_from_aur ${maindir} "yaourt"
|
sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist"
|
||||||
|
fi
|
||||||
|
sudo mkdir -p "${maindir}"/root/run/lock
|
||||||
|
|
||||||
info "Install ${NAME} script..."
|
# For some reasons, pacstrap does not create the pacman.conf file,
|
||||||
sudo pacman --noconfirm --root ${maindir}/root -S git
|
# I could not reproduce the issue locally though:
|
||||||
_install_from_aur ${maindir} "${CMD}-git" "${CMD}.install"
|
# https://app.travis-ci.com/github/fsquillace/junest/builds/268216346
|
||||||
sudo pacman --noconfirm --root ${maindir}/root -Rsn git
|
[[ -e "${maindir}"/root/etc/pacman.conf ]] || sudo curl "https://gitlab.archlinux.org/archlinux/packaging/packages/pacman/-/raw/main/pacman.conf" -o "${maindir}/root/etc/pacman.conf"
|
||||||
|
|
||||||
|
# Pacman/pacstrap bug: https://gitlab.archlinux.org/archlinux/packaging/packages/arch-install-scripts/-/issues/3
|
||||||
|
sudo sed -i '/^DownloadUser = alpm$/d' "${maindir}"/root/etc/pacman.conf
|
||||||
|
|
||||||
|
sudo tee -a "${maindir}"/root/etc/pacman.conf <<EOT
|
||||||
|
|
||||||
|
[junest]
|
||||||
|
SigLevel = Optional TrustedOnly
|
||||||
|
Server = https://raw.githubusercontent.com/fsquillace/junest-repo/master/any
|
||||||
|
EOT
|
||||||
|
info "pacman.conf being used:"
|
||||||
|
cat "${maindir}"/root/etc/pacman.conf
|
||||||
|
sudo pacman --noconfirm --config "${maindir}"/root/etc/pacman.conf --root "${maindir}"/root -Sy sudo-fake groot-git proot-static qemu-user-static-bin-alt yay-git
|
||||||
|
|
||||||
|
echo "Generating the metadata info"
|
||||||
|
sudo install -d -m 755 "${maindir}/root/etc/${CMD}"
|
||||||
|
sudo bash -c "echo 'JUNEST_ARCH=$ARCH' > ${maindir}/root/etc/${CMD}/info"
|
||||||
|
# Related to: https://github.com/fsquillace/junest/issues/305
|
||||||
|
sudo bash -c "echo 'export FAKEROOTDONTTRYCHOWN=true' > ${maindir}/root/etc/profile.d/junest.sh"
|
||||||
|
|
||||||
info "Generating the locales..."
|
info "Generating the locales..."
|
||||||
# sed command is required for locale-gen
|
# sed command is required for locale-gen but it is required by fakeroot
|
||||||
sudo ln -sf /usr/share/zoneinfo/posix/UTC ${maindir}/root/etc/localtime
|
# and cannot be removed
|
||||||
|
# localedef (called by locale-gen) requires gzip but it is supposed to be
|
||||||
|
# already installed as systemd already depends on it
|
||||||
|
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 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 "${maindir}"/root/bin/groot "${maindir}"/root locale-gen
|
||||||
sudo bash -c "echo LANG=\"en_US.UTF-8\" >> ${maindir}/root/etc/locale.conf"
|
sudo bash -c "echo LANG=\"en_US.UTF-8\" >> ${maindir}/root/etc/locale.conf"
|
||||||
|
|
||||||
info "Setting up the pacman keyring (this might take a while!)..."
|
info "Setting up the pacman keyring (this might take a while!)..."
|
||||||
sudo ${maindir}/root/opt/junest/bin/groot -b /dev ${maindir}/root bash -c \
|
if [[ $(uname -m) == *"arm"* ]]
|
||||||
"pacman-key --init; pacman-key --populate archlinux; [ -e /etc/pacman.d/gnupg/S.gpg-agent ] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye"
|
then
|
||||||
|
sudo pacman -S --noconfirm --root "${maindir}"/root archlinuxarm-keyring
|
||||||
|
else
|
||||||
|
sudo pacman -S --noconfirm --root "${maindir}"/root archlinux-keyring
|
||||||
|
fi
|
||||||
|
sudo mount --bind "${maindir}"/root "${maindir}"/root
|
||||||
|
sudo arch-chroot "${maindir}"/root bash -c '
|
||||||
|
set -e
|
||||||
|
pacman-key --init;
|
||||||
|
for keyring_file in /usr/share/pacman/keyrings/*.gpg;
|
||||||
|
do
|
||||||
|
keyring=$(basename $keyring_file | cut -f 1 -d ".");
|
||||||
|
pacman-key --populate $keyring;
|
||||||
|
done;'
|
||||||
|
sudo umount "${maindir}"/root
|
||||||
|
|
||||||
sudo rm ${maindir}/root/var/cache/pacman/pkg/*
|
sudo rm "${maindir}"/root/var/cache/pacman/pkg/*
|
||||||
|
# This is needed on system with busybox tar command.
|
||||||
|
# If the file does not have write permission, the tar command to extract files fails.
|
||||||
|
sudo chmod -R u+rw "${maindir}"/root/
|
||||||
|
|
||||||
mkdir -p ${maindir}/output
|
mkdir -p "${maindir}"/output
|
||||||
builtin cd ${maindir}/output
|
builtin cd "${maindir}"/output || return 1
|
||||||
local imagefile="${CMD}-${ARCH}.tar.gz"
|
local imagefile="${CMD}-${ARCH}.tar.gz"
|
||||||
info "Compressing image to ${imagefile}..."
|
info "Compressing image to ${imagefile}..."
|
||||||
sudo $TAR -zcpf ${imagefile} -C ${maindir}/root .
|
sudo "$TAR" -zcpf "${imagefile}" -C "${maindir}"/root .
|
||||||
|
|
||||||
if ! $disable_validation
|
if ! $disable_validation
|
||||||
then
|
then
|
||||||
mkdir -p ${maindir}/root_test
|
mkdir -p "${maindir}"/root_test
|
||||||
$TAR -zxpf ${imagefile} -C "${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" "${JUNEST_BASE}"/lib/checks/check_all.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
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo cp ${maindir}/output/${imagefile} ${ORIGIN_WD}
|
sudo cp "${maindir}"/output/"${imagefile}" "${ORIGIN_WD}"
|
||||||
|
|
||||||
builtin cd ${ORIGIN_WD}
|
builtin cd "${ORIGIN_WD}" || return 1
|
||||||
trap - QUIT EXIT ABRT KILL TERM INT
|
trap - QUIT EXIT ABRT KILL TERM INT
|
||||||
sudo rm -fr "$maindir"
|
sudo rm -fr "$maindir"
|
||||||
|
|
||||||
|
set +x
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,26 +11,30 @@
|
||||||
function _run_env_as_xroot(){
|
function _run_env_as_xroot(){
|
||||||
local cmd=$1
|
local cmd=$1
|
||||||
local backend_args="$2"
|
local backend_args="$2"
|
||||||
shift 2
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
check_same_arch
|
check_same_arch
|
||||||
|
|
||||||
local uid=$UID
|
local uid=$UID
|
||||||
# SUDO_USER is more reliable compared to SUDO_UID
|
# SUDO_USER is more reliable compared to SUDO_UID
|
||||||
[ -z $SUDO_USER ] || uid=$SUDO_USER:$SUDO_GID
|
[[ -z $SUDO_USER ]] || uid=$SUDO_USER:$SUDO_GID
|
||||||
|
|
||||||
local main_cmd="${SH[@]}"
|
local args=()
|
||||||
[ "$1" != "" ] && main_cmd="$(insert_quotes_on_spaces "$@")"
|
[[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")")
|
||||||
|
|
||||||
# With chown the ownership of the files is assigned to the real user
|
# With chown the ownership of the files is assigned to the real user
|
||||||
trap - QUIT EXIT ABRT KILL TERM INT
|
trap - QUIT EXIT ABRT KILL TERM INT
|
||||||
trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT KILL TERM INT
|
# shellcheck disable=SC2064
|
||||||
|
trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT TERM INT
|
||||||
|
|
||||||
copy_common_files
|
if ! $no_copy_files
|
||||||
|
then
|
||||||
|
copy_common_files
|
||||||
|
fi
|
||||||
|
|
||||||
check_nested_env
|
# shellcheck disable=SC2086
|
||||||
|
JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${DEFAULT_SH[@]}" "${args[@]}"
|
||||||
JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "${main_cmd}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -41,25 +45,31 @@ function _run_env_as_xroot(){
|
||||||
# UID (RO) : The user ID.
|
# UID (RO) : The user ID.
|
||||||
# SUDO_USER (RO) : The sudo user ID.
|
# SUDO_USER (RO) : The sudo user ID.
|
||||||
# SUDO_GID (RO) : The sudo group ID.
|
# SUDO_GID (RO) : The sudo group ID.
|
||||||
# SH (RO) : Contains the default command to run in JuNest.
|
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# backend_args ($1) : The arguments to pass to proot
|
# backend_args ($1) : The arguments to pass to backend program
|
||||||
# cmd ($2-?) : The command to run inside JuNest environment.
|
# no_copy_files ($2?) : If false it will copy some files in /etc
|
||||||
# Default command is defined by SH variable.
|
# from host to JuNest environment.
|
||||||
|
# cmd ($3-?) : The command to run inside JuNest environment.
|
||||||
|
# Default command is defined by DEFAULT_SH variable.
|
||||||
# Returns:
|
# Returns:
|
||||||
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
||||||
# Output:
|
# Output:
|
||||||
# - : The command output.
|
# - : The command output.
|
||||||
#######################################
|
#######################################
|
||||||
function run_env_as_groot(){
|
function run_env_as_groot(){
|
||||||
local backend_args="$1"
|
check_nested_env
|
||||||
shift
|
|
||||||
|
local backend_command="${1:-$GROOT}"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
provide_common_bindings
|
provide_common_bindings
|
||||||
local bindings=${RESULT}
|
local bindings=${RESULT}
|
||||||
unset RESULT
|
unset RESULT
|
||||||
|
|
||||||
_run_env_as_xroot "$GROOT $bindings" "$backend_args" "$@"
|
_run_env_as_xroot "$backend_command $bindings" "$backend_args" "$no_copy_files" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -70,19 +80,25 @@ function run_env_as_groot(){
|
||||||
# UID (RO) : The user ID.
|
# UID (RO) : The user ID.
|
||||||
# SUDO_USER (RO) : The sudo user ID.
|
# SUDO_USER (RO) : The sudo user ID.
|
||||||
# SUDO_GID (RO) : The sudo group ID.
|
# SUDO_GID (RO) : The sudo group ID.
|
||||||
# SH (RO) : Contains the default command to run in JuNest.
|
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# backend_args ($1) : The arguments to pass to proot
|
# backend_args ($1) : The arguments to pass to backend program
|
||||||
# cmd ($2-?) : The command to run inside JuNest environment.
|
# no_copy_files ($2?) : If false it will copy some files in /etc
|
||||||
# Default command is defined by SH variable.
|
# from host to JuNest environment.
|
||||||
|
# cmd ($3-?) : The command to run inside JuNest environment.
|
||||||
|
# Default command is defined by DEFAULT_SH variable.
|
||||||
# Returns:
|
# Returns:
|
||||||
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
||||||
# Output:
|
# Output:
|
||||||
# - : The command output.
|
# - : The command output.
|
||||||
#######################################
|
#######################################
|
||||||
function run_env_as_chroot(){
|
function run_env_as_chroot(){
|
||||||
local backend_args="$1"
|
check_nested_env
|
||||||
shift
|
|
||||||
|
|
||||||
_run_env_as_xroot chroot_cmd "$backend_args" "$@"
|
local backend_command="${1:-chroot_cmd}"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
|
_run_env_as_xroot "$backend_command" "$backend_args" "$no_copy_files" "$@"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
# shellcheck disable=SC1091
|
||||||
#
|
#
|
||||||
# This module contains all common functionalities for JuNest.
|
# This module contains all common functionalities for JuNest.
|
||||||
#
|
#
|
||||||
|
|
@ -18,30 +20,32 @@ ROOT_ACCESS_ERROR=105
|
||||||
NESTED_ENVIRONMENT=106
|
NESTED_ENVIRONMENT=106
|
||||||
VARIABLE_NOT_SET=107
|
VARIABLE_NOT_SET=107
|
||||||
NO_CONFIG_FOUND=108
|
NO_CONFIG_FOUND=108
|
||||||
|
UNPRIVILEGED_USERNS_DISABLED=109
|
||||||
|
|
||||||
JUNEST_HOME=${JUNEST_HOME:-~/.${CMD}}
|
JUNEST_HOME=${JUNEST_HOME:-~/.${CMD}}
|
||||||
JUNEST_BASE=${JUNEST_BASE:-${JUNEST_HOME}/opt/junest}
|
|
||||||
JUNEST_TEMPDIR=${JUNEST_TEMPDIR:-/tmp}
|
JUNEST_TEMPDIR=${JUNEST_TEMPDIR:-/tmp}
|
||||||
|
|
||||||
# The update of the variable PATH ensures that the executables are
|
# The update of the variable PATH ensures that the executables are
|
||||||
# found on different locations
|
# found on different locations
|
||||||
PATH=/usr/bin:/bin:/usr/sbin:/sbin:$PATH
|
PATH=/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin:${HOME}/.local/bin:"$PATH"
|
||||||
|
|
||||||
# The executable uname is essential in order to get the architecture
|
# The executable uname is essential in order to get the architecture
|
||||||
# of the host system, so a fallback mechanism cannot be used for it.
|
# of the host system, so a fallback mechanism cannot be used for it.
|
||||||
UNAME=uname
|
UNAME="uname"
|
||||||
|
|
||||||
ARCH_LIST=('x86_64' 'x86' 'arm')
|
ARCH_LIST=('x86_64' 'x86' 'arm')
|
||||||
HOST_ARCH=$($UNAME -m)
|
HOST_ARCH=$($UNAME -m)
|
||||||
if [ $HOST_ARCH == "i686" ] || [ $HOST_ARCH == "i386" ]
|
# To check all available architectures look here:
|
||||||
|
# https://wiki.archlinux.org/index.php/PKGBUILD#arch
|
||||||
|
if [[ $HOST_ARCH == "i686" ]] || [[ $HOST_ARCH == "i386" ]]
|
||||||
then
|
then
|
||||||
ARCH="x86"
|
ARCH="x86"
|
||||||
LD_LIB="${JUNEST_HOME}/lib/ld-linux.so.2"
|
LD_LIB="${JUNEST_HOME}/lib/ld-linux.so.2"
|
||||||
elif [ $HOST_ARCH == "x86_64" ]
|
elif [[ $HOST_ARCH == "x86_64" ]]
|
||||||
then
|
then
|
||||||
ARCH="x86_64"
|
ARCH="x86_64"
|
||||||
LD_LIB="${JUNEST_HOME}/lib64/ld-linux-x86-64.so.2"
|
LD_LIB="${JUNEST_HOME}/lib64/ld-linux-x86-64.so.2"
|
||||||
elif [[ $HOST_ARCH =~ .*(arm).* ]]
|
elif [[ $HOST_ARCH =~ .*(arm).* ]] || [[ $HOST_ARCH == "aarch64" ]]
|
||||||
then
|
then
|
||||||
ARCH="arm"
|
ARCH="arm"
|
||||||
LD_LIB="${JUNEST_HOME}/lib/ld-linux-armhf.so.3"
|
LD_LIB="${JUNEST_HOME}/lib/ld-linux-armhf.so.3"
|
||||||
|
|
@ -49,9 +53,11 @@ else
|
||||||
die "Unknown architecture ${HOST_ARCH}"
|
die "Unknown architecture ${HOST_ARCH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MAIN_REPO=https://s3-eu-west-1.amazonaws.com/${CMD}-repo
|
MAIN_REPO=https://link.storjshare.io/s/jvb5tgarnjtt565fffa44spvyuga/junest-repo
|
||||||
|
MAIN_REPO=https://pub-a2af2344e8554f6c807bc3db355ae622.r2.dev
|
||||||
ENV_REPO=${MAIN_REPO}/${CMD}
|
ENV_REPO=${MAIN_REPO}/${CMD}
|
||||||
DEFAULT_MIRROR='https://mirrors.kernel.org/archlinux/$repo/os/$arch'
|
# shellcheck disable=SC2016
|
||||||
|
DEFAULT_MIRROR='https://mirror.rackspace.com/archlinux/$repo/os/$arch'
|
||||||
|
|
||||||
ORIGIN_WD=$(pwd)
|
ORIGIN_WD=$(pwd)
|
||||||
|
|
||||||
|
|
@ -62,24 +68,26 @@ ORIGIN_WD=$(pwd)
|
||||||
# different locations in the host OS.
|
# different locations in the host OS.
|
||||||
|
|
||||||
# List of executables that are run inside JuNest:
|
# List of executables that are run inside JuNest:
|
||||||
SH=("/bin/sh" "--login")
|
DEFAULT_SH=("/bin/sh" "--login")
|
||||||
|
|
||||||
# List of executables that are run in the host OS:
|
# List of executables that are run in the host OS:
|
||||||
PROOT="${JUNEST_HOME}/opt/proot/proot-${ARCH}"
|
BWRAP="${JUNEST_HOME}/usr/bin/bwrap"
|
||||||
GROOT=${JUNEST_BASE}/bin/groot
|
PROOT="${JUNEST_HOME}/usr/bin/proot-${ARCH}"
|
||||||
|
GROOT="${JUNEST_HOME}/usr/bin/groot"
|
||||||
CLASSIC_CHROOT=chroot
|
CLASSIC_CHROOT=chroot
|
||||||
WGET="wget --no-check-certificate"
|
WGET="wget --content-disposition --no-check-certificate"
|
||||||
CURL="curl -L -J -O -k"
|
CURL="curl -L -J -O -k"
|
||||||
TAR=tar
|
TAR="tar"
|
||||||
CHOWN="chown"
|
CHOWN="chown"
|
||||||
LN=ln
|
LN="ln"
|
||||||
RM=rm
|
RM="rm"
|
||||||
MKDIR=mkdir
|
MKDIR="mkdir"
|
||||||
GETENT=getent
|
GETENT="getent"
|
||||||
CP=cp
|
CP="cp"
|
||||||
|
ID="id"
|
||||||
# Used for checking user namespace in config.gz file
|
# Used for checking user namespace in config.gz file
|
||||||
ZGREP=zgrep
|
ZGREP="zgrep"
|
||||||
UNSHARE=unshare
|
UNSHARE="unshare"
|
||||||
|
|
||||||
LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
|
LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
|
||||||
|
|
||||||
|
|
@ -88,32 +96,32 @@ LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
|
||||||
# image.
|
# image.
|
||||||
|
|
||||||
function ln_cmd(){
|
function ln_cmd(){
|
||||||
$LN "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$LN "$@"
|
$LN "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$LN "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function getent_cmd(){
|
function getent_cmd(){
|
||||||
$GETENT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$GETENT "$@"
|
$GETENT "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$GETENT "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cp_cmd(){
|
function cp_cmd(){
|
||||||
$CP "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CP "$@"
|
$CP "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CP "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function rm_cmd(){
|
function rm_cmd(){
|
||||||
$RM "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$RM "$@"
|
$RM "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$RM "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function chown_cmd(){
|
function chown_cmd(){
|
||||||
$CHOWN "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CHOWN "$@"
|
$CHOWN "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CHOWN "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkdir_cmd(){
|
function mkdir_cmd(){
|
||||||
$MKDIR "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$MKDIR "$@"
|
$MKDIR "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$MKDIR "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function zgrep_cmd(){
|
function zgrep_cmd(){
|
||||||
# No need for LD_EXEC as zgrep is a POSIX shell script
|
# 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(){
|
function download_cmd(){
|
||||||
|
|
@ -121,7 +129,7 @@ function download_cmd(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function chroot_cmd(){
|
function chroot_cmd(){
|
||||||
$CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CLASSIC_CHROOT "$@"
|
$CLASSIC_CHROOT "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CLASSIC_CHROOT "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function unshare_cmd(){
|
function unshare_cmd(){
|
||||||
|
|
@ -129,27 +137,40 @@ function unshare_cmd(){
|
||||||
# with --user option available.
|
# with --user option available.
|
||||||
# Hence, give priority to the `unshare` executable in JuNest image.
|
# Hence, give priority to the `unshare` executable in JuNest image.
|
||||||
# Also, unshare provides an environment in which /bin/sh maps to dash shell,
|
# Also, unshare provides an environment in which /bin/sh maps to dash shell,
|
||||||
# therefore it ignores all the remaining SH arguments (i.e. --login) as
|
# therefore it ignores all the remaining DEFAULT_SH arguments (i.e. --login) as
|
||||||
# they are not supported by dash.
|
# they are not supported by dash.
|
||||||
if $LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE --user "${SH[0]}" "-c" ":"
|
if $LD_EXEC "${JUNEST_HOME}"/usr/bin/$UNSHARE --user "${DEFAULT_SH[0]}" "-c" ":"
|
||||||
then
|
then
|
||||||
$LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE "${@}"
|
$LD_EXEC "${JUNEST_HOME}"/usr/bin/$UNSHARE "${@}"
|
||||||
elif $UNSHARE --user "${SH[0]}" "-c" ":"
|
elif $UNSHARE --user "${DEFAULT_SH[0]}" "-c" ":"
|
||||||
then
|
then
|
||||||
$UNSHARE "$@"
|
$UNSHARE "$@"
|
||||||
else
|
else
|
||||||
die "Error: Something went wrong with unshare command. Exiting"
|
die "Error: Something went wrong while executing unshare command. Exiting"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function bwrap_cmd(){
|
||||||
|
if $LD_EXEC "$BWRAP" --dev-bind / / "${DEFAULT_SH[0]}" "-c" ":"
|
||||||
|
then
|
||||||
|
$LD_EXEC "$BWRAP" "${@}"
|
||||||
|
else
|
||||||
|
die "Error: Something went wrong while executing bwrap command. Exiting"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function proot_cmd(){
|
function proot_cmd(){
|
||||||
local proot_args="$1"
|
local proot_args="$1"
|
||||||
shift
|
shift
|
||||||
if ${PROOT} ${proot_args} "${SH[@]}" "-c" ":"
|
# shellcheck disable=SC2086
|
||||||
|
if ${PROOT} ${proot_args} "${DEFAULT_SH[@]}" "-c" ":"
|
||||||
then
|
then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
${PROOT} ${proot_args} "${@}"
|
${PROOT} ${proot_args} "${@}"
|
||||||
elif PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${SH[@]}" "-c" ":"
|
elif PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${DEFAULT_SH[@]}" "-c" ":"
|
||||||
then
|
then
|
||||||
|
warn "Warn: Proot is not properly working. Disabling SECCOMP and expect the application to run slowly in particular when it uses syscalls intensively."
|
||||||
|
warn "Try to use Linux namespace instead as it is more reliable: junest ns"
|
||||||
PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${@}"
|
PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${@}"
|
||||||
else
|
else
|
||||||
die "Error: Something went wrong with proot command. Exiting"
|
die "Error: Something went wrong with proot command. Exiting"
|
||||||
|
|
@ -178,7 +199,7 @@ function check_nested_env() {
|
||||||
if [[ $JUNEST_ENV == "1" ]]
|
if [[ $JUNEST_ENV == "1" ]]
|
||||||
then
|
then
|
||||||
die_on_status $NESTED_ENVIRONMENT "Error: Nested ${NAME} environments are not allowed"
|
die_on_status $NESTED_ENVIRONMENT "Error: Nested ${NAME} environments are not allowed"
|
||||||
elif [[ ! -z $JUNEST_ENV ]] && [[ $JUNEST_ENV != "0" ]]
|
elif [[ -n $JUNEST_ENV ]] && [[ $JUNEST_ENV != "0" ]]
|
||||||
then
|
then
|
||||||
die_on_status $VARIABLE_NOT_SET "The variable JUNEST_ENV is not properly set"
|
die_on_status $VARIABLE_NOT_SET "The variable JUNEST_ENV is not properly set"
|
||||||
fi
|
fi
|
||||||
|
|
@ -200,7 +221,7 @@ function check_nested_env() {
|
||||||
# None
|
# None
|
||||||
#######################################
|
#######################################
|
||||||
function check_same_arch() {
|
function check_same_arch() {
|
||||||
source ${JUNEST_HOME}/etc/junest/info
|
source "${JUNEST_HOME}"/etc/junest/info
|
||||||
[ "$JUNEST_ARCH" != "$ARCH" ] && \
|
[ "$JUNEST_ARCH" != "$ARCH" ] && \
|
||||||
die_on_status $ARCHITECTURE_MISMATCH "The host system architecture is not correct: $ARCH != $JUNEST_ARCH"
|
die_on_status $ARCHITECTURE_MISMATCH "The host system architecture is not correct: $ARCH != $JUNEST_ARCH"
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -225,7 +246,7 @@ function check_same_arch() {
|
||||||
function provide_common_bindings(){
|
function provide_common_bindings(){
|
||||||
RESULT=""
|
RESULT=""
|
||||||
local re='(.*):.*'
|
local re='(.*):.*'
|
||||||
for bind in "/dev" "/sys" "/proc" "/tmp" "$HOME"
|
for bind in "/dev" "/sys" "/proc" "/tmp" "$HOME" "/run/user/$($ID -u)"
|
||||||
do
|
do
|
||||||
if [[ $bind =~ $re ]]
|
if [[ $bind =~ $re ]]
|
||||||
then
|
then
|
||||||
|
|
@ -258,24 +279,26 @@ function copy_passwd_and_group(){
|
||||||
# is configured.
|
# is configured.
|
||||||
# Try to at least get the current user via `getent passwd $USER` since it uses
|
# Try to at least get the current user via `getent passwd $USER` since it uses
|
||||||
# a more reliable and faster system call (getpwnam(3)).
|
# a more reliable and faster system call (getpwnam(3)).
|
||||||
if ! getent_cmd passwd > ${JUNEST_HOME}/etc/passwd || \
|
if ! getent_cmd passwd > "${JUNEST_HOME}"/etc/passwd || \
|
||||||
! getent_cmd passwd ${USER} >> ${JUNEST_HOME}/etc/passwd
|
! getent_cmd passwd "${USER}" >> "${JUNEST_HOME}"/etc/passwd
|
||||||
then
|
then
|
||||||
warn "getent command failed or does not exist. Binding directly from /etc/passwd."
|
warn "getent command failed or does not exist. Binding directly from /etc/passwd."
|
||||||
copy_file /etc/passwd ${JUNEST_HOME}/etc/passwd
|
copy_file /etc/passwd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! getent_cmd group > ${JUNEST_HOME}/etc/group
|
if ! getent_cmd group > "${JUNEST_HOME}"/etc/group
|
||||||
then
|
then
|
||||||
warn "getent command failed or does not exist. Binding directly from /etc/group."
|
warn "getent command failed or does not exist. Binding directly from /etc/group."
|
||||||
copy_file /etc/group ${JUNEST_HOME}/etc/group
|
copy_file /etc/group
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function copy_file() {
|
function copy_file() {
|
||||||
local file="${1}"
|
local file="${1}"
|
||||||
[[ -r "$file" ]] && cp_cmd "$file" "${JUNEST_HOME}/$file"
|
# -f option ensure to remove destination file if it cannot be opened
|
||||||
|
# https://github.com/fsquillace/junest/issues/284
|
||||||
|
[[ -r "$file" ]] && cp_cmd -f "$file" "${JUNEST_HOME}/$file"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,3 +309,27 @@ function copy_common_files() {
|
||||||
copy_file /etc/resolv.conf
|
copy_file /etc/resolv.conf
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prepare_archlinux() {
|
||||||
|
local sudo=${1:-sudo}
|
||||||
|
local pacman_options="--noconfirm --disable-download-timeout"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$sudo pacman $pacman_options -Syy
|
||||||
|
|
||||||
|
$sudo pacman-key --init
|
||||||
|
|
||||||
|
if [[ $(uname -m) == *"arm"* ]]
|
||||||
|
then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$sudo pacman $pacman_options -S archlinuxarm-keyring
|
||||||
|
$sudo pacman-key --populate archlinuxarm
|
||||||
|
else
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$sudo pacman $pacman_options -S archlinux-keyring
|
||||||
|
$sudo pacman-key --populate archlinux
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$sudo pacman $pacman_options -Su
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# This module contains all namespace functionalities for JuNest.
|
# This module contains functionalities for accessing to JuNest via bubblewrap.
|
||||||
#
|
#
|
||||||
# http://man7.org/linux/man-pages/man7/namespaces.7.html
|
# https://github.com/containers/bubblewrap
|
||||||
# http://man7.org/linux/man-pages/man2/unshare.2.html
|
|
||||||
#
|
#
|
||||||
# Dependencies:
|
# Dependencies:
|
||||||
# - lib/utils/utils.sh
|
# - lib/utils/utils.sh
|
||||||
|
|
@ -11,10 +10,29 @@
|
||||||
#
|
#
|
||||||
# vim: ft=sh
|
# vim: ft=sh
|
||||||
|
|
||||||
|
# shellcheck disable=SC2027
|
||||||
|
COMMON_BWRAP_OPTION="--bind "$JUNEST_HOME" / --bind "$HOME" "$HOME" --bind /tmp /tmp --bind /sys /sys --bind /proc /proc --dev-bind-try /dev /dev --bind-try "/run/user/$($ID -u)" "/run/user/$($ID -u)" --unshare-user-try"
|
||||||
CONFIG_PROC_FILE="/proc/config.gz"
|
CONFIG_PROC_FILE="/proc/config.gz"
|
||||||
CONFIG_BOOT_FILE="/boot/config-$($UNAME -r)"
|
CONFIG_BOOT_FILE="/boot/config-$($UNAME -r)"
|
||||||
|
PROC_USERNS_CLONE_FILE="/proc/sys/kernel/unprivileged_userns_clone"
|
||||||
|
PROC_USERNS_FILE="/proc/$$/ns/user"
|
||||||
|
|
||||||
function _is_user_namespace_enabled() {
|
function _is_user_namespace_enabled() {
|
||||||
|
if [[ -L $PROC_USERNS_FILE ]]
|
||||||
|
then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e $PROC_USERNS_CLONE_FILE ]]
|
||||||
|
then
|
||||||
|
# `-q` option in zgrep may cause a gzip: stdout: Broken pipe
|
||||||
|
# Use redirect to /dev/null instead
|
||||||
|
if zgrep_cmd "1" "$PROC_USERNS_CLONE_FILE" > /dev/null
|
||||||
|
then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
local config_file=""
|
local config_file=""
|
||||||
if [[ -e $CONFIG_PROC_FILE ]]
|
if [[ -e $CONFIG_PROC_FILE ]]
|
||||||
then
|
then
|
||||||
|
|
@ -23,78 +41,125 @@ function _is_user_namespace_enabled() {
|
||||||
then
|
then
|
||||||
config_file=$CONFIG_BOOT_FILE
|
config_file=$CONFIG_BOOT_FILE
|
||||||
else
|
else
|
||||||
return $NOT_EXISTING_FILE
|
return "$NOT_EXISTING_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! zgrep_cmd -q "CONFIG_USER_NS=y" $config_file
|
# `-q` option in zgrep may cause a gzip: stdout: Broken pipe
|
||||||
|
# Use redirect to /dev/null instead
|
||||||
|
if ! zgrep_cmd "CONFIG_USER_NS=y" "$config_file" > /dev/null
|
||||||
then
|
then
|
||||||
return $NO_CONFIG_FOUND
|
return "$NO_CONFIG_FOUND"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
return "$UNPRIVILEGED_USERNS_DISABLED"
|
||||||
}
|
}
|
||||||
|
|
||||||
function _check_user_namespace() {
|
function _check_user_namespace() {
|
||||||
set +e
|
set +e
|
||||||
_is_user_namespace_enabled
|
_is_user_namespace_enabled
|
||||||
case $? in
|
case $? in
|
||||||
$NOT_EXISTING_FILE) warn "Could not understand if user namespace is enabled. No config.gz file found. Proceeding anyway..." ;;
|
"$NOT_EXISTING_FILE") warn "Could not understand if user namespace is enabled. No config.gz file found. Proceeding anyway..." ;;
|
||||||
$NO_CONFIG_FOUND) warn "User namespace is not enabled or Kernel too old (<3.8). Proceeding anyway..." ;;
|
"$NO_CONFIG_FOUND") warn "Unprivileged user namespace is disabled at kernel compile time or kernel too old (<3.8). Proceeding anyway..." ;;
|
||||||
|
"$UNPRIVILEGED_USERNS_DISABLED") warn "Unprivileged user namespace disabled. Root permissions are required to enable it: sudo sysctl kernel.unprivileged_userns_clone=1" ;;
|
||||||
esac
|
esac
|
||||||
set -e
|
set -e
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
|
||||||
if [[ "$1" != "" ]]
|
|
||||||
then
|
|
||||||
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT --no-umount --recursive $bindings $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
|
|
||||||
else
|
|
||||||
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT --no-umount --recursive $bindings $backend_args "$JUNEST_HOME" "${SH[@]}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Run JuNest as fakeroot user via user namespace.
|
# Run JuNest as fakeroot via bwrap
|
||||||
#
|
#
|
||||||
# Globals:
|
# Globals:
|
||||||
# JUNEST_HOME (RO) : The JuNest home directory.
|
# JUNEST_HOME (RO) : The JuNest home directory.
|
||||||
# GROOT (RO) : The groot program.
|
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
|
||||||
# SH (RO) : Contains the default command to run in JuNest.
|
# BWRAP (RO): : The location of the bwrap binary.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# backend_args ($1) : The arguments to pass to proot
|
# backend_args ($1) : The arguments to pass to bwrap
|
||||||
# cmd ($2-?) : The command to run inside JuNest environment.
|
# no_copy_files ($2?) : If false it will copy some files in /etc
|
||||||
# Default command is defined by SH variable.
|
# from host to JuNest environment.
|
||||||
|
# cmd ($3-?) : The command to run inside JuNest environment.
|
||||||
|
# Default command is defined by DEFAULT_SH variable.
|
||||||
# Returns:
|
# Returns:
|
||||||
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
||||||
# Depends on the unshare command outcome.
|
# $ROOT_ACCESS_ERROR : If the user is the real root.
|
||||||
# Output:
|
# Output:
|
||||||
# - : The command output.
|
# - : The command output.
|
||||||
#######################################
|
#######################################
|
||||||
function run_env_with_namespace() {
|
function run_env_as_bwrap_fakeroot(){
|
||||||
local backend_args="$1"
|
check_nested_env
|
||||||
shift
|
|
||||||
|
local backend_command="${1:-$BWRAP}"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
_check_user_namespace
|
_check_user_namespace
|
||||||
|
|
||||||
check_same_arch
|
check_same_arch
|
||||||
|
|
||||||
copy_common_files
|
if ! $no_copy_files
|
||||||
copy_file /etc/hosts.equiv
|
then
|
||||||
copy_file /etc/netgroup
|
copy_common_files
|
||||||
copy_file /etc/networks
|
fi
|
||||||
# No need for localtime as it is setup during the image build
|
|
||||||
#copy_file /etc/localtime
|
|
||||||
copy_passwd_and_group
|
|
||||||
|
|
||||||
_run_env_with_namespace "$backend_args" "$@"
|
local args=()
|
||||||
|
[[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")")
|
||||||
|
|
||||||
|
# Fix PATH to /usr/bin to make sudo working and avoid polluting with host related bin paths
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
PATH="/usr/bin" BWRAP="${backend_command}" JUNEST_ENV=1 bwrap_cmd $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 $backend_args sudo "${DEFAULT_SH[@]}" "${args[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Run JuNest as normal user via bwrap.
|
||||||
|
#
|
||||||
|
# Globals:
|
||||||
|
# JUNEST_HOME (RO) : The JuNest home directory.
|
||||||
|
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
|
||||||
|
# BWRAP (RO): : The location of the bwrap binary.
|
||||||
|
# Arguments:
|
||||||
|
# backend_args ($1) : The arguments to pass to bwrap
|
||||||
|
# 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 DEFAULT_SH variable.
|
||||||
|
# Returns:
|
||||||
|
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
|
||||||
|
# Output:
|
||||||
|
# - : The command output.
|
||||||
|
#######################################
|
||||||
|
function run_env_as_bwrap_user() {
|
||||||
|
check_nested_env
|
||||||
|
|
||||||
|
local backend_command="${1:-$BWRAP}"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
|
_check_user_namespace
|
||||||
|
|
||||||
|
check_same_arch
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
local args=()
|
||||||
|
[[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")")
|
||||||
|
|
||||||
|
# Resets PATH to avoid polluting with host related bin paths
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
PATH='' BWRAP="${backend_command}" JUNEST_ENV=1 bwrap_cmd $COMMON_BWRAP_OPTION $backend_args "${DEFAULT_SH[@]}" "${args[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
#
|
#
|
||||||
# This module contains all proot functionalities for JuNest.
|
# This module contains all proot functionalities for JuNest.
|
||||||
#
|
#
|
||||||
|
|
@ -9,36 +10,39 @@
|
||||||
# vim: ft=sh
|
# vim: ft=sh
|
||||||
|
|
||||||
function _run_env_with_proot(){
|
function _run_env_with_proot(){
|
||||||
local proot_args="$1"
|
local backend_command="${1:-$PROOT}"
|
||||||
shift
|
local backend_args="$2"
|
||||||
|
shift 2
|
||||||
|
|
||||||
check_nested_env
|
local args=()
|
||||||
if [ "$1" != "" ]
|
[[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")")
|
||||||
then
|
|
||||||
JUNEST_ENV=1 proot_cmd "${proot_args}" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
|
# Resets PATH to avoid polluting with host related bin paths
|
||||||
else
|
PATH='' PROOT="${backend_command}" JUNEST_ENV=1 proot_cmd "${backend_args}" "${DEFAULT_SH[@]}" "${args[@]}"
|
||||||
JUNEST_ENV=1 proot_cmd "${proot_args}" "${SH[@]}"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _run_env_with_qemu(){
|
function _run_env_with_qemu(){
|
||||||
local proot_args="$1"
|
local backend_command="$1"
|
||||||
source ${JUNEST_HOME}/etc/junest/info
|
local backend_args="$2"
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
source "${JUNEST_HOME}"/etc/junest/info
|
||||||
|
|
||||||
if [ "$JUNEST_ARCH" != "$ARCH" ]
|
if [ "$JUNEST_ARCH" != "$ARCH" ]
|
||||||
then
|
then
|
||||||
local qemu_bin="qemu-$JUNEST_ARCH-static-$ARCH"
|
local qemu_bin="qemu-$JUNEST_ARCH-static-$ARCH"
|
||||||
local qemu_symlink="/tmp/${qemu_bin}-$RANDOM"
|
local qemu_symlink="/tmp/${qemu_bin}-$RANDOM"
|
||||||
trap - QUIT EXIT ABRT KILL TERM INT
|
trap - QUIT EXIT ABRT KILL TERM INT
|
||||||
trap "[ -e ${qemu_symlink} ] && rm_cmd -f ${qemu_symlink}" EXIT QUIT ABRT KILL TERM INT
|
# shellcheck disable=SC2064
|
||||||
|
trap "[ -e ${qemu_symlink} ] && rm_cmd -f ${qemu_symlink}" EXIT QUIT ABRT TERM INT
|
||||||
|
|
||||||
warn "Emulating $NAME via QEMU..."
|
warn "Emulating $NAME via QEMU..."
|
||||||
[ -e ${qemu_symlink} ] || \
|
[[ -e ${qemu_symlink} ]] || \
|
||||||
ln_cmd -s ${JUNEST_HOME}/opt/qemu/${qemu_bin} ${qemu_symlink}
|
ln_cmd -s "${JUNEST_HOME}/bin/${qemu_bin}" "${qemu_symlink}"
|
||||||
proot_args="-q ${qemu_symlink} $proot_args"
|
backend_args="-q ${qemu_symlink} $backend_args"
|
||||||
fi
|
fi
|
||||||
shift
|
|
||||||
_run_env_with_proot "$proot_args" "${@}"
|
_run_env_with_proot "${backend_command}" "$backend_args" "${@}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -47,23 +51,32 @@ function _run_env_with_qemu(){
|
||||||
# Globals:
|
# Globals:
|
||||||
# JUNEST_HOME (RO) : The JuNest home directory.
|
# JUNEST_HOME (RO) : The JuNest home directory.
|
||||||
# EUID (RO) : The user ID.
|
# EUID (RO) : The user ID.
|
||||||
# SH (RO) : Contains the default command to run in JuNest.
|
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# backend_args ($1) : The arguments to pass to proot
|
# 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
|
||||||
# Default command is defined by SH variable.
|
# from host to JuNest environment.
|
||||||
|
# cmd ($3-?) : The command to run inside JuNest environment.
|
||||||
|
# Default command is defined by DEFAULT_SH variable.
|
||||||
# Returns:
|
# Returns:
|
||||||
# $ROOT_ACCESS_ERROR : If the user is the real root.
|
# $ROOT_ACCESS_ERROR : If the user is the real root.
|
||||||
# Output:
|
# Output:
|
||||||
# - : The command output.
|
# - : The command output.
|
||||||
#######################################
|
#######################################
|
||||||
function run_env_as_fakeroot(){
|
function run_env_as_proot_fakeroot(){
|
||||||
(( EUID == 0 )) && \
|
(( EUID == 0 )) && \
|
||||||
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead."
|
die_on_status "$ROOT_ACCESS_ERROR" "You cannot access with root privileges. Use --groot option instead."
|
||||||
local backend_args="$1"
|
check_nested_env
|
||||||
shift
|
|
||||||
|
|
||||||
copy_common_files
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
|
if ! $no_copy_files
|
||||||
|
then
|
||||||
|
copy_common_files
|
||||||
|
fi
|
||||||
|
|
||||||
provide_common_bindings
|
provide_common_bindings
|
||||||
local bindings=${RESULT}
|
local bindings=${RESULT}
|
||||||
|
|
@ -71,7 +84,7 @@ function run_env_as_fakeroot(){
|
||||||
|
|
||||||
# An alternative is via -S option:
|
# An alternative is via -S option:
|
||||||
#_run_env_with_qemu "-S ${JUNEST_HOME} $1" "${@:2}"
|
#_run_env_with_qemu "-S ${JUNEST_HOME} $1" "${@:2}"
|
||||||
_run_env_with_qemu "-0 ${bindings} -r ${JUNEST_HOME} $backend_args" "$@"
|
_run_env_with_qemu "$backend_command" "-0 ${bindings} -r ${JUNEST_HOME} $backend_args" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -80,37 +93,46 @@ function run_env_as_fakeroot(){
|
||||||
# Globals:
|
# Globals:
|
||||||
# JUNEST_HOME (RO) : The JuNest home directory.
|
# JUNEST_HOME (RO) : The JuNest home directory.
|
||||||
# EUID (RO) : The user ID.
|
# EUID (RO) : The user ID.
|
||||||
# SH (RO) : Contains the default command to run in JuNest.
|
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# backend_args ($1) : The arguments to pass to proot
|
# 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
|
||||||
# Default command is defined by SH variable.
|
# from host to JuNest environment.
|
||||||
|
# cmd ($3-?) : The command to run inside JuNest environment.
|
||||||
|
# Default command is defined by DEFAULT_SH variable.
|
||||||
# Returns:
|
# Returns:
|
||||||
# $ROOT_ACCESS_ERROR : If the user is the real root.
|
# $ROOT_ACCESS_ERROR : If the user is the real root.
|
||||||
# Output:
|
# Output:
|
||||||
# - : The command output.
|
# - : The command output.
|
||||||
#######################################
|
#######################################
|
||||||
function run_env_as_user(){
|
function run_env_as_proot_user(){
|
||||||
(( EUID == 0 )) && \
|
(( EUID == 0 )) && \
|
||||||
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead."
|
die_on_status "$ROOT_ACCESS_ERROR" "You cannot access with root privileges. Use --groot option instead."
|
||||||
local backend_args="$1"
|
check_nested_env
|
||||||
shift
|
|
||||||
|
|
||||||
# Files to bind are visible in `proot --help`.
|
local backend_command="$1"
|
||||||
# This function excludes /etc/mtab file so that
|
local backend_args="$2"
|
||||||
# it will not give conflicts with the related
|
local no_copy_files="$3"
|
||||||
# symlink in the Arch Linux image.
|
shift 3
|
||||||
copy_common_files
|
|
||||||
copy_file /etc/hosts.equiv
|
if ! $no_copy_files
|
||||||
copy_file /etc/netgroup
|
then
|
||||||
copy_file /etc/networks
|
# Files to bind are visible in `proot --help`.
|
||||||
# No need for localtime as it is setup during the image build
|
# This function excludes /etc/mtab file so that
|
||||||
#copy_file /etc/localtime
|
# it will not give conflicts with the related
|
||||||
copy_passwd_and_group
|
# 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
|
provide_common_bindings
|
||||||
local bindings=${RESULT}
|
local bindings=${RESULT}
|
||||||
unset RESULT
|
unset RESULT
|
||||||
|
|
||||||
_run_env_with_qemu "${bindings} -r ${JUNEST_HOME} $backend_args" "$@"
|
_run_env_with_qemu "$backend_command" "${bindings} -r ${JUNEST_HOME} $backend_args" "$@"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
# None
|
# None
|
||||||
#######################################
|
#######################################
|
||||||
function is_env_installed(){
|
function is_env_installed(){
|
||||||
[ -d "$JUNEST_HOME" ] && [ "$(ls -A $JUNEST_HOME)" ] && return 0
|
[[ -d "$JUNEST_HOME" ]] && [[ "$(ls -A "$JUNEST_HOME")" ]] && return 0
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ function is_env_installed(){
|
||||||
function _cleanup_build_directory(){
|
function _cleanup_build_directory(){
|
||||||
local maindir=$1
|
local maindir=$1
|
||||||
check_not_null "$maindir"
|
check_not_null "$maindir"
|
||||||
builtin cd $ORIGIN_WD
|
builtin cd "$ORIGIN_WD" || return 1
|
||||||
trap - QUIT EXIT ABRT KILL TERM INT
|
trap - QUIT EXIT ABRT KILL TERM INT
|
||||||
rm_cmd -fr "$maindir"
|
rm_cmd -fr "$maindir"
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,8 @@ function _prepare_build_directory(){
|
||||||
local maindir=$1
|
local maindir=$1
|
||||||
check_not_null "$maindir"
|
check_not_null "$maindir"
|
||||||
trap - QUIT EXIT ABRT KILL TERM INT
|
trap - QUIT EXIT ABRT KILL TERM INT
|
||||||
trap "rm_cmd -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT KILL TERM INT
|
# shellcheck disable=SC2064
|
||||||
|
trap "rm_cmd -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT TERM INT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -51,11 +52,18 @@ function _setup_env(){
|
||||||
is_env_installed && die "Error: ${NAME} has been already installed in $JUNEST_HOME"
|
is_env_installed && die "Error: ${NAME} has been already installed in $JUNEST_HOME"
|
||||||
|
|
||||||
mkdir_cmd -p "${JUNEST_HOME}"
|
mkdir_cmd -p "${JUNEST_HOME}"
|
||||||
$TAR -zxpf ${imagepath} -C ${JUNEST_HOME}
|
$TAR -zxpf "${imagepath}" -C "${JUNEST_HOME}"
|
||||||
info "The default mirror URL is ${DEFAULT_MIRROR}."
|
info "${NAME} installed successfully!"
|
||||||
|
echo
|
||||||
|
info "Default mirror URL set to: ${DEFAULT_MIRROR}"
|
||||||
|
info "You can change the pacman mirror URL in /etc/pacman.d/mirrorlist according to your location:"
|
||||||
|
info " \$EDITOR ${JUNEST_HOME}/etc/pacman.d/mirrorlist"
|
||||||
|
echo
|
||||||
info "Remember to refresh the package databases from the server:"
|
info "Remember to refresh the package databases from the server:"
|
||||||
info " pacman -Syy"
|
info " pacman -Syy"
|
||||||
info "${NAME} installed successfully"
|
echo
|
||||||
|
info "To install packages from AUR follow the wiki here:"
|
||||||
|
info "https://github.com/fsquillace/junest#install-packages-from-aur"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -70,7 +78,6 @@ function _setup_env(){
|
||||||
# the JuNest system from the image.
|
# the JuNest system from the image.
|
||||||
# ENV_REPO (RO) : URL of the site containing JuNest images.
|
# ENV_REPO (RO) : URL of the site containing JuNest images.
|
||||||
# NAME (RO) : The JuNest name.
|
# NAME (RO) : The JuNest name.
|
||||||
# DEFAULT_MIRROR (RO) : Arch Linux URL mirror.
|
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# arch ($1?) : The JuNest architecture image to download.
|
# arch ($1?) : The JuNest architecture image to download.
|
||||||
# Defaults to the host architecture
|
# Defaults to the host architecture
|
||||||
|
|
@ -81,21 +88,22 @@ function _setup_env(){
|
||||||
#######################################
|
#######################################
|
||||||
function setup_env(){
|
function setup_env(){
|
||||||
local arch=${1:-$ARCH}
|
local arch=${1:-$ARCH}
|
||||||
contains_element $arch "${ARCH_LIST[@]}" || \
|
contains_element "$arch" "${ARCH_LIST[@]}" || \
|
||||||
die_on_status $NOT_AVAILABLE_ARCH "The architecture is not one of: ${ARCH_LIST[@]}"
|
die_on_status "$NOT_AVAILABLE_ARCH" "The architecture is not one of: ${ARCH_LIST[*]}"
|
||||||
|
|
||||||
local maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t ${CMD}.XXXXXXXXXX)
|
local maindir
|
||||||
_prepare_build_directory $maindir
|
maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t "${CMD}".XXXXXXXXXX)
|
||||||
|
_prepare_build_directory "$maindir"
|
||||||
|
|
||||||
info "Downloading ${NAME}..."
|
info "Downloading ${NAME}..."
|
||||||
builtin cd ${maindir}
|
builtin cd "${maindir}" || return 1
|
||||||
local imagefile=${CMD}-${arch}.tar.gz
|
local imagefile=${CMD}-${arch}.tar.gz
|
||||||
download_cmd ${ENV_REPO}/${imagefile}
|
download_cmd "${ENV_REPO}/${imagefile}"
|
||||||
|
|
||||||
info "Installing ${NAME}..."
|
info "Installing ${NAME}..."
|
||||||
_setup_env ${maindir}/${imagefile}
|
_setup_env "${maindir}/${imagefile}"
|
||||||
|
|
||||||
_cleanup_build_directory ${maindir}
|
_cleanup_build_directory "${maindir}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -105,7 +113,6 @@ function setup_env(){
|
||||||
# JUNEST_HOME (RO) : The JuNest home directory in which JuNest needs
|
# JUNEST_HOME (RO) : The JuNest home directory in which JuNest needs
|
||||||
# to be installed.
|
# to be installed.
|
||||||
# NAME (RO) : The JuNest name.
|
# NAME (RO) : The JuNest name.
|
||||||
# DEFAULT_MIRROR (RO) : Arch Linux URL mirror.
|
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# imagefile ($1) : The JuNest image file.
|
# imagefile ($1) : The JuNest image file.
|
||||||
# Returns:
|
# Returns:
|
||||||
|
|
@ -116,10 +123,10 @@ function setup_env(){
|
||||||
function setup_env_from_file(){
|
function setup_env_from_file(){
|
||||||
local imagefile=$1
|
local imagefile=$1
|
||||||
check_not_null "$imagefile"
|
check_not_null "$imagefile"
|
||||||
[ ! -e ${imagefile} ] && die_on_status $NOT_EXISTING_FILE "Error: The ${NAME} image file ${imagefile} does not exist"
|
[[ ! -e ${imagefile} ]] && die_on_status "$NOT_EXISTING_FILE" "Error: The ${NAME} image file ${imagefile} does not exist"
|
||||||
|
|
||||||
info "Installing ${NAME} from ${imagefile}..."
|
info "Installing ${NAME} from ${imagefile}..."
|
||||||
_setup_env ${imagefile}
|
_setup_env "${imagefile}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -136,18 +143,18 @@ function setup_env_from_file(){
|
||||||
#######################################
|
#######################################
|
||||||
function delete_env(){
|
function delete_env(){
|
||||||
! ask "Are you sure to delete ${NAME} located in ${JUNEST_HOME}" "N" && return
|
! ask "Are you sure to delete ${NAME} located in ${JUNEST_HOME}" "N" && return
|
||||||
if mountpoint -q ${JUNEST_HOME}
|
if mountpoint -q "${JUNEST_HOME}"
|
||||||
then
|
then
|
||||||
info "There are mounted directories inside ${JUNEST_HOME}"
|
info "There are mounted directories inside ${JUNEST_HOME}"
|
||||||
if ! umount --force ${JUNEST_HOME}
|
if ! umount --force "${JUNEST_HOME}"
|
||||||
then
|
then
|
||||||
error "Cannot umount directories in ${JUNEST_HOME}"
|
error "Cannot umount directories in ${JUNEST_HOME}"
|
||||||
die "Try to delete ${NAME} using root permissions"
|
die "Try to delete ${NAME} using root permissions"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# the CA directories are read only and can be deleted only by changing the mod
|
# the CA directories are read only and can be deleted only by changing the mod
|
||||||
chmod -R +w ${JUNEST_HOME}/etc/ca-certificates
|
chmod -R +w "${JUNEST_HOME}"/etc/ca-certificates
|
||||||
if rm_cmd -rf ${JUNEST_HOME}/*
|
if rm_cmd -rf "${JUNEST_HOME}"
|
||||||
then
|
then
|
||||||
info "${NAME} deleted in ${JUNEST_HOME}"
|
info "${NAME} deleted in ${JUNEST_HOME}"
|
||||||
else
|
else
|
||||||
|
|
|
||||||
60
lib/core/wrappers.sh
Normal file
60
lib/core/wrappers.sh
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Dependencies:
|
||||||
|
# None
|
||||||
|
#
|
||||||
|
# vim: ft=sh
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Create bin wrappers
|
||||||
|
#
|
||||||
|
# Globals:
|
||||||
|
# JUNEST_HOME (RO) : The JuNest home directory.
|
||||||
|
# Arguments:
|
||||||
|
# force ($1?) : Create bin wrappers even if the bin file exists.
|
||||||
|
# Defaults to false.
|
||||||
|
# Returns:
|
||||||
|
# None
|
||||||
|
# Output:
|
||||||
|
# None
|
||||||
|
#######################################
|
||||||
|
function create_wrappers() {
|
||||||
|
local force=${1:-false}
|
||||||
|
local bin_path=${2:-/usr/bin}
|
||||||
|
bin_path=${bin_path%/}
|
||||||
|
mkdir -p "${JUNEST_HOME}${bin_path}_wrappers"
|
||||||
|
# Arguments inside a variable (i.e. `JUNEST_ARGS`) separated by quotes
|
||||||
|
# are not recognized normally unless using `eval`. More info here:
|
||||||
|
# https://github.com/fsquillace/junest/issues/262
|
||||||
|
# https://github.com/fsquillace/junest/pull/287
|
||||||
|
cat <<EOF > "${JUNEST_HOME}/usr/bin/junest_wrapper"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
eval "junest_args_array=(\${JUNEST_ARGS:-ns})"
|
||||||
|
junest "\${junest_args_array[@]}" -- \$(basename \${0}) "\$@"
|
||||||
|
EOF
|
||||||
|
chmod +x "${JUNEST_HOME}/usr/bin/junest_wrapper"
|
||||||
|
|
||||||
|
cd "${JUNEST_HOME}${bin_path}" || return 1
|
||||||
|
for file in *
|
||||||
|
do
|
||||||
|
[[ -d $file ]] && continue
|
||||||
|
# Symlinks outside junest appear as broken even though they are correct
|
||||||
|
# within a junest session. The following do not skip broken symlinks:
|
||||||
|
[[ -x $file || -L $file ]] || continue
|
||||||
|
if [[ -e ${JUNEST_HOME}${bin_path}_wrappers/$file ]] && ! $force
|
||||||
|
then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
rm -f "${JUNEST_HOME}${bin_path}_wrappers/$file"
|
||||||
|
ln -s "${JUNEST_HOME}/usr/bin/junest_wrapper" "${JUNEST_HOME}${bin_path}_wrappers/$file"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove wrappers no longer needed
|
||||||
|
cd "${JUNEST_HOME}${bin_path}_wrappers" || return 1
|
||||||
|
for file in *
|
||||||
|
do
|
||||||
|
[[ -e ${JUNEST_HOME}${bin_path}/$file || -L ${JUNEST_HOME}${bin_path}/$file ]] || rm -f "$file"
|
||||||
|
done
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ function echoerr() {
|
||||||
# Message printed to stderr.
|
# Message printed to stderr.
|
||||||
#######################################
|
#######################################
|
||||||
function die() {
|
function die() {
|
||||||
error $@
|
error "$@"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,8 +70,8 @@ function die() {
|
||||||
function die_on_status() {
|
function die_on_status() {
|
||||||
status=$1
|
status=$1
|
||||||
shift
|
shift
|
||||||
error $@
|
error "$@"
|
||||||
exit $status
|
exit "$status"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -87,7 +87,7 @@ function die_on_status() {
|
||||||
# Message printed to stderr.
|
# Message printed to stderr.
|
||||||
#######################################
|
#######################################
|
||||||
function error() {
|
function error() {
|
||||||
echoerr -e "\033[1;31m$@\033[0m"
|
echoerr -e "\033[1;31m$*\033[0m"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -104,7 +104,7 @@ function error() {
|
||||||
#######################################
|
#######################################
|
||||||
function warn() {
|
function warn() {
|
||||||
# $@: msg (mandatory) - str: Message to print
|
# $@: msg (mandatory) - str: Message to print
|
||||||
echoerr -e "\033[1;33m$@\033[0m"
|
echoerr -e "\033[1;33m$*\033[0m"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -120,7 +120,7 @@ function warn() {
|
||||||
# Message printed to stdout.
|
# Message printed to stdout.
|
||||||
#######################################
|
#######################################
|
||||||
function info(){
|
function info(){
|
||||||
echo -e "\033[1;36m$@\033[0m"
|
echo -e "\033[1;36m$*\033[0m"
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
@ -142,12 +142,12 @@ function info(){
|
||||||
function ask(){
|
function ask(){
|
||||||
local question=$1
|
local question=$1
|
||||||
local default_answer=$2
|
local default_answer=$2
|
||||||
check_not_null $question
|
check_not_null "$question"
|
||||||
|
|
||||||
if [ ! -z "$default_answer" ]
|
if [ -n "$default_answer" ]
|
||||||
then
|
then
|
||||||
local answers="Y y N n"
|
local answers="Y y N n"
|
||||||
[[ "$answers" =~ "$default_answer" ]] || { error "The default answer: $default_answer is wrong."; return $WRONG_ANSWER; }
|
[[ "$answers" =~ $default_answer ]] || { error "The default answer: $default_answer is wrong."; return $WRONG_ANSWER; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local default="Y"
|
local default="Y"
|
||||||
|
|
@ -156,12 +156,13 @@ function ask(){
|
||||||
local other="n"
|
local other="n"
|
||||||
[ "$default" == "N" ] && other="y"
|
[ "$default" == "N" ] && other="y"
|
||||||
|
|
||||||
local prompt=$(info "$question (${default}/${other})> ")
|
local prompt
|
||||||
|
prompt=$(info "$question (${default}/${other})> ")
|
||||||
|
|
||||||
local res="none"
|
local res="none"
|
||||||
while [ "$res" != "Y" ] && [ "$res" != "N" ] && [ "$res" != "" ];
|
while [ "$res" != "Y" ] && [ "$res" != "N" ] && [ "$res" != "" ];
|
||||||
do
|
do
|
||||||
read -p "$prompt" res
|
read -r -p "$prompt" res
|
||||||
res=$(echo "$res" | tr '[:lower:]' '[:upper:]')
|
res=$(echo "$res" | tr '[:lower:]' '[:upper:]')
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
@ -170,36 +171,31 @@ function ask(){
|
||||||
[ "$res" == "Y" ]
|
[ "$res" == "Y" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_and_trap() {
|
|
||||||
local sigs="${@:2:${#@}}"
|
|
||||||
local traps="$(trap -p $sigs)"
|
|
||||||
[[ $traps ]] && die "Attempting to overwrite existing $sigs trap: $traps"
|
|
||||||
trap $@
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_and_force_trap() {
|
|
||||||
local sigs="${@:2:${#@}}"
|
|
||||||
local traps="$(trap -p $sigs)"
|
|
||||||
[[ $traps ]] && warn "Attempting to overwrite existing $sigs trap: $traps"
|
|
||||||
trap $@
|
|
||||||
}
|
|
||||||
|
|
||||||
function insert_quotes_on_spaces(){
|
function insert_quotes_on_spaces(){
|
||||||
# It inserts quotes between arguments.
|
# It inserts quotes between arguments.
|
||||||
# Useful to preserve quotes on command
|
# Useful to preserve quotes on command
|
||||||
# to be used inside sh -c/bash -c
|
# to be used inside sh -c/bash -c
|
||||||
C=''
|
local C=""
|
||||||
whitespace="[[:space:]]"
|
whitespace="[[:space:]]"
|
||||||
for i in "$@"
|
for i in "$@"
|
||||||
do
|
do
|
||||||
if [[ $i =~ $whitespace ]]
|
if [[ $i =~ $whitespace ]]
|
||||||
then
|
then
|
||||||
C="$C \"$i\""
|
temp_C="\"$i\""
|
||||||
else
|
else
|
||||||
C="$C $i"
|
temp_C="$i"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Handle edge case when C is empty to avoid adding an extra space
|
||||||
|
if [[ -z $C ]]
|
||||||
|
then
|
||||||
|
C="$temp_C"
|
||||||
|
else
|
||||||
|
C="$C $temp_C"
|
||||||
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
echo $C
|
echo "$C"
|
||||||
}
|
}
|
||||||
|
|
||||||
contains_element () {
|
contains_element () {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
source "$(dirname $0)/../utils/utils.sh"
|
source "$(dirname "$0")/../utils/utils.sh"
|
||||||
|
|
||||||
# Disable the exiterr
|
# Disable the exiterr
|
||||||
set +e
|
set +e
|
||||||
|
|
@ -10,12 +11,12 @@ function oneTimeSetUp(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_check_no_tabs(){
|
function test_check_no_tabs(){
|
||||||
assertCommandFailOnStatus 1 grep -R "$(printf '\t')" $(dirname $0)/../../bin/*
|
assertCommandFailOnStatus 1 grep -R "$(printf '\t')" "$(dirname "$0")"/../../bin/*
|
||||||
assertEquals "" "$(cat $STDOUTF)"
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
assertEquals "" "$(cat $STDERRF)"
|
assertEquals "" "$(cat "$STDERRF")"
|
||||||
assertCommandFailOnStatus 1 grep -R "$(printf '\t')" $(dirname $0)/../../lib/*
|
assertCommandFailOnStatus 1 grep -R "$(printf '\t')" "$(dirname "$0")"/../../lib/*
|
||||||
assertEquals "" "$(cat $STDOUTF)"
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
assertEquals "" "$(cat $STDERRF)"
|
assertEquals "" "$(cat "$STDERRF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
source $(dirname $0)/../utils/shunit2
|
source "$(dirname "$0")"/../utils/shunit2
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
VERSION=$1
|
|
||||||
|
|
||||||
cd /tmp
|
|
||||||
wget http://ftp.gnu.org/gnu/bash/bash-$VERSION.tar.gz
|
|
||||||
|
|
||||||
tar -zxf bash-$VERSION.tar.gz
|
|
||||||
cd /tmp/bash-$VERSION*
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
sudo make install
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
JUNEST_ROOT=$(readlink -f $(dirname $0)/../..)
|
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
|
||||||
|
|
||||||
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
||||||
|
|
||||||
|
|
@ -28,40 +29,97 @@ function tearDown(){
|
||||||
|
|
||||||
function init_mocks() {
|
function init_mocks() {
|
||||||
chroot_cmd() {
|
chroot_cmd() {
|
||||||
|
# shellcheck disable=SC2317
|
||||||
[ "$JUNEST_ENV" != "1" ] && return 1
|
[ "$JUNEST_ENV" != "1" ] && return 1
|
||||||
echo "chroot_cmd $@"
|
# shellcheck disable=SC2317
|
||||||
|
echo "chroot_cmd $*"
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2034
|
||||||
GROOT=chroot_cmd
|
GROOT=chroot_cmd
|
||||||
|
mychroot() {
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
echo mychroot "$*"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_groot_cmd(){
|
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)"
|
assertEquals "chroot_cmd -b /run/user/$(id -u) -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(){
|
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)"
|
assertEquals "chroot_cmd -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_groot_with_backend_command(){
|
||||||
|
assertCommandSuccess run_env_as_groot "mychroot" "" "false" ""
|
||||||
|
assertEquals "mychroot -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_groot_no_copy(){
|
||||||
|
assertCommandSuccess run_env_as_groot "" "" "true" pwd
|
||||||
|
assertEquals "chroot_cmd -b /run/user/$(id -u) -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 "" "" "false" ""
|
||||||
|
unset JUNEST_ENV
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_groot_cmd_with_backend_args(){
|
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)"
|
assertEquals "chroot_cmd -b /run/user/$(id -u) -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(){
|
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)"
|
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_chroot_no_cmd(){
|
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)"
|
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_chroot_with_backend_command(){
|
||||||
|
assertCommandSuccess run_env_as_chroot "mychroot" "" "false" ""
|
||||||
|
assertEquals "mychroot $JUNEST_HOME /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 "" "" "false" ""
|
||||||
|
unset JUNEST_ENV
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_chroot_cmd_with_backend_args(){
|
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)"
|
assertEquals "chroot_cmd -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
source $JUNEST_ROOT/tests/utils/shunit2
|
source "$JUNEST_ROOT"/tests/utils/shunit2
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
JUNEST_ROOT=$(readlink -f $(dirname $0)/../..)
|
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
|
||||||
|
|
||||||
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
||||||
|
|
||||||
|
|
@ -21,47 +22,59 @@ function oneTimeTearDown(){
|
||||||
|
|
||||||
function setUp(){
|
function setUp(){
|
||||||
ld_exec_mock() {
|
ld_exec_mock() {
|
||||||
echo "ld_exec $@"
|
# shellcheck disable=SC2317
|
||||||
|
echo "ld_exec $*"
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
ld_exec_mock_false() {
|
ld_exec_mock_false() {
|
||||||
echo "ld_exec $@"
|
echo "ld_exec $*"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2034
|
||||||
LD_EXEC=ld_exec_mock
|
LD_EXEC=ld_exec_mock
|
||||||
|
|
||||||
unshare_mock() {
|
unshare_mock() {
|
||||||
echo "unshare $@"
|
# shellcheck disable=SC2317
|
||||||
|
echo "unshare $*"
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2034
|
||||||
UNSHARE=unshare_mock
|
UNSHARE=unshare_mock
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
bwrap_mock() {
|
||||||
|
echo "bwrap $*"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
BWRAP=bwrap_mock
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_ln(){
|
function test_ln(){
|
||||||
LN=echo assertCommandSuccess ln_cmd -s ln_file new_file
|
LN="echo" assertCommandSuccess ln_cmd -s ln_file new_file
|
||||||
assertEquals "-s ln_file new_file" "$(cat $STDOUTF)"
|
assertEquals "-s ln_file new_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
LN=false assertCommandSuccess ln_cmd -s ln_file new_file
|
LN=false assertCommandSuccess ln_cmd -s ln_file new_file
|
||||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -s ln_file new_file" "$(cat $STDOUTF)"
|
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -s ln_file new_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
LN=false LD_EXEC=false assertCommandFail ln_cmd
|
LN=false LD_EXEC=false assertCommandFail ln_cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_getent(){
|
function test_getent(){
|
||||||
GETENT=echo assertCommandSuccess getent_cmd passwd
|
GETENT="echo" assertCommandSuccess getent_cmd passwd
|
||||||
assertEquals "passwd" "$(cat $STDOUTF)"
|
assertEquals "passwd" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
GETENT=false assertCommandSuccess getent_cmd passwd
|
GETENT="false" assertCommandSuccess getent_cmd passwd
|
||||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat $STDOUTF)"
|
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
GETENT=false LD_EXEC=false assertCommandFail getent_cmd
|
GETENT=false LD_EXEC=false assertCommandFail getent_cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_cp(){
|
function test_cp(){
|
||||||
CP=echo assertCommandSuccess cp_cmd passwd
|
CP="echo" assertCommandSuccess cp_cmd passwd
|
||||||
assertEquals "passwd" "$(cat $STDOUTF)"
|
assertEquals "passwd" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
CP=false assertCommandSuccess cp_cmd passwd
|
CP=false assertCommandSuccess cp_cmd passwd
|
||||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat $STDOUTF)"
|
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
CP=false LD_EXEC=false assertCommandFail cp_cmd
|
CP=false LD_EXEC=false assertCommandFail cp_cmd
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +84,9 @@ function test_download(){
|
||||||
CURL=/bin/false
|
CURL=/bin/false
|
||||||
assertCommandSuccess download_cmd
|
assertCommandSuccess download_cmd
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
WGET=/bin/false
|
WGET=/bin/false
|
||||||
|
# shellcheck disable=SC2034
|
||||||
CURL=/bin/true
|
CURL=/bin/true
|
||||||
assertCommandSuccess download_cmd
|
assertCommandSuccess download_cmd
|
||||||
|
|
||||||
|
|
@ -79,69 +94,77 @@ function test_download(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_rm(){
|
function test_rm(){
|
||||||
RM=echo assertCommandSuccess rm_cmd rm_file
|
RM="echo" assertCommandSuccess rm_cmd rm_file
|
||||||
assertEquals "rm_file" "$(cat $STDOUTF)"
|
assertEquals "rm_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
RM=false assertCommandSuccess rm_cmd rm_file
|
RM="false" assertCommandSuccess rm_cmd rm_file
|
||||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false rm_file" "$(cat $STDOUTF)"
|
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false rm_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
RM=false LD_EXEC=false assertCommandFail rm_cmd rm_file
|
RM=false LD_EXEC=false assertCommandFail rm_cmd rm_file
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_chown(){
|
function test_chown(){
|
||||||
local id=$(id -u)
|
local id
|
||||||
|
id=$(id -u)
|
||||||
|
|
||||||
CHOWN=echo assertCommandSuccess chown_cmd $id chown_file
|
CHOWN="echo" assertCommandSuccess chown_cmd "$id" chown_file
|
||||||
assertEquals "$id chown_file" "$(cat $STDOUTF)"
|
assertEquals "$id chown_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
CHOWN=false assertCommandSuccess chown_cmd $id chown_file
|
CHOWN="false" assertCommandSuccess chown_cmd "$id" chown_file
|
||||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false $id chown_file" "$(cat $STDOUTF)"
|
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false $id chown_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
CHOWN=false LD_EXEC=false assertCommandFail chown_cmd $id chown_file
|
CHOWN=false LD_EXEC=false assertCommandFail chown_cmd "$id" chown_file
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_mkdir(){
|
function test_mkdir(){
|
||||||
MKDIR=echo assertCommandSuccess mkdir_cmd -p new_dir/new_dir
|
MKDIR="echo" assertCommandSuccess mkdir_cmd -p new_dir/new_dir
|
||||||
assertEquals "-p new_dir/new_dir" "$(cat $STDOUTF)"
|
assertEquals "-p new_dir/new_dir" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
MKDIR=false assertCommandSuccess mkdir_cmd -p new_dir/new_dir
|
MKDIR=false assertCommandSuccess mkdir_cmd -p new_dir/new_dir
|
||||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -p new_dir/new_dir" "$(cat $STDOUTF)"
|
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -p new_dir/new_dir" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
MKDIR=false LD_EXEC=false assertCommandFail mkdir_cmd -p new_dir/new_dir
|
MKDIR=false LD_EXEC=false assertCommandFail mkdir_cmd -p new_dir/new_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_zgrep(){
|
function test_zgrep(){
|
||||||
ZGREP=echo assertCommandSuccess zgrep_cmd new_file
|
ZGREP="echo" assertCommandSuccess zgrep_cmd new_file
|
||||||
assertEquals "new_file" "$(cat $STDOUTF)"
|
assertEquals "new_file" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
mkdir -p ${JUNEST_HOME}/usr/bin
|
mkdir -p "${JUNEST_HOME}"/usr/bin
|
||||||
touch ${JUNEST_HOME}/usr/bin/false
|
touch "${JUNEST_HOME}"/usr/bin/false
|
||||||
chmod +x ${JUNEST_HOME}/usr/bin/false
|
chmod +x "${JUNEST_HOME}"/usr/bin/false
|
||||||
|
|
||||||
echo -e "#!/bin/bash\necho zgrep" > ${JUNEST_HOME}/usr/bin/false
|
echo -e "#!/bin/bash\necho zgrep" > "${JUNEST_HOME}"/usr/bin/false
|
||||||
ZGREP=false assertCommandSuccess zgrep_cmd new_file
|
ZGREP=false assertCommandSuccess zgrep_cmd new_file
|
||||||
assertEquals "zgrep" "$(cat $STDOUTF)"
|
assertEquals "zgrep" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
echo -e "#!/bin/bash\nexit 1" > ${JUNEST_HOME}/usr/bin/false
|
echo -e "#!/bin/bash\nexit 1" > "${JUNEST_HOME}"/usr/bin/false
|
||||||
ZGREP=false assertCommandFail zgrep_cmd new_file
|
ZGREP=false assertCommandFail zgrep_cmd new_file
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_unshare(){
|
function test_unshare(){
|
||||||
assertCommandSuccess unshare_cmd new_program
|
assertCommandSuccess unshare_cmd new_program
|
||||||
assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE --user /bin/sh -c :\nld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE new_program")" "$(cat $STDOUTF)"
|
assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE --user /bin/sh -c :\nld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE new_program")" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
LD_EXEC=ld_exec_mock_false assertCommandSuccess unshare_cmd new_program
|
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 -c :\nunshare --user /bin/sh -c :\nunshare new_program")" "$(cat $STDOUTF)"
|
assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/unshare_mock --user /bin/sh -c :\nunshare --user /bin/sh -c :\nunshare new_program")" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
UNSHARE=false LD_EXEC=false assertCommandFail unshare_cmd new_program
|
UNSHARE=false LD_EXEC=false assertCommandFail unshare_cmd new_program
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_bwrap(){
|
||||||
|
assertCommandSuccess bwrap_cmd new_program
|
||||||
|
assertEquals "$(echo -e "ld_exec $BWRAP --dev-bind / / /bin/sh -c :\nld_exec $BWRAP new_program")" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
BWRAP=false LD_EXEC=false assertCommandFail bwrap_cmd new_program
|
||||||
|
}
|
||||||
|
|
||||||
function test_chroot(){
|
function test_chroot(){
|
||||||
CLASSIC_CHROOT=echo assertCommandSuccess chroot_cmd root
|
CLASSIC_CHROOT="echo" assertCommandSuccess chroot_cmd root
|
||||||
assertEquals "root" "$(cat $STDOUTF)"
|
assertEquals "root" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
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)"
|
assertEquals "ld_exec $JUNEST_HOME/usr/bin/false root" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
|
CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
|
||||||
}
|
}
|
||||||
|
|
@ -154,39 +177,43 @@ function test_proot_cmd_compat(){
|
||||||
|
|
||||||
function test_proot_cmd_seccomp(){
|
function test_proot_cmd_seccomp(){
|
||||||
envv(){
|
envv(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
env
|
env
|
||||||
}
|
}
|
||||||
PROOT=envv
|
PROOT=envv
|
||||||
assertCommandSuccess proot_cmd cmd
|
assertCommandSuccess proot_cmd cmd
|
||||||
assertEquals "" "$(cat $STDOUTF | grep "^PROOT_NO_SECCOMP")"
|
assertEquals "" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")"
|
||||||
|
|
||||||
envv(){
|
envv(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
env | grep "^PROOT_NO_SECCOMP"
|
env | grep "^PROOT_NO_SECCOMP"
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2034
|
||||||
PROOT=envv
|
PROOT=envv
|
||||||
local output=$(proot_cmd | grep "^PROOT_NO_SECCOMP")
|
|
||||||
assertCommandSuccess proot_cmd cmd
|
assertCommandSuccess proot_cmd cmd
|
||||||
# The variable PROOT_NO_SECCOMP will be produced
|
# The variable PROOT_NO_SECCOMP will be produced
|
||||||
# twice due to the fallback mechanism
|
# twice due to the fallback mechanism
|
||||||
assertEquals "PROOT_NO_SECCOMP=1
|
assertEquals "PROOT_NO_SECCOMP=1
|
||||||
PROOT_NO_SECCOMP=1" "$(cat $STDOUTF | grep "^PROOT_NO_SECCOMP")"
|
PROOT_NO_SECCOMP=1" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_copy_passwd_and_group(){
|
function test_copy_passwd_and_group(){
|
||||||
getent_cmd_mock() {
|
getent_cmd_mock() {
|
||||||
echo $@
|
# shellcheck disable=SC2317
|
||||||
|
echo "$*"
|
||||||
}
|
}
|
||||||
GETENT=getent_cmd_mock assertCommandSuccess copy_passwd_and_group
|
GETENT=getent_cmd_mock assertCommandSuccess copy_passwd_and_group
|
||||||
assertEquals "$(echo -e "passwd\npasswd $USER")" "$(cat $JUNEST_HOME/etc/passwd)"
|
assertEquals "$(echo -e "passwd\npasswd $USER")" "$(cat "$JUNEST_HOME"/etc/passwd)"
|
||||||
assertEquals "group" "$(cat $JUNEST_HOME/etc/group)"
|
assertEquals "group" "$(cat "$JUNEST_HOME"/etc/group)"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_copy_passwd_and_group_fallback(){
|
function test_copy_passwd_and_group_fallback(){
|
||||||
cp_cmd_mock() {
|
cp_cmd_mock() {
|
||||||
echo $@
|
# shellcheck disable=SC2317
|
||||||
|
echo "$*"
|
||||||
}
|
}
|
||||||
CP=cp_cmd_mock GETENT=false LD_EXEC=false assertCommandSuccess copy_passwd_and_group
|
CP=cp_cmd_mock GETENT=false LD_EXEC=false assertCommandSuccess copy_passwd_and_group
|
||||||
assertEquals "$(echo -e "/etc/passwd $JUNEST_HOME//etc/passwd\n/etc/group $JUNEST_HOME//etc/group")" "$(cat $STDOUTF)"
|
assertEquals "$(echo -e "-f /etc/passwd $JUNEST_HOME//etc/passwd\n-f /etc/group $JUNEST_HOME//etc/group")" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_copy_passwd_and_group_failure(){
|
function test_copy_passwd_and_group_failure(){
|
||||||
|
|
@ -202,14 +229,14 @@ function test_nested_env_not_set_variable(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_check_same_arch_not_same(){
|
function test_check_same_arch_not_same(){
|
||||||
echo "JUNEST_ARCH=XXX" > ${JUNEST_HOME}/etc/junest/info
|
echo "JUNEST_ARCH=XXX" > "${JUNEST_HOME}"/etc/junest/info
|
||||||
assertCommandFailOnStatus 104 check_same_arch
|
assertCommandFailOnStatus 104 check_same_arch
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_check_same_arch(){
|
function test_check_same_arch(){
|
||||||
echo "JUNEST_ARCH=$ARCH" > ${JUNEST_HOME}/etc/junest/info
|
echo "JUNEST_ARCH=$ARCH" > "${JUNEST_HOME}"/etc/junest/info
|
||||||
assertCommandSuccess check_same_arch
|
assertCommandSuccess check_same_arch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
source $JUNEST_ROOT/tests/utils/shunit2
|
source "$JUNEST_ROOT"/tests/utils/shunit2
|
||||||
|
|
|
||||||
|
|
@ -1,230 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
source "$(dirname $0)/../utils/utils.sh"
|
|
||||||
|
|
||||||
JUNEST_BASE="$(readlink -f $(dirname $(readlink -f "$0"))/../..)"
|
|
||||||
|
|
||||||
# Disable the exiterr
|
|
||||||
set +e
|
|
||||||
|
|
||||||
function oneTimeSetUp(){
|
|
||||||
setUpUnitTests
|
|
||||||
}
|
|
||||||
|
|
||||||
function setUp(){
|
|
||||||
# Attempt to source the files under test to revert variable overrides
|
|
||||||
source $JUNEST_BASE/bin/groot -h &> /dev/null
|
|
||||||
set +e
|
|
||||||
|
|
||||||
cwdSetUp
|
|
||||||
mkdir -p chrootdir
|
|
||||||
|
|
||||||
init_mocks
|
|
||||||
}
|
|
||||||
|
|
||||||
function tearDown(){
|
|
||||||
cwdTearDown
|
|
||||||
}
|
|
||||||
|
|
||||||
## Mock functions ##
|
|
||||||
function init_mocks() {
|
|
||||||
function usage(){
|
|
||||||
echo "usage"
|
|
||||||
}
|
|
||||||
function is_user_root() {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
function chroot() {
|
|
||||||
echo "chroot($@)"
|
|
||||||
}
|
|
||||||
function mountpoint() {
|
|
||||||
echo "mountpoint($@)"
|
|
||||||
# As default suppose the mountpoint does not exist
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
function mount() {
|
|
||||||
echo "mount($@)"
|
|
||||||
}
|
|
||||||
function umount() {
|
|
||||||
echo "umount($@)"
|
|
||||||
}
|
|
||||||
function check_and_trap() {
|
|
||||||
echo "check_and_trap($@)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_help(){
|
|
||||||
assertCommandSuccess main -h
|
|
||||||
assertEquals "usage" "$(cat $STDOUTF)"
|
|
||||||
assertCommandSuccess main --help
|
|
||||||
assertEquals "usage" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
function test_version(){
|
|
||||||
assertCommandSuccess main -V
|
|
||||||
assertEquals "$NAME $(cat $JUNEST_BASE/VERSION)" "$(cat $STDOUTF)"
|
|
||||||
assertCommandSuccess main --version
|
|
||||||
assertEquals "$NAME $(cat $JUNEST_BASE/VERSION)" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
function test_groot_no_root(){
|
|
||||||
is_user_root() {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
assertCommandFailOnStatus $NO_ROOT_PRIVILEGES main
|
|
||||||
}
|
|
||||||
function test_groot_no_directory(){
|
|
||||||
assertCommandFailOnStatus $NOT_EXISTING_FILE main no-directory
|
|
||||||
}
|
|
||||||
function test_groot_mountpoint_exist(){
|
|
||||||
mountpoint_mock() {
|
|
||||||
echo "mountpoint($@)"
|
|
||||||
}
|
|
||||||
MOUNTPOINT=mountpoint_mock
|
|
||||||
assertCommandSuccess main chrootdir
|
|
||||||
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 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 QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /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 QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind ${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 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 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 QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
function test_groot_with_multiple_bind(){
|
|
||||||
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir
|
|
||||||
[[ -d chrootdir/home/tmp ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
[[ -d chrootdir/dev ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /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 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
|
|
||||||
[[ -d chrootdir/home/tmp ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
[[ -d chrootdir/dev ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
function test_groot_with_bind_no_umount(){
|
|
||||||
assertCommandSuccess main -n chrootdir
|
|
||||||
assertEquals "$(echo -e "mountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
function test_groot_with_chroot_teardown(){
|
|
||||||
echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts
|
|
||||||
MOUNTS_FILE=./mounts
|
|
||||||
CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown
|
|
||||||
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
|
|
||||||
umount(/home/mychroot/proc)
|
|
||||||
umount(/home/mychroot/dev/shm)
|
|
||||||
umount(/home/mychroot/dev)
|
|
||||||
umount(/home/mychroot)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_chroot_teardown_umount_failure(){
|
|
||||||
function umount() {
|
|
||||||
echo "umount($@)"
|
|
||||||
[[ "$1" == "/home/mychroot/dev/shm" ]] && return 128
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
UMOUNT=umount
|
|
||||||
echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts
|
|
||||||
MOUNTS_FILE=./mounts
|
|
||||||
CHROOTDIR=/home/mychroot assertCommandFailOnStatus 128 chroot_teardown
|
|
||||||
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
|
|
||||||
umount(/home/mychroot/proc)
|
|
||||||
umount(/home/mychroot/dev/shm)
|
|
||||||
umount(/home/mychroot/dev)
|
|
||||||
umount(/home/mychroot)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
function test_groot_with_chroot_teardown_with_trailing_slash(){
|
|
||||||
echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts
|
|
||||||
MOUNTS_FILE=./mounts
|
|
||||||
CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown
|
|
||||||
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
|
|
||||||
umount(/home/mychroot/proc)
|
|
||||||
umount(/home/mychroot/dev/shm)
|
|
||||||
umount(/home/mychroot/dev)
|
|
||||||
umount(/home/mychroot)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_rbind(){
|
|
||||||
assertCommandSuccess main -r -b /tmp chrootdir
|
|
||||||
[[ -d chrootdir/tmp ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
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_avoid_bind_proc(){
|
|
||||||
assertCommandSuccess main -i -b /proc chrootdir
|
|
||||||
[[ -d chrootdir/proc ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(proc chrootdir/proc -t proc)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_avoid_bind_dev(){
|
|
||||||
assertCommandSuccess main -i -b /dev chrootdir
|
|
||||||
[[ -d chrootdir/dev ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(udev chrootdir/dev -t devtmpfs)\nmount(devpts /dev/pts -t devpts)\nmount(shm /dev/shm -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_avoid_bind_sys(){
|
|
||||||
assertCommandSuccess main -i -b /sys chrootdir
|
|
||||||
[[ -d chrootdir/sys ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(sys chrootdir/sys -t sysfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_avoid_bind_run(){
|
|
||||||
assertCommandSuccess main -i -b /run chrootdir
|
|
||||||
[[ -d chrootdir/run ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(run chrootdir/run -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_avoid_bind_tmp(){
|
|
||||||
assertCommandSuccess main -i -b /tmp chrootdir
|
|
||||||
[[ -d chrootdir/tmp ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_groot_with_avoid_bind_combined(){
|
|
||||||
assertCommandSuccess main -i -b /tmp -b /usr chrootdir
|
|
||||||
cat $STDERRF
|
|
||||||
[[ -d chrootdir/tmp ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
[[ -d chrootdir/usr ]]
|
|
||||||
assertEquals 0 $?
|
|
||||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nmount(--bind /usr chrootdir/usr)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
|
||||||
}
|
|
||||||
|
|
||||||
source $(dirname $0)/../utils/shunit2
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
source "$(dirname $0)/../utils/utils.sh"
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
JUNEST_BASE="$(dirname $0)/../.."
|
source "$(dirname "$0")/../utils/utils.sh"
|
||||||
source $JUNEST_BASE/bin/junest -h &> /dev/null
|
|
||||||
|
JUNEST_BASE="$(dirname "$0")/../.."
|
||||||
|
source "$JUNEST_BASE"/bin/junest -h &> /dev/null
|
||||||
|
|
||||||
# Disable the exiterr
|
# Disable the exiterr
|
||||||
set +e
|
set +e
|
||||||
|
|
@ -12,178 +14,370 @@ function oneTimeSetUp(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUp(){
|
function setUp(){
|
||||||
|
## Mock functions ##
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function usage(){
|
||||||
|
echo "usage"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function version(){
|
||||||
|
echo "version"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function build_image_env(){
|
||||||
|
local disable_check=$1
|
||||||
|
echo "build_image_env($disable_check)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function delete_env(){
|
||||||
|
echo "delete_env"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function setup_env_from_file(){
|
||||||
|
echo "setup_env_from_file($1)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function setup_env(){
|
||||||
|
echo "setup_env($1)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function run_env_as_proot_fakeroot(){
|
||||||
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
echo "run_env_as_proot_fakeroot($backend_command,$backend_args,$no_copy_files,$*)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function run_env_as_groot(){
|
||||||
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
echo "run_env_as_groot($backend_command,$backend_args,$no_copy_files,$*)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function run_env_as_chroot(){
|
||||||
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
echo "run_env_as_chroot($backend_command,$backend_args,$no_copy_files,$*)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function run_env_as_proot_user(){
|
||||||
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
echo "run_env_as_proot_user($backend_command,$backend_args,$no_copy_files,$*)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function run_env_as_bwrap_fakeroot(){
|
||||||
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
echo "run_env_as_bwrap_fakeroot($backend_command,$backend_args,$no_copy_files,$*)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function run_env_as_bwrap_user(){
|
||||||
|
local backend_command="$1"
|
||||||
|
local backend_args="$2"
|
||||||
|
local no_copy_files="$3"
|
||||||
|
shift 3
|
||||||
|
echo "run_env_as_bwrap_user($backend_command,$backend_args,$no_copy_files,$*)"
|
||||||
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
function is_env_installed(){
|
function is_env_installed(){
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
# shellcheck disable=SC2317
|
||||||
|
function create_wrappers(){
|
||||||
## Mock functions ##
|
:
|
||||||
function usage(){
|
}
|
||||||
echo "usage"
|
|
||||||
}
|
|
||||||
function version(){
|
|
||||||
echo "version"
|
|
||||||
}
|
|
||||||
function build_image_env(){
|
|
||||||
local disable_validation=$1
|
|
||||||
echo "build_image_env($disable_validation)"
|
|
||||||
}
|
|
||||||
function delete_env(){
|
|
||||||
echo "delete_env"
|
|
||||||
}
|
|
||||||
function setup_env_from_file(){
|
|
||||||
echo "setup_env_from_file($1)"
|
|
||||||
}
|
|
||||||
function setup_env(){
|
|
||||||
echo "setup_env($1)"
|
|
||||||
}
|
|
||||||
function run_env_as_fakeroot(){
|
|
||||||
local backend_args="$1"
|
|
||||||
shift
|
|
||||||
echo "run_env_as_fakeroot($backend_args,$@)"
|
|
||||||
}
|
|
||||||
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_with_namespace(){
|
|
||||||
local backend_args="$1"
|
|
||||||
shift
|
|
||||||
echo "run_env_with_namespace($backend_args,$@)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_help(){
|
function test_help(){
|
||||||
assertCommandSuccess main -h
|
assertCommandSuccess main -h
|
||||||
assertEquals "usage" "$(cat $STDOUTF)"
|
assertEquals "usage" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --help
|
assertCommandSuccess main --help
|
||||||
assertEquals "usage" "$(cat $STDOUTF)"
|
assertEquals "usage" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
function test_version(){
|
function test_version(){
|
||||||
assertCommandSuccess main -V
|
assertCommandSuccess main -V
|
||||||
assertEquals "version" "$(cat $STDOUTF)"
|
assertEquals "version" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --version
|
assertCommandSuccess main --version
|
||||||
assertEquals "version" "$(cat $STDOUTF)"
|
assertEquals "version" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
function test_build_image_env(){
|
function test_build_image_env(){
|
||||||
assertCommandSuccess main -b
|
assertCommandSuccess main b
|
||||||
assertEquals "build_image_env(false)" "$(cat $STDOUTF)"
|
assertEquals "build_image_env(false)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --build-image
|
assertCommandSuccess main build
|
||||||
assertEquals "build_image_env(false)" "$(cat $STDOUTF)"
|
assertEquals "build_image_env(false)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main -b -n
|
assertCommandSuccess main b -n
|
||||||
assertEquals "build_image_env(true)" "$(cat $STDOUTF)"
|
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)"
|
assertEquals "build_image_env(true)" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
function create_wrappers(){
|
||||||
|
local force=$1
|
||||||
|
echo "create_wrappers($force)"
|
||||||
|
}
|
||||||
|
assertCommandSuccess main create-bin-wrappers
|
||||||
|
assertEquals "create_wrappers(false)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main create-bin-wrappers --force
|
||||||
|
assertEquals "create_wrappers(true)" "$(cat "$STDOUTF")"
|
||||||
|
}
|
||||||
|
|
||||||
function test_delete_env(){
|
function test_delete_env(){
|
||||||
assertCommandSuccess main -d
|
assertCommandSuccess main s -d
|
||||||
assertEquals "delete_env" "$(cat $STDOUTF)"
|
assertEquals "delete_env" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --delete
|
assertCommandSuccess main setup --delete
|
||||||
assertEquals "delete_env" "$(cat $STDOUTF)"
|
assertEquals "delete_env" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
function test_setup_env_from_file(){
|
function test_setup_env_from_file(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
is_env_installed(){
|
is_env_installed(){
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
assertCommandSuccess main -i myimage
|
assertCommandSuccess main s -i myimage
|
||||||
assertEquals "$(echo -e "setup_env_from_file(myimage)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --setup-from-file myimage
|
assertCommandSuccess main setup --from-file myimage
|
||||||
assertEquals "$(echo -e "setup_env_from_file(myimage)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
is_env_installed(){
|
is_env_installed(){
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
assertCommandFail main -i myimage
|
assertCommandFail main setup -i myimage
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_setup_env(){
|
function test_setup_env(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
is_env_installed(){
|
is_env_installed(){
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
assertCommandSuccess main -a arm
|
assertCommandSuccess main s
|
||||||
assertEquals "$(echo -e "setup_env(arm)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
assertEquals "setup_env()" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --arch arm
|
assertCommandSuccess main setup
|
||||||
assertEquals "$(echo -e "setup_env(arm)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
assertEquals "setup_env()" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main
|
assertCommandSuccess main s -a arm
|
||||||
assertEquals "$(echo -e "setup_env()\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
assertEquals "setup_env(arm)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main setup --arch arm
|
||||||
|
assertEquals "setup_env(arm)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
is_env_installed(){
|
is_env_installed(){
|
||||||
return 0
|
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 -f -p "-b arg"
|
function test_run_env_as_proot_fakeroot(){
|
||||||
assertEquals "run_env_as_fakeroot(-b arg,)" "$(cat $STDOUTF)"
|
assertCommandSuccess main p -f
|
||||||
assertCommandSuccess main -f -p "-b arg" -- command -kv
|
assertEquals "run_env_as_proot_fakeroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertEquals "run_env_as_fakeroot(-b arg,command -kv)" "$(cat $STDOUTF)"
|
assertCommandSuccess main proot --fakeroot
|
||||||
assertCommandSuccess main -f command --as
|
assertEquals "run_env_as_proot_fakeroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertEquals "run_env_as_fakeroot(,command --as)" "$(cat $STDOUTF)"
|
assertCommandSuccess main p -f -n
|
||||||
assertCommandFail main -a "myarch" -f command --as
|
assertEquals "run_env_as_proot_fakeroot(,,true,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main p -f --backend-command blah
|
||||||
|
assertEquals "run_env_as_proot_fakeroot(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot -f --backend-command blah
|
||||||
|
assertEquals "run_env_as_proot_fakeroot(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main proot -f -b "-b arg"
|
||||||
|
assertEquals "run_env_as_proot_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot -f -b "-b arg" -- command -kv
|
||||||
|
assertEquals "run_env_as_proot_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot -f command --as
|
||||||
|
assertEquals "run_env_as_proot_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot -f -- command --as
|
||||||
|
assertEquals "run_env_as_proot_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
is_env_installed(){
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
assertCommandFail main proot -f
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_user(){
|
function test_run_env_as_user(){
|
||||||
assertCommandSuccess main
|
assertCommandSuccess main proot
|
||||||
assertEquals "run_env_as_user(,)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_proot_user(,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main p -n
|
||||||
|
assertEquals "run_env_as_proot_user(,,true,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
assertCommandSuccess main -p "-b arg"
|
assertCommandSuccess main p --backend-command blah
|
||||||
assertEquals "run_env_as_user(-b arg,)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_proot_user(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main -p "-b arg" -- command -ll
|
assertCommandSuccess main proot --backend-command blah
|
||||||
assertEquals "run_env_as_user(-b arg,command -ll)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_proot_user(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main command -ls
|
|
||||||
assertEquals "run_env_as_user(,command -ls)" "$(cat $STDOUTF)"
|
|
||||||
|
|
||||||
assertCommandFail main -a "myarch" -- command -ls
|
assertCommandSuccess main proot -b "-b arg"
|
||||||
|
assertEquals "run_env_as_proot_user(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot -b "-b arg" -- command -ll
|
||||||
|
assertEquals "run_env_as_proot_user(,-b arg,false,command -ll)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot command -ls
|
||||||
|
assertEquals "run_env_as_proot_user(,,false,command -ls)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main proot -- command -ls
|
||||||
|
assertEquals "run_env_as_proot_user(,,false,command -ls)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
is_env_installed(){
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
assertCommandFail main proot
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_groot(){
|
function test_run_env_as_groot(){
|
||||||
assertCommandSuccess main -g
|
assertCommandSuccess main g
|
||||||
assertEquals "run_env_as_groot " "$(cat $STDOUTF)"
|
assertEquals "run_env_as_groot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main -g command
|
assertCommandSuccess main g -n
|
||||||
assertEquals "run_env_as_groot command" "$(cat $STDOUTF)"
|
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 g --backend-command blah
|
||||||
|
assertEquals "run_env_as_groot(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main groot --backend-command blah
|
||||||
|
assertEquals "run_env_as_groot(blah,,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")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
is_env_installed(){
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
assertCommandFail main groot
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_chroot(){
|
function test_run_env_as_chroot(){
|
||||||
assertCommandSuccess main -r
|
assertCommandSuccess main r
|
||||||
assertEquals "run_env_as_chroot " "$(cat $STDOUTF)"
|
assertEquals "run_env_as_chroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main -r command
|
assertCommandSuccess main r -b "-b arg"
|
||||||
assertEquals "run_env_as_chroot command" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_chroot(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main r --backend-command blah
|
||||||
|
assertEquals "run_env_as_chroot(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main root --backend-command blah
|
||||||
|
assertEquals "run_env_as_chroot(blah,,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")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
is_env_installed(){
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
assertCommandFail main root -f
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_namespace(){
|
function test_run_env_as_bwrap_fakeroot(){
|
||||||
assertCommandSuccess main -u -f
|
assertCommandSuccess main n -f
|
||||||
assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main --namespace --fakeroot
|
assertCommandSuccess main ns -f
|
||||||
assertEquals "run_env_with_namespace(,)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main ns -n -f
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,,true,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
assertCommandSuccess main -u -f -p "-b arg"
|
assertCommandSuccess main ns -f -b "-b arg"
|
||||||
assertEquals "run_env_with_namespace(-b arg,)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main -u -f -p "-b arg" -- command -kv
|
assertCommandSuccess main ns -f -b "-b arg" -- command -kv
|
||||||
assertEquals "run_env_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")"
|
||||||
assertCommandSuccess main -u -f command --as
|
assertCommandSuccess main ns -f command --as
|
||||||
assertEquals "run_env_with_namespace(,command --as)" "$(cat $STDOUTF)"
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main ns -f -- command --as
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main ns -f --backend-command blah
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -f --backend-command blah
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main -f
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -f
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main -f -b "-b arg"
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -f -b "-b arg" -- command -kv
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -f command --as
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -f -- command --as
|
||||||
|
assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
is_env_installed(){
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
assertCommandFail main ns -f
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_check_cli(){
|
function test_run_env_as_bwrap_user(){
|
||||||
assertCommandFail main -b -h
|
assertCommandSuccess main n
|
||||||
assertCommandFail main -b -c
|
assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandFail main -d -s
|
assertCommandSuccess main ns
|
||||||
assertCommandFail main -n -v
|
assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandFail main -d -r
|
assertCommandSuccess main ns -n
|
||||||
assertCommandFail main -h -f
|
assertEquals "run_env_as_bwrap_user(,,true,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandFail main -v -i fsd
|
|
||||||
assertCommandFail main -f -r
|
assertCommandSuccess main ns -b "-b arg"
|
||||||
assertCommandFail main -p args -v
|
assertEquals "run_env_as_bwrap_user(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
assertCommandFail main -a arch -v
|
assertCommandSuccess main ns -b "-b arg" -- command -kv
|
||||||
assertCommandFail main -d args
|
assertEquals "run_env_as_bwrap_user(,-b arg,false,command -kv)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main ns command --as
|
||||||
|
assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main ns -- command --as
|
||||||
|
assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main ns --backend-command blah
|
||||||
|
assertEquals "run_env_as_bwrap_user(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main --backend-command blah
|
||||||
|
assertEquals "run_env_as_bwrap_user(blah,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main
|
||||||
|
assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main
|
||||||
|
assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
assertCommandSuccess main -b "-b arg"
|
||||||
|
assertEquals "run_env_as_bwrap_user(,-b arg,false,)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -b "-b arg" -- command -kv
|
||||||
|
assertEquals "run_env_as_bwrap_user(,-b arg,false,command -kv)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main command --as
|
||||||
|
assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
assertCommandSuccess main -- command --as
|
||||||
|
assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
is_env_installed(){
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
assertCommandFail main ns
|
||||||
}
|
}
|
||||||
|
|
||||||
source $(dirname $0)/../utils/shunit2
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
JUNEST_ROOT=$(readlink -f $(dirname $0)/../..)
|
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
|
||||||
|
|
||||||
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
||||||
|
|
||||||
|
|
@ -15,8 +16,9 @@ function oneTimeSetUp(){
|
||||||
|
|
||||||
## Mock functions ##
|
## Mock functions ##
|
||||||
function init_mocks() {
|
function init_mocks() {
|
||||||
function unshare_cmd(){
|
# shellcheck disable=SC2317
|
||||||
echo "unshare $@"
|
function bwrap_cmd(){
|
||||||
|
echo "$BWRAP $*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,16 +41,16 @@ function tearDown(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function _test_copy_common_files() {
|
function _test_copy_common_files() {
|
||||||
[[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat ${JUNEST_HOME}/etc/hosts)"
|
[[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat "${JUNEST_HOME}"/etc/hosts)"
|
||||||
[[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat ${JUNEST_HOME}/etc/host.conf)"
|
[[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat "${JUNEST_HOME}"/etc/host.conf)"
|
||||||
[[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat ${JUNEST_HOME}/etc/nsswitch.conf)"
|
[[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat "${JUNEST_HOME}"/etc/nsswitch.conf)"
|
||||||
[[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat ${JUNEST_HOME}/etc/resolv.conf)"
|
[[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat "${JUNEST_HOME}"/etc/resolv.conf)"
|
||||||
}
|
}
|
||||||
|
|
||||||
function _test_copy_remaining_files() {
|
function _test_copy_remaining_files() {
|
||||||
[[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat ${JUNEST_HOME}/etc/hosts.equiv)"
|
[[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat "${JUNEST_HOME}"/etc/hosts.equiv)"
|
||||||
[[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat ${JUNEST_HOME}/etc/netgroup)"
|
[[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat "${JUNEST_HOME}"/etc/netgroup)"
|
||||||
[[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat ${JUNEST_HOME}/etc/networks)"
|
[[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat "${JUNEST_HOME}"/etc/networks)"
|
||||||
|
|
||||||
[[ -e ${JUNEST_HOME}/etc/passwd ]]
|
[[ -e ${JUNEST_HOME}/etc/passwd ]]
|
||||||
assertEquals 0 $?
|
assertEquals 0 $?
|
||||||
|
|
@ -57,57 +59,183 @@ function _test_copy_remaining_files() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_is_user_namespace_enabled_no_config_file(){
|
function test_is_user_namespace_enabled_no_config_file(){
|
||||||
|
PROC_USERNS_FILE="blah"
|
||||||
|
PROC_USERNS_CLONE_FILE="blah"
|
||||||
CONFIG_PROC_FILE="blah"
|
CONFIG_PROC_FILE="blah"
|
||||||
CONFIG_BOOT_FILE="blah"
|
CONFIG_BOOT_FILE="blah"
|
||||||
assertCommandFailOnStatus $NOT_EXISTING_FILE _is_user_namespace_enabled
|
assertCommandFailOnStatus "$NOT_EXISTING_FILE" _is_user_namespace_enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_is_user_namespace_enabled_no_config(){
|
function test_is_user_namespace_enabled_no_config(){
|
||||||
|
PROC_USERNS_FILE="blah"
|
||||||
|
PROC_USERNS_CLONE_FILE="blah"
|
||||||
touch config
|
touch config
|
||||||
gzip config
|
gzip config
|
||||||
|
# shellcheck disable=SC2034
|
||||||
CONFIG_PROC_FILE="config.gz"
|
CONFIG_PROC_FILE="config.gz"
|
||||||
|
# shellcheck disable=SC2034
|
||||||
CONFIG_BOOT_FILE="blah"
|
CONFIG_BOOT_FILE="blah"
|
||||||
assertCommandFailOnStatus $NO_CONFIG_FOUND _is_user_namespace_enabled
|
assertCommandFailOnStatus "$NO_CONFIG_FOUND" _is_user_namespace_enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_is_user_namespace_enabled_with_config(){
|
function test_is_user_namespace_enabled_with_userns_clone_file_disabled(){
|
||||||
echo "CONFIG_USER_NS=y" > config
|
PROC_USERNS_FILE="blah"
|
||||||
gzip config
|
PROC_USERNS_CLONE_FILE="unprivileged_userns_clone"
|
||||||
CONFIG_PROC_FILE="config.gz"
|
echo "0" > $PROC_USERNS_CLONE_FILE
|
||||||
CONFIG_BOOT_FILE="blah"
|
assertCommandFailOnStatus "$UNPRIVILEGED_USERNS_DISABLED" _is_user_namespace_enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_is_user_namespace_enabled_with_userns_clone_file_enabled(){
|
||||||
|
PROC_USERNS_CLONE_FILE="unprivileged_userns_clone"
|
||||||
|
echo "1" > $PROC_USERNS_CLONE_FILE
|
||||||
assertCommandSuccess _is_user_namespace_enabled
|
assertCommandSuccess _is_user_namespace_enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_namespace() {
|
function test_is_user_namespace_enabled_with_proc_userns_file_existing(){
|
||||||
assertCommandSuccess run_env_with_namespace "" ""
|
PROC_USERNS_FILE="user"
|
||||||
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)"
|
ln -s . $PROC_USERNS_FILE
|
||||||
|
PROC_USERNS_CLONE_FILE="blah"
|
||||||
|
assertCommandSuccess _is_user_namespace_enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_fakeroot() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "false"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_fakeroot_with_backend_command() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_fakeroot "mybwrap" "" "false"
|
||||||
|
assertEquals "mybwrap $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_user() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_user "" "" "false"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
_test_copy_common_files
|
_test_copy_common_files
|
||||||
_test_copy_remaining_files
|
_test_copy_remaining_files
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_namespace_with_bindings() {
|
function test_run_env_as_bwrap_user_with_backend_command() {
|
||||||
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" ""
|
assertCommandSuccess run_env_as_bwrap_user "mybwrap" "" "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)"
|
assertEquals "mybwrap $COMMON_BWRAP_OPTION /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
_test_copy_common_files
|
_test_copy_common_files
|
||||||
_test_copy_remaining_files
|
_test_copy_remaining_files
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_namespace_with_command() {
|
function test_run_env_as_bwrap_fakeroot_no_copy() {
|
||||||
assertCommandSuccess run_env_with_namespace "" "ls -la"
|
assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "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 -c \"ls -la\"" "$(cat $STDOUTF)"
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /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_as_bwrap_user_no_copy() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_user "" "" "true" ""
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION /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_as_bwrap_fakeroot_with_backend_args() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_fakeroot "" "--bind /usr /usr" "false"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 --bind /usr /usr sudo /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_user_with_backend_args() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_user "" "--bind /usr /usr" "false"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --bind /usr /usr /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
_test_copy_common_files
|
_test_copy_common_files
|
||||||
_test_copy_remaining_files
|
_test_copy_remaining_files
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_namespace_with_bindings_and_command() {
|
function test_run_env_as_bwrap_fakeroot_with_command() {
|
||||||
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
|
assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "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)"
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_user_with_command() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_user "" "" "false" "ls -la"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
_test_copy_common_files
|
_test_copy_common_files
|
||||||
_test_copy_remaining_files
|
_test_copy_remaining_files
|
||||||
}
|
}
|
||||||
|
|
||||||
source $JUNEST_ROOT/tests/utils/shunit2
|
function test_run_env_as_bwrap_fakeroot_with_backend_args_and_command() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_fakeroot "" "--bind /usr /usr" "false" "ls -la"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 --bind /usr /usr sudo /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_user_with_backend_args_and_command() {
|
||||||
|
assertCommandSuccess run_env_as_bwrap_user "" "--bind /usr /usr" "false" "ls -la"
|
||||||
|
assertEquals "$BWRAP $COMMON_BWRAP_OPTION --bind /usr /usr /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
_test_copy_remaining_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_fakeroot_nested_env(){
|
||||||
|
JUNEST_ENV=1
|
||||||
|
assertCommandFailOnStatus 106 run_env_as_bwrap_fakeroot "" "" "false" ""
|
||||||
|
unset JUNEST_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_bwrap_user_nested_env(){
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
JUNEST_ENV=1
|
||||||
|
assertCommandFailOnStatus 106 run_env_as_bwrap_user "" "" "false" ""
|
||||||
|
unset JUNEST_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
source "$JUNEST_ROOT"/tests/utils/shunit2
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
JUNEST_ROOT=$(readlink -f $(dirname $0)/../..)
|
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
|
||||||
|
|
||||||
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
||||||
|
|
||||||
|
|
@ -30,16 +31,16 @@ function tearDown(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function _test_copy_common_files() {
|
function _test_copy_common_files() {
|
||||||
[[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat ${JUNEST_HOME}/etc/hosts)"
|
[[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat "${JUNEST_HOME}"/etc/hosts)"
|
||||||
[[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat ${JUNEST_HOME}/etc/host.conf)"
|
[[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat "${JUNEST_HOME}"/etc/host.conf)"
|
||||||
[[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat ${JUNEST_HOME}/etc/nsswitch.conf)"
|
[[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat "${JUNEST_HOME}"/etc/nsswitch.conf)"
|
||||||
[[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat ${JUNEST_HOME}/etc/resolv.conf)"
|
[[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat "${JUNEST_HOME}"/etc/resolv.conf)"
|
||||||
}
|
}
|
||||||
|
|
||||||
function _test_copy_remaining_files() {
|
function _test_copy_remaining_files() {
|
||||||
[[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat ${JUNEST_HOME}/etc/hosts.equiv)"
|
[[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat "${JUNEST_HOME}"/etc/hosts.equiv)"
|
||||||
[[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat ${JUNEST_HOME}/etc/netgroup)"
|
[[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat "${JUNEST_HOME}"/etc/netgroup)"
|
||||||
[[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat ${JUNEST_HOME}/etc/networks)"
|
[[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat "${JUNEST_HOME}"/etc/networks)"
|
||||||
|
|
||||||
[[ -e ${JUNEST_HOME}/etc/passwd ]]
|
[[ -e ${JUNEST_HOME}/etc/passwd ]]
|
||||||
assertEquals 0 $?
|
assertEquals 0 $?
|
||||||
|
|
@ -47,72 +48,173 @@ function _test_copy_remaining_files() {
|
||||||
assertEquals 0 $?
|
assertEquals 0 $?
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_user(){
|
function test_run_env_as_proot_user(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
_run_env_with_qemu() {
|
_run_env_with_qemu() {
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
assertCommandSuccess run_env_as_user "-k 3.10" "/usr/bin/mkdir" "-v" "/newdir2"
|
assertCommandSuccess run_env_as_proot_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)"
|
assertEquals "-b /run/user/$(id -u) -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")
|
SH=("/usr/bin/echo")
|
||||||
assertCommandSuccess run_env_as_user "-k 3.10"
|
assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false"
|
||||||
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)"
|
assertEquals "-b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
_test_copy_common_files
|
_test_copy_common_files
|
||||||
_test_copy_remaining_files
|
_test_copy_remaining_files
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_as_fakeroot(){
|
function test_run_env_as_proot_user_with_backend_command(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
_run_env_with_qemu() {
|
_run_env_with_qemu() {
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
assertCommandSuccess run_env_as_fakeroot "-k 3.10" "/usr/bin/mkdir" "-v" "/newdir2"
|
assertCommandSuccess run_env_as_proot_user "myproot" "-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)"
|
assertEquals "myproot -b /run/user/$(id -u) -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")
|
SH=("/usr/bin/echo")
|
||||||
assertCommandSuccess run_env_as_fakeroot "-k 3.10"
|
assertCommandSuccess run_env_as_proot_user "myproot" "-k 3.10" "false"
|
||||||
assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)"
|
assertEquals "myproot -b /run/user/$(id -u) -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_proot_user_no_copy(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
_run_env_with_qemu() {
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
|
}
|
||||||
|
assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "true" "/usr/bin/mkdir" "-v" "/newdir2"
|
||||||
|
assertEquals "-b /run/user/$(id -u) -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_proot_user_nested_env(){
|
||||||
|
JUNEST_ENV=1
|
||||||
|
assertCommandFailOnStatus 106 run_env_as_proot_user "" "" "false"
|
||||||
|
unset JUNEST_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_proot_fakeroot(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
_run_env_with_qemu() {
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
|
}
|
||||||
|
assertCommandSuccess run_env_as_proot_fakeroot "" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
|
||||||
|
assertEquals "-0 -b /run/user/$(id -u) -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_proot_fakeroot "" "-k 3.10" "false"
|
||||||
|
assertEquals "-0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
_test_copy_common_files
|
_test_copy_common_files
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_quotes(){
|
function test_run_env_as_proot_fakeroot_with_backend_command(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
_run_env_with_qemu() {
|
_run_env_with_qemu() {
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
assertCommandSuccess run_env_as_user "-k 3.10" "bash" "-c" "/usr/bin/mkdir -v /newdir2"
|
assertCommandSuccess run_env_as_proot_fakeroot "myproot" "-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 bash -c /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
|
assertEquals "myproot -0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
SH=("/usr/bin/echo")
|
||||||
|
assertCommandSuccess run_env_as_proot_fakeroot "myproot" "-k 3.10" "false"
|
||||||
|
assertEquals "myproot -0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
_test_copy_common_files
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_as_proot_fakeroot_nested_env(){
|
||||||
|
JUNEST_ENV=1
|
||||||
|
assertCommandFailOnStatus 106 run_env_as_proot_fakeroot "" "" "false" ""
|
||||||
|
unset JUNEST_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_run_env_with_quotes(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
_run_env_with_qemu() {
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
|
}
|
||||||
|
assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false" "bash" "-c" "/usr/bin/mkdir -v /newdir2"
|
||||||
|
assertEquals "-b /run/user/$(id -u) -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")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_run_env_with_proot_args(){
|
function test_run_env_with_proot_args(){
|
||||||
|
# shellcheck disable=SC2317
|
||||||
proot_cmd() {
|
proot_cmd() {
|
||||||
[ "$JUNEST_ENV" != "1" ] && return 1
|
[ "$JUNEST_ENV" != "1" ] && return 1
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
|
|
||||||
assertCommandSuccess _run_env_with_proot --help
|
assertCommandSuccess _run_env_with_proot "" "--help"
|
||||||
assertEquals "--help /bin/sh --login" "$(cat $STDOUTF)"
|
assertEquals "--help /bin/sh --login" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
assertCommandSuccess _run_env_with_proot --help mycommand
|
assertCommandSuccess _run_env_with_proot "" "--help" mycommand
|
||||||
assertEquals "--help /bin/sh --login -c mycommand" "$(cat $STDOUTF)"
|
assertEquals "--help /bin/sh --login -c mycommand" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
assertCommandFail _run_env_with_proot
|
assertCommandFail _run_env_with_proot
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_qemu() {
|
function test_qemu() {
|
||||||
echo "JUNEST_ARCH=arm" > ${JUNEST_HOME}/etc/junest/info
|
echo "JUNEST_ARCH=arm" > "${JUNEST_HOME}"/etc/junest/info
|
||||||
|
# shellcheck disable=SC2317
|
||||||
rm_cmd() {
|
rm_cmd() {
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
ln_cmd() {
|
ln_cmd() {
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2317
|
||||||
_run_env_with_proot() {
|
_run_env_with_proot() {
|
||||||
echo $@
|
# shellcheck disable=SC2086
|
||||||
|
# shellcheck disable=SC2048
|
||||||
|
echo $*
|
||||||
}
|
}
|
||||||
|
|
||||||
RANDOM=100 ARCH=x86_64 assertCommandSuccess _run_env_with_qemu ""
|
RANDOM=100 ARCH=x86_64 assertCommandSuccess _run_env_with_qemu "" ""
|
||||||
assertEquals "$(echo -e "-s $JUNEST_HOME/opt/qemu/qemu-arm-static-x86_64 /tmp/qemu-arm-static-x86_64-100\n-q /tmp/qemu-arm-static-x86_64-100")" "$(cat $STDOUTF)"
|
assertEquals "$(echo -e "-s $JUNEST_HOME/bin/qemu-arm-static-x86_64 /tmp/qemu-arm-static-x86_64-100\n-q /tmp/qemu-arm-static-x86_64-100")" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
source $JUNEST_ROOT/tests/utils/shunit2
|
source "$JUNEST_ROOT"/tests/utils/shunit2
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
JUNEST_ROOT=$(readlink -f $(dirname $0)/../..)
|
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
|
||||||
|
|
||||||
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
source "$JUNEST_ROOT/tests/utils/utils.sh"
|
||||||
|
|
||||||
|
|
@ -26,24 +27,27 @@ function tearDown(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_is_env_installed(){
|
function test_is_env_installed(){
|
||||||
rm -rf $JUNEST_HOME/*
|
rm -rf "${JUNEST_HOME:?}"/*
|
||||||
assertCommandFail is_env_installed
|
assertCommandFail is_env_installed
|
||||||
touch $JUNEST_HOME/just_file
|
touch "$JUNEST_HOME"/just_file
|
||||||
assertCommandSuccess is_env_installed
|
assertCommandSuccess is_env_installed
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_setup_env(){
|
function test_setup_env(){
|
||||||
rm -rf $JUNEST_HOME/*
|
rm -rf "${JUNEST_HOME:?}"/*
|
||||||
|
# shellcheck disable=SC2317
|
||||||
wget_mock(){
|
wget_mock(){
|
||||||
# Proof that the setup is happening
|
# Proof that the setup is happening
|
||||||
# inside $JUNEST_TEMPDIR
|
# inside $JUNEST_TEMPDIR
|
||||||
local cwd=${PWD#${JUNEST_TEMPDIR}}
|
local cwd=${PWD#"${JUNEST_TEMPDIR}"}
|
||||||
local parent_dir=${PWD%${cwd}}
|
local parent_dir=${PWD%"${cwd}"}
|
||||||
assertEquals "$JUNEST_TEMPDIR" "${parent_dir}"
|
assertEquals "$JUNEST_TEMPDIR" "${parent_dir}"
|
||||||
touch file
|
touch file
|
||||||
tar -czvf ${CMD}-${ARCH}.tar.gz file
|
tar -czvf "${CMD}-${ARCH}".tar.gz file
|
||||||
}
|
}
|
||||||
|
# shellcheck disable=SC2034
|
||||||
WGET=wget_mock
|
WGET=wget_mock
|
||||||
|
# shellcheck disable=SC2119
|
||||||
setup_env 1> /dev/null
|
setup_env 1> /dev/null
|
||||||
assertTrue "[ -e $JUNEST_HOME/file ]"
|
assertTrue "[ -e $JUNEST_HOME/file ]"
|
||||||
|
|
||||||
|
|
@ -52,10 +56,10 @@ function test_setup_env(){
|
||||||
|
|
||||||
|
|
||||||
function test_setup_env_from_file(){
|
function test_setup_env_from_file(){
|
||||||
rm -rf $JUNEST_HOME/*
|
rm -rf "${JUNEST_HOME:?}"/*
|
||||||
touch file
|
touch file
|
||||||
tar -czvf ${CMD}-${ARCH}.tar.gz file 1> /dev/null
|
tar -czvf "${CMD}-${ARCH}".tar.gz file 1> /dev/null
|
||||||
assertCommandSuccess setup_env_from_file ${CMD}-${ARCH}.tar.gz
|
assertCommandSuccess setup_env_from_file "${CMD}-${ARCH}.tar.gz"
|
||||||
assertTrue "[ -e $JUNEST_HOME/file ]"
|
assertTrue "[ -e $JUNEST_HOME/file ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,10 +68,10 @@ function test_setup_env_from_file_not_existing_file(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_setup_env_from_file_with_absolute_path(){
|
function test_setup_env_from_file_with_absolute_path(){
|
||||||
rm -rf $JUNEST_HOME/*
|
rm -rf "${JUNEST_HOME:?}"/*
|
||||||
touch file
|
touch file
|
||||||
tar -czf ${CMD}-${ARCH}.tar.gz file
|
tar -czf "${CMD}-${ARCH}".tar.gz file
|
||||||
assertCommandSuccess setup_env_from_file ${CMD}-${ARCH}.tar.gz
|
assertCommandSuccess setup_env_from_file "${CMD}-${ARCH}.tar.gz"
|
||||||
assertTrue "[ -e $JUNEST_HOME/file ]"
|
assertTrue "[ -e $JUNEST_HOME/file ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,4 +82,4 @@ function test_delete_env(){
|
||||||
assertCommandFail is_env_installed
|
assertCommandFail is_env_installed
|
||||||
}
|
}
|
||||||
|
|
||||||
source $JUNEST_ROOT/tests/utils/shunit2
|
source "$JUNEST_ROOT"/tests/utils/shunit2
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
source "$(dirname $0)/../utils/utils.sh"
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
|
source "$(dirname "$0")/../utils/utils.sh"
|
||||||
|
|
||||||
unset HOME
|
unset HOME
|
||||||
export HOME=$(TMPDIR=/tmp mktemp -d -t pearl-user-home.XXXXXXX)
|
export HOME
|
||||||
|
HOME=$(TMPDIR=/tmp mktemp -d -t pearl-user-home.XXXXXXX)
|
||||||
|
|
||||||
source "$(dirname $0)/../../lib/utils/utils.sh"
|
source "$(dirname "$0")/../../lib/utils/utils.sh"
|
||||||
|
|
||||||
# Disable the exiterr
|
# Disable the exiterr
|
||||||
set +e
|
set +e
|
||||||
|
|
@ -20,37 +23,42 @@ function test_check_not_null(){
|
||||||
|
|
||||||
function test_echoerr(){
|
function test_echoerr(){
|
||||||
assertCommandSuccess echoerr "Test"
|
assertCommandSuccess echoerr "Test"
|
||||||
assertEquals "Test" "$(cat $STDERRF)"
|
assertEquals "Test" "$(cat "$STDERRF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_error(){
|
function test_error(){
|
||||||
assertCommandSuccess error "Test"
|
assertCommandSuccess error "Test"
|
||||||
local expected=$(echo -e "\033[1;31mTest\033[0m")
|
local expected
|
||||||
assertEquals "$expected" "$(cat $STDERRF)"
|
expected=$(echo -e "\033[1;31mTest\033[0m")
|
||||||
|
assertEquals "$expected" "$(cat "$STDERRF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_warn(){
|
function test_warn(){
|
||||||
assertCommandSuccess warn "Test"
|
assertCommandSuccess warn "Test"
|
||||||
local expected=$(echo -e "\033[1;33mTest\033[0m")
|
local expected
|
||||||
assertEquals "$expected" "$(cat $STDERRF)"
|
expected=$(echo -e "\033[1;33mTest\033[0m")
|
||||||
|
assertEquals "$expected" "$(cat "$STDERRF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_info(){
|
function test_info(){
|
||||||
assertCommandSuccess info "Test"
|
assertCommandSuccess info "Test"
|
||||||
local expected=$(echo -e "\033[1;36mTest\033[0m")
|
local expected
|
||||||
assertEquals "$expected" "$(cat $STDOUTF)"
|
expected=$(echo -e "\033[1;36mTest\033[0m")
|
||||||
|
assertEquals "$expected" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_die(){
|
function test_die(){
|
||||||
assertCommandFail die "Test"
|
assertCommandFail die "Test"
|
||||||
local expected=$(echo -e "\033[1;31mTest\033[0m")
|
local expected
|
||||||
assertEquals "$expected" "$(cat $STDERRF)"
|
expected=$(echo -e "\033[1;31mTest\033[0m")
|
||||||
|
assertEquals "$expected" "$(cat "$STDERRF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_die_on_status(){
|
function test_die_on_status(){
|
||||||
assertCommandFailOnStatus 222 die_on_status 222 "Test"
|
assertCommandFailOnStatus 222 die_on_status 222 "Test"
|
||||||
local expected=$(echo -e "\033[1;31mTest\033[0m")
|
local expected
|
||||||
assertEquals "$expected" "$(cat $STDERRF)"
|
expected=$(echo -e "\033[1;31mTest\033[0m")
|
||||||
|
assertEquals "$expected" "$(cat "$STDERRF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_ask_null_question(){
|
function test_ask_null_question(){
|
||||||
|
|
@ -79,34 +87,12 @@ function test_ask_wrong_default_answer() {
|
||||||
assertEquals 33 $?
|
assertEquals 33 $?
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_check_and_trap_fail() {
|
|
||||||
trap echo EXIT
|
|
||||||
trap ls QUIT
|
|
||||||
assertCommandFailOnStatus 1 check_and_trap 'pwd' EXIT QUIT
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_check_and_trap() {
|
|
||||||
trap - EXIT QUIT
|
|
||||||
assertCommandSuccess check_and_trap 'echo' EXIT QUIT
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_check_and_force_trap_fail() {
|
|
||||||
trap echo EXIT
|
|
||||||
trap ls QUIT
|
|
||||||
assertCommandSuccess check_and_force_trap 'echo' EXIT QUIT
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_check_and_force_trap() {
|
|
||||||
trap - EXIT QUIT
|
|
||||||
assertCommandSuccess check_and_force_trap 'echo' EXIT QUIT
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_insert_quotes_on_spaces(){
|
function test_insert_quotes_on_spaces(){
|
||||||
assertCommandSuccess insert_quotes_on_spaces this is "a test"
|
assertCommandSuccess insert_quotes_on_spaces this is "a test"
|
||||||
assertEquals "this is \"a test\"" "$(cat $STDOUTF)"
|
assertEquals "this is \"a test\"" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
assertCommandSuccess insert_quotes_on_spaces this is 'a test'
|
assertCommandSuccess insert_quotes_on_spaces this is 'a test'
|
||||||
assertEquals "this is \"a test\"" "$(cat $STDOUTF)"
|
assertEquals "this is \"a test\"" "$(cat "$STDOUTF")"
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_contains_element(){
|
function test_contains_element(){
|
||||||
|
|
@ -116,4 +102,4 @@ function test_contains_element(){
|
||||||
assertCommandFailOnStatus 1 contains_element "blabla" "${array[@]}"
|
assertCommandFailOnStatus 1 contains_element "blabla" "${array[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
source $(dirname $0)/../utils/shunit2
|
source "$(dirname "$0")"/../utils/shunit2
|
||||||
|
|
|
||||||
139
tests/unit-tests/test-wrappers.sh
Executable file
139
tests/unit-tests/test-wrappers.sh
Executable file
|
|
@ -0,0 +1,139 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
|
source "$(dirname "$0")/../utils/utils.sh"
|
||||||
|
|
||||||
|
source "$(dirname "$0")/../../lib/core/wrappers.sh"
|
||||||
|
|
||||||
|
# Disable the exiterr
|
||||||
|
set +e
|
||||||
|
|
||||||
|
function oneTimeSetUp(){
|
||||||
|
setUpUnitTests
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUp(){
|
||||||
|
junestSetUp
|
||||||
|
}
|
||||||
|
|
||||||
|
function tearDown(){
|
||||||
|
junestTearDown
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_empty_bin(){
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers does not exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_not_executable_file(){
|
||||||
|
touch "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "myfile wrapper should not exist" "[ ! -x $JUNEST_HOME/usr/bin_wrappers/myfile ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_directory(){
|
||||||
|
mkdir -p "$JUNEST_HOME"/usr/bin/mydir
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "mydir wrapper should not exist" "[ ! -e $JUNEST_HOME/usr/bin_wrappers/mydir ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_broken_link(){
|
||||||
|
ln -s /opt/myapp/bin/cmd "$JUNEST_HOME"/usr/bin/cmd
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "cmd wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/cmd ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_executable_file(){
|
||||||
|
touch "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/myfile ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_verify_content(){
|
||||||
|
# Test for:
|
||||||
|
# https://github.com/fsquillace/junest/issues/262
|
||||||
|
# https://github.com/fsquillace/junest/issues/292
|
||||||
|
touch "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
export JUNEST_ARGS="ns --fakeroot -b '--bind /run /run2'"
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
|
||||||
|
# Mock junest command to capture the actual output generated from myfile script
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
junest(){
|
||||||
|
for arg in "$@"
|
||||||
|
do
|
||||||
|
echo "$arg"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
assertEquals "ns
|
||||||
|
--fakeroot
|
||||||
|
-b
|
||||||
|
--bind /run /run2
|
||||||
|
--
|
||||||
|
test-wrappers.sh
|
||||||
|
pacman
|
||||||
|
-Rsn
|
||||||
|
neovim
|
||||||
|
new package" "$(source "$JUNEST_HOME"/usr/bin_wrappers/myfile pacman -Rsn neovim 'new package')"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_already_exist(){
|
||||||
|
touch "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
mkdir -p "$JUNEST_HOME"/usr/bin_wrappers
|
||||||
|
echo "original" > "$JUNEST_HOME"/usr/bin_wrappers/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin_wrappers/myfile
|
||||||
|
assertCommandSuccess create_wrappers false
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/myfile ]"
|
||||||
|
assertEquals "original" "$(cat "$JUNEST_HOME"/usr/bin_wrappers/myfile)"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_forced_already_exist(){
|
||||||
|
echo "new" > "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin/myfile
|
||||||
|
mkdir -p "$JUNEST_HOME"/usr/bin_wrappers
|
||||||
|
echo "original" > "$JUNEST_HOME"/usr/bin_wrappers/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin_wrappers/myfile
|
||||||
|
assertCommandSuccess create_wrappers true
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/myfile ]"
|
||||||
|
assertNotEquals "original" "$(cat "$JUNEST_HOME"/usr/bin_wrappers/myfile)"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_executable_no_longer_exist(){
|
||||||
|
mkdir -p "$JUNEST_HOME"/usr/bin_wrappers
|
||||||
|
touch "$JUNEST_HOME"/usr/bin_wrappers/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/bin_wrappers/myfile
|
||||||
|
assertCommandSuccess create_wrappers
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]"
|
||||||
|
assertTrue "myfile wrapper should not exist" "[ ! -x $JUNEST_HOME/usr/bin_wrappers/myfile ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_create_wrappers_custom_bin_path(){
|
||||||
|
mkdir -p "$JUNEST_HOME"/usr/mybindir
|
||||||
|
touch "$JUNEST_HOME"/usr/mybindir/myfile
|
||||||
|
chmod +x "$JUNEST_HOME"/usr/mybindir/myfile
|
||||||
|
assertCommandSuccess create_wrappers false /usr/mybindir/
|
||||||
|
assertEquals "" "$(cat "$STDOUTF")"
|
||||||
|
assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/mybindir_wrappers ]"
|
||||||
|
assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/mybindir_wrappers/myfile ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
source "$(dirname "$0")"/../utils/shunit2
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
tests_succeded=true
|
tests_succeded=true
|
||||||
for tst in $(ls $(dirname $0)/test* | grep -v $(basename $0))
|
# shellcheck disable=SC2010
|
||||||
|
for tst in $(ls "$(dirname "$0")"/test* | grep -v "$(basename "$0")")
|
||||||
do
|
do
|
||||||
$tst || tests_succeded=false
|
$tst || tests_succeded=false
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -987,7 +987,7 @@ _shunit_extractTestFunctions()
|
||||||
# extract the lines with test function names, strip of anything besides the
|
# extract the lines with test function names, strip of anything besides the
|
||||||
# function name, and output everything on a single line.
|
# function name, and output everything on a single line.
|
||||||
_shunit_regex_='^[ ]*(function )*test[A-Za-z0-9_]* *\(\)'
|
_shunit_regex_='^[ ]*(function )*test[A-Za-z0-9_]* *\(\)'
|
||||||
egrep "${_shunit_regex_}" "${_shunit_script_}" \
|
grep -E "${_shunit_regex_}" "${_shunit_script_}" \
|
||||||
|sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \
|
|sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \
|
||||||
|xargs
|
|xargs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,28 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
OLD_CWD=${PWD}
|
OLD_CWD=${PWD}
|
||||||
function cwdSetUp(){
|
function cwdSetUp(){
|
||||||
ORIGIN_CWD=$(TMPDIR=/tmp mktemp -d -t junest-cwd.XXXXXXXXXX)
|
ORIGIN_CWD=$(TMPDIR=/tmp mktemp -d -t junest-cwd.XXXXXXXXXX)
|
||||||
cd $ORIGIN_CWD
|
cd "$ORIGIN_CWD" || return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function cwdTearDown(){
|
function cwdTearDown(){
|
||||||
rm -rf $ORIGIN_CWD
|
rm -rf "$ORIGIN_CWD"
|
||||||
cd $OLD_CWD
|
cd "$OLD_CWD" || return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function junestSetUp(){
|
function junestSetUp(){
|
||||||
JUNEST_HOME=$(TMPDIR=/tmp mktemp -d -t junest-home.XXXXXXXXXX)
|
JUNEST_HOME=$(TMPDIR=/tmp mktemp -d -t junest-home.XXXXXXXXXX)
|
||||||
mkdir -p ${JUNEST_HOME}/etc/junest
|
mkdir -p "${JUNEST_HOME}/usr/bin"
|
||||||
echo "JUNEST_ARCH=x86_64" > ${JUNEST_HOME}/etc/junest/info
|
mkdir -p "${JUNEST_HOME}/etc/junest"
|
||||||
mkdir -p ${JUNEST_HOME}/etc/ca-certificates
|
echo "JUNEST_ARCH=x86_64" > "${JUNEST_HOME}/etc/junest/info"
|
||||||
|
mkdir -p "${JUNEST_HOME}/etc/ca-certificates"
|
||||||
}
|
}
|
||||||
|
|
||||||
function junestTearDown(){
|
function junestTearDown(){
|
||||||
# the CA directories are read only and can be deleted only by changing the mod
|
# the CA directories are read only and can be deleted only by changing the mod
|
||||||
[ -d ${JUNEST_HOME}/etc/ca-certificates ] && chmod -R +w ${JUNEST_HOME}/etc/ca-certificates
|
[ -d "${JUNEST_HOME}/etc/ca-certificates" ] && chmod -R +w "${JUNEST_HOME}/etc/ca-certificates"
|
||||||
rm -rf $JUNEST_HOME
|
rm -rf "$JUNEST_HOME"
|
||||||
unset JUNEST_HOME
|
unset JUNEST_HOME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,15 +34,17 @@ function setUpUnitTests(){
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertCommandSuccess(){
|
function assertCommandSuccess(){
|
||||||
|
# shellcheck disable=SC2091
|
||||||
$(set -e
|
$(set -e
|
||||||
"$@" > $STDOUTF 2> $STDERRF
|
"$@" > "$STDOUTF" 2> "$STDERRF"
|
||||||
)
|
)
|
||||||
assertTrue "The command $1 did not return 0 exit status" $?
|
assertTrue "The command $1 did not return 0 exit status" $?
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertCommandFail(){
|
function assertCommandFail(){
|
||||||
|
# shellcheck disable=SC2091
|
||||||
$(set -e
|
$(set -e
|
||||||
"$@" > $STDOUTF 2> $STDERRF
|
"$@" > "$STDOUTF" 2> "$STDERRF"
|
||||||
)
|
)
|
||||||
assertFalse "The command $1 returned 0 exit status" $?
|
assertFalse "The command $1 returned 0 exit status" $?
|
||||||
}
|
}
|
||||||
|
|
@ -49,8 +54,9 @@ function assertCommandFail(){
|
||||||
function assertCommandFailOnStatus(){
|
function assertCommandFailOnStatus(){
|
||||||
local status=$1
|
local status=$1
|
||||||
shift
|
shift
|
||||||
|
# shellcheck disable=SC2091
|
||||||
$(set -e
|
$(set -e
|
||||||
"$@" > $STDOUTF 2> $STDERRF
|
"$@" > "$STDOUTF" 2> "$STDERRF"
|
||||||
)
|
)
|
||||||
assertEquals $status $?
|
assertEquals "$status" $?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue