Skip to content

Commit 82e5e38

Browse files
authored
Merge pull request #80 from CESNET/develop
Develop
2 parents 76327c8 + cd8dc5d commit 82e5e38

28 files changed

+3184
-247
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
config.py
22
instance_config_override.py
33
run.py
4-
migrations/
54

65
# PyPi
76
.pypirc

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@ All notable changes to ExaFS will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.2.2] - 2026-02-19
9+
10+
### Changed
11+
- **Database migrations now tracked in git**`migrations/` removed from `.gitignore`
12+
- Replaced `db-init.py` with migration-based initialization (`flask db upgrade`)
13+
- Removed one-time `/admin/set-org-if-zero` endpoint, replaced with standalone `scripts/migrate_v0x_to_v1.py`
14+
- Fixed Flask-SQLAlchemy deprecation warning in Alembic `env.py`
15+
- Template URLs changed to use `url_for` helper, removed unused `rule.html` template
16+
- **`db-init.py` and `create-admin.py` moved to `scripts/`** — all setup scripts now live under `scripts/`
17+
18+
### Added
19+
- Idempotent baseline migration (`001_baseline`) that brings any ExaFS database (from v0.4+ to current) to the v1.2.2 schema
20+
- Optional `scripts/migrate_v0x_to_v1.py` helper for v0.x to v1.0+ data migration (org_id backfill)
21+
- `scripts/create-admin.py` — interactive script to create the first admin user and organization (replaces manual SQL inserts)
22+
- `scripts/db-init.py --reset` flag for development database reset
23+
- Migration test suite (`tests/test_migration.py`) — 46 tests covering fresh install, idempotency, upgrade from v0.4/v0.8/v1.0 schemas, and real 2019 production backup upgrade
24+
- `PYTHONPATH` set in Docker dev container for easier development
25+
826
## [1.2.1] - 2026-01-30
927

1028
### Fixed
@@ -286,6 +304,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
286304
- Route Distinguisher for VRF now supported
287305
- See config example and update your `config.py`
288306

307+
[1.2.2]: https://github.com/CESNET/exafs/compare/v1.2.1...v1.2.2
308+
[1.2.1]: https://github.com/CESNET/exafs/compare/v1.2.0...v1.2.1
289309
[1.2.0]: https://github.com/CESNET/exafs/compare/v1.1.9...v1.2.0
290310
[1.1.9]: https://github.com/CESNET/exafs/compare/v1.1.8...v1.1.9
291311
[1.1.8]: https://github.com/CESNET/exafs/compare/v1.1.7...v1.1.8

CLAUDE.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ exafs/
115115
├── config.example.py # Configuration template
116116
├── instance_config_override.example.py # Dashboard override template
117117
├── run.example.py # Application run script template
118-
├── db-init.py # Database initialization script
118+
├── scripts/
119+
│ ├── db-init.py # Database initialization (runs flask db upgrade)
120+
│ ├── create-admin.py # Interactive first admin user setup
121+
│ └── migrate_v0x_to_v1.py # Optional v0.x to v1.0+ migration helper
119122
├── pyproject.toml # Project metadata and dependencies
120123
├── setup.cfg # Setup configuration
121124
├── CHANGELOG.md # Version history
@@ -283,8 +286,11 @@ cp run.example.py run.py
283286

284287
# Edit config.py with database credentials and settings
285288

286-
# Initialize database
287-
python db-init.py
289+
# Initialize database (runs flask db upgrade)
290+
python scripts/db-init.py
291+
292+
# Create the first admin user and organization
293+
python scripts/create-admin.py
288294

289295
# Run tests
290296
pytest
@@ -295,15 +301,20 @@ python run.py
295301

296302
### Database Migrations
297303

304+
Migration files are tracked in `migrations/versions/` and committed to git.
305+
298306
```bash
299-
# Create a new migration
307+
# Create a new migration after model changes
300308
flask db migrate -m "Description of changes"
301309

302310
# Apply migrations
303311
flask db upgrade
304312

305313
# Rollback migration
306314
flask db downgrade
315+
316+
# For existing databases adopting migrations for the first time
317+
flask db stamp 001_baseline
307318
```
308319

309320
### Running Tests
@@ -787,8 +798,17 @@ flask db migrate -m "message" # Create migration
787798
flask db upgrade # Apply migrations
788799
flake8 . # Lint code
789800

790-
# Database
791-
python db-init.py # Initialize database
801+
# Database (source install)
802+
python scripts/db-init.py # Initialize database (runs migrations)
803+
python scripts/db-init.py --reset # Drop all tables and recreate (dev only)
804+
python scripts/create-admin.py # Create first admin user interactively
805+
806+
# Database (PyPI install — run from directory containing config.py)
807+
exafs-db-init # Initialize database (runs migrations)
808+
exafs-db-init --reset # Drop all tables and recreate (dev only)
809+
exafs-create-admin # Create first admin user interactively
810+
811+
flask db stamp 001_baseline # Mark existing DB as baseline
792812
flask db current # Show current migration
793813
flask db history # Show migration history
794814

@@ -804,7 +824,7 @@ supervisorctl status # Check status
804824
When working with this codebase:
805825

806826
1. **Always run tests** after making changes: `pytest`
807-
2. **Create migrations** for model changes: `flask db migrate`
827+
2. **Create migrations** for model changes: `flask db migrate` — commit migration files to git
808828
3. **Follow the service layer pattern** - business logic goes in services, not views
809829
4. **Use existing validators** in `flowapp/validators.py` for validation
810830
5. **Check authentication** - most routes need `@auth_required` decorator

