diff --git a/.travis.yml b/.travis.yml index 153b779..fab23ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,8 @@ script: # 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 diff --git a/README.md b/README.md index 72ae100..1268f8b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ 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.

@@ -11,7 +18,7 @@ The lightweight Arch Linux based distro that runs, without root privileges, on t |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) | [![Join the Discord server at https://discord.gg/ttfBT7MKve](https://img.shields.io/badge/Discord-Server-blueviolet.svg)](https://discord.gg/ttfBT7MKve) | +| [![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) @@ -63,6 +70,37 @@ 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 ========== @@ -70,7 +108,9 @@ Setup environment ----------------- The first operation required is to install the JuNest environment in the -location of your choice (by default `~/.junest`, configurable via the environment variable `JUNEST_HOME`): +location of your choice via `JUNEST_HOME` environment variable +(it must contain an absolute path) which by +default is `~/.junest`: ```sh junest setup @@ -177,37 +217,6 @@ 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). -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/` - Usage ===== There are three different ways you can run JuNest depending on the backend program you decide to use. diff --git a/VERSION b/VERSION index bd8293a..ef13716 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.4.6 +7.4.10 diff --git a/bin/junest b/bin/junest index 356482d..4084fe0 100755 --- a/bin/junest +++ b/bin/junest @@ -250,6 +250,7 @@ function execute_operation() { $ACT_VERSION && version && return if $ACT_BUILD; then + # shellcheck disable=SC2086 build_image_env $OPT_DISABLE_CHECK return fi @@ -281,6 +282,7 @@ function execute_operation() { fi if $ACT_CREATE_WRAPPERS; then + # shellcheck disable=SC2086 create_wrappers $OPT_FORCE "$OPT_BIN_PATH" exit fi @@ -305,7 +307,9 @@ function execute_operation() { 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[@]}" } diff --git a/lib/core/build.sh b/lib/core/build.sh index 0f3d8b0..65a9474 100644 --- a/lib/core/build.sh +++ b/lib/core/build.sh @@ -25,7 +25,8 @@ function _install_pkg(){ function _prepare() { # ArchLinux System initialization prepare_archlinux - sudo pacman -S --noconfirm git arch-install-scripts haveged + # curl is used to download pacman.conf file + sudo pacman -S --noconfirm git arch-install-scripts haveged curl } function build_image_env(){ @@ -59,13 +60,23 @@ function build_image_env(){ fi sudo mkdir -p "${maindir}"/root/run/lock - sudo tee -a "${maindir}"/root/etc/pacman.conf > /dev/null <> ${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" - sudo pacman --noconfirm --root "${maindir}"/root -Rsn gzip info "Setting up the pacman keyring (this might take a while!)..." if [[ $(uname -m) == *"arm"* ]] diff --git a/lib/core/namespace.sh b/lib/core/namespace.sh index bbda112..70763bd 100644 --- a/lib/core/namespace.sh +++ b/lib/core/namespace.sh @@ -15,8 +15,24 @@ COMMON_BWRAP_OPTION="--bind "$JUNEST_HOME" / --bind "$HOME" "$HOME" --bind /tmp 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 @@ -35,19 +51,7 @@ function _is_user_namespace_enabled() { return "$NO_CONFIG_FOUND" fi - if [[ ! -e $PROC_USERNS_CLONE_FILE ]] - then - return 0 - fi - - # `-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 "$UNPRIVILEGED_USERNS_DISABLED" - fi - - return 0 + return "$UNPRIVILEGED_USERNS_DISABLED" } function _check_user_namespace() { diff --git a/tests/unit-tests/test-chroot.sh b/tests/unit-tests/test-chroot.sh index 703004d..3739c58 100755 --- a/tests/unit-tests/test-chroot.sh +++ b/tests/unit-tests/test-chroot.sh @@ -29,12 +29,15 @@ function tearDown(){ 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 "$*" } } diff --git a/tests/unit-tests/test-common.sh b/tests/unit-tests/test-common.sh index d0a6c0b..89c1a1e 100755 --- a/tests/unit-tests/test-common.sh +++ b/tests/unit-tests/test-common.sh @@ -22,8 +22,10 @@ function oneTimeTearDown(){ function setUp(){ ld_exec_mock() { + # shellcheck disable=SC2317 echo "ld_exec $*" } + # shellcheck disable=SC2317 ld_exec_mock_false() { echo "ld_exec $*" return 1 @@ -32,11 +34,13 @@ function setUp(){ 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 $*" } @@ -173,6 +177,7 @@ function test_proot_cmd_compat(){ function test_proot_cmd_seccomp(){ envv(){ + # shellcheck disable=SC2317 env } PROOT=envv @@ -180,6 +185,7 @@ function test_proot_cmd_seccomp(){ assertEquals "" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")" envv(){ + # shellcheck disable=SC2317 env | grep "^PROOT_NO_SECCOMP" } # shellcheck disable=SC2034 @@ -193,6 +199,7 @@ 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 @@ -202,6 +209,7 @@ function test_copy_passwd_and_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 diff --git a/tests/unit-tests/test-junest.sh b/tests/unit-tests/test-junest.sh index 086062f..07a92b1 100755 --- a/tests/unit-tests/test-junest.sh +++ b/tests/unit-tests/test-junest.sh @@ -15,25 +15,32 @@ function oneTimeSetUp(){ 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" @@ -41,6 +48,7 @@ function setUp(){ 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" @@ -48,6 +56,7 @@ function setUp(){ 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" @@ -55,6 +64,7 @@ function setUp(){ 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" @@ -62,6 +72,7 @@ function setUp(){ 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" @@ -69,6 +80,7 @@ function setUp(){ 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" @@ -76,9 +88,11 @@ function setUp(){ 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(){ : } @@ -108,6 +122,7 @@ function test_build_image_env(){ } function test_create_wrappers(){ + # shellcheck disable=SC2317 function create_wrappers(){ local force=$1 echo "create_wrappers($force)" @@ -126,6 +141,7 @@ function test_delete_env(){ assertEquals "delete_env" "$(cat "$STDOUTF")" } function test_setup_env_from_file(){ + # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -134,6 +150,7 @@ function test_setup_env_from_file(){ assertCommandSuccess main setup --from-file myimage assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 0 } @@ -141,6 +158,7 @@ function test_setup_env_from_file(){ } function test_setup_env(){ + # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -153,6 +171,7 @@ function test_setup_env(){ assertCommandSuccess main setup --arch arm assertEquals "setup_env(arm)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 0 } @@ -181,6 +200,7 @@ function test_run_env_as_proot_fakeroot(){ 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 } @@ -207,6 +227,7 @@ function test_run_env_as_user(){ assertCommandSuccess main proot -- command -ls assertEquals "run_env_as_proot_user(,,false,command -ls)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -231,6 +252,7 @@ function test_run_env_as_groot(){ assertCommandSuccess main groot -- command assertEquals "run_env_as_groot(,,false,command)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -253,6 +275,7 @@ function test_run_env_as_chroot(){ assertCommandSuccess main root -- command assertEquals "run_env_as_chroot(,,false,command)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -295,6 +318,7 @@ function test_run_env_as_bwrap_fakeroot(){ assertCommandSuccess main -f -- command --as assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -337,6 +361,7 @@ function test_run_env_as_bwrap_user(){ assertCommandSuccess main -- command --as assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")" + # shellcheck disable=SC2317 is_env_installed(){ return 1 } diff --git a/tests/unit-tests/test-namespace.sh b/tests/unit-tests/test-namespace.sh index 373c1be..7a845aa 100755 --- a/tests/unit-tests/test-namespace.sh +++ b/tests/unit-tests/test-namespace.sh @@ -16,6 +16,7 @@ function oneTimeSetUp(){ ## Mock functions ## function init_mocks() { + # shellcheck disable=SC2317 function bwrap_cmd(){ echo "$BWRAP $*" } @@ -58,50 +59,45 @@ function _test_copy_remaining_files() { } 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_config(){ - echo "CONFIG_USER_NS=y" > config - gzip config - CONFIG_PROC_FILE="config.gz" - CONFIG_BOOT_FILE="blah" - PROC_USERNS_CLONE_FILE="not-existing-file" - assertCommandSuccess _is_user_namespace_enabled -} - function test_is_user_namespace_enabled_with_userns_clone_file_disabled(){ - echo "CONFIG_USER_NS=y" > config - gzip config - CONFIG_PROC_FILE="config.gz" - CONFIG_BOOT_FILE="blah" + 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(){ - echo "CONFIG_USER_NS=y" > config - gzip config - # shellcheck disable=SC2034 - CONFIG_PROC_FILE="config.gz" - # shellcheck disable=SC2034 - CONFIG_BOOT_FILE="blah" 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")" diff --git a/tests/unit-tests/test-proot.sh b/tests/unit-tests/test-proot.sh index dfc7498..0f4f11a 100755 --- a/tests/unit-tests/test-proot.sh +++ b/tests/unit-tests/test-proot.sh @@ -49,6 +49,7 @@ function _test_copy_remaining_files() { } function test_run_env_as_proot_user(){ + # shellcheck disable=SC2317 _run_env_with_qemu() { # shellcheck disable=SC2086 # shellcheck disable=SC2048 @@ -66,6 +67,7 @@ function test_run_env_as_proot_user(){ } function test_run_env_as_proot_user_with_backend_command(){ + # shellcheck disable=SC2317 _run_env_with_qemu() { # shellcheck disable=SC2086 # shellcheck disable=SC2048 @@ -83,6 +85,7 @@ function test_run_env_as_proot_user_with_backend_command(){ } function test_run_env_as_proot_user_no_copy(){ + # shellcheck disable=SC2317 _run_env_with_qemu() { # shellcheck disable=SC2086 # shellcheck disable=SC2048 @@ -120,6 +123,7 @@ function test_run_env_as_proot_user_nested_env(){ } function test_run_env_as_proot_fakeroot(){ + # shellcheck disable=SC2317 _run_env_with_qemu() { # shellcheck disable=SC2086 # shellcheck disable=SC2048 @@ -136,6 +140,7 @@ function test_run_env_as_proot_fakeroot(){ } function test_run_env_as_proot_fakeroot_with_backend_command(){ + # shellcheck disable=SC2317 _run_env_with_qemu() { # shellcheck disable=SC2086 # shellcheck disable=SC2048 @@ -159,6 +164,7 @@ function test_run_env_as_proot_fakeroot_nested_env(){ } function test_run_env_with_quotes(){ + # shellcheck disable=SC2317 _run_env_with_qemu() { # shellcheck disable=SC2086 # shellcheck disable=SC2048 @@ -169,6 +175,7 @@ function test_run_env_with_quotes(){ } function test_run_env_with_proot_args(){ + # shellcheck disable=SC2317 proot_cmd() { [ "$JUNEST_ENV" != "1" ] && return 1 # shellcheck disable=SC2086 @@ -187,16 +194,19 @@ function test_run_env_with_proot_args(){ 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 diff --git a/tests/unit-tests/test-setup.sh b/tests/unit-tests/test-setup.sh index d8c2456..de2df75 100755 --- a/tests/unit-tests/test-setup.sh +++ b/tests/unit-tests/test-setup.sh @@ -35,6 +35,7 @@ function test_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 diff --git a/tests/unit-tests/test-wrappers.sh b/tests/unit-tests/test-wrappers.sh index eef1f38..ee9776f 100755 --- a/tests/unit-tests/test-wrappers.sh +++ b/tests/unit-tests/test-wrappers.sh @@ -70,6 +70,7 @@ function test_create_wrappers_verify_content(){ assertEquals "" "$(cat "$STDOUTF")" # Mock junest command to capture the actual output generated from myfile script + # shellcheck disable=SC2317 junest(){ for arg in "$@" do