Skip to content

Commit e56eb97

Browse files
committedJun 27, 2017
Implement database migrations (bug 1376479)
We're using Alembic with Flask-Alembic. Added revision and upgrade manage.py commands. Created a initialization migration. Removed the schema file, `upgrade` is used to create the tables. Use `invoke revision {name-of-revision}` to create a migration revision.
1 parent 6d48c6f commit e56eb97

11 files changed

+113
-13
lines changed
 

‎README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ our code management microservice ecosystem.
1515

1616
##### Running the development server
1717

18-
To create a database schema:
18+
To create a database:
1919

2020
```bash
21-
$ invoke create_db
21+
$ invoke upgrade
2222
```
2323

2424
To build and start the development services' containers:

‎docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ services:
2121
- DATABASE_URL=sqlite:////db/sqlite.db
2222
volumes:
2323
- ./.db/:/db/
24+
- ./migrations/:/migrations/
2425
py3-linter:
2526
build:
2627
context: ./

‎docker/Dockerfile-prod

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ RUN apk --update --no-cache add \
1212
RUN mkdir /db
1313
RUN chown app:app /db
1414

15+
COPY migrations /migrations
16+
1517
COPY requirements.txt /requirements.txt
1618
RUN pip install --no-cache -r /requirements.txt
1719

‎docker/db/schema.db

-12 KB
Binary file not shown.

‎landoapi/app.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
import click
77
import connexion
8+
89
from connexion.resolver import RestyResolver
910
from landoapi.dockerflow import dockerflow
10-
from landoapi.models.storage import db
11+
from landoapi.models.storage import alembic, db
1112

1213

1314
def create_app(version_path):
@@ -22,9 +23,16 @@ def create_app(version_path):
2223
'SQLALCHEMY_DATABASE_URI', os.environ.get('DATABASE_URL', 'sqlite://')
2324
)
2425
flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
26+
flask_app.config['ALEMBIC'] = {'script_location': '/migrations/'}
2527

2628
flask_app.register_blueprint(dockerflow)
29+
30+
# Initialize database
2731
db.init_app(flask_app)
32+
33+
# Intialize the alembic extension
34+
alembic.init_app(app.app)
35+
2836
return app
2937

3038

‎landoapi/manage.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,25 @@
33
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
44

55
from landoapi.app import create_app
6-
from landoapi.models.storage import db
6+
from landoapi.models.storage import alembic
77

88
from flask_script import Manager
99

1010
app = create_app('/version.json')
11+
1112
manager = Manager(app.app)
1213

1314

1415
@manager.command
15-
def create_db():
16-
"""Creates SQLAlchemy database schema."""
17-
return db.create_all()
16+
def revision(message):
17+
"""Generate a new migration revision."""
18+
return alembic.revision(message)
19+
20+
21+
@manager.command
22+
def upgrade():
23+
"""Run all available migration upgrades."""
24+
return alembic.upgrade()
1825

1926

2027
if __name__ == "__main__":

‎landoapi/models/storage.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# This Source Code Form is subject to the terms of the Mozilla Public
22
# License, v. 2.0. If a copy of the MPL was not distributed with this
33
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
from flask_alembic import Alembic
45
from flask_sqlalchemy import SQLAlchemy
56

67
db = SQLAlchemy()
8+
alembic = Alembic()
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""add landings
2+
3+
Revision ID: ae9dd729e66c
4+
Revises:
5+
Create Date: 2017-06-20 17:13:22.173811
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
# revision identifiers, used by Alembic.
12+
revision = 'ae9dd729e66c'
13+
down_revision = None
14+
branch_labels = ('default', )
15+
depends_on = None
16+
17+
18+
def upgrade():
19+
# ### commands auto generated by Alembic - please adjust! ###
20+
op.create_table(
21+
'landings',
22+
sa.Column('id', sa.Integer(), nullable=False),
23+
sa.Column('request_id', sa.Integer(), nullable=True),
24+
sa.Column('revision_id', sa.String(length=30), nullable=True),
25+
sa.Column('status', sa.Integer(), nullable=True),
26+
sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('request_id')
27+
)
28+
# ### end Alembic commands ###
29+
30+
31+
def downgrade():
32+
# ### commands auto generated by Alembic - please adjust! ###
33+
op.drop_table('landings')
34+
# ### end Alembic commands ###

