Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3afdfa8
Implement direct dataplane access
emmyzhou-db May 19, 2025
34f6f48
Small refactor
emmyzhou-db May 19, 2025
afd1d5b
override generated code temp
emmyzhou-db May 21, 2025
4a8832b
Modify all credentials provider which are OAuth
emmyzhou-db May 22, 2025
419121e
Finally working :)
emmyzhou-db May 22, 2025
594f17e
Update ApiClient
emmyzhou-db May 23, 2025
ba1b401
add temp test
emmyzhou-db May 23, 2025
79e360d
Add host as a field to token sources
emmyzhou-db May 23, 2025
b60ed0e
Updated tests
emmyzhou-db May 23, 2025
b56c4d5
Updated tests
emmyzhou-db May 23, 2025
1508d67
Fix merge
emmyzhou-db May 24, 2025
6213dd8
Fix formatting
emmyzhou-db May 24, 2025
6199ed9
Final version
emmyzhou-db May 24, 2025
98664de
Add unit tests
emmyzhou-db May 26, 2025
0ab3df4
Merge branch 'main' into emmyzhou-db/code-gen
emmyzhou-db May 26, 2025
d59b798
Fix formatting
emmyzhou-db May 26, 2025
21a3b13
Merge branch 'main' into emmyzhou-db/code-gen
emmyzhou-db May 26, 2025
cd7d6d5
Direct dataplane access with code generation
emmyzhou-db May 26, 2025
21ab388
Add unit tests to ErrorTokenSource and DatabricksConfig
emmyzhou-db May 26, 2025
dc75702
Temporarily changed WorkspaceClient to only include the services rele…
emmyzhou-db May 26, 2025
fdf130e
Update change log
emmyzhou-db May 26, 2025
a2ae11b
Fix very annoying formatting issue
emmyzhou-db May 26, 2025
9f98250
Small change to order of methods in ApiClient
emmyzhou-db May 26, 2025
4a0b8fd
Delete databricks-sdk-java/src/test/java/com/databricks/sdk/service/s…
emmyzhou-db May 26, 2025
5655ae5
Small fix
emmyzhou-db May 26, 2025
ef392fd
Update ApiClient
emmyzhou-db May 26, 2025
3777641
Fix typo in changelog
emmyzhou-db May 26, 2025
b2eb8ab
Updated imp template
emmyzhou-db May 26, 2025
8c92152
Remove getReponse() from ApiClient
emmyzhou-db May 26, 2025
b8564f2
Update databricks-sdk-java/src/main/java/com/databricks/sdk/core/http…
emmyzhou-db May 27, 2025
5eadb66
Update OAuthHeaderFactory
emmyzhou-db May 27, 2025
ec211f3
Add latest generated code
emmyzhou-db May 27, 2025
dadddd8
Revert "Add latest generated code"
emmyzhou-db May 27, 2025
4ea2d8f
Revert API changes
emmyzhou-db May 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Release v0.52.0

