Skip to content

[Python] Support custom BigQuery endpoints and universe domains - #40675

Open
shunping wants to merge 3 commits into
apache:masterfrom
shunping:tpc-4
Open

shunping wants to merge 3 commits into
apache:masterfrom
shunping:tpc-4

Conversation

@shunping

@shunping shunping commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #40569. Note that the BigQuery apitools clients are currently being deprecated (#39889)

Problem

BigQueryWrapper._bigquery_client() builds the apitools BigqueryV2 client without a url, so it falls back to BASE_URL = 'https://bigquery.googleapis.com/bigquery/v2/'. apitools does not read GOOGLE_CLOUD_UNIVERSE_DOMAIN, and Beam has no option to override the endpoint. As a result, BigQuery REST calls (tables, jobs, datasets) always go to the public endpoint. This makes BigQuery IO unusable in Trusted Partner Cloud (TPC) and other non-default universes.

Changes

  • New --bigquery_endpoint option in GoogleCloudOptions, the Python equivalent of Java's BigQueryOptions.bigQueryEndpoint (Allow setting BigQuery endpoint #32153). It takes the root URL, e.g. https://bigquery.example.com. The input is normalized: a missing scheme defaults to https, and a trailing / or /bigquery/v2 is stripped.
  • Endpoint resolution for BigqueryV2, in this order:
    1. --bigquery_endpoint
    2. https://bigquery.<domain> when GOOGLE_CLOUD_UNIVERSE_DOMAIN is set to something other than googleapis.com
    3. The default public URL
      Step 2 matches how google-cloud-bigquery resolves its endpoint, so both clients target the same universe.
  • google.cloud.bigquery.Client (streaming inserts) gets client_options={'api_endpoint': ...} when --bigquery_endpoint is set, merged with quota_project_id. When the option is unset, the library resolves the endpoint itself, including GOOGLE_CLOUD_UNIVERSE_DOMAIN.
  • Worker-side fallback: when a wrapper is created without pipeline options, e.g. BigQueryWrapper() inside DoFns, the endpoint is read from the running pipeline's options via RuntimeValueProvider.

Not changed

  • The Storage Read API (BigQueryReadClient) does not use --bigquery_endpoint. It is served from a different host (bigquerystorage.<domain>), and the client library already reads GOOGLE_CLOUD_UNIVERSE_DOMAIN. Java does apply its option to the storage clients; this can be revisited if a separate storage endpoint option is needed.
  • Default behavior is unchanged when neither the option nor the env var is set.

@shunping
shunping marked this pull request as ready for review October 20, 2026 13:55

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📋 Review Summary

This PR adds support for custom BigQuery API endpoints and sovereign cloud universe domains via the --bigquery_endpoint pipeline option and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variable, wiring them into both the apitools and google-cloud-bigquery clients. The implementation is clean, well-structured, and thoroughly covered by unit tests.

🔍 General Feedback

  • The endpoint normalization logic in _normalize_bigquery_root handles trailing slashes, /bigquery/v2 suffixes, and bare hostnames cleanly.
  • Passing the derived host from api_url to _HttpWithHeaders ensures x-goog-user-project quota headers continue to work seamlessly against custom endpoints and TPC universe domains without leaking to OAuth token endpoints.

💡 Tip: Comment /gemini review on this pull request to trigger a new Gemini code review.

@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.08%. Comparing base (a8d6afd) to head (6414324).
⚠️ Report is 35 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #40675      +/-   ##
==========================================
+ Coverage   80.04%   80.08%   +0.03%     
==========================================
  Files         490      490              
  Lines       82916    83048     +132     
==========================================
+ Hits        66373    66508     +135     
+ Misses      16543    16540       -3     
Flag Coverage Δ
python 80.08% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

Assigning reviewers:

R: @claudevdm for label python.
Backup reviewer: jrmccluskey (if the main reviewer is unresponsive, you can escalate to them by tagging their username)

Note: If you would like to opt out of this review, comment assign to next reviewer.

Available commands:

  • stop reviewer notifications - opt out of the automated review tooling
  • remind me after tests pass - tag the comment author after tests pass
  • waiting on author - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).

Comment thread sdks/python/apache_beam/options/pipeline_options.py Outdated
Comment thread sdks/python/apache_beam/options/pipeline_options.py Outdated
BigQueryWrapper always sent BigQuery REST calls to bigquery.googleapis.com,
so it could not be used in Trusted Partner Cloud (TPC) or other universes.

Add a --bigquery_endpoint option, matching Java's bigQueryEndpoint. The
BigqueryV2 URL now comes from that option, then from
GOOGLE_CLOUD_UNIVERSE_DOMAIN, then the default URL. The option is also
passed to google.cloud.bigquery.Client, which reads the universe domain on
its own when the option is unset. Workers fall back to the running
pipeline's options.
Store the option as big_query_endpoint so it is serialized as
beam:option:big_query_endpoint:v1, which Java maps to the
bigQueryEndpoint option used by cross-language BigQuery transforms.

Both --bigquery_endpoint and --big_query_endpoint, and both attribute
names on BigQueryOptions, are accepted.
@shunping
shunping requested review from claudevdm and removed request for claudevdm October 21, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants