mirror of
https://github.com/YunoHost/ynh-dev.git
synced 2024-09-03 20:05:59 +02:00
470 lines
18 KiB
Bash
Executable file
470 lines
18 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
|
||
function show_usage() {
|
||
cat <<EOF
|
||
|
||
${BLUE}On the host, to manage the LXC${NORMAL}
|
||
${BLUE}==============================${NORMAL}
|
||
|
||
start [DIST] [NAME] [YNH_BRANCH] (Create and) starts a LXC (DIST=buster, NAME=ynh-dev and YNH_BRANCH=unstable by default)
|
||
attach [DIST] [NAME] [YNH_BRANCH] Attach an already started LXC (DIST=buster, NAME=ynh-dev and YNH_BRANCH=unstable by default)
|
||
destroy [DIST] [NAME] [YNH_BRANCH] Destroy the ynh-dev LXC (DIST=buster, NAME=ynh-dev and YNH_BRANCH=unstable by default)
|
||
rebuild [DIST] [NAME] [YNH_BRANCH] Rebuild a fresh, up-to-date box (DIST=buster, NAME=ynh-dev and YNH_BRANCH=unstable by default)
|
||
|
||
${BLUE}Inside the dev instance${NORMAL}
|
||
${BLUE}=======================${NORMAL}
|
||
|
||
ip Give the ip of the guest container
|
||
use-git [PKG] Use Git repositories from dev environment path
|
||
test [PKG] Deploy, update and run tests for some packages
|
||
Tests for single modules and functions can ran with
|
||
e.g. ./ynh-dev test yunohost/appurl:urlavailable
|
||
|
||
EOF
|
||
}
|
||
|
||
function main()
|
||
{
|
||
local ACTION="$1"
|
||
local ARGUMENTS="${@:2}"
|
||
|
||
[ -z "$ACTION" ] && show_usage && exit 0
|
||
|
||
case "${ACTION}" in
|
||
|
||
help|-h|--help) show_usage $ARGUMENTS ;;
|
||
|
||
start|--start) start_ynhdev $ARGUMENTS ;;
|
||
attach|--attach) attach_ynhdev $ARGUMENTS ;;
|
||
destroy|--destroy) destroy_ynhdev $ARGUMENTS ;;
|
||
rebuild|--rebuild) rebuild_ynhdev $ARGUMENTS ;;
|
||
|
||
ip|--ip) show_vm_ip $ARGUMENTS ;;
|
||
use-git|--use-git) use_git $ARGUMENTS ;;
|
||
test|--test) run_tests $ARGUMENTS ;;
|
||
|
||
*) critical "Unknown action ${ACTION}." ;;
|
||
esac
|
||
}
|
||
|
||
##################################################################
|
||
# Misc helpers #
|
||
##################################################################
|
||
|
||
readonly NORMAL=$(printf '\033[0m')
|
||
readonly BOLD=$(printf '\033[1m')
|
||
readonly faint=$(printf '\033[2m')
|
||
readonly UNDERLINE=$(printf '\033[4m')
|
||
readonly NEGATIVE=$(printf '\033[7m')
|
||
readonly RED=$(printf '\033[31m')
|
||
readonly GREEN=$(printf '\033[32m')
|
||
readonly ORANGE=$(printf '\033[33m')
|
||
readonly BLUE=$(printf '\033[34m')
|
||
readonly YELLOW=$(printf '\033[93m')
|
||
readonly WHITE=$(printf '\033[39m')
|
||
|
||
function success()
|
||
{
|
||
local msg=${1}
|
||
echo "[${BOLD}${GREEN} OK ${NORMAL}] ${msg}"
|
||
}
|
||
|
||
function info()
|
||
{
|
||
local msg=${1}
|
||
echo "[${BOLD}${BLUE}INFO${NORMAL}] ${msg}"
|
||
}
|
||
|
||
function warn()
|
||
{
|
||
local msg=${1}
|
||
echo "[${BOLD}${ORANGE}WARN${NORMAL}] ${msg}" 2>&1
|
||
}
|
||
|
||
function error()
|
||
{
|
||
local msg=${1}
|
||
echo "[${BOLD}${RED}FAIL${NORMAL}] ${msg}" 2>&1
|
||
}
|
||
|
||
function critical()
|
||
{
|
||
local msg=${1}
|
||
echo "[${BOLD}${RED}CRIT${NORMAL}] ${msg}" 2>&1
|
||
exit 1
|
||
}
|
||
|
||
function assert_inside_vm() {
|
||
[ -d /etc/yunohost ] || critical "There's no YunoHost in there. Are you sure that you are inside the container ?"
|
||
}
|
||
|
||
function create_sym_link() {
|
||
local DEST=$1
|
||
local LINK=$2
|
||
# Remove current sources if not a symlink
|
||
[ -L "$LINK" ] || rm -rf $LINK
|
||
# Symlink from Git repository
|
||
ln -sfn $DEST $LINK
|
||
}
|
||
|
||
##################################################################
|
||
# Actions #
|
||
##################################################################
|
||
|
||
function check_lxd_setup()
|
||
{
|
||
# Check lxd is installed somehow
|
||
[[ -e /snap/bin/lxd ]] || which lxd &>/dev/null \
|
||
|| critical "You need to have LXD installed for ynh-dev to be usable from the host machine. Refer to the README to know how to install it."
|
||
|
||
# Check that we'll be able to use lxc/lxd using sudo (for which the PATH is defined in /etc/sudoers and probably doesn't include /snap/bin)
|
||
if [[ ! -e /usr/bin/lxc ]] && [[ ! -e /usr/bin/lxd ]] && [[ -e /snap ]]
|
||
then
|
||
[[ -e /usr/local/bin/lxc ]] && [[ -e /usr/local/bin/lxd ]] \
|
||
|| critical "You might want to add lxc and lxd inside /usr/local/bin so that there's no tricky PATH issue with sudo. If you installed lxd/lxc with snapd, this should do the trick: sudo ln -s /snap/bin/lxc /usr/local/bin/lxc && sudo ln -s /snap/bin/lxd /usr/local/bin/lxd"
|
||
fi
|
||
|
||
ip a | grep -q lx[cd]br0 \
|
||
|| critical "There is no 'lxcbr0' or 'lxdbr0' interface... Did you ran 'lxd init' ?"
|
||
}
|
||
|
||
function start_ynhdev()
|
||
{
|
||
check_lxd_setup
|
||
|
||
local DIST=${1:-buster}
|
||
local YNH_BRANCH=${3:-unstable}
|
||
local BOX=${2:-ynh-dev}-${DIST}-${YNH_BRANCH}
|
||
|
||
if ! sudo lxc info $BOX &>/dev/null
|
||
then
|
||
if ! sudo lxc image info $BOX-base &>/dev/null
|
||
then
|
||
LXC_BASE="ynh-dev-$DIST-amd64-$YNH_BRANCH-base"
|
||
sudo lxc launch yunohost:$LXC_BASE $BOX -c security.nesting=true -c security.privileged=true \
|
||
|| critical "Failed to launch the container ?"
|
||
else
|
||
sudo lxc launch $BOX-base $BOX -c security.nesting=true -c security.privileged=true
|
||
fi
|
||
sudo lxc config device add $BOX ynhdev-shared-folder disk path=/ynh-dev source="$(readlink -f $(pwd))"
|
||
info "Now attaching to the container"
|
||
else
|
||
info "Attaching to existing container"
|
||
fi
|
||
|
||
attach_ynhdev "$@"
|
||
}
|
||
|
||
function attach_ynhdev()
|
||
{
|
||
check_lxd_setup
|
||
local DIST=${1:-buster}
|
||
local YNH_BRANCH=${3:-unstable}
|
||
local BOX=${2:-ynh-dev}-${DIST}-${YNH_BRANCH}
|
||
sudo lxc start $BOX 2>/dev/null || true
|
||
sudo lxc exec $BOX --cwd /ynh-dev -- /bin/bash
|
||
}
|
||
|
||
function destroy_ynhdev()
|
||
{
|
||
check_lxd_setup
|
||
local DIST=${1:-buster}
|
||
local YNH_BRANCH=${3:-unstable}
|
||
local BOX=${2:-ynh-dev}-${DIST}-${YNH_BRANCH}
|
||
sudo lxc stop $BOX
|
||
sudo lxc delete $BOX
|
||
}
|
||
|
||
function rebuild_ynhdev()
|
||
{
|
||
check_lxd_setup
|
||
|
||
local DIST=${1:-buster}
|
||
local YNH_BRANCH=${3:-unstable}
|
||
local BOX=${2:-ynh-dev}-${DIST}-${YNH_BRANCH}
|
||
|
||
set -x
|
||
sudo lxc info $BOX-rebuild >/dev/null && sudo lxc delete $BOX-rebuild --force
|
||
sudo lxc launch images:debian/$DIST/amd64 $BOX-rebuild -c security.nesting=true -c security.privileged=true
|
||
sleep 5
|
||
sudo lxc exec $BOX-rebuild -- apt install curl -y
|
||
INSTALL_SCRIPT="https://install.yunohost.org/$DIST"
|
||
sudo lxc exec $BOX-rebuild -- /bin/bash -c "curl $INSTALL_SCRIPT | bash -s -- -a -d $YNH_BRANCH"
|
||
sudo lxc stop $BOX-rebuild
|
||
sudo lxc publish $BOX-rebuild --alias $BOX-base
|
||
set +x
|
||
}
|
||
|
||
function show_vm_ip()
|
||
{
|
||
assert_inside_vm
|
||
hostname --all-ip-addresses | tr ' ' '\n'
|
||
}
|
||
|
||
function use_git()
|
||
{
|
||
assert_inside_vm
|
||
local PACKAGES=("$@")
|
||
|
||
if [ "$PACKAGES" = "" ]
|
||
then
|
||
PACKAGES=('moulinette' 'ssowat' 'yunohost' 'yunohost-admin')
|
||
fi
|
||
|
||
for i in "${!PACKAGES[@]}";
|
||
do
|
||
case ${PACKAGES[i]} in
|
||
ssowat)
|
||
create_sym_link "/ynh-dev/ssowat" "/usr/share/ssowat"
|
||
success "Now using Git repository for SSOwat"
|
||
;;
|
||
moulinette)
|
||
create_sym_link "/ynh-dev/moulinette/locales" "/usr/share/moulinette/locale"
|
||
create_sym_link "/ynh-dev/moulinette/moulinette" "/usr/lib/python3/dist-packages/moulinette"
|
||
success "Now using Git repository for Moulinette"
|
||
;;
|
||
yunohost)
|
||
|
||
for FILE in $(ls /ynh-dev/yunohost/bin/)
|
||
do
|
||
create_sym_link "/ynh-dev/yunohost/bin/$FILE" "/usr/bin/$FILE"
|
||
done
|
||
|
||
if [[ $(lsb_release -sc) == "bullseye" ]]
|
||
then
|
||
for FILE in $(ls /ynh-dev/yunohost/conf/metronome/modules/)
|
||
do
|
||
create_sym_link "/ynh-dev/yunohost/conf/metronome/modules/$FILE" "/usr/lib/metronome/modules/$FILE"
|
||
done
|
||
for FILE in $(ls /ynh-dev/yunohost/share/)
|
||
do
|
||
create_sym_link "/ynh-dev/yunohost/share/$FILE" "/usr/share/yunohost/$FILE"
|
||
done
|
||
create_sym_link "/ynh-dev/yunohost/hooks" "/usr/share/yunohost/hooks"
|
||
create_sym_link "/ynh-dev/yunohost/helpers" "/usr/share/yunohost/helpers.d"
|
||
create_sym_link "/ynh-dev/yunohost/conf" "/usr/share/yunohost/conf"
|
||
create_sym_link "/ynh-dev/yunohost/locales" "/usr/share/yunohost/locales"
|
||
create_sym_link "/ynh-dev/yunohost/src" "/usr/lib/python3/dist-packages/yunohost"
|
||
|
||
python3 "/ynh-dev/yunohost/doc/generate_bash_completion.py"
|
||
create_sym_link "/ynh-dev/yunohost/doc/bash-completion.sh" "/etc/bash_completion.d/yunohost"
|
||
else
|
||
# data
|
||
python3 "/ynh-dev/yunohost/data/actionsmap/yunohost_completion.py"
|
||
create_sym_link "/ynh-dev/yunohost/data/bash-completion.d/yunohost" "/etc/bash_completion.d/yunohost"
|
||
create_sym_link "/ynh-dev/yunohost/data/actionsmap/yunohost.yml" "/usr/share/moulinette/actionsmap/yunohost.yml"
|
||
create_sym_link "/ynh-dev/yunohost/data/hooks" "/usr/share/yunohost/hooks"
|
||
create_sym_link "/ynh-dev/yunohost/data/templates" "/usr/share/yunohost/templates"
|
||
create_sym_link "/ynh-dev/yunohost/data/helpers" "/usr/share/yunohost/helpers"
|
||
create_sym_link "/ynh-dev/yunohost/data/helpers.d" "/usr/share/yunohost/helpers.d"
|
||
create_sym_link "/ynh-dev/yunohost/data/other" "/usr/share/yunohost/yunohost-config/moulinette"
|
||
|
||
# lib
|
||
create_sym_link "/ynh-dev/yunohost/lib/metronome/modules/ldap.lib.lua" "/usr/lib/metronome/modules/ldap.lib.lua"
|
||
create_sym_link "/ynh-dev/yunohost/lib/metronome/modules/mod_auth_ldap2.lua" "/usr/lib/metronome/modules/mod_auth_ldap2.lua"
|
||
create_sym_link "/ynh-dev/yunohost/lib/metronome/modules/mod_legacyauth.lua" "/usr/lib/metronome/modules/mod_legacyauth.lua"
|
||
create_sym_link "/ynh-dev/yunohost/lib/metronome/modules/mod_storage_ldap.lua" "/usr/lib/metronome/modules/mod_storage_ldap.lua"
|
||
create_sym_link "/ynh-dev/yunohost/lib/metronome/modules/vcard.lib.lua" "/usr/lib/metronome/modules/vcard.lib.lua"
|
||
|
||
# src
|
||
create_sym_link "/ynh-dev/yunohost/src/yunohost" "/usr/lib/moulinette/yunohost"
|
||
|
||
# locales
|
||
create_sym_link "/ynh-dev/yunohost/locales" "/usr/lib/moulinette/yunohost/locales"
|
||
fi
|
||
|
||
success "Now using Git repository for YunoHost"
|
||
|
||
;;
|
||
yunohost-admin)
|
||
|
||
#rm -r /var/cache/ynh-dev/yunohost-admin
|
||
mkdir -p /var/cache/ynh-dev/yunohost-admin/
|
||
create_sym_link "/ynh-dev/yunohost-admin/app/.env" "/var/cache/ynh-dev/yunohost-admin/.env"
|
||
create_sym_link "/var/cache/ynh-dev/yunohost-admin/node_modules" "/ynh-dev/yunohost-admin/app/node_modules"
|
||
create_sym_link "/ynh-dev/yunohost-admin/app/package.json" "/var/cache/ynh-dev/yunohost-admin/package.json"
|
||
create_sym_link "/ynh-dev/yunohost-admin/app/package-lock.json" "/var/cache/ynh-dev/yunohost-admin/package-lock.json"
|
||
mv "/etc/nginx/conf.d/yunohost_admin.conf.inc" "/etc/nginx/conf.d/yunohost_admin.conf.inc.bkp"
|
||
trap 'on_exit' exit
|
||
on_exit()
|
||
{
|
||
mv "/etc/nginx/conf.d/yunohost_admin.conf.inc.bkp" "/etc/nginx/conf.d/yunohost_admin.conf.inc"
|
||
systemctl reload nginx
|
||
}
|
||
|
||
cd /var/cache/ynh-dev/yunohost-admin/
|
||
|
||
# Create .env file with the vm ip
|
||
# Will be used by webpack-dev-server to proxy api requests.
|
||
IP=$(hostname -I | tr ' ' '\n' | grep "\.")
|
||
echo "VUE_APP_IP=$IP" > .env
|
||
|
||
# Allow port 8080 in config file or else the dev server will stop working after postinstall
|
||
if [[ ! -e /etc/yunohost/installed ]]
|
||
then
|
||
python3 - <<EOF
|
||
import os, yaml
|
||
setting_file = "/etc/yunohost/firewall.yml"
|
||
assert os.path.exists(setting_file), "Firewall yaml file %s does not exists ?" % setting_file
|
||
with open(setting_file) as f:
|
||
settings = yaml.load(f)
|
||
if 8080 not in settings["ipv4"]["TCP"]:
|
||
settings["ipv4"]["TCP"].append(8080)
|
||
with open(setting_file, "w") as f:
|
||
yaml.safe_dump(settings, f, default_flow_style=False)
|
||
EOF
|
||
fi
|
||
|
||
# Install npm if needed
|
||
if [[ ! -e "/var/cache/ynh-dev/yunohost-admin/node_modules/vue" ]]
|
||
then
|
||
info "Installing dependencies to develop in yunohost-admin ..."
|
||
DISTRO="$(lsb_release -s -c)"
|
||
if [ "$DISTRO" == "buster" ]; then
|
||
KEYRING=/usr/share/keyrings/nodesource.gpg
|
||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor | sudo tee "$KEYRING" >/dev/null
|
||
gpg --no-default-keyring --keyring "$KEYRING" --list-keys
|
||
VERSION=node_8.x
|
||
KEYRING=/usr/share/keyrings/nodesource.gpg
|
||
echo "deb [signed-by=$KEYRING] https://deb.nodesource.com/$VERSION $DISTRO main" | sudo tee /etc/apt/sources.list.d/nodesource.list
|
||
fi
|
||
apt-get update
|
||
apt install nodejs npm -y
|
||
npm install -g npm@6
|
||
fi
|
||
|
||
# Install dependencies with npm install (or rather npm ci)
|
||
if [[ -e "/var/cache/ynh-dev/yunohost-admin/node_modules/vue" ]];
|
||
then
|
||
info "NB: skipping npm ci because vue is already installed. If you want to upgrade/refresh npm dependencies, you should run 'npm ci' manually, or delete /var/cache/ynh-dev/yunohot-admin/node_modules."
|
||
else
|
||
info "Installing npm dependencies ... (this may take a while)"
|
||
npm ci --no-bin-links
|
||
fi
|
||
|
||
info "Tweaking nginx and ssowat for yunohost admin dev..."
|
||
|
||
cat <<EOF > /etc/nginx/conf.d/yunohost_admin.conf.inc
|
||
location /yunohost/admin {
|
||
proxy_pass http://localhost:8080/yunohost/admin;
|
||
proxy_redirect off;
|
||
proxy_set_header Host \$host;
|
||
proxy_set_header X-Real-IP \$remote_addr;
|
||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Host \$server_name;
|
||
proxy_set_header X-Forwarded-Port \$server_port;
|
||
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade \$http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
}
|
||
location /sockjs-node {
|
||
proxy_pass http://localhost:8080/sockjs-node;
|
||
proxy_redirect off;
|
||
proxy_set_header Host \$host;
|
||
proxy_set_header X-Real-IP \$remote_addr;
|
||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Host \$server_name;
|
||
proxy_set_header X-Forwarded-Port \$server_port;
|
||
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade \$http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
}
|
||
EOF
|
||
|
||
|
||
# If ssowat's conf persistent ~empty, allow ourselves to add the rule for /sockjs-node for hot-reload
|
||
if [ ! -e /etc/ssowat/conf.json.persistent ] || [ -z "$(cat /etc/ssowat/conf.json.persistent | tr -d '{} \n')" ]
|
||
then
|
||
cat <<EOF >/etc/ssowat/conf.json.persistent
|
||
{
|
||
"permissions": {
|
||
"webadminhotreload": {
|
||
"auth_header": false,
|
||
"label": "Core permissions - skipped",
|
||
"public": true,
|
||
"show_tile": false,
|
||
"uris": [
|
||
"re:^[^/]*/sockjs-node",
|
||
],
|
||
"users": []
|
||
}
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
systemctl reload nginx
|
||
cd /ynh-dev/yunohost-admin/app/
|
||
info "Now running 'npm run serve'"
|
||
npm run serve
|
||
;;
|
||
*)
|
||
error "Invalid package '${PACKAGES[i]}': correct arguments are 'yunohost', 'ssowat', 'moulinette', 'yunohost-admin' or nothing for all"
|
||
;;
|
||
*)
|
||
error "Invalid package '${PACKAGES[i]}': correct arguments are 'yunohost', 'ssowat', 'moulinette', 'yunohost-admin' or nothing for all"
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
function run_tests()
|
||
{
|
||
assert_inside_vm
|
||
local PACKAGES="$@"
|
||
for PACKAGE in $PACKAGES;
|
||
do
|
||
TEST_FUNCTION=$(echo "$PACKAGE" | tr '/:' ' ' | awk '{print $3}')
|
||
TEST_MODULE=$(echo "$PACKAGE" | tr '/:' ' ' | awk '{print $2}')
|
||
PACKAGE=$(echo "$PACKAGE" | tr '/:' ' ' | awk '{print $1}')
|
||
|
||
case $PACKAGE in
|
||
yunohost)
|
||
# Pytest and tests dependencies
|
||
if ! type "pytest" > /dev/null 2>&1; then
|
||
info "> Installing pytest ..."
|
||
apt-get install python3-pip -y
|
||
pip3 install pytest pytest-sugar
|
||
fi
|
||
for DEP in "pytest-mock requests-mock mock"
|
||
do
|
||
if [ -z "$(pip3 show $DEP)" ]; then
|
||
info "Installing $DEP with pip3"
|
||
pip3 install $DEP
|
||
fi
|
||
done
|
||
|
||
# Apps for test
|
||
cd /ynh-dev/yunohost/src/yunohost/tests
|
||
[ -d "apps" ] || git clone https://github.com/YunoHost/test_apps ./apps
|
||
cd apps
|
||
git pull > /dev/null 2>&1
|
||
|
||
# Run tests
|
||
info "Running tests for YunoHost"
|
||
[ -e "/etc/yunohost/installed" ] || critical "You should run postinstallation before running tests :s."
|
||
if [[ -z "$TEST_MODULE" ]]
|
||
then
|
||
cd /ynh-dev/yunohost/
|
||
py.test tests
|
||
cd /ynh-dev/yunohost/src/yunohost
|
||
py.test tests
|
||
else
|
||
cd /ynh-dev/yunohost/src/yunohost
|
||
if [[ -z "$TEST_FUNCTION" ]]
|
||
then
|
||
py.test tests/test_"$TEST_MODULE".py
|
||
else
|
||
py.test tests/test_"$TEST_MODULE".py::test_"$TEST_FUNCTION"
|
||
fi
|
||
fi
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
main $@
|