z2 added
This commit is contained in:
parent
317dc8ed79
commit
8c9cccb2a1
9
z2/.env
Normal file
9
z2/.env
Normal file
@ -0,0 +1,9 @@
|
||||
# Add Environment Variables
|
||||
|
||||
DEBUG=False
|
||||
SECRET_KEY=5(15ds+i2+%ik6z&!yer+ga9m=e%jcqiz_5wszg)r-z!2--b2d
|
||||
DB_NAME=postgres
|
||||
DB_USER=postgres
|
||||
DB_PASS=postgres
|
||||
DB_SERVICE=postgres
|
||||
DB_PORT=5432
|
26
z2/README.md
Normal file
26
z2/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
Jednoducha message web aplikacia pouzivajuca Flask, Nginx a Postgres.
|
||||
|
||||
Prerobil som aplikaciu zo zadania z1.
|
||||
Aplikacia obsahuje 4 pody. Web, Data, Nginx a Postgres.
|
||||
start skriptom start-app.sh a zastavenie stop-app.sh
|
||||
Vsetky sluzby, persistent volumes aj deploymenty bezia podla minikube Kubernetes GUI spravne, avsak GUI stranku aplikacie neviem najst/nespusta sa spravne. Myslim ze ide o nejaky networking problem kedze ta ista aplikacia bez Kubernetes funguje spravne. Myslim ze porty mam exposnute spravne, viem to zistit prikazom "kubectl describe services". Tam vidime ze service "web" je exposnuty na porte 8000 ako chceme, napriklad na lokalnej adrese 127.17.0.7:8000. V browseri vsak na tejto adrese nie je frontend ako by som ocakaval. Ak budete mat cas niekedy, velmi by mi pomohlo ak by ste so mnou na to pozreli, kedze toto by som chcel deploynut aj na public cloud v ramci skusky.
|
||||
|
||||
Sucastou su 4 .yaml skripty ktore sa aplikuju do Kubernete start-app skriptom.
|
||||
|
||||
ngingx-deployment.yaml:
|
||||
Zakladny deployment ktory vytvori pod
|
||||
Service nginx pouzivany podom
|
||||
Persiste volume claim ako trvale ulozisko
|
||||
|
||||
data-deployment.yaml:
|
||||
opat deployment ktory vytvori pod
|
||||
PVC ulozisko
|
||||
|
||||
postgres-deployment.yaml:
|
||||
Deployment + service
|
||||
|
||||
web-deployment.yaml:
|
||||
Deployment + service + PVC
|
||||
Prave v tomto yaml subore bude zrejme chyba. Neviem vsak identifikovat kde, kedze podla niekolkych navodov exposujem port webu spravne a aj je zobrazeny "describe services" prikazom.
|
||||
|
||||
stop-app.sh odstrani vsetky sucasti vratane persistent volumes
|
49
z2/data-deployment.yaml
Normal file
49
z2/data-deployment.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
service: data
|
||||
name: data
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: data
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: data
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- "true"
|
||||
image: postgres:latest
|
||||
command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
|
||||
name: data
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/postgresql/data
|
||||
name: db-data
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: db-data
|
||||
persistentVolumeClaim:
|
||||
claimName: db-data
|
||||
status: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
service: db-data
|
||||
name: db-data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Mi
|
||||
status: {}
|
46
z2/docker-compose.yml
Normal file
46
z2/docker-compose.yml
Normal file
@ -0,0 +1,46 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
web:
|
||||
restart: always
|
||||
build: ./web
|
||||
expose:
|
||||
- "8000"
|
||||
links:
|
||||
- postgres:postgres
|
||||
volumes:
|
||||
- web-data:/usr/src/app/static
|
||||
env_file:
|
||||
- .env
|
||||
command: /usr/local/bin/gunicorn -w 2 -b :8000 app:app
|
||||
|
||||
nginx:
|
||||
restart: always
|
||||
build: ./nginx
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- .:/www/static
|
||||
- web-data:/usr/src/app/static
|
||||
links:
|
||||
- web:web
|
||||
|
||||
data:
|
||||
image: postgres:latest
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
command: "true"
|
||||
|
||||
postgres:
|
||||
restart: always
|
||||
image: postgres:latest
|
||||
environment:
|
||||
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
web-data:
|
15
z2/env-configmap.yaml
Normal file
15
z2/env-configmap.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
DB_NAME: postgres
|
||||
DB_PASS: postgres
|
||||
DB_PORT: "5432"
|
||||
DB_SERVICE: postgres
|
||||
DB_USER: postgres
|
||||
DEBUG: "False"
|
||||
SECRET_KEY: 5(15ds+i2+%ik6z&!yer+ga9m=e%jcqiz_5wszg)r-z!2--b2d
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: web-env
|
||||
name: env
|
69
z2/nginx-deployment.yaml
Normal file
69
z2/nginx-deployment.yaml
Normal file
@ -0,0 +1,69 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
service: nginx
|
||||
name: nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: nginx
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /www/static
|
||||
name: nginx-claim0
|
||||
- mountPath: /usr/src/app/static
|
||||
name: web-data
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: nginx-claim0
|
||||
persistentVolumeClaim:
|
||||
claimName: nginx-claim0
|
||||
- name: web-data
|
||||
persistentVolumeClaim:
|
||||
claimName: web-data
|
||||
status: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
service: nginx
|
||||
name: nginx
|
||||
spec:
|
||||
ports:
|
||||
- name: "8080"
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
service: nginx
|
||||
status:
|
||||
loadBalancer: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
service: nginx-claim0
|
||||
name: nginx-claim0
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Mi
|
||||
status: {}
|
5
z2/nginx/Dockerfile
Normal file
5
z2/nginx/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
||||
FROM tutum/nginx
|
||||
|
||||
RUN rm /etc/nginx/sites-enabled/default
|
||||
|
||||
COPY sites-enabled/ /etc/nginx/sites-enabled
|
17
z2/nginx/sites-enabled/flask_project
Normal file
17
z2/nginx/sites-enabled/flask_project
Normal file
@ -0,0 +1,17 @@
|
||||
server {
|
||||
|
||||
listen 8080;
|
||||
server_name example.org;
|
||||
charset utf-8;
|
||||
|
||||
location /static {
|
||||
alias /usr/src/app/static;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://web:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
52
z2/postgres-deployment.yaml
Normal file
52
z2/postgres-deployment.yaml
Normal file
@ -0,0 +1,52 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
service: postgres
|
||||
name: postgres
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: postgres
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: postgres
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: POSTGRES_HOST_AUTH_METHOD
|
||||
value: trust
|
||||
image: postgres:latest
|
||||
name: postgres
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/postgresql/data
|
||||
name: db-data
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: db-data
|
||||
persistentVolumeClaim:
|
||||
claimName: db-data
|
||||
status: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
service: postgres
|
||||
name: postgres
|
||||
spec:
|
||||
ports:
|
||||
- name: "5432"
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
selector:
|
||||
service: postgres
|
||||
status:
|
||||
loadBalancer: {}
|
18
z2/start-app.sh
Executable file
18
z2/start-app.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
#tento script pripravi a spusti vsetko, po jeho ukonceni je aplikacia beziaca a funkcna
|
||||
#predpoklada sa ze kubectl a minikube su spustene
|
||||
|
||||
echo "*Starting setup*"
|
||||
|
||||
echo "*Deploying postgres*"
|
||||
kubectl apply -f postgres-deployment.yaml
|
||||
echo "*Deploying nginx*"
|
||||
kubectl apply -f nginx-deployment.yaml
|
||||
echo "*Deploying data*"
|
||||
kubectl apply -f data-deployment.yaml
|
||||
echo "*Deploying web*"
|
||||
kubectl apply -f web-deployment.yaml
|
||||
echo "*Deploying configmap*"
|
||||
kubectl apply -f env-configmap.yaml
|
||||
echo "*Done*"
|
32
z2/stop-app.sh
Executable file
32
z2/stop-app.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
#tento script odstrani vsetky deploymenty/pody/service/persistent-volumes
|
||||
|
||||
|
||||
|
||||
kubectl delete -n default deployment web
|
||||
echo "*Deployment web deleted*"
|
||||
kubectl delete -n default deployment data
|
||||
echo "*Deployment data deleted*"
|
||||
kubectl delete -n default deployment nginx
|
||||
echo "*Deployment nginx deleted*"
|
||||
kubectl delete -n default deployment postgres
|
||||
echo "*Deployment postgres deleted*"
|
||||
kubectl delete -n default service web
|
||||
echo "*Service web deleted*"
|
||||
kubectl delete -n default service nginx
|
||||
echo "*Service web deleted*"
|
||||
kubectl delete -n default service postgres
|
||||
echo "*Service web deleted*"
|
||||
kubectl delete -n default configmap env
|
||||
echo "*Service web deleted*"
|
||||
kubectl get pv | tail -n+3 | awk '{print $1}' | xargs -I{} kubectl patch pv {} -p '{"metadata":{"finalizers": null}}'
|
||||
echo "*Finalizers edited so deletes don't hang*"
|
||||
kubectl delete pvc db-data --grace-period=0 --force --wait=false
|
||||
echo "*PVC db-data deleted*"
|
||||
kubectl delete pvc nginx-claim0 --grace-period=0 --force --wait=false
|
||||
echo "*PVC nginx deleted*"
|
||||
kubectl delete pvc web-data --grace-period=0 --force --wait=false
|
||||
echo "*PVC web-data deleted*"
|
||||
echo "------------"
|
||||
echo "App stopped"
|
107
z2/web-deployment.yaml
Normal file
107
z2/web-deployment.yaml
Normal file
@ -0,0 +1,107 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
service: web
|
||||
name: web
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: web
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: web
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- /usr/local/bin/gunicorn
|
||||
- -w
|
||||
- "2"
|
||||
- -b
|
||||
- :8000
|
||||
- app:app
|
||||
env:
|
||||
- name: DB_NAME
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: DB_NAME
|
||||
name: env
|
||||
- name: DB_PASS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: DB_PASS
|
||||
name: env
|
||||
- name: DB_PORT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: DB_PORT
|
||||
name: env
|
||||
- name: DB_SERVICE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: DB_SERVICE
|
||||
name: env
|
||||
- name: DB_USER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: DB_USER
|
||||
name: env
|
||||
- name: DEBUG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: DEBUG
|
||||
name: env
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: SECRET_KEY
|
||||
name: env
|
||||
image: nameton/z2_web:2
|
||||
name: web
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /usr/src/app/static
|
||||
name: web-data
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: web-data
|
||||
persistentVolumeClaim:
|
||||
claimName: web-data
|
||||
status: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
service: web
|
||||
name: web
|
||||
spec:
|
||||
ports:
|
||||
- name: "8000"
|
||||
port: 8000
|
||||
targetPort: 8000
|
||||
selector:
|
||||
service: web
|
||||
status:
|
||||
loadBalancer: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
service: web-data
|
||||
name: web-data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Mi
|
||||
status: {}
|
10
z2/web/Dockerfile
Normal file
10
z2/web/Dockerfile
Normal file
@ -0,0 +1,10 @@
|
||||
FROM python:3.7-slim
|
||||
|
||||
RUN python -m pip install --upgrade pip
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY requirements.txt requirements.txt
|
||||
RUN python -m pip install -r requirements.txt
|
||||
|
||||
COPY . .
|
30
z2/web/app.py
Normal file
30
z2/web/app.py
Normal file
@ -0,0 +1,30 @@
|
||||
# app.py
|
||||
|
||||
|
||||
from flask import Flask
|
||||
from flask import request, render_template
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from config import BaseConfig
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(BaseConfig)
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
|
||||
from models import *
|
||||
|
||||
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
def index():
|
||||
if request.method == 'POST':
|
||||
text = request.form['text']
|
||||
post = Post(text)
|
||||
db.session.add(post)
|
||||
db.session.commit()
|
||||
posts = Post.query.order_by(Post.date_posted.desc()).all()
|
||||
return render_template('index.html', posts=posts)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
28
z2/web/config.py
Normal file
28
z2/web/config.py
Normal file
@ -0,0 +1,28 @@
|
||||
# config.py
|
||||
|
||||
|
||||
import os
|
||||
|
||||
|
||||
class BaseConfig(object):
|
||||
SECRET_KEY = os.environ['SECRET_KEY']
|
||||
DEBUG = os.environ['DEBUG']
|
||||
DB_NAME = os.environ['DB_NAME']
|
||||
DB_USER = os.environ['DB_USER']
|
||||
DB_PASS = os.environ['DB_PASS']
|
||||
DB_SERVICE = os.environ['DB_SERVICE']
|
||||
DB_PORT = os.environ['DB_PORT']
|
||||
SQLALCHEMY_DATABASE_URI = 'postgresql://{0}:{1}@{2}:{3}/{4}'.format(
|
||||
DB_USER, DB_PASS, DB_SERVICE, DB_PORT, DB_NAME
|
||||
)
|
||||
|
||||
|
||||
# class BaseConfig(object):
|
||||
# SECRET_KEY = 'hi'
|
||||
# DEBUG = True
|
||||
# DB_NAME = 'postgres'
|
||||
# DB_SERVICE = 'localhost'
|
||||
# DB_PORT = 5432
|
||||
# SQLALCHEMY_DATABASE_URI = 'postgresql://{0}:{1}/{2}'.format(
|
||||
# DB_SERVICE, DB_PORT, DB_NAME
|
||||
# )
|
6
z2/web/create_db.py
Normal file
6
z2/web/create_db.py
Normal file
@ -0,0 +1,6 @@
|
||||
# create_db.py
|
||||
|
||||
|
||||
from app import db
|
||||
|
||||
db.create_all()
|
18
z2/web/models.py
Normal file
18
z2/web/models.py
Normal file
@ -0,0 +1,18 @@
|
||||
# models.py
|
||||
|
||||
|
||||
import datetime
|
||||
from app import db
|
||||
|
||||
|
||||
class Post(db.Model):
|
||||
|
||||
__tablename__ = 'posts'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
text = db.Column(db.String, nullable=False)
|
||||
date_posted = db.Column(db.DateTime, nullable=False)
|
||||
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.date_posted = datetime.datetime.now()
|
9
z2/web/requirements.txt
Normal file
9
z2/web/requirements.txt
Normal file
@ -0,0 +1,9 @@
|
||||
Flask==1.0.2
|
||||
Flask-SQLAlchemy==2.3.2
|
||||
Jinja2==2.10
|
||||
MarkupSafe==1.1.1
|
||||
SQLAlchemy==1.3.1
|
||||
Werkzeug==0.15.1
|
||||
gunicorn==19.9.0
|
||||
itsdangerous==1.1.0
|
||||
psycopg2==2.7.7
|
5
z2/web/static/css/bootstrap.min.css
vendored
Normal file
5
z2/web/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5
z2/web/static/css/main.css
Normal file
5
z2/web/static/css/main.css
Normal file
@ -0,0 +1,5 @@
|
||||
/* custom styles */
|
||||
|
||||
.container {
|
||||
max-width: 500px;
|
||||
}
|
1
z2/web/static/img/.gitkeep
Normal file
1
z2/web/static/img/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
|
7
z2/web/static/js/bootstrap.min.js
vendored
Normal file
7
z2/web/static/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
z2/web/static/js/main.js
Normal file
1
z2/web/static/js/main.js
Normal file
@ -0,0 +1 @@
|
||||
// custom scripts
|
27
z2/web/templates/_base.html
Normal file
27
z2/web/templates/_base.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Flask on Docker</title>
|
||||
<!-- meta -->
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<!-- styles -->
|
||||
<link href="static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="static/css/main.css" rel="stylesheet">
|
||||
{% block css %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<br>
|
||||
<!-- child template -->
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<!-- scripts -->
|
||||
<script src="//code.jquery.com/jquery-1.11.2.min.js" type="text/javascript"></script>
|
||||
<script src="static/js/bootstrap.min.js" type="text/javascript"></script>
|
||||
<script src="static/js/main.js" type="text/javascript"></script>
|
||||
{% block js %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
27
z2/web/templates/index.html
Normal file
27
z2/web/templates/index.html
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends "_base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="text-center">
|
||||
<h1>Welcome!</h1>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<form action="/" method="POST">
|
||||
<div class="form-group">
|
||||
<input name="text" class="form-control input-lg" type="text" placeholder="Enter a message" required>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-primary btn-lg btn-block" value="Submit">
|
||||
</form>
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
|
||||
<div>
|
||||
{% for post in posts %}
|
||||
<h4 class="well"><strong>{{post.text}}</strong> - <em>{{post.date_posted.strftime('%Y-%m-%d')}}</em></h4>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user