Manage configurations for a 12-factor app charm

Add a new configuration

A charm configuration can be added if your 12-factor app requires environment variables, for example, to pass a token for a service. Add the configuration in charmcraft.yaml:

config:
  options:
    token:
      description: The token for the service.
      type: string

A user-defined configuration option will correspond to an environment variable generated by the paas-charm project to expose the configuration to the Flask workload. In general, a configuration option config-option-name will be mapped as FLASK_CONFIG_OPTION_NAME where the option name will be converted to upper case, dashes will be converted to underscores and the FLASK_ prefix will be added. In the example above, the token configuration will be mapped as the FLASK_TOKEN environment variable. In addition to the environment variable, the configuration is also available in the Flask variable app.config without the FLASK_ prefix.

The configuration can be set on the deployed charm using:

juju config <app name> token=<token>

Manage secrets for a 12-factor app charm

A user secret can be added to a charm and all the keys and values in the secret will be exposed as environment variables. Add the secret configuration option in your project file:

config:
  options:
    api-token:
      type: secret
      description: Secret needed to access some API secret information

Once the charm is deployed, you can add a juju secret to the model:

user@host:~$ juju add-secret my-api-token value=1234 othervalue=5678
secret:cru00lvmp25c77qa0qrg

From this output, you can get the Juju secret ID. Grant the application access to view the value of the secret:

juju grant-secret my-api-token <app name>

Add the Juju secret ID to the application:

juju config <app name> api-token=secret:cru00lvmp25c77qa0qrg

The following environment variables are available for the application:

Write a Kubernetes charm for an async Flask app

In this how-to guide you will configure a 12-factor Flask application to use asynchronous Gunicorn workers to be able to serve to multiple users easily.

Make the rock async

To make the rock async, make sure to put the following in its requirements.txt file:

Flask
gevent

Pack the rock using rockcraft pack and redeploy the charm with the new rock using juju refresh.

Configure the async application

Now let’s enable async Gunicorn workers. We will expect this configuration option to be available in the Flask app configuration under the webserver-worker-class key. Verify that the new configuration has been added by running:

juju config flask-async-app | grep -A 6 webserver-worker-class:

The result should contain the key.

The worker class can be changed using Juju:

juju config flask-async-app webserver-worker-class=gevent

Test that the workers are operating in parallel by sending multiple simultaneous requests with curl:

curl --parallel --parallel-immediate --resolve flask-async-app:80:127.0.0.1 \
http://flask-async-app/io http://flask-async-app/io http://flask-async-app/io \
http://flask-async-app/io http://flask-async-app/io

and they will all return at the same time.

The results should arrive simultaneously and contain five instances of ok:

okokokokok

It can take up to a minute for the configuration to take effect. When the configuration changes, the charm will re-enter the active state.