לדלג לתוכן

ייבוא מ-Hasura

Provisa יכולה להמיר מטא-דאטה קיים של Hasura ל-config.yaml של Provisa, תוך שמירה על טבלאות מעוקבות, קשרים, הרשאות וסכמות מרוחקות.

ייבוא אינטראקטיבי (Admin ← Import Hasura Config)

משטח הניהול מריץ את אותם ממירים, כך שהייבוא לא דורש גישת shell ולא מחזור קובץ תצורה הלוך-ושוב. נדרשת יכולת org_settings; הייבוא נוחת בארגון שבו הסשן פועל.

  1. העלאה. בחרו תיקיית מטא-דאטה מכווצת (zip) של Hasura v2, פרויקט DDN מכווץ, ייצוא מטא-דאטה מאוחד (.yaml/.json, כולל המעטפת {resource_version, metadata} שה-API של המטא-דאטה מחזיר), או .hml בודד. השאירו את הפורמט על זיהוי אוטומטי אלא אם ההעלאה מעורפלת.
  2. מיפוי תחומים (אופציונלי). כל זוג ממפה סכמת v2 או תת-גרף DDN לתחום Provisa; כל מה שלא ממופה שומר על שמו המקורי.
  3. המרה ותצוגה מקדימה. השרת ממיר ומחזיר ספירות, את דוח ההמרה (ראו הדוח) ואת התצורה שנוצרה. בשלב זה שום דבר אינו נכתב. התצורה שנוצרה. שום דבר לא נכתב בשלב הזה.
  4. סקירה ועריכה. התצורה ניתנת לעריכה במקום — פרטי חיבור, שמות תחומים, שמות תפקידים. מה שמיישמים הוא מה שמוצג.
  5. החלה. החלה על ארגון זה טוענת את התצורה ובונה מחדש את הסכמות של הארגון. ייבוא תמיד מתמזג לתוך מה שיש לארגון.

נקודות קצה: POST /admin/import/hasura/preview וגם POST /admin/import/hasura/apply.


Hasura v2

ייצוא מטא-דאטה

שני מבני הייצוא מומרים.

ספריית המטא-דאטה של ה-CLI. hasura metadata export כותב ספרייה. databases/databases.yaml מפרט כל מקור עם סוגו וחיבורו, ומפנה לטבלאותיו ולפונקציותיו דרך אינדקסי !include:

hasura metadata export
# metadata/databases/databases.yaml
- name: default
  kind: postgres
  configuration:
    connection_info:
      database_url:
        from_env: HASURA_GRAPHQL_DATABASE_URL
  tables: "!include default/tables/tables.yaml"
  functions: "!include default/functions/functions.yaml"

גם המבנה השטוח (tables.yaml ו-actions.yaml בשורש) מומר.

מסמך ה-API היחיד של המטא-דאטה. ה-API של המטא-דאטה מחזיר את כל הייצוא כאובייקט אחד, עם ה-configuration לכל מקור שלמבנה הספרייה אין לו היכן להניחו:

curl -X POST http://localhost:8080/v1/metadata \
  -H "X-Hasura-Admin-Secret: <secret>" \
  -d '{"type":"export_metadata","args":{}}' \
  > metadata.json

גם האובייקט החשוף וגם המעטפת {resource_version, metadata} מתקבלים. ייבוא הניהול מקבל את הצורה הזו (ראו ייבוא אינטראקטיבי); ממיר שורת הפקודה קורא ספריות בלבד.

המרה

ממיר שורת הפקודה קורא ספריית מטא-דאטה של Hasura (המבנה ש-hasura metadata export מפיק, או המבנה השטוח tables.yaml / actions.yaml) וכותב תצורת Provisa:

python -m provisa.hasura_v2 ./metadata -o config.yaml

השמיטו את -o כדי לכתוב את התצורה ל-stdout. כשנשאר משהו לעשות מחדש ידנית, הדוח מודפס ל-stderr.

דגלים:

דגל מטרה
-o, --output נתיב ה-YAML של הפלט (ברירת מחדל: stdout)
--source-overrides קובץ YAML עם עקיפות חיבור לכל מקור (host, port, אישורים), מפתוח לפי שם המקור
--domain-map מיפויי סכמה-לתחום כזוגות SCHEMA=DOMAIN
--auth-env-file קובץ .env עם תצורת אימות; ממיר JWT/JWK, סוד מנהל ומפת claims
--dry-run ניתוח ואימות ללא כתיבת פלט

הדוח

