1.0.1 release #15

Merged
williamp merged 35 commits from testing into master 2023-03-21 18:10:14 +00:00
32 changed files with 335 additions and 96 deletions

View File

@@ -9,6 +9,10 @@ globals:
password:
from_secret: REGISTRY_PASSWORD
steps:
- name: brand commit before build
image: bash
commands:
- echo ${DRONE_COMMIT_SHA:0:7} > app/__commit__
- name: build app-testing
image: plugins/docker
settings:
@@ -35,6 +39,10 @@ globals:
password:
from_secret: REGISTRY_PASSWORD
steps:
- name: brand commit before build
image: bash
commands:
- echo ${DRONE_COMMIT_SHA:0:7} > app/__commit__
- name: build-app-prod
image: plugins/docker
settings:
@@ -43,7 +51,6 @@ steps:
dockerfile: ./Dockerfile
tags: ["${DRONE_COMMIT_SHA:0:7}", "latest-prod"]
<<: *docker_creds
trigger:
branch:
- master

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
### Database file
database.db
database_mysql/
### Python template
# Byte-compiled / optimized / DLL files

View File

@@ -1,6 +1,7 @@
FROM python:3.11.0-alpine3.16
COPY ./app /app
WORKDIR /app
RUN apk add gcc musl-dev mariadb-connector-c-dev
RUN pip3 install -r requirements.txt
ENV FLASK_APP=app.py
CMD ["python3", "-m", "flask", "run", "--host=0.0.0.0"]
CMD ["gunicorn", "-b", "0.0.0.0:80", "-w", "4", "app:app"]

1
app/__commit__ Normal file
View File

@@ -0,0 +1 @@
unknown

1
app/__version__ Normal file
View File

@@ -0,0 +1 @@
1.0.1

View File

@@ -3,17 +3,21 @@ from flask import Flask, render_template, redirect, url_for, request, flash
from flask_migrate import Migrate
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import (LoginManager, login_user, login_required, logout_user, current_user)
from misc import datetime, date, time, currDay
from misc import datetime, date, time, currDay, prevDay, ZoneInfo, currVersion, currCommit
from db import (db, Period, Task, Event, User)
from forms import (TaskForm, EventForm, PeriodForm, SignupForm, LoginForm)
from forms import (TaskForm, EventForm, PeriodForm, SignupForm, LoginForm, SettingsForm)
from create_events import createEvents
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SECRET_KEY'] = 'HwG55rpe83jcaglifXm8NuF4WEeXyJV4'
app.config['SECRET_KEY'] = os.environ['SECRET_KEY']
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, os.environ['SQLITE_DB'])
'mysql://' + os.environ['MYSQL_USER'] + \
':' + os.environ['MYSQL_PASSWORD'] + \
'@' + os.environ['MYSQL_HOST'] + \
':' + os.environ['MYSQL_PORT'] + \
'/' + os.environ['MYSQL_DB']
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
@@ -21,14 +25,21 @@ db.init_app(app)
migrate = Migrate()
migrate.init_app(app, db)
# Schedule creation of events every hour
#with app.app_context():
# scheduleCreateEvents(app, db, currDay, Period, Event, createEvents)
# Authentication stuff
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.init_app(app)
if os.environ['SIGNUP_ENABLED'] == "YES":
signup_enabled = True
if 'SIGNUP_ENABLED' in os.environ:
if os.environ['SIGNUP_ENABLED'] == "YES":
signup_enabled = True
else:
signup_enabled = False
else:
signup_enabled = False
@@ -36,10 +47,32 @@ else:
def load_user(user_id):
return User.query.get(int(user_id))
# Context processor injects current version and commit
@app.context_processor
def injectVerCommit():
return dict(currVersion=currVersion, currCommit=currCommit, datetime=datetime, ZoneInfo=ZoneInfo)
# Error handling
# Pass env variables for debugging in prod
NODE_NAME = os.environ['NODE_NAME']
POD_NAME = os.environ['POD_NAME']
# Error Routes
@app.errorhandler(404)
def notFound(e):
return render_template('errors/404.html', NODE_NAME=NODE_NAME, POD_NAME=POD_NAME), 404
@app.errorhandler(403)
def forbidden(e):
return render_template('errors/403.html', NODE_NAME=NODE_NAME, POD_NAME=POD_NAME), 403
@app.errorhandler(500)
def ISEerror(e):
return render_template('errors/500.html', NODE_NAME=NODE_NAME, POD_NAME=POD_NAME), 500
# Index route
@app.route('/')
def index():
createEvents(db, currDay, Period, Event)
return redirect('/events')
# Authentication routes
@@ -49,12 +82,13 @@ def login():
if form.validate_on_submit():
userName = form.userName.data
password = form.password.data
remember = form.rememberMe.data
user = User.query.filter_by(userName=userName).first()
if not user or not check_password_hash(user.password, password):
flash('Credentials incorrect! Please try again')
return redirect(url_for('login'))
login_user(user)
login_user(user, remember=remember)
return redirect(url_for('events'))
return render_template('login.html', form=form)
@@ -82,6 +116,19 @@ def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/settings', methods=('GET', 'POST'))
@login_required
def settings():
user = User.query.get_or_404(current_user.id)
form = SettingsForm(obj=user)
if form.validate_on_submit():
user.realName = form.realName.data
user.timezone = form.timezone.data
if form.password.data != '':
user.password = generate_password_hash(form.password.data, method='sha256')
db.session.commit()
return render_template('settings.html', form=form)
# Periods routes
@app.route('/periods')
@login_required
@@ -99,6 +146,7 @@ def newPeriod():
)
db.session.add(period)
db.session.commit()
# Run createEvents upon adding new period
createEvents(db, currDay, Period, Event)
return redirect(f'/period/edit/{period.period}')
return render_template('newPeriod.html', form=form)
@@ -131,9 +179,8 @@ def delete_period(periodNum):
def events():
events = Event.query.all()
periods = Period.query.all()
createEvents(db, currDay, Period, Event)
return render_template('events.html', events=events, periods=periods, datetime=datetime, date=date)
return render_template('events.html', events=events, periods=periods, datetime=datetime, date=date, ZoneInfo=ZoneInfo)
@app.route('/event/edit/<int:event_id>/', methods=('GET', 'POST'))
@login_required

