From e25d54ab6374f13e2dc2cdca4fcba2df95c90cd2 Mon Sep 17 00:00:00 2001 From: vr-ibm Date: Fri, 31 Jul 2026 16:03:56 -0500 Subject: [PATCH 1/4] secretmanager: add list resource for google_secret_manager_secret_version --- ...ogle_secret_manager_secret_version.go.tmpl | 179 ++++++++++++++++++ ...secret_manager_secret_version_test.go.tmpl | 86 +++++++++ ...ecret_manager_secret_version.html.markdown | 54 ++++++ 3 files changed, 319 insertions(+) create mode 100644 mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl create mode 100644 mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl create mode 100644 mmv1/third_party/terraform/website/docs/list-resources/google_secret_manager_secret_version.html.markdown diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl new file mode 100644 index 000000000000..1cef2633a7e7 --- /dev/null +++ b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl @@ -0,0 +1,179 @@ +{{- if ne $.TargetVersionName "ga" }} +// Copyright (c) IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package secretmanager + +import ( + "context" + "errors" + "fmt" + "regexp" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/list" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/registry" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + registry.FrameworkListResource{ + Name: "google_secret_manager_secret_version", + ProductName: "secretmanager", + Func: NewGoogleSecretManagerSecretVersionListResource, + }.Register() +} + +type GoogleSecretManagerSecretVersionListResource struct { + tpgresource.ListResourceMetadata +} + +type GoogleSecretManagerSecretVersionListModel struct { + Project types.String `tfsdk:"project"` + Secret types.String `tfsdk:"secret"` +} + +func NewGoogleSecretManagerSecretVersionListResource() list.ListResource { + listR := &GoogleSecretManagerSecretVersionListResource{} + listR.TypeName = "google_secret_manager_secret_version" + listR.SDKv2Resource = ResourceSecretManagerSecretVersion() + listR.ListConfigFields = []tpgresource.ListConfigField{ + {Name: "project", Kind: tpgresource.ListConfigKindString, Optional: true}, + {Name: "secret", Kind: tpgresource.ListConfigKindString, Optional: false}, + } + return listR +} + +func (listR *GoogleSecretManagerSecretVersionListResource) List(ctx context.Context, listReq list.ListRequest, stream *list.ListResultsStream) { + errStreamClosed := errors.New("stream closed") + + var data GoogleSecretManagerSecretVersionListModel + diags := listReq.Config.Get(ctx, &data) + if diags.HasError() { + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + if listR.Client == nil { + diags = append(diags, diag.NewErrorDiagnostic( + "Provider not configured", + "The Google provider client is not available; ensure the provider is configured (e.g. credentials and default project).", + )) + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + + project := listR.GetProject(data.Project) + secret := data.Secret.ValueString() + + stream.Results = func(push func(list.ListResult) bool) { + err := ListSecretManagerSecretVersions(listR.Client, project, secret, func(rd *schema.ResourceData) error { + result := listReq.NewListResult(ctx) + + if err := listR.SetResult(ctx, listReq.IncludeResource, &result, rd, "version"); err != nil { + return err + } + + if !push(result) { + return errStreamClosed + } + return nil + }) + if err == nil || errors.Is(err, errStreamClosed) { + return + } + diags.AddError("API Error", err.Error()) + result := listReq.NewListResult(ctx) + result.Diagnostics = diags + push(result) + } +} + +func ListSecretManagerSecretVersions(config *transport_tpg.Config, project, secret string, callback func(*schema.ResourceData) error) error { + if config == nil { + return fmt.Errorf("provider client is not configured") + } + + d := ResourceSecretManagerSecretVersion().Data(&terraform.InstanceState{}) + + if project != "" { + if err := d.Set("project", project); err != nil { + return fmt.Errorf("error setting project on temporary resource data: %w", err) + } + } + + // Normalize secret to full resource name + fullSecret := secret + if matched, _ := regexp.MatchString(`^projects/[^/]+/secrets/[^/]+$`, secret); !matched { + fullSecret = fmt.Sprintf("projects/%s/secrets/%s", project, secret) + } + if err := d.Set("secret", fullSecret); err != nil { + return fmt.Errorf("error setting secret on temporary resource data: %w", err) + } + + url := fmt.Sprintf("%sprojects/%s/secrets/%s/versions", transport_tpg.BaseUrl(Product, config), project, secret) + + billingProject := project + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + secretRegex := regexp.MustCompile(`projects/(.+)/secrets/(.+)/versions/(.+)$`) + + return transport_tpg.ListPages(transport_tpg.ListPagesOptions{ + Config: config, + TempData: d, + Resource: ResourceSecretManagerSecretVersion(), + ListURL: url, + BillingProject: billingProject, + ItemName: "versions", + UserAgent: userAgent, + Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { + name, ok := res["name"].(string) + if !ok || name == "" { + return fmt.Errorf("missing name in secret version list response") + } + + matches := secretRegex.FindStringSubmatch(name) + if matches == nil { + return fmt.Errorf("secret version name %q does not match expected format", name) + } + // matches[1]=project, matches[2]=secret, matches[3]=version + versionProject := matches[1] + versionSecret := matches[2] + versionNum := matches[3] + + if err := d.Set("project", versionProject); err != nil { + return err + } + if err := d.Set("secret", fmt.Sprintf("projects/%s/secrets/%s", versionProject, versionSecret)); err != nil { + return err + } + if err := d.Set("version", versionNum); err != nil { + return err + } + if err := d.Set("name", name); err != nil { + return err + } + if state, ok := res["state"].(string); ok { + if err := d.Set("enabled", state == "ENABLED"); err != nil { + return err + } + } + + d.SetId(name) + return nil + }, + Callback: callback, + }) +} +{{- end }} diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl new file mode 100644 index 000000000000..c1f4fddfd3cb --- /dev/null +++ b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl @@ -0,0 +1,86 @@ +{{- if ne $.TargetVersionName "ga" }} +package secretmanager_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + _ "github.com/hashicorp/terraform-provider-google/google/services/secretmanager" +) + +func TestAccSecretManagerSecretVersionListResource_basic(t *testing.T) { + t.Parallel() + + project := envvar.GetTestProjectFromEnv() + secretName := fmt.Sprintf("tf-test-secret-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretVersionListResourceBasic(project, secretName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_secret_manager_secret.test", "secret_id", secretName), + resource.TestCheckResourceAttrSet("google_secret_manager_secret_version.test", "version"), + ), + }, + { + Query: true, + Config: testAccSecretManagerSecretVersionListResourceQuery(project, secretName), + QueryResultChecks: []querycheck.QueryResultCheck{ + querycheck.ExpectLengthAtLeast("google_secret_manager_secret_version.all", 1), + querycheck.ExpectIdentity("google_secret_manager_secret_version.all", map[string]knownvalue.Check{ + "project": knownvalue.StringExact(project), + "secret": knownvalue.StringExact(fmt.Sprintf("projects/%s/secrets/%s", project, secretName)), + "version": knownvalue.NotNull(), + }), + }, + }, + }, + }) +} + +func testAccSecretManagerSecretVersionListResourceBasic(project, secretName string) string { + return fmt.Sprintf(` +resource "google_secret_manager_secret" "test" { + secret_id = %q + project = %q + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "test" { + secret = google_secret_manager_secret.test.id + secret_data = "my-secret-data" +} +`, secretName, project) +} + +func testAccSecretManagerSecretVersionListResourceQuery(project, secretName string) string { + return fmt.Sprintf(` +provider "google" {} + +list "google_secret_manager_secret_version" "all" { + provider = google + + config { + project = %q + secret = %q + } +} +`, project, secretName) +} +{{- end }} diff --git a/mmv1/third_party/terraform/website/docs/list-resources/google_secret_manager_secret_version.html.markdown b/mmv1/third_party/terraform/website/docs/list-resources/google_secret_manager_secret_version.html.markdown new file mode 100644 index 000000000000..08ca7a0d281e --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/list-resources/google_secret_manager_secret_version.html.markdown @@ -0,0 +1,54 @@ +--- +subcategory: "Secret Manager" +description: |- + List Secret Manager secret versions for use with terraform query + and .tfquery.hcl files. +--- + +# google_secret_manager_secret_version (list) + +Lists Secret Manager secret versions for use with +[`terraform query`](https://developer.hashicorp.com/terraform/cli/commands/query) and +`.tfquery.hcl` files. Results correspond to existing +[`google_secret_manager_secret_version`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/secret_manager_secret_version) +managed resources. + +For how list resources work in this provider, Terraform version requirements, and shared +`list` block arguments, refer to the guide +[Use list resources with terraform query (Google Cloud provider)](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/using_list_resources_with_terraform_query). + +## Example + +```hcl +list "google_secret_manager_secret_version" "all" { + provider = google + + config { + # Optional. Defaults to the provider project when omitted. + # project = "my-project" + secret = "my-secret" + } +} +``` + +Run `terraform query` from the directory that contains the `.tfquery.hcl` file. + +## Configuration (`config` block) + +* `project` - (Optional) Project ID containing the secret. If unset, the provider project is used. + +* `secret` - (Required) Secret name or full resource name (`projects/{project}/secrets/{secret}`). + +## Results + +By default each result includes resource identity for `google_secret_manager_secret_version`: + +* `project` - Project ID. + +* `secret` - Full secret resource name. + +* `version` - Version number. + +With `include_resource = true` on the `list` block, results also include the full resource-style +attributes documented for the managed +[`google_secret_manager_secret_version` resource](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/secret_manager_secret_version#attributes-reference). From 455966036a7380a76fde3628891ac91fcc105008 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 8 Sep 2026 12:00:49 -0700 Subject: [PATCH 2/4] fix: generate secret version list resource for GA --- .../list_google_secret_manager_secret_version.go.tmpl | 2 -- .../list_google_secret_manager_secret_version_test.go.tmpl | 2 -- 2 files changed, 4 deletions(-) diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl index 1cef2633a7e7..fb0e9d77ee3c 100644 --- a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl +++ b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl @@ -1,4 +1,3 @@ -{{- if ne $.TargetVersionName "ga" }} // Copyright (c) IBM Corp. 2014, 2026 // SPDX-License-Identifier: MPL-2.0 @@ -176,4 +175,3 @@ func ListSecretManagerSecretVersions(config *transport_tpg.Config, project, secr Callback: callback, }) } -{{- end }} diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl index c1f4fddfd3cb..72d0df27afbc 100644 --- a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl +++ b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl @@ -1,4 +1,3 @@ -{{- if ne $.TargetVersionName "ga" }} package secretmanager_test import ( @@ -83,4 +82,3 @@ list "google_secret_manager_secret_version" "all" { } `, project, secretName) } -{{- end }} From 1f21f4d4ca981658e7391237e9380d4e7a8e520c Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 8 Sep 2026 12:04:55 -0700 Subject: [PATCH 3/4] fix: rename static list resource files --- ...rsion.go.tmpl => list_google_secret_manager_secret_version.go} | 0 ....go.tmpl => list_google_secret_manager_secret_version_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename mmv1/third_party/terraform/services/secretmanager/{list_google_secret_manager_secret_version.go.tmpl => list_google_secret_manager_secret_version.go} (100%) rename mmv1/third_party/terraform/services/secretmanager/{list_google_secret_manager_secret_version_test.go.tmpl => list_google_secret_manager_secret_version_test.go} (100%) diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go similarity index 100% rename from mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go.tmpl rename to mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go similarity index 100% rename from mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go.tmpl rename to mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version_test.go From 7963ecb680b6ce5bb14866a7950c3dd575dd618e Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 8 Sep 2026 12:22:25 -0700 Subject: [PATCH 4/4] fix: set identity on secret version list results --- .../list_google_secret_manager_secret_version.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go index fb0e9d77ee3c..38130718d3d1 100644 --- a/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go +++ b/mmv1/third_party/terraform/services/secretmanager/list_google_secret_manager_secret_version.go @@ -163,6 +163,13 @@ func ListSecretManagerSecretVersions(config *transport_tpg.Config, project, secr if err := d.Set("name", name); err != nil { return err } + if err := tpgresource.SetResourceIdentityAttributes(d, map[string]interface{}{ + "project": versionProject, + "secret": fmt.Sprintf("projects/%s/secrets/%s", versionProject, versionSecret), + "version": versionNum, + }); err != nil { + return err + } if state, ok := res["state"].(string); ok { if err := d.Set("enabled", state == "ENABLED"); err != nil { return err