A Linux-based web emulator of computer networks for educational purposes. Two independent halves, wired together through RabbitMQ:
front/— the Flask web app (registration/login, network CRUD, admin, quiz, AI). Sources live infront/src, the entry point isfront/src/app.py, and the processes are started byfront/run_app.sh(uwsgi + a celery worker).front/src/quiz/is layeredcontroller → facade → service → entity.back/— the Mininet/OVS emulation celery worker. Sources inback/src, entry into the logic isrun_miminetinback/src/tasks.py.
Docs: README.md (Russian, deployment), docs/ARCHITECTURE.md (index; one file
per subject in docs/ARCHITECTURE/ — module map, data flow, templates,
conventions), docs/QUIZ.md (creating a practice task over the API and every
available requirement check), docs/DEVELOPMENT.md (running tests on a rootless
Linux host, no Docker), docs/FUNCTIONAL_TESTS.md, docs/BACKEND_TESTS.md
(per-file test inventory), docs/GIT.md, docs/REQUIREMENTS.md (specification
index, one file per subject in docs/REQUIREMENTS/).
Lint commands, ruff/ty config, CI triggers, test selection, coverage gates and
per-workflow environment setup are all defined in .github/workflows/*.yml and
the root pyproject.toml. Read them — they are the source of truth and they
change often. Everything below is only what those files cannot tell you.
- Broker env vars are lowercase:
amqp_urls,rpc_urls,exchange_name(seefront/.env). There is noAMQP_URL. - The root is a uv workspace with no project of its own, so the root
.venvholds both halves,mininetincluded; the README'suv sync --project backis not needed. tyignoresunsupported-baseonly for thedb.Modelfiles listed in the rootpyproject.toml. A new declarative model fails the check until it is added to[[tool.ty.overrides]]there.- Local backend tests need
PYTHONPATH=../src.back/tests/pytest.inisetspythonpath = src, but the rootdir isback/tests, where that path does not exist, so collection blows up ontest_jobs.pyandtest_vlan.py. - Backend tests split at direct calls to
run_miminet: below it — no root, no Mininet, ~1 s; above it — root, Mininet, OVS and a builtmimidump, and you must finish withmn -c. Without root on the host usescripts/back-test.sh build→test. - Backend test imports are inconsistent (
from src.tasks import ...in some files,from node_types import ...in others). Don't unify them — follow the file you are editing. - The same E2E functionality is covered twice: Selenium in
front/tests/and Playwright infront/tests/playwright/(they shareutils/networks.py, and the locators are duplicated in bothutils/locators.pycopies). A UI change usually means touching both. - Never take more than 4 Playwright workers — the tests compete for the single
selenium/passwordaccount and start failing. TEST_TARGET_HOSTdefaults to172.18.0.2, which is nginx inside the docker network and answers 502 from the host.run.shsubstitutes127.0.0.1; a manual pytest invocation does not.- Auth tests live outside the test directories (
front/src/auth_tests/) and need theCLIENT_YANDEXandBOT_TOKENsecrets — they cannot run locally. - A new browser-free frontend test only reaches the coverage job after being
listed explicitly in
.github/workflows/front_coverage.yml.
front/.envis the source of truth for the test stand.MODE=prodswitches to Yandex Cloud PostgreSQL (docker-compose-prod.yml);start_all_containers.shpicks the compose file based onMODE.- Docker networks are configured in
front/.envviaDOCKER_SUBNET/RABBITMQ_SUBNETand the staticNGINX_IP/MIMINET_IP/POSTGRES_IP. Change a subnet and all three IPs must change too, or the containers will not see each other; afterwards rundocker compose down && docker compose up -d. load_dotenv()reads.envfrom the current directory: run anything that needsamqp_urls/MODEfromfront/(or the compose dir).- There are no migrations in the repository:
Migrate(app, db)is infront/src/app.py, butmigrations/is not committed — you needflask db initbeforeflask db migrate(all of it inside themiminetcontainer). .gitignorecontains.*,*.iniand__init__.py. Thepytest.iniand__init__.pyfiles that are in the repo were force-added; new ones needgit add -f.back/ovs-init.shis the single source of truth for starting OVS (image, local harness and CI). A secondovs-vswitchdbreaks STP/RSTP ("No such RSTP object"), so do not duplicate that startup logic.- The backend cannot be deployed under WSL.
- Docs and code comments are written in English.
README.mdanddocs/*_TESTS.mdare still Russian — leave them as they are, but write anything new in English. - Branch naming rules —
docs/GIT.md. Read it before creating a branch. - Commit messages are in English:
<scope>: <description> (#<issue>).