8000 Expand Databricks API emulation: 13.3% -> 17.8% coverage by dmux · Pull Request #17 · dmux/minilake · GitHub
[go: up one dir, main page]

Skip to content

Expand Databricks API emulation: 13.3% -> 17.8% coverage - #17

Merged
dmux merged 1 commit into
mainfrom
feat/expand-databricks-api-emulation
Sep 15, 2026
Merged

dmux merged 1 commit into
mainfrom
feat/expand-databricks-api-emulation

Conversation

@dmux
@dmux dmux commented Sep 15, 2026
Copy link
Copy Markdown
Owner

Why

minilake's API coverage had never been measured. FEATURES.md listed what was
implemented and kept a hand-written "out of scope" table, but nothing answered
"what exactly breaks when someone points the CLI, the SDK or Terraform at this?"

This adds a reproducible answer, then closes the highest-value gaps it found.

Endpoints answered: 155 → 208 of the 1168 the databricks-sdk calls (13.3% → 17.8%).
CLI command groups working end-to-end: 10 → 21 — newly working: alerts,
cluster-policies, groups, groups-v2, instance-pools, metastores,
service-principals, service-principals-v2, tokens, users, users-v2.

The coverage harness

scripts/cli_coverage.py points the real databricks CLI at a disposable minilake
and probes every endpoint the installed SDK is known to call, via
databricks api <verb> <path>. An endpoint counts as missing only when minilake
answers with the catchall 501.

The unit of measurement is the (method, path) pair, not the path: probing
everything with GET scores POST-only endpoints as missing, because FastAPI falls
through to the catchall when no method matches. That distinction alone moved the
measured baseline from 10.0% to 13.3%.

Outputs docs/CLI_COVERAGE.md (generated, regenerate freely) and
docs/EMULATION_ROADMAP.md (hand-written, ranks what to close next). The CLI is
pinned into Dockerfile.test so numbers stay comparable across runs.

What was implemented

Things that already had an engine and only lacked a door — the best value here
by a wide margin:

  • sql_task.query — zero new endpoints. saved_queries.py had stored
    query_text all along; the task just never looked. The "no Queries API" note in
    FEATURES.md was simply stale.
  • POST /jobs/runs/submit — the one-shot run path databricks bundle run and
    most CI code take. Reuses the existing DAG scheduler wholesale; a submitted run
    carries its tasks on the run instead of reading them from a job. Honours
    idempotency_token.
  • Alerts (5 endpoints) and sql_task.alert, which evaluates the condition
    against real query results rather than storing a constant.

Compatibility walls — small endpoints that stopped clients before they reached
anything that worked:

  • UC current-metastore-assignment (+ metastore_summary, metastores list/get).
    One endpoint returning one synthetic id, and clients were giving up on it.
  • SCIM Users / Groups / ServicePrincipals (18 endpoints), including the PATCH forms
    Terraform sends for group membership and attribute eq "value" filtering. The
    identity.py user is seeded so Me and Users never disagree.
  • Tokens, secret scope ACLs, and clusters update / pin / unpin.

New functionality:

  • UC functions are created as real DuckDB macros, so a function registered
    through the UC API is then callable from the Statement Execution API by its
    three-part name — SELECT cat.sch.add_tax(100) returns 110.0. Not metadata-only.
  • Cluster policies and instance pools. Neither is enforced (there is no
    compute to constrain), but both resolve. Clusters now retain and validate
    policy_id / instance_pool_id, and a policy or pool in use cannot be deleted.

Scope notes

Identities, tokens and ACLs are records, not credentials. minilake accepts any
bearer token by design, so creating a user makes no way to log in and revoking a
token locks nobody out. These exist because tooling creates them as a setup step
and stops when that step fails.

One deliberate change to existing behaviour: CreateClusterRequest used
extra="ignore" and dropped policy_id (its docstring said so explicitly). Now
that policies and pools are real resources, a cluster that forgot the policy it was
created with would show as permanent drift in Terraform, so those two fields are
kept and validated. Everything else it ignores, it still ignores.

