Skip to content

Commit c951fbd

Browse files
tmatilaibrandonc
authored andcommitted
Add tfe_registry_gpg_keys data source
Retrieves all private registry GPG keys of an organization.
1 parent 7121fd5 commit c951fbd

File tree

5 files changed

+267
-0
lines changed

5 files changed

+267
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ FEATURES:
1515
* `r/tfe_workspace`: Now uses the organization's `default_execution_mode` and `default_agent_pool_id` as the default `execution_mode`, by @SwiftEngineer [1137](https://github.com/hashicorp/terraform-provider-tfe/pull/1137)'
1616
* **New Resource**: `r/tfe_registry_gpg_key` is a new resource for managing private registry GPG keys, by @tmatilai
1717
* **New Data Source**: `d/tfe_registry_gpg_key` is a new data source to retrieve a private registry GPG key, by @tmatilai
18+
* **New Data Source**: `d/tfe_registry_gpg_keys` is a new data source to retrieve all private registry GPG keys of an organization, by @tmatilai
1819

1920
ENHANCEMENTS:
2021
* `d/tfe_organization`: Make `name` argument optional if configured for the provider, by @tmatilai [1133](https://github.com/hashicorp/terraform-provider-tfe/pull/1133)
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package provider
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"github.com/hashicorp/go-tfe"
11+
"github.com/hashicorp/terraform-plugin-framework/attr"
12+
"github.com/hashicorp/terraform-plugin-framework/datasource"
13+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
14+
"github.com/hashicorp/terraform-plugin-framework/types"
15+
"github.com/hashicorp/terraform-plugin-log/tflog"
16+
)
17+
18+
// Ensure the implementation satisfies the expected interfaces.
19+
var (
20+
_ datasource.DataSource = &dataSourceTFERegistryGPGKeys{}
21+
_ datasource.DataSourceWithConfigure = &dataSourceTFERegistryGPGKeys{}
22+
)
23+
24+
// NewRegistryGPGKeysDataSource is a helper function to simplify the provider implementation.
25+
func NewRegistryGPGKeysDataSource() datasource.DataSource {
26+
return &dataSourceTFERegistryGPGKeys{}
27+
}
28+
29+
// dataSourceTFERegistryGPGKeys is the data source implementation.
30+
type dataSourceTFERegistryGPGKeys struct {
31+
config ConfiguredClient
32+
}
33+
34+
// modelTFERegistryGPGKeys maps the data source schema data.
35+
type modelTFERegistryGPGKeys struct {
36+
ID types.String `tfsdk:"id"`
37+
Organization types.String `tfsdk:"organization"`
38+
Keys []modelTFERegistryGPGKey `tfsdk:"keys"`
39+
}
40+
41+
// Metadata returns the data source type name.
42+
func (d *dataSourceTFERegistryGPGKeys) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
43+
resp.TypeName = req.ProviderTypeName + "_registry_gpg_keys"
44+
}
45+
46+
// Schema defines the schema for the data source.
47+
func (d *dataSourceTFERegistryGPGKeys) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
48+
resp.Schema = schema.Schema{
49+
Description: "This data source can be used to retrieve all private registry GPG keys of an organization.",
50+
Attributes: map[string]schema.Attribute{
51+
"id": schema.StringAttribute{
52+
Computed: true,
53+
},
54+
"organization": schema.StringAttribute{
55+
Description: "Name of the organization. If omitted, organization must be defined in the provider config.",
56+
Optional: true,
57+
Computed: true,
58+
},
59+
"keys": schema.ListAttribute{
60+
Description: "List of GPG keys in the organization.",
61+
Computed: true,
62+
ElementType: types.ObjectType{
63+
AttrTypes: map[string]attr.Type{
64+
"id": types.StringType,
65+
"organization": types.StringType,
66+
"ascii_armor": types.StringType,
67+
"created_at": types.StringType,
68+
"updated_at": types.StringType,
69+
},
70+
},
71+
},
72+
},
73+
}
74+
}
75+
76+
// Configure adds the provider configured client to the data source.
77+
func (d *dataSourceTFERegistryGPGKeys) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
78+
if req.ProviderData == nil {
79+
return
80+
}
81+
82+
client, ok := req.ProviderData.(ConfiguredClient)
83+
if !ok {
84+
resp.Diagnostics.AddError(
85+
"Unexpected Data Source Configure Type",
86+
fmt.Sprintf("Expected tfe.ConfiguredClient, got %T. This is a bug in the tfe provider, so please report it on GitHub.", req.ProviderData),
87+
)
88+
89+
return
90+
}
91+
d.config = client
92+
}
93+
94+
// Read refreshes the Terraform state with the latest data.
95+
func (d *dataSourceTFERegistryGPGKeys) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
96+
var data modelTFERegistryGPGKeys
97+
98+
// Read Terraform configuration data into the model
99+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
100+
101+
if resp.Diagnostics.HasError() {
102+
return
103+
}
104+
105+
var organization string
106+
resp.Diagnostics.Append(d.config.dataOrDefaultOrganization(ctx, req.Config, &organization)...)
107+
108+
if resp.Diagnostics.HasError() {
109+
return
110+
}
111+
112+
options := tfe.GPGKeyListOptions{
113+
Namespaces: []string{organization},
114+
}
115+
tflog.Debug(ctx, "Listing private registry GPG keys")
116+
keyList, err := d.config.Client.GPGKeys.ListPrivate(ctx, options)
117+
if err != nil {
118+
resp.Diagnostics.AddError("Unable to list private registry GPG keys", err.Error())
119+
return
120+
}
121+
122+
data.ID = types.StringValue(organization)
123+
data.Organization = types.StringValue(organization)
124+
data.Keys = []modelTFERegistryGPGKey{}
125+
126+
for {
127+
for _, key := range keyList.Items {
128+
data.Keys = append(data.Keys, modelFromTFEVGPGKey(key))
129+
}
130+
131+
if keyList.CurrentPage >= keyList.TotalPages {
132+
break
133+
}
134+
options.PageNumber = keyList.NextPage
135+
136+
tflog.Debug(ctx, "Listing private registry GPG keys")
137+
keyList, err = d.config.Client.GPGKeys.ListPrivate(ctx, options)
138+
if err != nil {
139+
resp.Diagnostics.AddError("Unable to list private registry GPG keys", err.Error())
140+
return
141+
}
142+
}
143+
144+
// Save data into Terraform state
145+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
146+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package provider
5+
6+
import (
7+
"fmt"
8+
"math/rand"
9+
"testing"
10+
"time"
11+
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
13+
)
14+
15+
func TestAccTFERegistryGPGKeysDataSource_basic(t *testing.T) {
16+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
17+
orgName := fmt.Sprintf("tst-terraform-%d", rInt)
18+
19+
resource.Test(t, resource.TestCase{
20+
PreCheck: func() { testAccPreCheck(t) },
21+
ProtoV5ProviderFactories: testAccMuxedProviders,
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccTFERegistryGPGKeysDataSourceConfig(orgName),
25+
Check: resource.ComposeAggregateTestCheckFunc(
26+
resource.TestCheckResourceAttr(
27+
"data.tfe_registry_gpg_keys.all", "organization", orgName),
28+
resource.TestCheckResourceAttr(
29+
"data.tfe_registry_gpg_keys.all", "keys.#", "1"),
30+
resource.TestCheckResourceAttrSet(
31+
"data.tfe_registry_gpg_keys.all", "keys.0.id"),
32+
resource.TestCheckResourceAttr(
33+
"data.tfe_registry_gpg_keys.all", "keys.0.organization", orgName),
34+
resource.TestCheckResourceAttrSet(
35+
"data.tfe_registry_gpg_keys.all", "keys.0.ascii_armor"),
36+
),
37+
},
38+
},
39+
})
40+
}
41+
42+
func TestAccTFERegistryGPGKeysDataSource_basicNoKeys(t *testing.T) {
43+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
44+
orgName := fmt.Sprintf("tst-terraform-%d", rInt)
45+
46+
resource.Test(t, resource.TestCase{
47+
PreCheck: func() { testAccPreCheck(t) },
48+
ProtoV5ProviderFactories: testAccMuxedProviders,
49+
Steps: []resource.TestStep{
50+
{
51+
Config: testAccTFERegistryGPGKeysDataSourceConfig_noKeys(orgName),
52+
Check: resource.ComposeAggregateTestCheckFunc(
53+
resource.TestCheckResourceAttr(
54+
"data.tfe_registry_gpg_keys.all", "organization", orgName),
55+
resource.TestCheckResourceAttr(
56+
"data.tfe_registry_gpg_keys.all", "keys.#", "0"),
57+
),
58+
},
59+
},
60+
})
61+
}
62+
63+
func testAccTFERegistryGPGKeysDataSourceConfig(orgName string) string {
64+
return fmt.Sprintf(`
65+
%s
66+
67+
data "tfe_registry_gpg_keys" "all" {
68+
organization = tfe_organization.foobar.name
69+
70+
depends_on = [tfe_registry_gpg_key.foobar]
71+
}
72+
`, testAccTFERegistryGPGKeyResourceConfig(orgName))
73+
}
74+
75+
func testAccTFERegistryGPGKeysDataSourceConfig_noKeys(orgName string) string {
76+
return fmt.Sprintf(`
77+
resource "tfe_organization" "foobar" {
78+
name = "%s"
79+
80+
}
81+
82+
data "tfe_registry_gpg_keys" "all" {
83+
organization = tfe_organization.foobar.name
84+
}
85+
`, orgName)
86+
}

