Use net/url to build resource URLs such that proper escaping is done

This commit is contained in:
Pieter Noordhuis 2024-10-17 17:30:48 +02:00
parent 7bf2ec378c
commit 7658dbdff2
No known key found for this signature in database
GPG Key ID: 12ACCCC104CF2930
12 changed files with 63 additions and 27 deletions

View File

@ -2,6 +2,7 @@ package mutator
import (
"context"
"net/url"
"strconv"
"strings"
@ -30,12 +31,17 @@ func (m *initializeURLs) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagn
return diag.FromErr(err)
}
orgId := strconv.FormatInt(workspaceId, 10)
urlPrefix := b.WorkspaceClient().Config.CanonicalHostName() + "/"
initializeForWorkspace(b, orgId, urlPrefix)
host := b.WorkspaceClient().Config.CanonicalHostName()
initializeForWorkspace(b, orgId, host)
return nil
}
func initializeForWorkspace(b *bundle.Bundle, orgId string, urlPrefix string) {
func initializeForWorkspace(b *bundle.Bundle, orgId string, host string) error {
baseURL, err := url.Parse(host)
if err != nil {
return err
}
// Add ?o=<workspace id> only if <workspace id> wasn't in the subdomain already.
// The ?o= is needed when vanity URLs / legacy workspace URLs are used.
// If it's not needed we prefer to leave it out since these URLs are rather
@ -43,14 +49,17 @@ func initializeForWorkspace(b *bundle.Bundle, orgId string, urlPrefix string) {
//
// See https://docs.databricks.com/en/workspace/workspace-details.html for
// further reading about the '?o=' suffix.
urlSuffix := ""
if !strings.Contains(urlPrefix, orgId) {
urlSuffix = "?o=" + orgId
if !strings.Contains(baseURL.Hostname(), orgId) {
values := baseURL.Query()
values.Add("o", orgId)
baseURL.RawQuery = values.Encode()
}
for _, group := range b.Config.Resources.AllResources() {
for _, r := range group.Resources {
r.InitializeURL(urlPrefix, urlSuffix)
r.InitializeURL(*baseURL)
}
}
return nil
}

View File

@ -93,7 +93,7 @@ func TestInitializeURLs(t *testing.T) {
"job1": "https://mycompany.databricks.com/jobs/1?o=123456",
"pipeline1": "https://mycompany.databricks.com/pipelines/3?o=123456",
"experiment1": "https://mycompany.databricks.com/ml/experiments/4?o=123456",
"model1": "https://mycompany.databricks.com/ml/models/a model uses its name for identifier?o=123456",
"model1": "https://mycompany.databricks.com/ml/models/a%20model%20uses%20its%20name%20for%20identifier?o=123456",
"servingendpoint1": "https://mycompany.databricks.com/ml/endpoints/my_serving_endpoint?o=123456",
"registeredmodel1": "https://mycompany.databricks.com/explore/data/models/8?o=123456",
"qualityMonitor1": "https://mycompany.databricks.com/explore/data/catalog/schema/qualityMonitor1?o=123456",

View File

@ -3,6 +3,7 @@ package config
import (
"context"
"fmt"
"net/url"
"github.com/databricks/cli/bundle/config/resources"
"github.com/databricks/databricks-sdk-go"
@ -38,7 +39,7 @@ type ConfigResource interface {
GetURL() string
// InitializeURL initializes the URL field of the resource.
InitializeURL(urlPrefix string, urlSuffix string)
InitializeURL(url.URL)
}
// ResourceGroup represents a group of resources of the same type.

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go"
@ -39,11 +41,12 @@ func (s *Cluster) TerraformResourceName() string {
return "databricks_cluster"
}
func (s *Cluster) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *Cluster) InitializeURL(baseURL url.URL) {
if s.ID == "" {
return
}
s.URL = urlPrefix + "compute/clusters/" + s.ID + urlSuffix
baseURL.Path = fmt.Sprintf("compute/clusters/%s", s.ID)
s.URL = baseURL.String()
}
func (s *Cluster) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"strconv"
"github.com/databricks/cli/libs/log"
@ -46,11 +48,12 @@ func (j *Job) TerraformResourceName() string {
return "databricks_job"
}
func (j *Job) InitializeURL(urlPrefix string, urlSuffix string) {
func (j *Job) InitializeURL(baseURL url.URL) {
if j.ID == "" {
return
}
j.URL = urlPrefix + "jobs/" + j.ID + urlSuffix
baseURL.Path = fmt.Sprintf("jobs/%s", j.ID)
j.URL = baseURL.String()
}
func (j *Job) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go"
@ -41,11 +43,12 @@ func (s *MlflowExperiment) TerraformResourceName() string {
return "databricks_mlflow_experiment"
}
func (s *MlflowExperiment) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *MlflowExperiment) InitializeURL(baseURL url.URL) {
if s.ID == "" {
return
}
s.URL = urlPrefix + "ml/experiments/" + s.ID + urlSuffix
baseURL.Path = fmt.Sprintf("ml/experiments/%s", s.ID)
s.URL = baseURL.String()
}
func (s *MlflowExperiment) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go"
@ -41,11 +43,12 @@ func (s *MlflowModel) TerraformResourceName() string {
return "databricks_mlflow_model"
}
func (s *MlflowModel) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *MlflowModel) InitializeURL(baseURL url.URL) {
if s.ID == "" {
return
}
s.URL = urlPrefix + "ml/models/" + s.ID + urlSuffix
baseURL.Path = fmt.Sprintf("ml/models/%s", s.ID)
s.URL = baseURL.String()
}
func (s *MlflowModel) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go"
@ -49,11 +51,12 @@ func (s *ModelServingEndpoint) TerraformResourceName() string {
return "databricks_model_serving"
}
func (s *ModelServingEndpoint) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *ModelServingEndpoint) InitializeURL(baseURL url.URL) {
if s.ID == "" {
return
}
s.URL = urlPrefix + "ml/endpoints/" + s.ID + urlSuffix
baseURL.Path = fmt.Sprintf("ml/endpoints/%s", s.ID)
s.URL = baseURL.String()
}
func (s *ModelServingEndpoint) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go"
@ -41,11 +43,12 @@ func (p *Pipeline) TerraformResourceName() string {
return "databricks_pipeline"
}
func (p *Pipeline) InitializeURL(urlPrefix string, urlSuffix string) {
func (p *Pipeline) InitializeURL(baseURL url.URL) {
if p.ID == "" {
return
}
p.URL = urlPrefix + "pipelines/" + p.ID + urlSuffix
baseURL.Path = fmt.Sprintf("pipelines/%s", p.ID)
p.URL = baseURL.String()
}
func (p *Pipeline) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"strings"
"github.com/databricks/cli/libs/log"
@ -47,11 +49,12 @@ func (s *QualityMonitor) TerraformResourceName() string {
return "databricks_quality_monitor"
}
func (s *QualityMonitor) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *QualityMonitor) InitializeURL(baseURL url.URL) {
if s.TableName == "" {
return
}
s.URL = urlPrefix + "explore/data/" + strings.ReplaceAll(s.TableName, ".", "/") + urlSuffix
baseURL.Path = fmt.Sprintf("explore/data/%s", strings.ReplaceAll(s.TableName, ".", "/"))
s.URL = baseURL.String()
}
func (s *QualityMonitor) GetName() string {

View File

@ -2,6 +2,8 @@ package resources
import (
"context"
"fmt"
"net/url"
"strings"
"github.com/databricks/cli/libs/log"
@ -51,11 +53,12 @@ func (s *RegisteredModel) TerraformResourceName() string {
return "databricks_registered_model"
}
func (s *RegisteredModel) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *RegisteredModel) InitializeURL(baseURL url.URL) {
if s.ID == "" {
return
}
s.URL = urlPrefix + "explore/data/models/" + strings.ReplaceAll(s.ID, ".", "/") + urlSuffix
baseURL.Path = fmt.Sprintf("explore/data/models/%s", strings.ReplaceAll(s.ID, ".", "/"))
s.URL = baseURL.String()
}
func (s *RegisteredModel) GetName() string {

View File

@ -3,6 +3,7 @@ package resources
import (
"context"
"fmt"
"net/url"
"strings"
"github.com/databricks/databricks-sdk-go"
@ -32,11 +33,12 @@ func (s *Schema) TerraformResourceName() string {
return "databricks_schema"
}
func (s *Schema) InitializeURL(urlPrefix string, urlSuffix string) {
func (s *Schema) InitializeURL(baseURL url.URL) {
if s.ID == "" {
return
}
s.URL = urlPrefix + "explore/data/" + strings.ReplaceAll(s.ID, ".", "/") + urlSuffix
baseURL.Path = fmt.Sprintf("explore/data/%s", strings.ReplaceAll(s.ID, ".", "/"))
s.URL = baseURL.String()
}
func (s *Schema) GetURL() string {