Skip to content

Commit 441c427

Browse files
committed
fixes
1 parent 56583c1 commit 441c427

File tree

2 files changed

+144
-56
lines changed

2 files changed

+144
-56
lines changed

databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.databricks.sdk.core.utils.Environment;
1414
import com.fasterxml.jackson.databind.ObjectMapper;
1515
import java.io.File;
16+
import java.net.URI;
1617
import java.io.IOException;
1718
import java.lang.reflect.Field;
1819
import java.time.Duration;
@@ -231,17 +232,21 @@ private synchronized DatabricksConfig innerResolve() {
231232
}
232233

233234
/**
234-
* Attempts to resolve host metadata from the well-known endpoint. Logs a warning and continues if
235-
* metadata resolution fails, since not all hosts support the discovery endpoint.
235+
* Attempts to resolve host metadata from the well-known endpoint. Only called for unified hosts.
236+
* Logs a warning and continues if metadata resolution fails, since not all hosts support the
237+
* discovery endpoint.
236238
*/
237239
private void tryResolveHostMetadata() {
238240
if (host == null) {
239241
return;
240242
}
243+
if (experimentalIsUnifiedHost == null || !experimentalIsUnifiedHost) {
244+
return;
245+
}
241246
try {
242247
resolveHostMetadata();
243248
} catch (Exception e) {
244-
LOG.debug("Failed to resolve host metadata: {}", e.getMessage());
249+
LOG.warn("Failed to resolve host metadata: {}. Falling back to user config.", e.getMessage());
245250
}
246251
}
247252