כל המרה ממיינת את מה שמצאה לשלושה חלקים. קראו אותם בסדר הזה.

  1. הועבר כמות שהוא. לאובייקט יש מקבילה ישירה ב-Provisa והוא מומר בלי שינוי משמעות: מקורות, טבלאות, קשרים מאושרים, הרשאות select, cron triggers.
  2. מופה ליכולת טובה יותר של Provisa. ל-Provisa יש יכולת שעושה את העבודה טוב יותר מזו של Hasura, ולכן האובייקט הופך ליכולת הזו. כל פריט אומר מדוע. כאן נכנסים event triggers, actions, remote schemas, שמות שדות שורש נוספים ותפקידים שירשו מכמה תפקידים.
  3. לעשות מחדש ידנית. לאובייקט אין מקבילה ב-Provisa, או שהייצוא חסר את מה שההמרה צריכה. כל פריט אומר מה לעשות. אלה האזהרות.

התצוגה המקדימה מחזירה את שלושת החלקים כרשימות. ממיר שורת הפקודה מדפיס אותם ל-stderr בשם Carried as, Mapped to ו-Redo by hand, כל אחד עם ספירה. המרה שאין בה דבר בחלק השלישי הושלמה.

מה מומר

מושג ב-Hasura חלק תוצאה ב-Provisa
מקור (kind, connection_info) הועבר sources[]. חיבור שכתוב במפורש בייצוא מומר ל-host, port, מסד נתונים ואישורים. חיבור שנקרא ממשתנה סביבה אינו מנוחש (ראו חיבורים ותחומים).
טבלה עוקבת הועבר טבלה רשומה. שמה המותאם (או שדה השורש select שלה) הופך לכינוי (alias) של הטבלה.
שמות עמודות מותאמים (column_config, או custom_column_names הישן) הועבר alias של העמודה.
שמות שדות שורש מעבר ל-select (select_by_pk, select_aggregate, insert, ...) מופה מדווחים בשמם. Provisa מגישה טבלה כשדה אחד: קריאה לפי מפתח היא מסנן עליו, אגרגט הוא השדה _aggregate שלו, כתיבה היא המוטציה שלו. בדקו שהשאילתות של האפליקציה בצורה הזו.
Object ו-array relationship הועבר קשר מאושר (many-to-one ל-object, one-to-many ל-array) ששדה ה-GraphQL שלו הוא שם ה-relationship של Hasura. המקרים החריגים מפורטים להלן. (REQ-1680)
הרשאת select הועבר הרשאות עמודה (visible_to) וכלל שורות. איבר עם משתנה הפעלה (X-Hasura-User-Id) הופך ל-current_setting('provisa.hasura_user_id'), שהבקשה קושרת בזמן השאילתה מה-claims של הזהות או מתכונות החבר. משתנה הפעלה של Hasura שומר על שמו; provisa.user_id נשאר הזהות המחוברת. (REQ-1682)
כלל שורות דרך relationship הועבר תת-שאילתת EXISTS על הטבלה הקשורה.
הרשאת insert, update ו-delete הועבר הרשאות כתיבה על הטבלה: אחת לכל תפקיד ופעולה. columns הופכות לעמודות ההרשאה, filter ל-rows שלה, check ל-check שלה ו-set ל-presets שלה.
תפקיד שירש מתפקיד אחד הועבר אותו תפקיד כ-parent_role_id.
תפקיד שירש מכמה תפקידים מופה תפקיד שמחזיק את איחוד הרשאותיהם, כתוב במפורש: לתפקיד ב-Provisa הורה אחד.
Computed field לעשות מחדש עמודה של view מעל הטבלה.
פונקציה עוקבת הועבר command; ראו להלן. אחרת, לעשות מחדש.
Action מופה command שקורא ל-handler של ה-action.
Cron trigger הועבר trigger מתוזמן.
Event trigger מופה trigger על שינויי הטבלה.
Remote schema מופה מקור graphql_remote ששדות השורש שלו נוחתים כטבלאות מנוהלות. (REQ-1681)

