SimCore
Shared transport-layer plumbing for the ADR-029 Train/IL/CTC RBC simulators
Toggle main menu visibility
Loading...
Searching...
No Matches
sim_config.py
Go to the documentation of this file.
1
"""JSON-file sim configuration loader. Replaces the old per-variable
2
os.environ reads (RBC_WEST_HOST, RBC_WEST_TRAIN_PORT, RBC_TRAIN_INDEX,
3
...) that used to be set directly in docker-compose.yml's own
4
`environment:` block for each service.
5
6
One JSON file per sim INSTANCE, not per sim type - train-west and
7
train-east need different values (trainIndex, which RBC ports) even
8
though they run the exact same Docker image (safeapi-sim:latest, see
9
docker-compose.yml's own header on why one image is reused for every
10
instance) - so the file is supplied at container-start time via a
11
bind-mounted path (SIM_CONFIG_PATH env var, default
12
DEFAULT_CONFIG_PATH), not baked into the image. See
13
sims/config/*.json for the actual per-instance files and
14
docker-compose.yml's own `volumes:` entries for how each gets mounted.
15
16
Schema (fields present depend on sim type - train/il have `trainIndex`,
17
ctc does not; see each sim's own header for its exact expected keys):
18
{
19
"siteTag": "WEST", # display tag only, log prefix
20
"trainIndex": 0, # train/il only - 0 or 1
21
"rbcWest": {"host": "c-west", "port": 15004},
22
"rbcEast": {"host": "c-east", "port": 15014},
23
"controlServer": {"bindHost": "0.0.0.0", "port": 9100},
24
"simPeriodSeconds": 2.0 # train only
25
}
26
"""
27
28
import
json
29
import
os
30
31
DEFAULT_CONFIG_PATH =
"/app/config.json"
32
33
34
def
load
():
35
"""@return the parsed JSON config dict from SIM_CONFIG_PATH (env,
36
default DEFAULT_CONFIG_PATH). Raises with the path included on a
37
missing file or invalid JSON, so a bad config fails loudly and
38
specifically at startup rather than as a generic KeyError somewhere
39
inside main() once a sim tries to use a field that was never
40
there."""
41
path = os.environ.get(
"SIM_CONFIG_PATH"
, DEFAULT_CONFIG_PATH)
42
try
:
43
with
open(path,
"r"
, encoding=
"utf-8"
)
as
f:
44
text = f.read()
45
except
OSError
as
exc:
46
raise
FileNotFoundError(
47
f
"sim config file not found/readable: {path} ({exc}) - set SIM_CONFIG_PATH to override"
48
)
from
None
49
try
:
50
return
json.loads(text)
51
except
json.JSONDecodeError
as
exc:
52
raise
ValueError(f
"sim config file {path} is not valid JSON: {exc}"
)
from
None
53
54
55
def
require
(config, *keys):
56
"""@return config[keys[0]][keys[1]]... - raises a clear KeyError
57
(naming the full dotted path and the config file it came from) if
58
any level is missing, rather than Python's own bare KeyError(key)
59
for just the last, most confusing level."""
60
value = config
61
for
i, key
in
enumerate(keys):
62
if
not
isinstance(value, dict)
or
key
not
in
value:
63
dotted =
"."
.join(keys[: i + 1])
64
raise
KeyError(f
"sim config is missing required field {dotted!r}"
)
65
value = value[key]
66
return
value
simcore.sim_config.require
require(config, *keys)
Definition
sim_config.py:55
simcore.sim_config.load
load()
Definition
sim_config.py:34
src
simcore
sim_config.py
Generated by
1.18.0