From 356bb1ca98e0633cf73c0a30a0208e396d62dff9 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Sun, 16 Nov 2014 17:53:46 +0100 Subject: [PATCH 01/17] issue #4: Allow to specify specific command --- bin/juju | 18 ++++++++++++------ lib/core.sh | 20 +++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/bin/juju b/bin/juju index 6f5e68c..d1bce75 100755 --- a/bin/juju +++ b/bin/juju @@ -29,7 +29,7 @@ source "$(dirname $0)/../lib/core.sh" usage() { echo -e "JuJu: The portable GNU/Linux distribution" - echo -e "Usage: $NAME [options]" + echo -e "Usage: $NAME [options] [command]" echo -e "Options:" echo -e "-i, --setup-from-file Setup the JuJu image in ${JUJU_HOME}" echo -e "-f, --fakeroot Run JuJu with fakeroot privileges" @@ -79,13 +79,19 @@ check_cli(){ 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" + if [ "$ARGS" != "" ] + then + if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \ + $OPT_VERSION + then + die "No arguments are needed. For the CLI syntax run: $NAME --help" + fi + fi return 0 } @@ -156,11 +162,11 @@ elif $OPT_SETUP_FROM_FILE; then fi if $OPT_FAKEROOT; then - run_juju_as_fakeroot + run_juju_as_fakeroot ${ARGS[@]} elif $OPT_ROOT; then - run_juju_as_root + run_juju_as_root ${ARGS[@]} else - run_juju_as_user + run_juju_as_user ${ARGS[@]} fi # vim: set ts=4 sw=4 noet: diff --git a/lib/core.sh b/lib/core.sh index 925696d..42d4838 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -141,31 +141,41 @@ function setup_from_file_juju(){ } +function _define_command(){ + local comm=$@ + [ "$comm" == "" ] && comm=${SH} + echo "$comm" +} + + function run_juju_as_root(){ [ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment" + local comm=$(_define_command $@) mkdir -p ${JUJU_HOME}/${HOME} - ${JUJU_HOME}/usr/bin/arch-chroot $JUJU_HOME /usr/bin/bash -c 'mkdir -p /run/lock && /bin/sh' + ${JUJU_HOME}/usr/bin/arch-chroot $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && ${comm}" } function _run_juju_with_proot(){ if ${PROOT} ${JUJU_HOME}/usr/bin/true &> /dev/null then - JUJU_ENV=1 ${PROOT} $@ ${JUJU_HOME} ${SH} + JUJU_ENV=1 ${PROOT} $@ else - JUJU_ENV=1 PROOT_NO_SECCOMP=1 ${PROOT} $@ ${JUJU_HOME} ${SH} + JUJU_ENV=1 PROOT_NO_SECCOMP=1 ${PROOT} $@ fi } function run_juju_as_fakeroot(){ - _run_juju_with_proot "-S" + local comm=$(_define_command $@) + _run_juju_with_proot "-S" ${JUJU_HOME} ${comm} } function run_juju_as_user(){ - _run_juju_with_proot "-R" + local comm=$(_define_command $@) + _run_juju_with_proot "-R" ${JUJU_HOME} ${comm} } From 811c140fed4e065901d6d751da6cd850cf781322 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Sun, 16 Nov 2014 19:32:40 +0100 Subject: [PATCH 02/17] issue #7: Expose the Proot args to JuJu cli --- README.md | 16 ++++++++++++++-- bin/juju | 27 +++++++++++++++++++-------- lib/core.sh | 17 +++++++++++------ 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a492cbf..c52057f 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,11 @@ JuJu can only works on GNU/Linux OS with kernel version greater or equal Advanced usage -------------- +### Build image ### You can build a new JuJu image from scratch by running the following command: - +``` # juju -b - +``` 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 @@ -66,6 +67,17 @@ After creating the image juju-x86\_64.tar.gz you can install it by running: # juju -i juju-x86_64.tar.gz +### Bind directories ### +To bind and host directory to a guest location, you can use proot arguments: +``` + $ juju -p "-b /mnt/mydata:/home/user/mydata" +``` + +Check out the proot options with: +``` + $ juju -p "--help" +``` + Dependencies ------------ JuJu comes with a very short list of dependencies in order to be installed in most diff --git a/bin/juju b/bin/juju index d1bce75..8f12cdc 100755 --- a/bin/juju +++ b/bin/juju @@ -34,6 +34,7 @@ usage() { echo -e "-i, --setup-from-file 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 "-p, --proot-args Proot arguments" 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" @@ -83,15 +84,22 @@ check_cli(){ then die "You must access to JuJu with either fakeroot or root permissions" fi - - if [ "$ARGS" != "" ] - then + if $OPT_PROOT_ARGS + then + if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \ + $OPT_ROOT || $OPT_VERSION + then + die "Invalid syntax: Proot args are not allowed with the other options" + fi + fi + if [ "$ARGS" != "" ] + then if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \ $OPT_VERSION then - die "No arguments are needed. For the CLI syntax run: $NAME --help" + die "No arguments are needed. For the CLI syntax run: $NAME --help" fi - fi + fi return 0 } @@ -101,7 +109,7 @@ check_cli(){ ### MAIN PROGRAM ### ################################### -TEMP=`getopt -o drfbi:hv --long delete,root,fakeroot,build-image,setup-from-file:,help,version -n 'juju' -- "$@"` +TEMP=`getopt -o drp:fbi:hv --long delete,root,proot-args:,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 @@ -112,6 +120,8 @@ OPT_SETUP_FROM_FILE=false IMAGE_FILE="" OPT_FAKEROOT=false OPT_ROOT=false +OPT_PROOT_ARGS=false +PROOT_ARGS="" OPT_BUILD_IMAGE=false OPT_DELETE=false OPT_HELP=false @@ -121,6 +131,7 @@ while true ; do -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 ;; + -p|--proot-args) OPT_PROOT_ARGS=true ; shift ; PROOT_ARGS=$1; shift ;; -b|--build-image) OPT_BUILD_IMAGE=true ; shift ;; -d|--delete) OPT_DELETE=true ; shift ;; -h|--help) OPT_HELP=true ; shift ;; @@ -162,11 +173,11 @@ elif $OPT_SETUP_FROM_FILE; then fi if $OPT_FAKEROOT; then - run_juju_as_fakeroot ${ARGS[@]} + run_juju_as_fakeroot "${PROOT_ARGS}" ${ARGS[@]} elif $OPT_ROOT; then run_juju_as_root ${ARGS[@]} else - run_juju_as_user ${ARGS[@]} + run_juju_as_user "${PROOT_ARGS}" ${ARGS[@]} fi # vim: set ts=4 sw=4 noet: diff --git a/lib/core.sh b/lib/core.sh index 42d4838..f447ce4 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -142,16 +142,21 @@ function setup_from_file_juju(){ function _define_command(){ - local comm=$@ - [ "$comm" == "" ] && comm=${SH} - echo "$comm" + local proot_args="$1" + local comm=${SH} + if [ "$2" != "" ] + then + shift + comm="$@" + fi + echo "$proot_args" "${comm[@]}" } function run_juju_as_root(){ [ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment" - local comm=$(_define_command $@) + local comm=$(_define_command "$@") mkdir -p ${JUJU_HOME}/${HOME} ${JUJU_HOME}/usr/bin/arch-chroot $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && ${comm}" } @@ -168,13 +173,13 @@ function _run_juju_with_proot(){ function run_juju_as_fakeroot(){ - local comm=$(_define_command $@) + local comm=$(_define_command "$@") _run_juju_with_proot "-S" ${JUJU_HOME} ${comm} } function run_juju_as_user(){ - local comm=$(_define_command $@) + local comm=$(_define_command "$@") _run_juju_with_proot "-R" ${JUJU_HOME} ${comm} } From fdebd2aa32b60fc2ddbce9691b3e9590a2ba95b0 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Sun, 16 Nov 2014 23:29:17 +0100 Subject: [PATCH 03/17] issue #3: Validate the image built --- lib/core.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/core.sh b/lib/core.sh index 925696d..b1774fc 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -248,6 +248,12 @@ function build_image_juju(){ echo 'export PATH=$PATH:/opt/juju/bin' > ${maindir}/root/etc/profile.d/juju.sh chmod +x ${maindir}/root/etc/profile.d/juju.sh + info "Validating JuJu image..." + arch-chroot ${maindir}/root pacman -Qi pacman &> /dev/null + arch-chroot ${maindir}/root yaourt -V &> /dev/null + arch-chroot ${maindir}/root proot --help &> /dev/null + arch-chroot ${maindir}/root arch-chroot --help &> /dev/null + builtin cd ${ORIGIN_WD} local imagefile="juju-${ARCH}.tar.gz" info "Compressing image to ${imagefile}..." From 0f6d7aaff0416aa8b1b6a1d834e57583eb39b4d1 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Wed, 19 Nov 2014 21:54:41 +0100 Subject: [PATCH 04/17] Improve function for getting the chroot and proot arguments --- lib/core.sh | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/core.sh b/lib/core.sh index cd16d27..72f5ffe 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -141,14 +141,17 @@ function setup_from_file_juju(){ } -function _define_command(){ - local proot_args="$1" +function _define_chroot_args(){ local comm=${SH} - if [ "$2" != "" ] - then - shift - comm="$@" - fi + [ "$1" != "" ] && comm="$@" + echo $comm +} + + +function _define_proot_args(){ + local proot_args="$1" + shift + local comm=$(_define_chroot_args "$@") echo "$proot_args" "${comm[@]}" } @@ -156,9 +159,8 @@ function _define_command(){ function run_juju_as_root(){ [ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment" - local comm=$(_define_command "$@") mkdir -p ${JUJU_HOME}/${HOME} - ${JUJU_HOME}/usr/bin/arch-chroot $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && ${comm}" + ${JUJU_HOME}/usr/bin/arch-chroot $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && $(_define_chroot_args "$@")" } @@ -173,13 +175,13 @@ function _run_juju_with_proot(){ function run_juju_as_fakeroot(){ - local comm=$(_define_command "$@") + local comm=$(_define_proot_args "$@") _run_juju_with_proot "-S" ${JUJU_HOME} ${comm} } function run_juju_as_user(){ - local comm=$(_define_command "$@") + local comm=$(_define_proot_args "$@") _run_juju_with_proot "-R" ${JUJU_HOME} ${comm} } From 8982cb5a24ae5e450e9cdf3cc3df24c50214bffc Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Wed, 19 Nov 2014 21:56:40 +0100 Subject: [PATCH 05/17] Make some functions in core private --- lib/core.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/core.sh b/lib/core.sh index 72f5ffe..631931d 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -83,7 +83,7 @@ function is_juju_installed(){ } -function cleanup_build_directory(){ +function _cleanup_build_directory(){ # $1: maindir (optional) - str: build directory to get rid local maindir=$1 builtin cd $ORIGIN_WD @@ -92,7 +92,7 @@ function cleanup_build_directory(){ } -function prepare_build_directory(){ +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 } @@ -113,7 +113,7 @@ function setup_juju(){ [ "$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 + _prepare_build_directory info "Downloading JuJu..." builtin cd ${maindir} @@ -123,7 +123,7 @@ function setup_juju(){ info "Installing JuJu..." _setup_juju ${maindir}/${imagefile} - cleanup_build_directory ${maindir} + _cleanup_build_directory ${maindir} } @@ -229,7 +229,7 @@ function build_image_juju(){ _check_package git local maindir=$(TMPDIR=$JUJU_TEMPDIR mktemp -d -t juju.XXXXXXXXXX) mkdir -p ${maindir}/root - prepare_build_directory + _prepare_build_directory info "Installing pacman and its dependencies..." pacstrap -d ${maindir}/root pacman arch-install-scripts binutils libunistring @@ -275,5 +275,5 @@ function build_image_juju(){ local imagefile="juju-${ARCH}.tar.gz" info "Compressing image to ${imagefile}..." tar -zcpf ${imagefile} -C ${maindir}/root . - cleanup_build_directory ${maindir} + _cleanup_build_directory ${maindir} } From 3a51433f0b86c80bd656d462a5ec51116c344564 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Thu, 20 Nov 2014 00:01:11 +0100 Subject: [PATCH 06/17] Add tests for util.sh #12 --- lib/util.sh | 4 +++- tests/util.sh | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/util.sh diff --git a/lib/util.sh b/lib/util.sh index 15fd48c..dc88506 100644 --- a/lib/util.sh +++ b/lib/util.sh @@ -17,7 +17,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -echoerr() { echo "$@" 1>&2; } +function echoerr(){ + echo "$@" 1>&2 +} function die(){ # $@: msg (mandatory) - str: Message to print error $@ diff --git a/tests/util.sh b/tests/util.sh new file mode 100644 index 0000000..0e39ad1 --- /dev/null +++ b/tests/util.sh @@ -0,0 +1,63 @@ +source "$(dirname $0)/../lib/util.sh" + +function is_equal(){ + [ "$1" == "$2" ] || return 1 && return 0 +} + +function test_echoerr(){ + local actual=$(echoerr "Test" 2>&1) + is_equal "$actual" "Test" || return 1 + return 0 +} + +function test_error(){ + local actual=$(error "Test" 2>&1) + local expected=$(echo -e "\033[1;31mTest\033[0m") + is_equal "$actual" "$expected" || return 1 + return 0 +} + +function test_warn(){ + local actual=$(warn "Test" 2>&1) + local expected=$(echo -e "\033[1;33mTest\033[0m") + is_equal "$actual" "$expected" || return 1 + return 0 +} + +function test_info(){ + local actual=$(info "Test") + local expected=$(echo -e "\033[1;37mTest\033[0m") + is_equal "$actual" "$expected" || return 1 + return 0 +} + +function test_die(){ + local actual=$(die "Test" 2>&1) + local expected=$(echo -e "\033[1;31mTest\033[0m") + is_equal "$actual" "$expected" || return 1 + return 0 +} + +function test_ask(){ + echo "Y" | ask "Test" &> /dev/null + is_equal $? 0 || return 1 + echo "y" | ask "Test" &> /dev/null + is_equal $? 0 || return 1 + echo "N" | ask "Test" &> /dev/null + is_equal $? 1 || return 1 + echo "n" | ask "Test" &> /dev/null + is_equal $? 1 || return 1 + echo -e "\n" | ask "Test" &> /dev/null + is_equal $? 0 || return 1 + echo -e "\n" | ask "Test" "N" &> /dev/null + is_equal $? 1 || return 1 + echo -e "asdf\n\n" | ask "Test" "N" &> /dev/null + is_equal $? 1 || return 1 + return 0 +} + + +for func in $(declare -F | grep test_ | awk '{print $3}' | xargs) +do + $func && echo -e "${func}...\033[1;32mOK\033[0m" || echo -e "${func}...\033[1;31mFAIL\033[0m" +done From b0a06625752d03ddb6e0bbbdfe1768172b804d39 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Mon, 24 Nov 2014 02:03:00 +0100 Subject: [PATCH 07/17] Add tests for core.sh #13 Included the tests for die as well. --- lib/core.sh | 8 +- tests/test_all.sh | 5 ++ tests/test_core.sh | 154 ++++++++++++++++++++++++++++++++ tests/{util.sh => test_util.sh} | 8 +- tests/utils.sh | 51 +++++++++++ 5 files changed, 220 insertions(+), 6 deletions(-) create mode 100755 tests/test_all.sh create mode 100755 tests/test_core.sh rename tests/{util.sh => test_util.sh} (93%) mode change 100644 => 100755 create mode 100644 tests/utils.sh diff --git a/lib/core.sh b/lib/core.sh index 631931d..c6cc042 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -75,6 +75,10 @@ then else die "The variable JUJU_ENV is not properly set" fi + +CHROOT=${JUJU_HOME}/usr/bin/arch-chroot +TRUE=${JUJU_HOME}/usr/bin/true + ################################# MAIN FUNCTIONS ############################## function is_juju_installed(){ @@ -160,12 +164,12 @@ 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 && $(_define_chroot_args "$@")" + ${CHROOT} $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && $(_define_chroot_args "$@")" } function _run_juju_with_proot(){ - if ${PROOT} ${JUJU_HOME}/usr/bin/true &> /dev/null + if ${PROOT} ${TRUE} &> /dev/null then JUJU_ENV=1 ${PROOT} $@ else diff --git a/tests/test_all.sh b/tests/test_all.sh new file mode 100755 index 0000000..684e6fd --- /dev/null +++ b/tests/test_all.sh @@ -0,0 +1,5 @@ + +for tst in $(ls $(dirname $0)/test_* | grep -v $(basename $0)) +do + $tst +done diff --git a/tests/test_core.sh b/tests/test_core.sh new file mode 100755 index 0000000..1a1dc77 --- /dev/null +++ b/tests/test_core.sh @@ -0,0 +1,154 @@ +#!/bin/bash +# To test this module you need to run it inside a Archlinux system. Also, the following packages needs to be installed: +# bash +# pacman +# arch-install-scripts +# proot +# coreutils +# grep +# sudo + +source "$(dirname $0)/utils.sh" +CURRPWD=$PWD +JUJU_HOME="" + +function set_up(){ + cd $CURRPWD + JUJU_HOME=$(TMPDIR=/tmp mktemp -d -t jujuhome.XXXXXXXXXX) + source "$(dirname $0)/../lib/core.sh" + ORIGIN_WD=$(TMPDIR=/tmp mktemp -d -t jujuowd.XXXXXXXXXX) + cd $ORIGIN_WD + JUJU_TEMPDIR=$(TMPDIR=/tmp mktemp -d -t jujutemp.XXXXXXXXXX) +} + + +function tear_down(){ + rm -rf $JUJU_HOME + rm -rf $ORIGIN_WD + rm -rf $JUJU_TEMPDIR +} + +function test_is_juju_installed(){ + is_juju_installed + is_equal $? 1 || return 1 + touch $JUJU_HOME/just_file + is_juju_installed + is_equal $? 0 || return 1 +} + + +function test_setup_juju(){ + wget_mock(){ + # Proof that the setup is happening + # inside $JUJU_TEMPDIR + local cwd=${PWD#${JUJU_TEMPDIR}} + local parent_dir=${PWD%${cwd}} + is_equal $JUJU_TEMPDIR ${parent_dir} || return 1 + touch file + tar -czvf juju-${ARCH}.tar.gz file + } + WGET=wget_mock + setup_juju 1> /dev/null + [ -e $JUJU_HOME/file ] || return 1 + [ -e $JUJU_HOME/run/lock ] || return 1 + + export -f setup_juju + JUJU_ENV=1 bash -ic "setup_juju" &> /dev/null + is_equal $? 1 || return 1 +} + + +function test_setup_from_file_juju(){ + touch file + tar -czvf juju-${ARCH}.tar.gz file 1> /dev/null + setup_from_file_juju juju-${ARCH}.tar.gz 1> /dev/null + [ -e $JUJU_HOME/file ] || return 1 + [ -e $JUJU_HOME/run/lock ] || return 1 + + export -f setup_from_file_juju + bash -ic "setup_from_file_juju noexist.tar.gz" &> /dev/null + is_equal $? 1 || return 1 + + export -f setup_from_file_juju + JUJU_ENV=1 bash -ic "setup_from_file_juju" &> /dev/null + is_equal $? 1 || return 1 +} + + +function test_run_juju_as_root(){ + install_mini_juju + CHROOT="sudo $CHROOT" + SH="type -t type" + local output=$(run_juju_as_root) + is_equal $output "builtin" || return 1 + local output=$(run_juju_as_root pwd) + is_equal $output "/" || return 1 + run_juju_as_root "[ -e /run/lock ]" + is_equal $? 0 || return 1 + [ -e $JUJU_HOME/${HOME} ] || return 1 + + export -f run_juju_as_root + JUJU_ENV=1 bash -ic "run_juju_as_root" &> /dev/null + is_equal $? 1 || return 1 +} + +function test_run_juju_as_user(){ + install_mini_juju + local output=$(run_juju_as_user "" "mkdir -v /newdir2") + is_equal "$output" "/usr/bin/mkdir: created directory '/newdir2'" || return 1 + [ -e $JUJU_HOME/newdir2 ] + is_equal $? 0 || return 1 + + SH="mkdir -v /newdir" + local output=$(run_juju_as_user "") + is_equal "$output" "/usr/bin/mkdir: created directory '/newdir'" || return 1 + [ -e $JUJU_HOME/newdir ] + is_equal $? 0 || return 1 +} + +function test_run_juju_as_user_proot_args(){ + install_mini_juju + run_juju_as_user "--help" "" 1> /dev/null + is_equal $? 0 || return 1 + run_juju_as_user "--helps" "" &> /dev/null + is_equal $? 1 || return 1 + + mkdir $JUJU_TEMPDIR/newdir + touch $JUJU_TEMPDIR/newdir/newfile + run_juju_as_user "-b $JUJU_TEMPDIR/newdir:/newdir" "ls -l /newdir/newfile" 1> /dev/null + is_equal $? 0 || return 1 +} + +#function test_run_juju_as_user_seccomp(){ + #install_mini_juju + #TRUE="/usr/bin/false" + #run_juju_as_user "" "env" "|" "grep" "PROOT_NO_SECCOMP" +#} + +#function test_run_juju_as_fakeroot(){ + #install_mini_juju + #local output=$(run_juju_as_fakeroot "" "bash") + #is_equal "$output" "root" || return 1 +#} + +function test_delete_juju(){ + install_mini_juju + echo "N" | delete_juju 1> /dev/null + is_juju_installed + is_equal $? 0 || return 1 + echo "Y" | delete_juju 1> /dev/null + is_juju_installed + is_equal $? 1 || return 1 + + export -f delete_juju + JUJU_ENV=1 bash -ic "delete_juju" &> /dev/null + is_equal $? 1 || return 1 +} + + +for func in $(declare -F | grep test_ | awk '{print $3}' | xargs) +do + set_up + $func && echo -e "${func}...\033[1;32mOK\033[0m" || echo -e "${func}...\033[1;31mFAIL\033[0m" + tear_down +done diff --git a/tests/util.sh b/tests/test_util.sh old mode 100644 new mode 100755 similarity index 93% rename from tests/util.sh rename to tests/test_util.sh index 0e39ad1..757f08f --- a/tests/util.sh +++ b/tests/test_util.sh @@ -1,9 +1,7 @@ +#!/bin/bash +source "$(dirname $0)/utils.sh" source "$(dirname $0)/../lib/util.sh" -function is_equal(){ - [ "$1" == "$2" ] || return 1 && return 0 -} - function test_echoerr(){ local actual=$(echoerr "Test" 2>&1) is_equal "$actual" "Test" || return 1 @@ -35,6 +33,8 @@ function test_die(){ local actual=$(die "Test" 2>&1) local expected=$(echo -e "\033[1;31mTest\033[0m") is_equal "$actual" "$expected" || return 1 + bash -ic "die Dying" &> /dev/null + is_equal $? 1 || return 1 return 0 } diff --git a/tests/utils.sh b/tests/utils.sh new file mode 100644 index 0000000..bd12d4e --- /dev/null +++ b/tests/utils.sh @@ -0,0 +1,51 @@ +function install_executable(){ + for i in $( ldd $* | grep -v dynamic | cut -d " " -f 3 | sed 's/://' | sort | uniq ) + do + cp --parents $i $JUJU_HOME + done + # ARCH amd64 + if [ -f /lib64/ld-linux-x86-64.so.2 ]; then + cp --parents /lib64/ld-linux-x86-64.so.2 $JUJU_HOME + fi + # ARCH i386 + if [ -f /lib/ld-linux.so.2 ]; then + cp --parents /lib/ld-linux.so.2 $JUJU_HOME + fi + cp --parent $* $JUJU_HOME/ +} + +function install_package(){ + pacman -Ql $1 | grep "/$" | sed 's/.* //' | xargs -I {} mkdir -p $JUJU_HOME/{} + pacman -Ql $1 | grep -v "/$" | sed 's/.* //' | xargs -I {} cp -f -a --parents {} $JUJU_HOME + #export -f install_executable + #export JUJU_HOME + #pacman -Ql $1 | sed 's/.* //' | grep "^/usr/bin/" | xargs -I {} bash -ic "install_executable {}" +} + +function install_mini_juju(){ + mkdir -p ${JUJU_HOME}/{proc,bin,sys,dev,run,tmp,etc} + touch ${JUJU_HOME}/etc/resolv.conf + mkdir -p ${JUJU_HOME}/usr/bin + #echo "root:x:0:0:root:/root:/bin/bash" > ${JUJU_HOME}/etc/passwd + #cp /etc/nsswitch.conf ${JUJU_HOME} + cp /usr/bin/arch-chroot ${JUJU_HOME}/usr/bin + install_executable /usr/bin/bash + install_executable /usr/bin/ls + install_executable /usr/bin/whoami + install_executable /usr/bin/grep + install_executable /usr/bin/mkdir + install_executable /usr/bin/proot + install_package bash + install_package talloc + install_package proot + install_package coreutils + install_package grep + ln -s /usr/bin/bash $JUJU_HOME/bin/sh +} + + +function is_equal(){ + [ "$1" == "$2" ] || return 1 && return 0 +} + + From 82824d79bfd0838be0fa65c4a09655f8a77d54d5 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Tue, 25 Nov 2014 00:28:47 +0100 Subject: [PATCH 08/17] Add test for run juju as fakeroot and for SECCOMP --- tests/test_core.sh | 25 +++++++++++++++---------- tests/utils.sh | 2 -- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/test_core.sh b/tests/test_core.sh index 1a1dc77..c83ad2d 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -7,6 +7,7 @@ # coreutils # grep # sudo +# gawk source "$(dirname $0)/utils.sh" CURRPWD=$PWD @@ -119,17 +120,21 @@ function test_run_juju_as_user_proot_args(){ is_equal $? 0 || return 1 } -#function test_run_juju_as_user_seccomp(){ - #install_mini_juju - #TRUE="/usr/bin/false" - #run_juju_as_user "" "env" "|" "grep" "PROOT_NO_SECCOMP" -#} +function test_run_juju_as_user_seccomp(){ + install_mini_juju + local output=$(run_juju_as_user "" "env" | grep "PROOT_NO_SECCOMP") + is_equal $output "" || return 1 -#function test_run_juju_as_fakeroot(){ - #install_mini_juju - #local output=$(run_juju_as_fakeroot "" "bash") - #is_equal "$output" "root" || return 1 -#} + TRUE="/usr/bin/false" + local output=$(run_juju_as_user "" "env" | grep "PROOT_NO_SECCOMP") + is_equal $output "PROOT_NO_SECCOMP=1" || return 1 +} + +function test_run_juju_as_fakeroot(){ + install_mini_juju + local output=$(run_juju_as_fakeroot "" "id" | awk '{print $1}') + is_equal "$output" "uid=0" || return 1 +} function test_delete_juju(){ install_mini_juju diff --git a/tests/utils.sh b/tests/utils.sh index bd12d4e..0ca7144 100644 --- a/tests/utils.sh +++ b/tests/utils.sh @@ -26,8 +26,6 @@ function install_mini_juju(){ mkdir -p ${JUJU_HOME}/{proc,bin,sys,dev,run,tmp,etc} touch ${JUJU_HOME}/etc/resolv.conf mkdir -p ${JUJU_HOME}/usr/bin - #echo "root:x:0:0:root:/root:/bin/bash" > ${JUJU_HOME}/etc/passwd - #cp /etc/nsswitch.conf ${JUJU_HOME} cp /usr/bin/arch-chroot ${JUJU_HOME}/usr/bin install_executable /usr/bin/bash install_executable /usr/bin/ls From 9f66f1682a45b1ea8f90828886de81084fd68a22 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Tue, 25 Nov 2014 01:16:06 +0100 Subject: [PATCH 09/17] Improve the mini pearl script for core unit tests --- tests/test_core.sh | 4 ++++ tests/utils.sh | 43 ++++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/tests/test_core.sh b/tests/test_core.sh index c83ad2d..5c85925 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -20,6 +20,9 @@ function set_up(){ ORIGIN_WD=$(TMPDIR=/tmp mktemp -d -t jujuowd.XXXXXXXXXX) cd $ORIGIN_WD JUJU_TEMPDIR=$(TMPDIR=/tmp mktemp -d -t jujutemp.XXXXXXXXXX) + + trap - QUIT EXIT ABRT KILL TERM INT + trap "rm -rf ${JUJU_HOME}; rm -rf ${ORIGIN_WD}; rm -rf ${JUJU_TEMPDIR}" EXIT QUIT ABRT KILL TERM INT } @@ -27,6 +30,7 @@ function tear_down(){ rm -rf $JUJU_HOME rm -rf $ORIGIN_WD rm -rf $JUJU_TEMPDIR + trap - QUIT EXIT ABRT KILL TERM INT } function test_is_juju_installed(){ diff --git a/tests/utils.sh b/tests/utils.sh index 0ca7144..9f6f263 100644 --- a/tests/utils.sh +++ b/tests/utils.sh @@ -1,44 +1,45 @@ function install_executable(){ for i in $( ldd $* | grep -v dynamic | cut -d " " -f 3 | sed 's/://' | sort | uniq ) - do - cp --parents $i $JUJU_HOME - done + do + cp -f --parents $i $JUJU_HOME + done + # ARCH amd64 if [ -f /lib64/ld-linux-x86-64.so.2 ]; then - cp --parents /lib64/ld-linux-x86-64.so.2 $JUJU_HOME + cp -f --parents /lib64/ld-linux-x86-64.so.2 $JUJU_HOME fi + # ARCH i386 if [ -f /lib/ld-linux.so.2 ]; then - cp --parents /lib/ld-linux.so.2 $JUJU_HOME + cp -f --parents /lib/ld-linux.so.2 $JUJU_HOME fi - cp --parent $* $JUJU_HOME/ + + cp -f --parents $* $JUJU_HOME/ } function install_package(){ + # Copy the directories pacman -Ql $1 | grep "/$" | sed 's/.* //' | xargs -I {} mkdir -p $JUJU_HOME/{} - pacman -Ql $1 | grep -v "/$" | sed 's/.* //' | xargs -I {} cp -f -a --parents {} $JUJU_HOME + + # Copy the files + pacman -Ql $1 | grep -v "/$" | sed 's/.* //' | xargs -I {} cp -f --parents {} $JUJU_HOME + + # Copy the dynamic libraries of the executables #export -f install_executable #export JUJU_HOME - #pacman -Ql $1 | sed 's/.* //' | grep "^/usr/bin/" | xargs -I {} bash -ic "install_executable {}" + #pacman -Ql $1 | grep -v "/$" | sed 's/.* //' | grep "^/usr/bin/" | xargs -I {} bash -ic "install_executable {}" } function install_mini_juju(){ - mkdir -p ${JUJU_HOME}/{proc,bin,sys,dev,run,tmp,etc} - touch ${JUJU_HOME}/etc/resolv.conf - mkdir -p ${JUJU_HOME}/usr/bin - cp /usr/bin/arch-chroot ${JUJU_HOME}/usr/bin - install_executable /usr/bin/bash - install_executable /usr/bin/ls - install_executable /usr/bin/whoami - install_executable /usr/bin/grep - install_executable /usr/bin/mkdir - install_executable /usr/bin/proot + install_package filesystem 2> /dev/null + install_package arch-install-scripts install_package bash - install_package talloc install_package proot install_package coreutils - install_package grep - ln -s /usr/bin/bash $JUJU_HOME/bin/sh + install_executable /usr/bin/bash + install_executable /usr/bin/ls + install_executable /usr/bin/mkdir + install_executable /usr/bin/proot } From d4ccad692ba55a6079340018085f7b605888b988 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Tue, 25 Nov 2014 21:45:47 +0100 Subject: [PATCH 10/17] Add test for juju script #11 --- bin/juju | 131 +++++++++++++++++++++----------------------- tests/test_juju.sh | 134 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 68 deletions(-) create mode 100755 tests/test_juju.sh diff --git a/bin/juju b/bin/juju index 8f12cdc..c00da88 100755 --- a/bin/juju +++ b/bin/juju @@ -105,79 +105,74 @@ check_cli(){ } -################################### -### MAIN PROGRAM ### -################################### +function parse_arguments(){ + TEMP=$(getopt -o drp:fbi:hv --long delete,root,proot-args:,fakeroot,build-image,setup-from-file:,help,version -n 'juju' -- "$@") + eval set -- "$TEMP" -TEMP=`getopt -o drp:fbi:hv --long delete,root,proot-args:,fakeroot,build-image,setup-from-file:,help,version -n 'juju' -- "$@"` + OPT_SETUP_FROM_FILE=false + IMAGE_FILE="" + OPT_FAKEROOT=false + OPT_ROOT=false + OPT_PROOT_ARGS=false + PROOT_ARGS="" + 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 ;; + -p|--proot-args) OPT_PROOT_ARGS=true ; shift ; PROOT_ARGS=$1; 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 ;; + *) die "Internal error!" ;; + esac + done -if [ $? != 0 ] ; then error "Error on parsing the command line. Try juju -h." ; exit ; fi + ARGS=() + for arg do + ARGS+=($arg) + done +} -# Note the quotes around `$TEMP': they are essential! -eval set -- "$TEMP" +function execute_operation(){ + $OPT_HELP && usage && return + $OPT_VERSION && version && return -OPT_SETUP_FROM_FILE=false -IMAGE_FILE="" -OPT_FAKEROOT=false -OPT_ROOT=false -OPT_PROOT_ARGS=false -PROOT_ARGS="" -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 ;; - -p|--proot-args) OPT_PROOT_ARGS=true ; shift ; PROOT_ARGS=$1; 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 + if $OPT_BUILD_IMAGE; then + build_image_juju + return + elif $OPT_DELETE; then + delete_juju + return + fi -ARGS=() -for arg do - ARGS+=($arg) -done + 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 -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 "${PROOT_ARGS}" ${ARGS[@]} -elif $OPT_ROOT; then - run_juju_as_root ${ARGS[@]} -else - run_juju_as_user "${PROOT_ARGS}" ${ARGS[@]} -fi + if $OPT_FAKEROOT; then + run_juju_as_fakeroot "${PROOT_ARGS}" ${ARGS[@]} + elif $OPT_ROOT; then + run_juju_as_root ${ARGS[@]} + else + run_juju_as_user "${PROOT_ARGS}" ${ARGS[@]} + fi +} +parse_arguments $@ +check_cli +execute_operation # vim: set ts=4 sw=4 noet: diff --git a/tests/test_juju.sh b/tests/test_juju.sh new file mode 100755 index 0000000..8d9a94a --- /dev/null +++ b/tests/test_juju.sh @@ -0,0 +1,134 @@ +#!/bin/bash +source "$(dirname $0)/utils.sh" +source $(dirname $0)/../bin/juju -h &> /dev/null +## Mock functions ## +function usage(){ + echo "usage" +} +function version(){ + echo "version" +} +function build_image_juju(){ + echo "build_image_juju" +} +function delete_juju(){ + echo "delete_juju" +} +function is_juju_installed(){ + return 0 +} +function setup_from_file_juju(){ + echo "setup_from_file_juju $@" +} +function setup_juju(){ + echo "setup_juju" +} +function run_juju_as_fakeroot(){ + echo "run_juju_as_fakeroot $@" +} +function run_juju_as_root(){ + echo "run_juju_as_root $@" +} +function run_juju_as_user(){ + echo "run_juju_as_user $@" +} + +function wrap_juju(){ + parse_arguments $@ + check_cli + execute_operation +} + + +function set_up(){ + echo > /dev/null +} + +function tear_down(){ + echo > /dev/null +} + + +function test_help(){ + local output=$(wrap_juju -h) + is_equal $output "usage" || return 1 + local output=$(wrap_juju --help) + is_equal $output "usage" || return 1 +} +function test_version(){ + local output=$(wrap_juju -v) + is_equal $output "version" || return 1 + local output=$(wrap_juju --version) + is_equal $output "version" || return 1 +} +function test_build_image_juju(){ + local output=$(wrap_juju -b) + is_equal $output "build_image_juju" || return 1 + local output=$(wrap_juju --build-image) + is_equal $output "build_image_juju" || return 1 +} +function test_delete_juju(){ + local output=$(wrap_juju -d) + is_equal $output "delete_juju" || return 1 + local output=$(wrap_juju --delete) + is_equal $output "delete_juju" || return 1 +} +function test_run_juju_as_fakeroot(){ + local output=$(wrap_juju -f) + is_equal $output "run_juju_as_fakeroot" || return 1 + local output=$(wrap_juju --fakeroot) + is_equal $output "run_juju_as_fakeroot" || return 1 + + local output=$(wrap_juju -f -p "-b arg") + is_equal "${output[@]}" "run_juju_as_fakeroot -b arg" || return 1 + local output=$(wrap_juju -f -p "-b arg" -- command) + is_equal "${output[@]}" "run_juju_as_fakeroot -b arg command" || return 1 + local output=$(wrap_juju -f command) + is_equal "${output[@]}" "run_juju_as_fakeroot command" || return 1 +} +function test_run_juju_as_user(){ + local output=$(wrap_juju) + is_equal $output "run_juju_as_user" || return 1 + + local output=$(wrap_juju -p "-b arg") + is_equal "${output[@]}" "run_juju_as_user -b arg" || return 1 + local output=$(wrap_juju -p "-b arg" -- command) + is_equal "${output[@]}" "run_juju_as_user -b arg command" || return 1 + local output=$(wrap_juju command) + is_equal "${output[@]}" "run_juju_as_user command" || return 1 +} +function test_run_juju_as_root(){ + local output=$(wrap_juju -r) + is_equal $output "run_juju_as_root" || return 1 + + local output=$(wrap_juju -r command) + is_equal "${output[@]}" "run_juju_as_root command" || return 1 +} + +function test_check_cli(){ + export -f check_cli + export -f parse_arguments + export -f execute_operation + export -f wrap_juju + bash -ic "wrap_juju -b -h" &> /dev/null + is_equal $? 1 || return 1 + bash -ic "wrap_juju -d -r" &> /dev/null + is_equal $? 1 || return 1 + bash -ic "wrap_juju -h -f" &> /dev/null + is_equal $? 1 || return 1 + bash -ic "wrap_juju -v -i fsd" &> /dev/null + is_equal $? 1 || return 1 + bash -ic "wrap_juju -f -r" &> /dev/null + is_equal $? 1 || return 1 + bash -ic "wrap_juju -p args -v" &> /dev/null + is_equal $? 1 || return 1 + bash -ic "wrap_juju -d args" &> /dev/null + is_equal $? 1 || return 1 +} + +for func in $(declare -F | grep test_ | awk '{print $3}' | xargs) +do + set_up + $func && echo -e "${func}...\033[1;32mOK\033[0m" || echo -e "${func}...\033[1;31mFAIL\033[0m" + tear_down +done From 4d32bf4ad85967cc004c202e4e7442ccfdfddfac Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Wed, 26 Nov 2014 23:47:06 +0100 Subject: [PATCH 11/17] Close issue #20 --- tests/test_core.sh | 25 ++++++++++------------ tests/utils.sh | 53 ++++++---------------------------------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/tests/test_core.sh b/tests/test_core.sh index 5c85925..2aacca6 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -1,18 +1,15 @@ #!/bin/bash -# To test this module you need to run it inside a Archlinux system. Also, the following packages needs to be installed: -# bash -# pacman -# arch-install-scripts -# proot -# coreutils -# grep -# sudo -# gawk source "$(dirname $0)/utils.sh" CURRPWD=$PWD +JUJU_MAIN_HOME=/tmp/jujutesthome +[ -e $JUJU_MAIN_HOME ] || JUJU_HOME=$JUJU_MAIN_HOME bash --rcfile "$(dirname $0)/../lib/core.sh" -ic "setup_juju" JUJU_HOME="" +function install_mini_juju(){ + cp -rfa $JUJU_MAIN_HOME/* $JUJU_HOME +} + function set_up(){ cd $CURRPWD JUJU_HOME=$(TMPDIR=/tmp mktemp -d -t jujuhome.XXXXXXXXXX) @@ -99,14 +96,14 @@ function test_run_juju_as_root(){ function test_run_juju_as_user(){ install_mini_juju - local output=$(run_juju_as_user "" "mkdir -v /newdir2") - is_equal "$output" "/usr/bin/mkdir: created directory '/newdir2'" || return 1 + local output=$(run_juju_as_user "" "mkdir -v /newdir2" | awk -F: '{print $1}') + is_equal "$output" "/usr/bin/mkdir" || return 1 [ -e $JUJU_HOME/newdir2 ] is_equal $? 0 || return 1 SH="mkdir -v /newdir" - local output=$(run_juju_as_user "") - is_equal "$output" "/usr/bin/mkdir: created directory '/newdir'" || return 1 + local output=$(run_juju_as_user "" | awk -F: '{print $1}') + is_equal "$output" "/usr/bin/mkdir" || return 1 [ -e $JUJU_HOME/newdir ] is_equal $? 0 || return 1 } @@ -137,7 +134,7 @@ function test_run_juju_as_user_seccomp(){ function test_run_juju_as_fakeroot(){ install_mini_juju local output=$(run_juju_as_fakeroot "" "id" | awk '{print $1}') - is_equal "$output" "uid=0" || return 1 + is_equal "$output" "uid=0(root)" || return 1 } function test_delete_juju(){ diff --git a/tests/utils.sh b/tests/utils.sh index 9f6f263..094c055 100644 --- a/tests/utils.sh +++ b/tests/utils.sh @@ -1,50 +1,11 @@ -function install_executable(){ - for i in $( ldd $* | grep -v dynamic | cut -d " " -f 3 | sed 's/://' | sort | uniq ) - do - cp -f --parents $i $JUJU_HOME - done - - # ARCH amd64 - if [ -f /lib64/ld-linux-x86-64.so.2 ]; then - cp -f --parents /lib64/ld-linux-x86-64.so.2 $JUJU_HOME - fi - - # ARCH i386 - if [ -f /lib/ld-linux.so.2 ]; then - cp -f --parents /lib/ld-linux.so.2 $JUJU_HOME - fi - - cp -f --parents $* $JUJU_HOME/ -} - -function install_package(){ - # Copy the directories - pacman -Ql $1 | grep "/$" | sed 's/.* //' | xargs -I {} mkdir -p $JUJU_HOME/{} - - # Copy the files - pacman -Ql $1 | grep -v "/$" | sed 's/.* //' | xargs -I {} cp -f --parents {} $JUJU_HOME - - # Copy the dynamic libraries of the executables - #export -f install_executable - #export JUJU_HOME - #pacman -Ql $1 | grep -v "/$" | sed 's/.* //' | grep "^/usr/bin/" | xargs -I {} bash -ic "install_executable {}" -} - -function install_mini_juju(){ - install_package filesystem 2> /dev/null - install_package arch-install-scripts - install_package bash - install_package proot - install_package coreutils - install_executable /usr/bin/bash - install_executable /usr/bin/ls - install_executable /usr/bin/mkdir - install_executable /usr/bin/proot -} - - function is_equal(){ - [ "$1" == "$2" ] || return 1 && return 0 + if [ "$1" == "$2" ] + then + return 0 + else + echo "$1!=$2" + return 1 + fi } From 95d933234c795ae27856541e6fd2867a4da90b2e Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Thu, 27 Nov 2014 00:46:43 +0100 Subject: [PATCH 12/17] Fix issue #6 --- lib/core.sh | 17 +++++++++++------ tests/test_core.sh | 10 +++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/core.sh b/lib/core.sh index c6cc042..e72219c 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -78,6 +78,7 @@ fi CHROOT=${JUJU_HOME}/usr/bin/arch-chroot TRUE=${JUJU_HOME}/usr/bin/true +ID="${JUJU_HOME}/usr/bin/id -u" ################################# MAIN FUNCTIONS ############################## @@ -169,12 +170,16 @@ function run_juju_as_root(){ function _run_juju_with_proot(){ - if ${PROOT} ${TRUE} &> /dev/null - then - JUJU_ENV=1 ${PROOT} $@ - else - JUJU_ENV=1 PROOT_NO_SECCOMP=1 ${PROOT} $@ - fi + ${PROOT} ${TRUE} &> /dev/null || export PROOT_NO_SECCOMP=1 + + [ "$(${PROOT} ${ID} 2> /dev/null )" == "0" ] && \ + die "You cannot access with root privileges. Use --root option instead." + + JUJU_ENV=1 ${PROOT} $@ + local ret=$? + export -n PROOT_NO_SECCOMP + + return $ret } diff --git a/tests/test_core.sh b/tests/test_core.sh index 2aacca6..bce0368 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -57,6 +57,7 @@ function test_setup_juju(){ export -f setup_juju JUJU_ENV=1 bash -ic "setup_juju" &> /dev/null is_equal $? 1 || return 1 + unset setup_juju } @@ -71,9 +72,9 @@ function test_setup_from_file_juju(){ bash -ic "setup_from_file_juju noexist.tar.gz" &> /dev/null is_equal $? 1 || return 1 - export -f setup_from_file_juju JUJU_ENV=1 bash -ic "setup_from_file_juju" &> /dev/null is_equal $? 1 || return 1 + unset setup_from_file_juju } @@ -92,6 +93,7 @@ function test_run_juju_as_root(){ export -f run_juju_as_root JUJU_ENV=1 bash -ic "run_juju_as_root" &> /dev/null is_equal $? 1 || return 1 + unset run_juju_as_root } function test_run_juju_as_user(){ @@ -119,6 +121,11 @@ function test_run_juju_as_user_proot_args(){ touch $JUJU_TEMPDIR/newdir/newfile run_juju_as_user "-b $JUJU_TEMPDIR/newdir:/newdir" "ls -l /newdir/newfile" 1> /dev/null is_equal $? 0 || return 1 + + export -f _run_juju_with_proot + ID="/usr/bin/echo 0" bash -ic "_run_juju_with_proot" &> /dev/null + is_equal $? 1 || return 1 + unset _run_juju_with_proot } function test_run_juju_as_user_seccomp(){ @@ -149,6 +156,7 @@ function test_delete_juju(){ export -f delete_juju JUJU_ENV=1 bash -ic "delete_juju" &> /dev/null is_equal $? 1 || return 1 + unset delete_juju } From 24a1b2b397232b43713e83a9ba92e0101623ae87 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Thu, 27 Nov 2014 22:48:48 +0100 Subject: [PATCH 13/17] Fix issue #21 --- tests/test_core.sh | 5 +++++ tests/test_juju.sh | 7 +++++++ tests/test_util.sh | 3 +++ 3 files changed, 15 insertions(+) diff --git a/tests/test_core.sh b/tests/test_core.sh index bce0368..fac8dbc 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -57,6 +57,7 @@ function test_setup_juju(){ export -f setup_juju JUJU_ENV=1 bash -ic "setup_juju" &> /dev/null is_equal $? 1 || return 1 + export -n setup_juju unset setup_juju } @@ -74,6 +75,7 @@ function test_setup_from_file_juju(){ JUJU_ENV=1 bash -ic "setup_from_file_juju" &> /dev/null is_equal $? 1 || return 1 + export -n setup_from_file_juju unset setup_from_file_juju } @@ -93,6 +95,7 @@ function test_run_juju_as_root(){ export -f run_juju_as_root JUJU_ENV=1 bash -ic "run_juju_as_root" &> /dev/null is_equal $? 1 || return 1 + export -n run_juju_as_root unset run_juju_as_root } @@ -125,6 +128,7 @@ function test_run_juju_as_user_proot_args(){ export -f _run_juju_with_proot ID="/usr/bin/echo 0" bash -ic "_run_juju_with_proot" &> /dev/null is_equal $? 1 || return 1 + export -n _run_juju_with_proot unset _run_juju_with_proot } @@ -157,6 +161,7 @@ function test_delete_juju(){ JUJU_ENV=1 bash -ic "delete_juju" &> /dev/null is_equal $? 1 || return 1 unset delete_juju + unset delete_juju } diff --git a/tests/test_juju.sh b/tests/test_juju.sh index 8d9a94a..38806f7 100755 --- a/tests/test_juju.sh +++ b/tests/test_juju.sh @@ -110,6 +110,7 @@ function test_check_cli(){ export -f parse_arguments export -f execute_operation export -f wrap_juju + export -f die bash -ic "wrap_juju -b -h" &> /dev/null is_equal $? 1 || return 1 bash -ic "wrap_juju -d -r" &> /dev/null @@ -124,6 +125,12 @@ function test_check_cli(){ is_equal $? 1 || return 1 bash -ic "wrap_juju -d args" &> /dev/null is_equal $? 1 || return 1 + export -n check_cli + export -n parse_arguments + export -n execute_operation + export -n wrap_juju + export -n die + unset die } for func in $(declare -F | grep test_ | awk '{print $3}' | xargs) diff --git a/tests/test_util.sh b/tests/test_util.sh index 757f08f..e7cfc1b 100755 --- a/tests/test_util.sh +++ b/tests/test_util.sh @@ -33,8 +33,11 @@ function test_die(){ local actual=$(die "Test" 2>&1) local expected=$(echo -e "\033[1;31mTest\033[0m") is_equal "$actual" "$expected" || return 1 + export -f die bash -ic "die Dying" &> /dev/null is_equal $? 1 || return 1 + export -n die + unset die return 0 } From ab74adb59d0bc2d76a2947c7156b4c40b927e07b Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Fri, 28 Nov 2014 00:03:19 +0100 Subject: [PATCH 14/17] Fix issue #25 --- tests/test_core.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_core.sh b/tests/test_core.sh index fac8dbc..d90e816 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -55,10 +55,13 @@ function test_setup_juju(){ [ -e $JUJU_HOME/run/lock ] || return 1 export -f setup_juju + export -f die JUJU_ENV=1 bash -ic "setup_juju" &> /dev/null is_equal $? 1 || return 1 export -n setup_juju unset setup_juju + export -n die + unset die } @@ -70,6 +73,7 @@ function test_setup_from_file_juju(){ [ -e $JUJU_HOME/run/lock ] || return 1 export -f setup_from_file_juju + export -f die bash -ic "setup_from_file_juju noexist.tar.gz" &> /dev/null is_equal $? 1 || return 1 @@ -77,6 +81,8 @@ function test_setup_from_file_juju(){ is_equal $? 1 || return 1 export -n setup_from_file_juju unset setup_from_file_juju + export -n die + unset die } @@ -158,10 +164,13 @@ function test_delete_juju(){ is_equal $? 1 || return 1 export -f delete_juju + export -f die JUJU_ENV=1 bash -ic "delete_juju" &> /dev/null is_equal $? 1 || return 1 + export -n delete_juju unset delete_juju - unset delete_juju + export -n die + unset die } From e96431a346f05fa83fba17ea3fda29e0ff62b9a5 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Fri, 28 Nov 2014 16:05:18 +0100 Subject: [PATCH 15/17] Fix #25 tests for old bash version --- tests/test_core.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_core.sh b/tests/test_core.sh index d90e816..fba5f0d 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -99,10 +99,13 @@ function test_run_juju_as_root(){ [ -e $JUJU_HOME/${HOME} ] || return 1 export -f run_juju_as_root + export -f die JUJU_ENV=1 bash -ic "run_juju_as_root" &> /dev/null is_equal $? 1 || return 1 export -n run_juju_as_root unset run_juju_as_root + export -n die + unset die } function test_run_juju_as_user(){ @@ -132,19 +135,24 @@ function test_run_juju_as_user_proot_args(){ is_equal $? 0 || return 1 export -f _run_juju_with_proot + export PROOT + export TRUE ID="/usr/bin/echo 0" bash -ic "_run_juju_with_proot" &> /dev/null is_equal $? 1 || return 1 export -n _run_juju_with_proot unset _run_juju_with_proot + export -n PROOT + export -n TRUE } function test_run_juju_as_user_seccomp(){ install_mini_juju - local output=$(run_juju_as_user "" "env" | grep "PROOT_NO_SECCOMP") + PROOT="" + local output=$(_run_juju_with_proot "" "env" | grep "PROOT_NO_SECCOMP") is_equal $output "" || return 1 TRUE="/usr/bin/false" - local output=$(run_juju_as_user "" "env" | grep "PROOT_NO_SECCOMP") + local output=$(_run_juju_with_proot "" "env" | grep "PROOT_NO_SECCOMP") is_equal $output "PROOT_NO_SECCOMP=1" || return 1 } From 5fadb34f94b4f35e9c88c0785c6c15393f63bcf8 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Sat, 29 Nov 2014 16:35:39 +0100 Subject: [PATCH 16/17] Fix issue #5 --- lib/core.sh | 11 ++--------- tests/test_core.sh | 36 ++++-------------------------------- 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/lib/core.sh b/lib/core.sh index e72219c..11a1f69 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -70,8 +70,7 @@ then SH="/bin/sh --login" elif [ "$JUJU_ENV" == "1" ] then - PROOT="$LD_LIB" - SH="/bin/sh" + die "Error: Nested JuJu environments are not allowed" else die "The variable JUJU_ENV is not properly set" fi @@ -115,7 +114,6 @@ function _setup_juju(){ 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 @@ -134,7 +132,6 @@ function setup_juju(){ 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" @@ -162,10 +159,8 @@ function _define_proot_args(){ function run_juju_as_root(){ - [ "$JUJU_ENV" == "1" ] && die "Error: The operation is not allowed inside JuJu environment" - mkdir -p ${JUJU_HOME}/${HOME} - ${CHROOT} $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && $(_define_chroot_args "$@")" + JUJU_ENV=1 ${CHROOT} $JUJU_HOME /usr/bin/bash -c "mkdir -p /run/lock && $(_define_chroot_args "$@")" } @@ -196,8 +191,6 @@ function run_juju_as_user(){ 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 diff --git a/tests/test_core.sh b/tests/test_core.sh index fba5f0d..1a4be0c 100755 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -53,15 +53,6 @@ function test_setup_juju(){ setup_juju 1> /dev/null [ -e $JUJU_HOME/file ] || return 1 [ -e $JUJU_HOME/run/lock ] || return 1 - - export -f setup_juju - export -f die - JUJU_ENV=1 bash -ic "setup_juju" &> /dev/null - is_equal $? 1 || return 1 - export -n setup_juju - unset setup_juju - export -n die - unset die } @@ -76,13 +67,6 @@ function test_setup_from_file_juju(){ export -f die bash -ic "setup_from_file_juju noexist.tar.gz" &> /dev/null is_equal $? 1 || return 1 - - JUJU_ENV=1 bash -ic "setup_from_file_juju" &> /dev/null - is_equal $? 1 || return 1 - export -n setup_from_file_juju - unset setup_from_file_juju - export -n die - unset die } @@ -97,15 +81,6 @@ function test_run_juju_as_root(){ run_juju_as_root "[ -e /run/lock ]" is_equal $? 0 || return 1 [ -e $JUJU_HOME/${HOME} ] || return 1 - - export -f run_juju_as_root - export -f die - JUJU_ENV=1 bash -ic "run_juju_as_root" &> /dev/null - is_equal $? 1 || return 1 - export -n run_juju_as_root - unset run_juju_as_root - export -n die - unset die } function test_run_juju_as_user(){ @@ -170,15 +145,12 @@ function test_delete_juju(){ echo "Y" | delete_juju 1> /dev/null is_juju_installed is_equal $? 1 || return 1 +} - export -f delete_juju - export -f die - JUJU_ENV=1 bash -ic "delete_juju" &> /dev/null +function test_nested_juju(){ + install_mini_juju + JUJU_ENV=1 bash -ic "source $CURRPWD/$(dirname $0)/../lib/core.sh" &> /dev/null is_equal $? 1 || return 1 - export -n delete_juju - unset delete_juju - export -n die - unset die } From b2dacdc3531fdf450e54afa2c9776722d6c97399 Mon Sep 17 00:00:00 2001 From: Filippo Squillace Date: Sun, 30 Nov 2014 16:52:53 +0100 Subject: [PATCH 17/17] Update the version to 2.5.6 (Lion) --- bin/juju | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/bin/juju b/bin/juju index c00da88..83eef6a 100755 --- a/bin/juju +++ b/bin/juju @@ -18,8 +18,14 @@ # along with this program. If not, see . # -NAME='juju' -VERSION='1.0' +NAME='JuJu' +CMD='juju' +VERSION='2.5.6' +CODE_NAME='Lion' +DESCRIPTION='The GNU/Linux distribution container for non-root users' +AUTHOR='Filippo Squillace ' +HOMEPAGE='https://github.com/fsquillace/juju' +COPYRIGHT='2012-2014' source "$(dirname $0)/../lib/core.sh" @@ -28,23 +34,23 @@ source "$(dirname $0)/../lib/core.sh" ################################### usage() { - echo -e "JuJu: The portable GNU/Linux distribution" - echo -e "Usage: $NAME [options] [command]" + echo -e "$NAME: $DESCRIPTION" + echo -e "Usage: $CMD [options] [command]" echo -e "Options:" - echo -e "-i, --setup-from-file 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 "-i, --setup-from-file Setup the $NAME image in ${JUJU_HOME}" + echo -e "-f, --fakeroot Run $NAME with fakeroot privileges" + echo -e "-r, --root Run $NAME with root privileges" echo -e "-p, --proot-args Proot arguments" - echo -e "-b, --build-image Build a JuJu image (must run in ArchLinux)" - echo -e "-d, --delete Delete JuJu from ${JUJU_HOME}" + echo -e "-b, --build-image Build a $NAME image (must run in ArchLinux)" + echo -e "-d, --delete Delete $NAME 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 " - echo -e "Homepage: http://github.com/fsquillace/juju" + echo -e "$NAME $VERSION ($CODE_NAME): $DESCRIPTION" + echo -e "Copyright (c) $COPYRIGHT $AUTHOR" + echo -e "Homepage: $HOMEPAGE" } check_cli(){ @@ -61,7 +67,7 @@ check_cli(){ 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" + die "The $NAME delete option must be used exclusively" fi fi if $OPT_HELP @@ -69,7 +75,7 @@ check_cli(){ 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" + die "The $NAME help option must be used exclusively" fi fi if $OPT_VERSION @@ -77,12 +83,12 @@ check_cli(){ 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" + die "The $NAME 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" + die "You must access to $NAME with either fakeroot or root permissions" fi if $OPT_PROOT_ARGS then @@ -97,7 +103,7 @@ check_cli(){ if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || $OPT_SETUP_FROM_FILE || \ $OPT_VERSION then - die "No arguments are needed. For the CLI syntax run: $NAME --help" + die "No arguments are needed. For the CLI syntax run: $CMD --help" fi fi @@ -106,7 +112,7 @@ check_cli(){ function parse_arguments(){ - TEMP=$(getopt -o drp:fbi:hv --long delete,root,proot-args:,fakeroot,build-image,setup-from-file:,help,version -n 'juju' -- "$@") + TEMP=$(getopt -o drp:fbi:hv --long delete,root,proot-args:,fakeroot,build-image,setup-from-file:,help,version -n "$CMD" -- "$@") eval set -- "$TEMP" OPT_SETUP_FROM_FILE=false