class Config(object): SQLALCHEMY_DATABASE_URI = get_env( 'DATABASE_URL', default=f'sqlite:///{"app" or __name__}.db') #'sqlite:///:memory:' SQLALCHEMY_TRACK_MODIFICATIONS = False #SQLALCHEMY_COMMIT_ON_TEARDOWN = True _binds = get_env('SQLALCHEMY_BINDS', default=None) if _binds: #https://docs.sqlalchemy.org/en/13/core/exceptions.html #https://flask-sqlalchemy.palletsprojects.com/en/2.x/binds/ #https://flask-migrate.readthedocs.io/en/latest/ SQLALCHEMY_BINDS = {} for _ in _binds.split(','): __ = _.split(':', 1) SQLALCHEMY_BINDS.update({ __[0].lower(): __[1] if __[1].rfind('://') != -1 else get_env(__[1]) }) print(SQLALCHEMY_BINDS) # SECURITY WARNING: don't run with debug turned on in production! #Default: True if ENV is 'development', or False otherwise. DEBUG = to_bool( get_env('DEBUG', default=os.sys.platform == 'win32' or os.name == 'nt')) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = get_env('SECRET_KEY', default=random_func(as_string=True, size=65)) DEVELOPMENT = TESTING = False @property def DATABASE_URI(self): return SQLALCHEMY_DATABASE_URI
def update_container_config_with_cloud(container_config: dict, env: Optional[dict] = None) -> None: """Updates the container config to run with --cloud. Args: container_config: An existing container config, to be updated in place. env: Refer to :meth:`get_container_config`. """ if env is None: env = utils.get_env() utils.echo( "Starting Orchest with --cloud. Some GUI functionality is altered.") cloud_inject = { "orchest-webserver": { "Env": [ "CLOUD=true", ], }, "update-server": { "Env": [ "CLOUD=true", ], }, "auth-server": { "Env": [ "CLOUD=true", ], }, } inject_dict(container_config, cloud_inject, overwrite=False)
def get_dev_container_config(env: Optional[dict] = None) -> dict: """Constructs the container config to run Orchest in "dev" mode. Note: The returned configuration adheres to: https://docs.docker.com/engine/api/v1.41/#operation/ContainerCreate Args: env: Refer to :meth:`get_container_config`. Returns: Dictionary mapping the name of the docker containers to their respective configs in the format required by the docker engine API. """ if env is None: env = utils.get_env() container_config = get_reg_container_config(env) dev_inject = { "orchest-webserver": { "Cmd": ["./debug.sh"], "Env": [ "FLASK_ENV=development", ], "HostConfig": { "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "orchest-webserver", "app") + ":/orchest/services/orchest-webserver/app", # Internal library. os.path.join(env["HOST_REPO_DIR"], "lib") + ":/orchest/lib", ], }, }, "auth-server": { "Cmd": ["sh", "-c", "umask 002 && flask run --host=0.0.0.0 --port=80"], "Env": [ "FLASK_APP=main.py", "FLASK_DEBUG=1", ], "HostConfig": { "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "auth-server", "app") + ":/orchest/services/auth-server/app", # Internal library. os.path.join(env["HOST_REPO_DIR"], "lib") + ":/orchest/lib", ], }, }, "file-manager": { "HostConfig": { "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "file-manager", "static") + ":/custom-static", ], }, }, "orchest-api": { "Cmd": ["flask", "run", "--host=0.0.0.0", "--port=80"], "Env": [ "FLASK_APP=main.py", "FLASK_ENV=development", ], "ExposedPorts": { "80/tcp": {} }, "HostConfig": { "PortBindings": { # Expose Swagger. "80/tcp": [{ "HostPort": "8080" }], }, "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "orchest-api", "app") + ":/orchest/services/orchest-api/app", # Internal library. os.path.join(env["HOST_REPO_DIR"], "lib") + ":/orchest/lib", ], }, }, } inject_dict(container_config, dev_inject, overwrite=False) return container_config
def get_reg_container_config(env: Optional[dict] = None) -> dict: """Constructs the container config to run Orchest in "reg" mode. Note: The returned dictionary needs to contain a configuration specification for every container that is to be started through the orchest-ctl. Note: The returned configuration adheres to: https://docs.docker.com/engine/api/v1.41/#operation/ContainerCreate Args: env: Refer to :meth:`get_container_config`. Returns: Dictionary mapping the name of the docker containers to their respective configs in the format required by the docker engine API. """ if env is None: env = utils.get_env() # name -> request body container_config = { "orchest-api": { "Image": "orchest/orchest-api:latest", "Env": [ f'ORCHEST_HOST_GID={env["ORCHEST_HOST_GID"]}', "PYTHONUNBUFFERED=TRUE", ], "HostConfig": { "GroupAdd": [f'{env["ORCHEST_HOST_GID"]}'], "Binds": [ "/var/run/docker.sock:/var/run/docker.sock", f'{env["HOST_USER_DIR"]}:/userdir', ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "orchest-webserver": { "Image": "orchest/orchest-webserver:latest", "Env": [ f'HOST_USER_DIR={env["HOST_USER_DIR"]}', f'HOST_CONFIG_DIR={env["HOST_CONFIG_DIR"]}', f'HOST_REPO_DIR={env["HOST_REPO_DIR"]}', f'HOST_OS={env["HOST_OS"]}', "PYTHONUNBUFFERED=TRUE", ], "HostConfig": { "GroupAdd": [f'{env["ORCHEST_HOST_GID"]}'], "Binds": [ "/var/run/docker.sock:/var/run/docker.sock", f'{env["HOST_USER_DIR"]}:/userdir', f'{env["HOST_CONFIG_DIR"]}:/config', f'{env["HOST_REPO_DIR"]}:/orchest-host', ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "celery-worker": { "Image": "orchest/celery-worker:latest", "Env": [ f'ORCHEST_HOST_GID={env["ORCHEST_HOST_GID"]}', ], "HostConfig": { "GroupAdd": [f'{env["ORCHEST_HOST_GID"]}'], "Binds": [ "/var/run/docker.sock:/var/run/docker.sock", # Mount is needed for copying the snapshot dir to # pipeline run dirs for jobs. f'{env["HOST_USER_DIR"]}:/userdir', ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "rabbitmq-server": { "Image": "rabbitmq:3", "HostName": "rabbitmq-server", "HostConfig": { "Binds": [ # Persisting RabbitMQ Queues. os.path.join(env["HOST_USER_DIR"], ".orchest/rabbitmq-mnesia") + ":/var/lib/rabbitmq/mnesia", ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "auth-server": { "Image": "orchest/auth-server:latest", "Env": [ "PYTHONUNBUFFERED=TRUE", ], "HostConfig": { "Binds": [ f'{env["HOST_USER_DIR"]}:/userdir', f'{env["HOST_CONFIG_DIR"]}:/config', ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "file-manager": { "Image": "orchest/file-manager:latest", "HostConfig": { "GroupAdd": [f'{env["ORCHEST_HOST_GID"]}'], "Binds": [ f'{env["HOST_USER_DIR"]}:/userdir', ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "nginx-proxy": { "Image": "orchest/nginx-proxy:latest", "ExposedPorts": { "80/tcp": {} }, "HostConfig": { "PortBindings": { # Exposure of 443 is injected based on certs. "80/tcp": [{ "HostPort": "8000" }], }, # Injected based on presence of certs on host. "Binds": [], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "orchest-database": { "Image": "postgres:13.1", "Env": [ "PGDATA=/userdir/.orchest/database/data", "POSTGRES_HOST_AUTH_METHOD=trust", ], "HostConfig": { "Binds": [ os.path.join(env["HOST_USER_DIR"], ".orchest/database") + ":/userdir/.orchest/database", ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, "update-server": { "Image": "orchest/update-server:latest", "Env": [ f'HOST_USER_DIR={env["HOST_USER_DIR"]}', f'HOST_CONFIG_DIR={env["HOST_CONFIG_DIR"]}', f'HOST_REPO_DIR={env["HOST_REPO_DIR"]}', f'HOST_OS={env["HOST_OS"]}', ], "HostConfig": { "Binds": [ "/var/run/docker.sock:/var/run/docker.sock", ], }, "NetworkingConfig": { "EndpointsConfig": { _config.DOCKER_NETWORK: {} } }, }, } if utils.do_proxy_certs_exist_on_host(): certs_bind: dict = { "nginx-proxy": { "Env": [ "ENABLE_SSL=true", ], "ExposedPorts": { "443/tcp": {} }, "HostConfig": { "PortBindings": { "443/tcp": [{ "HostPort": "443" }], }, "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "nginx-proxy", "certs") + ":/etc/ssl/certs", ], }, }, } inject_dict(container_config, certs_bind, overwrite=True) return container_config
def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ return username == get_env('UPLOAD_USER') and password == get_env('UPLOAD_PASSWORD')
def create_app(): import os from flask import Flask from flask_sqlalchemy import SQLAlchemy def get_config(x=None): return { 'development': 'config.DevelopementConfig', 'dev': 'config.DevelopementConfig', 'testing': 'config.TestingConfig', 'default': 'config.ProductionConfig', 'production': 'config.ProductionConfig', 'prod': 'config.ProductionConfig' }.get(str(x).lower(), 'config.ProductionConfig') app = Flask(__name__.split('.')[0], static_folder='static', template_folder='templates', static_url_path='', instance_relative_config=True) app.config.from_object( get_config( get_env('FLASK_ENV', default='dev' if os.sys.platform == 'win32' else 'prod'))) app.config.from_pyfile('config.cfg', silent=True) print(app.secret_key) @app.teardown_request def teardown_request_func(error=None): """ This function will run after a request, regardless if an exception occurs or not. It's a good place to do some cleanup, such as closing any database connections. If an exception is raised, it will be passed to the function. You should so everything in your power to ensure this function does not fail, so liberal use of try/except blocks is recommended. """ if error: # Log the error app.logger.error(error) @app.route('/index', methods=['GET']) @app.route('/index.html', methods=['GET']) @app.route('/', methods=['GET']) def _root(error=None): from flask import redirect, url_for return redirect(url_for('api.root')) @app.after_request def jsonify_request(response): """JSONify the response. https://github.com/Fuyukai/OWAPI/blob/master/owapi/app.py#L208""" if response.headers.get( 'Content-Type', '').lower() == app.config['JSONIFY_MIMETYPE'].lower(): from flask import request import json if request.args.get('format', 'json') in [ 'json_pretty', 'pretty' ] or app.config['JSONIFY_PRETTYPRINT_REGULAR']: from datetime import datetime, timedelta, timezone from email.utils import format_datetime response.set_data( json.dumps(response.get_json(), sort_keys=app.config['JSON_SORT_KEYS'], ensure_ascii=app.config['JSON_AS_ASCII'], indent=4, separators=(',', ': '))) response.headers['Cache-Control'] = 'public, max-age=300' response.headers['Expires'] = format_datetime( (datetime.utcnow() + timedelta(seconds=300)).replace(tzinfo=timezone.utc), usegmt=True) return response def get_http_exception_handler(app): """Overrides the default http exception handler to return JSON.""" from functools import wraps handle_http_exception = app.handle_http_exception @wraps(handle_http_exception) def ret_val(error): """Generic exception handler for general exceptions""" if not app.env.lower().startswith('dev') and error.code == 404: from flask import redirect, url_for return redirect(url_for('api.root')) #from werkzeug.exceptions import HTTPException #if isinstance(e, HTTPException) and (500 <= e.code < 600): # return error if not hasattr(error, 'code'): # or isinstance(error, HTTPException): error.code = 500 from werkzeug.exceptions import default_exceptions if error.code in default_exceptions: # Returning directly as below results in missing Location header # on 301 errors which is useful for this test as it will fail to redirect. def get_http_error_code(error_code=500): return { 301: u'Moved Permanently', 302: u'Found', 303: u'See Other', 304: u'Not Modified', 400: u'Bad request', 401: u'Unauthorized', 403: u'Forbidden', 404: u'Resource not found', 405: u'Method not allowed', 408: u'Request Timeout', 409: u'Conflict', 410: u'Gone', 418: u'I am a teapot', 429: u'Too many requests', 500: u'Internal server error', 501: u'Not Implemented', 502: u'Bad Gateway', 503: u'Service unavailable', 504: u'Gateway Timeout' }.get(error_code, 500) from flask import jsonify if not hasattr(error, 'original_exception'): error.original_exception = error or None return jsonify(code=get_http_error_code(error.code), description=error.description, message=str(error.original_exception), error=error.code), error.code return handle_http_exception(error) return ret_val # Override the HTTP exception handler. app.config['TRAP_HTTP_EXCEPTIONS'] = True #TRAP_BAD_REQUEST_ERRORS = PROPAGATE_EXCEPTIONS = True app.handle_http_exception = get_http_exception_handler(app) from werkzeug.exceptions import default_exceptions #werkzeug import HTTP_STATUS_CODES for exc in default_exceptions: #exc in HTTPException.__subclasses__() | exc in HTTP_STATUS_CODES app.register_error_handler(exc, get_http_exception_handler(app)) app.register_error_handler(Exception, get_http_exception_handler(app)) #if request.path.startswith('/api/'): return jsonify_error(ex) #else: return ex import logging handler = logging.FileHandler( 'static/flask.log' ) #RotatingFileHandler('flask.log', maxBytes=1024 * 1024 * 100, backupCount=3) handler.setLevel(logging.DEBUG if app.config['DEBUG'] else logging.INFO) handler.setFormatter( logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] ' '%(asctime)s %(message)s \r\n')) app.logger.addHandler(handler) # Blueprints from app import register register(app) return app, SQLAlchemy(app)
handler.setFormatter( logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] ' '%(asctime)s %(message)s \r\n')) app.logger.addHandler(handler) # Blueprints from app import register register(app) return app, SQLAlchemy(app) app, db = create_app() migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) manager.add_command('debug', Server(host='127.0.0.1', port=8080, use_debugger=True)) if __name__ == '__main__': db.create_all() manager.run() app.run(debug=app.config['DEBUG'], use_reloader=app.config['DEBUG'], port=int(get_env('PORT', 5000)), host='0.0.0.0') #https://gist.github.com/rochacbruno/b1fe0ccab1a81804def887e8ed40da57 #https://gist.github.com/rochacbruno/e44c1f0f43e89093bf7ddba77ee9feef
def update_container_config_with_dev(container_config: dict, env: Optional[dict] = None) -> None: """Updates the container config to run with --dev. Args: container_config: An existing container config, to be updated in place. env: Refer to :meth:`get_container_config`. """ if env is None: env = utils.get_env() dev_inject = { "orchest-webserver": { "Cmd": ["./debug.sh"], "Env": [ "FLASK_ENV=development", ], "HostConfig": { "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "orchest-webserver", "app") + ":/orchest/services/orchest-webserver/app", # Internal library. os.path.join(env["HOST_REPO_DIR"], "lib") + ":/orchest/lib", ], }, }, "auth-server": { "Cmd": ["sh", "-c", "umask 002 && flask run --host=0.0.0.0 --port=80"], "Env": ["FLASK_APP=main.py", "FLASK_DEBUG=1", "FLASK_ENV=development"], "HostConfig": { "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "auth-server", "app") + ":/orchest/services/auth-server/app", # Internal library. os.path.join(env["HOST_REPO_DIR"], "lib") + ":/orchest/lib", ], }, }, "file-manager": { "HostConfig": { "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "file-manager", "static") + ":/custom-static", ], }, }, "orchest-api": { "Cmd": ["flask", "run", "--host=0.0.0.0", "--port=80"], "Env": [ "FLASK_APP=main.py", "FLASK_ENV=development", ], "ExposedPorts": { "80/tcp": {} }, "HostConfig": { "PortBindings": { # Expose Swagger. "80/tcp": [{ "HostPort": "8080" }], }, "Binds": [ os.path.join(env["HOST_REPO_DIR"], "services", "orchest-api", "app") + ":/orchest/services/orchest-api/app", # Internal library. os.path.join(env["HOST_REPO_DIR"], "lib") + ":/orchest/lib", ], }, }, "update-server": { "Env": [ "FLASK_ENV=development", ], }, } inject_dict(container_config, dev_inject, overwrite=False)
from enum import Enum from datetime import datetime import json from app.utils import get_env from flask import Flask, jsonify, request, render_template, url_for, send_from_directory, escape from flask_sqlalchemy import SQLAlchemy from sqlalchemy.exc import IntegrityError, OperationalError, ProgrammingError import pyrez from pyrez.api import * from pyrez.exceptions import PlayerNotFound, MatchException from pyrez.enumerations import Champions, Tier from langs import * DEBUG = get_env("DEBUG") DATABASE_URL = get_env("DATABASE_URL") app = Flask( __name__, static_folder="static", template_folder="templates", static_url_path='' ) #https://stackoverflow.com/questions/4239825/static-files-in-flask-robot-txt-sitemap-xml-mod-wsgi app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URL app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False db = SQLAlchemy(app) class Session(db.Model): __tablename__ = "session"
def get_config(x=None): return 'config.' + { 'development': 'DevelopementConfig', 'dev': 'DevelopementConfig', 'testing': 'TestingConfig', 'default': 'ProductionConfig', 'production': 'ProductionConfig', 'prod': 'ProductionConfig' }.get(str(x).lower(), 'ProductionConfig') #init_db() #current_app.push() app.config.from_object( get_config( get_env('FLASK_ENV', default='dev' if os.sys.platform == 'win32' else 'prod'))) # object-based default configuration app.config.from_pyfile( 'config.cfg', silent=True) #https://flask.palletsprojects.com/en/1.1.x/config/ print(app.secret_key) db = SQLAlchemy(app) #db.init_app(app) from app import register register(app) ''' from app.overwatch import register as overwatch_register from app.twitch import register as twitch_register from app.smite import register as smite_register from app.youtube import register as youtube_register