Skip to content

Commit dd9d742

Browse files
committed
(refactor) DRYer code.
1 parent f37b089 commit dd9d742

16 files changed

+585
-253
lines changed

internal/provider/helpers.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package provider
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/terraform-plugin-framework/datasource"
7+
"github.com/hashicorp/terraform-plugin-framework/path"
8+
"github.com/hashicorp/terraform-plugin-framework/resource"
9+
client "github.com/pomerium/enterprise-client-go"
10+
)
11+
12+
// ConfigureClient is a helper to configure resources and data sources with the API client
13+
func ConfigureClient(req any, resp any, typeName string) *client.Client {
14+
var providerData any
15+
switch r := req.(type) {
16+
case datasource.ConfigureRequest:
17+
providerData = r.ProviderData
18+
case resource.ConfigureRequest:
19+
providerData = r.ProviderData
20+
}
21+
22+
if providerData == nil {
23+
return nil
24+
}
25+
26+
client, ok := providerData.(*client.Client)
27+
if !ok {
28+
switch r := resp.(type) {
29+
case *datasource.ConfigureResponse:
30+
r.Diagnostics.AddError(
31+
"Unexpected Data Source Configure Type",
32+
fmt.Sprintf("Expected *client.Client, got: %T.", providerData),
33+
)
34+
case *resource.ConfigureResponse:
35+
r.Diagnostics.AddError(
36+
"Unexpected Resource Configure Type",
37+
fmt.Sprintf("Expected *client.Client, got: %T.", providerData),
38+
)
39+
}
40+
return nil
41+
}
42+
43+
return client
44+
}
45+
46+
// ImportStatePassthroughID is a helper that implements the common import state pattern
47+
func ImportStatePassthroughID(req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
48+
resource.ImportStatePassthroughID(nil, path.Root("id"), req, resp)
49+
}

internal/provider/models.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package provider
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework/types"
5+
)
6+
7+
// ServiceAccountModel represents the shared model for service account resources and data sources
8+
type ServiceAccountModel struct {
9+
ID types.String `tfsdk:"id"`
10+
Name types.String `tfsdk:"name"`
11+
NamespaceID types.String `tfsdk:"namespace_id"`
12+
Description types.String `tfsdk:"description"`
13+
UserID types.String `tfsdk:"user_id"`
14+
ExpiresAt types.String `tfsdk:"expires_at"`
15+
}
16+
17+
// NamespaceModel represents the shared model for namespace resources and data sources
18+
type NamespaceModel struct {
19+
ID types.String `tfsdk:"id"`
20+
Name types.String `tfsdk:"name"`
21+
ParentID types.String `tfsdk:"parent_id"`
22+
}
23+
24+
// RouteModel represents the shared model for route resources and data sources
25+
type RouteModel struct {
26+
ID types.String `tfsdk:"id"`
27+
Name types.String `tfsdk:"name"`
28+
From types.String `tfsdk:"from"`
29+
To types.List `tfsdk:"to"`
30+
NamespaceID types.String `tfsdk:"namespace_id"`
31+
Policies types.List `tfsdk:"policies"`
32+
}
33+
34+
// PolicyModel represents the shared model for policy resources and data sources
35+
type PolicyModel struct {
36+
ID types.String `tfsdk:"id"`
37+
Name types.String `tfsdk:"name"`
38+
NamespaceID types.String `tfsdk:"namespace_id"`
39+
PPL types.String `tfsdk:"ppl"`
40+
}

internal/provider/namespace.go

+5-47
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@ package provider
22

