Compare commits

...

410 commits
1.0 ... master

Author SHA1 Message Date
Filippo Squillace
0037f96e15 Add warning box for Ubuntu restriction 2024-10-12 11:53:52 +02:00
Filippo Squillace
0242749f8e Replace yay with yay-git 2024-10-12 11:34:38 +02:00
Filippo Squillace
e2d9517a92 Test enabling back the check scripts 2024-10-08 19:47:29 +02:00
Filippo Squillace
452a69cff3 Do not remove gzip during build 2024-10-08 01:10:24 +02:00
Filippo Squillace
7af01ba481 Fix pacman 7 usage during build 2024-10-08 01:04:11 +02:00
Filippo Squillace
e68c24dec6 7.4.9 2024-08-01 20:29:07 +02:00
Filippo Squillace
fd44972137 Disable the checks and fix shellcheck 2024-08-01 20:21:34 +02:00
Filippo Squillace
4d2d0fcb84 7.4.8 2024-01-09 16:41:45 +01:00
Filippo Squillace
c91e013cd4 Copy pacman.conf file if does not exist 2024-01-09 16:32:29 +01:00
Filippo Squillace
2eaf739a29
Merge pull request #339 from cosmojg/patch-2
Explain installation before quickstart/setup
2023-11-15 22:33:52 +01:00
Cosmo
e680325f5a
Explain installation before quickstart/setup
This should clear up some of the confusion that new users experience when discovering JuNest for the first time
2023-11-13 15:29:05 -05:00
Filippo Squillace
6ae9f72dd5 Add Readme update 2023-07-22 16:34:44 +02:00
Filippo Squillace
d19d2f07b6 Add buymeacoffee badge 2023-07-22 16:26:21 +02:00
Filippo Squillace
2dd84efecb 7.4.7 2023-05-31 15:07:39 +02:00
Filippo Squillace
cc1287825d
Merge pull request #332 from fsquillace/userns-check
#328 Check if `user` file exist in `ns` directory
2023-05-31 15:06:25 +02:00
Filippo Squillace
b3565e093d #328 Check if user file exist in ns directory 2023-05-31 14:57:57 +02:00
Filippo Squillace
9a06d47f76 Add shellcheck disable 2023-05-29 12:00:15 +02:00
Filippo Squillace
daa60b05e3 Fix PATH when running trap 2023-05-29 11:47:18 +02:00
Filippo Squillace
507502dc1a 7.4.5 2023-05-07 16:27:17 +02:00
Filippo Squillace
c440252f2a
Merge pull request #326 from fsquillace/wrapper-custom-path
Wrapper custom path
2023-05-07 16:26:22 +02:00
Filippo Squillace
3742c16ce0 Add documentation and unit test 2023-05-07 16:13:10 +02:00
Filippo Squillace
c2dae9021d Add integ test 2023-05-07 14:15:55 +02:00
Filippo Squillace
39508ca8a9 First commit 2023-05-07 13:59:00 +02:00
Filippo Squillace
ae365215fb 7.4.4 2023-05-06 01:38:52 +02:00
Filippo Squillace
874f52f0f8 Remove PATH setting for chroot mode 2023-05-06 00:47:14 +02:00
Filippo Squillace
71397b942b
Merge pull request #325 from escape0707/patch-1
Update README.md to accommodate that sudo-fake provides sudo
2023-05-06 00:27:47 +02:00
Escape0707
296c9e47b4 Update README.md to accommodate that sudo-fake provides sudo
Since junest/sudo-fake now provides sudo, users don't need to ignore core/sudo during the installation of base-devel. They only need to make sure not to install core/sudo manually.
2023-05-06 00:58:20 +09:00
Filippo Squillace
9b00c5c4c5 Reduce PATH when accessing to Junest session 2023-04-30 13:20:54 +02:00
Filippo Squillace
ba0ddcc524 7.4.3 2023-02-18 23:47:20 +01:00
Filippo Squillace
4db85bcf1f #318: Use multi-call wrapper 2023-02-18 00:49:54 +01:00
Filippo Squillace
369cda8dc6 7.4.2 2023-02-18 00:03:19 +01:00
Filippo Squillace
b976f767d5 Add checks for fakeroot chown 2023-02-17 23:49:06 +01:00
Filippo Squillace
95f97a62b7 #305: Add fakeroot variable to bypass chown commands 2023-02-17 18:26:13 +01:00
Filippo Squillace
6048b43218 7.4.1 2023-01-31 22:09:43 +01:00
Filippo Squillace
3fb7676277 Merge branch 'master' into dev 2023-01-31 22:08:36 +01:00
Filippo Squillace
978f64ea0a
Merge pull request #316 from cosmojg/patch-2
Fix deprecated find -perm syntax
2023-01-31 21:51:08 +01:00
Filippo Squillace
48b20848c8
Merge pull request #317 from cosmojg/patch-3
Fix grammar and improve style
2023-01-31 21:50:52 +01:00
Cosmo
632b416955
Fix grammar and improve style 2023-01-31 00:30:41 -05:00
Cosmo
0b34458fb5
Fix deprecated find -perm syntax 2023-01-30 23:51:50 -05:00
Filippo Squillace
2492583877 7.4.0 2023-01-15 23:08:40 +01:00
Filippo Squillace
a9174267b3 Add unit tests 2023-01-15 22:28:08 +01:00
Filippo Squillace
65c45517e1 Bind /run/user directory 2023-01-15 22:03:27 +01:00
Filippo Squillace
20f42f6cb7 7.3.20 2022-12-31 11:17:45 +00:00
Filippo Squillace
76c1644c63 Add discord server link 2022-12-31 11:13:25 +00:00
Filippo Squillace
1c16425b88 7.3.19 2022-12-19 23:15:38 +00:00
Filippo Squillace
fab5b0df2e Remove arch-travis and directly use docker 2022-12-19 23:12:02 +00:00
Filippo Squillace
c052e660ee 7.3.18 2022-12-18 13:43:00 +00:00
Filippo Squillace
30967bc15f Remove -d option in pacstrap 2022-12-18 13:24:29 +00:00
Filippo Squillace
60c7d1c5d0 Update keyring 2022-12-18 12:43:56 +00:00
Filippo Squillace
91f95ae4b5 Change URL to CloudFlare provider 2022-12-18 10:51:00 +00:00
Filippo Squillace
2f6e137e7e 7.3.17 2022-11-05 13:02:35 +01:00
Filippo Squillace
991aa5d7fe
Merge pull request #302 from schance995/extend-path
Extend $PATH in common.sh with system $PATH.
2022-11-05 12:53:53 +01:00
Spencer Skylar Chan
e5f14c3735 Extend $PATH in common.sh with system $PATH.
This lets junest work on non-FHS systems such as GNU Guix.
2022-10-30 00:18:58 -04:00
Filippo Squillace
f0e82bf8bf 7.3.16 2022-10-15 12:50:44 +02:00
Filippo Squillace
56761f6e63 Change url 2022-10-15 12:49:49 +02:00
Filippo Squillace
77acbf5214 7.3.15 2022-08-05 18:06:47 +02:00
Filippo Squillace
799d3bdd42 Install keyring first during the build preparation 2022-08-05 18:06:29 +02:00
Filippo Squillace
a9f5304279 #297 Create bin wrapper for symlinks 2022-08-05 18:06:29 +02:00
Filippo Squillace
df2fec0a36 7.3.14 2022-04-24 20:14:12 +00:00
Filippo Squillace
73b8bec8db Fix wrapper when passing multiple arguments and add unit tests
This change come from the PR #289
2022-04-24 19:54:32 +00:00
Filippo Squillace
98775b538f
Merge pull request #294 from fsquillace/sudoj
Default to ns mode (not fakeroot) for bin wrappers and add sudoj command
2022-04-23 19:32:10 +02:00
Filippo Squillace
0e6aa260ad Default to ns mode (not fakeroot) for bin wrappers and add sudoj command
This is related to #292
2022-04-23 17:11:55 +00:00
Filippo Squillace
21b5e3fabb 7.3.13 2022-03-01 00:43:02 +01:00
Filippo Squillace
0295f37758 Add shellcheck 2022-03-01 00:05:09 +01:00
Filippo Squillace
e7d7056e9c
Merge pull request #291 from fsquillace/create-wrappers
Create wrappers
2022-02-17 00:27:52 +01:00
Filippo Squillace
e794a6150c Add more unit tests 2022-02-16 22:55:40 +01:00
Filippo Squillace
2b9f1839f1 Add create-bin-wrappers command 2022-02-13 20:07:13 +01:00
Filippo Squillace
5630a0f035
Merge pull request #287 from neiser/master
Fix quoting in wrapper script
2022-02-13 11:06:05 +01:00
Andreas Grub
bc543a9285 Fix quoting in wrapper script
The 'eval' introduced in #262 unfortunately breaks command
invocations were a parameter contains spaces, such as

rg "my pattern with spaces"

as it would be called as `rg my pattern with
spaces`. This can be fixed using printf. Using
parameter extension quoting with ${@@Q} only
works with bash >4.4 (but only >4.0 is required).

At least the above invocation then works correctly!
2022-02-12 06:31:18 +01:00
Filippo Squillace
5f7eaff50e 7.3.12 2022-01-08 11:57:53 +01:00
Filippo Squillace
7d8c619ee0 #284 Fix copy command 2022-01-05 23:47:55 +01:00
Filippo Squillace
e6bae0647c Merge branch 'dev' into master 2021-12-31 18:21:42 +01:00
Filippo Squillace
6efc4d0f52 Update VERSION 2021-12-31 18:20:27 +01:00
Filippo Squillace
de63bdf96a Change url main repo 2021-12-31 18:09:10 +01:00
Filippo Squillace
4a1c11d4ed Fix deploy script 2021-12-20 21:19:54 +00:00
Filippo Squillace
a9d11fb4d5
Merge pull request #280 from fsquillace/dev
Dev
2021-12-20 21:57:42 +01:00
Filippo Squillace
5e97524338 Update README with proot updates 2021-12-20 18:49:22 +00:00
Filippo Squillace
14d51d9856 Merge branch 'master' into dev 2021-12-20 18:07:00 +00:00
Filippo Squillace
46cc4aad48
Merge pull request #274 from ayaka14732/patch-2
Fix installation guide in README
2021-11-03 10:34:52 +01:00
Ayaka Mikazuki
4036a7737b
Update README.md 2021-11-03 11:18:42 +08:00
Filippo Squillace
6e872c5f26 Update version and README 2021-10-13 22:33:09 +02:00
Filippo Squillace
7fe9c0e9ec Fix the --backend-command option 2021-10-13 12:23:41 +02:00
Filippo Squillace
38ab252f98 Enable all capabilities in ns fakeroot mode 2021-09-21 14:21:48 +02:00
Filippo Squillace
9ecabcd524 Change mirrorlist, update the initial message, do not inherit PATH variable and use precompiled yay during build phase 2021-09-11 14:44:35 +02:00
Filippo Squillace
86277fd589 Put the original mirror back 2021-09-11 14:44:35 +02:00
Filippo Squillace
e45d76651e First commit 2021-09-11 14:44:33 +02:00
Filippo Squillace
fc3b54e97f Authenticate to Docker hub 2021-06-19 16:46:04 +02:00
Filippo Squillace
e9406123b9 Test travis 2021-06-19 16:08:49 +02:00
Filippo Squillace
08553a447e Remove @ from wrapper 2021-03-24 11:54:17 +01:00
Filippo Squillace
6af7bae418 Fix wrappers using eval #262 2021-03-24 11:49:28 +01:00
Filippo Squillace
700b809fbe 7.3.6 2021-02-16 18:18:24 +01:00
Filippo Squillace
8e560b4a8a Make namespace check more robust and update README 2021-02-16 18:13:27 +01:00
Filippo Squillace
79e4107196 Update VERSION 2021-01-10 13:26:07 +01:00
Filippo Squillace
b8ad2182be Update README 2021-01-10 13:25:49 +01:00
Filippo Squillace
6548e19eb5 Use proper proc,dev,sys binds for ns mode 2021-01-10 13:16:48 +01:00
Filippo Squillace
8d4217492a 7.3.4 2021-01-04 21:10:31 +01:00
Filippo Squillace
f0b6f0962e Use true fakechroot/fakeroot in ns fakeroot mode 2021-01-04 19:21:07 +01:00
Filippo Squillace
4527297be1 Remove warnings when using pacman 2020-12-31 12:57:33 +01:00
Filippo Squillace
6291e5cc83 Use the Junest repo to install package deps 2020-12-30 13:35:21 +01:00
Filippo Squillace
f98fa897bf 7.3.1 2020-12-30 00:59:00 +01:00
Filippo Squillace
d3f9f13ccd Fix deploy 2020-12-30 00:58:24 +01:00
Filippo Squillace
2242585778 Merge branch 'master' into dev 2020-12-29 19:04:38 +01:00
Filippo Squillace
8844f7b5d8
Merge pull request #258 from fsquillace/archlinux-travis
Archlinux travis
2020-12-29 19:03:05 +01:00
Filippo Squillace
d25ae30158 Update README 2020-12-29 19:02:14 +01:00
Filippo Squillace
2aeb23b882 Add tests for wrappers 2020-12-29 13:09:35 +01:00
Filippo Squillace
3d16ee2583 First commit for wrappers 2020-12-29 10:46:59 +01:00
Filippo Squillace
9d2e6e4bbf Add deploy feature 2020-12-28 12:07:19 +01:00
Filippo Squillace
b75faac48f Add remaining junest tests in travis 2020-12-27 18:59:08 +01:00
Filippo Squillace
95479ba41f Use arch-travis in CI 2020-12-26 12:23:11 +01:00
Filippo Squillace
78c4f72bc1
Merge pull request #257 from hodapp512/patch-1
Update README.md for updated bind usage
2020-12-11 11:00:46 +01:00
hodapp512
26e58aaeec
Update README.md for updated bind usage 2020-12-10 11:27:15 -06:00
Filippo Squillace
8609300b20
Merge pull request #254 from fsquillace/zst
Zst
2020-09-15 19:43:07 +02:00
Filippo Squillace
440dde6564 7.2.2 2020-09-15 19:40:16 +02:00
Filippo Squillace
84f4d20370 Disable integ test for ARM 2020-09-15 19:31:24 +02:00
Filippo Squillace
98107ac07f Change format package from xz 2020-09-15 14:06:03 +02:00
Filippo Squillace
7b3685941d 7.2.1 2020-03-28 18:48:51 +01:00
Filippo Squillace
6d7bc4efa4 Add all arch in proot-static package 2020-03-28 16:54:46 +01:00
Filippo Squillace
b0169a8e5f 7.2.0 2020-03-28 15:55:08 +01:00
Filippo Squillace
12e6f6214e Add arm arch to proot 2020-03-28 13:16:40 +01:00
Filippo Squillace
500546a0e2 Fix build and proot 2020-03-28 12:57:03 +01:00
Filippo Squillace
09b9c644d9 Add option to specify location of backend command 2020-03-27 18:39:58 +01:00
Filippo Squillace
348b73ce73 Remove groot content 2020-03-24 21:18:25 +01:00
Filippo Squillace
6592bc9bd2 Separate proot, qemu, groot into packages 2020-03-22 17:53:47 +01:00
Filippo Squillace
d1285908ae
Merge pull request #240 from fsquillace/dev
Fix travis for ARM tests
2020-03-17 14:54:12 +01:00
Filippo Squillace
1580ba9c8e Fix travis for ARM tests 2020-03-16 21:34:29 +01:00
Filippo Squillace
628ac3c655 7.1.0 2020-03-16 20:12:27 +01:00
Filippo Squillace
4b5b7b300b Add test for bwrap command 2020-03-16 18:59:01 +01:00
Filippo Squillace
385dd8c68c Add script to check all tests 2020-03-15 23:49:45 +01:00
Filippo Squillace
6e55e0c648 See mirror URL only for non arm arch 2020-03-15 23:26:25 +01:00
Filippo Squillace
121f2c74f6 Improve build for ARM arch 2020-03-15 17:10:49 +01:00
Filippo Squillace
9bfd7e047d Add bwrap as backend for ns 2020-03-15 13:41:06 +01:00
Filippo Squillace
538e87f036 Add FUNDING file 2020-02-21 23:07:59 +01:00
Filippo Squillace
5b60382ca4
Merge pull request #237 from fsquillace/dev
Dev
2019-12-15 15:46:40 +01:00
Filippo Squillace
7acf16cc73
Merge pull request #236 from fsquillace/fix
Remove interface lo when checking iftop
2019-12-15 15:46:20 +01:00
Filippo Squillace
11a439499b Remove interface lo when checking iftop 2019-12-15 14:31:11 +00:00
Filippo Squillace
e0dd3257a8 Add support for ARM arch during build and check 2019-12-15 11:55:27 +00:00
Filippo Squillace
4bb9b60638 Merge branch 'dev' 2019-12-01 17:11:10 +01:00
Filippo Squillace
606353047c 7.0.2 2019-12-01 17:10:01 +01:00
Filippo Squillace
493b105faa Remove socket filename for gpg agent during build check 2019-12-01 17:06:12 +01:00
Filippo Squillace
85aeda4ac9 Update the check for building image 2019-12-01 17:06:12 +01:00
Filippo Squillace
2e8f5905c7 7.0.1 2019-12-01 17:06:12 +01:00
Filippo Squillace
82b146a57e Add rw permission to files in image 2019-12-01 17:06:12 +01:00
Filippo Squillace
e12cd8d8ff
Merge pull request #233 from soraxas/master
Fix typos in --help message
2019-11-17 10:01:52 +01:00
Oscar Lai
8d91e18ab0 fixed typos in --help message 2019-11-10 02:22:42 +11:00
Filippo Squillace
c5847b8583 7.0.1 2019-10-25 20:48:20 +02:00
Filippo Squillace
27f92d0b3f Add rw permission to files in image 2019-10-25 20:46:27 +02:00
Filippo Squillace
97d19da268
Merge pull request #231 from fsquillace/new-junest
New junest
2019-10-22 22:27:52 +02:00
Filippo Squillace
632aad46bd Small fixes 2019-10-22 22:23:12 +02:00
Filippo Squillace
de0bec9bc5 Remove yaourt package and allow not to copy common etc files 2019-10-20 22:45:40 +02:00
Filippo Squillace
3341187cf6 Change the CLI and make ns the default backend 2019-10-20 16:15:31 +02:00
Filippo Squillace
ef4bf7cd79 6.0.10 2019-08-09 23:59:18 +10:00
Filippo Squillace
00c60118fb Enable AUR tests 2019-08-09 23:42:55 +10:00
Filippo Squillace
30b743cb1b Fix keyring setup for ARM arch 2019-08-09 22:11:49 +10:00
Filippo Squillace
313ef30662 Add aurutils to the check build script 2019-08-09 21:19:37 +10:00
Filippo Squillace
691369068d Update README and change order for PATH variable 2019-06-10 17:33:31 +10:00
Filippo Squillace
fbe49acc01 6.0.9 2018-10-31 21:51:23 +11:00
Filippo Squillace
98c97ddfa7 Merge branch 'dev' 2018-10-31 21:50:34 +11:00
Filippo Squillace
6361522e40 Fix aur validation tests and include sudo-fake in codebase 2018-10-31 20:53:08 +11:00
Filippo Squillace
cc351f419d Add check for disabled unprivileged user namespace 2018-10-28 17:34:45 +11:00
Filippo Squillace
bca7e565ca
Merge pull request #210 from DroidFreak32/patch-1
Fix JuNest image URL
2018-08-11 10:26:31 +10:00
DroidFreak32
34f3458335
Fix JuNest image URL 2018-07-21 18:04:43 +05:30
Filippo Squillace
5172093fe2 6.0.8 2017-09-23 22:35:35 +10:00
Filippo Squillace
5bc4cd245a :doc: x86 (32 bit) is deprecated 2017-09-23 22:33:46 +10:00
Filippo Squillace
0d7468b516 Merge pull request #200 from fsquillace/docs_and_nested_envs
Docs and nested envs
2017-09-18 17:02:06 +02:00
Filippo Squillace
d858d577c8 Fix checks for updating Arch Linux keyrings 2017-09-18 16:59:35 +02:00
Filippo Squillace
f60bbb5c2a Issue #195: Check presence of nested env first 2017-09-18 13:48:34 +02:00
Filippo Squillace
b2ba7f9d5b Issue #197: Differences between JuNest and other systems 2017-09-18 13:45:33 +02:00
Filippo Squillace
4b6fd63cf8 Inform with a warn in case SECCOMP gets disabled 2017-06-23 14:51:29 +02:00
Filippo Squillace
9cd13c88f6 6.0.7 2017-04-25 22:57:37 +01:00
Filippo Squillace
797853bbb4 Merge pull request #192 from fsquillace/activate_aur_test_namespac
Activate aur test namespac
2017-04-25 22:56:41 +01:00
Filippo Squillace
358f92d3e0 Remove package-query as a dependency for building JuNest Image 2017-04-25 22:53:10 +01:00
Filippo Squillace
c3610ec86a Activate the aur check for namespace mode 2017-04-25 09:17:03 +01:00
Filippo Squillace
22483b9ea9 6.0.6 2017-04-25 00:26:17 +01:00
Filippo Squillace
3eada1e4f1 Merge pull request #191 from fsquillace/issue_check_script_fix
Update the system before running checks
2017-04-25 00:25:34 +01:00
Filippo Squillace
8fe650ce87 Update the system before running checks 2017-04-25 00:22:09 +01:00
Filippo Squillace
d6d6883e82 6.0.5 2017-04-24 23:11:48 +01:00
Filippo Squillace
f9f7cbcaaa Update the check script to exclude sudo from base-devel 2017-04-24 23:10:32 +01:00
Filippo Squillace
51f6765634 6.0.4 2017-04-24 21:47:48 +01:00
Filippo Squillace
c2d5985fe3 Merge pull request #190 from fsquillace/issue_184_aur_namespace
Issue #184: Add `sudo-fake` to JuNest image
2017-04-24 09:47:50 +01:00
Filippo Squillace
7ebdf628cf Issue #184: Add sudo-fake to JuNest image 2017-04-24 09:21:40 +01:00
Filippo Squillace
35fce94c4e 6.0.3 2017-04-20 20:23:18 +01:00
Filippo Squillace
73b4b85399 Merge pull request #188 from fsquillace/issue_replace_mountpoint
Replace `mountpoint` command by checking mounts file
2017-04-20 20:20:18 +01:00
Filippo Squillace
bd0e9fbbcc Replace mountpoint command by checking mounts file
`mountpoint` does not detect some directory. By checking directly
from `/proc/self/mounts` groot can be more reliable and portable.
2017-04-20 20:19:04 +01:00
Filippo Squillace
137788a98a Groot: Do not umount directories that are not mountpoint 2017-04-19 23:52:26 +01:00
Filippo Squillace
b9e34d3e96 6.0.2 2017-04-19 22:36:09 +01:00
Filippo Squillace
7b2dee540f 🐛 Fix location of the check script during image build 2017-04-19 22:35:03 +01:00
Filippo Squillace
a2c40902a2 6.0.1 2017-04-19 21:19:55 +01:00
Filippo Squillace
9849062292 Merge pull request #187 from fsquillace/issue_fix_groot
Add -i and -r options for groot command
2017-04-19 21:18:40 +01:00
Filippo Squillace
03a29590de Add -i and -r options for groot command 2017-04-19 21:04:51 +01:00
Filippo Squillace
02650b754e 6.0.0 2017-04-18 20:51:37 +01:00
Filippo Squillace
3456857d7a Merge pull request #183 from fsquillace/issue_174_namespace
Issue 174 namespace
2017-04-18 12:38:10 +01:00
Filippo Squillace
665c45b7aa Issue #182: Update doc with comparison table on the execution modes 2017-04-18 09:11:32 +01:00
Filippo Squillace
0060658726 Issue #174: Add util-linux in JuNest image
util-linux contains `unshare` which is needed for the namespace mode.
2017-04-12 20:43:35 +01:00
Filippo Squillace
b817aa8445 Issue #174: Add -g option for Groot and integ tests for user namespace 2017-04-12 20:43:30 +01:00
Filippo Squillace
fcb4a36f30 Issue #174: Add option -n in groot and umount directories in order 2017-04-12 20:43:21 +01:00
Filippo Squillace
8e5531a27a Issue #174: Add unit test for namespace 2017-04-12 20:43:12 +01:00
Filippo Squillace
0f7fd33c53 Issue #174: Add new program GRoot and change version option for JuNest!
This replaces jchroot because GRoot can be also used in a user namespace environment.
2017-04-12 20:42:56 +01:00
Filippo Squillace
426b708d2d Issue #174: Rename common functions and define skeleton for namespace functions 2017-04-12 20:42:35 +01:00
Filippo Squillace
0ec35a4088 Issue #174: Add namespace module and check for user namespace 2017-04-12 20:42:10 +01:00
Filippo Squillace
f85c62274f 5.6.12 2017-03-18 15:56:14 +00:00
Filippo Squillace
2ed75c8545 🐛 Fix jchroot according to refactor 2017-03-18 15:55:03 +00:00
Filippo Squillace
7a6ef3f0f9 5.6.11 2017-03-18 15:34:35 +00:00
Filippo Squillace
3111c4253d Merge pull request #178 from fsquillace/fix-url
Create the proper S3 bucket for JuNest
2017-03-18 15:31:52 +00:00
Filippo Squillace
72640b3ca3 Create the proper S3 bucket for JuNest 2017-03-18 14:53:48 +00:00
Filippo Squillace
b3a41d1d52 5.6.10 2017-03-16 21:34:03 +00:00
Filippo Squillace
97b4a7b40d Merge pull request #177 from fsquillace/fix-url
Move to S3 service for hosting the JuNest images
2017-03-16 21:32:25 +00:00
Filippo Squillace
adcfe7c8dc Move to S3 service for hosting the JuNest images
Dropbox Public folder became private:
https://www.dropbox.com/help/16
2017-03-16 19:40:54 +00:00
Filippo Squillace
b58c946c45 Merge pull request #176 from fsquillace/issue_174_namespace
Issue #174: 🎨 Change structure of core modules
2017-03-13 21:42:45 +00:00
Filippo Squillace
ddc7ede70a Issue #174: 🎨 Change structure of core modules
This change separate different parts of the code into several categories:
`chroot`, `proot`, `build`, `common`, `setup`. This should simplify the
maintenance of the code and will help introducing the user namespace module
in a easier way.
2017-03-13 21:06:18 +00:00
Filippo Squillace
54a09245d2 Merge pull request #175 from cfriesicke/issue_172_recommended_kernel
Recommend minimum kernel 2.6.32; add Q&A entry for private futex warning
2017-03-11 17:22:13 +00:00
Christian Friesicke
bee9e2df54 📝 Add Q&A entry about private futex warning
Since this problem can be pin-pointed to kernel versions that are older
than 2.6.22, a Q&A entry separate from the more general "Kernel too
old" problem may be justified.

