-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Add google_service_account_key list resource #18242
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
Open
vr-ibm
wants to merge
2
commits into
GoogleCloudPlatform:main
Choose a base branch
from
vr-ibm:service-account-key-list-resource
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+314
−1
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
152 changes: 152 additions & 0 deletions
152
mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_key.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| // Copyright (c) IBM Corp. 2014, 2026 | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
|
|
||
| package resourcemanager | ||
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| "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" | ||
| "google.golang.org/api/iam/v1" | ||
|
|
||
| "github.com/hashicorp/terraform-provider-google/google/registry" | ||
| "github.com/hashicorp/terraform-provider-google/google/services/iambeta" | ||
| "github.com/hashicorp/terraform-provider-google/google/tpgresource" | ||
| transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" | ||
| ) | ||
|
|
||
| func init() { | ||
| registry.FrameworkListResource{ | ||
| Name: "google_service_account_key", | ||
| ProductName: "resourcemanager", | ||
| Func: NewGoogleServiceAccountKeyListResource, | ||
| }.Register() | ||
| } | ||
|
|
||
| type GoogleServiceAccountKeyListResource struct { | ||
| tpgresource.ListResourceMetadata | ||
| } | ||
|
|
||
| // GoogleServiceAccountKeyListModel matches [ListResourceMetadata.ListConfigFields] (tfsdk names and types). | ||
| type GoogleServiceAccountKeyListModel struct { | ||
| ServiceAccountID types.String `tfsdk:"service_account_id"` | ||
| } | ||
|
|
||
| func NewGoogleServiceAccountKeyListResource() list.ListResource { | ||
| listR := &GoogleServiceAccountKeyListResource{} | ||
| listR.TypeName = "google_service_account_key" | ||
| listR.SDKv2Resource = ResourceGoogleServiceAccountKey() | ||
| listR.ListConfigFields = []tpgresource.ListConfigField{{Name: "service_account_id", Kind: tpgresource.ListConfigKindString, Optional: false}} | ||
| return listR | ||
| } | ||
|
|
||
| func (listR *GoogleServiceAccountKeyListResource) List(ctx context.Context, listReq list.ListRequest, stream *list.ListResultsStream) { | ||
| var data GoogleServiceAccountKeyListModel | ||
| diags := listReq.Config.Get(ctx, &data) | ||
| if diags.HasError() { | ||
| stream.Results = list.ListResultsStreamDiagnostics(diags) | ||
| return | ||
| } | ||
| if data.ServiceAccountID.IsNull() || data.ServiceAccountID.ValueString() == "" { | ||
| diags = append(diags, diag.NewErrorDiagnostic( | ||
| "Missing required argument", | ||
| `The "service_account_id" argument is required and must not be empty.`, | ||
| )) | ||
| 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 | ||
| } | ||
| serviceAccountID := data.ServiceAccountID.ValueString() | ||
|
|
||
| errServiceAccountKeyListStreamClosed := errors.New("stream closed") | ||
| stream.Results = func(push func(list.ListResult) bool) { | ||
| err := ListServiceAccountKeys(listR.Client, serviceAccountID, func(rd *schema.ResourceData) error { | ||
| result := listReq.NewListResult(ctx) | ||
|
|
||
| if err := listR.SetResult(ctx, listReq.IncludeResource, &result, rd, "name"); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if !push(result) { | ||
| return errServiceAccountKeyListStreamClosed | ||
| } | ||
| return nil | ||
| }) | ||
| // A closed stream is not an error: return without pushing again. | ||
| if err == nil || errors.Is(err, errServiceAccountKeyListStreamClosed) { | ||
| return | ||
| } | ||
| diags.AddError("API Error", err.Error()) | ||
| result := listReq.NewListResult(ctx) | ||
| result.Diagnostics = diags | ||
| push(result) | ||
| } | ||
| } | ||
|
|
||
| func flattenGoogleServiceAccountKeyListItem(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { | ||
| var key iam.ServiceAccountKey | ||
| if err := tpgresource.Convert(res, &key); err != nil { | ||
| return err | ||
| } | ||
| d.SetId(key.Name) | ||
| return flattenServiceAccountKey(d, config, &key) | ||
| } | ||
|
|
||
| func ListServiceAccountKeys(config *transport_tpg.Config, serviceAccountID string, callback func(rd *schema.ResourceData) error) error { | ||
| if config == nil { | ||
| return fmt.Errorf("provider client is not configured") | ||
| } | ||
| d := ResourceGoogleServiceAccountKey().Data(&terraform.InstanceState{}) | ||
| if err := d.Set("service_account_id", serviceAccountID); err != nil { | ||
| return fmt.Errorf("error setting service_account_id on temporary resource data: %w", err) | ||
| } | ||
|
|
||
| var ( | ||
| url string | ||
| err error | ||
| ) | ||
| if strings.Contains(serviceAccountID, "projects/") { | ||
| url = transport_tpg.BaseUrl(iambeta.Product, config) + serviceAccountID + "/keys" | ||
| } else { | ||
| url, err = tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(iambeta.Product, config)+"projects/-/serviceAccounts/{{service_account_id}}/keys") | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
|
|
||
| billingProject := "" | ||
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { | ||
| billingProject = bp | ||
| } | ||
|
|
||
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return transport_tpg.ListPages(transport_tpg.ListPagesOptions{ | ||
| Config: config, | ||
| TempData: d, | ||
| Resource: ResourceGoogleServiceAccountKey(), | ||
| ListURL: url, | ||
| BillingProject: billingProject, | ||
| UserAgent: userAgent, | ||
| ItemName: "keys", | ||
| Flattener: flattenGoogleServiceAccountKeyListItem, | ||
| Callback: callback, | ||
| }) | ||
| } |
71 changes: 71 additions & 0 deletions
71
mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_key_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| package resourcemanager_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/resourcemanager" | ||
| ) | ||
|
|
||
| func TestAccListGoogleServiceAccountKey_queryIdentity(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| accountId := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) | ||
| project := envvar.GetTestProjectFromEnv() | ||
|
|
||
| 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: testAccListGoogleServiceAccountKey_setup(project, accountId), | ||
| }, | ||
| { | ||
| Query: true, | ||
| Config: testAccListGoogleServiceAccountKey_query(project, accountId), | ||
| QueryResultChecks: []querycheck.QueryResultCheck{ | ||
| querycheck.ExpectLengthAtLeast("google_service_account_key.all", 1), | ||
| querycheck.ExpectIdentity("google_service_account_key.all", map[string]knownvalue.Check{ | ||
| "name": knownvalue.NotNull(), | ||
| "service_account_id": knownvalue.NotNull(), | ||
| }), | ||
| }, | ||
| }, | ||
| }, | ||
| }) | ||
| } | ||
|
|
||
| func testAccListGoogleServiceAccountKey_setup(project, accountId string) string { | ||
| return fmt.Sprintf(` | ||
| resource "google_service_account" "sa" { | ||
| project = "%s" | ||
| account_id = "%s" | ||
| display_name = "Test SA for key listing" | ||
| } | ||
|
|
||
| resource "google_service_account_key" "key" { | ||
| service_account_id = google_service_account.sa.name | ||
| } | ||
| `, project, accountId) | ||
| } | ||
|
|
||
| func testAccListGoogleServiceAccountKey_query(project, accountId string) string { | ||
| return fmt.Sprintf(` | ||
| list "google_service_account_key" "all" { | ||
| provider = google | ||
| config { | ||
| service_account_id = "projects/%s/serviceAccounts/%s@%s.iam.gserviceaccount.com" | ||
| } | ||
| } | ||
| `, project, accountId, project) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
.../terraform/website/docs/list-resources/google_service_account_key.html.markdown
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| --- | ||
| subcategory: "Cloud Platform" | ||
| page_title: "google_service_account_key (list)" | ||
| description: |- | ||
| List Google Cloud IAM service account keys for a service account for use with | ||
| terraform query and .tfquery.hcl files. | ||
| --- | ||
|
|
||
| # google_service_account_key (list) | ||
|
|
||
| ## Overview | ||
|
|
||
| Lists service account keys belonging to a given service account. | ||
|
|
||
| Use this list resource with | ||
| [`terraform query`](https://developer.hashicorp.com/terraform/cli/commands/query) | ||
| and **`.tfquery.hcl`** files. | ||
|
|
||
| For how list resources work in this provider, file layout, Terraform version requirements, and | ||
| shared `list` block arguments, refer to the guide | ||
| [Use list resources with terraform query](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/using_list_resources_with_terraform_query). | ||
|
|
||
| ## Example Usage | ||
|
|
||
| ```hcl | ||
| list "google_service_account_key" "all" { | ||
| provider = google | ||
|
|
||
| config { | ||
| service_account_id = "projects/my-project/serviceAccounts/my-sa@my-project.iam.gserviceaccount.com" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Run `terraform query` from the directory that contains the `.tfquery.hcl` file. | ||
|
|
||
| ## Configuration (`config` block) | ||
|
|
||
| * `service_account_id` - (Required) Parent service account to list keys for. This may be either | ||
| the full resource name (for example | ||
| `projects/my-project/serviceAccounts/my-sa@my-project.iam.gserviceaccount.com`) or the | ||
| service account email. | ||
|
|
||
| ## Identity Attributes | ||
|
|
||
| By default each result includes **resource identity** for `google_service_account_key` (see | ||
| [Resource identity](https://developer.hashicorp.com/terraform/language/resources/identities)): | ||
|
|
||
| * `service_account_id` - Parent service account identifier. | ||
| * `name` - Full key resource name, such as | ||
| `projects/my-project/serviceAccounts/my-sa@my-project.iam.gserviceaccount.com/keys/1234567890abcdef`. | ||
|
|
||
| ## Resource Attributes | ||
|
|
||
| With `include_resource = true` on the `list` block, results also include the full resource-style | ||
| attributes documented for the managed | ||
| [`google_service_account_key` resource](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_key#attributes-reference). |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be done in its own PR to ensure that the flattener is done properly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put a flattener implementation in #18241, does that cover what you're looking for here?