Skip to main content

databricks-isv-testing

How to run and structure auth tests for Databricks ISV integrations: clean env per test, runner script patterns, U2M browser flows, and language-specific considerations.

Quellinformationen

Repository
databricks-solutions/partner-ai-dev-kit
Letzte Quellaktivität
15. April 2026 um 00:36
Erkannte Sprache von SKILL.md
Englisch
Sterne
5
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
databricks-isv-testing
description
How to run and structure auth tests for Databricks ISV integrations: clean env per test, runner script patterns, U2M browser flows, and language-specific considerations.
<!-- skill-version: 1.0.0 --> # Testing Auth for ISV Integrations Use this skill when **running or designing tests** for Databricks partner authentication (PAT, OAuth M2M, U2M). ## Core Principle: Clean Environment Per Test **Never run multiple auth types in one process** with mixed environment variables. SDKs and drivers error with "more than one authorization method configured" if conflicting credentials are set. ### Option A: `env -i` (Automated Test Runners) ```bash env -i PATH="$PATH" HOME="$HOME" \ DATABRICKS_HOST="https://myworkspace.cloud.databricks.com" \ DATABRICKS_TOKEN="dapi..." \ python your_pat_example.py ``` **Caveat:** In long interactive sessions, `env -i` may strip needed vars like `PYTHONPATH`. Use Option B for manual testing. ### Option B: Fresh Bash Subshell (Interactive Testing) ```bash /bin/bash -c ' export DATABRICKS_HOST="https://myworkspace.cloud.databricks.com" export DATABRICKS_TOKEN="dapi..." unset DATABRICKS_CLIENT_ID DATABRICKS_CLIENT_SECRET export PYTHONUNBUFFERED=1 python your_pat_example.py ' ``` Starts a completely clean child process. More reliable for interactive manual testing. --- ## Environment Variables by Auth Type | Auth Type | Selector Value | Required Variables | Must NOT Be Set | |-----------|----------------|--------------------|-----------------| | PAT | `pat` | `DATABRICKS_HOST`, `DATABRICKS_TOKEN` | `CLIENT_ID`, `CLIENT_SECRET` | | OAuth M2M | `oauth_m2m` | `DATABRICKS_HOST`, `DATABRICKS_CLIENT_ID`, `DATABRICKS_CLIENT_SECRET` | `DATABRICKS_TOKEN` | | U2M External Browser | `u2m_external_browser` | `DATABRICKS_HOST` | `CLIENT_ID`, `CLIENT_SECRET`, `TOKEN` | | U2M Custom OAuth App | `u2m_custom_oauth_app` | `DATABRICKS_HOST`, `DATABRICKS_U2M_CLIENT_ID` | `DATABRICKS_CLIENT_ID` | | U2M Token-Env | `u2m_token_env` | `DATABRICKS_HOST`, `DATABRICKS_ACCESS_TOKEN` | `CLIENT_ID`, `CLIENT_SECRET` | **Optional for all:** `DATABRICKS_HTTP_PATH` (SQL drivers), `DATABRICKS_WAREHOUSE_ID` (Statement Execution API). **Optional for U2M Custom OAuth App:** `DATABRICKS_U2M_CLIENT_SECRET` (if confidential app), `DATABRICKS_REDIRECT_URI` (default varies by connector). ### CLIENT_ID Distinction (Critical) | Env Var | Auth Type | What It Is | |---------|-----------|------------| | `DATABRICKS_CLIENT_ID` | `oauth_m2m` | M2M Service Principal UUID | | `DATABRICKS_U2M_CLIENT_ID` | `u2m_custom_oauth_app` | Custom OAuth App from App Connections | Using the wrong one causes `"OAuth application with client_id not available"`. --- ## Test Runner Script Pattern A well-structured test runner: 1. **Sources credentials once** from an env file 2. **Runs each test with isolated env** using `env -i` plus only required vars 3. **Records pass/fail** per test 4. **Prints summary** at the end ### Example Runner Structure ```bash #!/usr/bin/env bash set -euo pipefail # Load credentials source "${1:-credentials.env}" PASSED=0 FAILED=0 run_test() { local name="$1" local cmd="$2" echo "Running: $name" if eval "$cmd" > /dev/null 2>&1; then echo " PASS" ((PASSED++)) else echo " FAIL" ((FAILED++)) fi } # PAT Test run_test "PAT" "env -i PATH=\"$PATH\" HOME=\"$HOME\" \ DATABRICKS_HOST=\"$DATABRICKS_HOST\" \ DATABRICKS_TOKEN=\"$DATABRICKS_TOKEN\" \ python your_pat_example.py" # OAuth M2M Test run_test "OAuth M2M" "env -i PATH=\"$PATH\" HOME=\"$HOME\" \ DATABRICKS_HOST=\"$DATABRICKS_HOST\" \ DATABRICKS_CLIENT_ID=\"$DATABRICKS_CLIENT_ID\" \ DATABRICKS_CLIENT_SECRET=\"$DATABRICKS_CLIENT_SECRET\" \ python your_m2m_example.py" # Summary echo "" echo "Results: $PASSED passed, $FAILED failed" ``` --- ## U2M Browser Test Considerations ### Built-in OAuth App (External Browser) - Do NOT pass M2M credentials (`DATABRICKS_CLIENT_ID`/`DATABRICKS_CLIENT_SECRET`) - The SDK uses the built-in `databricks-cli` OAuth app - Redirect URI is typically `http://localhost:8020` ```bash env -i PATH="$PATH" HOME="$HOME" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ USER="$USER" DISPLAY="${DISPLAY:-}" \ python your_u2m_browser_example.py ``` ### Custom OAuth App (PKCE) - Use `DATABRICKS_U2M_CLIENT_ID` (NOT `DATABRICKS_CLIENT_ID`) - Optionally set `DATABRICKS_U2M_CLIENT_SECRET` and `DATABRICKS_REDIRECT_URI` - Default redirect URI is typically `http://localhost:8040/callback` ```bash env -i PATH="$PATH" HOME="$HOME" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_U2M_CLIENT_ID="$DATABRICKS_U2M_CLIENT_ID" \ DATABRICKS_U2M_CLIENT_SECRET="$DATABRICKS_U2M_CLIENT_SECRET" \ DATABRICKS_REDIRECT_URI="http://localhost:8040/callback" \ USER="$USER" DISPLAY="${DISPLAY:-}" \ python your_u2m_custom_app_example.py ``` ### Port Cleanup Before U2M Tests Before running custom OAuth app tests, kill any process holding the redirect port: ```bash lsof -ti:8040 | xargs kill -9 2>/dev/null || true ``` A previous hung test can leave the port bound. --- ## HTTPServer Pitfalls (PKCE Flow Implementation) When implementing the local callback server for PKCE: ### Python Implementation Pattern ```python import threading from http.server import HTTPServer, BaseHTTPRequestHandler class CallbackHandler(BaseHTTPRequestHandler): auth_code = None callback_received = threading.Event() def do_GET(self): if "/callback" in self.path: # Extract code from query params from urllib.parse import urlparse, parse_qs query = parse_qs(urlparse(self.path).query) CallbackHandler.auth_code = query.get("code", [None])[0] self.send_response(200) self.end_headers() self.wfile.write(b"Authentication complete. You can close this tab.") CallbackHandler.callback_received.set() else: # Ignore other requests (favicon, etc.) self.send_response(204) self.end_headers() def log_message(self, format, *args): pass # Suppress logging def run_callback_server(port=8040, timeout=120): server = HTTPServer(("localhost", port), CallbackHandler) server.timeout = timeout # CRITICAL: Set timeout # Handle requests until callback received or timeout while not CallbackHandler.callback_received.is_set(): server.handle_request() server.server_close() # Use server_close(), NOT shutdown() return CallbackHandler.auth_code ``` **Key Points:** - **Always set `server.timeout`** — Without it, `handle_request()` blocks forever - **Use `server.server_close()`** — NOT `server.shutdown()` (which hangs with `handle_request()`) - **Handle multiple requests** — Browser may send favicon requests before the callback - **Use `threading.Event`** — To signal when the actual callback is received --- ## Language-Specific Notes ### Python ```bash # PAT env -i PATH="$PATH" HOME="$HOME" PYTHONUNBUFFERED=1 \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_TOKEN="$DATABRICKS_TOKEN" \ python your_example.py # OAuth M2M env -i PATH="$PATH" HOME="$HOME" PYTHONUNBUFFERED=1 \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_CLIENT_ID="$DATABRICKS_CLIENT_ID" \ DATABRICKS_CLIENT_SECRET="$DATABRICKS_CLIENT_SECRET" \ python your_example.py # U2M (browser) env -i PATH="$PATH" HOME="$HOME" USER="$USER" DISPLAY="${DISPLAY:-}" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_U2M_CLIENT_ID="$DATABRICKS_U2M_CLIENT_ID" \ python your_example.py ``` ### Java - **Environment isolation:** Run with `env -i` to prevent Java SDK auto-reading conflicting env vars - **Java 17+ JDBC:** Add `--add-opens=java.base/java.nio=ALL-UNNAMED` to JVM args for Arrow-based OSS JDBC driver - **SDK Workarounds (U2M):** Must call `config.setScopes(Arrays.asList("all-apis"))` and `config.resolve()` before `config.authenticate()` ```bash export MAVEN_OPTS="--add-opens=java.base/java.nio=ALL-UNNAMED" # PAT env -i PATH="$PATH" HOME="$HOME" JAVA_HOME="$JAVA_HOME" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_TOKEN="$DATABRICKS_TOKEN" \ mvn -q exec:java -Dexec.mainClass="com.example.PatExample" # OAuth M2M env -i PATH="$PATH" HOME="$HOME" JAVA_HOME="$JAVA_HOME" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_CLIENT_ID="$DATABRICKS_CLIENT_ID" \ DATABRICKS_CLIENT_SECRET="$DATABRICKS_CLIENT_SECRET" \ mvn -q exec:java -Dexec.mainClass="com.example.M2MExample" ``` ### Go - **Go SDK uses `APP_AUTH_TYPE`:** The SDK reads `DATABRICKS_AUTH_TYPE` internally, so use `APP_AUTH_TYPE` for your auth selector - **Go SQL Driver uses `DATABRICKS_AUTH_TYPE`:** Safe to use as the selector - **Build once, run with `env -i`:** Build the binary first, then run with isolated env ```bash # Build once (example for Go SDK with build tags) go build -tags all_auth_example -o ./my_example ./ # PAT (Go SDK uses APP_AUTH_TYPE) env -i PATH="$PATH" HOME="$HOME" \ APP_AUTH_TYPE=pat \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_TOKEN="$DATABRICKS_TOKEN" \ ./my_example # OAuth M2M env -i PATH="$PATH" HOME="$HOME" \ APP_AUTH_TYPE=oauth_m2m \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_CLIENT_ID="$DATABRICKS_CLIENT_ID" \ DATABRICKS_CLIENT_SECRET="$DATABRICKS_CLIENT_SECRET" \ ./my_example # U2M (browser) - needs USER and DISPLAY env -i PATH="$PATH" HOME="$HOME" USER="$USER" DISPLAY="${DISPLAY:-}" \ APP_AUTH_TYPE=u2m_custom_oauth_app \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_U2M_CLIENT_ID="$DATABRICKS_U2M_CLIENT_ID" \ ./my_example ``` ### Node.js ```bash # PAT env -i PATH="$PATH" HOME="$HOME" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_HTTP_PATH="$DATABRICKS_HTTP_PATH" \ DATABRICKS_TOKEN="$DATABRICKS_TOKEN" \ node your_example.js # OAuth M2M env -i PATH="$PATH" HOME="$HOME" \ DATABRICKS_HOST="$DATABRICKS_HOST" \ DATABRICKS_HTTP_PATH="$DATABRICKS_HTTP_PATH" \ DATABRICKS_CLIENT_ID="$DATABRICKS_CLIENT_ID" \ DATABRICKS_CLIENT_SECRET="$DATABRICKS_CLIENT_SECRET" \ node your_example.js ``` --- ## Multi-Auth Example Pattern Support multiple auth types via an environment variable selector: ```python import os auth_type = os.environ.get("APP_AUTH_TYPE", "oauth_m2m")
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen