5 changed files with 402 additions and 0 deletions
-
214recipes/odoo/crud.sh
-
124recipes/odoo/install.sh
-
33templates/apps/odoo/odoo-addon-install
-
17templates/apps/odoo/odoo.conf.j2
-
14templates/apps/odoo/odoo.service.j2
@ -0,0 +1,214 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
function check_database_exists() { |
||||
|
db-psql list | grep -q "$longname" |
||||
|
} |
||||
|
|
||||
|
function check_port_used() { |
||||
|
# shellcheck disable=SC2034 |
||||
|
usedport=$(lxc exec "$container" -- bash -c "grep xmlrpc_port /etc/odoo/$shortname.conf | cut -d' ' -f3") |
||||
|
[[ "$usedport" == "$port" ]] |
||||
|
} |
||||
|
|
||||
|
function check_service_running() { |
||||
|
lxc exec "$container" -- bash -c "systemctl is-active --quiet ${longname}.service" |
||||
|
} |
||||
|
|
||||
|
function _read() { |
||||
|
disable_trace |
||||
|
check_database_exists |
||||
|
check_container "$container" |
||||
|
check_port_used |
||||
|
check_service_running |
||||
|
enable_trace |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
function _create() { |
||||
|
|
||||
|
echo "creating templates ... " |
||||
|
mkdir -p "$MIAOU_CONFIGDIR/apps/odoo" |
||||
|
|
||||
|
longport=$((port + 1000)) |
||||
|
APP_PORT=$port LONG_PORT=$longport APP_NAME=$shortname tera -e -t "$MIAOU_BASEDIR/templates/apps/odoo/odoo.conf.j2" -o "$MIAOU_CONFIGDIR/apps/odoo/$shortname.conf" "$MIAOU_CONFIGDIR/miaou.expanded.yaml" >/dev/null |
||||
|
APP_NAME=$shortname tera -t "$MIAOU_BASEDIR/templates/apps/odoo/odoo.service.j2" --env-only -o "$MIAOU_CONFIGDIR/apps/odoo/$longname.service" >/dev/null |
||||
|
echo "creating templates ... OK" |
||||
|
|
||||
|
echo "copying files to container <$container> ... " |
||||
|
lxc file push --uid 0 --gid 0 "$MIAOU_CONFIGDIR/apps/odoo/$shortname.conf" "$container/etc/odoo/$shortname.conf" |
||||
|
lxc file push --uid 0 --gid 0 "$MIAOU_CONFIGDIR/apps/odoo/$longname.service" "$container/etc/systemd/system/$longname.service" |
||||
|
echo "copying files to container <$container> ... OK" |
||||
|
|
||||
|
echo "create data folder for $shortname" |
||||
|
cat <<EOF | lxc_exec "$container" |
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
echo allow addons writable for user odoo |
||||
|
mkdir -p /home/odoo/data-$shortname/addons/18.0 |
||||
|
chmod u+w /home/odoo/data-$shortname/addons/18.0 |
||||
|
chown -R odoo:odoo /home/odoo/data-$shortname |
||||
|
EOF |
||||
|
|
||||
|
if ! (db-psql list | grep -q "$longname"); then |
||||
|
echo "create empty database <$longname> ... " |
||||
|
db-psql create "$longname" |
||||
|
echo "create empty database <$longname> ... OK" |
||||
|
|
||||
|
admin_username=$(echo -e "$data" | yq '.admin.username') |
||||
|
[[ $admin_username = 'null' ]] && echoerr "odoo recipe requires \`data:admin:username\` into miaou.yaml service definition of <$fqdn>" && exit 1 |
||||
|
|
||||
|
admin_password=$(echo -e "$data" | yq '.admin.password') |
||||
|
[[ $admin_password = 'null' ]] && echoerr "odoo recipe requires \`data:admin:password\` into miaou.yaml service definition of <$fqdn>" && exit 1 |
||||
|
|
||||
|
cat <<EOF | lxc_exec "$container" |
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
echo reloading systemd |
||||
|
systemctl daemon-reload |
||||
|
systemctl stop $longname |
||||
|
|
||||
|
echo initialize database... |
||||
|
su odoo -c "python3.10 /home/odoo/odoo/odoo-bin -c /etc/odoo/$shortname.conf -i base --without-demo=all --stop-after-init" |
||||
|
echo initialize database OK |
||||
|
|
||||
|
echo install default modules ... |
||||
|
su odoo -c "python3.10 /home/odoo/odoo/odoo-bin -c /etc/odoo/$shortname.conf -i account,contacts,l10n_fr,account,sale,point_of_sale -d $longname --worker=0 --stop-after-init" |
||||
|
echo default modules OK |
||||
|
|
||||
|
echo activate french language |
||||
|
su odoo -c "python3.10 /home/odoo/odoo/odoo-bin -c /etc/odoo/$shortname.conf --load-language fr_FR -d $longname --worker=0 --stop-after-init" |
||||
|
|
||||
|
echo change administrator password, default credential applied! |
||||
|
echo "UPDATE res_users SET login='$admin_username', password='$admin_password' WHERE id=2" | PGPASSWORD=$longname psql -U $longname -h ct1.lxd |
||||
|
|
||||
|
EOF |
||||
|
else |
||||
|
echo "database already exists!" |
||||
|
fi |
||||
|
|
||||
|
echo "initialize odoo $shortname $longname ..." |
||||
|
cat <<EOF | lxc_exec "$container" |
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
echo reloading systemd |
||||
|
systemctl daemon-reload |
||||
|
|
||||
|
if ! systemctl is-active --quiet $longname; then |
||||
|
echo start service $longname |
||||
|
systemctl enable $longname |
||||
|
systemctl start $longname |
||||
|
systemctl is-active --quiet $longname |
||||
|
else |
||||
|
echo service $longname already started! |
||||
|
fi |
||||
|
|
||||
|
EOF |
||||
|
echo "initialize odoo $shortname $longname ... OK" |
||||
|
} |
||||
|
|
||||
|
function _update() { |
||||
|
echo "update" |
||||
|
} |
||||
|
|
||||
|
function _delete() { |
||||
|
echo "delete" |
||||
|
} |
||||
|
|
||||
|
function usage() { |
||||
|
echo "Usage: $COMMAND_NAME -c|r|u|d --port $port --fqdn $fqdn --container $container --name $name --data $data" |
||||
|
exit 2 |
||||
|
} |
||||
|
|
||||
|
### MAIN |
||||
|
|
||||
|
# init_strict |
||||
|
|
||||
|
COMMAND_NAME=$(basename "$0") |
||||
|
|
||||
|
# read the options |
||||
|
|
||||
|
TEMP=$(getopt -n "$COMMAND_NAME" -o crud --long port:,container:,name:,fqdn:,domain:,subdomain:,data: -- "$@") |
||||
|
# shellcheck disable=SC2181 |
||||
|
[[ "$?" -eq 0 ]] || usage |
||||
|
eval set -- "$TEMP" |
||||
|
|
||||
|
action="unset" |
||||
|
port="unset" |
||||
|
fqdn="unset" |
||||
|
container="unset" |
||||
|
shortname="unset" |
||||
|
longname="unset" |
||||
|
data="unset" |
||||
|
|
||||
|
# extract options and their arguments into variables. |
||||
|
while true; do |
||||
|
case "$1" in |
||||
|
--port) |
||||
|
port=$2 |
||||
|
shift 2 |
||||
|
;; |
||||
|
--fqdn) |
||||
|
fqdn=$2 |
||||
|
shift 2 |
||||
|
;; |
||||
|
--container) |
||||
|
container=$2 |
||||
|
shift 2 |
||||
|
;; |
||||
|
--name) |
||||
|
shortname=$2 |
||||
|
longname="odoo-$shortname" |
||||
|
shift 2 |
||||
|
;; |
||||
|
--data) |
||||
|
data=$2 |
||||
|
shift 2 |
||||
|
;; |
||||
|
--domain) |
||||
|
shift 2 |
||||
|
;; |
||||
|
--subdomain) |
||||
|
shift 2 |
||||
|
;; |
||||
|
-c) |
||||
|
[[ "$action" == "unset" ]] || usage |
||||
|
action="_create" |
||||
|
shift 1 |
||||
|
;; |
||||
|
-r) |
||||
|
[[ "$action" == "unset" ]] || usage |
||||
|
action="_read" |
||||
|
shift 1 |
||||
|
;; |
||||
|
-u) |
||||
|
[[ "$action" == "unset" ]] || usage |
||||
|
action="_update" |
||||
|
shift 1 |
||||
|
;; |
||||
|
-d) |
||||
|
[[ "$action" == "unset" ]] || usage |
||||
|
action="_delete" |
||||
|
shift 1 |
||||
|
;; |
||||
|
--) |
||||
|
shift |
||||
|
break |
||||
|
;; |
||||
|
*) |
||||
|
echoerr "Internal error: unrecognized option: <$1>" |
||||
|
exit 1 |
||||
|
;; |
||||
|
esac |
||||
|
done |
||||
|
|
||||
|
[[ |
||||
|
"$action" != unset && |
||||
|
"$port" != unset && |
||||
|
"$fqdn" != unset && |
||||
|
"$container" != unset && |
||||
|
"$shortname" != unset && |
||||
|
"$data" != unset ]] || usage |
||||
|
|
||||
|
. "$MIAOU_BASEDIR/lib/init.sh" |
||||
|
|
||||
|
$action |
@ -0,0 +1,124 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
readonly EXPANDED_CONF="$MIAOU_CONFIGDIR/miaou.expanded.yaml" |
||||
|
readonly ODOO_DIR="/home/odoo/odoo" |
||||
|
|
||||
|
readonly WKHTML_VERSION="0.12.6.1-3" |
||||
|
readonly WKHTML_RELEASE="$WKHTML_VERSION.bookworm_amd64" |
||||
|
|
||||
|
function check_user_odoo() { |
||||
|
(lxc exec "$CONTAINER" -- id odoo &>/dev/null) || return 12 |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
function check_target_bgcolor() { |
||||
|
(lxc exec "$CONTAINER" -- grep -Pq "^\\\$o-community-color: $BACKGROUND_COLOR" "$ODOO_DIR/addons/web/static/src/legacy/scss/primary_variables.scss") || return 13 |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
function check_file_odoo-addon-install() { |
||||
|
(lxc exec "$CONTAINER" -- test -f /home/odoo/odoo/odoo-addon-install) || return 23 |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
function check() { |
||||
|
PREFIX="recipe:odoo:check" |
||||
|
check_user_odoo || return 21 |
||||
|
check_target_bgcolor || return 22 |
||||
|
check_file_odoo-addon-install || return 23 |
||||
|
} |
||||
|
|
||||
|
function install() { |
||||
|
PREFIX="recipe:odoo:install" |
||||
|
: $PREFIX |
||||
|
launch_container "$CONTAINER" |
||||
|
echo "initializing Odoo ... " |
||||
|
|
||||
|
lxc exec "$CONTAINER" -- bash <<EOF |
||||
|
set -Eeuo pipefail |
||||
|
echo "installing odoo..." |
||||
|
apt update && apt dist-upgrade -y |
||||
|
|
||||
|
echo "required packages" |
||||
|
apt install -y postgresql-client build-essential zlib1g-dev libssl-dev libxml2-dev libxslt1-dev libldap2-dev libsasl2-dev libpq-dev libffi-dev |
||||
|
|
||||
|
if [[ ! -d /usr/local/share/python3.10 ]]; then |
||||
|
echo "install python-3.10.17" |
||||
|
cd /tmp |
||||
|
wget https://www.python.org/ftp/python/3.10.17/Python-3.10.17.tgz |
||||
|
tar -xf Python-3.10.17.tgz |
||||
|
mv Python-3.10.17 /usr/local/share/python3.10 |
||||
|
cd /usr/local/share/python3.10 |
||||
|
./configure --enable-optimizations --enable-shared |
||||
|
make -j \$(nproc) |
||||
|
make altinstall |
||||
|
ldconfig /usr/local/share/python3.10 |
||||
|
else |
||||
|
echo "python-3.10.17 already installed!" |
||||
|
fi |
||||
|
|
||||
|
if dpkg -l | grep -s wkhtmltox | grep -qs $WKHTML_VERSION; then |
||||
|
echo package=wkhtmltox version=$WKHTML_RELEASE already found! |
||||
|
else |
||||
|
echo "wkhtmltox version=$WKHTML_RELEASE has to be installed!" |
||||
|
wget https://github.com/wkhtmltopdf/packaging/releases/download/$WKHTML_VERSION/wkhtmltox_$WKHTML_RELEASE.deb |
||||
|
dpkg -i wkhtmltox_$WKHTML_RELEASE.deb || (apt -fy install && rm wkhtmltox_$WKHTML_RELEASE.deb) |
||||
|
fi |
||||
|
|
||||
|
if ! grep -q odoo /etc/passwd; then |
||||
|
echo "add user <odoo>" |
||||
|
useradd -ms /bin/bash odoo |
||||
|
else |
||||
|
echo "user <odoo> already set!" |
||||
|
fi |
||||
|
|
||||
|
echo "install odoo in odoo userspace" |
||||
|
cat <<EOT | su - odoo |
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
if [[ ! -d odoo ]]; then |
||||
|
echo "git odoo from remote" |
||||
|
git clone https://github.com/odoo/odoo.git --depth 1 --branch 18.0 odoo |
||||
|
export MAKEFLAGS="-j\$(nproc)" |
||||
|
pip3.10 install --upgrade pip |
||||
|
pip3.10 install wheel pypdf2 slugify |
||||
|
pip3.10 install -r odoo/requirements.txt |
||||
|
else |
||||
|
echo "git odoo already downloaded!" |
||||
|
fi |
||||
|
echo "community-color change to $BACKGROUND_COLOR" |
||||
|
/opt/miaou-bash/tools/append_or_replace "^.*o-community-color:.*" "\\\\\\\$o-community-color: $BACKGROUND_COLOR !default;" /home/odoo/odoo/addons/web/static/src/legacy/scss/primary_variables.scss |
||||
|
|
||||
|
EOT |
||||
|
mkdir -p /etc/odoo |
||||
|
EOF |
||||
|
lxc file push "$MIAOU_BASEDIR/templates/apps/odoo/odoo-addon-install" "$CONTAINER/home/odoo/odoo/odoo-addon-install" |
||||
|
lxc exec "$CONTAINER" -- bash <<EOF |
||||
|
chown odoo:odoo /home/odoo/odoo/odoo-addon-install |
||||
|
chmod 740 /home/odoo/odoo/odoo-addon-install |
||||
|
echo "new script <odoo-addon-install> added!" |
||||
|
EOF |
||||
|
} |
||||
|
|
||||
|
function compute_bgcolor_target() { |
||||
|
target=$(yq '.target' "$EXPANDED_CONF") |
||||
|
case "$target" in |
||||
|
dev) builtin echo "#17a2b8" ;; |
||||
|
beta) builtin echo "#79A70A" ;; |
||||
|
prod) builtin echo "#7C7BAD" ;; |
||||
|
*) echoerr "unknown target <$target>" && exit 10 ;; |
||||
|
esac |
||||
|
} |
||||
|
|
||||
|
### MAIN |
||||
|
|
||||
|
. "$MIAOU_BASEDIR/lib/init.sh" |
||||
|
arg1_required "$@" |
||||
|
readonly CONTAINER="$1" |
||||
|
BACKGROUND_COLOR=$(compute_bgcolor_target) |
||||
|
readonly BACKGROUND_COLOR |
||||
|
|
||||
|
check || ( |
||||
|
install |
||||
|
check |
||||
|
) |
@ -0,0 +1,33 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
CLIENT=$1 |
||||
|
ADDON=$2 |
||||
|
|
||||
|
function usage() { |
||||
|
echo 'usage: <CLIENT> <ADDON>' |
||||
|
exit 100 |
||||
|
} |
||||
|
|
||||
|
# VERIFICATION |
||||
|
|
||||
|
[[ -z "$CLIENT" || -z "$ADDON" ]] && usage |
||||
|
[[ ! -d "/home/odoo/data-${CLIENT}" ]] && echo "unknown CLIENT <${CLIENT}>, should exist in folder /home/odoo/data-..." && exit 2 |
||||
|
|
||||
|
URL="https://pypi.org/project/odoo-addon-${ADDON}/" |
||||
|
curl --output /dev/null --silent --head --fail "${URL}" |
||||
|
[[ $? -ne 0 ]] && echo "unknown ADDON <${ADDON}>, should be downloadable from: ${URL}" && exit 3 |
||||
|
|
||||
|
[[ -d "/home/odoo/data-${CLIENT}/addons/18.0/${ADDON}" ]] && echo "ADDON <${ADDON}> already exists, consider removing manually!" && exit 4 |
||||
|
|
||||
|
# ACTION |
||||
|
|
||||
|
package=$(curl -Ls "$URL" | rg '<a href="(https://files.pythonhosted.org/.*)">' -r '$1') |
||||
|
wget $package -O /tmp/package.zip |
||||
|
rm /tmp/ADDON -rf && mkdir /tmp/ADDON |
||||
|
unzip /tmp/package.zip 'odoo/addons/*' -d /tmp/ADDON/ |
||||
|
real_name=$(unzip -l /tmp/package.zip | head -n4 | tail -n1 | cut -d'/' -f3) |
||||
|
chown -R odoo:odoo /tmp/ADDON/ |
||||
|
mv /tmp/ADDON/odoo/addons/* "/home/odoo/data-$CLIENT/addons/18.0/" |
||||
|
|
||||
|
# ADD |
||||
|
su odoo -c "python3.10 /home/odoo/odoo/odoo-bin -c /etc/odoo/$CLIENT.conf -i $real_name -d odoo-$CLIENT --worker=0 --stop-after-init" |
@ -0,0 +1,17 @@ |
|||||
|
[options] |
||||
|
data_dir = /home/odoo/data-{{ APP_NAME }} |
||||
|
|
||||
|
xmlrpc_port = {{ APP_PORT }} |
||||
|
longpolling_port = {{ LONG_PORT }} |
||||
|
|
||||
|
db_host = ct1.lxd |
||||
|
db_name = odoo-{{ APP_NAME }} |
||||
|
db_user = odoo-{{ APP_NAME }} |
||||
|
db_password = odoo-{{ APP_NAME }} |
||||
|
list_db = {{ target != 'prod'}} |
||||
|
|
||||
|
workers = 2 |
||||
|
db_maxconn = 10 |
||||
|
db_filter = .* |
||||
|
syslog = True |
||||
|
proxy_mode = True |
@ -0,0 +1,14 @@ |
|||||
|
[Unit] |
||||
|
Description=Odoo {{ APP_NAME }} |
||||
|
After=network.target |
||||
|
|
||||
|
[Service] |
||||
|
Type=simple |
||||
|
SyslogIdentifier=odoo-{{ APP_NAME }} |
||||
|
PermissionsStartOnly=true |
||||
|
User=odoo |
||||
|
Group=odoo |
||||
|
ExecStart=python3.10 /home/odoo/odoo/odoo-bin -c /etc/odoo/{{ APP_NAME }}.conf |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
Write
Preview
Loading…
Cancel
Save
Reference in new issue