From ab8359365d0f6b930e879251d9f6cb2d9abbe4c2 Mon Sep 17 00:00:00 2001 From: Josako Date: Tue, 6 Aug 2024 14:56:12 +0200 Subject: [PATCH] - Getting containers ready for the cloud --- common/extensions.py | 7 +- common/utils/simple_encryption.py | 39 ++++++ config/config.py | 140 ++++++++++----------- docker/build_tag_and_push.sh | 81 ++++++++++++ docker/{compose.yaml => compose_dev.yaml} | 34 ++++- docker/compose_stackhero.yaml | 123 ++++++++++++++++++ docker/docker_env_switch.sh | 57 +++++++++ docker/stackhero_link.sh | 14 +++ eveai_app/__init__.py | 27 ++-- eveai_app/templates/header.html | 2 +- eveai_app/views/user_views.py | 4 +- eveai_chat/__init__.py | 21 ++-- eveai_chat/socket_handlers/chat_handler.py | 4 +- eveai_chat_workers/__init__.py | 15 ++- eveai_workers/__init__.py | 15 ++- nginx/public/chat_eveai_mini.html | 2 +- nginx/static/assets/css/eveai.css | 10 ++ nginx/static/assets/img/EveAI_bg.jpg | Bin 0 -> 2436987 bytes requirements.txt | 3 +- scripts/generate_api_key_secret.py | 6 + 20 files changed, 494 insertions(+), 110 deletions(-) create mode 100644 common/utils/simple_encryption.py create mode 100755 docker/build_tag_and_push.sh rename docker/{compose.yaml => compose_dev.yaml} (82%) create mode 100644 docker/compose_stackhero.yaml create mode 100755 docker/docker_env_switch.sh create mode 100755 docker/stackhero_link.sh create mode 100644 nginx/static/assets/img/EveAI_bg.jpg create mode 100644 scripts/generate_api_key_secret.py diff --git a/common/extensions.py b/common/extensions.py index c727a0c..f36134b 100644 --- a/common/extensions.py +++ b/common/extensions.py @@ -10,7 +10,8 @@ from flask_jwt_extended import JWTManager from flask_session import Session from flask_wtf import CSRFProtect -from .utils.key_encryption import JosKMSClient +# from .utils.key_encryption import JosKMSClient +from .utils.simple_encryption import SimpleEncryption from .utils.minio_utils import MinioClient # Create extensions @@ -26,5 +27,7 @@ socketio = SocketIO() jwt = JWTManager() session = Session() -kms_client = JosKMSClient.from_service_account_json('config/gc_sa_eveai.json') +# kms_client = JosKMSClient.from_service_account_json('config/gc_sa_eveai.json') + +simple_encryption = SimpleEncryption() minio_client = MinioClient() diff --git a/common/utils/simple_encryption.py b/common/utils/simple_encryption.py new file mode 100644 index 0000000..d3ec947 --- /dev/null +++ b/common/utils/simple_encryption.py @@ -0,0 +1,39 @@ +from cryptography.fernet import Fernet +from flask import Flask + + +class SimpleEncryption: + def __init__(self, app: Flask = None): + self.app = app + self.fernet = None + if app is not None: + self.init_app(app) + + def init_app(self, app: Flask): + self.app = app + encryption_key = app.config.get('API_ENCRYPTION_KEY') + if not encryption_key: + raise ValueError("ENCRYPTION_KEY is not set in the app configuration") + self.fernet = Fernet(encryption_key.encode()) + + # Optionally log the initialization (similar to your current setup) + app.logger.info('SimpleEncryption initialized') + + def encrypt_api_key(self, api_key: str) -> str: + if not self.fernet: + raise RuntimeError("SimpleEncryption is not initialized. Call init_app first.") + return self.fernet.encrypt(api_key.encode()).decode() + + def decrypt_api_key(self, encrypted_api_key: str) -> str: + if not self.fernet: + raise RuntimeError("SimpleEncryption is not initialized. Call init_app first.") + return self.fernet.decrypt(encrypted_api_key.encode()).decode() + + @staticmethod + def generate_key() -> str: + """Generate a new Fernet key.""" + return Fernet.generate_key().decode() + +# Usage: +# from common.utils.simple_encryption import simple_encryption +# simple_encryption.init_app(app) diff --git a/config/config.py b/config/config.py index 7c2bd79..f9f3ab6 100644 --- a/config/config.py +++ b/config/config.py @@ -10,7 +10,7 @@ basedir = path.abspath(path.dirname(__file__)) class Config(object): DEBUG = False DEVELOPMENT = False - SECRET_KEY = '97867c1491bea5ee6a8e8436eb11bf2ba6a69ff53ab1b17ecba450d0f2e572e1' + SECRET_KEY = environ.get('SECRET_KEY') SESSION_COOKIE_SECURE = False SESSION_COOKIE_HTTPONLY = True @@ -29,7 +29,7 @@ class Config(object): # SECURITY_POST_RESET_VIEW = '/admin/login' # SECURITY_POST_CHANGE_VIEW = '/admin/login' # SECURITY_BLUEPRINT_NAME = 'security_bp' - SECURITY_PASSWORD_SALT = '228614859439123264035565568761433607235' + SECURITY_PASSWORD_SALT = environ.get('SECURITY_PASSWORD_SALT') REMEMBER_COOKIE_SAMESITE = 'strict' SESSION_COOKIE_SAMESITE = 'strict' SECURITY_CONFIRMABLE = True @@ -45,13 +45,6 @@ class Config(object): SECURITY_CSRF_HEADER = 'X-XSRF-TOKEN' WTF_CSRF_CHECK_DEFAULT = False - # flask-mailman settings - MAIL_SERVER = 'mail.flow-it.net' - MAIL_PORT = 587 - MAIL_USE_TLS = True - MAIL_USE_SSL = False - MAIL_DEFAULT_SENDER = ('eveAI Admin', 'eveai_admin@flow-it.net') - # file upload settings MAX_CONTENT_LENGTH = 16 * 1024 * 1024 UPLOAD_EXTENSIONS = ['.txt', '.pdf', '.png', '.jpg', '.jpeg', '.gif'] @@ -75,6 +68,18 @@ class Config(object): 'anthropic.claude-3-5-sonnet': 8000 } + # OpenAI API Keys + OPENAI_API_KEY = environ.get('OPENAI_API_KEY') + + # Groq API Keys + GROQ_API_KEY = environ.get('GROQ_API_KEY') + + # Anthropic API Keys + ANTHROPIC_API_KEY = environ.get('ANTHROPIC_API_KEY') + + # Portkey API Keys + PORTKEY_API_KEY = environ.get('PORTKEY_API_KEY') + # Celery settings CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' @@ -93,6 +98,12 @@ class Config(object): PERMANENT_SESSION_LIFETIME = timedelta(minutes=60) SESSION_REFRESH_EACH_REQUEST = True + # JWT settings + JWT_SECRET_KEY = environ.get('JWT_SECRET_KEY') + + # API Encryption + API_ENCRYPTION_KEY = environ.get('API_ENCRYPTION_KEY') + # Fallback Algorithms FALLBACK_ALGORITHMS = [ "RAG_TENANT", @@ -115,25 +126,31 @@ class DevConfig(Config): DEBUG = True FLASK_DEBUG = True PYCHARM_DEBUG = False + EXPLAIN_TEMPLATE_LOADING = False + + # Database Settings DB_HOST = environ.get('DB_HOST', 'localhost') DB_USER = environ.get('DB_USER', 'luke') DB_PASS = environ.get('DB_PASS', 'Skywalker!') DB_NAME = environ.get('DB_NAME', 'eveai') - SQLALCHEMY_DATABASE_URI = f'postgresql+pg8000://{DB_USER}:{DB_PASS}@{DB_HOST}:5432/{DB_NAME}' SQLALCHEMY_BINDS = {'public': SQLALCHEMY_DATABASE_URI} - EXPLAIN_TEMPLATE_LOADING = False + + # flask-mailman settings + MAIL_SERVER = 'mail.flow-it.net' + MAIL_PORT = 587 + MAIL_USE_TLS = True + MAIL_USE_SSL = False + MAIL_DEFAULT_SENDER = ('eveAI Admin', 'eveai_admin@flow-it.net') + MAIL_USERNAME = environ.get('MAIL_USERNAME') + MAIL_PASSWORD = environ.get('MAIL_PASSWORD') # Define the nginx prefix used for the specific apps EVEAI_APP_LOCATION_PREFIX = '/admin' EVEAI_CHAT_LOCATION_PREFIX = '/chat' - # flask-mailman settings - MAIL_USERNAME = 'eveai_super@flow-it.net' - MAIL_PASSWORD = '$6xsWGbNtx$CFMQZqc*' - # file upload settings - UPLOAD_FOLDER = '/app/tenant_files' + # UPLOAD_FOLDER = '/app/tenant_files' # Celery settings # eveai_app Redis Settings @@ -143,22 +160,10 @@ class DevConfig(Config): CELERY_BROKER_URL_CHAT = 'redis://redis:6379/3' CELERY_RESULT_BACKEND_CHAT = 'redis://redis:6379/3' - # OpenAI API Keys - OPENAI_API_KEY = 'sk-proj-8R0jWzwjL7PeoPyMhJTZT3BlbkFJLb6HfRB2Hr9cEVFWEhU7' - - # Groq API Keys - GROQ_API_KEY = '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' - - # Anthropic API Keys - ANTHROPIC_API_KEY = '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' - - # Portkey API Keys - PORTKEY_API_KEY = 'T2Dt4QTpgCvWxa1OftYCJtj7NcDZ' - # Unstructured settings - UNSTRUCTURED_API_KEY = 'pDgCrXumYhM3CNvjvwV8msMldXC3uw' - UNSTRUCTURED_BASE_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io' - UNSTRUCTURED_FULL_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io/general/v0/general' + # UNSTRUCTURED_API_KEY = 'pDgCrXumYhM3CNvjvwV8msMldXC3uw' + # UNSTRUCTURED_BASE_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io' + # UNSTRUCTURED_FULL_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io/general/v0/general' # SocketIO settings SOCKETIO_MESSAGE_QUEUE = 'redis://redis:6379/1' @@ -176,9 +181,6 @@ class DevConfig(Config): GC_KEY_RING = 'eveai-chat' GC_CRYPTO_KEY = 'envelope-encryption-key' - # JWT settings - JWT_SECRET_KEY = 'bsdMkmQ8ObfMD52yAFg4trrvjgjMhuIqg2fjDpD/JqvgY0ccCcmlsEnVFmR79WPiLKEA3i8a5zmejwLZKl4v9Q==' - # Session settings SESSION_REDIS = redis.from_url('redis://redis:6379/2') @@ -194,19 +196,28 @@ class DevConfig(Config): class ProdConfig(Config): DEVELOPMENT = False DEBUG = False - DEVELOPMENT = True - DEBUG = True - FLASK_DEBUG = True + DEBUG = False + FLASK_DEBUG = False PYCHARM_DEBUG = False - DB_HOST = environ.get('DB_HOST', 'bswnz4.stackhero-network.com') - DB_USER = environ.get('DB_USER', 'luke_skywalker') - DB_PASS = environ.get('DB_PASS', '2MK&1rHmWEydE2rFuJLq*ls%tdkPAk2') - DB_NAME = environ.get('DB_NAME', 'eveai') - DB_PORT = environ.get('DB_PORT', '5945') + EXPLAIN_TEMPLATE_LOADING = False + # Database Settings + DB_HOST = environ.get('DB_HOST') + DB_USER = environ.get('DB_USER') + DB_PASS = environ.get('DB_PASS') + DB_NAME = environ.get('DB_NAME') + DB_PORT = environ.get('DB_PORT') SQLALCHEMY_DATABASE_URI = f'postgresql+pg8000://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}' SQLALCHEMY_BINDS = {'public': SQLALCHEMY_DATABASE_URI} - EXPLAIN_TEMPLATE_LOADING = False + + # flask-mailman settings + MAIL_SERVER = 'mail.askeveai.com' + MAIL_PORT = 587 + MAIL_USE_TLS = True + MAIL_USE_SSL = False + MAIL_DEFAULT_SENDER = ('Evie Admin', 'evie_admin@askeveai.com') + MAIL_USERNAME = environ.get('MAIL_USERNAME') + MAIL_PASSWORD = environ.get('MAIL_PASSWORD') # Define the nginx prefix used for the specific apps EVEAI_APP_LOCATION_PREFIX = '/admin' @@ -217,12 +228,13 @@ class ProdConfig(Config): MAIL_PASSWORD = '$6xsWGbNtx$CFMQZqc*' # file upload settings - UPLOAD_FOLDER = '/app/tenant_files' + # UPLOAD_FOLDER = '/app/tenant_files' - REDIS_USER = 'admin' - REDIS_PASS = 'b32vtDtLriSY1fL2zGrZg8IZKI0g9ucsLtVNanRFAras6oZ51wjVNB1Y05uG7uEw' - REDIS_URL = '8bciqc.stackhero-network.com' - REDIS_PORT = '9961' + # Redis Settings + REDIS_USER = environ.get('REDIS_USER') + REDIS_PASS = environ.get('REDIS_PASS') + REDIS_URL = environ.get('REDIS_URL') + REDIS_PORT = environ.get('REDIS_PORT', '6379') REDIS_BASE_URI = f'redis://{REDIS_USER}:{REDIS_PASS}@{REDIS_URL}:{REDIS_PORT}' # Celery settings @@ -236,23 +248,6 @@ class ProdConfig(Config): # Session settings SESSION_REDIS = redis.from_url(f'{REDIS_BASE_URI}/2') - # OpenAI API Keys - OPENAI_API_KEY = 'sk-proj-8R0jWzwjL7PeoPyMhJTZT3BlbkFJLb6HfRB2Hr9cEVFWEhU7' - - # Groq API Keys - GROQ_API_KEY = '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' - - # Anthropic API Keys - ANTHROPIC_API_KEY = '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' - - # Portkey API Keys - PORTKEY_API_KEY = 'T2Dt4QTpgCvWxa1OftYCJtj7NcDZ' - - # Unstructured settings - UNSTRUCTURED_API_KEY = 'pDgCrXumYhM3CNvjvwV8msMldXC3uw' - UNSTRUCTURED_BASE_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io' - UNSTRUCTURED_FULL_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io/general/v0/general' - # SocketIO settings SOCKETIO_MESSAGE_QUEUE = f'{REDIS_BASE_URI}/1' SOCKETIO_CORS_ALLOWED_ORIGINS = '*' @@ -269,15 +264,14 @@ class ProdConfig(Config): GC_KEY_RING = 'eveai-chat' GC_CRYPTO_KEY = 'envelope-encryption-key' - # JWT settings - JWT_SECRET_KEY = 'bsdMkmQ8ObfMD52yAFg4trrvjgjMhuIqg2fjDpD/JqvgY0ccCcmlsEnVFmR79WPiLKEA3i8a5zmejwLZKl4v9Q==' - # PATH settings ffmpeg_path = '/usr/bin/ffmpeg' -config = { - 'dev': DevConfig(), - 'prod': ProdConfig(), - 'default': DevConfig(), -} +def get_config(config_name='dev'): + configs = { + 'dev': DevConfig, + 'prod': ProdConfig, + 'default': DevConfig, + } + return configs.get(config_name) diff --git a/docker/build_tag_and_push.sh b/docker/build_tag_and_push.sh new file mode 100755 index 0000000..286e9d0 --- /dev/null +++ b/docker/build_tag_and_push.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# Source the environment setup script +if [ -f "./docker_env_switch.sh" ]; then + source ./docker_env_switch.sh dev +else + echo "Error: set_environment.sh not found in the current directory." + exit 1 +fi + +# Docker Hub username +USERNAME="josakola" + +# List of all your services +ALL_SERVICES=("eveai_app" "eveai_workers" "eveai_chat" "eveai_chat_workers" "nginx") + +# Function to build, tag and push an image +build_tag_and_push() { + local service=$1 + echo "Building, tagging, and pushing ${service}..." + + # Extract dockerfile and context paths from Docker Compose configuration + local dockerfile_path + local context_path + + dockerfile_path=$(docker compose -f "$COMPOSE_FILE" config | grep "${service}" -A 10 | grep "dockerfile" | awk '{print $2}') + context_path=$(docker compose -f "$COMPOSE_FILE" config | grep "${service}" -A 10 | grep "context" | awk '{print $2}') + + # Verify the paths + echo "Dockerfile path: ${dockerfile_path}" + echo "Context path: ${context_path}" + + # Use docker buildx to build the image + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + -t "${USERNAME}/${service}:latest" \ + --push \ + --file "${dockerfile_path}" \ + "${context_path}" +} + +# Function to check if a service is in the ALL_SERVICES array +service_exists() { + local service=$1 + for s in "${ALL_SERVICES[@]}"; do + if [[ "$s" == "$service" ]]; then + return 0 + fi + done + return 1 +} + +# Ensure we're using buildx +docker buildx create --use + +# If COMPOSE_FILE is not set, use a default value +if [ -z "$COMPOSE_FILE" ]; then + COMPOSE_FILE="compose_dev.yaml" + echo "COMPOSE_FILE not set, using default: $COMPOSE_FILE" +else + echo "Using COMPOSE_FILE: $COMPOSE_FILE" +fi + +# If no arguments are provided, process all services +if [ $# -eq 0 ]; then + echo "No specific services provided. Processing all services..." + for service in "${ALL_SERVICES[@]}"; do + build_tag_and_push "$service" + done +else + # Process only the specified services + for service in "$@"; do + if service_exists "$service"; then + build_tag_and_push "$service" + else + echo "Warning: ${service} is not a recognized service name. Skipping." + fi + done +fi + +echo "Done!" diff --git a/docker/compose.yaml b/docker/compose_dev.yaml similarity index 82% rename from docker/compose.yaml rename to docker/compose_dev.yaml index 093d139..0354547 100644 --- a/docker/compose.yaml +++ b/docker/compose_dev.yaml @@ -11,17 +11,33 @@ x-common-variables: &common-variables DB_HOST: db DB_USER: luke - DB_PASS: Skywalker! + DB_PASS: 'Skywalker!' DB_NAME: eveai + DB_PORT: '5432' FLASK_ENV: development - FLASK_DEBUG: 1 + FLASK_DEBUG: true + SECRET_KEY: '97867c1491bea5ee6a8e8436eb11bf2ba6a69ff53ab1b17ecba450d0f2e572e1' + SECURITY_PASSWORD_SALT: '228614859439123264035565568761433607235' + MAIL_USERNAME: eveai_super@flow-it.net + MAIL_PASSWORD: '$6xsWGbNtx$CFMQZqc*' + OPENAI_API_KEY: 'sk-proj-8R0jWzwjL7PeoPyMhJTZT3BlbkFJLb6HfRB2Hr9cEVFWEhU7' + GROQ_API_KEY: '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' + ANTHROPIC_API_KEY: 'sk-ant-api03-c2TmkzbReeGhXBO5JxNH6BJNylRDonc9GmZd0eRbrvyekec2' + PORTKEY_API_KEY: 'T2Dt4QTpgCvWxa1OftYCJtj7NcDZ' + JWT_SECRET_KEY: 'bsdMkmQ8ObfMD52yAFg4trrvjgjMhuIqg2fjDpD/JqvgY0ccCcmlsEnVFmR79WPiLKEA3i8a5zmejwLZKl4v9Q==' + API_ENCRYPTION_KEY: 'xfF5369IsredSrlrYZqkM9ZNrfUASYYS6TCcAR9UKj4=' MINIO_ENDPOINT: minio:9000 MINIO_ACCESS_KEY: minioadmin MINIO_SECRET_KEY: minioadmin services: nginx: - image: nginx:latest + build: + context: ../nginx + dockerfile: Dockerfile + platforms: + - linux/amd64 + - linux/arm64 ports: - 80:80 - 8080:8080 @@ -39,6 +55,9 @@ services: build: context: .. dockerfile: ./docker/eveai_app/Dockerfile + platforms: + - linux/amd64 + - linux/arm64 ports: - 5001:5001 environment: @@ -69,6 +88,9 @@ services: build: context: .. dockerfile: ./docker/eveai_workers/Dockerfile + platforms: + - linux/amd64 + - linux/arm64 # ports: # - 5001:5001 environment: @@ -98,6 +120,9 @@ services: build: context: .. dockerfile: ./docker/eveai_chat/Dockerfile + platforms: + - linux/amd64 + - linux/arm64 ports: - 5002:5002 environment: @@ -125,6 +150,9 @@ services: build: context: .. dockerfile: ./docker/eveai_chat_workers/Dockerfile + platforms: + - linux/amd64 + - linux/arm64 # ports: # - 5001:5001 environment: diff --git a/docker/compose_stackhero.yaml b/docker/compose_stackhero.yaml new file mode 100644 index 0000000..905d122 --- /dev/null +++ b/docker/compose_stackhero.yaml @@ -0,0 +1,123 @@ +# Comments are provided throughout this file to help you get started. +# If you need more help, visit the Docker Compose reference guide at +# https://docs.docker.com/go/compose-spec-reference/ + +# Here the instructions define your application as a service called "server". +# This service is built from the Dockerfile in the current directory. +# You can add other services your application may depend on here, such as a +# database or a cache. For examples, see the Awesome Compose repository: +# https://github.com/docker/awesome-compose + +x-common-variables: &common-variables + DB_HOST: bswnz4.stackhero-network.com + DB_USER: luke_skywalker + DB_PASS: 2MK&1rHmWEydE2rFuJLq*ls%tdkPAk2 + DB_NAME: eveai + DB_PORT: '5945' + FLASK_ENV: production + FLASK_DEBUG: false + SECRET_KEY: '38wg8e1lvhlvcu0apr95n8o07axf244lzaa7b7djh7itrf8jnyyh1lkuco529w' + SECURITY_PASSWORD_SALT: '166448071751628781809462050022558634074' + MAIL_USERNAME: 'evie_admin@askeveai.com' + MAIL_PASSWORD: 's5D%R#y^v!s&6Z^i0k&' + REDIS_USER: admin + REDIS_PASS: 'b32vtDtLriSY1fL2zGrZg8IZKI0g9ucsLtVNanRFAras6oZ51wjVNB1Y05uG7uEw' + REDIS_URL: 8bciqc.stackhero-network.com + REDIS_PORT: '9961' + OPENAI_API_KEY: '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' + GROQ_API_KEY: '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' + ANTHROPIC_API_KEY: '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' + PORTKEY_API_KEY: '3C+zAGR8pCalevBXFVc0l8R2MPYc' + JWT_SECRET_KEY: '0d99e810e686ea567ef305d8e9b06195c4db482952e19276590a726cde60a408' + API_ENCRYPTION_KEY: 'Ly5XYWwEKiasfAwEqdEMdwR-k0vhrq6QPYd4whEROB0=' + +services: + nginx: + image: nginx:latest + ports: + - 80:80 + - 8080:8080 + volumes: + - ../nginx:/etc/nginx + - ../nginx/sites-enabled:/etc/nginx/sites-enabled + - ../nginx/static:/etc/nginx/static + - ../nginx/public:/etc/nginx/public + - ./logs/nginx:/var/log/nginx + labels: + - "traefik.enable=true" + - "traefik.http.routers.api.rule=Host(`evie.askeveai.com`)" + - "traefik.http.services.nginx.loadbalancer.server.port=80" + depends_on: + - eveai_app + - eveai_chat + + eveai_app: + image: josakola/eveai_app:latest + ports: + - 5001:5001 + environment: + <<: *common-variables + volumes: + - ./logs:/app/logs + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5001/health"] + interval: 10s + timeout: 5s + retries: 5 + command: ["sh", "-c", "scripts/start_eveai_app.sh"] + + eveai_workers: + image: josakola/eveai_workers:latest +# ports: +# - 5001:5001 + environment: + <<: *common-variables + volumes: + - ./logs:/app/logs +# healthcheck: +# test: [ "CMD", "curl", "-f", "http://localhost:5001/health" ] +# interval: 10s +# timeout: 5s +# retries: 5 + command: [ "sh", "-c", "scripts/start_eveai_workers.sh" ] + + eveai_chat: + image: josakola/eveai_chat:latest + ports: + - 5002:5002 + environment: + <<: *common-variables + volumes: + - ./logs:/app/logs + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:5002/health" ] # Adjust based on your health endpoint + interval: 10s + timeout: 5s + retries: 5 + command: ["sh", "-c", "scripts/start_eveai_chat.sh"] + + eveai_chat_workers: + image: josakola/eveai_chat_workers:latest +# ports: +# - 5001:5001 + environment: + <<: *common-variables + volumes: + - ./logs:/app/logs +# healthcheck: +# test: [ "CMD", "curl", "-f", "http://localhost:5001/health" ] +# interval: 10s +# timeout: 5s +# retries: 5 + command: [ "sh", "-c", "scripts/start_eveai_chat_workers.sh" ] + + +#volumes: +# minio_data: +# db-data: +# redis-data: +# tenant-files: +#secrets: +# db-password: +# file: ./db/password.txt + diff --git a/docker/docker_env_switch.sh b/docker/docker_env_switch.sh new file mode 100755 index 0000000..3f3a70e --- /dev/null +++ b/docker/docker_env_switch.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Function to display usage information +usage() { + echo "Usage: source $0 [dev|prod]" + echo " dev : Switch to development environment" + echo " prod : Switch to production environment" +} + +# Check if the script is sourced +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + echo "Error: This script must be sourced, not executed directly." + echo "Please run: source $0 [dev|prod]" + exit 1 +fi + +# Check if an argument is provided +if [ $# -eq 0 ]; then + usage + return 1 +fi + +# Set variables based on the environment +case $1 in + dev) + DOCKER_CONTEXT="default" + COMPOSE_FILE="compose_dev.yaml" + ;; + prod) + DOCKER_CONTEXT="mxz536.stackhero-network.com" + COMPOSE_FILE="compose_stackhero.yaml" + ;; + *) + echo "Invalid environment. Use 'dev' or 'prod'." + usage + return 1 + ;; +esac + +# Switch Docker context +echo "Switching to Docker context: $DOCKER_CONTEXT" +docker context use $DOCKER_CONTEXT + +# Set the COMPOSE_FILE environment variable +export COMPOSE_FILE=$COMPOSE_FILE +echo "Set COMPOSE_FILE to $COMPOSE_FILE" + +# Define aliases for common Docker commands +alias docker-compose="docker compose -f $COMPOSE_FILE" +alias dc="docker compose -f $COMPOSE_FILE" +alias dcup="docker compose -f $COMPOSE_FILE up -d" +alias dcdown="docker compose -f $COMPOSE_FILE down" +alias dcps="docker compose -f $COMPOSE_FILE ps" +alias dclogs="docker compose -f $COMPOSE_FILE logs" + +echo "Docker environment switched to $1" +echo "You can now use 'docker-compose', 'dc', 'dcup', 'dcdown', 'dcps', and 'dclogs' commands" \ No newline at end of file diff --git a/docker/stackhero_link.sh b/docker/stackhero_link.sh new file mode 100755 index 0000000..05a5bb2 --- /dev/null +++ b/docker/stackhero_link.sh @@ -0,0 +1,14 @@ +# HOST is your Stackhero for Docker instance domain name (mxz536.stackhero-network.com). +# SERVICE_ID is your Stackhero service ID. +# CERTIFICATES_PASSWORD is the password defined in your Stackhero for Docker configuration. +(export HOST="mxz536.stackhero-network.com" +export SERVICE_ID="svc-rlaeva" +export CERTIFICATES_PASSWORD="OonfQaQerGLLsWPKmnudyghFilIcPJRW" + +cd /tmp/ \ + && curl -o certificates.tar https://docker:$CERTIFICATES_PASSWORD@$HOST/stackhero/docker/certificates.tar \ + && tar -xf certificates.tar \ + && (docker context rm -f $HOST 2> /dev/null || true) \ + && docker context create $HOST \ + --description "$SERVICE_ID ($HOST)" \ + --docker "host=tcp://$HOST:2376,ca=ca.pem,cert=cert.pem,key=key.pem") \ No newline at end of file diff --git a/eveai_app/__init__.py b/eveai_app/__init__.py index afc415b..ed90506 100644 --- a/eveai_app/__init__.py +++ b/eveai_app/__init__.py @@ -6,8 +6,8 @@ from flask_security.signals import user_authenticated from werkzeug.middleware.proxy_fix import ProxyFix import logging.config -from common.extensions import (db, migrate, bootstrap, security, mail, login_manager, cors, kms_client, csrf, session, - minio_client) +from common.extensions import (db, migrate, bootstrap, security, mail, login_manager, cors, csrf, session, + minio_client, simple_encryption) from common.models.user import User, Role, Tenant, TenantDomain import common.models.interaction from config.logging_config import LOGGING @@ -15,6 +15,7 @@ from common.utils.security import set_tenant_session_data from .errors import register_error_handlers from common.utils.celery_utils import make_celery, init_celery from common.utils.template_filters import register_filters +from config.config import get_config def create_app(config_file=None): @@ -23,10 +24,16 @@ def create_app(config_file=None): # Ensure all necessary headers are handled app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1) - if config_file is None: - app.config.from_object('config.config.DevConfig') - else: - app.config.from_object(config_file) + environment = os.getenv('FLASK_ENV', 'development') + print(environment) + + match environment: + case 'development': + app.config.from_object(get_config('dev')) + case 'production': + app.config.from_object(get_config('prod')) + case _: + app.config.from_object(get_config('dev')) app.config['SESSION_KEY_PREFIX'] = 'eveai_app_' @@ -39,14 +46,13 @@ def create_app(config_file=None): logger = logging.getLogger(__name__) logger.info("eveai_app starting up") + logger.debug("start config") + logger.debug(app.config) # Register extensions register_extensions(app) - # Check GCloud availability - kms_client.check_kms_access_and_latency() - app.celery = make_celery(app.name, app.config) init_celery(app.celery, app) @@ -101,7 +107,8 @@ def register_extensions(app): csrf.init_app(app) login_manager.init_app(app) cors.init_app(app) - kms_client.init_app(app) + # kms_client.init_app(app) + simple_encryption.init_app(app) session.init_app(app) minio_client.init_app(app) diff --git a/eveai_app/templates/header.html b/eveai_app/templates/header.html index e1e41de..868b1be 100644 --- a/eveai_app/templates/header.html +++ b/eveai_app/templates/header.html @@ -1,5 +1,5 @@
-