‎migrations/script.py.mako

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""${message}
2+
3+
Revision ID: ${up_revision}
4+
Revises: ${down_revision | comma,n}
5+
Create Date: ${create_date}
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
${imports if imports else ""}
11+
12+
# revision identifiers, used by Alembic.
13+
revision = ${repr(up_revision)}
14+
down_revision = ${repr(down_revision)}
15+
branch_labels = ${repr(branch_labels)}
16+
depends_on = ${repr(depends_on)}
17+
18+
19+
def upgrade():
20+
${upgrades if upgrades else "pass"}
21+
22+
23+
def downgrade():
24+
${downgrades if downgrades else "pass"}

‎requirements.txt

+13
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,16 @@ Flask-SQLAlchemy==2.2 \
5757
--hash=sha256:fa3bd6343de231b2b3376a276df6d331c63c766449b660fc04d375a1c21312ac
5858
Flask-Script==2.0.5 \
5959
--hash=sha256:cef76eac751396355429a14c38967bb14d4973c53e07dec94af5cc8fb017107f
60+
alembic==0.9.2 \
61+
--hash=sha256:a2b6b599f48b39ebf33b7dd069463924ca59c94aae7ae6f3661e0e54b5e78647
62+
Mako==1.0.6 \
63+
--hash=sha256:48559ebd872a8e77f92005884b3d88ffae552812cdf17db6768e5c3be5ebbe0d
64+
python-editor==1.0.3 \
65+
--hash=sha256:a3c066acee22a1c94f63938341d4fb374e3fdd69366ed6603d7b24bed1efc565
66+
python-dateutil==2.6.0 \
67+
--hash=sha256:62a2f8df3d66f878373fd0072eacf4ee52194ba302e00082828e0d263b0418d2 \
68+
--hash=sha256:3acbef017340600e9ff8f2994d8f7afd6eacb295383f286466a6df3961e486f0 \
69+
--hash=sha256:537bf2a8f8ce6f6862ad705cd68f9e405c0b5db014aa40fa29eab4335d4b1716
70+
Flask-Alembic==2.0.1 \
71+
--hash=sha256:05a1e6f4148dbfcc9280a393373bfbd250af6f9f4f0ca9f744ef8f7376a3deec \
72+
--hash=sha256:7e67740b0b08d58dcae0c701d56b56e60f5fa4af907bb82b4cb0469229ba94ff

‎tasks.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def version(ctx):
7171
print(json.dumps(version))
7272

7373

74-
@task(name='build')
74+
@task
7575
def build(ctx):
7676
"""Build the production docker image."""
7777
ctx.run(
@@ -89,12 +89,21 @@ def imageid(ctx):
8989
)
9090

9191

92-
@task(name='create_db')
93-
def create_db(ctx):
94-
"""Call `create_all` on a SQLAlchemy database."""
92+
@task
93+
def revision(ctx, msg):
94+
"""Call Alembic to create a migration revision"""
95+
ctx.run(
96+
"docker-compose run --rm lando-api "
97+
"python landoapi/manage.py revision '%s'" % msg
98+
)
99+
100+
101+
@task
102+
def upgrade(ctx):
103+
"""Call Alembic to run all available migration upgrades."""
95104
ctx.run(
96105
"docker-compose run --rm lando-api "
97-
"python landoapi/manage.py create_db"
106+
"python landoapi/manage.py upgrade"
98107
)
99108

100109

@@ -104,5 +113,5 @@ def create_db(ctx):
104113
lint_all,
105114
lint_flake8,
106115
lint_yapf,
107-
), build, create_db, format, imageid, test, version
116+
), build, format, imageid, revision, test, upgrade, version
108117
)

0 commit comments

Comments
 (0)
Failed to load comments.