Source code for dockerflow.flask.checks

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
"""
This module contains a few built-in checks for the Flask integration.
"""
from sqlalchemy import text

from ... import health
from ...checks import (  # noqa
    CRITICAL,
    DEBUG,
    ERROR,
    INFO,
    STATUSES,
    WARNING,
    CheckMessage,
    Critical,
    Debug,
    Error,
    Info,
    Warning,
    level_to_text,
)


[docs] def check_database_connected(db): """ A built-in check to see if connecting to the configured default database backend succeeds. It's automatically added to the list of Dockerflow checks if a :class:`~flask_sqlalchemy.SQLAlchemy` object is passed to the :class:`~dockerflow.flask.app.Dockerflow` class during instantiation, e.g.:: from flask import Flask from flask_sqlalchemy import SQLAlchemy from dockerflow.flask import Dockerflow app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) dockerflow = Dockerflow(app, db=db) """ from sqlalchemy.exc import DBAPIError, SQLAlchemyError errors = [] try: with db.engine.connect() as connection: connection.execute(text("SELECT 1;")) except DBAPIError as e: msg = "DB-API error: {!s}".format(e) errors.append(Error(msg, id=health.ERROR_DB_API_EXCEPTION)) except SQLAlchemyError as e: msg = 'Database misconfigured: "{!s}"'.format(e) errors.append(Error(msg, id=health.ERROR_SQLALCHEMY_EXCEPTION)) return errors
[docs] def check_migrations_applied(migrate): """ A built-in check to see if all migrations have been applied correctly. It's automatically added to the list of Dockerflow checks if a `flask_migrate.Migrate <https://flask-migrate.readthedocs.io/>`_ object is passed to the :class:`~dockerflow.flask.app.Dockerflow` class during instantiation, e.g.:: from flask import Flask from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy from dockerflow.flask import Dockerflow app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) migrate = Migrate(app, db) dockerflow = Dockerflow(app, db=db, migrate=migrate) """ errors = [] from alembic.migration import MigrationContext from alembic.script import ScriptDirectory from sqlalchemy.exc import DBAPIError, SQLAlchemyError # pass in Migrate.directory here explicitly to be compatible with # older versions of Flask-Migrate that required the directory to be passed config = migrate.get_config(directory=migrate.directory) script = ScriptDirectory.from_config(config) try: with migrate.db.engine.connect() as connection: context = MigrationContext.configure(connection) db_heads = set(context.get_current_heads()) script_heads = set(script.get_heads()) except (DBAPIError, SQLAlchemyError) as e: msg = "Can't connect to database to check migrations: {!s}".format(e) return [Info(msg, id=health.INFO_CANT_CHECK_MIGRATIONS)] if db_heads != script_heads: msg = "Unapplied migrations found: {}".format(", ".join(script_heads)) errors.append(Warning(msg, id=health.WARNING_UNAPPLIED_MIGRATION)) return errors
[docs] def check_redis_connected(client): """ A built-in check to connect to Redis using the given client and see if it responds to the ``PING`` command. It's automatically added to the list of Dockerflow checks if a :class:`~redis.StrictRedis` instances is passed to the :class:`~dockerflow.flask.app.Dockerflow` class during instantiation, e.g.:: import redis from flask import Flask from dockerflow.flask import Dockerflow app = Flask(__name__) redis_client = redis.StrictRedis(host='localhost', port=6379, db=0) dockerflow = Dockerflow(app, redis=redis) An alternative approach to instantiating a Redis client directly would be using the `Flask-Redis <https://github.com/underyx/flask-redis>`_ Flask extension:: from flask import Flask from flask_redis import FlaskRedis from dockerflow.flask import Dockerflow app = Flask(__name__) app.config['REDIS_URL'] = 'redis://:password@localhost:6379/0' redis_store = FlaskRedis(app) dockerflow = Dockerflow(app, redis=redis_store) """ import redis errors = [] try: result = client.ping() except redis.ConnectionError as e: msg = "Could not connect to redis: {!s}".format(e) errors.append(Error(msg, id=health.ERROR_CANNOT_CONNECT_REDIS)) except redis.RedisError as e: errors.append( Error('Redis error: "{!s}"'.format(e), id=health.ERROR_REDIS_EXCEPTION) ) else: if not result: errors.append(Error("Redis ping failed", id=health.ERROR_REDIS_PING_FAILED)) return errors