This Q&A entry discusses the origin of the problem, some of the
symptoms (no symptoms for "simple" programs like vim, but warnings and
crashes for others), and concludes with a remark about possible (but
complicated) workarounds.
2017-03-11 17:45:54 +01:00
Christian Friesicke
978ab8d408 📝 Recommend kernel version 2.6.32
Reasoning: the pre-compiled binaries that are downloaded by JuNest
during installation as well as binaries that are available from the Arch
repositories are compiled for Linux kernel 2.6.32. Therefore, with
kernel version 2.6.32 on the host OS no warnings, errors, or unexpected
crashes due to kernel version incompatibilities should be expected.

The recommended kernel version is now mentioned in the "Dependencies"
section of the README. In the "Troubleshooting" section about "Kernel
too old", more specific information about the problem and the workaround
using PRoot -k option is added.

Resolves: #172
2017-03-11 17:33:22 +01:00
Filippo Squillace
615e20eff8 Merge pull request #173 from fsquillace/issue_fixes
Substitute bindings with explicit copy of files
2017-03-11 10:48:13 +00:00
Filippo Squillace
d07b06b39d Substitute bindings with explicit copy of files 2017-03-11 10:17:55 +00:00
Filippo Squillace
46221f26b1 Merge pull request #166 from fsquillace/passwd_user
Passwd user
2016-11-27 19:49:24 +00:00
Filippo Squillace
6568430add Mitigate user missing from getent enumeration
Sometimes `getent passwd` does not give the user information.
This change tries to at least get the current user via
`getent passwd $USER` since it uses
a more reliable and faster system call (getpwnam(3)).

