update
This commit is contained in:
parent
11c1383ec6
commit
9611528251
30
Dockerfile
Normal file
30
Dockerfile
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
FROM odoo:16.0
|
||||||
|
# Overwrite odoo with addons
|
||||||
|
COPY ./odoo /usr/lib/python3/dist-packages/
|
||||||
|
COPY ./addons /usr/lib/python3/dist-packages/odoo
|
||||||
|
COPY ./deployment/entrypoint.sh /
|
||||||
|
# Copy entrypoint script and Odoo configuration file
|
||||||
|
# COPY deployment/entrypoint.sh /
|
||||||
|
# COPY deployment/odoo.conf /etc/odoo/
|
||||||
|
|
||||||
|
# Set permissions and Mount /var/lib/odoo to allow restoring filestore and /mnt/extra-addons for users addons and /mnt/backup for backup
|
||||||
|
RUN chown odoo /etc/odoo/odoo.conf \
|
||||||
|
&& mkdir -p /mnt/extra-addons \
|
||||||
|
&& chown -R odoo /mnt/extra-addons \
|
||||||
|
&& mkdir -p /var/lib/odoo/backup \
|
||||||
|
&& chown -R odoo /var/lib/odoo/backup
|
||||||
|
VOLUME ["/var/lib/odoo", "/mnt/extra-addons","/var/lib/odoo/backup"]
|
||||||
|
|
||||||
|
# Expose Odoo services
|
||||||
|
EXPOSE 8069 8071 8072
|
||||||
|
|
||||||
|
# Set the default config file
|
||||||
|
ENV ODOO_RC /etc/odoo/odoo.conf
|
||||||
|
|
||||||
|
# COPY deployment/wait-for-psql.py /usr/local/bin/wait-for-psql.py
|
||||||
|
|
||||||
|
# Set default user when running the container
|
||||||
|
USER odoo
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
CMD ["odoo"]
|
137
Makefile
Normal file
137
Makefile
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
ifneq ("$(wildcard .env)", "")
|
||||||
|
include .env
|
||||||
|
endif
|
||||||
|
ifneq ("$(wildcard automation/automation.mk)", "")
|
||||||
|
include automation/automation.mk
|
||||||
|
endif
|
||||||
|
.SHELLFLAGS += ${SHELLFLAGS} -e
|
||||||
|
PWD = $(shell pwd)
|
||||||
|
UID = $(shell id -u)
|
||||||
|
GID = $(shell id -g)
|
||||||
|
PIP=${PWD}/venv/bin/pip
|
||||||
|
PYTHON=${PWD}/venv/bin/python
|
||||||
|
VENV := $(shell [ -d "${PWD}/venv" ] && echo "exists" || echo "missing")
|
||||||
|
DOCKERCMD=docker
|
||||||
|
DOCKER_COMPOSE_CMD=docker-compose
|
||||||
|
DOCKER_BUILD=$(DOCKERCMD) build
|
||||||
|
DOCKER_PUSH=$(DOCKERCMD) push
|
||||||
|
DOCKER_IMAGE=$(DOCKERCMD) image
|
||||||
|
DOCKER_EXEC=$(DOCKERCMD) exec
|
||||||
|
DEPLOY_PATH=${PWD}/deployment
|
||||||
|
SETUP_PATH=${PWD}/setup
|
||||||
|
CONFIG=odoo.conf
|
||||||
|
HUB=hub.nextzenos.com
|
||||||
|
CDN=https://cdn.nextzenos.com/CDN/NextERP
|
||||||
|
ORGANIZATION=nexterp
|
||||||
|
PROJECT := odoo18
|
||||||
|
ODOO_IMAGE=${HUB}/${ORGANIZATION}/$(PROJECT)
|
||||||
|
TAG := $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
|
CONTAINER_ID=${PROJECT}-${TAG}
|
||||||
|
VERSION := community
|
||||||
|
ADDONS=${PWD}/addons,${PWD}/odoo/addons,${PWD}/extra-addons
|
||||||
|
BACKUP=${CDN}/raw/branch/main/backup/${VERSION}/odoo18-main_2025-01-15_08-05-47.zip
|
||||||
|
|
||||||
|
AUTOMATION_PATH=${PWD}/automation
|
||||||
|
|
||||||
|
########### Automation #########
|
||||||
|
deploy-native:
|
||||||
|
@echo "Not implemented"
|
||||||
|
##### Virtual Environment #####
|
||||||
|
|
||||||
|
check-virtualenv:
|
||||||
|
@if [ "$(VENV)" = "missing" ]; then \
|
||||||
|
echo "Creating virtual environment..."; \
|
||||||
|
python3 -m venv venv; \
|
||||||
|
echo "Installing pip dependencies..."; \
|
||||||
|
$(PIP) install --upgrade pip; \
|
||||||
|
else \
|
||||||
|
echo "Skipping Creating virtual environment..."; \
|
||||||
|
fi;
|
||||||
|
##### Native Deployment#########
|
||||||
|
install: check-virtualenv
|
||||||
|
sudo apt update -y && \
|
||||||
|
sudo apt install -y python3-pip libldap2-dev libpq-dev libsasl2-dev postgresql-client libreoffice wkhtmltopdf ansible terraform&& \
|
||||||
|
${PIP} install --no-input -r requirements.txt --break-system-packages
|
||||||
|
download_backup:
|
||||||
|
@if [ -z "${LINKDB}" ]; then \
|
||||||
|
LinkDB=${BACKUP}; \
|
||||||
|
read -p "LinkDownload [default: ${BACKUP}]: " InputLinkDB; \
|
||||||
|
LinkDB=$${InputLinkDB:-${BACKUP}}; \
|
||||||
|
else \
|
||||||
|
LinkDB=${LINKDB}; \
|
||||||
|
fi; \
|
||||||
|
Filename=$$(basename $$LinkDB); \
|
||||||
|
echo "Downloading $$Filename from: $$LinkDB"; \
|
||||||
|
${PWD}/setup/download_backup.sh $$LinkDB backup.zip
|
||||||
|
gen_config:
|
||||||
|
$(MAKE) download_backup LINKDB=${BACKUP}
|
||||||
|
${PWD}/setup/init_config.sh --native ${ADDONS} ${DB_USER} ${DB_PASSWORD} ${DB_SERVER} ${DB_PORT}
|
||||||
|
run_server:
|
||||||
|
${PYTHON} odoo-bin --config=${CONFIG}
|
||||||
|
run_test:
|
||||||
|
${PYTHON} odoo-bin --test-tags :TestAccountMove.test_out_invoice_auto_post_monthly,TestAccountMove.test_included_tax --log-level=test --test-enable -d testdb-${TAG} --stop-after-init --config=${CONFIG}
|
||||||
|
${PYTHON} odoo-bin db --config=${CONFIG} drop testdb-${TAG}
|
||||||
|
restore_database:
|
||||||
|
@read -p "Backup Path [default: ${PWD}/deployment/backup/backup.zip]: " InputbackupDB; \
|
||||||
|
BackupDB=$${InputbackupDB:-${PWD}/deployment/backup/backup.zip}; \
|
||||||
|
read -p "Enter the database name: " DBNAME; \
|
||||||
|
echo "Restoring database: $$DBNAME"; \
|
||||||
|
${PYTHON} odoo-bin db --config=${CONFIG} load "$$DBNAME" "$$BackupDB"
|
||||||
|
scaffold_module:
|
||||||
|
read -p "Module Name: " ModuleName; \
|
||||||
|
read -p "addons Path[eg:addons, extra-addons, exercise]: " ModulePath; \
|
||||||
|
${PYTHON} odoo-bin scaffold $$ModuleName && \
|
||||||
|
mv $$ModuleName ${PWD}/$$ModulePath;
|
||||||
|
cleanup_addons:
|
||||||
|
@bash ${PWD}/setup/clean_up_addons.sh $(shell echo $(ADDONS) | tr ',' ' ')
|
||||||
|
install_modules:
|
||||||
|
${PYTHON} odoo-bin --config=${CONFIG} -d ${DATABASE} -i ${MODULES} --xmlrpc-port=${PORT}
|
||||||
|
|
||||||
|
##### Docker Deployment #########
|
||||||
|
run_test_docker:
|
||||||
|
sudo ${DOCKER_EXEC} ${CONTAINER_ID} odoo --test-tags :TestAccountMove.test_out_invoice_auto_post_monthly,TestAccountMove.test_included_tax --log-level=test --test-enable -d testdb-${TAG} --stop-after-init --config=/etc/odoo/${CONFIG} --xmlrpc-port=8071 && \
|
||||||
|
sudo ${DOCKER_EXEC} ${CONTAINER_ID} odoo db --config=/etc/odoo/${CONFIG} drop testdb-${TAG}
|
||||||
|
gen_config_docker:
|
||||||
|
$(MAKE) download_backup LINKDB=${BACKUP}
|
||||||
|
${PWD}/setup/init_config.sh --docker ${ODOO_IMAGE} ${TAG} ${CONTAINER_ID}
|
||||||
|
build_image:
|
||||||
|
DOCKER_BUILDKIT=1 ${DOCKER_BUILD} . --progress plain --tag ${ODOO_IMAGE}:${TAG}
|
||||||
|
push_image:
|
||||||
|
$(DOCKER_PUSH) ${ODOO_IMAGE}:${TAG}
|
||||||
|
run_server_docker:
|
||||||
|
@if ! docker ps | grep -q "${CONTAINER_ID}"; then \
|
||||||
|
echo "Container not found. Running docker-compose up -d"; \
|
||||||
|
else \
|
||||||
|
echo "Container already running. Skipping docker-compose up -d."; \
|
||||||
|
fi
|
||||||
|
cd ${DEPLOY_PATH} &&\
|
||||||
|
${DOCKER_COMPOSE_CMD} up -d
|
||||||
|
update_tag:
|
||||||
|
${SETUP_PATH}/update_tag.sh $(CURR_BRANCH)
|
||||||
|
restore_database_docker:
|
||||||
|
sudo ${DOCKER_EXEC} ${CONTAINER_ID} odoo db -c /etc/odoo/odoo.conf load backup /var/lib/odoo/backup/backup.zip
|
||||||
|
stop_server_docker:
|
||||||
|
@if ! docker ps | grep -q "${CONTAINER_ID}"; then \
|
||||||
|
echo "Container not found. Skipping"; \
|
||||||
|
else \
|
||||||
|
cd ${DEPLOY_PATH} &&\
|
||||||
|
${DOCKER_COMPOSE_CMD} down; \
|
||||||
|
fi
|
||||||
|
clean_up:
|
||||||
|
@if ! docker ps | grep -q "${CONTAINER_ID}"; then \
|
||||||
|
echo "Container not found. Skipping"; \
|
||||||
|
else \
|
||||||
|
cd ${DEPLOY_PATH} &&\
|
||||||
|
${DOCKER_COMPOSE_CMD} down; \
|
||||||
|
fi
|
||||||
|
find "${DEPLOY_PATH}" -mindepth 1 -maxdepth 1 \
|
||||||
|
! -name "etc" \
|
||||||
|
! -name "addons" \
|
||||||
|
! -name "backup" \
|
||||||
|
! -name "*.sh" \
|
||||||
|
! -name "*.template" \
|
||||||
|
! -name "*.py" \
|
||||||
|
! -name "*.yml" \
|
||||||
|
-print0 | sudo xargs -0 rm -rf {} && \
|
||||||
|
sudo rm -rf ${DEPLOY_PATH}/etc/*
|
||||||
|
|
BIN
deployment/backup/backup.zip
Normal file
BIN
deployment/backup/backup.zip
Normal file
Binary file not shown.
35
deployment/docker-compose.yml
Executable file
35
deployment/docker-compose.yml
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: ${ODOO_IMAGE:-odoo}:${ODOO_TAG:-16}
|
||||||
|
container_name: ${ODOO_CONTAINER:-odoo}
|
||||||
|
# user: root
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
ports:
|
||||||
|
- ${ODOO_PORT:-8069}:8069
|
||||||
|
# - "${ODOO_CHAT_PORT:-8072}:8072"
|
||||||
|
tty: true
|
||||||
|
command: --
|
||||||
|
environment:
|
||||||
|
- HOST=db
|
||||||
|
- USER=${PG_USER:-changeme}
|
||||||
|
- PASSWORD=${PG_PASS:-password}
|
||||||
|
volumes:
|
||||||
|
- ${ODOO_ADDONS:-./addons}:/mnt/extra-addons
|
||||||
|
- ${ODOO_CONFIG:-./etc}:/etc/odoo
|
||||||
|
- ${ODOO_BACKUP:-./backup}:/var/lib/odoo/backup
|
||||||
|
restart: always
|
||||||
|
db:
|
||||||
|
image: postgres:15
|
||||||
|
# user: root
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${PG_USER:-changeme}
|
||||||
|
- POSTGRES_PASSWORD=${PG_PASS:-password}
|
||||||
|
- POSTGRES_DB=postgres
|
||||||
|
ports:
|
||||||
|
- ${PG_PORT:-5432}:5432
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ${PG_DATA:-./postgresql}:/var/lib/postgresql/data
|
||||||
|
|
51
deployment/entrypoint.sh
Executable file
51
deployment/entrypoint.sh
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -v PASSWORD_FILE ]; then
|
||||||
|
PASSWORD="$(< $PASSWORD_FILE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set the postgres database host, port, user and password according to the environment
|
||||||
|
# and pass them as arguments to the odoo process if not present in the config file
|
||||||
|
: ${HOST:=${DB_PORT_5432_TCP_ADDR:='db'}}
|
||||||
|
: ${PORT:=${DB_PORT_5432_TCP_PORT:=5432}}
|
||||||
|
: ${USER:=${DB_ENV_POSTGRES_USER:=${POSTGRES_USER:='odoo'}}}
|
||||||
|
: ${PASSWORD:=${DB_ENV_POSTGRES_PASSWORD:=${POSTGRES_PASSWORD:='odoo'}}}
|
||||||
|
|
||||||
|
DB_ARGS=()
|
||||||
|
function check_config() {
|
||||||
|
param="$1"
|
||||||
|
value="$2"
|
||||||
|
if grep -q -E "^\s*\b${param}\b\s*=" "$ODOO_RC" ; then
|
||||||
|
value=$(grep -E "^\s*\b${param}\b\s*=" "$ODOO_RC" |cut -d " " -f3|sed 's/["\n\r]//g')
|
||||||
|
fi;
|
||||||
|
DB_ARGS+=("--${param}")
|
||||||
|
DB_ARGS+=("${value}")
|
||||||
|
}
|
||||||
|
check_config "db_host" "$HOST"
|
||||||
|
check_config "db_port" "$PORT"
|
||||||
|
check_config "db_user" "$USER"
|
||||||
|
check_config "db_password" "$PASSWORD"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
-- | odoo)
|
||||||
|
shift
|
||||||
|
if [[ "$1" == "scaffold" ]] ; then
|
||||||
|
exec odoo "$@"
|
||||||
|
else
|
||||||
|
# shellcheck disable=SC2068
|
||||||
|
wait-for-psql.py ${DB_ARGS[@]} --timeout=30
|
||||||
|
exec odoo "$@" "${DB_ARGS[@]}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
# shellcheck disable=SC2068
|
||||||
|
wait-for-psql.py ${DB_ARGS[@]} --timeout=30
|
||||||
|
exec odoo "$@" "${DB_ARGS[@]}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exec "$@"
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 1
|
15
deployment/env.template
Executable file
15
deployment/env.template
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
COMPOSE_PROJECT_NAME=
|
||||||
|
#Odoo
|
||||||
|
ODOO_IMAGE=
|
||||||
|
ODOO_TAG=
|
||||||
|
ODOO_PORT=10017
|
||||||
|
ODOO_CONTAINER=
|
||||||
|
# ODOO_CHAT_PORT=
|
||||||
|
ODOO_ADDONS=./addons
|
||||||
|
ODOO_CONFIG=./etc
|
||||||
|
ODOO_BACKUP=./backup
|
||||||
|
#Database
|
||||||
|
PG_PORT=
|
||||||
|
PG_USER=
|
||||||
|
PG_PASS=
|
||||||
|
ENTRYPOINT=./entrypoint.sh
|
9
deployment/etc/odoo.conf
Normal file
9
deployment/etc/odoo.conf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[options]
|
||||||
|
addons_path = /mnt/extra-addons
|
||||||
|
data_dir = /var/lib/odoo
|
||||||
|
db_host = db
|
||||||
|
db_port = 5432
|
||||||
|
db_user = default_repo
|
||||||
|
db_password = smartyourlife
|
||||||
|
proxy_mode = True
|
||||||
|
|
7
deployment/odoo.conf.template
Executable file
7
deployment/odoo.conf.template
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
[options]
|
||||||
|
addons_path = /mnt/extra-addons
|
||||||
|
data_dir = /var/lib/odoo
|
||||||
|
db_host =
|
||||||
|
db_port =
|
||||||
|
db_user =
|
||||||
|
db_password =
|
32
deployment/wait-for-psql.py
Executable file
32
deployment/wait-for-psql.py
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import psycopg2
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
arg_parser = argparse.ArgumentParser()
|
||||||
|
arg_parser.add_argument('--db_host', required=True)
|
||||||
|
arg_parser.add_argument('--db_port', required=True)
|
||||||
|
arg_parser.add_argument('--db_user', required=True)
|
||||||
|
arg_parser.add_argument('--db_password', required=True)
|
||||||
|
arg_parser.add_argument('--timeout', type=int, default=5)
|
||||||
|
|
||||||
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
while (time.time() - start_time) < args.timeout:
|
||||||
|
try:
|
||||||
|
conn = psycopg2.connect(user=args.db_user, host=args.db_host, port=args.db_port, password=args.db_password, dbname='postgres')
|
||||||
|
error = ''
|
||||||
|
break
|
||||||
|
except psycopg2.OperationalError as e:
|
||||||
|
error = e
|
||||||
|
else:
|
||||||
|
conn.close()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
if error:
|
||||||
|
print("Database connection failure: %s" % error, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
12
odoo.conf.template
Normal file
12
odoo.conf.template
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[options]
|
||||||
|
db_host =
|
||||||
|
db_port = 5432
|
||||||
|
db_user =
|
||||||
|
db_password =
|
||||||
|
xmlrpc_port =
|
||||||
|
addons_path =
|
||||||
|
dbfilter =
|
||||||
|
proxy_mode =
|
||||||
|
logfile = /var/log/odoo/odoo.log
|
||||||
|
db_maxconn = 1000
|
||||||
|
list_db =
|
1195
setup/base-addons.txt
Normal file
1195
setup/base-addons.txt
Normal file
File diff suppressed because it is too large
Load Diff
101
setup/clean_up_addons.sh
Executable file
101
setup/clean_up_addons.sh
Executable file
@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if at least one root folder is provided as an argument
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "Usage: $0 <root_folder> [<root_folder>...]"
|
||||||
|
echo "Please provide at least one root folder path."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Define the protected items list file
|
||||||
|
PROTECTED_LIST="protected.txt"
|
||||||
|
if [ ! -f "$PROTECTED_LIST" ]; then
|
||||||
|
echo "Error: '$PROTECTED_LIST' not found."
|
||||||
|
echo "Please create 'protected.txt' one directory up with a list of protected files/folders (one per line)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Safeguard: Check if any file/folder matching patterns in protected.txt exists in a root folder
|
||||||
|
check_protected_items() {
|
||||||
|
local root_dir="$1"
|
||||||
|
while IFS= read -r pattern; do
|
||||||
|
# Skip empty lines
|
||||||
|
[ -z "$pattern" ] && continue
|
||||||
|
|
||||||
|
# Handle wildcards by using find for pattern matching
|
||||||
|
if [[ "$pattern" == *"*"* ]]; then
|
||||||
|
# Convert pattern to a find-compatible search
|
||||||
|
if [[ "$pattern" == /* ]]; then
|
||||||
|
search_path="${root_dir}${pattern}"
|
||||||
|
else
|
||||||
|
search_path="${root_dir}/${pattern}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use find to check if any files match the pattern
|
||||||
|
if find "$root_dir" -path "$search_path" 2>/dev/null | grep -q .; then
|
||||||
|
echo "Error: Protected pattern '$pattern' matches files in '$root_dir'. Aborting execution."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Exact match for non-wildcard entries
|
||||||
|
if [ -e "$root_dir/$pattern" ]; then
|
||||||
|
echo "Error: Protected item '$pattern' found in '$root_dir'. Aborting execution."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$PROTECTED_LIST"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check and delete subfolders
|
||||||
|
delete_non_manifest_folders() {
|
||||||
|
local dir="$1"
|
||||||
|
|
||||||
|
# Loop through all immediate subdirectories in the given directory
|
||||||
|
for subfolder in "$dir"/*/ ; do
|
||||||
|
# Check if it's a directory
|
||||||
|
if [ -d "$subfolder" ]; then
|
||||||
|
# Check if __manifest__.py exists in this subfolder
|
||||||
|
if [ ! -f "$subfolder/__manifest__.py" ]; then
|
||||||
|
echo "Deleting '$subfolder' (no __manifest__.py found)"
|
||||||
|
rm -rf "$subfolder"
|
||||||
|
else
|
||||||
|
echo "Keeping '$subfolder' (__manifest__.py found)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process each root folder provided as an argument
|
||||||
|
for ROOT_FOLDER in "$@"; do
|
||||||
|
# Check if the root folder exists and is a directory
|
||||||
|
if [ ! -d "$ROOT_FOLDER" ]; then
|
||||||
|
echo "Error: '$ROOT_FOLDER' is not a valid directory. Skipping."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform the safeguard check for this root folder
|
||||||
|
echo "Checking for protected items in '$ROOT_FOLDER' from '$PROTECTED_LIST'..."
|
||||||
|
check_protected_items "$ROOT_FOLDER"
|
||||||
|
|
||||||
|
# Change to the root folder to handle relative paths cleanly
|
||||||
|
cd "$ROOT_FOLDER" || {
|
||||||
|
echo "Error: Could not change to directory '$ROOT_FOLDER'. Skipping."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the function with the current root folder
|
||||||
|
echo "Processing '$ROOT_FOLDER'..."
|
||||||
|
delete_non_manifest_folders "."
|
||||||
|
|
||||||
|
# Return to the original directory to process the next root folder
|
||||||
|
cd - > /dev/null || {
|
||||||
|
echo "Error: Could not return from '$ROOT_FOLDER'. Exiting."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Cleanup complete for '$ROOT_FOLDER'!"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "All root folders processed!"
|
||||||
|
|
||||||
|
exit 0
|
27
setup/clean_up_virtualenvs.sh
Executable file
27
setup/clean_up_virtualenvs.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Get the current branch name
|
||||||
|
branch_name=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
|
||||||
|
# Get a list of all virtual environments, filtering out duplicates and those not containing the branch name
|
||||||
|
virtualenvs=$(pyenv virtualenvs | awk '{print $1}' | sort -u | grep "$branch_name")
|
||||||
|
|
||||||
|
# Count the number of virtual environments
|
||||||
|
count=$(echo "$virtualenvs" | wc -l)
|
||||||
|
|
||||||
|
# Calculate how many virtual environments to keep
|
||||||
|
keep_count=$((count - $1))
|
||||||
|
|
||||||
|
# If there are more than 3 virtual environments, delete the oldest ones
|
||||||
|
if (( keep_count > 0 )); then
|
||||||
|
# Get the oldest virtual environments (assuming they are listed first)
|
||||||
|
oldest_venvs=$(echo "$virtualenvs" | head -n "$keep_count")
|
||||||
|
|
||||||
|
# Loop through the oldest virtual environments and delete them
|
||||||
|
for venv in $oldest_venvs; do
|
||||||
|
echo "Deleting virtual environment: $venv"
|
||||||
|
pyenv virtualenv-delete -f "$venv"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Old virtual environments containing '$branch_name' deleted."
|
29
setup/color_log.py
Normal file
29
setup/color_log.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
def colorize(text, code):
|
||||||
|
"""Colorizes text using ANSI escape codes."""
|
||||||
|
return f"\033[{code}m{text}\033[0m"
|
||||||
|
|
||||||
|
def Show(status, message):
|
||||||
|
"""Displays a message with a status indicator."""
|
||||||
|
colors = {
|
||||||
|
0: (colorize("[", "90")+colorize(" OK ", "38;5;154") + colorize("]", "90")), # Green, Grey
|
||||||
|
1: (colorize("[", "90")+colorize(" FAILED ", "91") + colorize("]", "90")), # Red, Grey
|
||||||
|
2: (colorize("[", "90")+colorize(" INFO ", "38;5;154") + colorize("]", "90")), # Green, Grey
|
||||||
|
3: (colorize("[", "90")+colorize(" NOTICE ", "33") + colorize("]", "90")), # Yellow, Grey
|
||||||
|
}
|
||||||
|
print(f"{colors.get(status, '')} {message}")
|
||||||
|
if status == 1:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def Warn(message):
|
||||||
|
"""Displays a warning message in red."""
|
||||||
|
print(colorize(message, "91"))
|
||||||
|
|
||||||
|
def GreyStart():
|
||||||
|
"""Starts a grey-colored output."""
|
||||||
|
print(colorize("", "90"), end="")
|
||||||
|
|
||||||
|
def ColorReset():
|
||||||
|
"""Resets the output color."""
|
||||||
|
print("\033[0m", end="")
|
10
setup/dir2file.sh
Executable file
10
setup/dir2file.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Define output file name
|
||||||
|
input_dir="$1"
|
||||||
|
output_file="$2"
|
||||||
|
# Find all directories in root and write to file
|
||||||
|
# Using find to list only directories (-type d) at depth 1 (-maxdepth 1)
|
||||||
|
find $input_dir -maxdepth 1 -type d -not -path "$input_dir" -exec basename {} \; | sort >> "$output_file"
|
||||||
|
|
||||||
|
echo "Folder list has been written to $output_file"
|
82
setup/download_backup.sh
Executable file
82
setup/download_backup.sh
Executable file
@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
export PATH=/usr/sbin:$PATH
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
set -euo pipefail
|
||||||
|
readonly COLOUR_RESET='\e[0m'
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
trap 'onCtrlC' INT
|
||||||
|
onCtrlC() {
|
||||||
|
echo -e "${COLOUR_RESET}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
exit 1
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
GreyStart() {
|
||||||
|
echo -e "${aCOLOUR[2]}\c"
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorReset() {
|
||||||
|
echo -e "$COLOUR_RESET\c"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
main() {
|
||||||
|
DEPLOYMENT_DIR=$(pwd)/deployment
|
||||||
|
BACKUP_DIR="$DEPLOYMENT_DIR/backup"
|
||||||
|
DOWNLOAD_URL="$1"
|
||||||
|
BACKUP_FILE="$BACKUP_DIR/$2"
|
||||||
|
# Check if the deployment and backup directories exist, create them if not
|
||||||
|
if [[ ! -d "$BACKUP_DIR" ]]; then
|
||||||
|
echo "Backup directory does not exist. Creating: $BACKUP_DIR"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the download URL is valid
|
||||||
|
echo "Checking if the URL is valid: $DOWNLOAD_URL"
|
||||||
|
if curl --head --silent --fail "$DOWNLOAD_URL" > /dev/null; then
|
||||||
|
echo "URL is valid. Proceeding with download..."
|
||||||
|
else
|
||||||
|
Show 1 "Error: Invalid or inaccessible URL: $DOWNLOAD_URL"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download the file and rename it to backup.zip
|
||||||
|
wget -O "$BACKUP_FILE" "$DOWNLOAD_URL"
|
||||||
|
|
||||||
|
# Check if the file was downloaded
|
||||||
|
if [[ -f "$BACKUP_FILE" ]]; then
|
||||||
|
Show 0 "Backup file successfully downloaded to: $BACKUP_FILE"
|
||||||
|
else
|
||||||
|
Show 1 "Error: Backup file was not downloaded."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
67
setup/gen_config.py
Normal file
67
setup/gen_config.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import configparser
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
from dotenv import set_key
|
||||||
|
from pathlib import Path
|
||||||
|
import socket
|
||||||
|
import secrets
|
||||||
|
import string
|
||||||
|
import color_log
|
||||||
|
def find_available_port(start_port=80):
|
||||||
|
"""Finds an available port starting from the given port."""
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
sock.bind(('0.0.0.0', start_port))
|
||||||
|
color_log.Show(3,f" {start_port} is Open")
|
||||||
|
return start_port
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == 98: # Address already in use
|
||||||
|
print(f"{start_port} already in use , Try other port ...")
|
||||||
|
start_port += 1
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Generates a random password and finds an available port.
|
||||||
|
Updates the Odoo configuration file and .env file with these values.
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser(description="Generate Odoo configuration")
|
||||||
|
parser.add_argument('--db_user', type=str, help='')
|
||||||
|
parser.add_argument('--db_pass', type=str, help='')
|
||||||
|
parser.add_argument('--deploy_path', type=str, help='')
|
||||||
|
parser.add_argument('--addons_path', type=str, help='')
|
||||||
|
# parser.add_argument('--db_filter', type=str, help='')
|
||||||
|
parser.add_argument('--db_port', type=int, help='')
|
||||||
|
parser.add_argument('--db_server', type=str, help='')
|
||||||
|
args = parser.parse_args()
|
||||||
|
db_port = args.db_port
|
||||||
|
db_user = args.db_user
|
||||||
|
db_pass = args.db_pass
|
||||||
|
db_server = args.db_server
|
||||||
|
app_port = find_available_port(8069)
|
||||||
|
addons_path = args.addons_path
|
||||||
|
base_dir= args.deploy_path
|
||||||
|
# db_filter= args.db_filter
|
||||||
|
# Copy template files
|
||||||
|
os.makedirs(f"{base_dir}/etc", exist_ok=True)
|
||||||
|
color_log.Show(3,f"Copy {base_dir}/odoo.conf.template to {base_dir}/etc/odoo.conf")
|
||||||
|
shutil.copyfile(f'{base_dir}/odoo.conf.template', f'{base_dir}/odoo.conf')
|
||||||
|
|
||||||
|
# Update Odoo configuration file
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(f'{base_dir}/odoo.conf')
|
||||||
|
config['options']['db_host'] = str(db_server)
|
||||||
|
config['options']['db_user'] = db_user
|
||||||
|
config['options']['db_password'] = db_pass
|
||||||
|
config['options']['db_port'] = str(db_port)
|
||||||
|
config['options']['addons_path'] = addons_path
|
||||||
|
config['options']['xmlrpc_port'] = str(app_port)
|
||||||
|
config['options']['dbfilter'] = ".*"
|
||||||
|
config['options']['proxy_mode'] = "True"
|
||||||
|
with open(f'{base_dir}/odoo.conf', 'w') as configfile:
|
||||||
|
config.write(configfile)
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
93
setup/gen_config_docker.py
Executable file
93
setup/gen_config_docker.py
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import configparser
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
from dotenv import set_key
|
||||||
|
from pathlib import Path
|
||||||
|
import socket
|
||||||
|
import secrets
|
||||||
|
import string
|
||||||
|
import color_log
|
||||||
|
def generate_password(length=16):
|
||||||
|
"""Generates a random password of specified length."""
|
||||||
|
alphabet = string.ascii_letters + string.digits
|
||||||
|
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
||||||
|
|
||||||
|
def find_available_port(start_port=80):
|
||||||
|
"""Finds an available port starting from the given port."""
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
sock.bind(('0.0.0.0', start_port))
|
||||||
|
color_log.Show(3,f" {start_port} is Open")
|
||||||
|
return start_port
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == 98: # Address already in use
|
||||||
|
print(f"{start_port} already in use , Try other port ...")
|
||||||
|
start_port += 1
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Generates a random password and finds an available port.
|
||||||
|
Updates the Odoo configuration file and .env file with these values.
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser(description="Generate Odoo configuration")
|
||||||
|
parser.add_argument('--db_port', type=int, help='')
|
||||||
|
parser.add_argument('--db_user', type=str, help='')
|
||||||
|
parser.add_argument('--deploy_path', type=str, help='')
|
||||||
|
parser.add_argument('--image', type=str, help='')
|
||||||
|
parser.add_argument('--tag', type=str, help='')
|
||||||
|
parser.add_argument('--addons', type=str, help='')
|
||||||
|
parser.add_argument('--config', type=str, help='')
|
||||||
|
parser.add_argument('--container', type=str, help='')
|
||||||
|
parser.add_argument('--backup', type=str, help='')
|
||||||
|
args = parser.parse_args()
|
||||||
|
db_port = args.db_port
|
||||||
|
db_pass = "smartyourlife"
|
||||||
|
db_user = args.db_user
|
||||||
|
base_dir= args.deploy_path
|
||||||
|
image=args.image
|
||||||
|
tag=args.tag
|
||||||
|
container=args.container
|
||||||
|
addons=args.addons
|
||||||
|
config_path=args.config
|
||||||
|
app_port = 10017
|
||||||
|
backup = args.backup
|
||||||
|
# Copy template files
|
||||||
|
os.makedirs(f"{base_dir}/etc", exist_ok=True)
|
||||||
|
color_log.Show(3,f"Copy {base_dir}/odoo.conf.template to {base_dir}/etc/odoo.conf")
|
||||||
|
shutil.copyfile(f'{base_dir}/odoo.conf.template', f'{base_dir}/etc/odoo.conf')
|
||||||
|
shutil.copyfile(f'{base_dir}/env.template', f'{base_dir}/.env')
|
||||||
|
|
||||||
|
# Update Odoo configuration file
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(f'{base_dir}/etc/odoo.conf')
|
||||||
|
config['options']['db_host'] = "db"
|
||||||
|
config['options']['db_user'] = db_user
|
||||||
|
config['options']['db_password'] = db_pass
|
||||||
|
config['options']['db_port'] = str(db_port)
|
||||||
|
config['options']['addons_path'] = "/mnt/extra-addons"
|
||||||
|
config['options']['data_dir'] = "/var/lib/odoo"
|
||||||
|
config['options']['proxy_mode'] = "True"
|
||||||
|
with open(f'{base_dir}/etc/odoo.conf', 'w') as configfile:
|
||||||
|
config.write(configfile)
|
||||||
|
|
||||||
|
# Update .env file
|
||||||
|
env_file_path = Path("deployment/.env")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="COMPOSE_PROJECT_NAME", value_to_set=f"odoo-{tag}",quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="PG_PORT", value_to_set=find_available_port(int(os.getenv('DB_PORT','5432'))+1),quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="PG_USER", value_to_set=db_user,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="PG_PASS", value_to_set=db_pass,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_CONFIG", value_to_set=config_path,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_ADDONS", value_to_set=addons,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_PORT", value_to_set=find_available_port(app_port),quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_IMAGE", value_to_set=image,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_TAG", value_to_set=tag,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_CONTAINER", value_to_set=container,quote_mode="never")
|
||||||
|
set_key(dotenv_path=env_file_path, key_to_set="ODOO_BACKUP", value_to_set=backup,quote_mode="never")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
245
setup/init_config.sh
Executable file
245
setup/init_config.sh
Executable file
@ -0,0 +1,245 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
export PATH=/usr/sbin:$PATH
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
set -euo pipefail
|
||||||
|
DEPLOY_PATH=$(pwd)/deployment
|
||||||
|
SETUP_PATH=$(pwd)/setup
|
||||||
|
PIP=$(pwd)/venv/bin/pip
|
||||||
|
PYTHON=$(pwd)/venv/bin/python
|
||||||
|
ODOO_ADDONS=${DEPLOY_PATH}/addons
|
||||||
|
ODOO_CONFIG=${DEPLOY_PATH}/etc
|
||||||
|
ODOO_BACKUP=${DEPLOY_PATH}/backup
|
||||||
|
# System
|
||||||
|
DEPENDS_PACKAGE=('wget' 'curl' 'git' 'unzip' 'make' 'wkhtmltopdf' 'postgresql-client')
|
||||||
|
DEPENDS_COMMAND=('wget' 'curl' 'git' 'unzip' 'make' 'wkhtmltopdf' 'psql')
|
||||||
|
((EUID)) && sudo_cmd="sudo" || sudo_cmd=""
|
||||||
|
readonly MINIMUM_DOCER_VERSION="20"
|
||||||
|
UNAME_U="$(uname -s)"
|
||||||
|
readonly UNAME_U
|
||||||
|
readonly COLOUR_RESET='\e[0m'
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
trap 'onCtrlC' INT
|
||||||
|
onCtrlC() {
|
||||||
|
echo -e "${COLOUR_RESET}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
exit 1
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
GreyStart() {
|
||||||
|
echo -e "${aCOLOUR[2]}\c"
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorReset() {
|
||||||
|
echo -e "$COLOUR_RESET\c"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Update_Package_Resource() {
|
||||||
|
GreyStart
|
||||||
|
if [ -x "$(command -v apk)" ]; then
|
||||||
|
${sudo_cmd} apk update
|
||||||
|
elif [ -x "$(command -v apt)" ]; then
|
||||||
|
${sudo_cmd} apt update
|
||||||
|
elif [ -x "$(command -v dnf)" ]; then
|
||||||
|
${sudo_cmd} dnf check-update
|
||||||
|
elif [ -x "$(command -v zypper)" ]; then
|
||||||
|
${sudo_cmd} zypper update
|
||||||
|
elif [ -x "$(command -v yum)" ]; then
|
||||||
|
${sudo_cmd} yum update
|
||||||
|
fi
|
||||||
|
ColorReset
|
||||||
|
}
|
||||||
|
# 3 Check OS
|
||||||
|
Check_OS() {
|
||||||
|
if [[ $UNAME_U == *Linux* ]]; then
|
||||||
|
Show 0 "Your System is : $UNAME_U"
|
||||||
|
else
|
||||||
|
Show 1 "This script is only for Linux."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
Install_Depends() {
|
||||||
|
for ((i = 0; i < ${#DEPENDS_COMMAND[@]}; i++)); do
|
||||||
|
cmd=${DEPENDS_COMMAND[i]}
|
||||||
|
if [[ ! -x $(${sudo_cmd} which "$cmd") ]]; then
|
||||||
|
packagesNeeded=${DEPENDS_PACKAGE[i]}
|
||||||
|
Show 2 "Install the necessary dependencies: \e[33m$packagesNeeded \e[0m"
|
||||||
|
GreyStart
|
||||||
|
if [ -x "$(command -v apk)" ]; then
|
||||||
|
${sudo_cmd} apk add --no-cache "$packagesNeeded"
|
||||||
|
elif [ -x "$(command -v apt-get)" ]; then
|
||||||
|
${sudo_cmd} apt-get -y -q install "$packagesNeeded" --no-upgrade
|
||||||
|
elif [ -x "$(command -v dnf)" ]; then
|
||||||
|
${sudo_cmd} dnf install "$packagesNeeded"
|
||||||
|
elif [ -x "$(command -v zypper)" ]; then
|
||||||
|
${sudo_cmd} zypper install "$packagesNeeded"
|
||||||
|
elif [ -x "$(command -v yum)" ]; then
|
||||||
|
${sudo_cmd} yum install "$packagesNeeded"
|
||||||
|
elif [ -x "$(command -v pacman)" ]; then
|
||||||
|
${sudo_cmd} pacman -S "$packagesNeeded"
|
||||||
|
elif [ -x "$(command -v paru)" ]; then
|
||||||
|
${sudo_cmd} paru -S "$packagesNeeded"
|
||||||
|
else
|
||||||
|
Show 1 "Package manager not found. You must manually install: \e[33m$packagesNeeded \e[0m"
|
||||||
|
fi
|
||||||
|
ColorReset
|
||||||
|
else
|
||||||
|
Show 2 "\e[33m ${DEPENDS_COMMAND[i]}\e[0m Installed"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
Check_Dependency_Installation() {
|
||||||
|
for ((i = 0; i < ${#DEPENDS_COMMAND[@]}; i++)); do
|
||||||
|
cmd=${DEPENDS_COMMAND[i]}
|
||||||
|
if [[ ! -x $(${sudo_cmd} which "$cmd") ]]; then
|
||||||
|
packagesNeeded=${DEPENDS_PACKAGE[i]}
|
||||||
|
Show 1 "Dependency \e[33m$packagesNeeded \e[0m installation failed, please try again manually!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
Check_Docker_Install() {
|
||||||
|
if [[ -x "$(command -v docker)" ]]; then
|
||||||
|
Docker_Version=$(${sudo_cmd} docker version --format '{{.Server.Version}}')
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
Install_Docker
|
||||||
|
elif [[ ${Docker_Version:0:2} -lt "${MINIMUM_DOCER_VERSION}" ]]; then
|
||||||
|
Show 1 "Recommended minimum Docker version is \e[33m${MINIMUM_DOCER_VERSION}.xx.xx\e[0m,\Current Docker verison is \e[33m${Docker_Version}\e[0m,\nPlease uninstall current Docker and rerun the CasaOS installation script."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Show 0 "Current Docker verison is ${Docker_Version}."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
Install_Docker
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
Install_Docker() {
|
||||||
|
Show 2 "Install the necessary dependencies: \e[33mDocker \e[0m"
|
||||||
|
if [[ ! -d "${PREFIX}/etc/apt/sources.list.d" ]]; then
|
||||||
|
${sudo_cmd} mkdir -p "${PREFIX}/etc/apt/sources.list.d"
|
||||||
|
fi
|
||||||
|
GreyStart
|
||||||
|
if [[ "${REGION}" = "CN" ]]; then
|
||||||
|
${sudo_cmd} curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
|
||||||
|
else
|
||||||
|
${sudo_cmd} curl -fsSL https://get.docker.com | bash
|
||||||
|
fi
|
||||||
|
ColorReset
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
Show 1 "Installation failed, please try again."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Check_Docker_Install_Final
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
Check_Docker_Install_Final() {
|
||||||
|
if [[ -x "$(command -v docker)" ]]; then
|
||||||
|
Docker_Version=$(${sudo_cmd} docker version --format '{{.Server.Version}}')
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
Install_Docker
|
||||||
|
elif [[ ${Docker_Version:0:2} -lt "${MINIMUM_DOCER_VERSION}" ]]; then
|
||||||
|
Show 1 "Recommended minimum Docker version is \e[33m${MINIMUM_DOCER_VERSION}.xx.xx\e[0m,\Current Docker verison is \e[33m${Docker_Version}\e[0m,\nPlease uninstall current Docker and rerun the CasaOS installation script."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Show 0 "Current Docker verison is ${Docker_Version}."
|
||||||
|
Check_Docker_Running
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
Show 1 "Installation failed, please run 'curl -fsSL https://get.docker.com | bash' and rerun the CasaOS installation script."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
Generate_Config_Docker(){
|
||||||
|
ODOO_IMAGE=${1:-}
|
||||||
|
ODOO_TAG=${2:-}
|
||||||
|
ODOO_CONTAINER=${3:-}
|
||||||
|
if [[ ! -f "${DEPLOY_PATH}/.env" ]]; then
|
||||||
|
cp "${DEPLOY_PATH}/env.template" "${DEPLOY_PATH}/.env"
|
||||||
|
fi
|
||||||
|
USER="${REPO_NAME:-"default_repo"}"
|
||||||
|
# Convert to lowercase
|
||||||
|
USER="${USER,,}"
|
||||||
|
${PYTHON} "$SETUP_PATH/gen_config_docker.py" --db_port 5432 --db_user $USER --deploy_path "$DEPLOY_PATH" \
|
||||||
|
--image "${ODOO_IMAGE}" --container "${ODOO_CONTAINER}" --tag "${ODOO_TAG:=latest}" \
|
||||||
|
--addons "${ODOO_ADDONS}" --config "${ODOO_CONFIG}" --backup "${ODOO_BACKUP}"
|
||||||
|
Show 0 " Generate Config Complete"
|
||||||
|
}
|
||||||
|
Generate_Config_Native(){
|
||||||
|
DB_USER=${2:-}
|
||||||
|
DB_PASSWORD=${3:-}
|
||||||
|
DB_SERVER=${4:-}
|
||||||
|
DB_PORT=${5:-}
|
||||||
|
ADDONS=${1:-}
|
||||||
|
REPO_NAME=$(basename "$(git rev-parse --show-toplevel)" | sed -E 's/[.-]/_/g')
|
||||||
|
USER="${REPO_NAME:-"default_repo"}"
|
||||||
|
# Convert to lowercase
|
||||||
|
USER="${USER,,}"
|
||||||
|
PASSWORD="$(openssl rand -hex 24)"
|
||||||
|
# Check if the user already exists
|
||||||
|
USER_EXISTS=$(psql "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_SERVER}:${DB_PORT}/postgres" -t -A -c "SELECT COUNT(*) FROM pg_roles WHERE rolname='$USER';")
|
||||||
|
|
||||||
|
if [ $USER_EXISTS -eq 0 ]; then
|
||||||
|
# User does not exist, create the user
|
||||||
|
Show 2 "Create the new PostgreSQL username: $USER with password: $PASSWORD"
|
||||||
|
psql "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_SERVER}:${DB_PORT}/postgres" -c "CREATE USER $USER WITH PASSWORD '$PASSWORD';"
|
||||||
|
Show 2 "Grant $USER superuser (admin) privileges"
|
||||||
|
psql "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_SERVER}:${DB_PORT}/postgres" -c "ALTER USER $USER WITH SUPERUSER;"
|
||||||
|
else
|
||||||
|
# User exists, update the password (do not try to create)
|
||||||
|
Show 2 "User $USER already exists, updating password to $PASSWORD"
|
||||||
|
psql "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_SERVER}:${DB_PORT}/postgres" -c "ALTER USER $USER WITH PASSWORD '$PASSWORD';"
|
||||||
|
fi
|
||||||
|
${PYTHON} "$SETUP_PATH/gen_config.py" --db_user $USER --db_pass $PASSWORD --deploy_path "$(pwd)" \
|
||||||
|
--addons_path $ADDONS --db_port $DB_PORT --db_server $DB_SERVER
|
||||||
|
Show 0 " Generate Config Complete"
|
||||||
|
}
|
||||||
|
main(){
|
||||||
|
TYPE=${1:-}
|
||||||
|
Check_OS
|
||||||
|
# Update_Package_Resource
|
||||||
|
# Install_Depends
|
||||||
|
# Check_Dependency_Installation
|
||||||
|
# Check_Docker_Install
|
||||||
|
case "$TYPE" in
|
||||||
|
--native)
|
||||||
|
Generate_Config_Native $2 $3 $4 $5 $6
|
||||||
|
;;
|
||||||
|
--docker)
|
||||||
|
Generate_Config_Docker $2 $3 $4
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# else
|
||||||
|
Show 1 "Invalid argument (--docker|--native)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
44
setup/merge_module.py
Executable file
44
setup/merge_module.py
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
import subprocess
|
||||||
|
import yaml
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
# Set up argument parsing
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Checkout modules from target branch that are not in source branch."
|
||||||
|
)
|
||||||
|
parser.add_argument("yaml_file", help="Path to the YAML file")
|
||||||
|
parser.add_argument("source_branch", help="The source branch")
|
||||||
|
parser.add_argument("target_branch", help="The target branch")
|
||||||
|
parser.add_argument("root_repo", help="Path to the root repository")
|
||||||
|
|
||||||
|
# Parse the arguments
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
yaml_file = args.yaml_file
|
||||||
|
source_branch = args.source_branch
|
||||||
|
target_branch = args.target_branch
|
||||||
|
root_repo = args.root_repo
|
||||||
|
|
||||||
|
# Change to the repository directory
|
||||||
|
os.chdir(root_repo)
|
||||||
|
# Read YAML file
|
||||||
|
with open(yaml_file, "r") as file:
|
||||||
|
data = yaml.safe_load(file)
|
||||||
|
|
||||||
|
# Extract module lists for source and target branches
|
||||||
|
modules_source = data["branches"].get(source_branch, {}).get("modules", [])
|
||||||
|
modules_target = data["branches"].get(target_branch, {}).get("modules", [])
|
||||||
|
|
||||||
|
# Ensure the latest changes are fetched
|
||||||
|
subprocess.run(["git", "fetch", "origin"], check=True)
|
||||||
|
|
||||||
|
# Checkout source branch first
|
||||||
|
print(f"Checking out source branch: {source_branch}")
|
||||||
|
subprocess.run(["git", "checkout", source_branch], check=True)
|
||||||
|
|
||||||
|
# Checkout modules in target_branch that are not in source_branch
|
||||||
|
for module in modules_target:
|
||||||
|
if module not in modules_source:
|
||||||
|
print(f"Checking out module: {module}")
|
||||||
|
subprocess.run(["git", "checkout", target_branch, "--", module], check=True)
|
33
setup/migrate-lang.sh
Executable file
33
setup/migrate-lang.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Set source and destination repositories
|
||||||
|
SRC_REPO="/root/dev/NextERP/dev/Viindoo/odoo-18.0"
|
||||||
|
DEST_REPO="/root/dev/NextERP/dev/odoo18/Odoo18"
|
||||||
|
LANG="vi"
|
||||||
|
# Ensure both paths exist
|
||||||
|
if [ ! -d "$SRC_REPO" ]; then
|
||||||
|
echo "Error: Source repository does not exist!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$DEST_REPO" ]; then
|
||||||
|
echo "Error: Destination repository does not exist!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find and copy vi.po files while preserving directory structure
|
||||||
|
cd "$SRC_REPO" || exit
|
||||||
|
find . -type f -name "${LANG}.po" | while read -r file; do
|
||||||
|
# Get the directory path of the file
|
||||||
|
dir_path=$(dirname "$file")
|
||||||
|
|
||||||
|
# Ensure the destination directory exists
|
||||||
|
mkdir -p "$DEST_REPO/$dir_path"
|
||||||
|
|
||||||
|
# Copy the file
|
||||||
|
cp "$file" "$DEST_REPO/$dir_path/"
|
||||||
|
|
||||||
|
echo "Copied: $file -> $DEST_REPO/$dir_path/"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "All ${LANG}.po files copied successfully!"
|
82
setup/modules_scan.sh
Executable file
82
setup/modules_scan.sh
Executable file
@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if required arguments are provided
|
||||||
|
if [ $# -lt 3 ] || [ $# -gt 4 ]; then
|
||||||
|
echo "Usage: $0 <input_file> <root_folder> <output_yaml_file> [list_branch]"
|
||||||
|
echo "Example: $0 exclude_list.txt /path/to/git/repo /path/to/output.yaml 'branch1 branch2'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
INPUT_FILE="$1"
|
||||||
|
ROOT_FOLDER="$2"
|
||||||
|
OUTPUT_FILE="$3"
|
||||||
|
LIST_BRANCH="$4"
|
||||||
|
|
||||||
|
# Check if input file exists
|
||||||
|
if [ ! -f "$INPUT_FILE" ]; then
|
||||||
|
echo "Error: Input file '$INPUT_FILE' not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if root folder exists
|
||||||
|
if [ ! -d "$ROOT_FOLDER" ]; then
|
||||||
|
echo "Error: Root folder '$ROOT_FOLDER' not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if output YAML file exists, if not create it
|
||||||
|
if [ ! -f "$OUTPUT_FILE" ]; then
|
||||||
|
echo "Output file does not exist. Creating $OUTPUT_FILE"
|
||||||
|
touch "$OUTPUT_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Change to root folder
|
||||||
|
cd "$ROOT_FOLDER" || exit 1
|
||||||
|
|
||||||
|
# Initialize output file
|
||||||
|
echo "branches:" > "$OUTPUT_FILE"
|
||||||
|
|
||||||
|
# Get all git branches
|
||||||
|
git fetch --all
|
||||||
|
if [ -z "$LIST_BRANCH" ]; then
|
||||||
|
branches=$(git branch -r | grep -v HEAD | sed 's/origin\///' | sed 's/^[[:space:]]*//')
|
||||||
|
else
|
||||||
|
branches=$LIST_BRANCH
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process each branch
|
||||||
|
for branch in $branches; do
|
||||||
|
echo "Processing branch: $branch"
|
||||||
|
|
||||||
|
# Checkout branch
|
||||||
|
git checkout "$branch" 2>/dev/null || continue
|
||||||
|
|
||||||
|
# Get all folders in current branch
|
||||||
|
folders=$(find . -maxdepth 1 -type d -not -path '.' -not -path './.*' | sed 's|./||')
|
||||||
|
|
||||||
|
# Array to store modules not in input file
|
||||||
|
modules=()
|
||||||
|
|
||||||
|
# Check each folder against input file
|
||||||
|
while IFS= read -r folder; do
|
||||||
|
# Skip if folder is empty
|
||||||
|
[ -z "$folder" ] && continue
|
||||||
|
|
||||||
|
# Check if folder is in input file
|
||||||
|
if ! grep -Fxq "$folder" "$INPUT_FILE"; then
|
||||||
|
modules+=("$folder")
|
||||||
|
fi
|
||||||
|
done <<< "$folders"
|
||||||
|
|
||||||
|
# Write to yaml if there are modules
|
||||||
|
if [ ${#modules[@]} -gt 0 ]; then
|
||||||
|
echo " $branch:" >> "$OUTPUT_FILE"
|
||||||
|
echo " modules:" >> "$OUTPUT_FILE"
|
||||||
|
for module in "${modules[@]}"; do
|
||||||
|
echo " - $module" >> "$OUTPUT_FILE"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Output written to $OUTPUT_FILE"
|
Loading…
Reference in New Issue
Block a user