db-init.py

Lines changed: 0 additions & 39 deletions
This file was deleted.

docs/DB_MIGRATIONS.md

Lines changed: 98 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,115 @@
1-
# How to Upgrade the Database
1+
# Database Migrations
22

3-
## General Guidelines
4-
Migrations can be inconsistent. To avoid issues, we removed migrations from git repostory. To start the migration on your server, it is recomended reset the migration state on the server and run the migration based on the updated database models when switching application versions via Git.
3+
ExaFS uses [Flask-Migrate](https://flask-migrate.readthedocs.io/) (Alembic) for database schema management. Migration files are shipped inside the `flowapp` package (`flowapp/migrations/`) and are found automatically — no `flask db init` is needed.
4+
5+
## New Installation
6+
7+
For a fresh database, run the migrations to create all tables and seed data:
8+
9+
```bash
10+
flask db upgrade
11+
```
12+
13+
Or use the init script (source install):
14+
15+
```bash
16+
python scripts/db-init.py
17+
```
18+
19+
Or the installed command (PyPI install):
520

621
```bash
7-
rm -rf migrations/
22+
exafs-db-init
823
```
924

10-
```SQL
11-
DROP TABLE alembic_version;
25+
## Upgrading Between Versions
26+
27+
When upgrading ExaFS to a new version, apply any new migrations:
28+
29+
```bash
30+
flask db upgrade
31+
```
32+
33+
This will apply only the migrations that haven't been applied yet.
34+
35+
## Existing Installation (One-Time Setup)
36+
37+
If you already have a running ExaFS database from any previous version, the baseline migration is idempotent — it will create missing tables, add missing columns, and skip anything that already exists.
38+
39+
### Deployments that used `flask db init` (self-managed migrations)
40+
41+
Some deployments previously ran `flask db init` to create a local `migrations/` directory and auto-generated migration files. Starting with v1.2.2, migration files are tracked in git and shipped with the project. To switch to the official migrations:
42+
43+
1. **Delete the local migrations directory** created by `flask db init`:
44+
```bash
45+
rm -rf migrations/
46+
```
47+
Migrations are now bundled inside the `flowapp` pip package — no local directory needed.
48+
49+
2. **Clear the old alembic_version** and **stamp the baseline** to register with the official migration track (your schema is already up to date):
50+
```sql
51+
DELETE FROM alembic_version;
52+
```
53+
```bash
54+
flask db stamp 001_baseline
55+
```
56+
57+
3. From now on, just run `flask db upgrade` when updating ExaFS.
58+
59+
### Deployments without any migration tracking
60+
61+
If your database has an `alembic_version` table from a previous migration setup but no local `migrations/` directory, clear it first:
62+
63+
```sql
64+
DELETE FROM alembic_version;
1265
```
1366

67+
Then run the upgrade:
68+
1469
```bash
15-
flask db init
16-
flask db migrate -m "Initial migration based on current DB state"
1770
flask db upgrade
1871
```
1972

20-
## Steps for Upgrading to v1.0.x
21-
Limits for number of rules were introduced. Some database engines (Mariadb 10.x for example) have issue to set Non Null foreigin key to 0 and automatic migrations fail. The solution may be in diferent version (Mariadb 11.x works fine), or to set limits in db manually later.
73+
The baseline migration will inspect your database and bring it up to the current schema without affecting existing data.
74+
75+
## Upgrading from v0.x to v1.0+
2276

23-
To set the limit to 0 for existing organizations run
77+
If you are upgrading from a pre-1.0 version, the baseline migration will add the missing `org_id` columns and organization limit columns automatically. However, existing rules still need to be linked to organizations. An optional helper script is provided for this:
2478

25-
```SQL
26-
UPDATE organization
27-
SET limit_flowspec4 = 0, limit_flowspec6 = 0, limit_rtbh = 0
28-
WHERE limit_flowspec4 IS NULL OR limit_flowspec6 IS NULL OR limit_rtbh IS NULL;
79+
```bash
80+
python scripts/migrate_v0x_to_v1.py
2981
```
3082

31-
In all cases we need later assign rules to organizations. There's an admin endpoint for this:
83+
This script:
84+
1. Sets NULL organization limits to 0
85+
2. Helps assign existing rules to organizations based on users' organizations
86+
3. Reports users with multiple organizations or ambiguous rule ownership that need manual assignment
87+
88+
Feel free to contact [email protected] if you need help with the migration.
89+
90+
## Creating New Migrations
3291

33-
`https://yourexafs.url/admin/set-org-if-zero`
92+
When you modify a database model, create a new migration:
93+
94+
```bash
95+
flask db migrate -m "Description of changes"
96+
```
97+
98+
Review the generated file in `flowapp/migrations/versions/`, then apply it:
99+
100+
```bash
101+
flask db upgrade
102+
```
103+
104+
Commit the migration file to git so other deployments can apply it.
105+
106+
## Development Reset
107+
108+
To completely reset the database during development:
109+
110+
```bash
111+
python scripts/db-init.py --reset # source install
112+
exafs-db-init --reset # PyPI install
113+
```
34114

35-
Or you can start with clean database and manually migrate data by SQL dump later. Feel free to contact [email protected] if you need help with the DB migration to 1.0.x.
115+
This drops all tables and recreates them from scratch. **Do not use in production.**

0 commit comments

Comments
 (0)