internal/provider/provider_next.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ func (p *frameworkProvider) Configure(ctx context.Context, req provider.Configur
114114
func (p *frameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
115115
return []func() datasource.DataSource{
116116
NewRegistryGPGKeyDataSource,
117+
NewRegistryGPGKeysDataSource,
117118
NewSAMLSettingsDataSource,
118119
}
119120
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
layout: "tfe"
3+
page_title: "Terraform Enterprise: tfe_registry_gpg_keys"
4+
description: |-
5+
Get information on private registry GPG keys of an organization.
6+
---
7+
8+
# Data Source: tfe_registry_gpg_key
9+
10+
Use this data source to get information about all private registry GPG keys of an organization.
11+
12+
## Example Usage
13+
14+
```hcl
15+
data "tfe_registry_gpg_keys" "all" {
16+
organization = "my-org-name"
17+
}
18+
```
19+
20+
## Argument Reference
21+
22+
The following arguments are supported:
23+
24+
* `organization` - (Optional) Name of the organization. If omitted, organization must be defined in the provider config.
25+
26+
## Attributes Reference
27+
28+
* `keys` - List of GPG keys in the organization. Each element contains the following attributes:
29+
* `id` - ID of the GPG key.
30+
* `organization` - Name of the organization.
31+
* `ascii_armor` - ASCII-armored representation of the GPG key.
32+
* `created_at` - The time when the GPG key was created.
33+
* `updated_at` - The time when the GPG key was last updated.

0 commit comments

Comments
 (0)