diff --git a/app.py b/app.py index 6a55c88..196e158 100644 --- a/app.py +++ b/app.py @@ -2,6 +2,9 @@ from flask import Flask, render_template, request, jsonify, session # external from werkzeug.security import generate_password_hash # built-in from flask_session import Session # external +import logging +from logging.handlers import RotatingFileHandler + import os, shutil, signal, atexit, json, yaml, logging, tempfile # built-in import docker, ansible_runner # external @@ -125,7 +128,7 @@ def cleanup_files(file_paths): if os.path.exists(file_path): os.unlink(file_path) # removes the file - + def run_ansible(hosts, command, type): # [NOTE] shell command execution will not work with other shells like zsh, fish, etc. """ Runs an Ansible playbook on specified hosts with a given command. @@ -206,6 +209,30 @@ def cleanup(action='stop'): app.logger.info("Cleanup complete.") +import logging +from logging.handlers import RotatingFileHandler + +# Set up logging +log_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + +# Create a file handler for logging to a file (overwrite the file each time) +log_file = "app.log" # The log file name +file_handler = logging.FileHandler(log_file, mode='w') # 'w' mode will overwrite the file each time +file_handler.setFormatter(log_formatter) +file_handler.setLevel(logging.DEBUG) # Adjust the level as needed (DEBUG, INFO, WARNING, ERROR, CRITICAL) + +# Create a console handler for logging to the terminal +console_handler = logging.StreamHandler() +console_handler.setFormatter(log_formatter) +console_handler.setLevel(logging.DEBUG) # Adjust the level as needed + +# Get the app logger and set the log level +app.logger.setLevel(logging.DEBUG) +app.logger.addHandler(file_handler) +app.logger.addHandler(console_handler) + +# Log a message to verify setup +app.logger.info("Logging setup complete. Logs will be saved to 'app.log' and displayed on the console.") ## ROUTES (FOR RENDERING HTML PAGES) ## @app.route('/') @@ -253,6 +280,16 @@ def SPAWN_MACHINES_ROUTE(): app.logger.error(f"Error in spawn_machines: {str(e)}") return jsonify({"error": str(e)}), 500 +@app.route('/logs', methods=['GET']) +def display_logs_from_file(): + """Render the logs HTML page with logs read directly from the log file.""" + log_file_path = 'app.log' # Path to your log file + try: + with open(log_file_path, 'r') as f: + logs = f.readlines() # Read all lines from the log file + except FileNotFoundError: + logs = ["Log file not found. Please ensure the application is running and generating logs."] + return render_template('logs.html', logs=logs) @app.route('/run_command', methods=['POST']) def RUN_COMMAND_ROUTE(): @@ -391,6 +428,11 @@ def SAVE_CONFIG_ROUTE(): # [NOTE] needs more testing, [IMPROVEMENT] add error ha with open('nginx_config.yml', 'w') as file: yaml.dump(config, file) + # Get the list of spawned containers + machine_info = session.get('machine_info', []) + if not machine_info: + return jsonify({"message": "No machines spawned. Please spawn machines first."}) + # Create a temporary inventory file with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.yml') as temp_inventory: inventory = { @@ -550,6 +592,7 @@ def SAVE_CONFIG_ROUTE(): # [NOTE] needs more testing, [IMPROVEMENT] add error ha else: return jsonify({"message": "Invalid configuration option."}) + ## [NOTE] SOME IMPORTANT POINTS (FOR ROUTES): ## @@ -585,4 +628,4 @@ def handle_sigterm(signum, frame): ## MAIN ENTRY POINT ## if __name__ == '__main__': - app.run(debug=True) # start the Flask app in debug mode, [NOTE] to disable auto-reload, set 'use_reloader=False' + app.run(debug=True, use_reloader=False) # start the Flask app in debug mode (with auto-reload disabled) diff --git a/templates/index.html b/templates/index.html index 9e0c6ad..67ca4bb 100644 --- a/templates/index.html +++ b/templates/index.html @@ -44,6 +44,7 @@
diff --git a/templates/logs.html b/templates/logs.html new file mode 100644 index 0000000..e09f135 --- /dev/null +++ b/templates/logs.html @@ -0,0 +1,103 @@ + + + + + +No logs available.
+ {% endif %} +