Fix TypeError creating B2 tasks on TrueNAS 24.10: handle both credential schemas
On 24.10 (Electric Eel) credentials["provider"] is the type string with account/key in credentials["attributes"]; 25.04+ moved them into a provider dict. The injected get_restic_config only handled the newer shape and raised TypeError on 24.10 at task creation (#1). The method now detects the schema and reads credentials from the right place on both. create_task.py list-credentials and list-tasks use the same schema-agnostic lookup.
This commit is contained in:
@@ -21,6 +21,15 @@
|
||||
own job runner, and later `ix-*` boot units still need midclt. Manual runs
|
||||
of `apply.sh` never trigger a restart.
|
||||
|
||||
- **`TypeError: string indices must be integers` when creating a B2 task on
|
||||
TrueNAS 24.10 (Electric Eel)** (#1). The credential schema differs between
|
||||
releases: on 24.10 `credentials["provider"]` is the type string (`"B2"`)
|
||||
with the account/key in `credentials["attributes"]`, while 25.04+ moved
|
||||
them into a provider dict. The injected `get_restic_config` only handled
|
||||
the 25.04+ shape. It now detects the schema and reads the credentials from
|
||||
the right place on both; `create_task.py list-credentials` and `list-tasks`
|
||||
got the same treatment.
|
||||
|
||||
- **`create_task.py verify` false-positive after reboot.** `verify` trusted
|
||||
`hook_status.json`, which only records that the files were patched on disk —
|
||||
not that the running process loaded them. `verify` now also compares the
|
||||
|
||||
@@ -186,6 +186,11 @@ B2_BLOCK = """
|
||||
# TRUECLOUD_PATCH — added by truenas-truecloud-patch/patch/apply.sh
|
||||
def _tc_get_restic_config(task):
|
||||
p = task["credentials"]["provider"]
|
||||
if not isinstance(p, dict):
|
||||
# TrueNAS <= 24.10: provider is the type string ("B2") and the
|
||||
# account/key live in the credential's attributes dict. 25.04+
|
||||
# moved them into a provider dict.
|
||||
p = task["credentials"]["attributes"]
|
||||
return "", {"B2_ACCOUNT_ID": p["account"], "B2_ACCOUNT_KEY": p["key"]}
|
||||
|
||||
B2RcloneRemote.get_restic_config = staticmethod(_tc_get_restic_config)
|
||||
|
||||
+10
-3
@@ -177,6 +177,14 @@ def cmd_verify():
|
||||
print(f"Check {os.path.join(_PATCH_DIR, 'apply.log')} and journalctl -u middlewared")
|
||||
sys.exit(1)
|
||||
|
||||
def _provider_type(cred):
|
||||
"""Provider type string across schemas (<=24.10 plain str, >=25.04 dict)."""
|
||||
p = (cred or {}).get("provider")
|
||||
if isinstance(p, dict):
|
||||
return p.get("type", "?")
|
||||
return p or "?"
|
||||
|
||||
|
||||
def cmd_list_credentials(client, _args):
|
||||
creds = client("GET", "/cloudsync/credentials")
|
||||
if not creds:
|
||||
@@ -185,7 +193,7 @@ def cmd_list_credentials(client, _args):
|
||||
print(f"{'ID':>4} {'Provider':<14} Name")
|
||||
print("─" * 55)
|
||||
for c in sorted(creds, key=lambda x: x["id"]):
|
||||
print(f"{c['id']:>4} {c['provider']['type']:<14} {c['name']}")
|
||||
print(f"{c['id']:>4} {_provider_type(c):<14} {c['name']}")
|
||||
|
||||
|
||||
def cmd_list_tasks(client, _args):
|
||||
@@ -196,8 +204,7 @@ def cmd_list_tasks(client, _args):
|
||||
print(f"{'ID':>4} {'Enabled':<8} {'Provider':<14} Name")
|
||||
print("─" * 60)
|
||||
for t in sorted(tasks, key=lambda x: x["id"]):
|
||||
creds = t.get("credentials") or {}
|
||||
ptype = (creds.get("provider") or {}).get("type", "?")
|
||||
ptype = _provider_type(t.get("credentials"))
|
||||
enabled = "yes" if t.get("enabled") else "no"
|
||||
print(f"{t['id']:>4} {enabled:<8} {ptype:<14} {t.get('description', '')}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user