Reference:
be748493a3
2016-11-27 12:49:09 +00:00
Filippo Squillace
6d4e5f7404 5.6.9 2016-06-09 22:14:52 +01:00
Filippo Squillace
56a5f48b32 Use the new junest-git package 2016-06-09 21:14:35 +01:00
Filippo Squillace
55a4ffd78a 5.6.8 2016-06-07 23:24:49 +01:00
Filippo Squillace
33214edcef Merge pull request #152 from fsquillace/issue_81_passwd
Issue 81 passwd
2016-06-07 22:45:37 +01:00
fsquillace
846bcc9c1f Issue #81: Use getent to build the passwd and group files 2016-06-07 22:24:28 +01:00
fsquillace
147798117b 📝 Fix path to unit tests 2016-05-31 20:27:27 +01:00
Filippo Squillace
6084218598 Merge pull request #151 from fsquillace/add_logo
📝 Add logo and refactor README.md
2016-05-31 19:00:18 +01:00
fsquillace
709ceda12f 📝 Add logo and refactor README.md 2016-05-31 18:26:43 +01:00
Filippo Squillace
e4e43f004d Merge pull request #150 from fsquillace/issue_141_refactor
Issue 141 refactor
2016-05-31 09:07:53 +01:00
fsquillace
c114590ea9 📝 Update README for installation process and change the bash version 2016-05-30 23:01:28 +01:00
fsquillace
374cb2e42e Move the unit tests to a specific folder 2016-05-30 23:01:28 +01:00
fsquillace
195d8d0069 Update travis 2016-05-30 23:01:28 +01:00
fsquillace
1f66d810cd Remove check for mtab file and lock directory 2016-05-30 23:01:28 +01:00
fsquillace
3102ff1d8a 🎨 Refactor core.sh code 2016-05-30 23:01:28 +01:00
fsquillace
19f4848a9d 🎨 Substitute tab chars with whitespace 2016-05-30 23:01:28 +01:00
fsquillace
ce3fefeab5 Issue #141: 🎨 Refactor code 2016-05-30 23:01:26 +01:00
Filippo Squillace
b7f10dc55b 📝 Update CONTRIBUTING.md and change unit tests file names 2016-05-11 22:40:12 +01:00
Filippo Squillace
360995492c Merge pull request #139 from fsquillace/issue_138_pkgfile
Issue #138: pkgfile documentation
2016-02-26 23:31:30 +00:00
Filippo Squillace
ea3af255cf Issue #138: pkgfile documentation 2016-02-26 23:21:52 +00:00
Filippo Squillace
421d8034c0 Merge pull request #136 from fsquillace/contributing
Contributing
2016-01-30 12:39:27 +00:00
Filippo Squillace
d36093b0f5 Change the name of proot variable 2016-01-30 12:14:44 +00:00
Filippo Squillace
0ecd1b297b Add CONTRIBUTING.md file 2016-01-30 12:14:36 +00:00
builder
846b47ff3a Small fix in usage function 2015-12-26 15:56:07 +00:00
builder
c10c8713bb Fix proot arguments help 2015-12-26 13:31:24 +00:00
Filippo Squillace
acfaed0dd4 Merge pull request #133 from fsquillace/issue_127_mtab
Issue #127: Do not let proot mount the mtab file
2015-12-26 12:57:03 +00:00
builder
36212d3cbf Issue #127: Do not let proot mount the mtab file
This change prevents inconsistency problems when the JuNest environment
is run simultaneously in fakeroot and normal user. The mtab file is
never mount by proot but, instead, it is symlinked to /proc/self/mounts.
2015-12-26 12:55:19 +00:00
Filippo Squillace
3beab7fc74 Merge pull request #132 from adamcavendish/patch-1
Add a message for showing proot arguments help
2015-12-13 20:19:06 +00:00
Adam Basfop Cavendish
6116585fb8 Add a message for showing proot arguments help 2015-12-14 01:14:45 +08:00
Filippo Squillace
aaa70898ad Merge pull request #129 from fsquillace/gratipay-badge
Gratipay badge and LANG fix
2015-12-01 20:35:46 +00:00
Filippo Squillace
c6bb53e2cc Issue #128: Fix the /etc/locale.conf file 2015-12-01 19:52:11 +00:00
Filippo Squillace
336652ccf6 Add gratipay badge 2015-10-30 21:37:14 +00:00
Filippo Squillace
5502966276 Update the version to 5.6.7 (Nitida) 2015-10-24 16:40:28 +00:00
Filippo Squillace
90510f8da9 Add OpenHub badge and TOC in README 2015-10-22 00:01:35 +00:00
Filippo Squillace
fd28e511fc Update README with junest-builder reference 2015-10-19 18:51:11 +00:00
Filippo Squillace
016c028da1 Merge pull request #122 from fsquillace/issue_116_gpg_agent
Issue #116: Kill gpg-agent during build of image
2015-10-18 21:50:37 +01:00
Filippo Squillace
dbc6f7ad12 Issue #116: Kill gpg-agent during build of image
Use jchroot instead of arch-chroot since it is more reliable on
all architectures.
2015-10-18 17:20:59 +00:00
Filippo Squillace
73e222300f Merge pull request #121 from fsquillace/issue_114_umask
Issue #114: Add umask on build image script
2015-10-16 13:50:45 +01:00
Filippo Squillace
1aa7a3ddbd Issue #114: Add umask on build image script 2015-10-16 09:28:10 +00:00
Filippo Squillace
88992cc503 Small fix in the proot seccomp test 2015-10-15 22:39:02 +00:00
Filippo Squillace
f6cd31996d Merge pull request #120 from fsquillace/fallback
Issue #113: Fix fallback for proot command
2015-10-15 19:39:17 +01:00
Filippo Squillace
2cfb81daaa Issue #113: Fix fallback for proot command 2015-10-14 23:39:36 +00:00
Filippo Squillace
cfa512755f Update contacts in docs 2015-08-29 18:30:59 +00:00
Filippo Squillace
f3ad4571f0 Merge pull request #105 from fsquillace/issue_104_newaur
Issue 104 newaur
2015-08-08 23:39:20 +01:00
Filippo Squillace
6365d52f50 Issue #104: Use junest-git package in the image 2015-08-08 09:57:23 +00:00
Filippo Squillace
e0a9ee3b26 Change URLs for the AUR repository system 2015-08-07 12:48:08 +00:00
Filippo Squillace
06879b277c Merge pull request #103 from fsquillace/issue_102_aur
Issue #102: Update README for installing JuNest via AUR
2015-08-05 09:42:29 +01:00
Filippo Squillace
f3c043ee15 Issue #102: Update README for installing JuNest via AUR 2015-08-04 15:17:42 +00:00
Filippo Squillace
ccfe4c79ea Merge pull request #99 from fsquillace/issue_94_test_arch
Issue #94: Add tests for arch option
2015-07-18 19:31:10 +01:00
Filippo Squillace
6b357245c3 Issue #94: Add tests for arch option 2015-07-18 17:16:38 +00:00
Filippo Squillace
9e633b77e0 Merge pull request #98 from fsquillace/issue_96_check
Issue #96: Add the check option
2015-07-17 23:47:12 +01:00
Filippo Squillace
7f3919700a Issue #96: Add the check option 2015-07-17 22:32:07 +00:00
Filippo Squillace
47f496a692 Merge pull request #97 from fsquillace/issue_93_metadata
Issue 93 metadata
2015-07-05 15:50:42 +01:00
Filippo Squillace
e2b14e9bff Issue #93: Improve help and add test for proot access 2015-07-05 14:20:07 +00:00
Filippo Squillace
438eeafb63 Issue #93: Add test for chroot 2015-07-05 11:46:35 +00:00
Filippo Squillace
b7ad845771 Issue #93: Add JuNest metadata 2015-07-04 23:46:27 +00:00
Filippo Squillace
d27f790562 Issue #95: Document the uname executable 2015-06-29 21:56:47 +00:00
Filippo Squillace
7b026c133c Merge pull request #92 from fsquillace/issue_91_arch
Issue 91 arch
2015-06-29 20:59:40 +01:00
Filippo Squillace
0cf7c624ec Issue #91: Add the architecture option 2015-06-29 19:57:07 +00:00
Filippo Squillace
8475d8eb41 Fix the build of x86 image 2015-06-29 15:04:31 +00:00
Filippo Squillace
45814d65a5 Refactor the chroot script 2015-06-28 13:08:48 +00:00
Filippo Squillace
98a1ef5bf0 Issue #88: Copy qemu static and all proot compat binaries 2015-06-24 18:34:10 +00:00
Filippo Squillace
2cae586c34 Use SUDO_USER instead of SUDO_UID 2015-06-24 18:33:02 +00:00
Filippo Squillace
59d71111b1 Merge pull request #90 from fsquillace/issue_89_true
Issue 89 true
2015-06-24 09:38:03 +01:00
Filippo Squillace
e3a0726a19 Remove binutils from the image 2015-06-23 22:45:15 +00:00
Filippo Squillace
21f3b6ebda Issue #89: Remove id executable 2015-06-23 22:45:15 +00:00
Filippo Squillace
a5346f8154 Issue #89: Remove the _run_proot function 2015-06-23 22:45:14 +00:00
Filippo Squillace
5e19ac138e Issue #89: Adjust the tests 2015-06-23 22:45:05 +00:00
Filippo Squillace
8425b09fce Issue #89: Remove the true executable 2015-06-23 07:56:49 +00:00
Filippo Squillace
dc8018a4b9 Merge pull request #87 from fsquillace/issue_74_chroot
Issue 74 chroot
2015-06-23 08:55:45 +01:00
Filippo Squillace
be3f771cee Issue #74: Update doc and remove arch-install-scripts from JuNest image 2015-06-22 22:01:56 +00:00
Filippo Squillace
f15dc54b38 Issue #74: Apply chroot_cmd function 2015-06-22 21:21:30 +00:00
Filippo Squillace
e4b6bbb974 Issue #74: Substitute arch-chroot to jchroot 2015-06-22 21:21:24 +00:00
Filippo Squillace
3dc3a830a2 Issue #74: Create the initial chroot skeleton 2015-06-20 21:54:23 +00:00
Filippo Squillace
5c2c52f94c Merge pull request #86 from fsquillace/issue_79_fallback
Issue 79 fallback
2015-06-20 16:22:59 +01:00
Filippo Squillace
6994a6b2e6 Issue #79: Apply the new executables 2015-06-20 14:49:51 +00:00
Filippo Squillace
5773c42f04 Issue #79: Add tests for ln, rm, chown and mkdir commands 2015-06-20 14:49:51 +00:00
Filippo Squillace
29d76a01a9 Issue #79: Create the initial functions 2015-06-20 14:49:46 +00:00
Filippo Squillace
eea6d6e150 Add badges in README 2015-06-06 12:38:03 +00:00
Filippo Squillace
622cb88587 Remove the nano editor
Since there is a default URL mirror the nano editor
is no longer needed in the image as default.
2015-06-03 22:09:11 +00:00
Filippo Squillace
e42cd2fc37 Update README 2015-06-03 21:32:36 +00:00
Filippo Squillace
108fe1d456 Improve the validation of the image 2015-05-28 17:58:00 +00:00
Filippo Squillace
4a7e46d42f Remove the last word section 2015-05-25 21:00:28 +00:00
Filippo Squillace
4d1b76f72f Merge pull request #83 from fsquillace/junest
Junest
2015-05-25 21:39:39 +01:00
Filippo Squillace
82cb6caa14 Issue #63: Change name to JuNest! 2015-05-25 17:52:45 +00:00
Filippo Squillace
c7638f0655 Update the README 2015-05-23 18:51:46 +00:00
Filippo Squillace
2a6ced8b9b Merge pull request #82 from fsquillace/issue_63_newname
New name for the project: JuJube!
2015-05-17 16:13:30 +01:00
Filippo Squillace
39b0e941b8 Issue #63: Change name to JuJube! 2015-05-17 15:09:54 +00:00
Filippo Squillace
1e3f25d5cb Issue #63: Parametrize the environment name 2015-05-15 19:56:11 +00:00
Filippo Squillace
85d8e2ddeb Issue #73: Ensure to delete mtab in normal user 2015-05-10 16:11:38 +00:00
Filippo Squillace
925730784a Merge pull request #75 from fsquillace/issue_73_mtab
Issue #73: Remove mtab symlink and avoid some error suppressions
2015-05-06 23:36:35 +01:00
Filippo Squillace
6e6d714127 Issue #73: Remove mtab symlink and avoid some error suppressions 2015-05-05 23:26:47 +00:00
Filippo Squillace
03d687ed12 Merge pull request #72 from fsquillace/issue_71_chroot
Issue #71: Use chroot to fallback in root mode
2015-05-02 22:48:50 +01:00
Filippo Squillace
00f0ee3b6a Issue #71: Use chroot to fallback in root mode 2015-05-02 21:13:07 +00:00
Filippo Squillace
ad19933d00 Improve the validation function 2015-04-16 01:52:39 +02:00
Filippo Squillace
9ae8bf787c Issue #69: Add default mirror URL 2015-04-15 04:01:51 +02:00
Filippo Squillace
47c017f1a4 Merge pull request #70 from fsquillace/issue_58
Issue 58
2015-04-09 00:24:57 +01:00
Filippo Squillace
fa440287fe Ensure to have assign ownership to the user on root access 2015-04-09 03:26:57 +02:00
Filippo Squillace
3180cd63f8 Issue #58: Fix on root access 2015-04-09 03:10:15 +02:00
Filippo Squillace
4214206da0 Issue #58: Update travis for install AUR packages 2015-04-04 17:00:37 +02:00
Filippo Squillace
0a0aac52f5 Fix the test_all.sh 2015-04-04 16:32:40 +02:00
Filippo Squillace
8d9dda2453 Issue #58: Fix the command execution under CLI 2015-04-04 16:29:55 +02:00
Filippo Squillace
166a629086 Update travis link 2015-03-29 22:17:36 +02:00
Filippo Squillace
119d3c3430 Issue #67: Add shunit for test_core 2015-03-27 14:49:03 +01:00
Filippo Squillace
32e986ee0e Issue #67: Add shunit for test_juju 2015-03-27 01:53:35 +01:00
Filippo Squillace
3d26d98154 Issue #67: Add shunit for test_util 2015-03-27 00:28:44 +01:00
Filippo Squillace
180d154f6b Issue #68: Check the JuJu deletion 2015-03-25 23:15:11 +01:00
Filippo Squillace
c7d3b150ab Issue #68: Update README with build status 2015-03-25 23:15:01 +01:00
Filippo Squillace
f53f6353e6 Issue #68: First travis.yml version 2015-03-25 23:14:44 +01:00
Filippo Squillace
e058c3523d Issue #18: Update README for JuJu as a container 2015-02-15 16:44:12 +01:00
Filippo Squillace
6bb2574642 Merge pull request #62 from fsquillace/disable_validation
Issue #61: Add disable validation option
2015-02-12 02:05:03 +01:00
Filippo Squillace
5405d4fb91 Issue #61: Add disable validation option 2015-02-12 01:29:31 +01:00
Filippo Squillace
8c896aea8a Update copyright year 2015-02-01 18:40:23 +01:00
Filippo Squillace
ce2ad7afb1 Improve the README file 2015-01-31 13:24:37 +01:00
Filippo Squillace
c241e2329d Issue #29: Changing ownership of the files at exit of chroot 2015-01-30 18:07:05 +01:00
Filippo Squillace
41a6236313 Issue #53: Validation test for JuJu image 2015-01-28 00:48:17 +01:00
Filippo Squillace
fa1379b406 Merge pull request #57 from fsquillace/issue_65_arguments
Issue 65 arguments
2015-01-27 23:36:22 +01:00
Filippo Squillace
e82cc672f6 Issue #56: Fix tests 2015-01-27 01:11:30 +01:00
Filippo Squillace
30f630973d Issue #56: Allow quotes on command passed to CLI 2015-01-27 00:44:41 +01:00
Filippo Squillace
30d8931ec5 Issue #56: Fix arguments 2015-01-25 20:41:39 +01:00
Filippo Squillace
3283c59e94 Issue #49: Fix yaourt and makepkg by applying patches 2015-01-19 01:08:17 +01:00
Filippo Squillace
fd4c8ae02e Fix test for running proot as root 2015-01-18 13:54:49 +01:00
Filippo Squillace
ca3be673a4 Fix issue #54: tests and the check for root access to proot 2015-01-17 19:15:41 +01:00
Filippo Squillace
239230ebf3 Update the version to 3.6.9 (Snake) 2015-01-15 23:29:34 +01:00
Filippo Squillace
58e6143db0 Fix issue #49: Change the permission to build the image and adapt for arm architecture 2015-01-15 01:10:48 +01:00
Filippo Squillace
cf9eaed98b Fix issue #52: Add new installation method in README 2015-01-13 01:49:42 +01:00
Filippo Squillace
aa76e6cff5 Wrap the tar into a variable 2015-01-12 23:18:05 +01:00
Filippo Squillace
740824c892 Fix issue #51: Enable curl redirection 2015-01-11 02:11:20 +01:00
Filippo Squillace
01bf1738a6 Fix issue #49: Optimize image and docs
- Remove sed command from the image
- Use proot for faking the user on compiling of packages
- Add link to README for pacman rosetta
2015-01-10 21:37:31 +01:00
Filippo Squillace
2189b52fc9 Merge pull request #50 from fsquillace/issue_49
Fix issue #49: Adapt image with the new pacman version
2015-01-09 20:37:35 +01:00
Filippo Squillace
8033367988 Fix issue #49: Adapt image with the new pacman version 2015-01-09 20:33:02 +01:00
Filippo Squillace
6ff8694b9c Merge pull request #48 from fsquillace/issue_46
Fix issue #46: Deprecate getopt
2015-01-09 00:30:12 +01:00
Filippo Squillace
7610e75260 Fix issue #46: Deprecate getopt 2015-01-09 00:26:24 +01:00
Filippo Squillace
ebc9dcbd38 Merge pull request #47 from fsquillace/issue_43
Issue 43
2015-01-08 20:03:30 +01:00
Filippo Squillace
ccb4fa6325 Fix issue #43 2015-01-08 01:44:42 +01:00
Filippo Squillace
91832ba2b8 Refactor _run_proot function 2015-01-08 00:47:49 +01:00
Filippo Squillace
b4dfd79819 Fix issue #45 2015-01-08 00:45:41 +01:00
Filippo Squillace
f3ab18d628 Merge pull request #44 from fsquillace/issue_42
Fix issue #42
2015-01-06 00:26:10 +01:00
Filippo Squillace
4cf8cadd20 Fix issue #42 2015-01-06 00:25:01 +01:00
Filippo Squillace
5ebc099249 Merge pull request #41 from fsquillace/issue_40
Fix issue #40
2015-01-05 23:47:28 +01:00
Filippo Squillace
1c30ed26cb Fix issue #40 2015-01-04 22:22:32 +01:00
Filippo Squillace
1cab9ba2cf Merge branch 'dev' of github.com:fsquillace/juju into dev 2014-12-23 15:40:14 +01:00
Filippo Squillace
022e4f9094 Update doc for the new compat binary 2014-12-23 15:39:18 +01:00
Filippo Squillace
2068df5126 Fix tests 2014-12-23 15:39:18 +01:00
Filippo Squillace
d94a9562c8 Change test for compatibility with old environment 2014-12-23 15:39:18 +01:00
Filippo Squillace
c34eba1b0a Fix issue #36
- Add tests for proot compat
2014-12-23 15:39:18 +01:00
Filippo Squillace
d25799652a Add proot compat binary 2014-12-23 15:39:18 +01:00
Filippo Squillace
12507bfaed Fix issue #38 2014-12-23 15:39:18 +01:00
Filippo Squillace
2a1e4477f5 Add link to README.md 2014-12-23 15:39:18 +01:00
Filippo Squillace
f6cac03cc1 Add sed command to JuJu image 2014-12-23 15:39:16 +01:00
Filippo Squillace
92f4ad8976 Remove the juju.sh profile since juju could be used internally 2014-12-23 15:39:04 +01:00
Filippo Squillace
c0a41ca1ca Fix issue #31 2014-12-23 15:39:02 +01:00
Filippo Squillace
6ec61a938a Fix issue #32 2014-12-23 15:38:46 +01:00
Filippo Squillace
670e0fa8b7 Merge pull request #39 from fsquillace/proot_comp
Proot compatible binary
2014-12-23 15:26:17 +01:00
Filippo Squillace
63d2423449 Update doc for the new compat binary 2014-12-23 15:23:41 +01:00
Filippo Squillace
a91729820e Fix tests 2014-12-23 14:48:22 +01:00
Filippo Squillace
460a0a595e Change test for compatibility with old environment 2014-12-23 13:33:05 +01:00
Filippo Squillace
410b7512d4 Fix issue #36
- Add tests for proot compat
2014-12-23 02:07:40 +01:00
Filippo Squillace
be1bd7b487 Fix issue #38 2014-12-21 21:34:24 +01:00
Filippo Squillace
97c03a5961 Add proot compat binary 2014-12-21 20:52:35 +01:00
Filippo Squillace
6163bc3d46 Add link to README.md 2014-12-21 20:48:01 +01:00
Filippo Squillace
ecb885206a Fix issue #37 2014-12-15 21:32:22 +01:00
Filippo Squillace
5823e4c553 Fix issue #35 2014-12-15 21:22:34 +01:00
Filippo Squillace
1444bcd649 Add sed command to JuJu image 2014-12-15 20:56:57 +01:00
Filippo Squillace
03e0f483e9 Small fix on the juju temp dir variable 2014-12-13 19:56:08 +01:00
Filippo Squillace
0b0c3be4dc Remove the juju.sh profile since juju could be used internally 2014-12-02 23:28:20 +01:00
Filippo Squillace
a19d6692a9 Merge branch '31_keyring' into dev
Conflicts:
	lib/core.sh
2014-12-02 23:16:14 +01:00
Filippo Squillace
edc70245fc Merge pull request #34 from fsquillace/32_mirrorlist
Avoid copying the mirrorlist from host OS
2014-12-02 22:11:02 +00:00
Filippo Squillace
b5ad28b4b1 Fix issue #31 2014-12-02 02:38:07 +01:00
Filippo Squillace
54f7629417 Fix issue #32 2014-12-01 00:00:19 +01:00
Filippo Squillace
8fbcb1b6fa Merge pull request #30 from fsquillace/dev
Merge from dev branch
2014-11-30 16:03:58 +00:00
Filippo Squillace
b2dacdc353 Update the version to 2.5.6 (Lion) 2014-11-30 16:52:53 +01:00
Filippo Squillace
c20a892f76 Merge pull request #27 from fsquillace/issue_5
Fix issue #5
2014-11-29 15:37:20 +00:00
Filippo Squillace
5fadb34f94 Fix issue #5 2014-11-29 16:35:39 +01:00
Filippo Squillace
dca66197d8 Merge pull request #26 from fsquillace/issue_25
Issue #25
2014-11-28 19:22:18 +00:00
Filippo Squillace
e96431a346 Fix #25 tests for old bash version 2014-11-28 16:05:18 +01:00
Filippo Squillace
ab74adb59d Fix issue #25 2014-11-28 00:03:19 +01:00
Filippo Squillace
69569eaab0 Merge pull request #24 from fsquillace/issue_21
Fix issue #21
2014-11-27 21:50:05 +00:00
Filippo Squillace
24a1b2b397 Fix issue #21 2014-11-27 22:48:48 +01:00
Filippo Squillace
6a0ea8e9ce Merge pull request #23 from fsquillace/issue_6
Fix issue #6
2014-11-27 21:17:42 +00:00
Filippo Squillace
95d933234c Fix issue #6 2014-11-27 20:52:25 +01:00
Filippo Squillace
4d32bf4ad8 Close issue #20 2014-11-26 23:47:59 +01:00
Filippo Squillace
b3b24141cd Merge pull request #19 from fsquillace/tests
Add Tests for the juju modules
2014-11-25 21:33:00 +00:00
Filippo Squillace
d4ccad692b Add test for juju script #11 2014-11-25 21:51:43 +01:00
Filippo Squillace
9f66f1682a Improve the mini pearl script for core unit tests 2014-11-25 21:50:10 +01:00
Filippo Squillace
82824d79bf Add test for run juju as fakeroot and for SECCOMP 2014-11-25 21:50:10 +01:00
Filippo Squillace
b0a0662575 Add tests for core.sh #13
Included the tests for die as well.
2014-11-25 21:49:57 +01:00
Filippo Squillace
3a51433f0b Add tests for util.sh #12 2014-11-25 21:49:24 +01:00
Filippo Squillace
8982cb5a24 Make some functions in core private 2014-11-19 21:56:40 +01:00
Filippo Squillace
0f6d7aaff0 Improve function for getting the chroot and proot arguments 2014-11-19 21:54:41 +01:00
Filippo Squillace
f1297478e8 Merge pull request #9 from fsquillace/proot_cli
Allow to specify specific command and Expose the Proot args to JuJu cli
2014-11-17 21:00:56 +00:00
Filippo Squillace
c0735b24ad Merge pull request #8 from fsquillace/3_validation_image
issue #3: Validate the image built
2014-11-17 20:50:22 +00:00
Filippo Squillace
fdebd2aa32 issue #3: Validate the image built 2014-11-17 00:16:57 +01:00
Filippo Squillace
811c140fed issue #7: Expose the Proot args to JuJu cli 2014-11-16 23:52:07 +01:00
Filippo Squillace
356bb1ca98 issue #4: Allow to specify specific command 2014-11-16 17:53:46 +01:00
37 changed files with 5454 additions and 624 deletions

2
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,2 @@
github: fsquillace
custom: https://github.com/fsquillace/junest/blob/master/README.md#donating

3
.gitignore vendored
View file

@ -1 +1,4 @@
*.swp
*pkg.tar.*
*.tar.gz
*.SRCINFO

62
.travis.yml Normal file
View file

@ -0,0 +1,62 @@
sudo: required
os: linux
cache:
directories:
- ~/.ccache
- ~/.pkg-cache
services:
- docker
env:
matrix:
- TRAVIS_BASH_VERSION="4.0"
before_install:
- ./ci/install-bash.sh "$TRAVIS_BASH_VERSION"
- sudo apt-get update
- sudo apt-get -y install awscli
install:
- PATH=$PWD/bin:$PATH
script:
#######################
# Unit Tests
#######################
- bash --version
- bash ./tests/checkstyle/checkstyle.sh
- bash ./tests/unit-tests/unit-tests.sh
- shellcheck bin/junest lib/**/*.sh ci/*.sh tests/**/*.sh
# ARM with qemu does seem to work properly. Disabling integ tests for ARM for now.
#- export JUNEST_HOME=~/.junest-arm
#- junest setup --arch arm
#- junest proot --fakeroot -- echo "Installing JuNest (\$(uname -m))"
#- 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
#######################
# 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

