Welcome to flask_tern

This pkg provides some common setup code and extension integration code to support Flask API development within TERN. It provides small wrappers around commonly used Flask extensions, to simplify configuration. This modules enables full configuration of a Flask application and it’s extension via environment variables. Furthermore it provides full integration with TERNs SSO which is based on keycloak. It also provides a custom Blueprint which helps in creating OpenApi conform APIs, using standard Flask views.

To simplify testing the flask_tern.testing provides some re-usable fixtures to provide some consistent testing setup with PyTest.

The included 3rd party extensions are:

Usage

To use the extensions and bundled extension within this package, use pip to install it, and set up your falks application as usual. There is also a cookiecutter project which creates a fully funcional protytpe application using flask_tern. See: flask-cookiecutter.

Keep reading for a more detailed description of supported extensions.

Install pkg:

pip install flask_tern

Extensions

Each bundled extension has it’s own set of configuration options. See flask_tern.settings for a full list of default values set by this package.

There is also an extension init method (flask_tern.init_app()) to configure all bundled extensions in one step.

Typical usage would be:

def create_app(config=None):
    app = Flask(__name__)
    # load app defaults
    from my_app import settings

    load_settings(app, "MY_APP_", defaults=settings, config=config)

    import flask_tern
    flask_tern.init_app(app)

See below how to use configure each extension separately.

Settings

The flask_tern.settings module provides some default configurations which are loaded when using flask_tern.utils.config.load_settings() method.

The flask_tern.utils.config.load_settings() provides a way to easily load configuration from env vars and config files.

Standard flask environment variables are supported. See Configuration Handling

This extension will look only at environment variable names starting with the prefix passed into flask_tern.utils.config.load_settings(). The example belows uses MY_APP_ prefix, which means env vars like MY_APP_<SETTING> will be used to configure the Flask app.

Settings can also be loaded from a python file (does not need to have the .py ending but it will be interpreted as python file) anywhere on the file system. To load a custom settings file set the env var {PREFIX}_SETTINGS to the location of the config file. This file well be loaded by the flask config file loader flask.Config.from_pyfile(). For the example below the env var should be set like MY_APP_SETTINGS=/path/to/my_conf.py.

Typical usage would be:

def create_app(config=None):
    app = Flask(__name__)
    # load app defaults
    from my_app import settings

    load_settings(app, "MY_APP_", defaults=settings, config=config)

SQLAlchemy

flask_tern makes it easy to use Flask-SQLAlchemy in your project.

It provides a little helper method to initialise Flask-SQLAlchemy extension flask_tern.db.init_app(). To access the extension just use the module global flask_tern.db.db object.

The Flask-SQLAlchemy extension is initialised wthin a custom declarative base flask_tern.db.DeclarativeBase class which allows defininf declarative SQLAlechy models without any dependency os Flask. This enables the re-use of SQLAlchemy models outised of a Flask application. To make use of this feature just use flask_tern.db.DeclarativeBase as base class for all your SQLAlchemy model classes. When accessed via Flask-SQLAlchemy your model objects still can use the convenience methods like db.Model.query added by Flask-SQLAlchemy, but the model can now alse be used outside of any Flask context.

Typical usage:

def create_app():
    app = Flask(__name__)
    load_settings(app, "MY_APP_")

    # initialise Flask-SQLAchemy
    from flask_tern import db
    db.init_app(app)

To access the extension just import the flask_sqlalchemy.SQLAlchemy object:

from flask_tern.db import db

Elasticsearch

flask_tern.elasticsearch is just a small extension to help configure elasticsearch_dsl.

Default configuration provided can be found in flask_tern.elasticsearch.settings.

Typical Usage:

def create_app():
    app = Flask(__name__)
    load_settings(app, "MY_APP_")

    # initialise Flask-SQLAchemy
    from flask_tern import elasticsearch
    elasticsearch.init_app(app)

To use elasticsearch in your application just use elasticsearch_dsl as usual.

from elasticsearch_dsl import connections

es = connection.get_connection()

# es is now an elasticsearch.Elasticsearch instance and can be used to access ES.

Caching

flask_tern.cache is a small integration helper for Flask-Caching.

Typical Usage:

def create_app():
    app = Flask(__name__)
    load_settings(app, "MY_APP_")

    # initialise Flask-Caching
    from flask_tern import cache
    cache.init_app(app)

Access flaskcache:flask_caching.Cache extension:

from flask_tern.cache import cache

cache.set("key", value)

ProxyFix

flask_tern.proxyfix is a small wrapper around Tell Flask it is Behind a Proxy, which makes it possible to configure the ProxyFix middleware via environment variables.

See flask_tern.proxyfix.settings for configuration details.

def create_app():
    app = Flask(__name__)
    load_settings(app, "MY_APP_")

    # initialise ProxyFix middleware
    from flask_tern import proxyfix
    proxyfix.init_app(app)

Metrics

Todo

create a small extension to collect app internal metrics via statsd.

Healthcheck

flask_tern.healthcheck makes it easy to add healtchecks to your application. All the heavy lifting has already been done by https://github.com/ateliedocodigo/py-healthcheck which has detailed documentation. The module also provides some commonly used health checkers.

This addon provides some useful healthchecks out of the box and the flask_tern.healthcheck.init_app() method takes care of setting everything up.

def create_app():
    app = Flask(__name__)
    load_settings(app, "MY_APP_")

    # configure healthcheck extension
    from flask_tern import healtcheck
    healthcheck.init_app(app)

    # add additional healthchecks
    healthcheck.add_check(app, <func>)

Healthchecks can be invoked via a GET request to /api/_health. This endpoint is useful for e.g. in a k8s deployment as readiness and / or health probe.

Authentication

flask_tern.auth provides support for HTTP Basic, Cooke (session), OpenID Connect and Api Key authentication.

As usual configuration follows the same pattern as all other extensions:

def create_app():
    app = Flask(__name__)
    load_settings(app, "MY_APP_")

    # configure healthcheck extension
    from flask_tern import auth
    auth.init_app(app)

There is also a global variable flask_tern.auth.current_user provided, which contains user details about the current authenticate / identified user during a request.

from flask_tern.auth import current_user

Detailed documentation is available here: Authentication.

Logging

flask_tern.logging provides some configuration and helper methods to write json (structured) log messagges to stdout, which works well with log collection in a container environment.

There are some additional helper methods to generate well formatted audit log messages.

See Logging for details.

OpenAPI

flask_tern.openapi provides a blueprint which makes creating OpenAPI conform APIs easy. It makes it possible to annotate standard falks view methods to validate requests and responses according to the provided OpenAPI document. It is also possible to provide a live documentation to the API via Swagger UI.

See OpenAPI for details.

Testing

flask_tern.testing.fixtures provides a few pytest fixtures to help with writing unittests.

Extensions

Reference

Version history