ynh-dev/ynh-dev

470 lines
18 KiB
Bash
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 $@