Skip to content

Commit

Permalink
Show file tree
Hide file tree
Showing 11 changed files with 937 additions and 2 deletions.
4 changes: 4 additions & 0 deletions example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ resource "pomerium_namespace" "test_namespace" {
parent_id = "9d8dbd2c-8cce-4e66-9c1f-c490b4a07243"
}

resource "pomerium_settings" "settings" {
installation_id = "localhost-dev"
}

resource "pomerium_policy" "test_policy" {
name = "test-policy"
namespace_id = pomerium_namespace.test_namespace.id
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.10.0
google.golang.org/grpc v1.68.0
google.golang.org/protobuf v1.35.2
)

require (
Expand All @@ -26,7 +27,6 @@ require (
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
Expand Down Expand Up @@ -69,7 +69,6 @@ require (
golang.org/x/tools v0.25.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
106 changes: 106 additions & 0 deletions internal/provider/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package provider

import (
"context"
"time"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/pomerium/enterprise-client-go/pb"
"google.golang.org/protobuf/types/known/durationpb"
)

func FromStringSlice(slice []string) types.List {
if slice == nil {
return types.ListNull(types.StringType)
}
fields := make([]attr.Value, 0)
for _, v := range slice {
fields = append(fields, types.StringValue(v))
}
return types.ListValueMust(types.StringType, fields)
}

// FromStringList converts a Settings_StringList to a types.List
func FromStringList(sl *pb.Settings_StringList) types.List {
if sl == nil {
return types.ListNull(types.StringType)
}
return FromStringSlice(sl.Values)
}

// FromStringMap converts a map[string]string to a types.Map
func FromStringMap(m map[string]string) types.Map {
if m == nil {
return types.MapNull(types.StringType)
}
elements := make(map[string]attr.Value)
for k, v := range m {
elements[k] = types.StringValue(v)
}
return types.MapValueMust(types.StringType, elements)
}

// ToStringList converts a types.List to Settings_StringList and handles diagnostics internally
func ToStringList(ctx context.Context, dst **pb.Settings_StringList, list types.List, diagnostics *diag.Diagnostics) {
// Handle null list case first
if list.IsNull() {
*dst = nil
return
}

var values []string
diagnostics.Append(list.ElementsAs(ctx, &values, false)...)
if !diagnostics.HasError() {
*dst = &pb.Settings_StringList{Values: values}
}
}

// ToStringMap converts a types.Map to map[string]string and handles diagnostics internally
func ToStringMap(ctx context.Context, dst *map[string]string, m types.Map, diagnostics *diag.Diagnostics) {
if m.IsNull() {
*dst = nil
return
}

result := make(map[string]string)
diagnostics.Append(m.ElementsAs(ctx, &result, false)...)
if !diagnostics.HasError() {
*dst = result
}
}

// ToStringSlice converts a types.List to string slice and handles diagnostics internally
func ToStringSlice(ctx context.Context, dst *[]string, list types.List, diagnostics *diag.Diagnostics) {
*dst = make([]string, 0)
if !list.IsNull() {
var values []string
diagnostics.Append(list.ElementsAs(ctx, &values, false)...)
if !diagnostics.HasError() {
*dst = values
}
}
}

// ToDuration converts a types.String containing a duration to a durationpb.Duration and handles diagnostics internally
func ToDuration(dst **durationpb.Duration, src types.String, field string, diagnostics *diag.Diagnostics) {
if src.IsNull() {
*dst = nil
return
}

if d, err := time.ParseDuration(src.ValueString()); err == nil {
*dst = durationpb.New(d)
} else {
diagnostics.AddError("invalid "+field, err.Error())
}
}

// FromDuration converts a durationpb.Duration to a types.String
func FromDuration(d *durationpb.Duration) types.String {
if d == nil {
return types.StringNull()
}
return types.StringValue(d.AsDuration().String())
}
137 changes: 137 additions & 0 deletions internal/provider/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package provider_test

import (
"context"
"testing"
"time"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/pomerium/enterprise-client-go/pb"
"github.com/pomerium/enterprise-terraform-provider/internal/provider"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/durationpb"
)

func TestFromStringSlice(t *testing.T) {
tests := []struct {
name string
input []string
expected types.List
}{
{
name: "nil slice",
input: nil,
expected: types.ListNull(types.StringType),
},
{
name: "empty slice",
input: []string{},
expected: types.ListValueMust(types.StringType, []attr.Value{}),
},
{
name: "normal slice",
input: []string{"a", "b", "c"},
expected: types.ListValueMust(types.StringType, []attr.Value{
types.StringValue("a"),
types.StringValue("b"),
types.StringValue("c"),
}),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := provider.FromStringSlice(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}

func TestFromDurationP(t *testing.T) {
tests := []struct {
name string
input *durationpb.Duration
expected types.String
}{
{
name: "nil duration",
input: nil,
expected: types.StringNull(),
},
{
name: "zero duration",
input: durationpb.New(0),
expected: types.StringValue("0s"),
},
{
name: "normal duration",
input: durationpb.New(time.Hour + time.Minute),
expected: types.StringValue("1h1m0s"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := provider.FromDuration(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}

func TestToStringList(t *testing.T) {
ctx := context.Background()
tests := []struct {
name string
input types.List
expectError bool
validate func(*testing.T, *pb.Settings_StringList)
}{
{
name: "null list",
input: types.ListNull(types.StringType),
validate: func(t *testing.T, s *pb.Settings_StringList) {
assert.Nil(t, s)
},
},
{
name: "empty list",
input: types.ListValueMust(types.StringType, []attr.Value{}),
validate: func(t *testing.T, s *pb.Settings_StringList) {
require.NotNil(t, s)
assert.Empty(t, s.Values)
},
},
{
name: "valid list",
input: types.ListValueMust(types.StringType, []attr.Value{
types.StringValue("value1"),
types.StringValue("value2"),
}),
validate: func(t *testing.T, s *pb.Settings_StringList) {
require.NotNil(t, s)
assert.Equal(t, []string{"value1", "value2"}, s.Values)
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var result *pb.Settings_StringList
diagnostics := diag.Diagnostics{}
provider.ToStringList(ctx, &result, tt.input, &diagnostics)

if tt.expectError {
assert.True(t, diagnostics.HasError())
return
}

assert.False(t, diagnostics.HasError())
if tt.validate != nil {
tt.validate(t, result)
}
})
}
}
4 changes: 4 additions & 0 deletions internal/provider/help/settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Global Pomerium Settings

The settings are global object.

5 changes: 5 additions & 0 deletions internal/provider/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,8 @@ func TestConfigureClient(t *testing.T) {
})
}
}

// helper function to create pointers
func ptr[T any](v T) *T {
return &v
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ func (p *PomeriumProvider) Resources(_ context.Context) []func() resource.Resour
NewNamespaceResource,
NewRouteResource,
NewPolicyResource,
NewSettingsResource,
NewServiceAccountResource,
}
}
Expand Down
Loading

0 comments on commit cf1265e

Please sign in to comment.