מעבר מ-Hasura v2 ל-Provisa¶
דרישות מוקדמות¶
- מופע Hasura v2 פועל (v2.x) עם מטא-דאטה מיוצא.
- יצוא מטא-דאטה באמצעות ה-CLI של Hasura:
זה יוצר ספריית metadata/ המכילה sources.yaml, actions.yaml,
cron_triggers.yaml, inherited_roles.yaml, remote_schemas.yaml, וכו'.
3. Python 3.11+ עם חבילת provisa מותקנת.
שימוש ב-CLI¶
ארגומנטים¶
| ארגומנט | נדרש | תיאור |
|---|---|---|
metadata_dir |
כן | נתיב לספריית המטא-דאטה המיוצאת של Hasura v2 |
אפשרויות¶
| אפשרות | ברירת מחדל | תיאור |
|---|---|---|
-o, --output FILE |
stdout | נתיב קובץ YAML של פלט |
--source-overrides FILE |
None | קובץ YAML עם דריסות חיבור לכל-מקור |
--domain-map KEY=VAL ... |
None | מיפויי סכמה-לדומיין (למשל public=core hr=people) |
--auth-env-file FILE |
None | נתיב לקובץ .env עם תצורת אימות JWT/admin-secret |
--dry-run |
כבוי | פענוח ואימות ללא כתיבת פלט |
קובץ דריסות מקור¶
קובץ YAML עם מפתחות לפי שם מקור עם תכונות חיבור לדריסה:
default:
host: prod-db.example.com
port: 5432
database: myapp
username: provisa_user
password: "${env:PROD_DB_PASSWORD}"
קובץ סביבת אימות¶
קובץ בסגנון .env המחזיק את תצורת אימות ה-Hasura להמרה. הממיר
ממפה:
- JWT עם
jwk_url-> Provisaprovider: oauth. - JWT
claims_map-> Provisarole_mapping[]. - Admin secret -> Provisa
superuser. - אימות webhook -> אזהרה נפלטת (אין שווה-ערך ב-Provisa).
מטריצת שוויון תכונות¶
| תכונת Hasura v2 | שווה-ערך Provisa | הערות |
|---|---|---|
| מקורות (postgres, mysql, mssql, bigquery, citus) | sources[] |
סוג ממופה: pg/postgres -> postgresql, mssql -> sqlserver. כתובת URL של החיבור מפוענחת ל-host/port/database/username/password. הגדרות pool נשמרות. |
| טבלאות (טבלאות עוקבות) | tables[] |
שם סכמה + טבלה נשמר. source_id מקשר למקור. |
שמות טבלה מותאמים (custom_name, custom_root_fields.select) |
tables[].alias |
הראשון שאינו null מבין select, select_by_pk, custom_name. |
| שמות עמודה מותאמים | columns[].alias |
ממפה מילון custom_column_names לשיוכי עמודה. |
| הרשאות בחירה (עמודות, פילטר) | columns[].visible_to[], rls_rules[] |
רשימות עמודות הופכות ל-visible_to. עמודות תו-כללי (*) נתמכות. פילטרים מומרים ל-SQL דרך bool_expr_to_sql. |
| הרשאות הוספה/עדכון (עמודות) | columns[].writable_by[] |
רשימות עמודות הופכות ל-writable_by. תפקידים משודרגים ליכולת write. |
| הרשאות מחיקה | שדרוג יכולת תפקיד | התפקיד מקבל יכולת write. אין מיפוי מחיקה לכל-טבלה. |
| קשרי אובייקט | relationships[] עם cardinality: many-to-one |
שיוך עמודה נשמר. |
| קשרי מערך | relationships[] עם cardinality: one-to-many |
שיוך עמודה נשמר. |
| שדות מחושבים | functions[] |
ממופים ל-Function עם returns המצביע לטבלת האב. |
| פונקציות עוקבות | functions[] |
exposed_as ברירת מחדל ל-mutation. סכמה נשמרת. |
| Actions (handler של פרוצדורה מאוחסנת) | functions[] |
מומר ל-Function config כשמגובה על ידי פרוצדורה מאוחסנת. |
| Actions (handler של webhook) | לא מומר | אזהרה נפלטת, כולל כתובת ה-handler. |
| Cron triggers | לא מומר | אזהרה נפלטת. (טריגרים מתוזמנים בזמן-ריצה קיימים, אך הממיר אינו ממפה אותם.) |
| Event triggers | לא מומר | אזהרה נפלטת. (טריגרי אירועים בזמן-ריצה קיימים, אך הממיר אינו ממפה אותם.) |
| תפקידים בירושה | roles[].parent_role_id |
התפקיד הראשון ב-role_set הופך להורה. כל התפקידים הצאצאים נוצרים. |
| סכמות מרוחקות | sources[] (graphql_remote) |
נרשם כמקור graphql_remote. שם, URL, כותרות, ותצורת אימות נשמרים. |
| טבלאות enum | טבלה נוצרת | דגל is_enum אינו מועבר (אין שווה-ערך ב-Provisa). |
| רשימות allow | מדולג | לא קיים במודל המטא-דאטה. |
שלבים לאחר-המרה¶
- סקרו את ה-YAML הפלט. בדקו שמקורות, טבלאות, ותפקידים נראים נכונים.
- הגדירו חיבורי מקור. הממיר מפענח כתובות URL של חיבור אך ברירת-מחדל
ל-
localhostבכשל פענוח. השתמשו ב---source-overridesאו ערכו את הפלט ישירות. - אמתו שיוכי דומיין. ללא
--domain-map, כל הטבלאות נופלות ל-default. שייכו סכמות לדומיינים עם--domain-map public=core analytics=reporting. - בדקו כללי RLS. פילטרים מומרים לקירובי SQL. ביטויים
בוליאניים מורכבים (
_and/_or/_existsמקוננים) צריכים להיסקר ידנית. - סקרו אזהרות. הממיר מדפיס תקציר אזהרות ל-stderr עבור תכונות שהממיר אינו ממפה (event triggers, cron triggers, actions מגובות webhook).
- הגדירו אימות. אם מופע ה-Hasura שלכם משתמש באימות JWT/webhook, צרו קובץ סביבת
אימות והריצו מחדש עם
--auth-env-file. - בדקו. הפעילו את שרת Provisa ואמתו שאילתות מול מקורות הנתונים שלכם.
בעיות נפוצות ופתרון תקלות¶
כתובת URL של חיבור לא מפוענחת¶
אם database_url של המקור הוא הפניה למשתנה סביבה ({"from_env": "PG_URL"}),
הממיר אינו יכול לפתור אותה בזמן ההמרה. למקור יהיו ערכי placeholder
(host: localhost, database: default). תקנו עם --source-overrides.
עמודות תו-כללי¶
כאשר הרשאה מעניקה columns: "*", הממיר יוצר רשומת עמודת תו-כללי
אחת. לאחר ההמרה, ייתכן שתרצו להחליף אותה ברשימות עמודה מפורשות
על ידי בדיקת סכמת מסד הנתונים בפועל.
נאמנות טריגר אירוע¶
טריגרי אירועים מומרים עם operations ו-webhook_url אך ערבויות
משלוח ספציפיות ל-Hasura (exactly-once, משלוח-מחדש) אין להן שווה-ערך ישיר ב-Provisa.
סקרו את סעיף event_triggers והגדירו את תשתית ה-webhook שלכם בהתאם.
תפקידים חסרים¶
תפקידים נאספים רק מרשומות הרשאה. אם תפקיד קיים ב-Hasura אך אין לו הרשאות על אף טבלה או action, הוא לא יופיע בפלט.
שדות שורש מותאמים¶
רק שדות שורש select ו-select_by_pk משמשים לשיוך הטבלה. שדות שורש
מותאמים אחרים (select_aggregate, insert, update, delete) אינם ממופים.
דוגמה¶
המרת פרויקט Hasura v2 טיפוסי עם שתי סכמות ממופות לדומיינים:
# Export metadata from Hasura
hasura metadata export --endpoint http://localhost:8080
# Convert with domain mapping and source overrides
python -m provisa.hasura_v2 metadata/ \
-o provisa.yaml \
--domain-map public=core hr=people \
--source-overrides overrides.yaml \
--auth-env-file auth.env
# Dry run first to check for warnings
python -m provisa.hasura_v2 metadata/ --dry-run
מבנה פלט:
sources:
- id: default
type: postgresql
host: prod-db.example.com
port: 5432
database: myapp
...
domains:
- id: core
- id: people
tables:
- source_id: default
domain_id: core
schema_name: public
table_name: users
columns:
- name: id
visible_to: [user, admin]
- name: email
visible_to: [admin]
writable_by: [admin]
alias: Users
roles:
- id: admin
capabilities: [read, write]
domain_access: ["*"]
- id: user
capabilities: [read]
domain_access: ["*"]
rls_rules:
- table_id: default.public.users
role_id: user
filter: "id = x-hasura-user-id"
relationships:
- id: default.public.orders.user
source_table_id: default.public.orders
target_table_id: default.public.users
source_column: user_id
target_column: id
cardinality: many-to-one