web: docker packaging, env-based config
This commit is contained in:
parent
363ab2b3f6
commit
60021fb738
7 changed files with 95 additions and 51 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
olddata
|
||||
webapp/data.db
|
||||
config.py
|
||||
*pyc
|
||||
*sublime*
|
||||
kasownik.ini
|
||||
|
|
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
version: "3.8"
|
||||
|
||||
services:
|
||||
kasownik-web:
|
||||
build: web
|
||||
ports:
|
||||
- 5000:5000
|
||||
volumes:
|
||||
- ./web:/usr/src
|
||||
environment:
|
||||
- SPACEAUTH_CONSUMER_KEY
|
||||
- SPACEAUTH_CONSUMER_SECRET
|
||||
- DISABLE_LDAP=true
|
14
web/Dockerfile
Normal file
14
web/Dockerfile
Normal file
|
@ -0,0 +1,14 @@
|
|||
FROM python:3.9-slim
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y build-essential libsasl2-dev libldap2-dev
|
||||
|
||||
ADD requirements.txt .
|
||||
# Downgrade setuptools to fix anyjson dependency
|
||||
RUN pip install setuptools~=57.5.0 && \
|
||||
pip install -r requirements.txt
|
||||
|
||||
WORKDIR /usr/src
|
||||
ADD . .
|
||||
|
||||
STOPSIGNAL SIGINT
|
||||
CMD ["uwsgi", "--http-socket", "0.0.0.0:5000", "--plugins", "python3", "--wsgi", "webapp.wsgi:app", "--threads", "10", "--master"]
|
34
web/config.py
Normal file
34
web/config.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import environs
|
||||
|
||||
env = environs.Env()
|
||||
env.read_env()
|
||||
|
||||
DEBUG = env.bool("DEBUG", False)
|
||||
SQLALCHEMY_DATABASE_URI = env.str("SQLALCHEMY_DATABASE_URI", "sqlite:///data.db")
|
||||
DUMMY_TRANSFER_UID = "NOTAMEMBER"
|
||||
|
||||
SPACEAUTH_CONSUMER_KEY = env.str("SPACEAUTH_CONSUMER_KEY", "kasownik")
|
||||
SPACEAUTH_CONSUMER_SECRET = env.str("SPACEAUTH_CONSUMER_SECRET", "changeme")
|
||||
|
||||
SECRET_KEY = env.str("SECRET_KEY", "changeme")
|
||||
|
||||
DISABLE_LDAP = env.bool("DISABLE_LDAP", False)
|
||||
|
||||
LDAP_URI = env.str("LDAP_URI", "ldaps://ldap.hackerspace.pl")
|
||||
LDAP_BIND_DN = env.str("LDAP_BIND_DN", "cn=kasownik,ou=Services,dc=hackerspace,dc=pl")
|
||||
LDAP_BIND_PASSWORD = env.str("LDAP_BIND_PASSWORD", "changeme")
|
||||
|
||||
LDAP_USER_FILTER = env.str("LDAP_USER_FILTER", "(objectClass=hsMember)")
|
||||
LDAP_USER_BASE = env.str("LDAP_USER_BASE", "ou=People,dc=hackerspace,dc=pl")
|
||||
LDAP_CA_PATH = env.str("LDAP_CA_PATH", "/etc/ssl/certs/ca-certificates.crt")
|
||||
|
||||
CACHE_TYPE = env.str("CACHE_TYPE", "null")
|
||||
CACHE_NO_NULL_WARNING = True
|
||||
|
||||
MEMBERSHIP_FEES = env.json(
|
||||
"MEMBERSHIP_FEES",
|
||||
{
|
||||
"starving": 75,
|
||||
"fatty": 150,
|
||||
},
|
||||
)
|
|
@ -1,33 +0,0 @@
|
|||
class Config(object):
|
||||
DEBUG = False
|
||||
TESTING = False
|
||||
SQLALCHEMY_DATABASE_URI = "sqlite:///data.db"
|
||||
DUMMY_TRANSFER_UID = 'NOTAMEMBER'
|
||||
|
||||
SPACEAUTH_CONSUMER_KEY = 'kasownik'
|
||||
SPACEAUTH_CONSUMER_SECRET = 'changeme'
|
||||
|
||||
SECRET_KEY = 'changeme'
|
||||
|
||||
LDAP_URI = 'ldap://ldap.hackerspace.pl'
|
||||
LDAP_BIND_DN = 'cn=fascist,ou=Services,dc=hackerspace,dc=pl'
|
||||
LDAP_BIND_PASSWORD = 'changeme'
|
||||
|
||||
LDAP_USER_FILTER = '(objectClass=hsMember)'
|
||||
LDAP_USER_BASE = 'ou=People,dc=hackerspace,dc=pl'
|
||||
LDAP_CA_PATH = '/etc/ssl/certs/ca-certificates.crt'
|
||||
|
||||
CACHE_TYPE = 'null'
|
||||
CACHE_NO_NULL_WARNING = True
|
||||
|
||||
MEMBERSHIP_FEES = {
|
||||
'starving': 75,
|
||||
'fatty': 150,
|
||||
}
|
||||
|
||||
class DevelopmentConfig(Config):
|
||||
DEBUG = True
|
||||
DISABLE_LDAP = True
|
||||
|
||||
class CurrentConfig(DevelopmentConfig):
|
||||
pass
|
|
@ -11,13 +11,14 @@ chardet==3.0.4
|
|||
click==6.7
|
||||
configparser==3.5.0
|
||||
enum34==1.1.6
|
||||
environs==11.0.0
|
||||
Flask==0.12.2
|
||||
Flask-Caching==1.3.3
|
||||
Flask-Gravatar==0.4.2
|
||||
Flask-Login==0.4.1
|
||||
Flask-OAuthlib==0.9.4
|
||||
Flask-Prometheus==0.0.1
|
||||
Flask-SpaceAuth @ git+https://code.hackerspace.pl/informatic/flask-spaceauth@0f997ab8fa307f7eabacf27e5f19fc1c715a69f3
|
||||
Flask-SpaceAuth @ https://code.hackerspace.pl/informatic/flask-spaceauth/archive/v0.2.0.tar.gz
|
||||
Flask-SQLAlchemy==2.1
|
||||
Flask-WTF==0.10.3
|
||||
idna==2.10
|
||||
|
@ -27,14 +28,17 @@ Jinja2==2.11.3
|
|||
lazy-object-proxy==1.3.1
|
||||
Mako==1.0.0
|
||||
MarkupSafe==1.1.0
|
||||
marshmallow==3.21.3
|
||||
mccabe==0.6.1
|
||||
oauthlib==2.0.7
|
||||
packaging==24.1
|
||||
prometheus-client==0.1.1
|
||||
prometheus-flask-exporter==0.8.0
|
||||
psycopg2==2.9.4
|
||||
psycopg2-binary==2.9.4
|
||||
pyasn1==0.4.8
|
||||
pyasn1-modules==0.2.8
|
||||
pylint==1.8.2
|
||||
python-dotenv==1.0.1
|
||||
python-ldap==3.3.1
|
||||
python-memcached==1.59
|
||||
pytz==2014.10
|
||||
|
@ -46,6 +50,7 @@ SQLAlchemy==1.3.24
|
|||
sqlparse==0.4.1
|
||||
sqltap==0.3.5
|
||||
urllib3==1.25.10
|
||||
uWSGI==2.0.26
|
||||
Werkzeug==0.16.1
|
||||
wrapt==1.10.11
|
||||
WTForms==2.0.1
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
import os
|
||||
from functools import wraps
|
||||
|
||||
import memcache
|
||||
import requests
|
||||
import sqltap.wsgi
|
||||
import click
|
||||
|
@ -40,13 +39,19 @@ from flask_gravatar import Gravatar
|
|||
from spaceauth import SpaceAuth
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object("config.CurrentConfig")
|
||||
app.config.from_object("config")
|
||||
|
||||
auth = SpaceAuth()
|
||||
db = SQLAlchemy()
|
||||
cache = Cache()
|
||||
gravatar = Gravatar(size=256, rating='g', default='retro',
|
||||
force_default=False, use_ssl=True, base_url=None)
|
||||
gravatar = Gravatar(
|
||||
size=256,
|
||||
rating="g",
|
||||
default="retro",
|
||||
force_default=False,
|
||||
use_ssl=True,
|
||||
base_url=None,
|
||||
)
|
||||
|
||||
# TODO unsubscribe me from life
|
||||
cache_enabled = False
|
||||
|
@ -57,16 +62,20 @@ import webapp.models # noqa
|
|||
from webapp.authutils import AnonymousUser, User
|
||||
|
||||
auth.anonymous_user = AnonymousUser
|
||||
|
||||
|
||||
@auth.user_loader
|
||||
def load_user(username, profile=None):
|
||||
return User(username)
|
||||
|
||||
|
||||
def admin_required(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if not current_user.is_admin:
|
||||
return auth.unauthorized()
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
@ -77,10 +86,10 @@ class DecimalEncoder(json.JSONEncoder):
|
|||
# but that would mean a yield on the line with super(...),
|
||||
# which wouldn't work (see my comment below), so...
|
||||
return str(o)
|
||||
#return (str(o) for o in [o])
|
||||
# return (str(o) for o in [o])
|
||||
elif isinstance(o, datetime.datetime):
|
||||
return str(o)
|
||||
#return (str(o) for o in [o])
|
||||
# return (str(o) for o in [o])
|
||||
return super(DecimalEncoder, self).default(o)
|
||||
|
||||
|
||||
|
@ -95,40 +104,43 @@ def create_app():
|
|||
app.wsgi_app = sqltap.wsgi.SQLTapMiddleware(app.wsgi_app)
|
||||
|
||||
# Setup prometheus metrics
|
||||
if app.config.get('PROMETHEUS_DIR'):
|
||||
if app.config.get("PROMETHEUS_DIR"):
|
||||
# This needs to be set before importing prometheus_client
|
||||
os.environ['prometheus_multiproc_dir'] = app.config['PROMETHEUS_DIR']
|
||||
os.environ["prometheus_multiproc_dir"] = app.config["PROMETHEUS_DIR"]
|
||||
|
||||
# FIXME: we could expose this somehow
|
||||
from prometheus_flask_exporter.multiprocess import UWsgiPrometheusMetrics
|
||||
metrics = UWsgiPrometheusMetrics(group_by='url_rule')
|
||||
|
||||
metrics = UWsgiPrometheusMetrics(group_by="url_rule")
|
||||
|
||||
metrics.init_app(app)
|
||||
#metrics.register_endpoint('/varz', app)
|
||||
# metrics.register_endpoint('/varz', app)
|
||||
|
||||
# Register blueprints
|
||||
import webapp.views
|
||||
import webapp.admin
|
||||
import webapp.api
|
||||
|
||||
app.register_blueprint(webapp.admin.bp)
|
||||
app.register_blueprint(webapp.api.bp)
|
||||
|
||||
# Custom filters
|
||||
@app.template_filter('inflect')
|
||||
@app.template_filter("inflect")
|
||||
def inflect(v, one, two, five):
|
||||
num = abs(v)
|
||||
|
||||
if num == 0:
|
||||
return '%d %s' % (v, five)
|
||||
return "%d %s" % (v, five)
|
||||
elif num == 1:
|
||||
return '%d %s' % (v, one)
|
||||
return "%d %s" % (v, one)
|
||||
elif num <= 4:
|
||||
return '%d %s' % (v, two)
|
||||
return "%d %s" % (v, two)
|
||||
|
||||
return '%d %s' % (v, five)
|
||||
return "%d %s" % (v, five)
|
||||
|
||||
# Custom CLI commands
|
||||
import webapp.commands
|
||||
|
||||
app.cli.commands.update(webapp.commands.group.commands)
|
||||
|
||||
app.json_encoder = DecimalEncoder
|
||||
|
|
Loading…
Reference in a new issue