From 6933f0e5cd6e181609384542640b2b52bf6869ac Mon Sep 17 00:00:00 2001 From: Stephen Lewis Date: Tue, 28 Apr 2026 11:32:09 -0700 Subject: [PATCH 1/4] Use BaseUrl in resources instead of BasePaths Also implemented handling of REP urls with the BaseUrl function --- .../examples/base_configs/test_file.go.tmpl | 23 ++- mmv1/templates/terraform/operation.go.tmpl | 19 ++- mmv1/templates/terraform/product.go.tmpl | 1 + mmv1/templates/terraform/resource.go.tmpl | 144 +++++++----------- .../samples/base_configs/test_file.go.tmpl | 23 ++- .../terraform/provider/provider.go.tmpl | 3 - .../terraform/registry/registry.go | 2 + .../terraform/transport/base_url.go | 22 ++- .../terraform/transport/base_url_test.go | 112 +++++++++++++- .../terraform/transport/config.go.tmpl | 44 ------ .../terraform/transport/config_test.go | 134 ---------------- 11 files changed, 217 insertions(+), 310 deletions(-) diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl b/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl index 3cecfa52334f..ed882dad7047 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl @@ -24,12 +24,14 @@ import ( "strings" "testing" "time" + urlPkg "net/url" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "{{ $.ImportPath }}/acctest" "{{ $.ImportPath }}/envvar" + "{{ $.ImportPath }}/services/{{ lower $.Res.ProductMetadata.Name }}" "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" @@ -48,6 +50,8 @@ var ( _ = tpgresource.SetLabels _ = transport_tpg.Config{} _ = googleapi.Error{} + _ = urlPkg.JoinPath + _ = {{ lower $.Res.ProductMetadata.Name }}.Product ) {{ range $e := $.Res.TestExamples }} @@ -152,26 +156,19 @@ func testAccCheck{{ $.Res.ResourceName }}DestroyProducer(t *testing.T) func(s *t {{- else }} config := acctest.GoogleProviderConfig(t) - {{ if $.Res.ProductMetadata.Version.RepEnabled }} - - urlFormatted, err := tpgresource.ReplaceVarsForTest(config, rs, "{{$.Res.SelfLinkUri}}") - + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl({{ lower $.Res.ProductMetadata.Name }}.Product, config), "{{$.Res.SelfLinkUri}}") if err != nil { return err } - - loc := tpgresource.LocationFromId(urlFormatted) - basePath, err := transport_tpg.ResourceBasePath(config.{{$.Res.ProductMetadata.Name}}BasePath, config.{{$.Res.ProductMetadata.Name}}RepBasePath, "{{$.Res.ProductMetadata.Name}}", config, loc) + url, err = tpgresource.ReplaceVarsForTest(config, rs, url) if err != nil { return err } - url := fmt.Sprintf("%s%s", basePath, urlFormatted) - {{- else }} - url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{"{{"}}{{$.Res.ProductMetadata.Name}}{{"BasePath}}"}}{{$.Res.SelfLinkUri}}") - if err != nil { - return err +{{- if $.Res.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) } - {{- end }} +{{- end }} billingProject := "" diff --git a/mmv1/templates/terraform/operation.go.tmpl b/mmv1/templates/terraform/operation.go.tmpl index 158335ed2b3d..6b8a4213ab34 100644 --- a/mmv1/templates/terraform/operation.go.tmpl +++ b/mmv1/templates/terraform/operation.go.tmpl @@ -25,6 +25,7 @@ import ( "log" "strings" "time" + urlPkg "net/url" "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" @@ -63,16 +64,20 @@ func (w *{{ $.ProductMetadata.Name }}OperationWaiter) QueryOp() (interface{}, er if w == nil { return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") } -{{- if $.ProductMetadata.Version.RepEnabled }} - basePath, err := transport_tpg.ResourceBasePath(w.Config.{{$.ProductMetadata.Name}}BasePath, w.Config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", w.Config, w.Location) + // Returns the proper get. + url, err := urlPkg.JoinPath( + transport_tpg.BaseUrl(Product, w.Config), + fmt.Sprintf("{{ replaceAll $.GetAsync.Operation.BaseUrl "{{op_id}}" "%s" }}", w.CommonOperationWaiter.Op.Name), + ) if err != nil { return nil, err } - url := fmt.Sprintf("%s{{ replaceAll $.GetAsync.Operation.BaseUrl "{{op_id}}" "%s" }}", basePath, w.CommonOperationWaiter.Op.Name) -{{ else }} - // Returns the proper get. - url := fmt.Sprintf("%s{{ replaceAll $.GetAsync.Operation.BaseUrl "{{op_id}}" "%s" }}", w.Config.{{ $.ProductMetadata.Name }}BasePath, w.CommonOperationWaiter.Op.Name) -{{ end }} +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") && w.Location == "" { + return nil, fmt.Errorf("failed to find location for a resource with a regionalized endpoint %s", url) + } + url = strings.ReplaceAll(url, "{{"{{"}}location{{"}}"}}", w.Location) +{{- end }} return transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ Config: w.Config, Method: "GET", diff --git a/mmv1/templates/terraform/product.go.tmpl b/mmv1/templates/terraform/product.go.tmpl index 3b5791f680d1..078c954be0dd 100644 --- a/mmv1/templates/terraform/product.go.tmpl +++ b/mmv1/templates/terraform/product.go.tmpl @@ -28,6 +28,7 @@ var Product = registry.Product{ BaseUrl: "{{ $.Version.BaseUrl }}", {{- if $.Version.RepUrl }} RepUrl: "{{ $.Version.RepUrl }}", + RepByDefault: {{ $.RepByDefault }}, {{- end }} CustomEndpointField: "{{ underscore $.Name }}_custom_endpoint", CustomEndpointEnvVar: "GOOGLE_{{ upper (underscore $.Name) }}_CUSTOM_ENDPOINT", diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index 3057cac242d3..779663618555 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -34,6 +34,7 @@ import ( "strconv" "strings" "time" + urlPkg "net/url" "github.com/hashicorp/errwrap" "github.com/hashicorp/go-cty/cty" @@ -89,6 +90,7 @@ var ( _ = transport_tpg.Config{} _ = verify.ValidateEnum _ = googleapi.Error{} + _ = urlPkg.JoinPath ) func init() { @@ -292,27 +294,19 @@ func resource{{ $.ResourceName -}}Create(d *schema.ResourceData, meta interface{ defer transport_tpg.MutexStore.Unlock(lockName) {{- end}} -{{- if $.ProductMetadata.Version.RepEnabled }} - urlFormatted, err := tpgresource.ReplaceVars(d, config, "{{$.CreateUri}}") + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.CreateUri}}") if err != nil { return err } - loc := tpgresource.LocationFromId(urlFormatted) - - basePath, err := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) - if err != nil { - return fmt.Errorf("Error qualifying Create base path for {{ $.Name -}}: %s", err) - } - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{$.CreateUri}}") - url = fmt.Sprintf("%s%s", basePath, url) -{{ else }} - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.CreateUri}}") -{{- end }} + url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) if err != nil { return err } +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) + } +{{- end }} log.Printf("[DEBUG] Creating new {{ $.Name -}}: %#v", obj) {{- if $.NestedQuery -}} @@ -564,27 +558,19 @@ func resource{{ $.ResourceName -}}PollRead(d *schema.ResourceData, meta interfac return func() (map[string]interface{}, error) { config := meta.(*transport_tpg.Config) -{{ if $.ProductMetadata.Version.RepEnabled }} - urlFormatted, err := tpgresource.ReplaceVars(d, config, "{{$.CreateUri}}") + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}") if err != nil { - return err - } - loc := tpgresource.LocationFromId(urlFormatted) - - basePath := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) - if err != nil { - return fmt.Errorf("Error qualifying base path for {{ $.Name -}}: %s", err) + return nil, err } - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{$.SelfLinkUri}}") - url = fmt.Sprintf("%s%s", basePath, url) -{{ else }} - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}") -{{- end }} - + url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) if err != nil { return nil, err } +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) + } +{{- end }} billingProject := "" @@ -672,26 +658,19 @@ func resource{{ $.ResourceName -}}Read(d *schema.ResourceData, meta interface{}) return err } -{{- if $.ProductMetadata.Version.RepEnabled }} - urlFormatted, err := tpgresource.ReplaceVars(d, config, "{{$.CreateUri}}") + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}{{$.ReadQueryParams}}") if err != nil { return err } - loc := tpgresource.LocationFromId(urlFormatted) - - basePath, err := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) - if err != nil { - return fmt.Errorf("Error qualifying base path for {{ $.Name -}}: %s", err) - } - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{$.SelfLinkUri}}{{$.ReadQueryParams}}") - url = fmt.Sprintf("%s%s", basePath, url) -{{ else }} - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") -{{- end }} + url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) if err != nil { return err } +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) + } +{{- end }} billingProject := "" @@ -962,22 +941,19 @@ func resource{{ $.ResourceName -}}Update(d *schema.ResourceData, meta interface{ defer transport_tpg.MutexStore.Unlock(lockName) {{- end}} -{{- if $.ProductMetadata.Version.RepEnabled }} - loc := tpgresource.LocationFromId(d.Id()) - - basePath, err := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{ $.UpdateUri }}") if err != nil { - return fmt.Errorf("Error qualifying base path for {{ $.Name -}}: %s", err) + return err } - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.UpdateUri }}") - url = fmt.Sprintf("%s%s", basePath, url) -{{ else }} - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{ $.UpdateUri }}") -{{- end }} + url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) if err != nil { return err } +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) + } +{{- end }} log.Printf("[DEBUG] Updating {{ $.Name }} %q: %#v", d.Id(), obj) headers := make(http.Header) @@ -1072,22 +1048,19 @@ if len(updateMask) > 0 { if d.HasChange("{{ join ($.PropertyNamesToStrings (index $CustomUpdateProps $group)) "\") || d.HasChange(\""}}") { obj := make(map[string]interface{}) {{ if $group.FingerprintName }} -{{- if $.ProductMetadata.Version.RepEnabled }} - loc := tpgresource.LocationFromId(d.Id()) - - basePath, err := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) + getUrl, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}") if err != nil { - return fmt.Errorf("Error qualifying base path for {{ $.Name -}}: %s", err) + return err } - getUrl, err := tpgresource.ReplaceVars(d, config, "{{ $.UpdateUri }}") - getUrl = fmt.Sprintf("%s%s", basePath, getUrl) -{{ else }} - - getUrl, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}") -{{- end }} + getUrl, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, getUrl) if err != nil { return err } +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(getUrl, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", getUrl) + } +{{- end }} {{ if $.SupportsIndirectUserProjectOverride -}} if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { billingProject = parts[1] @@ -1166,21 +1139,19 @@ if d.HasChange("{{ join ($.PropertyNamesToStrings (index $CustomUpdateProps $gro transport_tpg.MutexStore.Lock(lockName) defer transport_tpg.MutexStore.Unlock(lockName) {{- end}} -{{- if $.ProductMetadata.Version.RepEnabled }} - loc := tpgresource.LocationFromId(d.Id()) - - basePath, err := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{ $group.UpdateUrl }}") if err != nil { - return fmt.Errorf("Error qualifying base path for {{ $.Name -}}: %s", err) + return err } - url, err := tpgresource.ReplaceVars(d, config, "{{ $group.UpdateUrl }}") - url = fmt.Sprintf("%s%s", basePath, url) -{{ else }} - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{ $group.UpdateUrl }}"){{- end }} + url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) if err != nil { return err } - +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) + } +{{- end }} headers := make(http.Header) {{ if $.CustomCode.PreUpdate -}} @@ -1303,22 +1274,19 @@ func resource{{ $.ResourceName }}Delete(d *schema.ResourceData, meta interface{} transport_tpg.MutexStore.Lock(lockName) defer transport_tpg.MutexStore.Unlock(lockName) {{- end }} -{{- if $.ProductMetadata.Version.RepEnabled }} - loc := tpgresource.LocationFromId(d.Id()) - - basePath, err := transport_tpg.ResourceBasePath(config.{{$.ProductMetadata.Name}}BasePath, config.{{$.ProductMetadata.Name}}RepBasePath, "{{$.ProductMetadata.Name}}", config, loc) + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.DeleteUri}}") if err != nil { - return fmt.Errorf("Error qualifying base path for {{ $.Name -}}: %s", err) + return err } - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{$.DeleteUri}}") - url = fmt.Sprintf("%s%s", basePath, url) -{{ else }} - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.DeleteUri}}") -{{- end }} + url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) if err != nil { return err } +{{- if $.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) + } +{{- end }} {{/*If the deletion of the object requires sending a request body, the custom code will set 'obj' */}} var obj map[string]interface{} {{- if and $.NestedQuery $.NestedQuery.ModifyByPatch }} diff --git a/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl index 5d23239ffc76..0528f121398f 100644 --- a/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl @@ -31,6 +31,7 @@ import ( "strings" "testing" "time" + urlPkg "net/url" "github.com/hashicorp/terraform-plugin-testing/helper/resource" {{- if $needsPlancheck }} @@ -40,6 +41,7 @@ import ( "{{ $.ImportPath }}/acctest" "{{ $.ImportPath }}/envvar" + "{{ $.ImportPath }}/services/{{ lower $.Res.ProductMetadata.Name }}" "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" @@ -58,6 +60,8 @@ var ( _ = tpgresource.SetLabels _ = transport_tpg.Config{} _ = googleapi.Error{} + _ = urlPkg.JoinPath + _ = {{ lower $.Res.ProductMetadata.Name }}.Product ) {{ range $s := $.Res.TestSamples }} @@ -185,26 +189,19 @@ func testAccCheck{{ $.Res.ResourceName }}DestroyProducer(t *testing.T) func(s *t {{- else }} config := acctest.GoogleProviderConfig(t) - - {{ if $.Res.ProductMetadata.Version.RepEnabled }} - urlFormatted, err := tpgresource.ReplaceVarsForTest(config, rs, "{{$.Res.SelfLinkUri}}") - + url, err := urlPkg.JoinPath(transport_tpg.BaseUrl({{ lower $.Res.ProductMetadata.Name }}.Product, config), "{{$.Res.SelfLinkUri}}") if err != nil { return err } - - loc := tpgresource.LocationFromId(urlFormatted) - basePath, err := transport_tpg.ResourceBasePath(config.{{$.Res.ProductMetadata.Name}}BasePath, config.{{$.Res.ProductMetadata.Name}}RepBasePath, "{{$.Res.ProductMetadata.Name}}", config, loc) + url, err = tpgresource.ReplaceVarsForTest(config, rs, url) if err != nil { return err } - url := fmt.Sprintf("%s%s", basePath, urlFormatted) - {{- else }} - url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{"{{"}}{{$.Res.ProductMetadata.Name}}{{"BasePath}}"}}{{$.Res.SelfLinkUri}}") - if err != nil { - return err +{{- if $.Res.ProductMetadata.Version.RepEnabled }} + if strings.Contains(url, "{{"{{"}}location{{"}}"}}") { + return fmt.Errorf("failed to qualify endpoint for a resource with a regionalized endpoint %s", url) } - {{- end }} +{{- end }} billingProject := "" diff --git a/mmv1/third_party/terraform/provider/provider.go.tmpl b/mmv1/third_party/terraform/provider/provider.go.tmpl index 4d8405c5b569..fb9c11976d4c 100644 --- a/mmv1/third_party/terraform/provider/provider.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider.go.tmpl @@ -395,9 +395,6 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr // Registered products {{- range $product := $.Products }} config.{{ $product.Name }}BasePath = transport_tpg.BaseUrl(registry.GetProduct("{{ lower $product.Name }}"), &config) - {{- if $product.Version.RepEnabled }} - config.{{ $product.Name }}RepBasePath = registry.GetProduct("{{ lower $product.Name }}").RepUrl - {{- end -}} {{- end }} stopCtx, ok := schema.StopContext(ctx) diff --git a/mmv1/third_party/terraform/registry/registry.go b/mmv1/third_party/terraform/registry/registry.go index 16c002e4c793..47befd5e3b43 100644 --- a/mmv1/third_party/terraform/registry/registry.go +++ b/mmv1/third_party/terraform/registry/registry.go @@ -19,6 +19,8 @@ type Product struct { BaseUrl string // RepUrl is the base URL for regional API requests. It may contain Magic Modules templating directives. RepUrl string + // RepByDefault is if this product should default to REP endpoints if available. + RepByDefault bool // CustomEndpointField is the name of the product's custom endpoint field in the provider schema. CustomEndpointField string // CustomEndpointEnvVar is the name of the product's custom endpoint environment variable. diff --git a/mmv1/third_party/terraform/transport/base_url.go b/mmv1/third_party/terraform/transport/base_url.go index 8ea3e125ad0e..ab3f8abce678 100644 --- a/mmv1/third_party/terraform/transport/base_url.go +++ b/mmv1/third_party/terraform/transport/base_url.go @@ -8,21 +8,29 @@ import ( // Returns the base URL for a product taking into account the following rules: // 1. If there is a custom endpoint set, return that immediately. -// 2. Otherwise, start with the base URL for the product. -// 2. If mTLS is active, make necessary adjustments. -// 3. If universe_domain is active, make necessary adjustments. +// 2. Otherwise, determine whether to use the REP url or standard url. +// 3. Make adjustments for mTLS / universe domain. // 4. Return final URL. func BaseUrl(product registry.Product, config *Config) string { if v := config.CustomEndpoints[product.CustomEndpointField]; v != "" { return v } - path := product.BaseUrl + u := product.BaseUrl + if config.PreferRegionalEndpoints { + u = product.RepUrl + } else if config.PreferGlobalEndpoints { + u = product.BaseUrl + } else if product.RepByDefault { + u = product.RepUrl + } + if config.IsMtls { - path = GetMtlsEndpoint(product.BaseUrl) + u = GetMtlsEndpoint(product.BaseUrl) } if config.UniverseDomain != "" && config.UniverseDomain != "googleapis.com" { - path = strings.ReplaceAll(path, "googleapis.com", config.UniverseDomain) + u = strings.ReplaceAll(u, "googleapis.com", config.UniverseDomain) } - return path + + return u } diff --git a/mmv1/third_party/terraform/transport/base_url_test.go b/mmv1/third_party/terraform/transport/base_url_test.go index 571d173a3e98..f46fcd3d0f6b 100644 --- a/mmv1/third_party/terraform/transport/base_url_test.go +++ b/mmv1/third_party/terraform/transport/base_url_test.go @@ -14,6 +14,13 @@ func TestBaseUrl(t *testing.T) { CustomEndpointField: "compute_custom_endpoint", CustomEndpointEnvVar: "GOOGLE_COMPUTE_CUSTOM_ENDPOINT", } + artifactregistryProduct := registry.Product{ + Name: "artifactregistry", + BaseUrl: "https://artifactregistry.googleapis.com/v1/", + RepUrl: "https://artifactregistry.{{location}}.rep.googleapis.com/v1/", + CustomEndpointField: "artifact_registry_custom_endpoint", + CustomEndpointEnvVar: "GOOGLE_ARTIFACT_REGISTRY_CUSTOM_ENDPOINT", + } cases := []struct { name string product registry.Product @@ -26,6 +33,68 @@ func TestBaseUrl(t *testing.T) { config: &transport_tpg.Config{}, want: computeProduct.BaseUrl, }, + { + name: "product RepUrl unused", + product: artifactregistryProduct, + config: &transport_tpg.Config{}, + want: artifactregistryProduct.BaseUrl, + }, + { + name: "product RepUrl regional preferred", + product: artifactregistryProduct, + config: &transport_tpg.Config{ + PreferRegionalEndpoints: true, + }, + want: artifactregistryProduct.RepUrl, + }, + { + name: "product without RepUrl regional preferred", + product: computeProduct, + config: &transport_tpg.Config{ + PreferRegionalEndpoints: true, + }, + want: computeProduct.BaseUrl, + }, + { + name: "product RepUrl rep by default", + product: registry.Product{ + Name: artifactregistryProduct.Name, + BaseUrl: artifactregistryProduct.BaseUrl, + RepUrl: artifactregistryProduct.RepUrl, + RepByDefault: true, + CustomEndpointField: artifactregistryProduct.CustomEndpointField, + CustomEndpointEnvVar: artifactregistryProduct.CustomEndpointEnvVar, + }, + config: &transport_tpg.Config{}, + want: artifactregistryProduct.RepUrl, + }, + { + name: "product without RepUrl rep by default", + product: registry.Product{ + Name: artifactregistryProduct.Name, + BaseUrl: artifactregistryProduct.BaseUrl, + RepByDefault: true, + CustomEndpointField: artifactregistryProduct.CustomEndpointField, + CustomEndpointEnvVar: artifactregistryProduct.CustomEndpointEnvVar, + }, + config: &transport_tpg.Config{}, + want: artifactregistryProduct.BaseUrl, + }, + { + name: "product RepUrl global preferred", + product: registry.Product{ + Name: artifactregistryProduct.Name, + BaseUrl: artifactregistryProduct.BaseUrl, + RepUrl: artifactregistryProduct.RepUrl, + RepByDefault: true, + CustomEndpointField: artifactregistryProduct.CustomEndpointField, + CustomEndpointEnvVar: artifactregistryProduct.CustomEndpointEnvVar, + }, + config: &transport_tpg.Config{ + PreferGlobalEndpoints: true, + }, + want: artifactregistryProduct.BaseUrl, + }, { name: "IsMtls", product: computeProduct, @@ -34,6 +103,15 @@ func TestBaseUrl(t *testing.T) { }, want: "https://compute.mtls.googleapis.com/compute/beta/", }, + { + name: "IsMtls+REP", + product: artifactregistryProduct, + config: &transport_tpg.Config{ + IsMtls: true, + PreferRegionalEndpoints: true, + }, + want: "https://artifactregistry.{{location}}.rep.mtls.googleapis.com/v1/", + }, { name: "UniverseDomain", product: computeProduct, @@ -43,7 +121,16 @@ func TestBaseUrl(t *testing.T) { want: "https://compute.fakedomain.test/compute/beta/", }, { - name: "UniverseDomain and IsMtls", + name: "UniverseDomain+REP", + product: artifactregistryProduct, + config: &transport_tpg.Config{ + UniverseDomain: "fakedomain.test", + PreferRegionalEndpoints: true, + }, + want: "https://artifactregistry.{{location}}.rep.fakedomain.test/v1/", + }, + { + name: "UniverseDomain+IsMtls", product: computeProduct, config: &transport_tpg.Config{ UniverseDomain: "fakedomain.test", @@ -51,6 +138,16 @@ func TestBaseUrl(t *testing.T) { }, want: "https://compute.mtls.fakedomain.test/compute/beta/", }, + { + name: "UniverseDomain+IsMtls+REP", + product: artifactregistryProduct, + config: &transport_tpg.Config{ + UniverseDomain: "fakedomain.test", + IsMtls: true, + PreferRegionalEndpoints: true, + }, + want: "https://artifactregistry.{{location}}.rep.mtls.fakedomain.test/v1/", + }, { name: "CustomEndpoint", product: computeProduct, @@ -63,6 +160,19 @@ func TestBaseUrl(t *testing.T) { }, want: "https://sandbox.compute.google.com/beta/", }, + { + name: "CustomEndpoint+REP", + product: artifactregistryProduct, + config: &transport_tpg.Config{ + CustomEndpoints: map[string]string{ + artifactregistryProduct.CustomEndpointField: "https://sandbox.artifactregistry.google.com/beta/", + }, + UniverseDomain: "fakedomain.test", + IsMtls: true, + PreferRegionalEndpoints: true, + }, + want: "https://sandbox.artifactregistry.google.com/beta/", + }, } for _, tc := range cases { diff --git a/mmv1/third_party/terraform/transport/config.go.tmpl b/mmv1/third_party/terraform/transport/config.go.tmpl index 645820f57c3b..90dcb4be4f8c 100644 --- a/mmv1/third_party/terraform/transport/config.go.tmpl +++ b/mmv1/third_party/terraform/transport/config.go.tmpl @@ -239,9 +239,6 @@ type Config struct { CustomEndpoints map[string]string {{ range $product := $.Products }} {{ $product.Name }}BasePath string - {{- if ne $product.Version.RepUrl "" }} - {{ $product.Name }}RepBasePath string - {{- end -}} {{- end }} RequestBatcherServiceUsage *RequestBatcher @@ -262,15 +259,6 @@ var DefaultBasePaths = map[string]string{ {{- end }} } -// Contains the REP status for each generated product. This allows us to track -// default REP enablement across versions and have a central place to look up -// product support -var DefaultRepStatus = map[string]bool{ -{{- range $product := $.Products }} - {{ $product.Name }}BasePathKey : {{ $product.RepByDefault }}, -{{- end }} -} - var DefaultClientScopes = []string{ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/userinfo.email", @@ -1161,35 +1149,3 @@ func GetUniverseDomainFromMeta(meta interface{}) string { } return config.UniverseDomain } - -// Returns the base path for a resource taking into account the following rules: -// Overridden path takes precedence over everything -// Regional endpoint should be returned if preferred -// Global endpoint should be returned if preferred -// If no preferences, return the product default based on DefaultRepStatus map -func ResourceBasePath(basePath, repPath, basePathKey string, config *Config, location string) (string, error) { - var path string - // Set the default to the product-level default - if DefaultRepStatus[basePathKey] { - path = repPath - } else { - path = basePath - } - // If product default has been overridden, use override - if basePath != DefaultBasePaths[basePathKey] { - path = basePath - } else if config.PreferRegionalEndpoints { - // If user has specified a preference, switch to that - path = repPath - } else if config.PreferGlobalEndpoints { - // If user has specified a preference, switch to that - path = basePath - } - if strings.Contains(path, "{{"{{"}}location{{"}}"}}") && location == "" { - log.Printf("[WARN] Found base path with location but no location provided: %s", path) - return path, fmt.Errorf("failed to find location for a resource with a regionalized endpoint %s", path) - } - // Still try to replace location even if it may not exist, this allows - // for products that only support REP on their base_url - return strings.ReplaceAll(path, "{{"{{"}}location{{"}}"}}", location), nil -} diff --git a/mmv1/third_party/terraform/transport/config_test.go b/mmv1/third_party/terraform/transport/config_test.go index 0a2b1a5cf1af..1e9e44fbc71b 100644 --- a/mmv1/third_party/terraform/transport/config_test.go +++ b/mmv1/third_party/terraform/transport/config_test.go @@ -522,137 +522,3 @@ func TestGetRegionFromRegionSelfLink(t *testing.T) { }) } } - -func TestResourceBasePathDefault(t *testing.T) { - config := &transport_tpg.Config{ - Credentials: transport_tpg.TestFakeCredentialsPath, - Project: "my-gce-project", - Region: "us-central1", - } - cases := map[string]struct { - BasePath string - RepPath string - BasePathKey string - Config *transport_tpg.Config - Location string - ExpectedOutput string - }{ - "Default to global path": { - BasePath: "https://clouddeploy.googleapis.com/v1/", - RepPath: "https://www.clouddeploy.{{location}}.rep.googleapis.com/v1/", - BasePathKey: "Clouddeploy", - Config: config, - Location: "us-central1", - ExpectedOutput: "https://clouddeploy.googleapis.com/v1/", - }, - "Overridden path takes priority": { - BasePath: "https://override.{{location}}.googleapis.com/v1/", - RepPath: "https://www.clouddeploy.{{location}}.rep.googleapis.com/v1/", - BasePathKey: "Clouddeploy", - Config: config, - Location: "us-central1", - ExpectedOutput: "https://override.us-central1.googleapis.com/v1/", - }, - } - - for tn, tc := range cases { - t.Run(tn, func(t *testing.T) { - - basePath, _ := transport_tpg.ResourceBasePath(tc.BasePath, tc.RepPath, tc.BasePathKey, tc.Config, tc.Location) - - if basePath != tc.ExpectedOutput { - t.Fatalf("want %s, got %s", tc.ExpectedOutput, basePath) - } - }) - } -} - -func TestResourceBasePathPreferGlobal(t *testing.T) { - config := &transport_tpg.Config{ - Credentials: transport_tpg.TestFakeCredentialsPath, - Project: "my-gce-project", - Region: "us-central1", - PreferGlobalEndpoints: true, - } - cases := map[string]struct { - BasePath string - RepPath string - BasePathKey string - Config *transport_tpg.Config - Location string - ExpectedOutput string - }{ - "Default to global path": { - BasePath: "https://clouddeploy.googleapis.com/v1/", - RepPath: "https://www.clouddeploy.{{location}}.rep.googleapis.com/v1/", - BasePathKey: "Clouddeploy", - Config: config, - Location: "us-central1", - ExpectedOutput: "https://clouddeploy.googleapis.com/v1/", - }, - "Overridden path takes priority": { - BasePath: "https://override.{{location}}.googleapis.com/v1/", - RepPath: "https://www.clouddeploy.{{location}}.rep.googleapis.com/v1/", - BasePathKey: "Clouddeploy", - Config: config, - Location: "us-central1", - ExpectedOutput: "https://override.us-central1.googleapis.com/v1/", - }, - } - - for tn, tc := range cases { - t.Run(tn, func(t *testing.T) { - - basePath, _ := transport_tpg.ResourceBasePath(tc.BasePath, tc.RepPath, tc.BasePathKey, tc.Config, tc.Location) - - if basePath != tc.ExpectedOutput { - t.Fatalf("want %s, got %s", tc.ExpectedOutput, basePath) - } - }) - } -} - -func TestResourceBasePathPreferRegional(t *testing.T) { - config := &transport_tpg.Config{ - Credentials: transport_tpg.TestFakeCredentialsPath, - Project: "my-gce-project", - Region: "us-central1", - PreferRegionalEndpoints: true, - } - cases := map[string]struct { - BasePath string - RepPath string - BasePathKey string - Config *transport_tpg.Config - Location string - ExpectedOutput string - }{ - "Default to regional path": { - BasePath: "https://clouddeploy.googleapis.com/v1/", - RepPath: "https://www.clouddeploy.{{location}}.rep.googleapis.com/v1/", - BasePathKey: "Clouddeploy", - Config: config, - Location: "us-central1", - ExpectedOutput: "https://www.clouddeploy.us-central1.rep.googleapis.com/v1/", - }, - "Overridden path takes priority": { - BasePath: "https://override.{{location}}.googleapis.com/v1/", - RepPath: "https://www.clouddeploy.{{location}}.rep.googleapis.com/v1/", - BasePathKey: "Clouddeploy", - Config: config, - Location: "us-central1", - ExpectedOutput: "https://override.us-central1.googleapis.com/v1/", - }, - } - - for tn, tc := range cases { - t.Run(tn, func(t *testing.T) { - - basePath, _ := transport_tpg.ResourceBasePath(tc.BasePath, tc.RepPath, tc.BasePathKey, tc.Config, tc.Location) - - if basePath != tc.ExpectedOutput { - t.Fatalf("want %s, got %s", tc.ExpectedOutput, basePath) - } - }) - } -} From 300b5b1bff1ab0d2dc63781958835be18ad9179f Mon Sep 17 00:00:00 2001 From: Stephen Lewis Date: Tue, 28 Apr 2026 12:06:47 -0700 Subject: [PATCH 2/4] Fixed behavior when no RepUrl is available --- mmv1/third_party/terraform/transport/base_url.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/transport/base_url.go b/mmv1/third_party/terraform/transport/base_url.go index ab3f8abce678..153aba22fa64 100644 --- a/mmv1/third_party/terraform/transport/base_url.go +++ b/mmv1/third_party/terraform/transport/base_url.go @@ -17,11 +17,11 @@ func BaseUrl(product registry.Product, config *Config) string { } u := product.BaseUrl - if config.PreferRegionalEndpoints { + if config.PreferRegionalEndpoints && product.RepUrl != "" { u = product.RepUrl } else if config.PreferGlobalEndpoints { u = product.BaseUrl - } else if product.RepByDefault { + } else if product.RepByDefault && product.RepUrl != "" { u = product.RepUrl } From 4e380c56317626f04cfeba44bf209ddf9255af6b Mon Sep 17 00:00:00 2001 From: Stephen Lewis Date: Tue, 28 Apr 2026 12:12:31 -0700 Subject: [PATCH 3/4] Fixed REP interaction with mTLS/universe domain --- mmv1/third_party/terraform/transport/base_url.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/transport/base_url.go b/mmv1/third_party/terraform/transport/base_url.go index 153aba22fa64..96fe8eea4f92 100644 --- a/mmv1/third_party/terraform/transport/base_url.go +++ b/mmv1/third_party/terraform/transport/base_url.go @@ -26,7 +26,7 @@ func BaseUrl(product registry.Product, config *Config) string { } if config.IsMtls { - u = GetMtlsEndpoint(product.BaseUrl) + u = GetMtlsEndpoint(u) } if config.UniverseDomain != "" && config.UniverseDomain != "googleapis.com" { u = strings.ReplaceAll(u, "googleapis.com", config.UniverseDomain) From 3141e8462fbdf4d4ee1a9b3e9ed0015ba5eba24a Mon Sep 17 00:00:00 2001 From: Stephen Lewis Date: Wed, 29 Apr 2026 10:18:10 -0700 Subject: [PATCH 4/4] Switched from url.JoinPath to string formatting to avoid escaping {} --- .../examples/base_configs/test_file.go.tmpl | 8 +--- mmv1/templates/terraform/operation.go.tmpl | 7 +-- mmv1/templates/terraform/resource.go.tmpl | 44 +++---------------- .../samples/base_configs/test_file.go.tmpl | 8 +--- 4 files changed, 11 insertions(+), 56 deletions(-) diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl b/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl index ed882dad7047..35f01788b0a9 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl @@ -24,7 +24,6 @@ import ( "strings" "testing" "time" - urlPkg "net/url" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -50,7 +49,6 @@ var ( _ = tpgresource.SetLabels _ = transport_tpg.Config{} _ = googleapi.Error{} - _ = urlPkg.JoinPath _ = {{ lower $.Res.ProductMetadata.Name }}.Product ) @@ -156,11 +154,7 @@ func testAccCheck{{ $.Res.ResourceName }}DestroyProducer(t *testing.T) func(s *t {{- else }} config := acctest.GoogleProviderConfig(t) - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl({{ lower $.Res.ProductMetadata.Name }}.Product, config), "{{$.Res.SelfLinkUri}}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVarsForTest(config, rs, url) + url, err := tpgresource.ReplaceVarsForTest(config, rs, fmt.Sprintf("%s%s", transport_tpg.BaseUrl({{ lower $.Res.ProductMetadata.Name }}.Product, config), "{{$.Res.SelfLinkUri}}")) if err != nil { return err } diff --git a/mmv1/templates/terraform/operation.go.tmpl b/mmv1/templates/terraform/operation.go.tmpl index 6b8a4213ab34..8bddac026be7 100644 --- a/mmv1/templates/terraform/operation.go.tmpl +++ b/mmv1/templates/terraform/operation.go.tmpl @@ -25,7 +25,6 @@ import ( "log" "strings" "time" - urlPkg "net/url" "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" @@ -65,13 +64,11 @@ func (w *{{ $.ProductMetadata.Name }}OperationWaiter) QueryOp() (interface{}, er return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") } // Returns the proper get. - url, err := urlPkg.JoinPath( + url := fmt.Sprintf( + "%s%s", transport_tpg.BaseUrl(Product, w.Config), fmt.Sprintf("{{ replaceAll $.GetAsync.Operation.BaseUrl "{{op_id}}" "%s" }}", w.CommonOperationWaiter.Op.Name), ) - if err != nil { - return nil, err - } {{- if $.ProductMetadata.Version.RepEnabled }} if strings.Contains(url, "{{"{{"}}location{{"}}"}}") && w.Location == "" { return nil, fmt.Errorf("failed to find location for a resource with a regionalized endpoint %s", url) diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index 779663618555..ddb1d16ab597 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -34,7 +34,6 @@ import ( "strconv" "strings" "time" - urlPkg "net/url" "github.com/hashicorp/errwrap" "github.com/hashicorp/go-cty/cty" @@ -90,7 +89,6 @@ var ( _ = transport_tpg.Config{} _ = verify.ValidateEnum _ = googleapi.Error{} - _ = urlPkg.JoinPath ) func init() { @@ -294,11 +292,7 @@ func resource{{ $.ResourceName -}}Create(d *schema.ResourceData, meta interface{ defer transport_tpg.MutexStore.Unlock(lockName) {{- end}} - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.CreateUri}}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{$.CreateUri}}")) if err != nil { return err } @@ -558,11 +552,7 @@ func resource{{ $.ResourceName -}}PollRead(d *schema.ResourceData, meta interfac return func() (map[string]interface{}, error) { config := meta.(*transport_tpg.Config) - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}") - if err != nil { - return nil, err - } - url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}")) if err != nil { return nil, err } @@ -658,11 +648,7 @@ func resource{{ $.ResourceName -}}Read(d *schema.ResourceData, meta interface{}) return err } - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}{{$.ReadQueryParams}}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}{{$.ReadQueryParams}}")) if err != nil { return err } @@ -941,11 +927,7 @@ func resource{{ $.ResourceName -}}Update(d *schema.ResourceData, meta interface{ defer transport_tpg.MutexStore.Unlock(lockName) {{- end}} - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{ $.UpdateUri }}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{ $.UpdateUri }}")) if err != nil { return err } @@ -1048,11 +1030,7 @@ if len(updateMask) > 0 { if d.HasChange("{{ join ($.PropertyNamesToStrings (index $CustomUpdateProps $group)) "\") || d.HasChange(\""}}") { obj := make(map[string]interface{}) {{ if $group.FingerprintName }} - getUrl, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}") - if err != nil { - return err - } - getUrl, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, getUrl) + getUrl, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{$.SelfLinkUri}}")) if err != nil { return err } @@ -1139,11 +1117,7 @@ if d.HasChange("{{ join ($.PropertyNamesToStrings (index $CustomUpdateProps $gro transport_tpg.MutexStore.Lock(lockName) defer transport_tpg.MutexStore.Unlock(lockName) {{- end}} - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{ $group.UpdateUrl }}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{ $group.UpdateUrl }}")) if err != nil { return err } @@ -1274,11 +1248,7 @@ func resource{{ $.ResourceName }}Delete(d *schema.ResourceData, meta interface{} transport_tpg.MutexStore.Lock(lockName) defer transport_tpg.MutexStore.Unlock(lockName) {{- end }} - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl(Product, config), "{{$.DeleteUri}}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, url) + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, fmt.Sprintf("%s%s", transport_tpg.BaseUrl(Product, config), "{{$.DeleteUri}}")) if err != nil { return err } diff --git a/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl index 0528f121398f..f5b93d7b9c27 100644 --- a/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/test_file.go.tmpl @@ -31,7 +31,6 @@ import ( "strings" "testing" "time" - urlPkg "net/url" "github.com/hashicorp/terraform-plugin-testing/helper/resource" {{- if $needsPlancheck }} @@ -60,7 +59,6 @@ var ( _ = tpgresource.SetLabels _ = transport_tpg.Config{} _ = googleapi.Error{} - _ = urlPkg.JoinPath _ = {{ lower $.Res.ProductMetadata.Name }}.Product ) @@ -189,11 +187,7 @@ func testAccCheck{{ $.Res.ResourceName }}DestroyProducer(t *testing.T) func(s *t {{- else }} config := acctest.GoogleProviderConfig(t) - url, err := urlPkg.JoinPath(transport_tpg.BaseUrl({{ lower $.Res.ProductMetadata.Name }}.Product, config), "{{$.Res.SelfLinkUri}}") - if err != nil { - return err - } - url, err = tpgresource.ReplaceVarsForTest(config, rs, url) + url, err := tpgresource.ReplaceVarsForTest(config, rs, fmt.Sprintf("%s%s", transport_tpg.BaseUrl({{ lower $.Res.ProductMetadata.Name }}.Product, config), "{{$.Res.SelfLinkUri}}")) if err != nil { return err }