@@ -852,37 +857,46 @@ HostMetadata getHostMetadata() throws IOException {
852857
* discovery endpoint.
853858
*
854859
* <p>Fills in {@code accountId}, {@code workspaceId}, and {@code discoveryUrl} (derived from
855-
* {@code oidc_endpoint}, with any {@code {account_id}} placeholder substituted) if not already
856-
* set.
860+
* {@code oidc_endpoint}, with {@code /.well-known/oauth-authorization-server} appended and any
861+
* {@code {account_id}} placeholder substituted) if not already set.
862+
*
863+
* <p>Errors from the metadata endpoint are non-fatal: a warning is logged and the method returns
864+
* without modifying the config. This mirrors the Go SDK behavior where metadata resolution is
865+
* best-effort during config init.
857866
*
858867
* <p><b>Note:</b> This API is experimental and may change or be removed in future releases
859868
* without notice.
860-
*
861-
* @throws DatabricksException if {@code accountId} cannot be resolved or {@code oidc_endpoint} is
862-
* missing from the host metadata.
863869
*/
864870
void resolveHostMetadata() throws IOException {
865871
if (host == null) {
866872
return;
867873
}
868874
HostMetadata meta = getHostMetadata();
869875
if (accountId == null && meta.getAccountId() != null) {
876+
LOG.debug("Resolved account_id from host metadata: \"{}\"", meta.getAccountId());
870877
accountId = meta.getAccountId();
871878
}
872-
if (accountId == null) {
873-
throw new DatabricksException(
874-
"account_id is not configured and could not be resolved from host metadata");
875-
}
876879
if (workspaceId == null && meta.getWorkspaceId() != null) {
880+
LOG.debug("Resolved workspace_id from host metadata: \"{}\"", meta.getWorkspaceId());
877881
workspaceId = meta.getWorkspaceId();
878882
}
879883
if (discoveryUrl == null) {
880-
if (meta.getOidcEndpoint() != null && !meta.getOidcEndpoint().isEmpty()) {
881-
discoveryUrl = meta.getOidcEndpoint().replace("{account_id}", accountId);
882-
} else {
883-
throw new DatabricksException(
884-
"discovery_url is not configured and could not be resolved from host metadata");
884+
if (meta.getOidcEndpoint() == null || meta.getOidcEndpoint().isEmpty()) {
885+
LOG.warn("Host metadata missing oidc_endpoint; skipping discovery URL resolution");
886+
return;
887+
}
888+
String oidcRoot = meta.getOidcEndpoint();
889+
if (oidcRoot.contains("{account_id}")) {
890+
if (accountId == null || accountId.isEmpty()) {
891+
LOG.warn(
892+
"Host metadata oidc_endpoint contains {account_id} placeholder but account_id is not set; skipping discovery URL resolution");
893+
return;
894+
}
895+
oidcRoot = oidcRoot.replace("{account_id}", accountId);
885896
}
897+
URI oidcUri = URI.create(oidcRoot.endsWith("/") ? oidcRoot : oidcRoot + "/");
898+
discoveryUrl = oidcUri.resolve(".well-known/oauth-authorization-server").toString();
899+
LOG.debug("Resolved discovery_url from host metadata: \"{}\"", discoveryUrl);
886900
}
887901
}
888902

databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java

Lines changed: 113 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ public void testToStringWithEnv() {
9999
public void testWorkspaceLevelOidcEndpointsWithAccountId() throws IOException {
100100
try (FixtureServer server =
101101
new FixtureServer()
102-
.with("GET", "/.well-known/databricks-config", "{}", 404)
103102
.with(
104103
"GET",
105104
"/oidc/.well-known/oauth-authorization-server",
@@ -119,7 +118,6 @@ public void testWorkspaceLevelOidcEndpointsWithAccountId() throws IOException {
119118
public void testWorkspaceLevelOidcEndpointsRetries() throws IOException {
120119
try (FixtureServer server =
121120
new FixtureServer()
122-
.with("GET", "/.well-known/databricks-config", "{}", 404)
123121
.with("GET", "/oidc/.well-known/oauth-authorization-server", "", 429)
124122
.with(
125123
"GET",
@@ -445,9 +443,7 @@ public void testGetHostMetadataWorkspaceStaticOidcEndpoint() throws IOException
445443
+ DUMMY_WORKSPACE_ID
446444
+ "\"}";
447445
try (FixtureServer server =
448-
new FixtureServer()
449-
.with("GET", "/.well-known/databricks-config", response, 200)
450-
.with("GET", "/.well-known/databricks-config", response, 200)) {
446+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
451447
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
452448
config.resolve(emptyEnv());
453449
HostMetadata meta = config.getHostMetadata();
@@ -462,9 +458,7 @@ public void testGetHostMetadataAccountRawOidcTemplate() throws IOException {
462458
String response =
463459
"{\"oidc_endpoint\":\"https://acc.databricks.com/oidc/accounts/{account_id}\"}";
464460
try (FixtureServer server =
465-
new FixtureServer()
466-
.with("GET", "/.well-known/databricks-config", response, 200)
467-
.with("GET", "/.well-known/databricks-config", response, 200)) {
461+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
468462
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
469463
config.resolve(emptyEnv());
470464
HostMetadata meta = config.getHostMetadata();
@@ -477,9 +471,7 @@ public void testGetHostMetadataAccountRawOidcTemplate() throws IOException {
477471
@Test
478472
public void testGetHostMetadataRaisesOnHttpError() throws IOException {
479473
try (FixtureServer server =
480-
new FixtureServer()
481-
.with("GET", "/.well-known/databricks-config", "{}", 404)
482-
.with("GET", "/.well-known/databricks-config", "{}", 404)) {
474+
new FixtureServer().with("GET", "/.well-known/databricks-config", "{}", 404)) {
483475
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
484476
config.resolve(emptyEnv());
485477
DatabricksException ex =
@@ -501,15 +493,15 @@ public void testResolveHostMetadataWorkspacePopulatesAllFields() throws IOExcept
501493
+ DUMMY_WORKSPACE_ID
502494
+ "\"}";
503495
try (FixtureServer server =
504-
new FixtureServer()
505-
.with("GET", "/.well-known/databricks-config", response, 200)
506-
.with("GET", "/.well-known/databricks-config", response, 200)) {
496+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
507497
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
508498
config.resolve(emptyEnv());
509499
config.resolveHostMetadata();
510500
assertEquals(DUMMY_ACCOUNT_ID, config.getAccountId());
511501
assertEquals(DUMMY_WORKSPACE_ID, config.getWorkspaceId());
512-
assertEquals("https://ws.databricks.com/oidc", config.getDiscoveryUrl());
502+
assertEquals(
503+
"https://ws.databricks.com/oidc/.well-known/oauth-authorization-server",
504+
config.getDiscoveryUrl());
513505
}
514506
}
515507

@@ -518,15 +510,16 @@ public void testResolveHostMetadataAccountSubstitutesAccountId() throws IOExcept
518510
String response =
519511
"{\"oidc_endpoint\":\"https://acc.databricks.com/oidc/accounts/{account_id}\"}";
520512
try (FixtureServer server =
521-
new FixtureServer()
522-
.with("GET", "/.well-known/databricks-config", response, 200)
523-
.with("GET", "/.well-known/databricks-config", response, 200)) {
513+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
524514
DatabricksConfig config =
525515
new DatabricksConfig().setHost(server.getUrl()).setAccountId(DUMMY_ACCOUNT_ID);
526516
config.resolve(emptyEnv());
527517
config.resolveHostMetadata();
528518
assertEquals(
529-
"https://acc.databricks.com/oidc/accounts/" + DUMMY_ACCOUNT_ID, config.getDiscoveryUrl());
519+
"https://acc.databricks.com/oidc/accounts/"
520+
+ DUMMY_ACCOUNT_ID
521+
+ "/.well-known/oauth-authorization-server",
522+
config.getDiscoveryUrl());
530523
}
531524
}
532525

@@ -539,9 +532,7 @@ public void testResolveHostMetadataDoesNotOverwriteExistingFields() throws IOExc
539532
+ "\"account_id\":\"other-account\","
540533
+ "\"workspace_id\":\"other-ws\"}";
541534
try (FixtureServer server =
542-
new FixtureServer()
543-
.with("GET", "/.well-known/databricks-config", response, 200)
544-
.with("GET", "/.well-known/databricks-config", response, 200)) {
535+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
545536
DatabricksConfig config =
546537
new DatabricksConfig()
547538
.setHost(server.getUrl())
@@ -555,42 +546,38 @@ public void testResolveHostMetadataDoesNotOverwriteExistingFields() throws IOExc
555546
}
556547

557548
@Test
558-
public void testResolveHostMetadataRaisesWhenAccountIdUnresolvable() throws IOException {
549+
public void testResolveHostMetadataMissingAccountIdWithPlaceholderSkipsDiscoveryUrl()
550+
throws IOException {
559551
String response =
560552
"{\"oidc_endpoint\":\"https://acc.databricks.com/oidc/accounts/{account_id}\"}";
561553
try (FixtureServer server =
562-
new FixtureServer()
563-
.with("GET", "/.well-known/databricks-config", response, 200)
564-
.with("GET", "/.well-known/databricks-config", response, 200)) {
554+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
565555
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
566556
config.resolve(emptyEnv());
567-
DatabricksException ex =
568-
assertThrows(DatabricksException.class, () -> config.resolveHostMetadata());
569-
assertTrue(ex.getMessage().contains("account_id is not configured"));
557+
config.resolveHostMetadata();
558+
// DiscoveryURL should not be set because account_id is empty and placeholder can't be
559+
// substituted
560+
assertNull(config.getDiscoveryUrl());
570561
}
571562
}
572563

573564
@Test
574-
public void testResolveHostMetadataRaisesWhenOidcEndpointMissing() throws IOException {
565+
public void testResolveHostMetadataNoOidcEndpointSkipsDiscoveryUrl() throws IOException {
575566
String response = "{\"account_id\":\"" + DUMMY_ACCOUNT_ID + "\"}";
576567
try (FixtureServer server =
577-
new FixtureServer()
578-
.with("GET", "/.well-known/databricks-config", response, 200)
579-
.with("GET", "/.well-known/databricks-config", response, 200)) {
568+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
580569
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
581570
config.resolve(emptyEnv());
582-
DatabricksException ex =
583-
assertThrows(DatabricksException.class, () -> config.resolveHostMetadata());
584-
assertTrue(ex.getMessage().contains("discovery_url is not configured"));
571+
config.resolveHostMetadata();
572+
assertEquals(DUMMY_ACCOUNT_ID, config.getAccountId());
573+
assertNull(config.getDiscoveryUrl());
585574
}
586575
}
587576

588577
@Test
589578
public void testResolveHostMetadataRaisesOnHttpError() throws IOException {
590579
try (FixtureServer server =
591-
new FixtureServer()
592-
.with("GET", "/.well-known/databricks-config", "{}", 500)
593-
.with("GET", "/.well-known/databricks-config", "{}", 500)) {
580+
new FixtureServer().with("GET", "/.well-known/databricks-config", "{}", 500)) {
594581
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
595582
config.resolve(emptyEnv());
596583
DatabricksException ex =
@@ -599,6 +586,93 @@ public void testResolveHostMetadataRaisesOnHttpError() throws IOException {
599586
}
600587
}
601588

589+
// --- tryResolveHostMetadata (config init) tests ---
590+
591+
@Test
592+
public void testEnsureResolvedResolvesHostMetadataWhenUnifiedHost() throws IOException {
593+
String response =
594+
"{\"oidc_endpoint\":\"https://ws.databricks.com/oidc\","
595+
+ "\"account_id\":\""
596+
+ DUMMY_ACCOUNT_ID
597+
+ "\","
598+
+ "\"workspace_id\":\""
599+
+ DUMMY_WORKSPACE_ID
600+
+ "\"}";
601+
try (FixtureServer server =
602+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
603+
DatabricksConfig config =
604+
new DatabricksConfig()
605+
.setHost(server.getUrl())
606+
.setExperimentalIsUnifiedHost(true);
607+
config.resolve(emptyEnv());
608+
assertEquals(DUMMY_ACCOUNT_ID, config.getAccountId());
609+
assertEquals(DUMMY_WORKSPACE_ID, config.getWorkspaceId());
610+
assertEquals(
611+
"https://ws.databricks.com/oidc/.well-known/oauth-authorization-server",
612+
config.getDiscoveryUrl());
613+
}
614+
}
615+
616+
@Test
617+
public void testEnsureResolvedSkipsHostMetadataWhenNotUnified() throws IOException {
618+
// No metadata endpoint fixture — if it were called, the fixture server would fail
619+
try (FixtureServer server = new FixtureServer()) {
620+
DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl());
621+
config.resolve(emptyEnv());
622+
assertNull(config.getAccountId());
623+
assertNull(config.getWorkspaceId());
624+
}
625+
}
626+
627+
@Test
628+
public void testEnsureResolvedHostMetadataFailureNonFatal() throws IOException {
629+
try (FixtureServer server =
630+
new FixtureServer()
631+
.with("GET", "/.well-known/databricks-config", "{\"error\": \"internal error\"}", 500)) {
632+
DatabricksConfig config =
633+
new DatabricksConfig()
634+
.setHost(server.getUrl())
635+
.setExperimentalIsUnifiedHost(true);
636+
// Should not throw — metadata failure is non-fatal
637+
config.resolve(emptyEnv());
638+
assertNull(config.getAccountId());
639+
assertNull(config.getWorkspaceId());
640+
}
641+
}
642+
643+
@Test
644+
public void testEnsureResolvedHostMetadataNoOidcEndpointNonFatal() throws IOException {
645+
String response = "{\"account_id\":\"" + DUMMY_ACCOUNT_ID + "\"}";
646+
try (FixtureServer server =
647+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
648+
DatabricksConfig config =
649+
new DatabricksConfig()
650+
.setHost(server.getUrl())
651+
.setExperimentalIsUnifiedHost(true);
652+
config.resolve(emptyEnv());
653+
assertEquals(DUMMY_ACCOUNT_ID, config.getAccountId());
654+
assertNull(config.getDiscoveryUrl());
655+
}
656+
}
657+
658+
@Test
659+
public void testEnsureResolvedHostMetadataMissingAccountIdWithPlaceholderNonFatal()
660+
throws IOException {
661+
String response =
662+
"{\"oidc_endpoint\":\"https://acc.databricks.com/oidc/accounts/{account_id}\"}";
663+
try (FixtureServer server =
664+
new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) {
665+
DatabricksConfig config =
666+
new DatabricksConfig()
667+
.setHost(server.getUrl())
668+
.setExperimentalIsUnifiedHost(true);
669+
config.resolve(emptyEnv());
670+
// DiscoveryURL should not be set because account_id is empty and placeholder can't be
671+
// substituted
672+
assertNull(config.getDiscoveryUrl());
673+
}
674+
}
675+
602676
// --- discoveryUrl / OIDC endpoint tests ---
603677

604678
@Test

0 commit comments

Comments
 (0)