From f032ce15859c30b2421f5a6bcad1f52580c33f0b Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Wed, 3 Apr 2024 11:38:46 -0500 Subject: [PATCH] Go rewrite: import ID formats in doc template (#10345) --- mmv1/api/resource.go | 69 +++++++++++++++++++ .../terraform/resource.html.markdown.tmpl | 30 +++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 90ed4c82534d..25697683cabf 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -14,6 +14,7 @@ package api import ( "fmt" + "regexp" "strings" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" @@ -829,3 +830,71 @@ func (r Resource) TerraformName() string { } return fmt.Sprintf("google_%s_%s", r.ProductMetadata.TerraformName(), google.Underscore(r.Name)) } + +func (r Resource) ImportIdFormatsFromResource() []string { + return ImportIdFormats(r.ImportFormat, r.Identity, r.BaseUrl) +} + +// Returns a list of import id formats for a given resource. If an id +// contains provider-default values, this fn will return formats both +// including and omitting the value. +// +// If a resource has an explicit import_format value set, that will be the +// base import url used. Next, the values of `identity` will be used to +// construct a URL. Finally, `{{name}}` will be used by default. +// +// For instance, if the resource base url is: +// +// projects/{{project}}/global/networks +// +// It returns 3 formats: +// a) self_link: projects/{{project}}/global/networks/{{name}} +// b) short id: {{project}}/{{name}} +// c) short id w/o defaults: {{name}} +func ImportIdFormats(importFormat, identity []string, baseUrl string) []string { + var idFormats []string + if len(importFormat) == 0 { + underscoredBaseUrl := baseUrl + // TODO Q2: underscore base url needed? + // underscored_base_url = base_url.gsub( + // /{{[[:word:]]+}}/, &:underscore + // ) + if len(identity) == 0 { + idFormats = []string{fmt.Sprintf("%s/{{name}}", underscoredBaseUrl)} + } else { + var transformedIdentity []string + for _, id := range identity { + transformedIdentity = append(transformedIdentity, fmt.Sprintf("{{%s}}", id)) + } + identityPath := strings.Join(transformedIdentity, "/") + idFormats = []string{fmt.Sprintf("%s/{{name}}", identityPath)} + } + } else { + idFormats = importFormat + } + + // short id: {{project}}/{{zone}}/{{name}} + fieldMarkers := regexp.MustCompile(`{{[[:word:]]+}}`).FindAllString(idFormats[0], -1) + shortIdFormat := strings.Join(fieldMarkers, "/") + + // short ids without fields with provider-level defaults: + + // without project + fieldMarkers = slices.DeleteFunc(fieldMarkers, func(s string) bool { return s == "{{project}}" }) + shortIdDefaultProjectFormat := strings.Join(fieldMarkers, "/") + + // without project or location + fieldMarkers = slices.DeleteFunc(fieldMarkers, func(s string) bool { return s == "{{region}}" }) + fieldMarkers = slices.DeleteFunc(fieldMarkers, func(s string) bool { return s == "{{zone}}" }) + shortIdDefaultFormat := strings.Join(fieldMarkers, "/") + + // If the id format can include `/` characters we cannot allow short forms such as: + // `{{project}}/{{%name}}` as there is no way to differentiate between + // project-name/resource-name and resource-name/with-slash + if !strings.Contains(idFormats[0], "%") { + idFormats = append(idFormats, shortIdFormat, shortIdDefaultProjectFormat, shortIdDefaultFormat) + } + + // TODO Q2: id_formats.uniq.reject(&:empty?).sort_by { |i| [i.count('/'), i.count('{{')] }.reverse + return idFormats +} diff --git a/mmv1/templates/terraform/resource.html.markdown.tmpl b/mmv1/templates/terraform/resource.html.markdown.tmpl index 420a101dd325..da0989e65dc0 100644 --- a/mmv1/templates/terraform/resource.html.markdown.tmpl +++ b/mmv1/templates/terraform/resource.html.markdown.tmpl @@ -155,8 +155,7 @@ This resource provides the following [Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: - `create` - Default is {{$.Timeouts.InsertMinutes}} minutes. -{{/*TODO: <% if updatable?(object, properties) || object.root_labels? -%> */}} -- `update` - Default is {{$.Timeouts.UpdateMinutes}} minutes. +- `update` - Default is {{$.Timeouts.UpdateMinutes}} minutes.{{/*TODO: <% if updatable?(object, properties) || object.root_labels? -%> */}} - `delete` - Default is {{$.Timeouts.DeleteMinutes}} minutes. ## Import @@ -165,6 +164,33 @@ This resource provides the following This resource does not support import. {{ else }} + {{$.Name}} can be imported using any of these accepted formats: +{{ range $idFormat := $.ImportIdFormatsFromResource }} +* `{{$idFormat}}` +{{- end }} + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import {{$.Name}} using one of the formats above. For example: + +```tf +import { + id = "{{ index $.ImportIdFormatsFromResource 0 }}" + to = {{$.TerraformName}}.default +} +``` +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), {{$.Name}} can be imported using one of the formats above. For example: + +``` + {{- range $idFormat := $.ImportIdFormatsFromResource }} +$ terraform import {{$.TerraformName}}.default {{$idFormat}} + {{- end }} +``` {{ end }} + +{{- if or (contains $.BaseUrl "{{project}}") $.SupportsIndirectUserProjectOverride}} +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override). +{{- end }}