View File

@@ -9,3 +9,5 @@ def createEvents(db, currDay, Period, Event):
)
db.session.add(event)
db.session.commit()
print("createEvents script ran successfully")

View File

@@ -43,3 +43,4 @@ class User(UserMixin, db.Model):
email = db.Column(db.String(100), unique=True)
password = db.Column(db.String(100))
realName = db.Column(db.String(1000))
timezone = db.Column(db.String(20), default='UTC')

View File

@@ -1,6 +1,7 @@
import pytz
from db import Task
from flask_wtf import FlaskForm
from wtforms import (StringField, DateField, TimeField, TextAreaField, IntegerField, BooleanField,
from wtforms import (StringField, DateField, TimeField, TextAreaField, IntegerField, SelectField, BooleanField,
RadioField, EmailField, PasswordField)
from wtforms.validators import InputRequired, Length
from wtforms_sqlalchemy.orm import QuerySelectField
@@ -10,8 +11,7 @@ def get_tasks():
class TaskForm(FlaskForm):
title = StringField('Title', validators=[InputRequired(),
Length(min=5, max=100)])
description = TextAreaField('Description', validators=[InputRequired(),
Length(max=200)])
description = TextAreaField('Description', validators=[Length(max=200)])
class EventForm(FlaskForm):
# eventDate = DateField('Date', validators=[InputRequired()], format='m-%d-%Y')
# period_num = IntegerField(validators=[InputRequired()])
@@ -21,6 +21,11 @@ class PeriodForm(FlaskForm):
weekendSchedule = BooleanField(label='Include on Weekends?', false_values=None)
periodTime = TimeField('Time', format="%H:%M")
class SettingsForm(FlaskForm):
password = PasswordField('Password')
realName = StringField('Real Name')
timezone = SelectField('Time Zone', choices=pytz.all_timezones)
class SignupForm(FlaskForm):
userName = StringField('Username', validators=[InputRequired()])
password = PasswordField('Password', validators=[InputRequired()])
@@ -29,4 +34,5 @@ class SignupForm(FlaskForm):
class LoginForm(FlaskForm):
userName = StringField('Username', validators=[InputRequired()])
password = PasswordField('Password', validators=[InputRequired()])
password = PasswordField('Password', validators=[InputRequired()])
rememberMe = BooleanField(label='Remember me?')

View File

@@ -16,49 +16,49 @@ period9 = Period(period=9, periodTime='15:30:00', weekendSchedule=False)
task1 = Task(id=1,
title="Sexy ERP time",
description="Be the dominant partner and fuck so much XD",
created_timestamp='1668278862', due_timestamp='')
created_timestamp=1668278862, due_timestamp=None)
task2 = Task(id=2, title="Test task",
description="Test",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task3 = Task(id=3, title="La Nager",
description="Francis stuff",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task4 = Task(id=4, title="Ops/Tech Meeting",
description="HEIL GEORGE!",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task5 = Task(id=5, title="Tech Team Meeting",
description="Awkward AF",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task6 = Task(id=6, title="Write BellScheduler",
description="heh",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task7 = Task(id=7, title="Fap to cunny porn",
description="FBI OPEN UP!",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task8 = Task(id=8, title="Go on vrchat",
description="Mmm... virtual headpats!",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
task9 = Task(id=9, title="Brush teeth",
description="Ya dont do that more often, ya gross fuck",
created_timestamp='1668278862',
due_timestamp='')
created_timestamp=1668278862,
due_timestamp=None)
event1 = Event(id=1, scheduled_date='11-12-2022', period_num=1, task_id=4)
event2 = Event(id=2, scheduled_date='11-12-2022', period_num=2, task_id=2)
event3 = Event(id=3, scheduled_date='11-12-2022', period_num=3, task_id=5)
event4 = Event(id=4, scheduled_date='11-12-2022', period_num=4, task_id=6)
event5 = Event(id=5, scheduled_date='11-12-2022', period_num=5, task_id=1)
event6 = Event(id=6, scheduled_date='11-12-2022', period_num=6, task_id=3)
event7 = Event(id=7, scheduled_date='11-12-2022', period_num=7, task_id=7)
event8 = Event(id=8, scheduled_date='11-12-2022', period_num=8, task_id=8)
event9 = Event(id=9, scheduled_date='11-12-2022', period_num=9, task_id=9)
event1 = Event(id=1, scheduled_date='03-17-2023', period_num=1, task_id=4)
event2 = Event(id=2, scheduled_date='03-17-2023', period_num=2, task_id=2)
event3 = Event(id=3, scheduled_date='03-17-2023', period_num=3, task_id=5)
event4 = Event(id=4, scheduled_date='03-17-2023', period_num=4, task_id=6)
event5 = Event(id=5, scheduled_date='03-17-2023', period_num=5, task_id=1)
event6 = Event(id=6, scheduled_date='03-17-2023', period_num=6, task_id=3)
event7 = Event(id=7, scheduled_date='03-17-2023', period_num=7, task_id=7)
event8 = Event(id=8, scheduled_date='03-17-2023', period_num=8, task_id=8)
event9 = Event(id=9, scheduled_date='03-17-2023', period_num=9, task_id=9)
db.session.add_all([period1, period2, period3, period4, period5, period6, period7, period8, period9])
db.session.add_all([task1, task2, task3, task4, task5, task6, task7, task8, task9])

View File

@@ -1,36 +0,0 @@
"""empty message
Revision ID: bf65c9f77f9f
Revises:
Create Date: 2022-11-19 09:49:20.565127
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'bf65c9f77f9f'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('userName', sa.String(length=1000), nullable=True),
sa.Column('email', sa.String(length=100), nullable=True),
sa.Column('password', sa.String(length=100), nullable=True),
sa.Column('realName', sa.String(length=1000), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('user')
# ### end Alembic commands ###

View File

@@ -1,4 +1,17 @@
import time
from datetime import datetime, date
from datetime import datetime, date, timedelta
from zoneinfo import ZoneInfo
# Get current day in UTC and put it in str format
currDay = datetime.now()
currDay = currDay.strftime('%m-%d-%Y')
currDay = currDay.strftime('%m-%d-%Y')
# Get previous day in UTC and put it in str format
prevDay = datetime.now() + timedelta(days=-1)
prevDay = prevDay.strftime('%m-%d-%Y')
with open('__version__','r') as file:
currVersion = file.read()
with open('__commit__','r') as file:
currCommit = file.read()

View File

@@ -1,6 +1,9 @@
# This file is used by pip to install required python packages
# Usage: pip install -r requirements.txt
# Gunicorn WSGI Server
gunicorn==20.1.0
# Flask Framework
click==8.1.3
Flask==2.2.2
@@ -20,6 +23,15 @@ Flask-User==1.0.2.2
# WTForms Extensions
WTForms-SQLAlchemy==0.3.0
# APScheduler automated scheduler
APScheduler==3.9.1.post1
# Python Time packages
pytz==2022.6
# Automated tests
pytest==7.2.0
pytest-cov==4.0.0
# MySQL Package
mysqlclient==2.1.1

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
app/static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
app/static/manifest.json Normal file
View File

@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/static/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/static/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@@ -1,6 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Favicon manifest tags -->
<link rel="manifest" href="/static/manifest.json" />
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@@ -10,14 +14,14 @@
<title>{% block title %} {% endblock %} - BellScheduler</title>
</head>
<body>
<body class="d-flex flex-column min-vh-100">
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="{{ url_for('index') }}">BellScheduler</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<ul class="navbar-nav mr-auto mt-3 mt-lg-0">
<li class="nav-item">
<a class="nav-link" href="/events">Events</a>
</li>
@@ -27,14 +31,17 @@
<li class="nav-item">
<a class="nav-link" href="/periods">Periods</a>
</li>
</ul>
</div>
<div class="float-right">
{% if current_user.is_authenticated %}
<a href="{{ url_for('logout') }}" class="nav-link"> Logout {{current_user.userName}} </a>
<li class="nav-item">
<a class="nav-link" href="/settings">Settings</a>
</li>
{% endif %}
</ul>
{% if current_user.is_authenticated %}
<a href="{{ url_for('logout') }}"> Logout {{current_user.userName}} </a>
{% endif %}
{% if not current_user.is_authenticated %}
<a href="{{ url_for('login') }}" class="nav-link"> Login </a>
<a href="{{ url_for('login') }}"> Login </a>
{% endif %}
</div>
</nav>
@@ -42,7 +49,9 @@
<div class="container">
{% block content %} {% endblock %}
</div>
<footer class="card-footer mt-auto">
Version {{ currVersion }} &nbsp; &nbsp; Commit: {{ currCommit }}
</footer>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

View File

@@ -9,7 +9,10 @@
<p>
<b><a href="/task/{{ event.tasks.id }}">
{{ event.tasks.title }}
</a></b> <br> {{ event.tasks.description }}
</a></b> <br>{% if event.tasks.description != None %}
<p>{{ event.tasks.description }}</p>
{% endif %}
</p>
{% else %}
<div><p>(no task assigned... yet)</p></div>

View File

@@ -0,0 +1,22 @@
{% extends 'base.html' %}
{% set currDay = datetime.now() %}
{% set currTime = currDay.strftime('%I:%M %p') %}
{% set currDay = currDay.strftime('%m-%d-%Y') %}
{% block content %}
<span><h1><b>{% block title %} Error 403 {% endblock %}</h1></b></span>
<div>
<div>
<h2> Forbidden <br> <br> </h2>
</div>
<div>
Date: {{ currDay }} <br>
Time {{ currTime }} (UTC) <br> <br>
</div>
<div>
Node: {{ NODE_NAME }} <br>
Pod: {{ POD_NAME }}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends 'base.html' %}
{% set currDay = datetime.now() %}
{% set currTime = currDay.strftime('%I:%M %p') %}
{% set currDay = currDay.strftime('%m-%d-%Y') %}
{% block content %}
<span><h1><b>{% block title %} Error 404 {% endblock %}</h1></b></span>
<div>
<div>
<h2> Page Not Found <br> <br> </h2>
</div>
<div>
Date: {{ currDay }} <br>
Time {{ currTime }} (UTC) <br> <br>
</div>
<div>
Node: {{ NODE_NAME }} <br>
Pod: {{ POD_NAME }}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends 'base.html' %}
{% set currDay = datetime.now() %}
{% set currTime = currDay.strftime('%I:%M %p') %}
{% set currDay = currDay.strftime('%m-%d-%Y') %}
{% block content %}
<span><h1><b>{% block title %} Error 500 {% endblock %}</b></h1></span>
<div>
<div>
<h2> Internal Server Error <br> <br> </h2>
</div>
<div>
Date: {{ currDay }} <br>
Time {{ currTime }} (UTC) <br> <br>
</div>
<div>
Node: {{ NODE_NAME }} <br>
Pod: {{ POD_NAME }}
</div>
</div>
{% endblock %}

View File

@@ -1,10 +1,12 @@
{% extends 'base.html' %}
{% set currDay = datetime.now() %}
{% set currDay = currDay.astimezone(ZoneInfo(current_user.timezone)) %}
{% set currTime = currDay.strftime('%I:%M %p') %}
{% set currDay = currDay.strftime('%m-%d-%Y') %}
{% block content %}
<span><h1>{% block title %} Events {% endblock %}</h1></span>
<b>Current Date: {{ currDay }} </b> <br> <br>
<b>Current Date: {{ currDay }} </b> <br> <b>Current Time: {{ currTime }}</b> <br> <br>
<div>
{% for period in periods %}
<div>
@@ -18,7 +20,9 @@
</a>
</b>
<div>
{% if event.tasks.description != None %}
<p>{{ event.tasks.description }}</p>
{% endif %}
</div>
{% else %}
<div><p>(no task assigned... yet)</p></div>

View File

@@ -19,6 +19,9 @@
{{ form.password.label }}
{{ form.password }}
</p>
<p>
{{ form.rememberMe.label}} {{ form.rememberMe }}
</p>
<p>
<button class="btn btn-primary" type="submit">Submit</button>
</p>

View File

@@ -0,0 +1,23 @@
{% extends 'base.html' %}
{% block content %}
<span><h1>{% block title %} Settings {% endblock %}</h1></span>
<form method="post">
{{ form.csrf_token }}
<p>
<b>User: {{ current_user.userName }}</b>
<div>
{{ form.realName.label }} {{ form.realName }}
</div> <br>
<div>
{{ form.password.label }} {{ form.password }}
</div> <br>
<div>
{{ form.timezone.label }} {{ form.timezone }}
</div>
</p>
<p>
<button class="btn btn-primary" type="submit">Submit</button>
</p>
</form>
{% endblock %}

View File

@@ -8,7 +8,9 @@
<div>
<div>
<br>
<p>{{ task.description }}</p>
{% if task.description != None %}
<p>{{ task.description }}</p>
{% endif %}
</div>
<div>
<p>Created: {{ createdTime.strftime('%Y-%m-%d %I:%M %p') }} </p>

View File

@@ -11,7 +11,9 @@
<p><b>{{ task.title }}</b> </p>
</a>
<b>
{{ task.description }}
{% if task.description != None %}
{{ task.description }}
{% endif %}
</b>
<div>
<p>Created: {{ createdTime.strftime('%Y-%m-%d %I:%M %p') }}</p>
@@ -19,4 +21,5 @@
<hr>
</div>
{% endfor %}
</div>
{% endblock %}

35
app/worker.py Normal file
View File

@@ -0,0 +1,35 @@
import os
from flask import Flask
from misc import currDay, datetime, time, timedelta
from db import db, Period, Event
from create_events import createEvents
from apscheduler.schedulers.background import BlockingScheduler
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ['SECRET_KEY']
app.config['SQLALCHEMY_DATABASE_URI'] =\
'mysql://' + os.environ['MYSQL_USER'] + \
':' + os.environ['MYSQL_PASSWORD'] + \
'@' + os.environ['MYSQL_HOST'] + \
':' + os.environ['MYSQL_PORT'] + \
'/' + os.environ['MYSQL_DB']
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
# Define function to run create_events with app context
def run_create_events():
with app.app_context():
createEvents(db, currDay, Period, Event)
# Call createEvents on initial launch of the script
run_create_events()
# Set up scheduler to run function at 59th minute of every hour
scheduler = BlockingScheduler()
scheduler.add_job(run_create_events, 'cron', minute=59)
# Start scheduler
scheduler.start()

View File

@@ -4,8 +4,42 @@ services:
image: container-registry.infra.dubyatp.xyz/bellscheduler/app:latest-testing
restart: always
environment:
- SQLITE_DB=database.db
volumes:
- ./database.db:/app/database.db
- MYSQL_USER=root
- MYSQL_PASSWORD=notasecuresecretkeyonlyuseforlocaldevelopment
- MYSQL_HOST=db
- MYSQL_PORT=3306
- MYSQL_DB=bellscheduler
- SECRET_KEY=notasecuresecretkeyonlyuseforlocaldevelopment
- NODE_NAME=local
- POD_NAME=local
- FLASK_ENV=development
- FLASK_DEBUG=1
- PYTHONUNBUFFERED=1
ports:
- 127.0.0.1:5000:5000
- 127.0.0.1:80:80
worker:
image: container-registry.infra.dubyatp.xyz/bellscheduler/app:latest-testing
restart: always
entrypoint: python3
command: "-m worker"
environment:
- MYSQL_USER=root
- MYSQL_PASSWORD=notasecuresecretkeyonlyuseforlocaldevelopment
- MYSQL_HOST=db
- MYSQL_PORT=3306
- MYSQL_DB=bellscheduler
- SECRET_KEY=notasecuresecretkeyonlyuseforlocaldevelopment
- NODE_NAME=local
- POD_NAME=local
- FLASK_ENV=development
- FLASK_DEBUG=1
- PYTHONUNBUFFERED=1
db:
image: mariadb:10.7.8-focal
restart: always
environment:
- MARIADB_ROOT_PASSWORD=notasecuresecretkeyonlyuseforlocaldevelopment
volumes:
- ./database_mysql:/var/lib/mysql
ports:
- 127.0.0.1:3306:3306