seed: refuse an engine that would ignore what these flows rely on
A node type accepts a setting it does not know and ignores it, which is right for a node someone is editing and wrong here: seeded against the engine this installation is running today, every rollershutter would take the trigger's default minute instead of the twenty-six seconds it actually takes, and every Victron reading would arrive as an object where a number was declared. It would look like it had worked. So the seed asks what the node types know before it writes anything, and says which rebuild is missing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -383,6 +383,39 @@ def push(api: Api, flows: list[Flow]) -> None:
|
||||
print(f" dashboard '{name}': {len(widgets)} widgets, published")
|
||||
|
||||
|
||||
#: Settings these flows depend on that a node type gained for this port. A node
|
||||
#: type accepts an unknown setting and ignores it — which is right for a node
|
||||
#: someone is editing and wrong here, where it would mean a rollershutter
|
||||
#: running for the default minute instead of the twenty-six seconds it takes.
|
||||
NEEDED = {
|
||||
"trigger": {
|
||||
"wait_port": "a shutter would run for the default wait, not its own",
|
||||
"passthrough": "a motor would be commanded with 'true' rather than a direction",
|
||||
},
|
||||
"mqtt": {
|
||||
"json_key": "every Victron reading would arrive as an object, not a number",
|
||||
},
|
||||
"http": {
|
||||
"query": "the weather key would have to sit in the flow file in clear",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _engine_too_old(api: Api) -> list[tuple[str, str]]:
|
||||
"""Settings this installation's node types do not know about yet."""
|
||||
types = {t["type"]: t for t in api("GET", "/flows/node-types")}
|
||||
stale = []
|
||||
for type_name, settings in NEEDED.items():
|
||||
schema = types.get(type_name, {}).get("params_schema") or {}
|
||||
known = set(schema.get("properties") or {})
|
||||
if not known:
|
||||
continue
|
||||
for setting, why in settings.items():
|
||||
if setting not in known:
|
||||
stale.append((f"{type_name}.{setting}", why))
|
||||
return stale
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
dry = "--dry" in argv
|
||||
h = house()
|
||||
@@ -401,6 +434,24 @@ def main(argv: list[str]) -> int:
|
||||
return 0
|
||||
|
||||
api = Api()
|
||||
stale = _engine_too_old(api)
|
||||
if stale:
|
||||
print(
|
||||
"\nThis installation's engine does not have what these flows need:",
|
||||
file=sys.stderr,
|
||||
)
|
||||
for setting, why in stale:
|
||||
print(f" {setting} — {why}", file=sys.stderr)
|
||||
print(
|
||||
"\nAn unknown setting is accepted and ignored rather than refused, so\n"
|
||||
"seeding now would look like it worked and run every shutter for a\n"
|
||||
"minute. Rebuild the image first:\n"
|
||||
' docker compose -p fluksio-app --env-file "$PWD/.env" \\\n'
|
||||
" -f docker/compose.yml up --build -d backend",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
have = set(api("GET", "/secrets/")["data"])
|
||||
missing = [name for name in SECRETS if name not in have]
|
||||
if missing:
|
||||
|
||||
Reference in New Issue
Block a user