260
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,260 @@
Contributing to JuNest
=====================
First off, thanks for taking the time to contribute!
The following is a set of guidelines for contributing to JuNest.
These are just guidelines, not rules, use your best judgment and
feel free to propose changes to this document in a pull request.
**Table of Contents**
- [How Can I Contribute?](#how-can-i-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Styleguides](#styleguides)
- [Git Commit Messages](#git-commit-messages)
- [Documentation Styleguide](#documentation-styleguide)
- [Shell Styleguide](#shell-styleguide)
- [Versioning](#versioning)
## How Can I Contribute? ##
### Reporting Bugs ###
This section guides you through submitting a bug report for JuNest.
#### Before submitting a bug report ####
You might be able to find the cause of the problem and fix things yourself.
- **Check the [troubleshooting section](https://github.com/fsquillace/junest#troubleshooting)**
- **Check if you can reproduce the problem with the latest version of JuNest**
- **Check for [existing open/closed issues](https://github.com/fsquillace/junest/issues?utf8=%E2%9C%93&q=is%3Aissue)**
- If the bug has already been suggested, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Bug Report? ####
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/) in the [JuNest issues page](https://github.com/fsquillace/junest/issues).
Explain the problem and include additional details to help maintainers reproduce the problem:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started JuNest, e.g. which command exactly you used in the terminal. When listing steps, **don't just say what you did, but explain how you did it**. For example.
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Put the bug label to the issue.**
Include details about your configuration and environment:
* **Which version of JuNest are you using?**
* **What's the name and version of the OS you're using**?
* **Are you running JuNest in a virtual machine?** If so, which VM software are you using and which operating systems and versions are used for the host and the guest?
* **Which packages do you have installed?** You can get that list by running `pacman -Qq`.
#### Template For Submitting Bug Reports ####
[Short description of problem here]
**Reproduction Steps:**
1. [First Step]
2. [Second Step]
3. [Other Steps...]
**Expected behavior:**
[Describe expected behavior here]
**Observed behavior:**
[Describe observed behavior here]
**JuNest version:** [Enter JuNest version here]
**OS and version:** [Enter OS name and version here]
**Installed packages:**
[List of installed packages here]
**Additional information:**
* Problem started happening recently, didn't happen in an older version of JuNest: [Yes/No]
* Problem can be reliably reproduced, doesn't happen randomly: [Yes/No]
### Suggesting Enhancements ###
This section guides you through submitting an enhancement suggestion for JuNest, including completely new features and minor improvements to existing functionality.
#### Before Submitting An Enhancement Suggestion ####
* **Check if you're using the latest version of JuNest**
- **Check for [existing open/closed issues](https://github.com/fsquillace/junest/issues?utf8=%E2%9C%93&q=is%3Aissue)**
- If enhancement has already been suggested, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Enhancement Suggestion? ####
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/) in the [JuNest issues page](https://github.com/fsquillace/junest/issues).
Create an issue on that repository and provide the following information:
* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Specify which version of JuNest you're using.**
* **Specify the name and version of the OS you're using.**
* **Put the enanchement label to the issue.**
#### Template For Submitting Enhancement Suggestions ####
[Short description of suggestion]
**Steps which explain the enhancement**
1. [First Step]
2. [Second Step]
3. [Other Steps...]
**Current and suggested behavior**
[Describe current and suggested behavior here]
**Why would the enhancement be useful to most users**
[Explain why the enhancement would be useful to most users]
[List some other text editors or applications where this enhancement exists]
**JuNest Version:** [Enter JuNest version here]
**OS and Version:** [Enter OS name and version here]
### Your First Code Contribution ###
All JuNest issues are tracked as [GitHub issues](https://guides.github.com/features/issues/) in the [JuNest issues page](https://github.com/fsquillace/junest/issues).
#### Pull Requests ####
* Fork the repo and create your feature branch from ***dev***.
* If you make significant changes, please add tests too.
Get familiar with [shunit](https://github.com/kward/shunit2).
* If you've changed APIs, please update the documentation
* Follow the [Shell styleguide](#shell-styleguide).
* Document new code based on the
[Documentation Styleguide](#documentation-styleguide).
* End files with a newline.
* Follow the [Git commit messages](#git-commit-messages).
* Send a [GitHub Pull Request to JuNest](https://github.com/fsquillace/junest/compare/dev...) with a clear list of what you've done (read more about [pull requests](http://help.github.com/pull-requests/)).
* Put **dev as the base branch** and NOT the master one.
#### Unit Tests ####
To run unit tests:
```sh
./tests/unit-tests/unit-tests.sh
```
#### Integration Tests ####
Generally, there is no need to run integration tests locally
since [Travis](https://travis-ci.org/fsquillace/junest) will run as
soon as the pull request gets created.
## Styleguides ##
### Git Commit Messages ###
* Follow the [seven rules](http://chris.beams.io/posts/git-commit/#seven-rules) of a great Git commit message
* Reference issues and pull requests liberally
* Consider starting the commit message with an applicable emoji:
* :art: `:art:` when improving the format/structure of the code
* :racehorse: `:racehorse:` when improving performance
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
* :memo: `:memo:` when writing docs
* :penguin: `:penguin:` when fixing something on Linux
* :apple: `:apple:` when fixing something on Mac OS
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
* :bug: `:bug:` when fixing a bug
* :fire: `:fire:` when removing code or files
* :green_heart: `:green_heart:` when fixing the CI build
* :white_check_mark: `:white_check_mark:` when adding tests
* :lock: `:lock:` when dealing with security
* :arrow_up: `:arrow_up:` when upgrading dependencies
* :arrow_down: `:arrow_down:` when downgrading dependencies
* :shirt: `:shirt:` when removing linter warnings
* :package: `:package:` when bumping the version
### Documentation Styleguide ###
* Use [Markdown](https://daringfireball.net/projects/markdown).
### Shell Styleguide ###
* Use [google shell styleguide](https://google.github.io/styleguide/shell.xml)
#### Function documentation ####
For function documentation follows the example below:
#######################################
# Cleanup files from the backup dir.
#
# Globals:
# VAR1 (RO,bool) : `my_func` access to VAR1.
# VAR2 (WO) : `my_func` change the value of VAR2.
# VAR3 (RW) : `my_func` read and write to VAR3.
# Arguments:
# arg1 ($1,int) : Directory to cleanup.
# arg2 ($2-) : Command to execute for the cleanup.
# Returns:
# 0 : Cleanup completed successfully.
# 101 : Backup directory is not readable.
# $NOT_DIR_ERROR : Backup directory is not a directory.
# Output:
# None
#######################################
my_func() {
local arg1=$1
shift
local arg2=$@
...
}
The documentation is divided by a description of the function, a `Globals`,
`Arguments`, `Returns` and `Output` sections. If a section does not need details
use the word `None` inside of it.
`Globals` section provides all global variables that interact with the function.
`Arguments` section provides the list of arguments to pass to the function. Use
the parenthesis to indicate the position of the arguments:
- `$1` : Argument is in position one.
- `$2-` : Argument takes all args from position two up to the end.
- `$@` : Argument takes all args.
- `$3?` : Argument is optional.
Variables defined in `Globals` and `Arguments` sections can have the following
types:
- `int` : Integer variable.
- `str` : String variable (default).
- `bool` : Bool variable.
`Returns` section contains the exit status of the function.
`Output` section describe the string printed to stdout.
## Versioning ##
* JuNest uses the following [semantic versioning](http://semver.org/)
### Public API ###
The public API refers to the following parts of JuNest system:
- JuNest script CLI
Any potential code change that cause backwards incompatible changes to the
public API requires the major version to be incremented.

11
LICENSE
View file

@ -1,4 +1,6 @@
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
@ -631,8 +633,8 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
JuNest: The Arch Linux based distro that runs upon any Linux distros without root access
Copyright (C) 2014 Filippo Squillace
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -652,7 +654,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
JuNest Copyright (C) 2014 Filippo Squillace
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -673,3 +675,4 @@ the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

699
README.md
View file

@ -1,179 +1,616 @@
JuJu
====
**JuJu**: the GNU/Linux distribution container for non-root users
JuNest
======
> [!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">
<a href="https://github.com/fsquillace/junest"><img
alt="JuNest"
width=250px
src="https://cdn.rawgit.com/fsquillace/junest-logo/master/junest.svg"></a>
</h1>
|Project Status|Donation|Communication|
|:------------:|:------:|:-----------:|
| [![Build status](https://api.travis-ci.com/fsquillace/junest.png?branch=master)](https://app.travis-ci.com/github/fsquillace/junest) [![OpenHub](https://www.openhub.net/p/junest/widgets/project_thin_badge.gif)](https://www.openhub.net/p/junest) | [![Github Sponsors](https://img.shields.io/badge/GitHub-Sponsors-orange.svg)](https://github.com/sponsors/fsquillace) [![PayPal](https://img.shields.io/badge/PayPal-Donation-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8LEHQKBCYTACY) [![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/fsquillace) | [![Join the Discord server at https://discord.gg/ttfBT7MKve](https://img.shields.io/badge/Discord-Server-blueviolet.svg)](https://discord.gg/ttfBT7MKve) |
**Table of Contents**
- [Description](#description)
- [Quickstart](#quickstart)
- [Installation](#installation)
- [Usage](#usage)
- [Advanced usage](#advanced-usage)
- [Internals](#internals)
- [Troubleshooting](#troubleshooting)
- [More documentation](#more-documentation)
- [Contributing](#contributing)
- [Donating](#donating)
- [Authors](#authors)
Description
-----------
**JuJu** is a small ArchLinux based GNU/Linux distribution.
===========
**JuNest** (Jailed User Nest) is a lightweight Arch Linux based distribution
that allows the creation of disposable and partially isolated GNU/Linux environments
within any generic GNU/Linux host OS and without requiring root
privileges to install packages.
It allows to have an isolated GNU/Linux environment inside any generic host GNU/Linux OS
and without the need to have root privileges for installing packages.
JuNest is built around [pacman](https://wiki.archlinux.org/index.php/Pacman),
the Arch Linux package manager, which allows access
to a wide range of packages from the Arch Linux repositories.
JuJu contains just the package managers (called pacman and yaourt) that allows to access
to a wide range of packages from ArchLinux repositories.
The main advantages of using JuNest include:
The main advantages on using JuJu are:
- Install packages without root privileges.
- Isolated environment in which you can install packages without affecting a production system.
- Access to a wide range of packages in particular on GNU/Linux distros that may contain a limited repositories (such as CentOS and RedHat).
- Available for x86\_64, i686 and ARMv6 architectures but you can build you own image from scratch too!
- All ArchLinux lovers can have their favourite distro everywhere!
- Create partially isolated environments in which you can install packages without risking mishaps on production systems.
- Access a wider range of packages, particularly on GNU/Linux distros with comparatively limited repositories (such as CentOS and Red Hat).
- 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 enjoy their favourite distro everywhere!
Quickstart
----------
There are three different ways you can run JuJu:
JuNest follows the [Arch Linux philosophy](https://wiki.archlinux.org/index.php/The_Arch_Way).
- As normal user - Allow to make basic operations using [proot](https://wiki.archlinux.org/index.php/Proot):
```
$ juju
```
- As fakeroot - Allow to install/remove packages using [proot](https://wiki.archlinux.org/index.php/Proot):
```
$ juju -f
```
- As root - Allow to have fully root privileges inside JuJu environment using [arch-chroot](https://wiki.archlinux.org/index.php/Chroot) (you need to be root for executing this):
```
# juju -r
```
How different is JuNest from Docker and Vagrant?
------------------------------------------------
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).
The first time you execute it, the script will download the JuJu image and place it
to the default directory ~/.juju.
You can change the default directory by changing the environment variable *JUJU\_HOME*.
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
processes belonging to the host OS.
Installation
============
## Dependencies ##
JuNest comes with a very short list of dependencies in order to be installed in most
of GNU/Linux distributions.
Before installing JuNest be sure that all dependencies are properly installed in your system:
- [bash (>=4.0)](https://www.gnu.org/software/bash/)
- [GNU coreutils](https://www.gnu.org/software/coreutils/)
## Installation from git repository ##
Just clone the JuNest repo somewhere (for example in ~/.local/share/junest):
```sh
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) ###
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/`
Quickstart
==========
Setup environment
-----------------
The first operation required is to install the JuNest environment in the
location of your choice via `JUNEST_HOME` environment variable
(it must contain an absolute path) which by
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
=====
There are three different ways you can run JuNest depending on the backend program you decide to use.
Linux namespaces based
----------------------
The [Linux namespaces](http://man7.org/linux/man-pages/man7/namespaces.7.html)
represents the default backend program for JuNest.
The requirements for having Linux namespaces working are:
1. Kernel starting from Linux 3.8 allows unprivileged processes to create
user and mount namespaces.
1. The Linux kernel distro must have the user namespace enabled.
In the last years, the majority of GNU/Linux distros have the user namespace
enabled by default. This means that you do not need to have root privileges to
access to the JuNest environment via this method.
This
[wiki](https://github.com/fsquillace/junest/wiki/Linux-distros-with-user-namespace-enabled-by-default)
provides the state of the user namespace on several GNU/Linux distros.
In order to run JuNest via Linux namespaces:
- As 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
------------
Just clone JuJu somewhere (for example in ~/juju):
This solution suits only for privileged users. JuNest provides the possibility
to run the environment via `chroot` program.
In particular, it uses a special program called `GRoot`, a small and portable
version of
[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
work, JuNest is even providing the possibility to run the environment directly via
the pure `chroot` command.
$ git clone git://github.com/fsquillace/juju ~/juju
$ export PATH=~/juju/bin:$PATH
In order to run JuNest via `chroot` solutions:
JuJu can only works on GNU/Linux OS with kernel version greater or equal
2.6.32 on 64 bit 32 bit and ARMv6 architectures.
- 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 root`
Execution modes comparison table
----------------
The following table shows the capabilities that each backend program is able to perform:
| | QEMU | Root privileges required | Manage Official Packages | Manage AUR Packages | Portability | Support | User modes |
| --- | ---- | ------------------------ | ------------------------ | ------------------- | ----------- | ------- | ---------- |
| **Linux Namespaces** | NO | NO | YES | YES | Poor | YES | Normal user and `fakeroot` |
| **Proot** | YES | NO | YES | NO | YES | YES | Normal user and `fakeroot` |
| **Chroot** | NO | YES | YES | YES | YES | YES | `root` only |
Advanced usage
--------------
You can build a new JuJu image from scratch by running the following command:
==============
## Build image ##
You can build a new JuNest image from scratch by running the following command:
# juju -b
```sh
junest build [-n]
```
In this way the script will create a directory containing all the essentials
files in order to make JuJu working properly (such as pacman, yaourt, arch-chroot and proot).
Remember that the script to build the image must run in an ArchLinux OS with
arch-install-scripts, package-query, git and the base-devel packages installed.
To change the build directory just use the *JUJU_TMPDIR* (by default /tmp).
The script will create a directory containing all the essentials
files in order to make JuNest working properly (such as `pacman` and `proot`).
The option `-n` will skip the final validation tests if they are not needed.
Remember that the script to build the image must run in an Arch Linux OS with
arch-install-scripts and the base-devel packages installed.
To change the build directory just use the `JUNEST_TEMPDIR` (by default /tmp).
After creating the image juju-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:
# juju -i juju-x86_64.tar.gz
```sh
junest setup -i junest-x86_64.tar.gz
```
Dependencies
------------
JuJu comes with a very short list of dependencies in order to be installed in most
of GNU/Linux distributions. The dependencies needed in the host OS are:
- bash
- wget or curl
- tar
- mkdir
- linux kernel 2.6.32+
For more details, you can also take a look at
[junest-builder](https://github.com/fsquillace/junest-builder)
that contains the script and systemd service used for the automatic building
of the JuNest image.
Related wiki page:
- [How to build a JuNest image using QEMU](https://github.com/fsquillace/junest/wiki/How-to-build-a-JuNest-image-using-QEMU)
## Run JuNest using a different architecture via QEMU ##
The following command will download the ARM JuNest image and will run QEMU in
case the host OS runs on `x86_64` architecture:
```sh
$> export JUNEST_HOME=~/.junest-arm
$> junest setup -a arm
$> junest proot -- uname -m
armv7l
```
## Bind directories ##
To bind a host directory to a guest location:
```sh
junest -b "--bind /home/user/mydata /mnt/mydata"
```
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:
```sh
junest [u|g|p] -b "--help"
```
## Systemd integration ##
Although JuNest has not been designed to be a complete container, it is even possible to
virtualize the process tree thanks to the [systemd container](https://wiki.archlinux.org/index.php/Systemd-nspawn).
The JuNest containter allows to run services inside the container that can be
visible from the host OS through the network.
The drawbacks of this are that the host OS must use systemd as a service manager,
and the container can only be executed using root privileges.
To boot a JuNest container:
```sh
sudo systemd-nspawn -bD ~/.junest
```
Related wiki page:
- [How to run junest as a container](https://github.com/fsquillace/junest/wiki/How-to-run-JuNest-as-a-container)
- [How to run services using Systemd](https://github.com/fsquillace/junest/wiki/How-to-run-services-using-Systemd)
Internals
=========
## Automatic fallback for all the dependent host OS executables ##
JuNest attempts first to run the executables in the host OS located in different
positions (`/usr/bin`, `/bin`, `/usr/sbin` and `/sbin`).
As a fallback it tries to run the same executable if it is available in the JuNest
environment.
## Automatic building of the JuNest images ##
There is a periodic automation build of the JuNest images for `x86_64` arch
only.
The JuNest image for `arm` architecture may not be always up to date because
the build is performed manually.
## Static QEMU binaries ##
There are static QEMU binaries included in JuNest image that allows to run JuNest
in a different architecture from the host system. They are located in `/opt/qemu`
directory.
Troubleshooting
---------------
===============
###Cannot use AUR repository###
- **Q**: Why do I get the following error when I try to install a package with yaourt?
```
Cannot find the gzip binary required for compressing man and info pages.
```
- **A**: JuJu comes with a very basic number of packages.
In order to install packages using yaourt you may need to install the package group *base-devel*
that contains all the essential packages for compiling source code (such as gcc, make, patch, etc):
For Arch Linux related FAQs take a look at the [General troubleshooting page](https://wiki.archlinux.org/index.php/General_troubleshooting).
```
pacman -S base-devel
```
## Cannot use AUR repository ##
###Kernel too old###
- **Q**: Why do I get the error: "FATAL: kernel too old"?
- **A**: This is because the executable from the precompiled package cannot
always run if the kernel is old.
In order to check if the executable can be compatible with the kernel of
the host OS just use file command, for instance:
> **Q**: Why do I get the following error when I try to install a package?
```
file ~/.juju/usr/bin/bash
Cannot find the gzip binary required for compressing man and info pages.
> **A**: JuNest comes with a very basic number of packages.
> In order to install AUR packages you need to install the package group `base-devel` first
> that contains all the essential packages for compiling from source code (such as gcc, make, patch, etc):
#> pacman -S 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 ##
> **Q**: Why I cannot install packages?
#> pacman -S lsof
Packages (1): lsof-4.88-2
Total Download Size: 0.09 MiB
Total Installed Size: 0.21 MiB
error: no servers configured for repository: core
error: no servers configured for repository: community
error: failed to commit transaction (no servers configured for repository)
Errors occurred, no packages were upgraded.
> **A**: You need simply to update the mirrorlist file according to your location:
# Uncomment the repository line according to your location
#> nano /etc/pacman.d/mirrorlist
#> pacman -Syy
## Locate the package for a given file ##
> **Q**: How do I find which package a certain file belongs to?
> **A**: JuNest is a really small distro, therefore you frequently need to find
> the package name for a certain file. `pkgfile` is an extremely useful package
> that allows you to detect the package of a given file.
> For instance, if you want to find the package name for the command `getopt`:
#> pacman -S pkgfile
#> pkgfile --update
$> pkgfile getop
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 ##
> **Q**: Why do I get the error: "FATAL: kernel too old"?
> **A**: This is because the binaries from the precompiled package are
> compiled for Linux kernel 2.6.32. When JuNest is started without further
> options, it tries to run a shell from the JuNest chroot. The system sees that
> the host OS kernel is too old and refuses to start the shell.
> The solution is to present a higher "fake" kernel version to the JuNest
> chroot. PRoot offers the *-k* option for this, and JuNest passes this option
> on to PRoot when *-p* is prepended. For example, to fake a kernel version of
> 3.10, issue the following command:
$> junest proot -b "-k 3.10"
> As Arch Linux ships binaries for kernel version 2.6.32, the above error is
> not unique to the precompiled package from JuNest. It will also appear when
> trying to run binaries that were later installed in the JuNest chroot with
> the `pacman` command.
> In order to check if an executable inside JuNest chroot is compatible with
> the kernel of the host OS just use the `file` command, for instance:
$> file ~/.junest/usr/bin/bash
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked
(uses shared libs), for GNU/Linux 2.6.32,
BuildID[sha1]=ec37e49e7188ff4030052783e61b859113e18ca6, stripped
```
From the output you can see what is the minimum recommended Linux kernel version.
> The output shows the minimum recommended Linux kernel version.
###SUID permissions###
- **Q**: Why I do not have permissions for ping?
```
ping www.google.com
## Kernel doesn't support private futexes ##
> **Q**: Why do I get the warning: "kompat: this kernel doesn't support private
> futexes and PRoot can't emulate them."?
> **A**: This happens on older host OS kernels when the trick of showing a fake
> kernel version to the JuNest chroot is applied (see above:
> [Kernel too old](#kernel-too-old)).
> The consequence of showing a fake kernel version to the JuNest chroot is that
> in the background, PRoot needs to translate requests from applications in the
> chroot to the old kernel of the host OS. Some of the newer kernel
> functionality can be emulated, but private futexes cannot be translated.
> Private Futexes were introduced in Linux kernel 2.6.22. Therefore, the above
> problem likely appears on old Linux systems, for example RHEL5 systems, which
> are based on Linux kernel 2.6.18. Many of the core tools like `which`, `man`,
> or `vim` run without problems while others, especially XOrg-based programs,
> are more likely to show the warning. These are also more likely to crash
> unexpectedly.
> Currently, there is no (easy) workaround for this. In order to be fully
> compatible with kernels below 2.6.22, both the precompiled package from
> JuNest and all software that is installed later needs to be compiled for this
> kernel. Most likely this can only be achieved by building the needed software
> packages from source, which kind of contradicts JuNest's distro-in-a-distro
> philosophy.
## SUID permissions ##
> **Q**: Why I do not have permissions for ping?
$> ping www.google.com
ping: icmp open socket: Operation not permitted
```
- **A**: The ping command uses *suid* permissions that allow to execute the command using
root privileges. The fakeroot mode is not able to execute a command set with suid,
and you may need to use root privileges. There are other few commands that
have *suid* permission, you can list the commands from your JuJu environment
with the following command:
```
find /usr/bin -perm +4000
```
> **A**: The ping command uses *suid* permissions that allow to execute the command using
> root privileges. The fakeroot mode is not able to execute a command set with suid,
> and you may need to use root privileges. There are other few commands that
> have *suid* permission, you can list the commands from your JuNest environment
> with the following command:
###No characters are visible on a graphic application###
- **Q**: Why I do not see any characters in the application I have installed?
$> find /usr/bin -perm /4000
- **A**: This is probably because there are no
[https://wiki.archlinux.org/index.php/Font_Configuration](fonts) installed in
the system.
## No characters are visible on a graphic application ##
To quick fix this, you can just install a fonts package:
```
pacman -S gnu-free-fonts
```
> **Q**: Why I do not see any characters in the application I have installed?
###Missing permissions on removing a package###
- **Q**: Why I cannot remove the package I have installed?
```
pacman -Rsn lsof
checking dependencies...
> **A**: This is probably because there are no
> [fonts](https://wiki.archlinux.org/index.php/Font_Configuration) installed in
> the system.
Packages (1): lsof-4.88-1
> To quick fix this, you can just install a fonts package:
Total Removed Size: 0.21 MiB
#> pacman -S gnu-free-fonts
error: cannot remove /usr/share/licenses/lsof/LICENSE (Permission denied)
error: could not remove database entry lsof-4.88-1
```
## Differences between filesystem and package ownership ##
- **A**: This is probably because you have installed the package with root
permissions. Since JuJu gives the possibility to install packages
either as root or as normal user you need to remember that and remove
the package with the right user!
> **Q**: Why do I get warning when I install a package using root privileges?
License
-------
Copyright (c) 2012-2014
#> pacman -S systat
...
warning: directory ownership differs on /usr/
filesystem: 1000:100 package: 0:0
...
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published
by the Free Software Foundation; either version 2, or (at your option)
any later version.
> **A**: In these cases the package installation went smoothly anyway.
> This should happen every time you install package with root privileges
> since JuNest will try to preserve the JuNest environment by assigning ownership
> of the files to the real user.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
## Unprivileged user namespace disable at kernel compile time or kernel too old ##
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
> **Q**: Why do I get this warning when I run JuNest via Linux namespaces?
## Author
Filippo Squillace <feel.squally@gmail.com>
$> junest ns
Unprivileged user namespace is disabled at kernel compile time or kernel too old (<3.8). Proceeding anyway...
## WWW
https://github.com/fsquillace/juju
> **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
> does not have a newer Linux version or the user namespace is not enabled.
> JuNest does not stop the execution of the program but it attempts to run it
> anyway. If you have root permissions try to enable it, otherwise try to use
> Proot as backend program.
More documentation
==================
There are additional tutorials in the
[JuNest wiki page](https://github.com/fsquillace/junest/wiki).
Contributing
============
Contributions are welcome! You could help improving JuNest in the following ways:
- [Reporting Bugs](CONTRIBUTING.md#reporting-bugs)
- [Suggesting Enhancements](CONTRIBUTING.md#suggesting-enhancements)
- [Writing Code](CONTRIBUTING.md#your-first-code-contribution)
Donating
========
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/images/0)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/0)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/1)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/1)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/2)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/2)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/3)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/3)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/4)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/4)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/5)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/5)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/6)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/6)[![](https://sourcerer.io/fame/fsquillace/fsquillace/junest/images/7)](https://sourcerer.io/fame/fsquillace/fsquillace/junest/links/7)

1
VERSION Normal file
View file

@ -0,0 +1 @@
7.4.10

166
bin/juju
View file

@ -1,166 +0,0 @@
#!/usr/bin/env bash
#
# This file is part of JuJu: The portable GNU/Linux distribution
#
# Copyright (c) 2012-2014 Filippo Squillace <feel.squally@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
NAME='juju'
VERSION='1.0'
source "$(dirname $0)/../lib/core.sh"
###################################
### General functions ###
###################################
usage() {
echo -e "JuJu: The portable GNU/Linux distribution"
echo -e "Usage: $NAME [options]"
echo -e "Options:"
echo -e "-i, --setup-from-file <image> Setup the JuJu image in ${JUJU_HOME}"
echo -e "-f, --fakeroot Run JuJu with fakeroot privileges"
echo -e "-r, --root Run JuJu with root privileges"
echo -e "-b, --build-image Build a JuJu image (must run in ArchLinux)"
echo -e "-d, --delete Delete JuJu from ${JUJU_HOME}"
echo -e "-h, --help Show this help message"
echo -e "-v, --version Show the $NAME version"
}
version() {
echo -e "JuJu ($VERSION): The portable GNU/Linux distribution"
echo -e "Copyright (c) 2012-2014 Filippo Squillace <feel.squally@gmail.com>"
echo -e "Homepage: http://github.com/fsquillace/juju"
}
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_DELETE
then
if $OPT_BUILD_IMAGE || $OPT_HELP || $OPT_VERSION || $OPT_SETUP_FROM_FILE || \
$OPT_FAKEROOT || $OPT_ROOT
then
die "The JuJu 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
then
die "The JuJu 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
then
die "The JuJu version option must be used exclusively"
fi
fi
if $OPT_FAKEROOT && $OPT_ROOT
then
die "You must access to JuJu with either fakeroot or root permissions"
fi
[ "$ARGS" != "" ] && die "No arguments are needed. For the CLI syntax run: $NAME --help"
return 0
}
###################################
### MAIN PROGRAM ###
###################################
TEMP=`getopt -o drfbi:hv --long delete,root,fakeroot,build-image,setup-from-file:,help,version -n 'juju' -- "$@"`
if [ $? != 0 ] ; then error "Error on parsing the command line. Try juju -h." ; exit ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
OPT_SETUP_FROM_FILE=false
IMAGE_FILE=""
OPT_FAKEROOT=false
OPT_ROOT=false
OPT_BUILD_IMAGE=false
OPT_DELETE=false
OPT_HELP=false
OPT_VERSION=false
while true ; do
case "$1" in
-i|--setup-from-file) OPT_SETUP_FROM_FILE=true ; shift ; IMAGE_FILE=$1 ; shift ;;
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
-r|--root) OPT_ROOT=true ; shift ;;
-b|--build-image) OPT_BUILD_IMAGE=true ; shift ;;
-d|--delete) OPT_DELETE=true ; shift ;;
-h|--help) OPT_HELP=true ; shift ;;
-v|--version) OPT_VERSION=true ; shift ;;
--) shift ; break ;;
*) error "Internal error!" ; exit 1 ;;
esac
done
ARGS=()
for arg do
ARGS+=($arg)
done
check_cli || exit 1
################ DEFINE ACTION ########################
$OPT_HELP && usage && exit
$OPT_VERSION && version && exit
if $OPT_BUILD_IMAGE; then
build_image_juju
exit
elif $OPT_DELETE; then
delete_juju
exit
fi
if ! is_juju_installed
then
if $OPT_SETUP_FROM_FILE; then
setup_from_file_juju $IMAGE_FILE
else
setup_juju
fi
elif $OPT_SETUP_FROM_FILE; then
die "Error: The image cannot be installed since $JUJU_HOME is not empty."
fi
if $OPT_FAKEROOT; then
run_juju_as_fakeroot
elif $OPT_ROOT; then
run_juju_as_root
else
run_juju_as_user
fi
# vim: set ts=4 sw=4 noet:

322
bin/junest Executable file
View file

@ -0,0 +1,322 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091
#
# This file is part of JuNest (https://github.com/fsquillace/junest).
#
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")")"/..)}"
source "${JUNEST_BASE}/lib/utils/utils.sh"
source "${JUNEST_BASE}/lib/core/common.sh"
source "${JUNEST_BASE}/lib/core/build.sh"
source "${JUNEST_BASE}/lib/core/setup.sh"
source "${JUNEST_BASE}/lib/core/chroot.sh"
source "${JUNEST_BASE}/lib/core/namespace.sh"
source "${JUNEST_BASE}/lib/core/proot.sh"
source "${JUNEST_BASE}/lib/core/wrappers.sh"
###################################
### General functions ###
###################################
usage() {
echo -e "$NAME (v$(cat "$JUNEST_BASE"/VERSION)): $DESCRIPTION"
echo
echo -e "Usage: $CMD [action] [options] [--] [command]"
echo
echo -e "General:"
echo -e "-h, --help Show this help message"
echo -e "-V, --version Show the $NAME version"
echo
echo -e "Actions and options:"
echo -e " s[etup] Setup $NAME in ${JUNEST_HOME} either from repo or from file"
echo -e " -i, --from-file <image> Setup the $NAME image in ${JUNEST_HOME}"
echo -e " -a, --arch <arch> $NAME architecture to download (x86_64, arm)"
echo -e " Defaults to the host architecture ($ARCH)"
echo -e " -d, --delete Delete $NAME from ${JUNEST_HOME}"
echo
echo -e " n[s] Access via Linux Namespaces using BubbleWrap (Default action)"
echo -e " -f, --fakeroot Run $NAME with fakeroot privileges"
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
}
version() {
echo -e "$NAME $(cat "$JUNEST_BASE"/VERSION)"
}
function parse_arguments(){
# Actions
ACT_SETUP=false
ACT_BUILD=false
ACT_CREATE_WRAPPERS=false
ACT_NAMESPACE=false
ACT_PROOT=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=""
OPT_NO_COPY_FILES=false
BACKEND_COMMAND=""
while [[ -n "$1" ]]
do
case "$1" in
-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_ns_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=()
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
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
then
die "Error: The image is still not installed in $JUNEST_HOME. Run this first: $CMD setup"
fi
if $ACT_CREATE_WRAPPERS; then
# shellcheck disable=SC2086
create_wrappers $OPT_FORCE "$OPT_BIN_PATH"
exit
fi
local run_env
if $ACT_NAMESPACE; then
if $OPT_FAKEROOT; then
run_env=run_env_as_bwrap_fakeroot
else
run_env=run_env_as_bwrap_user
fi
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
elif $ACT_ROOT; then
run_env=run_env_as_chroot
fi
# 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() {
parse_arguments "$@"
execute_operation
}
main "$@"
# vim: set ts=4 sw=4 noet:

8
bin/sudoj Executable file
View 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
View 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
View 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
View 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

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

@ -0,0 +1,102 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091
#
# This modules is used for:
# - Running checks against the building JuNest image
# - Integration tests on JuNest script against different execution modes (i.e. -f, -u, -r modes)
#
# Dependencies:
# - None
#
# vim: ft=sh
set -ex
RUN_ROOT_TESTS=false
SKIP_AUR_TESTS=false
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_BASE can be overridden for testing purposes.
# There is no need for doing it for normal usage.
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f "$(dirname "$(readlink -f "$0")")"/../..)}"
source "${JUNEST_BASE}/lib/utils/utils.sh"
source "${JUNEST_BASE}/lib/core/common.sh"
info "Validating JuNest located in ${JUNEST_HOME}..."
info "Initial JuNest setup..."
# The following ensures that the gpg agent gets killed (if exists)
# otherwise it is not possible to exit from the session
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
prepare_archlinux "$SUDO"
PACMAN_OPTIONS="--noconfirm --disable-download-timeout"
# 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
echo "Checking ${repo_package1} package from official repo..."
# shellcheck disable=SC2086
$SUDO pacman $PACMAN_OPTIONS -S ${repo_package1}
tree -L 1
# shellcheck disable=SC2086
$SUDO pacman $PACMAN_OPTIONS -Rsn ${repo_package1}
repo_package2=iftop
info "Checking ${repo_package2} package from official repo..."
# shellcheck disable=SC2086
$SUDO pacman $PACMAN_OPTIONS -S ${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
then
aur_package=tcptraceroute
info "Checking ${aur_package} package from AUR repo..."
yay --noconfirm -S ${aur_package}
# shellcheck disable=SC2086
$SUDO pacman $PACMAN_OPTIONS -Rsn ${aur_package}
fi
exit 0

31
lib/checks/check_all.sh Executable file
View 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

View file

@ -1,256 +0,0 @@
#!/usr/bin/env bash
#
# This file is part of JuJu: The portable GNU/Linux distribution
#
# Copyright (c) 2012-2014 Filippo Squillace <feel.squally@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# References:
# https://wiki.archlinux.org/index.php/PKGBUILD
# https://wiki.archlinux.org/index.php/Creating_Packages
set -e
################################ IMPORTS #################################
source "$(dirname ${BASH_ARGV[0]})/util.sh"
################################# VARIABLES ##############################
[ -z ${JUJU_HOME} ] && JUJU_HOME=~/.juju
if [ -z ${JUJU_TEMPDIR} ] || [ ! -d ${JUJU_TEMPDIR} ]
then
JUJU_TEMPDIR=/tmp
fi
JUJU_REPO=https://bitbucket.org/fsquillace/juju-repo/raw/master
ORIGIN_WD=$(pwd)
# The essentials executables that MUST exist in the host OS are (wget|curl), bash, mkdir
if command -v wget > /dev/null 2>&1
then
WGET="wget --no-check-certificate"
elif command -v curl > /dev/null 2>&1
then
WGET="curl -J -O -k"
else
die "Error: Either wget or curl commands must be installed"
fi
TAR=tar
ARCH=$(uname -m)
[[ $ARCH =~ .*(armv6).* ]] && ARCH=${BASH_REMATCH[1]}
if [ $ARCH == "i686" ]
then
LD_LIB="${JUJU_HOME}/lib/ld-linux.so.2"
elif [ $ARCH == "x86_64" ]
then
LD_LIB="${JUJU_HOME}/lib64/ld-linux-x86-64.so.2"
elif [ $ARCH == "armv6" ]
then
LD_LIB="${JUJU_HOME}/lib/ld-linux-armhf.so.3"
else
die "Unknown architecture ${ARCH}"
fi
if [ -z $JUJU_ENV ] || [ "$JUJU_ENV" == "0" ]
then
PROOT="$LD_LIB --library-path ${JUJU_HOME}/usr/lib:${JUJU_HOME}/lib ${JUJU_HOME}/usr/bin/proot"
SH="/bin/sh --login"
elif [ "$JUJU_ENV" == "1" ]
then
PROOT="$LD_LIB"
SH="/bin/sh"
else
die "The variable JUJU_ENV is not properly set"
fi
################################# MAIN FUNCTIONS ##############################
function is_juju_installed(){
[ -d "$JUJU_HOME" ] && [ "$(ls -A $JUJU_HOME)" ] && return 0
return 1
}
function cleanup_build_directory(){
# $1: maindir (optional) - str: build directory to get rid
local maindir=$1
builtin cd $ORIGIN_WD
trap - QUIT EXIT ABRT KILL TERM INT
rm -fr "$maindir"
}
function prepare_build_directory(){
trap - QUIT EXIT ABRT KILL TERM INT
trap "rm -rf ${maindir}; die \"Error occurred when installing JuJu\"" EXIT QUIT ABRT KILL TERM INT
}
function _setup_juju(){
is_juju_installed && die "Error: JuJu has been already installed in $JUJU_HOME"
mkdir -p "${JUJU_HOME}"
imagepath=$1
tar -zxpf ${imagepath} -C ${JUJU_HOME}
mkdir -p ${JUJU_HOME}/run/lock
info "JuJu installed successfully"
}
function setup_juju(){
# Setup the JuJu environment
[ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment"
local maindir=$(TMPDIR=$JUJU_TEMPDIR mktemp -d -t juju.XXXXXXXXXX)
prepare_build_directory
info "Downloading JuJu..."
builtin cd ${maindir}
local imagefile=juju-${ARCH}.tar.gz
$WGET ${JUJU_REPO}/${imagefile}
info "Installing JuJu..."
_setup_juju ${maindir}/${imagefile}
cleanup_build_directory ${maindir}
}
function setup_from_file_juju(){
# Setup from file the JuJu environment
[ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment"
local imagefile=$1
[ ! -e ${imagefile} ] && die "Error: The JuJu image file ${imagefile} does not exist"
info "Installing JuJu from ${imagefile}..."
_setup_juju ${ORIGIN_WD}/${imagefile}
builtin cd $ORIGIN_WD
}
function run_juju_as_root(){
[ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment"
mkdir -p ${JUJU_HOME}/${HOME}
${JUJU_HOME}/usr/bin/arch-chroot $JUJU_HOME /usr/bin/bash -c 'mkdir -p /run/lock && /bin/sh'
}
function _run_juju_with_proot(){
if ${PROOT} ${JUJU_HOME}/usr/bin/true &> /dev/null
then
JUJU_ENV=1 ${PROOT} $@ ${JUJU_HOME} ${SH}
else
JUJU_ENV=1 PROOT_NO_SECCOMP=1 ${PROOT} $@ ${JUJU_HOME} ${SH}
fi
}
function run_juju_as_fakeroot(){
_run_juju_with_proot "-S"
}
function run_juju_as_user(){
_run_juju_with_proot "-R"
}
function delete_juju(){
[ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment"
! ask "Are you sure to delete JuJu located in ${JUJU_HOME}" "N" && return
if mountpoint -q ${JUJU_HOME}
then
info "There are mounted directories inside ${JUJU_HOME}"
if ! umount --force ${JUJU_HOME}
then
error "Cannot umount directories in ${JUJU_HOME}"
die "Try to delete juju using root permissions"
fi
fi
if rm -rf ${JUJU_HOME}/*
then
info "JuJu deleted in ${JUJU_HOME}"
else
error "Error: Cannot delete JuJu in ${JUJU_HOME}"
fi
}
function _check_package(){
if ! pacman -Qq $1 > /dev/null
then
die "Package $1 must be installed"
fi
}
function build_image_juju(){
# The function must runs on ArchLinux
# The dependencies are:
# arch-install-scripts
# base-devel
# package-query
# git
_check_package arch-install-scripts
_check_package gcc
_check_package package-query
_check_package git
local maindir=$(TMPDIR=$JUJU_TEMPDIR mktemp -d -t juju.XXXXXXXXXX)
mkdir -p ${maindir}/root
prepare_build_directory
info "Installing pacman and its dependencies..."
pacstrap -d ${maindir}/root pacman arch-install-scripts binutils libunistring
info "Generating the locales..."
ln -sf /usr/share/zoneinfo/posix/UTC ${maindir}/root/etc/localtime
echo "en_US.UTF-8 UTF-8" >> ${maindir}/root/etc/locale.gen
arch-chroot ${maindir}/root locale-gen
echo 'LANG = "en_US.UTF-8"' >> ${maindir}/root/etc/locale.conf
info "Compiling and installing yaourt..."
mkdir -p ${maindir}/packages/{package-query,yaourt,proot}
builtin cd ${maindir}/packages/package-query
$WGET https://aur.archlinux.org/packages/pa/package-query/PKGBUILD
makepkg -sfc --asroot
pacman --noconfirm --root ${maindir}/root -U package-query*.pkg.tar.xz
builtin cd ${maindir}/packages/yaourt
$WGET https://aur.archlinux.org/packages/ya/yaourt/PKGBUILD
makepkg -sfc --asroot
pacman --noconfirm --root ${maindir}/root -U yaourt*.pkg.tar.xz
info "Compiling and installing proot..."
builtin cd ${maindir}/packages/proot
$WGET https://aur.archlinux.org/packages/pr/proot/PKGBUILD
makepkg -sfcA --asroot
pacman --noconfirm --root ${maindir}/root -U proot*.pkg.tar.xz
rm ${maindir}/root/var/cache/pacman/pkg/*
info "Copying JuJu scripts..."
git clone https://github.com/fsquillace/juju.git ${maindir}/root/opt/juju
echo 'export PATH=$PATH:/opt/juju/bin' > ${maindir}/root/etc/profile.d/juju.sh
chmod +x ${maindir}/root/etc/profile.d/juju.sh
builtin cd ${ORIGIN_WD}
local imagefile="juju-${ARCH}.tar.gz"
info "Compressing image to ${imagefile}..."
tar -zcpf ${imagefile} -C ${maindir}/root .
cleanup_build_directory ${maindir}
}

141
lib/core/build.sh Normal file
View file

@ -0,0 +1,141 @@
#!/usr/bin/env bash
#
# This module contains all build functionalities for JuNest.
#
# Dependencies:
# - lib/utils/utils.sh
# - lib/core/common.sh
#
# vim: ft=sh
function _install_pkg(){
# This function allows to install packages from AUR.
# At the moment is not used.
local maindir=$1
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 _prepare() {
# ArchLinux System initialization
prepare_archlinux
# curl is used to download pacman.conf file
sudo pacman -S --noconfirm git arch-install-scripts haveged curl
}
function build_image_env(){
set -x
umask 022
# 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 )) && \
die "You cannot build with root privileges."
_prepare
local disable_validation=$1
local maindir
maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t "${CMD}".XXXXXXXXXX)
sudo mkdir -p "${maindir}"/root
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..."
# All the essential executables (ln, mkdir, chown, etc) are in coreutils
# bwrap command belongs to bubblewrap
sudo pacstrap -G -M "${maindir}"/root pacman coreutils bubblewrap
if [[ ${ARCH} != "arm" ]]
then
# x86_64 does not have any mirror set by default...
sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist"
fi
sudo mkdir -p "${maindir}"/root/run/lock
# For some reasons, pacstrap does not create the pacman.conf file,
# I could not reproduce the issue locally though:
# https://app.travis-ci.com/github/fsquillace/junest/builds/268216346
[[ -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..."
# sed command is required for locale-gen but it is required by fakeroot
# 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 "${maindir}"/root/bin/groot "${maindir}"/root locale-gen
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!)..."
if [[ $(uname -m) == *"arm"* ]]
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/*
# 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
builtin cd "${maindir}"/output || return 1
local imagefile="${CMD}-${ARCH}.tar.gz"
info "Compressing image to ${imagefile}..."
sudo "$TAR" -zcpf "${imagefile}" -C "${maindir}"/root .
if ! $disable_validation
then
mkdir -p "${maindir}"/root_test
$TAR -zxpf "${imagefile}" -C "${maindir}/root_test"
JUNEST_HOME="${maindir}/root_test" "${JUNEST_BASE}"/lib/checks/check_all.sh
fi
sudo cp "${maindir}"/output/"${imagefile}" "${ORIGIN_WD}"
builtin cd "${ORIGIN_WD}" || return 1
trap - QUIT EXIT ABRT KILL TERM INT
sudo rm -fr "$maindir"
set +x
}

104
lib/core/chroot.sh Normal file
View file

@ -0,0 +1,104 @@
#!/usr/bin/env bash
#
# This module contains all chroot functionalities for JuNest.
#
# Dependencies:
# - lib/utils/utils.sh
# - lib/core/common.sh
#
# vim: ft=sh
function _run_env_as_xroot(){
local cmd=$1
local backend_args="$2"
local no_copy_files="$3"
shift 3
check_same_arch
local uid=$UID
# SUDO_USER is more reliable compared to SUDO_UID
[[ -z $SUDO_USER ]] || uid=$SUDO_USER:$SUDO_GID
local args=()
[[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")")
# With chown the ownership of the files is assigned to the real user
trap - QUIT EXIT ABRT KILL TERM INT
# shellcheck disable=SC2064
trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT TERM INT
if ! $no_copy_files
then
copy_common_files
fi
# shellcheck disable=SC2086
JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${DEFAULT_SH[@]}" "${args[@]}"
}
#######################################
# Run JuNest as real root via GRoot command.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# UID (RO) : The user ID.
# SUDO_USER (RO) : The sudo user ID.
# SUDO_GID (RO) : The sudo group ID.
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to backend program
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by DEFAULT_SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Output:
# - : The command output.
#######################################
function run_env_as_groot(){
check_nested_env
local backend_command="${1:-$GROOT}"
local backend_args="$2"
local no_copy_files="$3"
shift 3
provide_common_bindings
local bindings=${RESULT}
unset RESULT
_run_env_as_xroot "$backend_command $bindings" "$backend_args" "$no_copy_files" "$@"
}
#######################################
# Run JuNest as real root via chroot command.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# UID (RO) : The user ID.
# SUDO_USER (RO) : The sudo user ID.
# SUDO_GID (RO) : The sudo group ID.
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to backend program
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by DEFAULT_SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Output:
# - : The command output.
#######################################
function run_env_as_chroot(){
check_nested_env
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" "$@"
}

335
lib/core/common.sh Normal file
View file

@ -0,0 +1,335 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034
# shellcheck disable=SC1091
#
# This module contains all common functionalities for JuNest.
#
# Dependencies:
# - lib/utils/utils.sh
#
# vim: ft=sh
NAME='JuNest'
CMD='junest'
DESCRIPTION='The Arch Linux based distro that runs upon any Linux distros without root access'
NOT_AVAILABLE_ARCH=102
NOT_EXISTING_FILE=103
ARCHITECTURE_MISMATCH=104
ROOT_ACCESS_ERROR=105
NESTED_ENVIRONMENT=106
VARIABLE_NOT_SET=107
NO_CONFIG_FOUND=108
UNPRIVILEGED_USERNS_DISABLED=109
JUNEST_HOME=${JUNEST_HOME:-~/.${CMD}}
JUNEST_TEMPDIR=${JUNEST_TEMPDIR:-/tmp}
# The update of the variable PATH ensures that the executables are
# found on different locations
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
# of the host system, so a fallback mechanism cannot be used for it.
UNAME="uname"
ARCH_LIST=('x86_64' 'x86' 'arm')
HOST_ARCH=$($UNAME -m)
# To check all available architectures look here:
# https://wiki.archlinux.org/index.php/PKGBUILD#arch
if [[ $HOST_ARCH == "i686" ]] || [[ $HOST_ARCH == "i386" ]]
then
ARCH="x86"
LD_LIB="${JUNEST_HOME}/lib/ld-linux.so.2"
elif [[ $HOST_ARCH == "x86_64" ]]
then
ARCH="x86_64"
LD_LIB="${JUNEST_HOME}/lib64/ld-linux-x86-64.so.2"
elif [[ $HOST_ARCH =~ .*(arm).* ]] || [[ $HOST_ARCH == "aarch64" ]]
then
ARCH="arm"
LD_LIB="${JUNEST_HOME}/lib/ld-linux-armhf.so.3"
else
die "Unknown architecture ${HOST_ARCH}"
fi
MAIN_REPO=https://link.storjshare.io/s/jvb5tgarnjtt565fffa44spvyuga/junest-repo
MAIN_REPO=https://pub-a2af2344e8554f6c807bc3db355ae622.r2.dev
ENV_REPO=${MAIN_REPO}/${CMD}
# shellcheck disable=SC2016
DEFAULT_MIRROR='https://mirror.rackspace.com/archlinux/$repo/os/$arch'
ORIGIN_WD=$(pwd)
################## EXECUTABLES ################
# This section contains all the executables needed for JuNest to run properly.
# They are based on a fallback mechanism that tries to use the executable in
# different locations in the host OS.
# List of executables that are run inside JuNest:
DEFAULT_SH=("/bin/sh" "--login")
# List of executables that are run in the host OS:
BWRAP="${JUNEST_HOME}/usr/bin/bwrap"
PROOT="${JUNEST_HOME}/usr/bin/proot-${ARCH}"
GROOT="${JUNEST_HOME}/usr/bin/groot"
CLASSIC_CHROOT=chroot
WGET="wget --content-disposition --no-check-certificate"
CURL="curl -L -J -O -k"
TAR="tar"
CHOWN="chown"
LN="ln"
RM="rm"
MKDIR="mkdir"
GETENT="getent"
CP="cp"
ID="id"
# Used for checking user namespace in config.gz file
ZGREP="zgrep"
UNSHARE="unshare"
LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
# The following functions attempt first to run the executable in the host OS.
# As a last hope they try to run the same executable available in the JuNest
# image.
function ln_cmd(){
$LN "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$LN "$@"
}
function getent_cmd(){
$GETENT "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$GETENT "$@"
}
function cp_cmd(){
$CP "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CP "$@"
}
function rm_cmd(){
$RM "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$RM "$@"
}
function chown_cmd(){
$CHOWN "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CHOWN "$@"
}
function mkdir_cmd(){
$MKDIR "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$MKDIR "$@"
}
function zgrep_cmd(){
# No need for LD_EXEC as zgrep is a POSIX shell script
$ZGREP "$@" || "${JUNEST_HOME}"/usr/bin/$ZGREP "$@"
}
function download_cmd(){
$WGET "$@" || $CURL "$@"
}
function chroot_cmd(){
$CLASSIC_CHROOT "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CLASSIC_CHROOT "$@"
}
function unshare_cmd(){
# Most of the distros do not have the `unshare` command updated
# with --user option available.
# Hence, give priority to the `unshare` executable in JuNest image.
# Also, unshare provides an environment in which /bin/sh maps to dash shell,
# therefore it ignores all the remaining DEFAULT_SH arguments (i.e. --login) as
# they are not supported by dash.
if $LD_EXEC "${JUNEST_HOME}"/usr/bin/$UNSHARE --user "${DEFAULT_SH[0]}" "-c" ":"
then
$LD_EXEC "${JUNEST_HOME}"/usr/bin/$UNSHARE "${@}"
elif $UNSHARE --user "${DEFAULT_SH[0]}" "-c" ":"
then
$UNSHARE "$@"
else
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
}
function proot_cmd(){
local proot_args="$1"
shift
# shellcheck disable=SC2086
if ${PROOT} ${proot_args} "${DEFAULT_SH[@]}" "-c" ":"
then
# shellcheck disable=SC2086
${PROOT} ${proot_args} "${@}"
elif PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${DEFAULT_SH[@]}" "-c" ":"
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} "${@}"
else
die "Error: Something went wrong with proot command. Exiting"
fi
}
############## COMMON FUNCTIONS ###############
#######################################
# Check if the executable is being running inside a JuNest environment.
#
# Globals:
# JUNEST_ENV (RO) : The boolean junest env check
# NESTED_ENVIRONMENT (RO) : The nest env exception
# VARIABLE_NOT_SET (RO) : The var not set exception
# NAME (RO) : The JuNest name
# Arguments:
# None
# Returns:
# VARIABLE_NOT_SET : If no JUNEST_ENV is not properly set
# NESTED_ENVIRONMENT : If the script is executed inside JuNest env
# Output:
# None
#######################################
function check_nested_env() {
if [[ $JUNEST_ENV == "1" ]]
then
die_on_status $NESTED_ENVIRONMENT "Error: Nested ${NAME} environments are not allowed"
elif [[ -n $JUNEST_ENV ]] && [[ $JUNEST_ENV != "0" ]]
then
die_on_status $VARIABLE_NOT_SET "The variable JUNEST_ENV is not properly set"
fi
}
#######################################
# Check if the architecture between Host OS and Guest OS is the same.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home path.
# ARCHITECTURE_MISMATCH (RO) : The arch mismatch exception
# ARCH (RO) : The host OS arch
# JUNEST_ARCH (RO) : The JuNest arch
# Arguments:
# None
# Returns:
# ARCHITECTURE_MISMATCH : If arch between host and guest is not the same
# Output:
# None
#######################################
function check_same_arch() {
source "${JUNEST_HOME}"/etc/junest/info
[ "$JUNEST_ARCH" != "$ARCH" ] && \
die_on_status $ARCHITECTURE_MISMATCH "The host system architecture is not correct: $ARCH != $JUNEST_ARCH"
return 0
}
#######################################
# Provide the proot common binding options for both normal user and fakeroot.
# The list of bindings can be found in `proot --help`. This function excludes
# /etc/mtab file so that it will not give conflicts with the related
# symlink in the image.
#
# Globals:
# HOME (RO) : The home directory.
# RESULT (WO) : Contains the binding options.
# Arguments:
# None
# Returns:
# None
# Output:
# None
#######################################
function provide_common_bindings(){
RESULT=""
local re='(.*):.*'
for bind in "/dev" "/sys" "/proc" "/tmp" "$HOME" "/run/user/$($ID -u)"
do
if [[ $bind =~ $re ]]
then
[ -e "${BASH_REMATCH[1]}" ] && RESULT="-b $bind $RESULT"
else
[ -e "$bind" ] && RESULT="-b $bind $RESULT"
fi
done
return 0
}
#######################################
# Build passwd and group files using getent command.
# If getent fails the function fallbacks by copying the content from /etc/passwd
# and /etc/group.
#
# The generated passwd and group will be stored in $JUNEST_HOME/etc/junest.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# Arguments:
# None
# Returns:
# None
# Output:
# None
#######################################
function copy_passwd_and_group(){
# Enumeration of users/groups is disabled/limited depending on how nsswitch.conf
# is configured.
# Try to at least get the current user via `getent passwd $USER` since it uses
# a more reliable and faster system call (getpwnam(3)).
if ! getent_cmd passwd > "${JUNEST_HOME}"/etc/passwd || \
! getent_cmd passwd "${USER}" >> "${JUNEST_HOME}"/etc/passwd
then
warn "getent command failed or does not exist. Binding directly from /etc/passwd."
copy_file /etc/passwd
fi
if ! getent_cmd group > "${JUNEST_HOME}"/etc/group
then
warn "getent command failed or does not exist. Binding directly from /etc/group."
copy_file /etc/group
fi
return 0
}
function copy_file() {
local file="${1}"
# -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
}
function copy_common_files() {
copy_file /etc/host.conf
copy_file /etc/hosts
copy_file /etc/nsswitch.conf
copy_file /etc/resolv.conf
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
}

165
lib/core/namespace.sh Normal file
View file

@ -0,0 +1,165 @@
#!/usr/bin/env bash
#
# This module contains functionalities for accessing to JuNest via bubblewrap.
#
# https://github.com/containers/bubblewrap
#
# Dependencies:
# - lib/utils/utils.sh
# - lib/core/common.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_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() {
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=""
if [[ -e $CONFIG_PROC_FILE ]]
then
config_file=$CONFIG_PROC_FILE
elif [[ -e $CONFIG_BOOT_FILE ]]
then
config_file=$CONFIG_BOOT_FILE
else
return "$NOT_EXISTING_FILE"
fi
# `-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
return "$NO_CONFIG_FOUND"
fi
return "$UNPRIVILEGED_USERNS_DISABLED"
}
function _check_user_namespace() {
set +e
_is_user_namespace_enabled
case $? in
"$NOT_EXISTING_FILE") warn "Could not understand if user namespace is enabled. No config.gz file found. 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
set -e
}
#######################################
# Run JuNest as fakeroot 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.
# $ROOT_ACCESS_ERROR : If the user is the real root.
# Output:
# - : The command output.
#######################################
function run_env_as_bwrap_fakeroot(){
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
fi
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[@]}"
}

138
lib/core/proot.sh Normal file
View file

@ -0,0 +1,138 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091
#
# This module contains all proot functionalities for JuNest.
#
# Dependencies:
# - lib/utils/utils.sh
# - lib/core/common.sh
#
# vim: ft=sh
function _run_env_with_proot(){
local backend_command="${1:-$PROOT}"
local backend_args="$2"
shift 2
local args=()
[[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")")
# Resets PATH to avoid polluting with host related bin paths
PATH='' PROOT="${backend_command}" JUNEST_ENV=1 proot_cmd "${backend_args}" "${DEFAULT_SH[@]}" "${args[@]}"
}
function _run_env_with_qemu(){
local backend_command="$1"
local backend_args="$2"
shift 2
source "${JUNEST_HOME}"/etc/junest/info
if [ "$JUNEST_ARCH" != "$ARCH" ]
then
local qemu_bin="qemu-$JUNEST_ARCH-static-$ARCH"
local qemu_symlink="/tmp/${qemu_bin}-$RANDOM"
trap - QUIT EXIT 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..."
[[ -e ${qemu_symlink} ]] || \
ln_cmd -s "${JUNEST_HOME}/bin/${qemu_bin}" "${qemu_symlink}"
backend_args="-q ${qemu_symlink} $backend_args"
fi
_run_env_with_proot "${backend_command}" "$backend_args" "${@}"
}
#######################################
# Run JuNest as fakeroot.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# EUID (RO) : The user ID.
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to proot
# 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:
# $ROOT_ACCESS_ERROR : If the user is the real root.
# Output:
# - : The command output.
#######################################
function run_env_as_proot_fakeroot(){
(( EUID == 0 )) && \
die_on_status "$ROOT_ACCESS_ERROR" "You cannot access with root privileges. Use --groot option instead."
check_nested_env
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
local bindings=${RESULT}
unset RESULT
# An alternative is via -S option:
#_run_env_with_qemu "-S ${JUNEST_HOME} $1" "${@:2}"
_run_env_with_qemu "$backend_command" "-0 ${bindings} -r ${JUNEST_HOME} $backend_args" "$@"
}
#######################################
# Run JuNest as normal user.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# EUID (RO) : The user ID.
# DEFAULT_SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to proot
# 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:
# $ROOT_ACCESS_ERROR : If the user is the real root.
# Output:
# - : The command output.
#######################################
function run_env_as_proot_user(){
(( EUID == 0 )) && \
die_on_status "$ROOT_ACCESS_ERROR" "You cannot access with root privileges. Use --groot option instead."
check_nested_env
local backend_command="$1"
local backend_args="$2"
local no_copy_files="$3"
shift 3
if ! $no_copy_files
then
# Files to bind are visible in `proot --help`.
# This function excludes /etc/mtab file so that
# it will not give conflicts with the related
# symlink in the Arch Linux image.
copy_common_files
copy_file /etc/hosts.equiv
copy_file /etc/netgroup
copy_file /etc/networks
# No need for localtime as it is setup during the image build
#copy_file /etc/localtime
copy_passwd_and_group
fi
provide_common_bindings
local bindings=${RESULT}
unset RESULT
_run_env_with_qemu "$backend_command" "${bindings} -r ${JUNEST_HOME} $backend_args" "$@"
}

164
lib/core/setup.sh Normal file
View file

@ -0,0 +1,164 @@
#!/usr/bin/env bash
#
# This module contains all setup functionalities for JuNest.
#
# Dependencies:
# - lib/utils/utils.sh
# - lib/core/common.sh
#
# vim: ft=sh
#######################################
# Check if the JuNest system is installed in JUNEST_HOME.
#
# Globals:
# JUNEST_HOME (RO) : Contains the JuNest home directory.
# Arguments:
# None
# Returns:
# 0 : If JuNest is installed
# 1 : If JuNest is not installed
# Output:
# None
#######################################
function is_env_installed(){
[[ -d "$JUNEST_HOME" ]] && [[ "$(ls -A "$JUNEST_HOME")" ]] && return 0
return 1
}
function _cleanup_build_directory(){
local maindir=$1
check_not_null "$maindir"
builtin cd "$ORIGIN_WD" || return 1
trap - QUIT EXIT ABRT KILL TERM INT
rm_cmd -fr "$maindir"
}
function _prepare_build_directory(){
local maindir=$1
check_not_null "$maindir"
trap - QUIT EXIT ABRT KILL TERM INT
# shellcheck disable=SC2064
trap "rm_cmd -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT TERM INT
}
function _setup_env(){
local imagepath=$1
check_not_null "$imagepath"
is_env_installed && die "Error: ${NAME} has been already installed in $JUNEST_HOME"
mkdir_cmd -p "${JUNEST_HOME}"
$TAR -zxpf "${imagepath}" -C "${JUNEST_HOME}"
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 " pacman -Syy"
echo
info "To install packages from AUR follow the wiki here:"
info "https://github.com/fsquillace/junest#install-packages-from-aur"
}
#######################################
# Setup JuNest.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory in which JuNest needs
# to be installed.
# ARCH (RO) : The host architecture.
# JUNEST_TEMPDIR (RO) : The JuNest temporary directory for building
# the JuNest system from the image.
# ENV_REPO (RO) : URL of the site containing JuNest images.
# NAME (RO) : The JuNest name.
# Arguments:
# arch ($1?) : The JuNest architecture image to download.
# Defaults to the host architecture
# Returns:
# $NOT_AVAILABLE_ARCH : If the architecture is not one of the available ones.
# Output:
# None
#######################################
function setup_env(){
local arch=${1:-$ARCH}
contains_element "$arch" "${ARCH_LIST[@]}" || \
die_on_status "$NOT_AVAILABLE_ARCH" "The architecture is not one of: ${ARCH_LIST[*]}"
local maindir
maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t "${CMD}".XXXXXXXXXX)
_prepare_build_directory "$maindir"
info "Downloading ${NAME}..."
builtin cd "${maindir}" || return 1
local imagefile=${CMD}-${arch}.tar.gz
download_cmd "${ENV_REPO}/${imagefile}"
info "Installing ${NAME}..."
_setup_env "${maindir}/${imagefile}"
_cleanup_build_directory "${maindir}"
}
#######################################
# Setup JuNest from file.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory in which JuNest needs
# to be installed.
# NAME (RO) : The JuNest name.
# Arguments:
# imagefile ($1) : The JuNest image file.
# Returns:
# $NOT_EXISTING_FILE : If the image file does not exist.
# Output:
# None
#######################################
function setup_env_from_file(){
local imagefile=$1
check_not_null "$imagefile"
[[ ! -e ${imagefile} ]] && die_on_status "$NOT_EXISTING_FILE" "Error: The ${NAME} image file ${imagefile} does not exist"
info "Installing ${NAME} from ${imagefile}..."
_setup_env "${imagefile}"
}
#######################################
# Remove an existing JuNest system.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory to remove.
# Arguments:
# None
# Returns:
# None
# Output:
# None
#######################################
function delete_env(){
! ask "Are you sure to delete ${NAME} located in ${JUNEST_HOME}" "N" && return
if mountpoint -q "${JUNEST_HOME}"
then
info "There are mounted directories inside ${JUNEST_HOME}"
if ! umount --force "${JUNEST_HOME}"
then
error "Cannot umount directories in ${JUNEST_HOME}"
die "Try to delete ${NAME} using root permissions"
fi
fi
# the CA directories are read only and can be deleted only by changing the mod
chmod -R +w "${JUNEST_HOME}"/etc/ca-certificates
if rm_cmd -rf "${JUNEST_HOME}"
then
info "${NAME} deleted in ${JUNEST_HOME}"
else
error "Error: Cannot delete ${NAME} in ${JUNEST_HOME}"
fi
}

60
lib/core/wrappers.sh Normal file
View 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
}

View file

@ -1,67 +0,0 @@
#!/usr/bin/env bash
#
# This file is part of JuJu: The portable GNU/Linux distribution
#
# Copyright (c) 2012-2014 Filippo Squillace <feel.squally@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
echoerr() { echo "$@" 1>&2; }
function die(){
# $@: msg (mandatory) - str: Message to print
error $@
exit 1
}
function error(){
# $@: msg (mandatory) - str: Message to print
echoerr -e "\033[1;31m$@\033[0m"
}
function warn(){
# $@: msg (mandatory) - str: Message to print
echoerr -e "\033[1;33m$@\033[0m"
}
function info(){
# $@: msg (mandatory) - str: Message to print
echo -e "\033[1;37m$@\033[0m"
}
function ask(){
# $1: question string
# $2: default value - can be either Y, y, N, n (by default Y)
local default="Y"
[ -z $2 ] || default=$(echo "$2" | tr '[:lower:]' '[:upper:]')
local other="n"
[ "$default" == "N" ] && other="y"
local prompt="$1 (${default}/${other})> "
local res="none"
while [ "$res" != "Y" ] && [ "$res" != "N" ] && [ "$res" != "" ];
do
read -p "$prompt" res
res=$(echo "$res" | tr '[:lower:]' '[:upper:]')
done
[ "$res" == "" ] && res="$default"
if [ "$res" == "Y" ]
then
return 0
else
return 1
fi
}

205
lib/utils/utils.sh Normal file
View file

@ -0,0 +1,205 @@
#!/usr/bin/env bash
NULL_EXCEPTION=11
WRONG_ANSWER=33
#######################################
# Check if the argument is null.
#
# Globals:
# None
# Arguments:
# argument ($1) : Argument to check.
# Returns:
# 0 : If argument is not null.
# NULL_EXCEPTION : If argument is null.
# Output:
# None
#######################################
function check_not_null() {
[ -z "$1" ] && { error "Error: null argument $1"; return $NULL_EXCEPTION; }
return 0
}
#######################################
# Redirect message to stderr.
#
# Globals:
# None
# Arguments:
# msg ($@): Message to print.
# Returns:
# None
# Output:
# Message printed to stderr.
#######################################
function echoerr() {
echo "$@" 1>&2;
}
#######################################
# Print an error message to stderr and exit program.
#
# Globals:
# None
# Arguments:
# msg ($@) : Message to print.
# Returns:
# 1 : The unique exit status printed.
# Output:
# Message printed to stderr.
#######################################
function die() {
error "$@"
exit 1
}
#######################################
# Print an error message to stderr and exit program with a given status.
#
# Globals:
# None
# Arguments:
# status ($1) : The exit status to use.
# msg ($2-) : Message to print.
# Returns:
# $? : The $status exit status.
# Output:
# Message printed to stderr.
#######################################
function die_on_status() {
status=$1
shift
error "$@"
exit "$status"
}
#######################################
# Print an error message to stderr.
#
# Globals:
# None
# Arguments:
# msg ($@): Message to print.
# Returns:
# None
# Output:
# Message printed to stderr.
#######################################
function error() {
echoerr -e "\033[1;31m$*\033[0m"
}
#######################################
# Print a warn message to stderr.
#
# Globals:
# None
# Arguments:
# msg ($@): Message to print.
# Returns:
# None
# Output:
# Message printed to stderr.
#######################################
function warn() {
# $@: msg (mandatory) - str: Message to print
echoerr -e "\033[1;33m$*\033[0m"
}
#######################################
# Print an info message to stdout.
#
# Globals:
# None
# Arguments:
# msg ($@): Message to print.
# Returns:
# None
# Output:
# Message printed to stdout.
#######################################
function info(){
echo -e "\033[1;36m$*\033[0m"
}
#######################################
# Ask a question and wait to receive an answer from stdin.
# It returns $default_answer if no answer has be received from stdin.
#
# Globals:
# None
# Arguments:
# question ($1) : The question to ask.
# default_answer ($2) : Possible values: 'Y', 'y', 'N', 'n' (default: 'Y')
# Returns:
# 0 : If user replied with either 'Y' or 'y'.
# 1 : If user replied with either 'N' or 'n'.
# WRONG_ANSWER : If `default_answer` is not one of the possible values.
# Output:
# Print the question to ask.
#######################################
function ask(){
local question=$1
local default_answer=$2
check_not_null "$question"
if [ -n "$default_answer" ]
then
local answers="Y y N n"
[[ "$answers" =~ $default_answer ]] || { error "The default answer: $default_answer is wrong."; return $WRONG_ANSWER; }
fi
local default="Y"
[ -z "$default_answer" ] || default=$(echo "$default_answer" | tr '[:lower:]' '[:upper:]')
local other="n"
[ "$default" == "N" ] && other="y"
local prompt
prompt=$(info "$question (${default}/${other})> ")
local res="none"
while [ "$res" != "Y" ] && [ "$res" != "N" ] && [ "$res" != "" ];
do
read -r -p "$prompt" res
res=$(echo "$res" | tr '[:lower:]' '[:upper:]')
done
[ "$res" == "" ] && res="$default"
[ "$res" == "Y" ]
}
function insert_quotes_on_spaces(){
# It inserts quotes between arguments.
# Useful to preserve quotes on command
# to be used inside sh -c/bash -c
local C=""
whitespace="[[:space:]]"
for i in "$@"
do
if [[ $i =~ $whitespace ]]
then
temp_C="\"$i\""
else
temp_C="$i"
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
echo "$C"
}
contains_element () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}

22
tests/checkstyle/checkstyle.sh Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091
source "$(dirname "$0")/../utils/utils.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
function test_check_no_tabs(){
assertCommandFailOnStatus 1 grep -R "$(printf '\t')" "$(dirname "$0")"/../../bin/*
assertEquals "" "$(cat "$STDOUTF")"
assertEquals "" "$(cat "$STDERRF")"
assertCommandFailOnStatus 1 grep -R "$(printf '\t')" "$(dirname "$0")"/../../lib/*
assertEquals "" "$(cat "$STDOUTF")"
assertEquals "" "$(cat "$STDERRF")"
}
source "$(dirname "$0")"/../utils/shunit2

125
tests/unit-tests/test-chroot.sh Executable file
View file

@ -0,0 +1,125 @@
#!/bin/bash
# shellcheck disable=SC1091
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
source "$JUNEST_ROOT/tests/utils/utils.sh"
source "$JUNEST_ROOT/lib/utils/utils.sh"
source "$JUNEST_ROOT/lib/core/common.sh"
source "$JUNEST_ROOT/lib/core/chroot.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
function setUp(){
cwdSetUp
junestSetUp
init_mocks
}
function tearDown(){
junestTearDown
cwdTearDown
}
function init_mocks() {
chroot_cmd() {
# shellcheck disable=SC2317
[ "$JUNEST_ENV" != "1" ] && return 1
# shellcheck disable=SC2317
echo "chroot_cmd $*"
}
# shellcheck disable=SC2034
GROOT=chroot_cmd
mychroot() {
# shellcheck disable=SC2317
echo mychroot "$*"
}
}
function test_run_env_as_groot_cmd(){
assertCommandSuccess run_env_as_groot "" "" "false" 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")"
}
function test_run_env_as_groot_no_cmd(){
assertCommandSuccess run_env_as_groot "" "" "false" ""
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(){
assertCommandSuccess run_env_as_groot "" "-n -b /home/blah" "false" pwd
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(){
assertCommandSuccess run_env_as_chroot "" "" "false" pwd
assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")"
}
function test_run_env_as_chroot_no_cmd(){
assertCommandSuccess run_env_as_chroot "" "" "false" ""
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(){
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")"
}
source "$JUNEST_ROOT"/tests/utils/shunit2

242
tests/unit-tests/test-common.sh Executable file
View file

@ -0,0 +1,242 @@
#!/bin/bash
# shellcheck disable=SC1091
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
source "$JUNEST_ROOT/tests/utils/utils.sh"
source "$JUNEST_ROOT/lib/utils/utils.sh"
source "$JUNEST_ROOT/lib/core/common.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
junestSetUp
}
function oneTimeTearDown(){
junestTearDown
}
function setUp(){
ld_exec_mock() {
# shellcheck disable=SC2317
echo "ld_exec $*"
}
# shellcheck disable=SC2317
ld_exec_mock_false() {
echo "ld_exec $*"
return 1
}
# shellcheck disable=SC2034
LD_EXEC=ld_exec_mock
unshare_mock() {
# shellcheck disable=SC2317
echo "unshare $*"
}
# shellcheck disable=SC2034
UNSHARE=unshare_mock
# shellcheck disable=SC2317
bwrap_mock() {
echo "bwrap $*"
}
# shellcheck disable=SC2034
BWRAP=bwrap_mock
}
function test_ln(){
LN="echo" assertCommandSuccess ln_cmd -s ln_file new_file
assertEquals "-s ln_file new_file" "$(cat "$STDOUTF")"
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")"
LN=false LD_EXEC=false assertCommandFail ln_cmd
}
function test_getent(){
GETENT="echo" assertCommandSuccess getent_cmd passwd
assertEquals "passwd" "$(cat "$STDOUTF")"
GETENT="false" assertCommandSuccess getent_cmd passwd
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat "$STDOUTF")"
GETENT=false LD_EXEC=false assertCommandFail getent_cmd
}
function test_cp(){
CP="echo" assertCommandSuccess cp_cmd passwd
assertEquals "passwd" "$(cat "$STDOUTF")"
CP=false assertCommandSuccess cp_cmd passwd
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat "$STDOUTF")"
CP=false LD_EXEC=false assertCommandFail cp_cmd
}
function test_download(){
WGET=/bin/true
CURL=/bin/false
assertCommandSuccess download_cmd
# shellcheck disable=SC2034
WGET=/bin/false
# shellcheck disable=SC2034
CURL=/bin/true
assertCommandSuccess download_cmd
WGET=/bin/false CURL=/bin/false assertCommandFail download_cmd
}
function test_rm(){
RM="echo" assertCommandSuccess rm_cmd rm_file
assertEquals "rm_file" "$(cat "$STDOUTF")"
RM="false" assertCommandSuccess rm_cmd rm_file
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false rm_file" "$(cat "$STDOUTF")"
RM=false LD_EXEC=false assertCommandFail rm_cmd rm_file
}
function test_chown(){
local id
id=$(id -u)
CHOWN="echo" assertCommandSuccess chown_cmd "$id" chown_file
assertEquals "$id chown_file" "$(cat "$STDOUTF")"
CHOWN="false" assertCommandSuccess chown_cmd "$id" chown_file
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false $id chown_file" "$(cat "$STDOUTF")"
CHOWN=false LD_EXEC=false assertCommandFail chown_cmd "$id" chown_file
}
function test_mkdir(){
MKDIR="echo" assertCommandSuccess mkdir_cmd -p new_dir/new_dir
assertEquals "-p new_dir/new_dir" "$(cat "$STDOUTF")"
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")"
MKDIR=false LD_EXEC=false assertCommandFail mkdir_cmd -p new_dir/new_dir
}
function test_zgrep(){
ZGREP="echo" assertCommandSuccess zgrep_cmd new_file
assertEquals "new_file" "$(cat "$STDOUTF")"
mkdir -p "${JUNEST_HOME}"/usr/bin
touch "${JUNEST_HOME}"/usr/bin/false
chmod +x "${JUNEST_HOME}"/usr/bin/false
echo -e "#!/bin/bash\necho zgrep" > "${JUNEST_HOME}"/usr/bin/false
ZGREP=false assertCommandSuccess zgrep_cmd new_file
assertEquals "zgrep" "$(cat "$STDOUTF")"
echo -e "#!/bin/bash\nexit 1" > "${JUNEST_HOME}"/usr/bin/false
ZGREP=false assertCommandFail zgrep_cmd new_file
}
function test_unshare(){
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")"
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")"
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(){
CLASSIC_CHROOT="echo" assertCommandSuccess chroot_cmd root
assertEquals "root" "$(cat "$STDOUTF")"
CLASSIC_CHROOT=false assertCommandSuccess chroot_cmd root
assertEquals "ld_exec $JUNEST_HOME/usr/bin/false root" "$(cat "$STDOUTF")"
CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
}
function test_proot_cmd_compat(){
PROOT="/bin/true" assertCommandSuccess proot_cmd "" ""
PROOT="/bin/false" assertCommandFail proot_cmd --helps
}
function test_proot_cmd_seccomp(){
envv(){
# shellcheck disable=SC2317
env
}
PROOT=envv
assertCommandSuccess proot_cmd cmd
assertEquals "" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")"
envv(){
# shellcheck disable=SC2317
env | grep "^PROOT_NO_SECCOMP"
}
# shellcheck disable=SC2034
PROOT=envv
assertCommandSuccess proot_cmd cmd
# The variable PROOT_NO_SECCOMP will be produced
# twice due to the fallback mechanism
assertEquals "PROOT_NO_SECCOMP=1
PROOT_NO_SECCOMP=1" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")"
}
function test_copy_passwd_and_group(){
getent_cmd_mock() {
# shellcheck disable=SC2317
echo "$*"
}
GETENT=getent_cmd_mock assertCommandSuccess copy_passwd_and_group
assertEquals "$(echo -e "passwd\npasswd $USER")" "$(cat "$JUNEST_HOME"/etc/passwd)"
assertEquals "group" "$(cat "$JUNEST_HOME"/etc/group)"
}
function test_copy_passwd_and_group_fallback(){
cp_cmd_mock() {
# shellcheck disable=SC2317
echo "$*"
}
CP=cp_cmd_mock GETENT=false LD_EXEC=false assertCommandSuccess copy_passwd_and_group
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(){
CP=false GETENT=false LD_EXEC=false assertCommandFailOnStatus 1 copy_passwd_and_group
}
function test_nested_env(){
JUNEST_ENV=1 assertCommandFailOnStatus 106 check_nested_env
}
function test_nested_env_not_set_variable(){
JUNEST_ENV=aaa assertCommandFailOnStatus 107 check_nested_env
}
function test_check_same_arch_not_same(){
echo "JUNEST_ARCH=XXX" > "${JUNEST_HOME}"/etc/junest/info
assertCommandFailOnStatus 104 check_same_arch
}
function test_check_same_arch(){
echo "JUNEST_ARCH=$ARCH" > "${JUNEST_HOME}"/etc/junest/info
assertCommandSuccess check_same_arch
}
source "$JUNEST_ROOT"/tests/utils/shunit2

383
tests/unit-tests/test-junest.sh Executable file
View file

@ -0,0 +1,383 @@
#!/bin/bash
# shellcheck disable=SC1091
source "$(dirname "$0")/../utils/utils.sh"
JUNEST_BASE="$(dirname "$0")/../.."
source "$JUNEST_BASE"/bin/junest -h &> /dev/null
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
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(){
return 0
}
# shellcheck disable=SC2317
function create_wrappers(){
:
}
}
function test_help(){
assertCommandSuccess main -h
assertEquals "usage" "$(cat "$STDOUTF")"
assertCommandSuccess main --help
assertEquals "usage" "$(cat "$STDOUTF")"
}
function test_version(){
assertCommandSuccess main -V
assertEquals "version" "$(cat "$STDOUTF")"
assertCommandSuccess main --version
assertEquals "version" "$(cat "$STDOUTF")"
}
function test_build_image_env(){
assertCommandSuccess main b
assertEquals "build_image_env(false)" "$(cat "$STDOUTF")"
assertCommandSuccess main build
assertEquals "build_image_env(false)" "$(cat "$STDOUTF")"
assertCommandSuccess main b -n
assertEquals "build_image_env(true)" "$(cat "$STDOUTF")"
assertCommandSuccess main build --disable-check
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(){
assertCommandSuccess main s -d
assertEquals "delete_env" "$(cat "$STDOUTF")"
assertCommandSuccess main setup --delete
assertEquals "delete_env" "$(cat "$STDOUTF")"
}
function test_setup_env_from_file(){
# shellcheck disable=SC2317
is_env_installed(){
return 1
}
assertCommandSuccess main s -i myimage
assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")"
assertCommandSuccess main setup --from-file myimage
assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")"
# shellcheck disable=SC2317
is_env_installed(){
return 0
}
assertCommandFail main setup -i myimage
}
function test_setup_env(){
# shellcheck disable=SC2317
is_env_installed(){
return 1
}
assertCommandSuccess main s
assertEquals "setup_env()" "$(cat "$STDOUTF")"
assertCommandSuccess main setup
assertEquals "setup_env()" "$(cat "$STDOUTF")"
assertCommandSuccess main s -a arm
assertEquals "setup_env(arm)" "$(cat "$STDOUTF")"
assertCommandSuccess main setup --arch arm
assertEquals "setup_env(arm)" "$(cat "$STDOUTF")"
# shellcheck disable=SC2317
is_env_installed(){
return 0
}
assertCommandFail main setup -a arm
}
function test_run_env_as_proot_fakeroot(){
assertCommandSuccess main p -f
assertEquals "run_env_as_proot_fakeroot(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main proot --fakeroot
assertEquals "run_env_as_proot_fakeroot(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main p -f -n
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(){
assertCommandSuccess main proot
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 --backend-command blah
assertEquals "run_env_as_proot_user(blah,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main proot --backend-command blah
assertEquals "run_env_as_proot_user(blah,,false,)" "$(cat "$STDOUTF")"
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(){
assertCommandSuccess main g
assertEquals "run_env_as_groot(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main g -n
assertEquals "run_env_as_groot(,,true,)" "$(cat "$STDOUTF")"
assertCommandSuccess main g -b "-b arg"
assertEquals "run_env_as_groot(,-b arg,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main 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(){
assertCommandSuccess main r
assertEquals "run_env_as_chroot(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main r -b "-b arg"
assertEquals "run_env_as_chroot(,-b arg,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main 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_as_bwrap_fakeroot(){
assertCommandSuccess main n -f
assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns -f
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 ns -f -b "-b arg"
assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns -f -b "-b arg" -- command -kv
assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns -f command --as
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_run_env_as_bwrap_user(){
assertCommandSuccess main n
assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns
assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns -n
assertEquals "run_env_as_bwrap_user(,,true,)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns -b "-b arg"
assertEquals "run_env_as_bwrap_user(,-b arg,false,)" "$(cat "$STDOUTF")"
assertCommandSuccess main ns -b "-b arg" -- command -kv
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
}
function test_invalid_option(){
assertCommandFail main --no-option
assertCommandFail main n --no-option
assertCommandFail main g --no-option
assertCommandFail main r --no-option
assertCommandFail main p --no-option
assertCommandFail main b --no-option
assertCommandFail main s --no-option
}
source "$(dirname "$0")"/../utils/shunit2

View file

@ -0,0 +1,241 @@
#!/bin/bash
# shellcheck disable=SC1091
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
source "$JUNEST_ROOT/tests/utils/utils.sh"
source "$JUNEST_ROOT/lib/utils/utils.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
## Mock functions ##
function init_mocks() {
# shellcheck disable=SC2317
function bwrap_cmd(){
echo "$BWRAP $*"
}
}
function setUp(){
cwdSetUp
junestSetUp
# Attempt to source the files under test to revert variable
# overrides (i.e. SH variable)
source "$JUNEST_ROOT/lib/core/common.sh"
source "$JUNEST_ROOT/lib/core/namespace.sh"
set +e
init_mocks
}
function tearDown(){
junestTearDown
cwdTearDown
}
function _test_copy_common_files() {
[[ -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/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)"
}
function _test_copy_remaining_files() {
[[ -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/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat "${JUNEST_HOME}"/etc/networks)"
[[ -e ${JUNEST_HOME}/etc/passwd ]]
assertEquals 0 $?
[[ -e ${JUNEST_HOME}/etc/group ]]
assertEquals 0 $?
}
function test_is_user_namespace_enabled_no_config_file(){
PROC_USERNS_FILE="blah"
PROC_USERNS_CLONE_FILE="blah"
CONFIG_PROC_FILE="blah"
CONFIG_BOOT_FILE="blah"
assertCommandFailOnStatus "$NOT_EXISTING_FILE" _is_user_namespace_enabled
}
function test_is_user_namespace_enabled_no_config(){
PROC_USERNS_FILE="blah"
PROC_USERNS_CLONE_FILE="blah"
touch config
gzip config
# shellcheck disable=SC2034
CONFIG_PROC_FILE="config.gz"
# shellcheck disable=SC2034
CONFIG_BOOT_FILE="blah"
assertCommandFailOnStatus "$NO_CONFIG_FOUND" _is_user_namespace_enabled
}
function test_is_user_namespace_enabled_with_userns_clone_file_disabled(){
PROC_USERNS_FILE="blah"
PROC_USERNS_CLONE_FILE="unprivileged_userns_clone"
echo "0" > $PROC_USERNS_CLONE_FILE
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
}
function test_is_user_namespace_enabled_with_proc_userns_file_existing(){
PROC_USERNS_FILE="user"
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_remaining_files
}
function test_run_env_as_bwrap_user_with_backend_command() {
assertCommandSuccess run_env_as_bwrap_user "mybwrap" "" "false"
assertEquals "mybwrap $COMMON_BWRAP_OPTION /bin/sh --login" "$(cat "$STDOUTF")"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_bwrap_fakeroot_no_copy() {
assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "true" ""
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_remaining_files
}
function test_run_env_as_bwrap_fakeroot_with_command() {
assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "false" "ls -la"
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_remaining_files
}
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

220
tests/unit-tests/test-proot.sh Executable file
View file

@ -0,0 +1,220 @@
#!/bin/bash
# shellcheck disable=SC1091
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
source "$JUNEST_ROOT/tests/utils/utils.sh"
source "$JUNEST_ROOT/lib/utils/utils.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
function setUp(){
cwdSetUp
junestSetUp
# Attempt to source the files under test to revert variable
# overrides (i.e. SH variable)
source "$JUNEST_ROOT/lib/core/common.sh"
source "$JUNEST_ROOT/lib/core/proot.sh"
set +e
}
function tearDown(){
junestTearDown
cwdTearDown
}
function _test_copy_common_files() {
[[ -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/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)"
}
function _test_copy_remaining_files() {
[[ -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/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat "${JUNEST_HOME}"/etc/networks)"
[[ -e ${JUNEST_HOME}/etc/passwd ]]
assertEquals 0 $?
[[ -e ${JUNEST_HOME}/etc/group ]]
assertEquals 0 $?
}
function test_run_env_as_proot_user(){
# shellcheck disable=SC2317
_run_env_with_qemu() {
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false" "/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")"
SH=("/usr/bin/echo")
assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false"
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_remaining_files
}
function test_run_env_as_proot_user_with_backend_command(){
# shellcheck disable=SC2317
_run_env_with_qemu() {
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
assertCommandSuccess run_env_as_proot_user "myproot" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
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")
assertCommandSuccess run_env_as_proot_user "myproot" "-k 3.10" "false"
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
}
function test_run_env_as_proot_fakeroot_with_backend_command(){
# shellcheck disable=SC2317
_run_env_with_qemu() {
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
assertCommandSuccess run_env_as_proot_fakeroot "myproot" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
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(){
# shellcheck disable=SC2317
proot_cmd() {
[ "$JUNEST_ENV" != "1" ] && return 1
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
assertCommandSuccess _run_env_with_proot "" "--help"
assertEquals "--help /bin/sh --login" "$(cat "$STDOUTF")"
assertCommandSuccess _run_env_with_proot "" "--help" mycommand
assertEquals "--help /bin/sh --login -c mycommand" "$(cat "$STDOUTF")"
assertCommandFail _run_env_with_proot
}
function test_qemu() {
echo "JUNEST_ARCH=arm" > "${JUNEST_HOME}"/etc/junest/info
# shellcheck disable=SC2317
rm_cmd() {
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
# shellcheck disable=SC2317
ln_cmd() {
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
# shellcheck disable=SC2317
_run_env_with_proot() {
# shellcheck disable=SC2086
# shellcheck disable=SC2048
echo $*
}
RANDOM=100 ARCH=x86_64 assertCommandSuccess _run_env_with_qemu "" ""
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

85
tests/unit-tests/test-setup.sh Executable file
View file

@ -0,0 +1,85 @@
#!/bin/bash
# shellcheck disable=SC1091
JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..)
source "$JUNEST_ROOT/tests/utils/utils.sh"
source "$JUNEST_ROOT/lib/utils/utils.sh"
source "$JUNEST_ROOT/lib/core/common.sh"
source "$JUNEST_ROOT/lib/core/setup.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
function setUp(){
cwdSetUp
junestSetUp
}
function tearDown(){
junestTearDown
cwdTearDown
}
function test_is_env_installed(){
rm -rf "${JUNEST_HOME:?}"/*
assertCommandFail is_env_installed
touch "$JUNEST_HOME"/just_file
assertCommandSuccess is_env_installed
}
function test_setup_env(){
rm -rf "${JUNEST_HOME:?}"/*
# shellcheck disable=SC2317
wget_mock(){
# Proof that the setup is happening
# inside $JUNEST_TEMPDIR
local cwd=${PWD#"${JUNEST_TEMPDIR}"}
local parent_dir=${PWD%"${cwd}"}
assertEquals "$JUNEST_TEMPDIR" "${parent_dir}"
touch file
tar -czvf "${CMD}-${ARCH}".tar.gz file
}
# shellcheck disable=SC2034
WGET=wget_mock
# shellcheck disable=SC2119
setup_env 1> /dev/null
assertTrue "[ -e $JUNEST_HOME/file ]"
assertCommandFailOnStatus 102 setup_env "noarch"
}
function test_setup_env_from_file(){
rm -rf "${JUNEST_HOME:?}"/*
touch file
tar -czvf "${CMD}-${ARCH}".tar.gz file 1> /dev/null
assertCommandSuccess setup_env_from_file "${CMD}-${ARCH}.tar.gz"
assertTrue "[ -e $JUNEST_HOME/file ]"
}
function test_setup_env_from_file_not_existing_file(){
assertCommandFailOnStatus 103 setup_env_from_file noexist.tar.gz
}
function test_setup_env_from_file_with_absolute_path(){
rm -rf "${JUNEST_HOME:?}"/*
touch file
tar -czf "${CMD}-${ARCH}".tar.gz file
assertCommandSuccess setup_env_from_file "${CMD}-${ARCH}.tar.gz"
assertTrue "[ -e $JUNEST_HOME/file ]"
}
function test_delete_env(){
echo "N" | delete_env 1> /dev/null
assertCommandSuccess is_env_installed
echo "Y" | delete_env 1> /dev/null
assertCommandFail is_env_installed
}
source "$JUNEST_ROOT"/tests/utils/shunit2

105
tests/unit-tests/test-utils.sh Executable file
View file

@ -0,0 +1,105 @@
#!/bin/bash
# shellcheck disable=SC1091
source "$(dirname "$0")/../utils/utils.sh"
unset HOME
export HOME
HOME=$(TMPDIR=/tmp mktemp -d -t pearl-user-home.XXXXXXX)
source "$(dirname "$0")/../../lib/utils/utils.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
function test_check_not_null(){
assertCommandFailOnStatus 11 check_not_null "" ""
assertCommandSuccess check_not_null "bla" ""
}
function test_echoerr(){
assertCommandSuccess echoerr "Test"
assertEquals "Test" "$(cat "$STDERRF")"
}
function test_error(){
assertCommandSuccess error "Test"
local expected
expected=$(echo -e "\033[1;31mTest\033[0m")
assertEquals "$expected" "$(cat "$STDERRF")"
}
function test_warn(){
assertCommandSuccess warn "Test"
local expected
expected=$(echo -e "\033[1;33mTest\033[0m")
assertEquals "$expected" "$(cat "$STDERRF")"
}
function test_info(){
assertCommandSuccess info "Test"
local expected
expected=$(echo -e "\033[1;36mTest\033[0m")
assertEquals "$expected" "$(cat "$STDOUTF")"
}
function test_die(){
assertCommandFail die "Test"
local expected
expected=$(echo -e "\033[1;31mTest\033[0m")
assertEquals "$expected" "$(cat "$STDERRF")"
}
function test_die_on_status(){
assertCommandFailOnStatus 222 die_on_status 222 "Test"
local expected
expected=$(echo -e "\033[1;31mTest\033[0m")
assertEquals "$expected" "$(cat "$STDERRF")"
}
function test_ask_null_question(){
assertCommandFailOnStatus 11 ask "" "Y"
}
function test_ask(){
echo "Y" | ask "Test" &> /dev/null
assertEquals 0 $?
echo "y" | ask "Test" &> /dev/null
assertEquals 0 $?
echo "N" | ask "Test" &> /dev/null
assertEquals 1 $?
echo "n" | ask "Test" &> /dev/null
assertEquals 1 $?
echo -e "\n" | ask "Test" &> /dev/null
assertEquals 0 $?
echo -e "\n" | ask "Test" "N" &> /dev/null
assertEquals 1 $?
echo -e "asdf\n\n" | ask "Test" "N" &> /dev/null
assertEquals 1 $?
}
function test_ask_wrong_default_answer() {
echo "Y" | ask "Test" G &> /dev/null
assertEquals 33 $?
}
function test_insert_quotes_on_spaces(){
assertCommandSuccess insert_quotes_on_spaces this is "a test"
assertEquals "this is \"a test\"" "$(cat "$STDOUTF")"
assertCommandSuccess insert_quotes_on_spaces this is 'a test'
assertEquals "this is \"a test\"" "$(cat "$STDOUTF")"
}
function test_contains_element(){
array=("something to search for" "a string" "test2000")
assertCommandSuccess contains_element "a string" "${array[@]}"
assertCommandFailOnStatus 1 contains_element "blabla" "${array[@]}"
}
source "$(dirname "$0")"/../utils/shunit2

139
tests/unit-tests/test-wrappers.sh Executable file
View 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

9
tests/unit-tests/unit-tests.sh Executable file
View file

@ -0,0 +1,9 @@
#!/bin/bash
tests_succeded=true
# shellcheck disable=SC2010
for tst in $(ls "$(dirname "$0")"/test* | grep -v "$(basename "$0")")
do
$tst || tests_succeded=false
done
$tests_succeded

1067
tests/utils/shunit2 Normal file

File diff suppressed because it is too large Load diff

62
tests/utils/utils.sh Normal file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env bash
OLD_CWD=${PWD}
function cwdSetUp(){
ORIGIN_CWD=$(TMPDIR=/tmp mktemp -d -t junest-cwd.XXXXXXXXXX)
cd "$ORIGIN_CWD" || return 1
}
function cwdTearDown(){
rm -rf "$ORIGIN_CWD"
cd "$OLD_CWD" || return 1
}
function junestSetUp(){
JUNEST_HOME=$(TMPDIR=/tmp mktemp -d -t junest-home.XXXXXXXXXX)
mkdir -p "${JUNEST_HOME}/usr/bin"
mkdir -p "${JUNEST_HOME}/etc/junest"
echo "JUNEST_ARCH=x86_64" > "${JUNEST_HOME}/etc/junest/info"
mkdir -p "${JUNEST_HOME}/etc/ca-certificates"
}
function junestTearDown(){
# 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"
rm -rf "$JUNEST_HOME"
unset JUNEST_HOME
}
function setUpUnitTests(){
OUTPUT_DIR="${SHUNIT_TMPDIR}/output"
mkdir "${OUTPUT_DIR}"
STDOUTF="${OUTPUT_DIR}/stdout"
STDERRF="${OUTPUT_DIR}/stderr"
}
function assertCommandSuccess(){
# shellcheck disable=SC2091
$(set -e
"$@" > "$STDOUTF" 2> "$STDERRF"
)
assertTrue "The command $1 did not return 0 exit status" $?
}
function assertCommandFail(){
# shellcheck disable=SC2091
$(set -e
"$@" > "$STDOUTF" 2> "$STDERRF"
)
assertFalse "The command $1 returned 0 exit status" $?
}
# $1: expected exit status
# $2-: The command under test
function assertCommandFailOnStatus(){
local status=$1
shift
# shellcheck disable=SC2091
$(set -e
"$@" > "$STDOUTF" 2> "$STDERRF"
)
assertEquals "$status" $?
}