Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DataPlane API Support #936

Merged
merged 44 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
0ed887f
WIP
hectorcast-db May 27, 2024
773ea11
Generate
hectorcast-db May 27, 2024
2407299
Test
hectorcast-db May 27, 2024
dc6b882
Test2
hectorcast-db May 28, 2024
9d12135
singular
hectorcast-db May 28, 2024
75345a3
Client getter
hectorcast-db May 28, 2024
be639ae
DP method
hectorcast-db May 28, 2024
ecd2bc0
Request
hectorcast-db May 28, 2024
c361d9d
CP client
hectorcast-db May 28, 2024
ff60fc1
delete stuff
hectorcast-db May 28, 2024
a12d718
cleanup
hectorcast-db May 28, 2024
338b481
Method WIP
hectorcast-db May 28, 2024
d71d58f
more gen
hectorcast-db May 28, 2024
ef348a1
finish method
hectorcast-db May 28, 2024
5e30cb1
Clean interface
hectorcast-db May 28, 2024
bb425d5
Tests
hectorcast-db May 29, 2024
ae97970
Error hadnling
hectorcast-db May 29, 2024
579f6b5
Fixes
hectorcast-db May 29, 2024
e8b0d3c
fixes 2
hectorcast-db May 29, 2024
bb5d618
Cleanup
hectorcast-db May 29, 2024
c161714
c2
hectorcast-db May 29, 2024
6eb4951
Rename
hectorcast-db May 29, 2024
2a4517d
Move
hectorcast-db May 29, 2024
e86f899
Extract description generation and tag
hectorcast-db May 29, 2024
b7c8d4d
Remove safeguards
hectorcast-db May 31, 2024
4d11f28
Merge branch 'generate-dataplane-code' into dataplane-support
hectorcast-db May 31, 2024
3827a83
fixes
hectorcast-db May 31, 2024
b163d9c
Generate
hectorcast-db May 31, 2024
3007351
Remove old file
hectorcast-db Jun 3, 2024
b728c49
Update spec
hectorcast-db Jun 7, 2024
bbc2d72
Generate from master
hectorcast-db Jun 7, 2024
f1b393c
Merge branch 'main' into dataplane-support
hectorcast-db Jun 10, 2024
d3547b7
Generate
hectorcast-db Jun 10, 2024
c59391b
Delete endpoints
hectorcast-db Jun 10, 2024
c5cfd49
Cleanup
hectorcast-db Jun 10, 2024
5a4837b
More cleanup
hectorcast-db Jun 10, 2024
3554e86
Fixes
hectorcast-db Jun 19, 2024
ef5c86a
Merge branch 'main' into dataplane-support
hectorcast-db Jul 5, 2024
c0bc3d5
Regenerate
hectorcast-db Jul 5, 2024
d33b531
Fixes
hectorcast-db Jul 5, 2024
438bbe2
Formatting
hectorcast-db Jul 5, 2024
7a90930
Regenerate
hectorcast-db Jul 5, 2024
008945c
Make field private
hectorcast-db Jul 5, 2024
6607dfd
Remove file
hectorcast-db Jul 5, 2024
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
2 changes: 1 addition & 1 deletion .codegen/_openapi_sha
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fc26589775a1c48b14211cd11b6903d1b4ed071c
f9166063cb5a6677c83877de2a2bb95c82958dd5
17 changes: 14 additions & 3 deletions .codegen/accounts.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
type AccountClient struct {
Config *config.Config

{{range .Services}}{{if and .IsAccounts (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and .IsAccounts (not .HasParent)}}
{{.Comment " // " 80}}
{{(.TrimPrefix "account").PascalName}} {{.Package.Name}}.{{.Name}}Interface
{{end}}{{end}}
Expand Down Expand Up @@ -42,9 +42,20 @@ func NewAccountClient(c ...*Config) (*AccountClient, error) {
if err != nil {
return nil, err
}
{{range .Services}}{{if and .IsAccounts (not .HasParent) (.HasDataPlaneMethods) (not .IsDataPlane)}}
{{.CamelName}} := {{.Package.Name}}.New{{.Name}}(apiClient)
{{- end}}{{end}}
return &AccountClient{
Config: cfg,
{{range .Services}}{{if and .IsAccounts (not .HasParent) (not .IsDataPlane)}}
{{(.TrimPrefix "account").PascalName}}: {{.Package.Name}}.New{{.Name}}(apiClient),{{end}}{{end}}
{{range .Services}}{{if and .IsAccounts (not .HasParent) (not .IsDataPlane) (not .HasDataPlaneMethods)}}
{{(.TrimPrefix "account").PascalName}}: {{.Package.Name}}.New{{.Name}}(apiClient),
{{- end -}}
{{if and .IsAccounts (not .HasParent) (not .IsDataPlane) (.HasDataPlaneMethods)}}
{{(.TrimPrefix "account").PascalName}}: {{.CamelName}},
{{- end -}}
{{if and .IsAccounts (not .HasParent) .IsDataPlane}}
{{(.TrimPrefix "account").PascalName}}: {{.Package.Name}}.New{{.Name}}(apiClient, {{.ControlPlaneService.CamelName}}),
{{- end -}}
{{end}}
}, nil
}
17 changes: 12 additions & 5 deletions .codegen/api.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.

// {{if .Description}}{{.Description}}{{else}}These APIs allow you to manage {{range .Services}}{{if (not .IsDataPlane)}}{{.TitleName}}, {{end}}{{end}}etc.{{end}}
// {{if .Description}}{{.Description}}{{else}}These APIs allow you to manage {{range .Services}}{{.TitleName}}, {{end}}etc.{{end}}
package {{.Name}}

import (
Expand All @@ -22,7 +22,6 @@ import (
"Workspace"
}}
{{range .Services}}
{{if not .IsDataPlane}}

type {{.PascalName}}Interface interface {
{{if (in $extendedInterface .PascalName) }}
Expand Down Expand Up @@ -106,10 +105,17 @@ type {{.PascalName}}Interface interface {
{{end -}}
}

func New{{.PascalName}}(client *client.DatabricksClient) *{{.PascalName}}API {
func New{{.PascalName}}(client *client.DatabricksClient,
{{- if .IsDataPlane}}
controlPlane *{{.ControlPlaneService.PascalName}}API,
{{end -}}
) *{{.PascalName}}API {
return &{{.PascalName}}API{
impl: &{{.CamelName}}Impl{
client: client,
{{- if .IsDataPlane}}
controlPlane: controlPlane,
{{end}}
},
{{range .Subservices}}
{{.CamelName}}: New{{.PascalName}}(client),
Expand Down Expand Up @@ -149,6 +155,8 @@ func (a *{{.PascalName}}API) Impl() {{.PascalName}}Service {
return a.impl
}



{{range .Waits}}
// {{.PascalName}} repeatedly calls [{{.Method.Service.Name}}API.{{.Poll.PascalName}}] and waits to reach {{range $i, $e := .Success}}{{if $i}} or {{end}}{{.Content}}{{end}} state
func (a *{{.Method.Service.PascalName}}API) {{.PascalName}}(ctx context.Context{{range .Binding}}, {{.PollField.CamelName}} {{template "type" .PollField.Entity}}{{end}},
Expand Down Expand Up @@ -412,7 +420,6 @@ func (a *{{.Service.Name}}API) {{.Shortcut.PascalName}}AndWait(ctx context.Conte
}
{{end}}
{{end -}}
{{end}}
{{- end}}
{{- define "field-path" -}}
{{- range .}}.{{.PascalName}}{{end}}
Expand All @@ -428,4 +435,4 @@ func (a *{{.Service.Name}}API) {{.Shortcut.PascalName}}AndWait(ctx context.Conte

{{- define "wait-response-type" -}}
(*{{.Wait.PascalName}}[{{with .Response}}{{if .IsEmpty}}struct{}{{else}}{{.PascalName}}{{end}}{{end}}], error)
{{- end -}}
{{- end -}}
55 changes: 53 additions & 2 deletions .codegen/impl.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ package {{.Name}}

import (
"context"
"errors"
"fmt"
goauth "golang.org/x/oauth2"
"time"
"io"
"net/http"
Expand All @@ -13,22 +15,71 @@ import (
{{range .ImportedPackages}}
"github.com/databricks/databricks-sdk-go/service/{{.}}"{{end}}
)
{{range .Services}} {{if not .IsDataPlane}}
{{range .Services}}
// unexported type that holds implementations of just {{.Name}} API methods
type {{.CamelName}}Impl struct {
{{- if .IsDataPlane}}
oauth2.DataPlaneHelper
controlPlane *{{.ControlPlaneService.PascalName}}API
{{end -}}
client *client.DatabricksClient
}

{{range .Methods}}
{{if .Service.IsDataPlane}}
func (a *{{.Service.CamelName}}Impl) {{.PascalName}}(ctx context.Context{{if .Request}}, request {{.Request.PascalName}}{{end}}) {{ template "response-type" . }} {
getRequest := {{.Service.DataPlaneInfoMethod.Request.PascalName}}{
{{- range .Service.DataPlaneInfoMethod.Request.Fields}}
{{.PascalName}}: request.{{.PascalName}},
{{end}}
}
token, err := a.client.Config.GetToken()
if err != nil {
return nil, err
}
infoGetter := func() (*oauth2.DataPlaneInfo, error) {
response, err := a.controlPlane.{{.Service.DataPlaneInfoMethod.PascalName}}(ctx, getRequest)
if err != nil {
return nil, err
}
if response.{{(index .DataPlaneInfoFields 0).PascalName}} == nil {
return nil, errors.New("resource does not support direct Data Plane access")
Copy link
Contributor

Choose a reason for hiding this comment

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

When would this case happen? Is this a bug in the API definition? Or is it possible that some model serving endpoints support direct-to-dataplane access and others don't?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

DataPlane access needs to be enabled on a resource level. If you call this method for a Model which is not "optimized" (their flag for DataPlane), this field won't be set (the endpointURL does not exists)

}
return response{{range .DataPlaneInfoFields}}.{{.PascalName}}{{end}}, nil
}
refresh := func(info *oauth2.DataPlaneInfo) (*goauth.Token, error) {
return a.client.GetOAuthToken(ctx, info.AuthorizationDetails, token)
}
getParams := []string{
{{- range .Service.DataPlaneInfoMethod.Request.Fields}}
request.{{.PascalName}},
{{end -}}
}
endpointUrl, dataPlaneToken, err := a.GetDataPlaneDetails("{{.PascalName}}", getParams, refresh, infoGetter)
if err != nil {
return nil, err
}
{{ template "make-header" . }}
opts := []httpclient.DoOption{}
opts = append(opts, httpclient.WithRequestHeaders(headers))
{{- template "response-var" . }}
{{if .Response}}opts = append(opts, httpclient.WithRequestData(request)){{end}}
hectorcast-db marked this conversation as resolved.
Show resolved Hide resolved
{{if .Response}}opts = append(opts, httpclient.WithResponseUnmarshal(&{{.Response.CamelName}})){{end}}
opts = append(opts, httpclient.WithToken(dataPlaneToken))
err = a.client.ApiClient().Do(ctx, http.Method{{.TitleVerb}}, endpointUrl, opts...)
return {{ template "response" . }}
}

{{else}}
func (a *{{.Service.CamelName}}Impl) {{.PascalName}}(ctx context.Context{{if .Request}}, request {{.Request.PascalName}}{{end}}) {{ template "response-type" . }} {
{{- template "response-var" . }}
path := {{ template "path" . }}
{{ template "make-header" . }}
err := a.client.Do(ctx, http.Method{{.TitleVerb}}, path, headers, {{ template "request-param" . }}, {{if .Response}}&{{.Response.CamelName}}{{else}}nil{{end}})
return {{ template "response" . }}
}
{{end -}}
{{end}}
{{end -}}
{{end}}

{{- define "path" -}}
Expand Down
5 changes: 3 additions & 2 deletions .codegen/interface.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/databricks/databricks-sdk-go/retries"
)

{{range .Services}} {{if not .IsDataPlane}}
{{range .Services}}
{{.Comment "// " 80}}
type {{.PascalName}}Service interface {
{{range .Methods}}
Expand All @@ -21,5 +21,6 @@ type {{.PascalName}}Service interface {
{{end}}
}



{{end}}
{{end}}
8 changes: 4 additions & 4 deletions .codegen/mock_account_client.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func NewMockAccountClient(t interface {
cli := &MockAccountClient {
AccountClient: &databricks.AccountClient{
Config: nil,
{{range .Services}}{{if and .IsAccounts (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and .IsAccounts (not .HasParent) }}
{{(.TrimPrefix "account").PascalName}}: {{ template "mock-interface-constructor" . }}(t),
{{- end}}{{end}}
},
}
{{range .ServicesSortedByParent}} {{if and .IsAccounts (not .IsDataPlane)}}
{{range .ServicesSortedByParent}} {{if and .IsAccounts }}
{{if .HasSubservices}}
mock{{.PascalName}}API := cli.GetMock{{.PascalName}}API()
{{end}}
Expand All @@ -40,7 +40,7 @@ func NewMockAccountClient(t interface {
return cli
}

{{range .Services}}{{if and (.IsAccounts) (.HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and (.IsAccounts) (.HasParent) }}
hectorcast-db marked this conversation as resolved.
Show resolved Hide resolved
func(m *MockAccountClient) GetMock{{.PascalName}}API() *{{ template "mock-interface-name" . }} {
api, ok := m.GetMock{{.ParentService.PascalName}}API().{{.PascalName}}().(*{{ template "mock-interface-name" . }})
if !ok {
Expand All @@ -50,7 +50,7 @@ func(m *MockAccountClient) GetMock{{.PascalName}}API() *{{ template "mock-interf
}
{{end}}{{end}}

{{range .Services}}{{if and .IsAccounts (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and .IsAccounts (not .HasParent) }}
func(m *MockAccountClient) GetMock{{.Name}}API() *{{ template "mock-interface-name" . }} {
api, ok := m.AccountClient.{{(.TrimPrefix "account").PascalName}}.(*{{ template "mock-interface-name" . }})
if !ok {
Expand Down
8 changes: 4 additions & 4 deletions .codegen/mock_workspace_client.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func NewMockWorkspaceClient(t interface {
cli := &MockWorkspaceClient{
WorkspaceClient: &databricks.WorkspaceClient{
Config: nil,
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) }}
{{.Name}}: {{ template "mock-interface-constructor" . }}(t),
{{- end}}{{end}}
},
}
{{range .ServicesSortedByParent}} {{if and (not .IsAccounts) (not .IsDataPlane)}}
{{range .ServicesSortedByParent}} {{if and (not .IsAccounts) }}
{{if .HasSubservices}}
mock{{.CamelName}}API := cli.GetMock{{.PascalName}}API()
{{end}}
Expand All @@ -40,7 +40,7 @@ func NewMockWorkspaceClient(t interface {
return cli
}

{{range .Services}}{{if and (not .IsAccounts) (.HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and (not .IsAccounts) (.HasParent) }}
func(m *MockWorkspaceClient) GetMock{{.PascalName}}API() *{{ template "mock-interface-name" . }} {
api, ok := m.GetMock{{.ParentService.Name}}API().{{.PascalName}}().(*{{ template "mock-interface-name" . }})
if !ok {
Expand All @@ -51,7 +51,7 @@ func(m *MockWorkspaceClient) GetMock{{.PascalName}}API() *{{ template "mock-inte

{{end}}{{end}}

{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) }}
func(m *MockWorkspaceClient) GetMock{{.Name}}API() *{{ template "mock-interface-name" . }} {
api, ok := m.WorkspaceClient.{{.Name}}.(*{{ template "mock-interface-name" . }})
if !ok {
Expand Down
4 changes: 2 additions & 2 deletions .codegen/service-pkg.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Databricks SDK for Go APIs
//
//{{range .Services}}{{if and .Description (not .IsDataPlane)}} - [{{.Package.Name}}.{{.PascalName}}API]: {{.Summary}}
//{{range .Services}}{{if and .Description }} - [{{.Package.Name}}.{{.PascalName}}API]: {{.Summary}}
//
//{{end}}{{end}}
package service
Expand All @@ -15,6 +15,6 @@ import (
// https://pkg.go.dev/github.com/databricks/databricks-sdk-go/service
// See: https://pkg.go.dev/golang.org/x/tools/internal/imports#ImportPathToAssumedName
var (
{{range .Services}}{{if (not .IsDataPlane)}} _ *{{.Package.Name}}.{{.PascalName}}API = nil{{end}}
{{range .Services}} _ *{{.Package.Name}}.{{.PascalName}}API = nil
{{end}}
)
29 changes: 13 additions & 16 deletions .codegen/workspaces.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,12 @@ type WorkspaceClient struct {
Config *config.Config
apiClient *httpclient.ApiClient

{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) }}
{{.Comment " // " 80}}
{{.Name}} {{.Package.Name}}.{{.Name}}Interface
{{end}}{{end}}
}

// Returns a new OAuth scoped to the authorization details provided.
// It will return an error if the CredentialStrategy does not support OAuth tokens.
//
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't need this on the WorkspaceClient, but the Client itself.

// **NOTE:** Experimental: This API may change or be removed in a future release
// without warning.
func (a *WorkspaceClient) GetOAuthToken(ctx context.Context, authorizationDetails string) (*credentials.OAuthToken, error) {
originalToken, err := a.Config.GetToken()
if err != nil {
return nil, err
}
return a.apiClient.GetOAuthToken(ctx, authorizationDetails, originalToken)
}

var ErrNotWorkspaceClient = errors.New("invalid Databricks Workspace configuration")

// NewWorkspaceClient creates new Databricks SDK client for Workspaces or
Expand Down Expand Up @@ -61,11 +48,21 @@ func NewWorkspaceClient(c ...*Config) (*WorkspaceClient, error) {
if err != nil {
return nil, err
}
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) (.HasDataPlaneMethods) (not .IsDataPlane)}}
{{.CamelName}} := {{.Package.Name}}.New{{.Name}}(databricksClient)
{{- end}}{{end}}
return &WorkspaceClient{
Config: cfg,
apiClient: apiClient,
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) (not .IsDataPlane)}}
{{range .Services}}{{if and (not .IsAccounts) (not .HasParent) (not .IsDataPlane) (not .HasDataPlaneMethods)}}
{{.Name}}: {{.Package.Name}}.New{{.Name}}(databricksClient),
{{- end}}{{end}}
{{- end -}}
{{if and (not .IsAccounts) (not .HasParent) (not .IsDataPlane) (.HasDataPlaneMethods)}}
{{.Name}}: {{.CamelName}},
{{- end -}}
{{if and (not .IsAccounts) (not .HasParent) .IsDataPlane}}
{{.Name}}: {{.Package.Name}}.New{{.Name}}(databricksClient, {{.ControlPlaneService.CamelName}}),
{{- end -}}
{{end}}
}, nil
}
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ experimental/mocks/service/catalog/mock_account_storage_credentials_interface.go
experimental/mocks/service/catalog/mock_artifact_allowlists_interface.go linguist-generated=true
experimental/mocks/service/catalog/mock_catalogs_interface.go linguist-generated=true
experimental/mocks/service/catalog/mock_connections_interface.go linguist-generated=true
experimental/mocks/service/catalog/mock_endpoints_interface.go linguist-generated=true
experimental/mocks/service/catalog/mock_external_locations_interface.go linguist-generated=true
experimental/mocks/service/catalog/mock_functions_interface.go linguist-generated=true
experimental/mocks/service/catalog/mock_grants_interface.go linguist-generated=true
Expand Down Expand Up @@ -79,6 +80,7 @@ experimental/mocks/service/provisioning/mock_storage_interface.go linguist-gener
experimental/mocks/service/provisioning/mock_vpc_endpoints_interface.go linguist-generated=true
experimental/mocks/service/provisioning/mock_workspaces_interface.go linguist-generated=true
experimental/mocks/service/serving/mock_apps_interface.go linguist-generated=true
experimental/mocks/service/serving/mock_serving_endpoints_data_plane_interface.go linguist-generated=true
experimental/mocks/service/serving/mock_serving_endpoints_interface.go linguist-generated=true
experimental/mocks/service/settings/mock_account_ip_access_lists_interface.go linguist-generated=true
experimental/mocks/service/settings/mock_account_settings_interface.go linguist-generated=true
Expand Down
1 change: 1 addition & 0 deletions account_client.go

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

15 changes: 15 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/databricks/databricks-sdk-go/config"
"github.com/databricks/databricks-sdk-go/httpclient"
"golang.org/x/oauth2"
)

func New(cfg *config.Config) (*DatabricksClient, error) {
Expand Down Expand Up @@ -46,6 +47,20 @@ func (c *DatabricksClient) ConfiguredAccountID() string {
return c.Config.AccountID
}

// Returns the inner Api Client.
func (c *DatabricksClient) ApiClient() *httpclient.ApiClient {
return c.client
}

// Returns a new OAuth token using the provided token. The token must be a JWT token.
// The resulting token is scoped to the authorization details provided.
//
// **NOTE:** Experimental: This API may change or be removed in a future release
// without warning.
func (c *DatabricksClient) GetOAuthToken(ctx context.Context, authDetails string, token *oauth2.Token) (*oauth2.Token, error) {
return c.client.GetOAuthToken(ctx, authDetails, token)
}

// Do sends an HTTP request against path.
func (c *DatabricksClient) Do(ctx context.Context, method, path string,
headers map[string]string, request, response any,
Expand Down
Loading