Also fixed along the way

services/catchall.py registers only GET/POST/PUT/PATCH/DELETE, so a HEAD or
OPTIONS request to an unrouted path misses it and gets Starlette's bare 404
instead of minilake's 501 — contradicting the project's "fail loudly" rule. Nothing
is broken today (both HEAD endpoints the SDK calls are implemented), so it is
documented in the roadmap rather than changed here.

Testing

338 passing, up from 267 — 71 new tests across 9 files, all driven through the
real databricks-sdk against the Dockerized stack per the project's testing rules.

Two are the ones that would fail if a feature ever quietly degraded to metadata:
test_sql_function_is_callable_by_three_part_name and
test_sql_task_alert_triggers_on_real_data.

docker compose -f docker-compose.test.yml build
docker compose -f docker-compose.test.yml up --abort-on-container-exit --exit-code-from test-runner
docker compose -f docker-compose.test.yml down -v

To regenerate the coverage map:

docker compose -f docker-compose.test.yml up -d minilake-test-server
uv run python scripts/cli_coverage.py --host http://localhost:8123

Adds a measured coverage map and closes the highest-value gaps it found.
Endpoints answered: 155 -> 208 of the 1168 the databricks-sdk calls. CLI
command groups working end-to-end: 10 -> 21.

Coverage tooling:
- scripts/cli_coverage.py drives the real `databricks` CLI against a running
  minilake and probes every (method, path) the installed SDK calls, recording
  which fall through to the catchall 501. The unit is the method+path pair,
  not the path: probing everything with GET scores POST-only endpoints as
  missing, since FastAPI falls through when no method matches.
- docs/CLI_COVERAGE.md (generated) and docs/EMULATION_ROADMAP.md (curated).
- Databricks CLI pinned into Dockerfile.test so the map is reproducible.

Features that already had an engine and only lacked an endpoint:
- sql_task.query now resolves a saved query's text and runs it on the real
  SQL engine. No new endpoints -- the Queries API had existed all along, and
  the "no Queries API" note in FEATURES.md was stale.
- POST /jobs/runs/submit: one-shot runs, the path `bundle run` and most CI
  code take. Reuses the existing DAG scheduler; a submitted run carries its
  tasks inline instead of reading them from a job. Honours idempotency_token.
- Alerts (/api/2.0/sql/alerts) plus sql_task.alert, which evaluates the
  condition against real query results rather than storing a state.

Compatibility gaps that stopped clients during setup:
- UC current-metastore-assignment, metastore_summary, metastores list/get.
- SCIM Users/Groups/ServicePrincipals: full CRUD, the PATCH forms Terraform
  sends for group membership, and `attribute eq "value"` filtering. The
  identity user is seeded so Me and Users agree.
- Tokens, secret scope ACLs, and clusters update/pin/unpin.

New functionality:
- UC functions are backed by real DuckDB macros, so a function registered
  through the UC API is callable from the Statement Execution API by its
  three-part name -- not metadata-only.
- Cluster policies and instance pools. Neither is enforced (there is no
  compute to constrain), but both resolve; clusters retain and validate
  policy_id/instance_pool_id, and one in use cannot be deleted.

Identities, tokens and ACLs remain records rather than credentials: minilake
accepts any bearer token by design, so none of this authenticates anything.

Tests: 338 passing (up from 267), all driven through the real databricks-sdk
against the Dockerized stack.
@dmux dmux self-assigned this Sep 15, 2026
@dmux dmux added the enhancement New feature or request label Sep 15, 2026
@dmux
dmux commented Sep 15, 2026
Copy link
Copy Markdown
Owner Author

LGTM! 🚀

@dmux
dmux merged commit f8061cd into main Sep 15, 2026
3 checks passed
@dmux
dmux deleted the feat/expand-databricks-api-emulation branch September 30, 2026 01:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0