Organize documentation by moving requirements (HighLevelReqs, Component-*, lmxproxy_protocol) to docs/requirements/ and test infrastructure docs to docs/test_infra/. Updates all cross-references in README, CLAUDE.md, infra/README, component docs, and 23 plan files.
6.0 KiB
Test Infrastructure: MS SQL 2022 Database
Overview
The test database uses Microsoft SQL Server 2022 Developer Edition running in Docker. It provides two empty databases for ScadaLink — schema creation is handled by EF Core migrations at application startup (dev mode).
Image & Ports
- Image:
mcr.microsoft.com/mssql/server:2022-latest - Port: 1433
- Edition: Developer (free, full-featured)
Credentials
| Account | Username | Password | Purpose |
|---|---|---|---|
| SA | sa |
ScadaLink_Dev1# |
Server admin (setup only) |
| App | scadalink_app |
ScadaLink_Dev1# |
Application login (db_owner on both databases) |
Databases
| Database | Purpose |
|---|---|
ScadaLinkConfig |
Configuration Database component — templates, deployments, users, audit log |
ScadaLinkMachineData |
Machine/operational data storage |
Both databases are created by infra/mssql/setup.sql. EF Core migrations populate the ScadaLinkConfig schema. The ScadaLinkMachineData database is seeded with sample tables and stored procedures by infra/mssql/machinedata_seed.sql.
Data Persistence
SQL data is stored in the named Docker volume scadalink-mssql-data. Data survives container restarts and docker compose down. To reset the database completely:
docker compose down -v
docker compose up -d
# Re-run setup.sql after the container starts
First-Time Setup
After the first docker compose up -d, run the setup script:
docker exec -i scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'ScadaLink_Dev1#' -C \
-i /docker-entrypoint-initdb.d/setup.sql
This creates the databases and the scadalink_app login. Then seed the Machine Data database with sample tables, stored procedures, and data:
docker exec -i scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'ScadaLink_Dev1#' -C \
-i /docker-entrypoint-initdb.d/machinedata_seed.sql
You only need to run these once (or again after deleting the volume).
Connection Strings
For appsettings.Development.json:
Server=localhost,1433;Database=ScadaLinkConfig;User Id=scadalink_app;Password=ScadaLink_Dev1#;TrustServerCertificate=true
Server=localhost,1433;Database=ScadaLinkMachineData;User Id=scadalink_app;Password=ScadaLink_Dev1#;TrustServerCertificate=true
Verification
- Check the container is running:
docker ps --filter name=scadalink-mssql
- Query using
sqlcmdinside the container:
docker exec -it scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'ScadaLink_Dev1#' -C \
-Q "SELECT name FROM sys.databases"
- Verify the app login:
docker exec -it scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U scadalink_app -P 'ScadaLink_Dev1#' -C \
-d ScadaLinkConfig \
-Q "SELECT DB_NAME()"
CLI Tool
The infra/tools/mssql_tool.py script provides a convenient CLI for interacting with the SQL Server.
Install dependencies (one-time):
pip install -r infra/tools/requirements.txt
Commands:
# Check connectivity and verify expected databases exist
python infra/tools/mssql_tool.py check
# Run the first-time setup script (uses autocommit mode for CREATE DATABASE)
python infra/tools/mssql_tool.py setup --script infra/mssql/setup.sql
# List tables in a database
python infra/tools/mssql_tool.py tables --database ScadaLinkConfig
# Run an ad-hoc query
python infra/tools/mssql_tool.py query --database ScadaLinkConfig --sql "SELECT name FROM sys.tables"
Use --host, --port, --user, --password to override defaults (localhost:1433, sa, ScadaLink_Dev1#). Run with --help for full usage.
Machine Data Tables & Stored Procedures
The machinedata_seed.sql script creates the following in ScadaLinkMachineData:
Tables:
| Table | Description | Sample Data |
|---|---|---|
TagHistory |
Time-series tag values from OPC UA / custom protocols | Pressure, flow, level, temperature, speed readings for SiteA/SiteB |
ProductionCounts |
Shift/line production totals (good, reject, efficiency) | 3 days of 2-shift data across 2 sites |
EquipmentEvents |
State changes, faults, maintenance, alarm events | Pump faults, belt inspections, batch starts |
BatchRecords |
Production batch tracking (start, complete, abort) | 5 batches including one in-progress |
AlarmHistory |
Historical alarm activations, acks, and clears | Active, acknowledged, and cleared alarms |
Stored Procedures:
| Procedure | Description |
|---|---|
usp_GetTagHistory |
Get tag values for a tag path within a date range |
usp_GetProductionSummary |
Aggregate production by line over a date range |
usp_InsertBatchRecord |
Insert a new batch (for CachedWrite testing) |
usp_CompleteBatch |
Complete or abort a batch |
usp_GetEquipmentEvents |
Get recent equipment events with optional filters |
usp_GetActiveAlarms |
Get active/acknowledged alarms by severity |
Relevance to ScadaLink Components
- Configuration Database — primary consumer; EF Core context targets
ScadaLinkConfig. - Deployment Manager — reads/writes deployment records in
ScadaLinkConfig. - Template Engine — reads/writes template definitions in
ScadaLinkConfig. - Security & Auth — user/role data stored in
ScadaLinkConfig. - External System Gateway — scripts use
Database.Connection("machineDataConnection")to queryScadaLinkMachineDatatables and stored procedures. - Site Runtime — scripts call stored procedures via
Database.Connection()andDatabase.CachedWrite()for batch recording and data queries. - Inbound API — methods can query machine data via named database connections.
Notes
- The
sapassword must meet SQL Server complexity requirements (uppercase, lowercase, digit, special character, 8+ characters). - If the container fails to start, check Docker has at least 2GB RAM allocated (SQL Server minimum requirement).
- The setup script is idempotent — safe to run multiple times.