test/lib/plane.sh

486 lines
13 KiB
Bash

#!/bin/bash
#
# Plane Service
PATH=$HOME/.docker/cli-plugins:/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# FIXME plane's nginx proxy has a few additional rules that we may
# need to port to Traefik:
# add_header X-Content-Type-Options "nosniff" always;
# add_header Referrer-Policy "no-referrer-when-downgrade" always;
# add_header Permissions-Policy "interest-cohort=()" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# add_header X-Forwarded-Proto "$scheme";
# add_header X-Forwarded-Host "$host";
# add_header X-Forwarded-For "$proxy_add_x_forwarded_for";
# add_header X-Real-IP "$remote_addr";
config_plane() {
echo -ne "\n* Configuring /federated/apps/plane container.."
if [ ! -d "/federated/apps/plane" ]; then
mkdir -p /federated/apps/plane/data/plane &> /dev/null
fi
POSTGRES_PASSWORD=$(create_password)
USE_TRAEFIK=true
cat >/federated/apps/plane/plane.env <<'EOF'
APP_DOMAIN=plane.@DOMAIN@
APP_RELEASE=stable
WEB_REPLICAS=1
SPACE_REPLICAS=1
ADMIN_REPLICAS=1
API_REPLICAS=1
NGINX_PORT=80
WEB_URL=http://${APP_DOMAIN}
DEBUG=0
SENTRY_DSN=
SENTRY_ENVIRONMENT=production
CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}
API_BASE_URL=http://api:8000
#DB SETTINGS
PGHOST=postgresql
PGDATABASE=plane
POSTGRES_USER=plane
POSTGRES_PASSWORD=@POSTGRES_PASSWORD@
POSTGRES_DB=plane
POSTGRES_PORT=5432
PGDATA=/var/lib/postgresql/data
DATABASE_URL=
# REDIS SETTINGS
REDIS_HOST=plane-redis
REDIS_PORT=6379
REDIS_URL=
# RabbitMQ Settings
RABBITMQ_HOST=plane-mq
RABBITMQ_PORT=5672
RABBITMQ_USER=plane
RABBITMQ_PASSWORD=plane
RABBITMQ_VHOST=plane
AMQP_URL=
# Secret Key
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
# DATA STORE SETTINGS
USE_MINIO=1
AWS_REGION=
AWS_ACCESS_KEY_ID=access-key
AWS_SECRET_ACCESS_KEY=secret-key
AWS_S3_ENDPOINT_URL=http://plane-minio:9000
AWS_S3_BUCKET_NAME=uploads
MINIO_ROOT_USER=access-key
MINIO_ROOT_PASSWORD=secret-key
BUCKET_NAME=uploads
FILE_SIZE_LIMIT=5242880
# Gunicorn Workers
GUNICORN_WORKERS=1
# UNCOMMENT `DOCKER_PLATFORM` IF YOU ARE ON `ARM64` AND DOCKER IMAGE IS NOT AVAILABLE FOR RESPECTIVE `APP_RELEASE`
# DOCKER_PLATFORM=linux/amd64
DOCKERHUB_USER=makeplane
PULL_POLICY=if_not_present
CUSTOM_BUILD=false
EOF
cat > /federated/apps/plane/docker-compose.yml <<'EOF'
x-app-env: &app-env
environment:
- NGINX_PORT=${NGINX_PORT:-80}
- WEB_URL=${WEB_URL:-http://localhost}
- DEBUG=${DEBUG:-0}
- SENTRY_DSN=${SENTRY_DSN:-""}
- SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT:-"production"}
- CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGINS:-}
# Gunicorn Workers
- GUNICORN_WORKERS=${GUNICORN_WORKERS:-1}
#DB SETTINGS
- PGHOST=${PGHOST:-postgresql}
- PGDATABASE=${PGDATABASE:-plane}
- POSTGRES_USER=${POSTGRES_USER:-plane}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-@POSTGRES_PASSWORD@}
- POSTGRES_DB=${POSTGRES_DB:-plane}
- POSTGRES_PORT=${POSTGRES_PORT:-5432}
- PGDATA=${PGDATA:-/var/lib/postgresql/data}
- DATABASE_URL=${DATABASE_URL:-postgresql://plane:@POSTGRES_PASSWORD@@postgresql/plane}
# REDIS SETTINGS
- REDIS_HOST=${REDIS_HOST:-plane-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_URL=${REDIS_URL:-redis://plane-redis:6379/}
# RabbitMQ Settings
- RABBITMQ_HOST=${RABBITMQ_HOST:-plane-mq}
- RABBITMQ_PORT=${RABBITMQ_PORT:-5672}
- RABBITMQ_DEFAULT_USER=${RABBITMQ_USER:-plane}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD:-plane}
- RABBITMQ_DEFAULT_VHOST=${RABBITMQ_VHOST:-plane}
- RABBITMQ_VHOST=${RABBITMQ_VHOST:-plane}
- AMQP_URL=${AMQP_URL:-amqp://plane:plane@plane-mq:5672/plane}
# Application secret
- SECRET_KEY=${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
# DATA STORE SETTINGS
- USE_MINIO=${USE_MINIO:-1}
- AWS_REGION=${AWS_REGION:-}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-"access-key"}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-"secret-key"}
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
- MINIO_ROOT_USER=${MINIO_ROOT_USER:-"access-key"}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-"secret-key"}
- BUCKET_NAME=${BUCKET_NAME:-uploads}
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
# Live server env
- API_BASE_URL=${API_BASE_URL:-http://api:8000}
services:
web:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-frontend:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
expose:
- 3000
ports:
- 3000:3000
env_file:
- ./plane.env
EOF
if $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`plane.@DOMAIN@`)"
- "traefik.http.routers.web.entrypoints=websecure"
- "traefik.http.routers.web.tls.certresolver=letsencrypt"
- "traefik.http.services.web.loadbalancer.server.port=3000"
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
networks:
core:
ipv4_address: 192.168.0.50
pull_policy: if_not_present
restart: unless-stopped
command: node web/server.js web
deploy:
replicas: ${WEB_REPLICAS:-1}
depends_on:
- api
- worker
space:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-space:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.51
EOF
if $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
labels:
- "traefik.enable=true"
- "traefik.http.routers.space.rule=Host(`plane.@DOMAIN@`) && PathPrefix(`/spaces`)"
- "traefik.http.routers.space.entrypoints=websecure"
- "traefik.http.routers.space.tls.certresolver=letsencrypt"
- "traefik.http.services.space.loadbalancer.server.port=3000"
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
pull_policy: if_not_present
restart: unless-stopped
command: node space/server.js space
deploy:
replicas: ${SPACE_REPLICAS:-1}
depends_on:
- api
- worker
- web
admin:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-admin:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.52
EOF
if $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
labels:
- "traefik.enable=true"
- "traefik.http.routers.admin.rule=Host(`plane.@DOMAIN@`) && PathPrefix(`/god-mode`)"
- "traefik.http.routers.admin.entrypoints=websecure"
- "traefik.http.routers.admin.tls.certresolver=letsencrypt"
- "traefik.http.services.admin.loadbalancer.server.port=3000"
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
pull_policy: if_not_present
restart: unless-stopped
command: node admin/server.js admin
deploy:
replicas: ${ADMIN_REPLICAS:-1}
depends_on:
- api
- web
live:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-live:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.53
EOF
if $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
labels:
- "traefik.enable=true"
- "traefik.http.routers.live.rule=Host(`plane.@DOMAIN@`) && PathPrefix(`/live`)"
- "traefik.http.routers.live.entrypoints=websecure"
- "traefik.http.routers.live.tls.certresolver=letsencrypt"
- "traefik.http.services.live.loadbalancer.server.port=3000"
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
pull_policy: if_not_present
restart: unless-stopped
command: node live/dist/server.js live
deploy:
replicas: ${LIVE_REPLICAS:-1}
depends_on:
- api
- web
api:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.54
EOF
if $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`plane.@DOMAIN@`) && (PathPrefix(`/api`) || PathPrefix(`/auth`))"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
pull_policy: if_not_present
restart: unless-stopped
command: ./bin/docker-entrypoint-api.sh
deploy:
replicas: ${API_REPLICAS:-1}
volumes:
- logs_api:/code/plane/logs
depends_on:
- plane-redis
- plane-mq
worker:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.55
pull_policy: if_not_present
restart: unless-stopped
command: ./bin/docker-entrypoint-worker.sh
volumes:
- logs_worker:/code/plane/logs
depends_on:
- api
- plane-redis
- plane-mq
beat-worker:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.56
pull_policy: if_not_present
restart: unless-stopped
command: ./bin/docker-entrypoint-beat.sh
volumes:
- logs_beat-worker:/code/plane/logs
depends_on:
- api
- plane-redis
- plane-mq
migrator:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
platform: ${DOCKER_PLATFORM:-}
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.57
pull_policy: if_not_present
restart: "no"
command: ./bin/docker-entrypoint-migrator.sh
volumes:
- logs_migrator:/code/plane/logs
depends_on:
- plane-redis
plane-redis:
<<: *app-env
image: valkey/valkey:7.2.5-alpine
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.58
pull_policy: if_not_present
restart: unless-stopped
volumes:
- redisdata:/data
plane-mq:
<<: *app-env
image: rabbitmq:3.13.6-management-alpine
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.59
restart: always
volumes:
- rabbitmq_data:/var/lib/rabbitmq
plane-minio:
<<: *app-env
image: minio/minio:latest
env_file:
- ./plane.env
networks:
core:
ipv4_address: 192.168.0.60
EOF
if $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
labels:
- "traefik.enable=true"
- "traefik.http.routers.uploads.rule=Host(`plane.@DOMAIN@`) && PathPrefix(`/uploads`)"
- "traefik.http.routers.uploads.entrypoints=websecure"
- "traefik.http.routers.uploads.tls.certresolver=letsencrypt"
- "traefik.http.services.uploads.loadbalancer.server.port=9000"
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
pull_policy: if_not_present
restart: unless-stopped
command: server /export --console-address ":9090"
volumes:
- uploads:/export
EOF
if ! $USE_TRAEFIK; then
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
proxy:
<<: *app-env
image: ${DOCKERHUB_USER:-makeplane}/plane-proxy:${APP_RELEASE:-stable}
env_file:
- ./plane.env
platform: ${DOCKER_PLATFORM:-}
pull_policy: if_not_present
restart: unless-stopped
ports:
- ${NGINX_PORT}:80
depends_on:
- web
- api
- space
EOF
fi
cat >> /federated/apps/plane/docker-compose.yml <<'EOF'
volumes:
redisdata:
uploads:
logs_api:
logs_worker:
logs_beat-worker:
logs_migrator:
rabbitmq_data:
networks:
core:
external: true
EOF
sed -i -e "s,@DOMAIN@,${DOMAIN},g" \
-e "s,@POSTGRES_PASSWORD@,${POSTGRES_PASSWORD},g" \
/federated/apps/plane/docker-compose.yml \
/federated/apps/plane/plane.env
set -x
# Create database and user in postgresql
docker exec postgresql psql -U postgres -c "CREATE DATABASE plane" &> /dev/null
docker exec postgresql psql -U postgres -c "CREATE USER plane WITH PASSWORD '${POSTGRES_PASSWORD}'" &> /dev/null
docker exec postgresql psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE plane TO plane" &> /dev/null
set +x
unset POSTGRES_PASSWORD
cat > /federated/apps/plane/.env <<EOF
#IMAGE_VERSION="v1.11.33"
EOF
chmod 600 /federated/apps/plane/.env
echo -ne "done."
}
start_plane() {
# Start service with command to make sure it's up before proceeding
# start_service "plane" "nc -z 192.168.0.48 80 &> /dev/null" "7"
echo -ne "done."
}
uninstall_plane() {
docker exec postgresql psql -U postgres -c "DROP DATABASE plane" &> /dev/null
docker exec postgresql psql -U postgres -c "DROP USER plane" &> /dev/null
}