33
import (
44
"context"
5-
"fmt"
65

76
"github.com/hashicorp/terraform-plugin-framework/diag"
8-
"github.com/hashicorp/terraform-plugin-framework/path"
97
"github.com/hashicorp/terraform-plugin-framework/resource"
10-
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
11-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
12-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
138
"github.com/hashicorp/terraform-plugin-framework/types"
149
"github.com/hashicorp/terraform-plugin-log/tflog"
1510

@@ -34,55 +29,18 @@ type NamespaceResource struct {
3429
}
3530

3631
// NamespaceResourceModel describes the resource data model.
37-
type NamespaceResourceModel struct {
38-
ID types.String `tfsdk:"id"`
39-
Name types.String `tfsdk:"name"`
40-
ParentID types.String `tfsdk:"parent_id"`
41-
}
32+
type NamespaceResourceModel = NamespaceModel
4233

4334
func (r *NamespaceResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
4435
resp.TypeName = req.ProviderTypeName + "_namespace"
4536
}
4637

4738
func (r *NamespaceResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
48-
resp.Schema = schema.Schema{
49-
MarkdownDescription: "Namespace resource for Pomerium.",
50-
51-
Attributes: map[string]schema.Attribute{
52-
"id": schema.StringAttribute{
53-
Computed: true,
54-
Description: "Unique identifier for the namespace.",
55-
PlanModifiers: []planmodifier.String{
56-
stringplanmodifier.UseStateForUnknown(),
57-
},
58-
},
59-
"name": schema.StringAttribute{
60-
Description: "Name of the namespace.",
61-
Required: true,
62-
},
63-
"parent_id": schema.StringAttribute{
64-
Description: "ID of the parent namespace (optional).",
65-
Optional: true,
66-
},
67-
},
68-
}
39+
resp.Schema = NamespaceSchema(false)
6940
}
7041

7142
func (r *NamespaceResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
72-
if req.ProviderData == nil {
73-
return
74-
}
75-
76-
c, ok := req.ProviderData.(*client.Client)
77-
if !ok {
78-
resp.Diagnostics.AddError(
79-
"Unexpected Provider Data Type",
80-
fmt.Sprintf("Expected *client.Client, got: %T.", req.ProviderData),
81-
)
82-
return
83-
}
84-
85-
r.client = c
43+
r.client = ConfigureClient(req, resp, "namespace")
8644
}
8745

8846
func (r *NamespaceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
@@ -186,8 +144,8 @@ func (r *NamespaceResource) Delete(ctx context.Context, req resource.DeleteReque
186144
resp.State.RemoveResource(ctx)
187145
}
188146

189-
func (r *NamespaceResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
190-
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
147+
func (r *NamespaceResource) ImportState(_ context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
148+
ImportStatePassthroughID(req, resp)
191149
}
192150

193151
func ConvertNamespaceToPB(_ context.Context, src *NamespaceResourceModel) (*pb.Namespace, diag.Diagnostics) {

internal/provider/namespace_data_source.go

+2-21
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package provider
22

33
import (
44
"context"
5-
"fmt"
65

76
"github.com/hashicorp/terraform-plugin-framework/datasource"
87
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
9-
"github.com/hashicorp/terraform-plugin-framework/types"
108

119
client "github.com/pomerium/enterprise-client-go"
1210
"github.com/pomerium/enterprise-client-go/pb"
@@ -22,11 +20,7 @@ type NamespaceDataSource struct {
2220
client *client.Client
2321
}
2422

25-
type NamespaceDataSourceModel struct {
26-
ID types.String `tfsdk:"id"`
27-
Name types.String `tfsdk:"name"`
28-
ParentID types.String `tfsdk:"parent_id"`
29-
}
23+
type NamespaceDataSourceModel = NamespaceModel
3024

3125
func (d *NamespaceDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
3226
resp.TypeName = req.ProviderTypeName + "_namespace"
@@ -54,20 +48,7 @@ func (d *NamespaceDataSource) Schema(_ context.Context, _ datasource.SchemaReque
5448
}
5549

5650
func (d *NamespaceDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
57-
if req.ProviderData == nil {
58-
return
59-
}
60-
61-
client, ok := req.ProviderData.(*client.Client)
62-
if !ok {
63-
resp.Diagnostics.AddError(
64-
"Unexpected Data Source Configure Type",
65-
fmt.Sprintf("Expected *client.Client, got: %T.", req.ProviderData),
66-
)
67-
return
68-
}
69-
70-
d.client = client
51+
d.client = ConfigureClient(req, resp, "namespace")
7152
}
7253

7354
func (d *NamespaceDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {

internal/provider/namespaces_data_source.go

-6
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ type NamespacesDataSource struct {
2222
client *client.Client
2323
}
2424

25-
type NamespaceModel struct {
26-
ID types.String `tfsdk:"id"`
27-
Name types.String `tfsdk:"name"`
28-
ParentID types.String `tfsdk:"parent_id"`
29-
}
30-
3125
type NamespacesDataSourceModel struct {
3226
Namespaces []NamespaceModel `tfsdk:"namespaces"`
3327
}
+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
9+
10+
client "github.com/pomerium/enterprise-client-go"
11+
"github.com/pomerium/enterprise-client-go/pb"
12+
)
13+
14+
var _ datasource.DataSource = &PoliciesDataSource{}
15+
16+
func NewPoliciesDataSource() datasource.DataSource {
17+
return &PoliciesDataSource{}
18+
}
19+
20+
type PoliciesDataSource struct {
21+
client *client.Client
22+
}
23+
24+
type PoliciesDataSourceModel struct {
25+
Policies []PolicyModel `tfsdk:"policies"`
26+
}
27+
28+
func (d *PoliciesDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
29+
resp.TypeName = req.ProviderTypeName + "_policies"
30+
}
31+
32+
func (d *PoliciesDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
33+
resp.Schema = schema.Schema{
34+
MarkdownDescription: "List all policies",
35+
36+
Attributes: map[string]schema.Attribute{
37+
"policies": schema.ListNestedAttribute{
38+
Computed: true,
39+
NestedObject: schema.NestedAttributeObject{
40+
Attributes: map[string]schema.Attribute{
41+
"id": schema.StringAttribute{
42+
Computed: true,
43+
Description: "Unique identifier for the policy.",
44+
},
45+
"name": schema.StringAttribute{
46+
Computed: true,
47+
Description: "Name of the policy.",
48+
},
49+
"namespace_id": schema.StringAttribute{
50+
Computed: true,
51+
Description: "ID of the namespace the policy belongs to.",
52+
},
53+
"ppl": schema.StringAttribute{
54+
Computed: true,
55+
Description: "Policy Policy Language (PPL) string.",
56+
},
57+
},
58+
},
59+
},
60+
},
61+
}
62+
}
63+
64+
func (d *PoliciesDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
65+
if req.ProviderData == nil {
66+
return
67+
}
68+
69+
client, ok := req.ProviderData.(*client.Client)
70+
if !ok {
71+
resp.Diagnostics.AddError(
72+
"Unexpected Data Source Configure Type",
73+
fmt.Sprintf("Expected *client.Client, got: %T.", req.ProviderData),
74+
)
75+
return
76+
}
77+
78+
d.client = client
79+
}
80+
81+
func (d *PoliciesDataSource) Read(ctx context.Context, _ datasource.ReadRequest, resp *datasource.ReadResponse) {
82+
var data PoliciesDataSourceModel
83+
84+
policiesResp, err := d.client.PolicyService.ListPolicies(ctx, &pb.ListPoliciesRequest{})
85+
if err != nil {
86+
resp.Diagnostics.AddError("Error reading policies", err.Error())
87+
return
88+
}
89+
90+
policies := make([]PolicyModel, 0, len(policiesResp.Policies))
91+
for _, policy := range policiesResp.Policies {
92+
var policyModel PolicyModel
93+
diags := ConvertPolicyFromPB(&policyModel, policy)
94+
if diags.HasError() {
95+
resp.Diagnostics.Append(diags...)
96+
return
97+
}
98+
policies = append(policies, policyModel)
99+
}
100+
101+
data.Policies = policies
102+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
103+
}

internal/provider/policy.go

+2-34
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ import (
77
"github.com/hashicorp/terraform-plugin-framework/diag"
88
"github.com/hashicorp/terraform-plugin-framework/path"
99
"github.com/hashicorp/terraform-plugin-framework/resource"
10-
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
11-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
12-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
1310
"github.com/hashicorp/terraform-plugin-framework/types"
1411
"github.com/hashicorp/terraform-plugin-log/tflog"
1512

@@ -34,43 +31,14 @@ type PolicyResource struct {
3431
}
3532

3633
// PolicyResourceModel describes the resource data model.
37-
type PolicyResourceModel struct {
38-
ID types.String `tfsdk:"id"`
39-
Name types.String `tfsdk:"name"`
40-
NamespaceID types.String `tfsdk:"namespace_id"`
41-
PPL types.String `tfsdk:"ppl"`
42-
}
34+
type PolicyResourceModel = PolicyModel
4335

4436
func (r *PolicyResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
4537
resp.TypeName = req.ProviderTypeName + "_policy"
4638
}
4739

4840
func (r *PolicyResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
49-
resp.Schema = schema.Schema{
50-
MarkdownDescription: "Policy resource for Pomerium.",
51-
52-
Attributes: map[string]schema.Attribute{
53-
"id": schema.StringAttribute{
54-
Computed: true,
55-
Description: "Unique identifier for the policy.",
56-
PlanModifiers: []planmodifier.String{
57-
stringplanmodifier.UseStateForUnknown(),
58-
},
59-
},
60-
"name": schema.StringAttribute{
61-
Description: "Name of the policy.",
62-
Required: true,
63-
},
64-
"namespace_id": schema.StringAttribute{
65-
Description: "ID of the namespace the policy belongs to.",
66-
Required: true,
67-
},
68-
"ppl": schema.StringAttribute{
69-
Description: "Policy Policy Language (PPL) string.",
70-
Required: true,
71-
},
72-
},
73-
}
41+
resp.Schema = PolicySchema(false)
7442
}
7543

7644
func (r *PolicyResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {

0 commit comments

Comments
 (0)