Skip to content

fix(ingestion): resolve Airbyte source/destination config from public API for lineage#30426

Open
VolubleRain1 wants to merge 1 commit into
open-metadata:mainfrom
VolubleRain1:fix/airbyte-public-api-lineage-config
Open

fix(ingestion): resolve Airbyte source/destination config from public API for lineage#30426
VolubleRain1 wants to merge 1 commit into
open-metadata:mainfrom
VolubleRain1:fix/airbyte-public-api-lineage-config

Conversation

@VolubleRain1

@VolubleRain1 VolubleRain1 commented Jul 23, 2026

Copy link
Copy Markdown

Fixes #30428

Addresses the public-API portion of #26993.

Problem

Airbyte pipeline lineage is not produced when the service uses the public API (api/public/v1), even for connector types that are otherwise supported (Postgres/MySQL/MSSQL).

Two causes, both in the source/destination resolution used by get_source_table_details / get_destination_table_details:

  1. Config field name. The models only read sourceName/destinationName and connectionConfiguration. The public API returns the connector type under sourceType/destinationType and the config under configuration:

    GET /api/public/v1/sources/{id}      -> { sourceType: "postgres", configuration: {database, schema, ...} }
    GET /api/public/v1/destinations/{id} -> { destinationType: "postgres", configuration: {database, schema, ...} }
    

    So connectionConfiguration is Noneschema/database resolve to None → lineage silently skipped.

  2. Connector-type identifier. The support guard compares against internal-API display names (AirbyteSource.POSTGRES = "Postgres", MSSQL = "Microsoft SQL Server (MSSQL)"), but the public API returns slugs (postgres, mssql, mysql). Even after (1), the guard fails and returns None.

Fix

  • AirbyteSourceResponse/AirbyteDestinationResponse now also accept sourceType/destinationType and configuration, and expose resolved_type / resolved_configuration that fall back across both API shapes.
  • New SOURCE_TYPE_LOOKUP / DESTINATION_TYPE_LOOKUP maps in constants.py recognize both display names and public-API slugs.
  • The lineage helpers use the resolved values.

Internal-API behavior is unchanged (display names still map).

Testing

  • Added test_yield_pipeline_lineage_details_public_api asserting lineage is produced from a public-API-shaped source/destination (mirrors the existing internal-API test).
  • Existing internal-API lineage test still passes.

Scope

This makes lineage work on the public API for the already-supported DB connector types. Adding warehouse destinations (Snowflake/BigQuery/Redshift) — the destination used in #26993 — is a larger enhancement (which destination configs to support) and is intentionally left out of this PR; noted in #26993.

Greptile Summary

Updates Airbyte lineage resolution to support public-API response fields and connector slugs.

  • Adds normalized source and destination type/configuration accessors.
  • Maps supported internal display names and public connector slugs to shared connector types.
  • Expands regression tests across supported public-API connector branches.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failures remain.

Important Files Changed

Filename Overview
ingestion/src/metadata/ingestion/source/pipeline/airbyte/constants.py Adds lookup maps that normalize supported internal connector display names and public-API slugs.
ingestion/src/metadata/ingestion/source/pipeline/airbyte/models.py Models both Airbyte API response shapes and exposes normalized connector type and configuration properties.
ingestion/src/metadata/ingestion/source/pipeline/airbyte/utils.py Uses normalized response fields and connector enums when constructing lineage table details.
ingestion/tests/unit/topology/pipeline/test_airbyte.py Adds public-API lineage and connector-specific table-detail regression coverage.

Reviews (3): Last reviewed commit: "fix(ingestion): resolve Airbyte source/d..." | Re-trigger Greptile

@VolubleRain1
VolubleRain1 requested a review from a team as a code owner July 23, 2026 21:59
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🔴 Playwright Results — 3 test failure(s)

✅ 4533 passed · ❌ 3 failed · 🟡 23 flaky · ⏭️ 102 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 436 0 4 16
✅ Shard 2 11 0 0 0
🟡 Shard 3 826 0 5 8
🔴 Shard 4 812 3 0 25
🟡 Shard 5 829 0 4 5
🟡 Shard 6 829 0 3 46
🟡 Shard 7 790 0 7 2

Genuine Failures (failed on all attempts)

Features/OntologyExplorerRdf.spec.ts › term Relations Graph requests /rdf/glossary/graph scoped to the selected term (glossaryTermId) when RDF is enabled (shard 4)
�[31mTest timeout of 60000ms exceeded.�[39m
Features/OntologyExplorerRdf.spec.ts › glossary Relations Graph calls /rdf/glossary/graph when RDF is enabled and renders nodes from the response (shard 4)
Error: GET /rdf/glossary/graph must be called on the glossary Relations Graph when RDF is enabled

�[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBe�[2m(�[22m�[32mexpected�[39m�[2m) // Object.is equality�[22m

Expected: �[32mtrue�[39m
Received: �[31mfalse�[39m
Features/OntologyExplorerRdf.spec.ts › renders without crashing when /rdf/glossary/graph returns duplicate nodes and dangling edges (shard 4)
Error: the valid term-to-term edge must be rendered

�[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBe�[2m(�[22m�[32mexpected�[39m�[2m) // Object.is equality�[22m

Expected: �[32mtrue�[39m
Received: �[31mfalse�[39m
🟡 23 flaky test(s) (passed on retry)
  • Features/TeamsDragAndDrop.spec.ts › Add teams in hierarchy (shard 1, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab IS visible for supported type: chart (shard 1, 1 retry)
  • Flow/SearchRBAC.spec.ts › User without permission (shard 1, 1 retry)
  • Flow/SearchRBAC.spec.ts › a dashboard-scoped user sees dashboards but never tables (shard 1, 2 retries)
  • Features/ContextCenterArticles.spec.ts › Article listing search filters, clears, and shows empty state (shard 3, 1 retry)
  • Features/ContextCenterArticles.spec.ts › Article edit persistence and unsaved title behavior are correct (shard 3, 2 retries)
  • Features/ContextCenterArticles.spec.ts › description: switching articles does not bleed unsaved content into next article (shard 3, 1 retry)
  • Features/ContextCenterMemories.spec.ts › edit-memory button on the row opens the modal in edit mode (shard 3, 1 retry)
  • Features/Glossary/GlossaryAdvancedOperations.spec.ts › should change domain on glossary (shard 3, 1 retry)
  • Features/UserProfileOnlineStatus.spec.ts › Should show online status badge on user profile for active users (shard 5, 1 retry)
  • Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts › renders a clickable entity link for instances with a related entity (shard 5, 1 retry)
  • Pages/CustomProperties.spec.ts › Should verify property name is visible for apiCollection in right panel (shard 5, 1 retry)
  • Pages/CustomProperties.spec.ts › String (shard 5, 1 retry)
  • Pages/Entity.spec.ts › Domain Propagation (shard 6, 1 retry)
  • Pages/Entity.spec.ts › Tier Add, Update and Remove (shard 6, 1 retry)
  • Pages/EntityDataSteward.spec.ts › Tier Add, Update and Remove (shard 6, 1 retry)
  • Pages/Glossary.spec.ts › Rename Glossary Term and verify assets (shard 7, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify Impact Analysis service filter selection (shard 7, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab is NOT visible for pipelineService in platform lineage (shard 7, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab is NOT visible for apiService in platform lineage (shard 7, 1 retry)
  • Pages/ServiceEntity.spec.ts › Tier Add, Update and Remove (shard 7, 1 retry)
  • Pages/TestSuite.spec.ts › Logical TestSuite (shard 7, 1 retry)
  • Pages/UserDetails.spec.ts › Create team with domain and verify visibility of inherited domain in user profile after team removal (shard 7, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

Comment thread ingestion/src/metadata/ingestion/source/pipeline/airbyte/utils.py Outdated
Comment thread ingestion/src/metadata/ingestion/source/pipeline/airbyte/utils.py Outdated
Comment thread ingestion/tests/unit/topology/pipeline/test_airbyte.py
@VolubleRain1
VolubleRain1 force-pushed the fix/airbyte-public-api-lineage-config branch from dbf8529 to d945339 Compare July 23, 2026 22:29
@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

# Internal API (`/sources/get`) returns `sourceName` + `connectionConfiguration`;
# the public API (`/api/public/v1/sources/{id}`) returns `sourceType` + `configuration`.
sourceName: Optional[str] = None # noqa: N815, UP045
sourceType: Optional[str] = None # noqa: N815, UP045

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine this is returned by the sources/{sourceId} endpoint from Airbyte?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — these fields come from the Airbyte public API: GET /api/public/v1/sources/{sourceId} and GET /api/public/v1/destinations/{destinationId}, which return sourceType/destinationType (slug, e.g. postgres) and configuration. The internal API (/sources/get) instead returns sourceName (display name) and connectionConfiguration. Confirmed against a live self-hosted instance — the model now accepts both shapes via resolved_type/resolved_configuration.

@harshach harshach added the safe to test Add this label to run secure Github workflows on PRs label Jul 23, 2026
# while the public API (`api/public/v1`) reports them as slugs (e.g. "postgres").
# These maps let lineage resolution accept either form.
SOURCE_TYPE_LOOKUP = {
AirbyteSource.MYSQL.value: AirbyteSource.MYSQL,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need more of these types? to cover all the connectors that Airbyte supports?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. This PR intentionally keeps the scope narrow — it only remaps the already-supported connector types (Postgres/MySQL/MSSQL/MongoDB) to their public-API slugs, so it stays a focused bug fix for the public-API lineage path rather than changing coverage.

Happy to extend it, though. The highest-value additions are warehouse destinations — Snowflake/BigQuery/Redshift — whose configuration exposes database + schema directly, so they'd need only a lookup entry plus the existing default extraction. That would also close the Snowflake-destination case in #26993. Additional DB sources (Oracle, Redshift, ClickHouse, etc.) are doable too but each needs its own config-key handling.

Would you prefer I expand the lookups (starting with warehouse destinations) in this PR, or land this focused fix first and follow up with a coverage-expansion PR?

… API for lineage

Airbyte pipeline lineage read the connector type and config only from the
internal-API fields (sourceName/destinationName, connectionConfiguration). On the
public API (api/public/v1) those live under sourceType/destinationType and
configuration, so schema/database resolved to None and no lineage was produced.
The connector-type guard also only matched internal display names ('Postgres'),
not public API slugs ('postgres').

- Response models expose resolved_type/resolved_configuration that fall back to
  the public-API fields.
- Add SOURCE/DESTINATION_TYPE_LOOKUP mapping both display names and public slugs
  to the supported connector enums.
- Lineage helpers use the resolved values.

Adds a public-API lineage regression test; internal-API behavior is unchanged.
Addresses the public-API portion of open-metadata#26993 (warehouse destinations such as
Snowflake remain a separate enhancement).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Cale <cale.anderson93@gmail.com>
@VolubleRain1
VolubleRain1 force-pushed the fix/airbyte-public-api-lineage-config branch from d945339 to 60b0e08 Compare July 23, 2026 23:17
@gitar-bot

gitar-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 resolved / 1 findings

Fixes Airbyte pipeline lineage generation for the public API by adding support for sourceType/destinationType and configuration fields alongside normalization lookup maps. No issues found.

✅ 1 resolved
Edge Case: MongoDB source config can raise AttributeError

📄 ingestion/src/metadata/ingestion/source/pipeline/airbyte/utils.py:52
In the MongoDB branch, source_config.get("database_config", {}).get("database") only falls back to {} when the database_config key is absent. If the key is present but explicitly None (which can happen with the public-API config shape), .get("database") is called on None and raises AttributeError, aborting lineage generation instead of skipping gracefully. Consider (source_config.get("database_config") or {}).get("database").

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Airbyte lineage not generated on public API (api/public/v1): source/destination config & connector type unresolved

3 participants