מקרי relationships:

  • התנגשות. כשכבר יש לטבלה שדה בשם ה-relationship, ה-relationship לוקחת את השם ש-Provisa נותנת לה, והדוח מזהיר. שנו את שמה בדף Relationships אם האפליקציה צריכה שם אחר.
  • אותו join פעמיים. relationship שנייה שמצהירה על join שכבר הוצהר עליו ממוזגת לראשונה. הדוח מציין זאת בין הפריטים שהועברו.
  • כמה זוגות עמודות. קשר ב-Provisa מצטרף על זוג עמודות אחד. relationship שמצטרפת על כמה מקבלת אזהרה ואינה נוצרת, אך כללי שורות דרכה מועברים.
  • עמודת מפתח זר בלבד. object relationship שהוצהרה ב-foreign_key_constraint_on: artist_id אינה נוקבת ביעד בייצוא. הממיר פותר אותה דרך ה-array relationship ההפוכה ומזהיר כשאין כזו.

פרטי הרשאות הכתיבה:

  • filter או check ריק פירושו כל שורה, ונכתב TRUE.
  • ערך set שהוא משתנה הפעלה (X-Hasura-User-Id) הופך ל-preset מסוג session של משתנה ההפעלה התואם (X-Hasura-User-Id הופך ל-hasura_user_id). כל ערך אחר הופך ל-preset מסוג literal. עמודת preset אינה מופיעה גם בעמודות ההרשאה.
  • ה-admin המובלע של Hasura מחזיק בכל הרשאה. הוא הופך לתפקיד org_admin, שמחזיק בהרשאת insert, update ו-delete על כל עמודה וכל שורה, ושמו מופיע בכל עמודה מיובאת. (REQ-1684)
  • כל תפקיד עם הרשאת insert, update או delete מקבל גם את הזכות write.

פרטי commands:

  • פונקציה עוקבת. הייצוא נוקב בפונקציה ובתפקידים שקוראים לה, לא בארגומנטים שלה ולא במה שהיא מחזירה. התצוגה המקדימה קוראת את שניהם מקטלוג מסד הנתונים ורושמת command עם החתימה שנמצאה. כשהמקור אינו נגיש, אינו PostgreSQL, או שהפונקציה חסרה, עמוסה (overloaded) או מחזירה שורות מטבלה שהייבוא אינו רושם, הפונקציה עוברת ל"לעשות מחדש". ממיר שורת הפקודה אינו מגיע לעולם למסד נתונים, ולכן כל פונקציה עוקבת שהוא מוצא עוברת ל"לעשות מחדש".
  • Action. ה-command קורא ל-handler של ה-action ב-POST. {{VAR}} ב-URL של ה-handler נכתב ${env:VAR} ונפתר כשה-command נקרא. ה-command גלוי לתפקידים שהרשאות ה-action נוקבות בהם, או ל-org_admin בלבד כשאינן נוקבות באף אחד. action אסינכרוני מקבל אזהרה: ה-command שלו ממתין לתשובת ה-handler. סוג החזרה שהייצוא אינו נושא את שדותיו מקבל אזהרה.
  • Event trigger. ה-trigger נורה בכל שינוי בטבלה, פעם אחת לכל אצוות שינויים, ושולח את הטבלה ואת השורות ששונו. הוא אינו נורה לכל שורה עם ערכים ישנים וחדשים. trigger של Hasura על פחות משלוש הפעולות מקבל אזהרה, כי ה-trigger של Provisa נורה על כולן. ניסיונות חוזרים אינם מועברים: trigger של Hasura עם num_retries מקבל אזהרה, כי trigger של Provisa קורא פעם אחת. נסו שוב ב-handler אם קריאה שהוחמצה חשובה.
  • Cron trigger. ביטוי ה-cron, ה-URL, ה-payload והדגל enabled מועברים. ניסיונות חוזרים אינם מועברים ומקבלים אזהרה באותו אופן.

מסמך מאוחד כולל גם סעיפים שלממיר אין להם יעד: query_collections, allowlist, rest_endpoints, network ו-opentelemetry. כשאחד מהם קיים, הדוח מפרט אותו בין הפריטים לעשות מחדש. קורא הספריות אינו פותח את הקבצים שלהם לעולם.

חיבורים ותחומים בלשונית הייבוא

חיבור שהייצוא כותב במפורש מומר כפי שהוא. כשהייצוא קורא URL של מסד נתונים ממשתנה סביבה (database_url: {from_env: HASURA_GRAPHQL_DATABASE_URL}), ערך המשתנה אינו בייצוא, ולכן ההמרה אינה מנחשת אחד. המקור נרשם עם שדות חיבור ריקים, והדוח מורה לעשות אותו מחדש: הזינו את ה-host, ה-port, מסד הנתונים, המשתמש והסיסמה של המקור בהגדרות המקורות של הייבוא והמירו שוב. רק השדות ששניתם עוברים, כעקיפות מקור. שורות התחומים מכסות כל סכמה, subgraph ו-remote schema שההעלאה נושאת; כל אחת היא בורר מעל התחומים הקיימים של הארגון שמקבל גם שם מוקלד, המסומן "תחום חדש" כשאינו תואם לאף אחד. החלה ממזגת עם מה שכבר יש לארגון. (REQ-1687)

הטיפוסים מגיעים מהמקור בתצוגה המקדימה

ייצוא Hasura נוקב עמודות בלי טיפוסים, וטבלה מעוקבת ללא הרשאה לא נוקבת עמודות כלל. התצוגה המקדימה רצה עם חיבורי המקור שסיפקתם, כך שהיא קוראת את information_schema.columns של כל מקור SQL בר-הגעה: כל עמודה לא-מטופסת מקבלת את הטיפוס של המקור ממופה לאוצר המילים של ה-IR, וטבלה ללא עמודות לוקחת כל עמודה שיש למקור, נראית ל-org_admin בלבד, מכיוון ש-Hasura חשפה אותה לאף תפקיד אחר. מקור שהתצוגה המקדימה לא יכולה להגיע אליו מדווח כאזהרת [sources] והעמודות שלו נשארות לא-מטופסות עד שתסיימו לפני ההחלה. (REQ-1691, REQ-1684)

מגבלות

  • Computed fields נעשים מחדש ידנית: הייצוא נוקב בפונקציית מסד הנתונים אך אינו מגדיר אותה. הוסיפו אותה כעמודה של view מעל הטבלה, או חשבו אותה באפליקציה.
  • Remote schemas נוחתים כטבלאות מתוך ה-SDL של הרשאות התפקידים. remote schema ללא הרשאות אינו מנחית דבר, כי הייצוא אינו נושא הצהרה אחרת על צורתו. (REQ-1681)
  • פונקציות עוקבות זקוקות למסד הנתונים בזמן התצוגה המקדימה כדי לקרוא את חתימתן; במצב לא מקוון הן נעשות מחדש בדף Commands.
  • ניסיונות חוזרים של event ו-cron triggers אינם מועברים.

Hasura DDN (v3)

איתור פרויקט ה-HML

ממיר ה-DDN קורא ישירות את תיקיית פרויקט ה-DDN של קבצי .hml — אין צורך בשלב build של supergraph. רכיב התיקייה הראשון תחת שורש הפרויקט נלקח כשם תת-הגרף; קבצים תחת globals/ משויכים לתת-הגרף globals.

המרה

python -m provisa.ddn ./my-ddn-project -o config.yaml

השמיטו את -o כדי לכתוב את התצורה ל-stdout.

דגלים:

דגל מטרה
-o, --output נתיב YAML לפלט (ברירת מחדל: stdout)
--source-overrides קובץ YAML עם דריסות חיבור לפי מקור
--domain-map מיפויי תת-גרף-לתחום כזוגות SUBGRAPH=DOMAIN
--aggregates-output נתיב פלט לקובץ הצד (sidecar) של ביטויי צבירה (ברירת מחדל: <output>-aggregates.yaml)
--dry-run פירוק ואימות בלי לכתוב פלט

מטא-דאטה מסוג AggregateExpression נשמר בקובץ צד *-aggregates.yaml.

מה מומר

מושג DDN מקבילה ב-Provisa
מודל תת-גרף tables[] תחת מקור
קשר relationships[]
כלל הרשאה מסנן RLS
Command Mutation של webhook או View
Connector רשומת מקור עם פרטי חיבור

מגבלות

  • מחברי Lambda (פונקציות TypeScript/Python) דורשים הגדרת webhook ידנית
  • תוספי מחזור חיים (Lifecycle plugins) אין להם מקבילה ישירה
  • מצבי אימות DDN ממופים לספקי אימות של Provisa אך נתיבי claim של JWT עשויים לדרוש התאמה

אחרי הייבוא

  1. עברו על config.yaml שנוצר ועל הדוח — התחילו בפריטי Redo by hand
  2. אמתו את אישורי החיבור. חיבור שהייצוא קרא ממשתנה סביבה מגיע ריק; הדוח נוקב בו
  3. הפעילו את Provisa ואמתו שהטבלאות מופיעות ב-Explorer
  4. הריצו את שאילתות ה-GraphQL הקיימות שלכם — הסכמה תואמת לתבניות נפוצות
  5. הגישו שאילתות לאישור דרך ה-Admin API או ה-UI לפני הפעלת ממשל בסביבת ייצור