Skip to content

Migrate Teradata test connection to the @check framework (#31642) - #33140

Merged
Khairajani merged 1 commit into
2.0from
backport/teradata-test-connection-checks-2.0
Sep 10, 2026
Merged

Migrate Teradata test connection to the @check framework (#31642)#33140
Khairajani merged 1 commit into
2.0from
backport/teradata-test-connection-checks-2.0

Conversation

@Khairajani

Copy link
Copy Markdown
Contributor

Backport of #31642 to 2.0.

git cherry-pick -x with one conflict in connection.py, resolved by taking the incoming side: 2.0's only drift in that file was Optional[...] styling inside the test_connection method the migration removes. All three files are byte-identical to main.

🤖 Generated with Claude Code

* feat(ingestion): migrate Teradata test connection to the @check framework

Teradata was still on the legacy test_connection_db_common path, so every
failure surfaced as the raw teradatasql exception with no structured
diagnosis - a bad password rendered as a 25-line Go stack trace from
gosqldriver/teradatasql.

- TeradataChecks implements the seeded steps on the shared ping/list_*/
  run_sql helpers, and inherits the TCP reachability preflight, so an
  unreachable host fails as a network problem before credentials are
  exercised.
- TERADATA_ERRORS maps the driver's own codes to diagnoses. teradatasql
  exposes no .errno/.sqlstate, so both are read back out of the message
  text, which is where the driver puts them - but the codes are stable and
  locale-independent unlike the prose that follows. Only codes confirmed
  against Teradata's published references are encoded; anything else keeps
  its raw errorLog rather than getting a guessed diagnosis. Auth is keyed
  on SQLState 28000 rather than Error 8017 alone so the LDAP and Kerberos
  logmech rejections, which carry their own codes, are covered too.
- teradata.json: CheckAccess gains category=ConnectionGate. The runner
  short-circuits on the category, not the legacy shortCircuit flag, so
  without it a failed gate let every later step open its own connection.
  A test asserts this and fails when the line is removed.
- teradata.json: add the GetDatabases step. The legacy handler already
  passed TERADATA_GET_DATABASE as a GetDatabases query, but the seeded
  definition had no such step and the runner iterates the definition - so
  that query had never run.
- _get_client registers engine.dispose for deterministic teardown.

Tests cover each classifier rule, rule precedence where two could match,
that a bare number in a message is not read as a code, that the provider's
checks match the seeded definition exactly, and an end-to-end runner pass
asserting the gate diagnosis and that later steps skip.

* fix(ingestion): make the new Teradata GetDatabases step non-mandatory

The step is newly introduced - the legacy handler passed the query but the
seeded definition had no step for it, so it never ran. As mandatory it
would newly fail a service whose user cannot read dbc.databasesvx but which
tests and ingests fine today, and a failed mandatory step also aborts
ingestion. Non-mandatory keeps the diagnosis without the regression.

Also:
- Reword the auth rule's rationale to what is sourced. Error 8017 under
  SQLState 28000 is what Teradata reports for both LOGMECH=TD2 and
  LOGMECH=LDAP; the earlier comment claimed the class additionally covered
  Kerberos rejections carrying their own codes, which was not verified. The
  rule is unchanged - keying on the standard class rather than a single
  code stands on its own, without asserting coverage that has not been
  observed.
- Cover get_databases' success path, which no test reached: the runner
  tests all fail at the gate, so the summarizer had no runtime coverage at
  all. Three cases - a normal count, an empty result, and the sample cap.

* fix(ingestion): diagnose Teradata network failures the Go driver reports itself

A hostname typo came back as a raw 25-line stack trace with no diagnosis.
Two separate causes:

The reachability preflight never ran. ping() derives the probe target from
the engine URL and skips the probe when no port is present - and Teradata's
hostPort is commonly a bare hostname, so the skip was the normal case, not
the edge case. check_access now probes the port the driver would dial,
defaulting to 1025, so a DNS or firewall failure is caught in Python and
fails fast.

Nothing in the error pack could catch what got through. teradatasql is a Go
driver behind cgo: it resolves the hostname itself and reports the failure
as its own OperationalError, with no Python socket exception in the chain.
NETWORK_ERRORS matches by exception type, so it is structurally blind to
every network failure teradatasql detects on its own. Added Error 493
(hostname lookup, observed) and a generic rule on SQLState 08000, the
SQL-standard connection-exception class, as the backstop for whatever still
reaches the driver.

Tests cover both codes, the rule ordering between them, and that the
preflight probes the configured port when given and 1025 when not.

* refactor(ingestion): match Teradata codes with the shared Matchers.contains

Review feedback. The bespoke regex matchers were compared against
Matchers.contains across every case the tests cover - both codes, both
SQLStates, the rule-ordering cases and the bare-number false positive -
and agreed on all 28 combinations. The brackets alone already prevent a
number elsewhere in the message being read as a code, which was the only
thing the regex was there to guarantee.

So the custom machinery bought nothing: two compiled patterns, three
helpers and a Matcher import deleted in favour of the shared matcher. The
comment explaining why the rules key on the bracketed code rather than the
prose after it is kept - that reasoning is what makes the rules stable
across locales, and it survives the implementation change. All 26 tests
pass untouched, which is itself evidence the two forms are equivalent.

Also use the real driver exception in the tests. They previously subclassed
sqlite3.OperationalError and justified it by saying teradatasqlalchemy is
absent from the unit test environment - that was wrong, generalised from a
local venv rather than checked. setup.py's test_unit includes
plugins[teradata], so CI has the dialect. The tests now subclass
teradatasql.OperationalError and build a real teradatasql engine, so
SQLAlchemy wraps the error exactly as it does in production. sqlite remains
only where a genuinely queryable engine is needed, and says so.

* test(ingestion): keep the Teradata test module importable without the driver

gitar-bot review. The previous commit made this module hard-import
teradatasql at collection time, so every test in it - including the ~23 that
only call ErrorPack.classify on a synthetic exception - would fail to
collect wherever the optional teradata extra is not installed. A collection
error is the worst version of this: it takes the whole file down rather
than skipping the part that needs the driver.

The driver was never needed. run_sql wraps whatever connect raises into a
CheckError and the error pack reads the message text, so the exception's
type and DBAPI lineage are immaterial to every assertion here. Verified by
uninstalling teradatasql and teradatasqlalchemy entirely: all 26 pass.

So the stand-in is a plain Exception carrying a real driver message, and
the engine is sqlite because the dialect is incidental to what is asserted.
Both now say that, rather than the previous two justifications - one of
which claimed CI lacks the extra, which was wrong.

---------

Co-authored-by: Khairajani <himanshu.k@deuexsolutions.com>
(cherry picked from commit 8ad603b)
@Khairajani
Khairajani requested review from a team as code owners September 10, 2026 12:31
@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

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

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

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!

@gitar-bot

gitar-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Migrates Teradata test connection to the @check framework by backporting #31642 to the 2.0 branch. All three affected files are byte-identical to main after resolving a minor conflict in connection.py. No issues found.

Options

Display: compact → Counting what did not apply, without listing it.

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

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit b36a0e032c5491b567ff063b6ea07cb8fbeeb432 in Playwright run 34477933326, attempt 1.

✅ 620 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 1h 2m 28s

⏱️ Max setup 3m 55s · max shard execution 13m 12s · max shard-job elapsed before upload 18m 50s · reporting 5s

🌐 214.40 requests/attempt · 2.74 app boots/UI scenario · 6.69% common-shard skew

Optimization targets still in progress:

  • Browser traffic was 214.4 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 2.74 per UI scenario (1781 boots / 650 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard chromium-01 104 0 0 0 0 0
✅ Shard chromium-02 102 0 0 0 0 0
✅ Shard chromium-03 91 0 0 0 0 0
✅ Shard chromium-04 102 0 0 0 0 0
✅ Shard data-asset-rules-01 65 0 0 0 0 0
✅ Shard domain-isolation-01 16 0 0 0 0 0
✅ Shard global-state-01 34 0 0 0 0 0
✅ Shard ingestion-01 29 0 0 0 0 0
✅ Shard ingestion-02 35 0 0 0 0 0
✅ Shard reindex-01 2 0 0 0 0 0
✅ Shard search-01 11 0 0 0 0 0
✅ Shard search-rbac-01 29 0 0 0 0 0

📦 Download artifacts

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

@Khairajani
Khairajani merged commit 4ae025b into 2.0 Sep 10, 2026
234 of 266 checks passed
@Khairajani
Khairajani deleted the backport/teradata-test-connection-checks-2.0 branch September 10, 2026 13:59
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 skip-pr-checks Bypass PR metadata validation check

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants