Cursor/bigquery universe domain clean 3190 - #2323
ybelleguic wants to merge 2 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Add an optional universe_domain field to the BigQuery credentials proto and plumb it through to the BigQuery and data-lineage clients so the CLI can target non-default universes (e.g. Trusted Partner Cloud). The value is read from .df-credentials.json and can be entered during 'dataform init-creds'. When unset, clients keep defaulting to the Google Default Universe. Adds unit tests covering credential parsing and client construction.
821f551 to
2f09b5c
Compare
| apiEndpoint: endpoint, | ||
| credentials: credentials.credentials && JSON.parse(credentials.credentials), | ||
| libName: DATAFORM_CLI_LIB_NAME, | ||
| libVersion: version | ||
| libVersion: version, | ||
| ...(credentials.universeDomain ? { universeDomain: credentials.universeDomain } : {}) |
There was a problem hiding this comment.
This doesn't take effect: LineageClient resolves servicePath = opts.servicePath || opts.apiEndpoint || 'datalineage.' + universeDomain, and we always pass apiEndpoint from LineageEndpointRouter, which hardcodes googleapis.com. So lineage keeps targeting GDU hosts.
It's also a bit worse than a no-op: gax compares the configured universe against the credential's before each call, so setting it here makes that check pass while we carry on dialing a GDU endpoint — a loud failure becomes a silent one.
Could the endpoint router become universe-aware, or this hunk drop out for now? Either way it needs coverage; emitter_test.ts doesn't touch it.
| const universeDomain = question( | ||
| "Enter the universe domain to connect to, or leave blank to use the default " + | ||
| "('googleapis.com'). Set this only when targeting a non-default universe such as a " + | ||
| "Trusted Partner Cloud (TPC):" | ||
| ).trim(); |
There was a problem hiding this comment.
Could we avoid prompting every user for this? Nearly all of them are on GDU, and the proto change by itself already lets the rare TPC user set the field by hand in .df-credentials.json.
If it does stay interactive, it's currently untested — cli/index_init_test.ts only covers the failure path.
| credentials: fs.readFileSync(cloudCredentialsPath, "utf8"), | ||
| location | ||
| location, | ||
| ...(universeDomain ? { universeDomain } : {}) |
There was a problem hiding this comment.
If someone supplies a TPC service-account key but leaves the prompt blank, we write no universeDomain: BigQuery then defaults to googleapis.com while google-auth derives the key's own universe, and they disagree at query time. Worth falling back to cloudCredentials.universe_domain here.
| location: credentials.location, | ||
| credentials: credentials.credentials && JSON.parse(credentials.credentials) | ||
| credentials: credentials.credentials && JSON.parse(credentials.credentials), | ||
| ...(credentials.universeDomain ? { universeDomain: credentials.universeDomain } : {}) |
There was a problem hiding this comment.
Nit: redundant here — @google-cloud/bigquery already falsy-checks options.universeDomain (bigquery.js:120), so universeDomain: credentials.universeDomain || undefined would do.
The guard in emitter.ts is needed though, since gax uses ?? — might be worth a comment there noting the asymmetry.
| expect(credentials.universeDomain).to.satisfy( | ||
| (value: string) => value === "" || value === undefined | ||
| ); |
There was a problem hiding this comment.
read() returns a protobufjs message, so an unset string is deterministically "" — this can just be expect(credentials.universeDomain).to.equal(""). As written it would still pass if the value became undefined, which is the distinction the guards in bigquery.ts and emitter.ts depend on.
| await adapter.setMetadata(action); | ||
| }); | ||
|
|
||
| suite("createBigQueryClientProvider", () => { |
There was a problem hiding this comment.
Nit: this suite doesn't exercise BigQueryDbAdapter — could it be a sibling top-level suite rather than nested inside it?
| string credentials = 3; | ||
| // Options are listed here: https://cloud.google.com/bigquery/docs/locations | ||
| string location = 4; | ||
| // The universe domain to connect to (e.g. "googleapis.com"). Leave unset to |
There was a problem hiding this comment.
Nit: (e.g. "googleapis.com") next to "leave unset to use the default" is a little contradictory, since that's the one value you'd never set here. A non-default universe would be a clearer example.
| - `projectId`: your GCP project id | ||
| - `credentials`: the entire content of your GCP service account key JSON file as a single string (you can generate it with `jq -Rsa < path/to/key.json`). | ||
| - `location`: location to use in your project | ||
| - `universeDomain` (optional): the universe domain to connect to (e.g. `googleapis.com`). Leave unset to use the default Google Default Universe (GDU). Set this only when targeting a non-default universe such as a Trusted Partner Cloud (TPC). |
There was a problem hiding this comment.
This covers the integration-test credentials only — is a matching update to the user-facing Cloud docs tracked anywhere?
|
Thanks for this — the BigQuery half looks good. Two things I'd like to sort out before this might be considered:
One question: (FYI the CLA check is failing, and the title is still the generated branch name.) |
What
Adds support for configuring the
universeDomainused by the BigQuery anddata-lineage clients, so the Dataform CLI can connect to a non-default universe
(for example a Trusted Partner Cloud / TPC deployment) instead of the Google
Default Universe (
googleapis.com).Why
@google-cloud/bigqueryalready acceptsuniverseDomainon its constructoroptions, but there was no way to set it from Dataform: the BigQuery client is
built in
createBigQueryClientProvider()(cli/api/dbadapters/bigquery.ts)purely from the credentials, and the credentials shape is defined by the
BigQueryproto. Since.df-credentials.jsonis strictly validated againstthat proto (
verifyObjectMatchesProtorejects unknown fields), users targetinga non-default universe had no supported way to specify it.
Changes
protos/profiles.proto: add an optionalstring universe_domain = 5;fieldto the
BigQuerycredentials message.cli/api/dbadapters/bigquery.ts: forwarduniverseDomaintonew BigQuery({ ... })when set.cli/api/lineage/emitter.ts: forwarduniverseDomaintonew LineageClient({ ... })when set (google-gaxClientOptionssupports it),so lineage emission targets the same universe.
cli/credentials.ts: prompt for an optional universe domain duringdataform init-creds(leaving it blank keeps the default).contributing.md: document the new optional field in the credentials schema.cli/api/commands/credentials_test.ts(new) covers credential parsingincluding rejection of unknown fields;
cli/api/dbadapters/bigquery_test.tsverifies the value reaches the client and defaults to
googleapis.comwhenunset.
The field is optional and empty by default, so existing credentials files and
callers are completely unaffected.
Testing
bazel test //cli/api:commands/credentials_test //cli/api:dbadapters/bigquery_test— pass../scripts/run_tests(eslint + full Bazel suite) — pass../scripts/run run <project> --dry-runwith a.df-credentials.jsoncontaining
universeDomainis accepted and the BigQuery request targets thederived endpoint (
https://bigquery.<universeDomain>/...).