### New Features and Improvements
* Added Direct-to-Dataplane API support, allowing users to query route optimized model serving endpoints ([#453](https://github.com/databricks/databricks-sdk-java/pull/453)).

### Bug Fixes

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.databricks.sdk.core.error.PrivateLinkInfo;
import com.databricks.sdk.core.http.HttpClient;
import com.databricks.sdk.core.http.Request;
import com.databricks.sdk.core.http.RequestOptions;
import com.databricks.sdk.core.http.Response;
import com.databricks.sdk.core.retry.RequestBasedRetryStrategyPicker;
import com.databricks.sdk.core.retry.RetryStrategy;
Expand Down Expand Up @@ -50,7 +51,6 @@ public Builder withDatabricksConfig(DatabricksConfig config) {
this.accountId = config.getAccountId();
this.retryStrategyPicker = new RequestBasedRetryStrategyPicker(config.getHost());
this.isDebugHeaders = config.isDebugHeaders();

return this;
}

Expand Down Expand Up @@ -173,33 +173,42 @@ public Map<String, String> getStringMap(Request req) {

protected <I, O> O withJavaType(Request request, JavaType javaType) {
try {
Response response = getResponse(request);
Response response = executeInner(request, request.getUrl(), new RequestOptions());
return deserialize(response.getBody(), javaType);
} catch (IOException e) {
throw new DatabricksException("IO error: " + e.getMessage(), e);
}
}

/**
* Executes HTTP request with retries and converts it to proper POJO
* Executes HTTP request with retries and converts it to proper POJO.
*
* @param in Commons HTTP request
* @param target Expected pojo type
* @return POJO of requested type
*/
public <T> T execute(Request in, Class<T> target) throws IOException {
Response out = getResponse(in);
return execute(in, target, new RequestOptions());
}

/**
* Executes HTTP request with retries and converts it to proper POJO, using custom request
* options.
*
* @param in Commons HTTP request
* @param target Expected pojo type
* @param options Optional request options to customize request behavior
* @return POJO of requested type
*/
public <T> T execute(Request in, Class<T> target, RequestOptions options) throws IOException {
Response out = executeInner(in, in.getUrl(), options);
if (target == Void.class) {
return null;
}
return deserialize(out, target);
}

private Response getResponse(Request in) {
return executeInner(in, in.getUrl());
}

private Response executeInner(Request in, String path) {
private Response executeInner(Request in, String path, RequestOptions options) {
RetryStrategy retryStrategy = retryStrategyPicker.getRetryStrategy(in);
int attemptNumber = 0;
while (true) {
Expand All @@ -224,6 +233,8 @@ private Response executeInner(Request in, String path) {
}
in.withHeader("User-Agent", userAgent);

options.applyOptions(in);

// Make the request, catching any exceptions, as we may want to retry.
try {
out = httpClient.execute(in);
Expand Down Expand Up @@ -434,4 +445,8 @@ public String serialize(Object body) throws JsonProcessingException {
}
return mapper.writeValueAsString(body);
}

public HttpClient getHttpClient() {
return httpClient;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.databricks.sdk.core;

import com.databricks.sdk.core.oauth.OAuthHeaderFactory;
import com.databricks.sdk.core.oauth.Token;
import com.databricks.sdk.core.utils.AzureUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -68,7 +69,7 @@ private Optional<String> getSubscription(DatabricksConfig config) {
}

@Override
public HeaderFactory configure(DatabricksConfig config) {
public OAuthHeaderFactory configure(DatabricksConfig config) {
if (!config.isAzure()) {
return null;
}
Expand All @@ -86,15 +87,17 @@ public HeaderFactory configure(DatabricksConfig config) {
mgmtTokenSource = null;
}
CliTokenSource finalMgmtTokenSource = mgmtTokenSource;
return () -> {
Token token = tokenSource.getToken();
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", token.getTokenType() + " " + token.getAccessToken());
if (finalMgmtTokenSource != null) {
AzureUtils.addSpManagementToken(finalMgmtTokenSource, headers);
}
return AzureUtils.addWorkspaceResourceId(config, headers);
};
return OAuthHeaderFactory.fromSuppliers(
tokenSource::getToken,
() -> {
Token token = tokenSource.getToken();
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", token.getTokenType() + " " + token.getAccessToken());
if (finalMgmtTokenSource != null) {
AzureUtils.addSpManagementToken(finalMgmtTokenSource, headers);
}
return AzureUtils.addWorkspaceResourceId(config, headers);
});
} catch (DatabricksException e) {
String stderr = e.getMessage();
if (stderr.contains("not found")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.databricks.sdk.core;

import com.databricks.sdk.core.oauth.Token;
import com.databricks.sdk.core.oauth.OAuthHeaderFactory;
import com.databricks.sdk.core.utils.OSUtils;
import java.util.*;
import org.slf4j.Logger;
Expand Down Expand Up @@ -36,7 +36,7 @@ private CliTokenSource getDatabricksCliTokenSource(DatabricksConfig config) {
}

@Override
public HeaderFactory configure(DatabricksConfig config) {
public OAuthHeaderFactory configure(DatabricksConfig config) {
String host = config.getHost();
if (host == null) {
return null;
Expand All @@ -48,12 +48,7 @@ public HeaderFactory configure(DatabricksConfig config) {
return null;
}
tokenSource.getToken(); // We need this for checking if databricks CLI is installed.
return () -> {
Token token = tokenSource.getToken();
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", token.getTokenType() + " " + token.getAccessToken());
return headers;
};
return OAuthHeaderFactory.fromTokenSource(tokenSource);
} catch (DatabricksException e) {
String stderr = e.getMessage();
if (stderr.contains("not found")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import com.databricks.sdk.core.http.HttpClient;
import com.databricks.sdk.core.http.Request;
import com.databricks.sdk.core.http.Response;
import com.databricks.sdk.core.oauth.ErrorTokenSource;
import com.databricks.sdk.core.oauth.OAuthHeaderFactory;
import com.databricks.sdk.core.oauth.OpenIDConnectEndpoints;
import com.databricks.sdk.core.oauth.TokenSource;
import com.databricks.sdk.core.utils.Cloud;
import com.databricks.sdk.core.utils.Environment;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -209,6 +212,24 @@ public synchronized Map<String, String> authenticate() throws DatabricksExceptio
}
}

public TokenSource getTokenSource() {
if (headerFactory == null) {
try {
ConfigLoader.fixHostIfNeeded(this);
headerFactory = credentialsProvider.configure(this);
} catch (Exception e) {
return new ErrorTokenSource("Failed to get token source: " + e.getMessage());
}
setAuthType(credentialsProvider.authType());
}

if (headerFactory instanceof OAuthHeaderFactory) {
return (TokenSource) headerFactory;
}
return new ErrorTokenSource(
String.format("OAuth Token not supported for current auth type %s", authType));
}

public CredentialsProvider getCredentialsProvider() {
return this.credentialsProvider;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@ public NamedIDTokenSource(String name, IDTokenSource idTokenSource) {
this.name = name;
this.idTokenSource = idTokenSource;
}

public String getName() {
return name;
}

public IDTokenSource getIdTokenSource() {
return idTokenSource;
}
}

public DefaultCredentialsProvider() {}
Expand Down Expand Up @@ -143,14 +135,13 @@ private void addOIDCCredentialsProviders(DatabricksConfig config) {
config.getClientId(),
config.getHost(),
endpoints,
namedIdTokenSource.getIdTokenSource(),
namedIdTokenSource.idTokenSource,
config.getHttpClient())
.audience(config.getTokenAudience())
.accountId(config.isAccountClient() ? config.getAccountId() : null)
.build();

providers.add(
new TokenSourceCredentialsProvider(oauthTokenSource, namedIdTokenSource.getName()));
providers.add(new TokenSourceCredentialsProvider(oauthTokenSource, namedIdTokenSource.name));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.databricks.sdk.core.http;

import java.util.function.Function;

/**
* A builder class for configuring HTTP request transformations including authentication, URL, and
* user agent headers.
*
* <p>Experimental: this class is experimental and subject to change in backward incompatible ways.
*/
public class RequestOptions {
private Function<Request, Request> authenticateFunc;
private Function<Request, Request> urlFunc;
private Function<Request, Request> userAgentFunc;

/**
* Constructs a new RequestOptions instance with default identity functions. Initially, all
* transformations are set to pass through the request unchanged.
*/
public RequestOptions() {
// Default to identity functions
this.authenticateFunc = request -> request;
this.urlFunc = request -> request;
this.userAgentFunc = request -> request;
}

/**
* Sets the authorization header for the request.
*
* @param authorization The authorization value to be set in the header
* @return This RequestOptions instance for method chaining
*/
public RequestOptions withAuthorization(String authorization) {
this.authenticateFunc = request -> request.withHeader("Authorization", authorization);
return this;
}

/**
* Sets the URL for the request.
*
* @param url The URL to be set for the request
* @return This RequestOptions instance for method chaining
*/
public RequestOptions withUrl(String url) {
this.urlFunc = request -> request.withUrl(url);
return this;
}

/**
* Sets the User-Agent header for the request.
*
* @param userAgent The user agent string to be set in the header
* @return This RequestOptions instance for method chaining
*/
public RequestOptions withUserAgent(String userAgent) {
this.userAgentFunc = request -> request.withHeader("User-Agent", userAgent);
return this;
}

/**
* Applies all configured transformations to the given request. The transformations are applied in
* the following order: 1. Authentication 2. URL 3. User-Agent
*
* @param request The original request to be transformed
* @return A new Request instance with all transformations applied
*/
public Request applyOptions(Request request) {
// Apply all transformation functions in sequence
return userAgentFunc.apply(urlFunc.apply(authenticateFunc.apply(request)));
}
}
Loading
Loading