CSRF exempt for Flask-RESTPlus API

| Comments

The @csrf.exempt method does not work with Resource methods or decorators, it should be done on Api level. Here is an example how to exclude resources from CSRF protection based on class:

def csrf_exempt_my_resource(view):
    if issubclass(view.view_class, MyResource):
        return csrf.exempt(view)
    return view

api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint, title='My API', decorators=[csrf_exempt_my_resource])

Or for all resources:

api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint, title='My Private API', decorators=[csrf.exempt])

Function as model column in Flask Admin

| Comments

I like the idea about separation of business logic from models and views into services. There are more details in these slides from the EuroPython talk.

Usually in Flask-Admin for a new column a new method with @property decorator is added and the model becomes fat. Also it’s not good to put something with queries in property. Another way is to put this function to the services and use column formatter in Flask-Admin.

def get_some_data(model_id)
    """Function in services."""
    return RelatedModel.objects(model=model_id).count()

class MyModelView(ModelView):
    column_formatters = {
        'related_model_count': lambda view, context, model, name: get_some_data(model.id)

    column_list = [..., 'related_model_count']

Docker healthcheck for Flask app with Celery

| Comments

With docker-compose it can be done the next way

      test: wget --spider --quiet http://localhost:8080/-/health
    command: celery worker --app app.celeryapp -n worker@%h --loglevel INFO
      test: celery inspect ping --app app.celeryapp -d worker@$$HOSTNAME

Where /-/health is just a simple route

def health():
    return 'ok'

How to update docker service using a version from docker-compose

| Comments

Here is a small script which compares the version of the running service and the version in the docker-compose file, if they are different it runs an update.

REDIS_VERSION=$(docker service ls | grep "redis" | awk '{print $5}')
REDIS_NEW_VERSION=$(grep -Po "image:\s*\Kredis:.*" docker-compose.yml)
    echo "update $REDIS_VERSION -> $REDIS_NEW_VERSION"
    docker service update --image $REDIS_NEW_VERSION app_redis

Env variables for Vue.js in Nginx container

| Comments

The default approach for Vue.js is to use .env files during build stage. But I like more this one with envsubst. There is no need to rebuild image for each environment or when the configuration is changed.

Here is a small modification for entrypoint.sh, so it can replace all variables with VUE_APP_ prefix.


function join_by { local IFS="$1"; shift; echo "$*"; }

# Find vue env vars
vars=$(env | grep VUE_APP_ | awk -F = '{print "$"$1}')
vars=$(join_by ' ' $vars)
echo "Found variables $vars"

for file in /dist/js/app.*;
  echo "Processing $file ...";

  # Use the existing JS file as template
  cp $file $file.tmpl
  envsubst "$vars" < $file.tmpl > $file
  rm $file.tmpl

exec "$@"

A script to transfer azure storage containers to another storage

| Comments

Here is an example of a script to copy azure storage containers from one storage to another and keep public access level. It uses Azure CLI and AzCopy tools.



containers=$(az storage container list --connection-string $CONNECTION_STRING_SOURCE --output tsv | awk '{print $2}')
for i in $containers;
    docker run --rm incendonet/azcopy azcopy --source https://$STORAGE_NAME_SOURCE.blob.core.windows.net/$i --source-key $STORAGE_KEY_SOURCE --destination https://$STORAGE_NAME_DEST.blob.core.windows.net/$i --dest-key $STORAGE_KEY_DEST --recursive
    access_level=$(az storage container show-permission -n $i --connection-string $CONNECTION_STRING_SOURCE --output tsv)
    az storage container set-permission -n $i --connection-string $CONNECTION_STRING_DEST --public-access $access_level    
1/9 »