diff --git a/.devcontainer/ansible/roles/setup-container/meta/main.yml b/.devcontainer/ansible/roles/setup-container/meta/main.yml deleted file mode 100644 index a5e6e20..0000000 --- a/.devcontainer/ansible/roles/setup-container/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - { role: geerlingguy.docker, become: true } \ No newline at end of file diff --git a/.devcontainer/ansible/setup-container.yml b/.devcontainer/ansible/setup-container.yml index 523dc39..936e967 100644 --- a/.devcontainer/ansible/setup-container.yml +++ b/.devcontainer/ansible/setup-container.yml @@ -1,18 +1,6 @@ ---- - name: Setup container hosts: localhost connection: local gather_facts: true - vars: - # docker defaults - docker_edition: 'ce' - docker_package_state: present - docker_service_manage: false - docker_install_compose_plugin: true - docker_compose_package: docker-compose-plugin - docker_compose_package_state: present - - docker_users: - - "{{ lookup('env', 'USER') }}" roles: - role: setup-container \ No newline at end of file diff --git a/.devcontainer/ansible/setup-docker.yml b/.devcontainer/ansible/setup-docker.yml new file mode 100644 index 0000000..0fce7db --- /dev/null +++ b/.devcontainer/ansible/setup-docker.yml @@ -0,0 +1,18 @@ +- name: Setup Docker + hosts: localhost + connection: local + gather_facts: true + become: true + vars: + # docker defaults + docker_edition: 'ce' + docker_package_state: present + docker_service_manage: false + docker_install_compose_plugin: true + docker_compose_package: docker-compose-plugin + docker_compose_package_state: present + + docker_users: + - "{{ lookup('env', 'USER') }}" + roles: + - role: geerlingguy.docker \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 37b319f..78c4b4d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -45,7 +45,14 @@ "eamodio.gitlens", "nhoizey.gremlins", "esbenp.prettier-vscode", - "peakchen90.open-html-in-browser" + "peakchen90.open-html-in-browser", + "ms-python.autopep8", + "codezombiech.gitignore", + "ms-vscode.makefile-tools", + "yy0931.save-as-root", + "ms-python.isort", + "ZainChen.json", + "euskadi31.json-pretty-printer" ], "settings": { "files.exclude": { diff --git a/.vscode/settings.json b/.vscode/settings.json index fc507e6..9764a42 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "cachelib", "cssless", "devcontainer", + "geerlingguy", "htmx", "HTMX", "hykin", @@ -29,14 +30,4 @@ "yamlpath", "zcompdump" ], - "python.analysis.extraPaths": [ - "./app" - ], - "files.exclude": { - "**/__pycache__": true, - "**/.webassets-cache": true, - "**/*.pyc": { - "when": "$(basename).py" - } - } } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 95d4ace..062a15a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -195,6 +195,10 @@ RUN echo ${USER} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USER} && \ chmod 0440 /etc/sudoers.d/${USER} USER ${USER} + +COPY --chown=${USER}:${USER} .devcontainer/ansible ${PROJECT_PATH}/.devcontainer/ansible +RUN LC_ALL=C.UTF-8 ansible-playbook --inventory 127.0.0.1 --connection=local .devcontainer/ansible/requirements.yml && \ + LC_ALL=C.UTF-8 ansible-playbook --inventory 127.0.0.1 --connection=local .devcontainer/ansible/setup-docker.yml # https://code.visualstudio.com/remote/advancedcontainers/start-processes#_adding-startup-commands-to-the-docker-image-instead CMD [ "sleep", "infinity" ] diff --git a/Makefile b/Makefile index e3d2d48..9575296 100644 --- a/Makefile +++ b/Makefile @@ -30,5 +30,5 @@ bash-image: build-image docker run -it --rm -p 9830:9830 -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/traefikturkey/onboard:latest bash ansible: - LC_ALL=C.UTF-8 ansible-playbook --inventory 127.0.0.1 --connection=local .devcontainer/ansible/requirements.yml - LC_ALL=C.UTF-8 ansible-playbook --inventory 127.0.0.1 --connection=local .devcontainer/ansible/setup-container.yml \ No newline at end of file + -LC_ALL=C.UTF-8 ansible-playbook --inventory 127.0.0.1 --connection=local .devcontainer/ansible/requirements.yml + -LC_ALL=C.UTF-8 ansible-playbook --inventory 127.0.0.1 --connection=local .devcontainer/ansible/setup-container.yml \ No newline at end of file diff --git a/app/app.py b/app/app.py index b18e6dd..548df81 100644 --- a/app/app.py +++ b/app/app.py @@ -1,97 +1,56 @@ -import asyncio -import logging -import os -import secrets +import docker +import time import signal import sys -from datetime import datetime -from typing import Any -from flask import Flask, render_template -from flask_assets import Environment, Bundle -from flask_caching import Cache - -logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.DEBUG) - -app = Flask(__name__) -app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True -app.secret_key = os.environ.get("FLASK_SECRET_KEY", secrets.token_hex()) - -if os.environ.get("FLASK_DEBUG", "False") == "True": - cache_config={ - 'CACHE_TYPE': 'null' - } -else: - # 600 seconds = 10 minutes - cache_config={ - 'CACHE_TYPE': 'simple', - 'CACHE_DEFAULT_TIMEOUT': 600 - } - from flask_minify import Minify - Minify(app=app, html=True, js=True, cssless=True) - -cache = Cache(app, config=cache_config) -page_timeout = int(os.environ.get('CACHE_PAGE_TIMEOUT', 600)) - -assets = Environment(app) - -css = Bundle( - 'css/*.css', - filters="cssmin", - output="assets/common.css" -) -assets.register('css_all', css) -css.build() - -@app.context_processor -def inject_current_date(): - return { - 'today_date': datetime.now(), - 'site_title': os.environ.get('SITE_TITLE', 'Prototype') - } - - -@app.route('/') -def index(tab_name=None): - return render_template('index.html') - - -############################################################################### -# -# Main Startup Code -# -############################################################################### - -if __name__ == '__main__': - port = int(os.environ.get("FLASK_PORT", os.environ.get("ONBOARD_PORT", 9830))) - development = bool(os.environ.get("FLASK_ENV", "development") == "development") - if development: - app.run(port=port, debug=bool(os.environ.get("FLASK_DEBUG", "True"))) - if bool(os.environ.get('WERKZEUG_RUN_MAIN')): - print("") - app.logger.info("Shutting down...") - sys.exit() - else: - try: - from hypercorn.config import Config - from hypercorn.asyncio import serve - - shutdown_event = asyncio.Event() - - def _signal_handler(*_: Any) -> None: - app.logger.info("Shutting down...") - shutdown_event.set() - - config = Config() - config.accesslog="-" - config.errorlog="-" - config.loglevel="DEBUG" - config.bind = f"0.0.0.0:{port}" - loop = asyncio.new_event_loop() - loop.add_signal_handler(signal.SIGTERM, _signal_handler) - loop.run_until_complete( - serve(app, config, shutdown_trigger=shutdown_event.wait) - ) - except KeyboardInterrupt: - app.logger.info("Shutting down...") - sys.exit() - \ No newline at end of file +import re + +# Create a Docker client instance +client = docker.from_env() + + +# Define a callback function to handle events +def event_callback(event): + if event["Action"] == "start": + container_name = event["Actor"]["Attributes"]["name"] + container = client.containers.get(container_name) + labels = container.labels + + traefik_host_labels = { + k: v for k, v in labels.items() if k.startswith("traefik.http.routers.") + } + + if traefik_host_labels: + fqdns = [] + for label_key, label_value in traefik_host_labels.items(): + match = re.search(r"rule=Host\(`(.+?)`\)", label_value) + if match: + fqdn = match.group(1) + fqdns.append(fqdn) + + print(f"Container {container_name} started with Traefik FQDNs: {', '.join(fqdns)}") + else: + print(f"Container {container_name} started without Traefik host labels.") + + elif event["Action"] == "stop": + print(f"Container {event['Actor']['Attributes']['name']} stopped.") + + +# Define a signal handler function +def signal_handler(signal, frame): + print("Received signal, stopping event listener...") + sys.exit(0) + + +# Set up signal handlers +signal.signal(signal.SIGTERM, signal_handler) +signal.signal(signal.SIGINT, signal_handler) + +# Start listening for events +print("Listening for Docker events...") +try: + for event in client.events(decode=True): + event_callback(event) + # Flush the output buffer to ensure the message is printed immediately + time.sleep(0.1) +except KeyboardInterrupt: + print("Keyboard interrupt received, stopping event listener...") diff --git a/cspell.json b/cspell.json deleted file mode 100644 index 55aa572..0000000 --- a/cspell.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "version": "0.2", - "ignorePaths": [], - "dictionaryDefinitions": [], - "dictionaries": [], - "words": [ - "codeium", - "dont", - "esbenp", - "evander", - "fabianlauer", - "galt", - "mafen", - "pycache", - "rearden", - "traefikturkey", - "vsicons", - "webassets" - ], - "ignoreWords": [], - "import": [] -}