Skip to content

Commit

Permalink
Fixing map merging and tests. Adding doc (#399)
Browse files Browse the repository at this point in the history
Reference: #399
  • Loading branch information
bendbennett committed Aug 2, 2022
1 parent 6fb3d0a commit b73cbd9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 52 deletions.
33 changes: 24 additions & 9 deletions internal/privatestate/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@ type Data struct {
func (d Data) Bytes(_ context.Context) ([]byte, diag.Diagnostics) {
var diags diag.Diagnostics

bytes, err := json.Marshal(d)
mergedMap := make(map[string][]byte, len(d.Framework)+len(d.Provider))

for k, v := range d.Framework {
mergedMap[k] = v
}

for k, v := range d.Provider {
mergedMap[k] = v
}

bytes, err := json.Marshal(mergedMap)
if err != nil {
diags.AddError(
"Error Encoding Private State",
Expand All @@ -43,11 +53,11 @@ func (d Data) Bytes(_ context.Context) ([]byte, diag.Diagnostics) {
// It must be a JSON encoded slice of bytes, that is map[string][]byte.
func NewData(ctx context.Context, data []byte) (Data, diag.Diagnostics) {
var (
u map[string][]byte
diags diag.Diagnostics
dataMap map[string][]byte
diags diag.Diagnostics
)

err := json.Unmarshal(data, &u)
err := json.Unmarshal(data, &dataMap)
if err != nil {
diags.AddError(
"Error Decoding Private State",
Expand All @@ -63,7 +73,7 @@ func NewData(ctx context.Context, data []byte) (Data, diag.Diagnostics) {
Provider: make(map[string][]byte),
}

for k, v := range u {
for k, v := range dataMap {
if isInvalidProviderDataKey(ctx, k) {
output.Framework[k] = v
continue
Expand Down Expand Up @@ -123,14 +133,18 @@ func (d ProviderData) SetKey(ctx context.Context, key string, value []byte) diag

if !utf8.Valid(value) {
diags.AddError("UTF-8 Invalid",
"Values stored in private state must be valid UTF-8")
"Values stored in private state must be valid UTF-8\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
)

return diags
}

if !json.Valid(value) {
diags.AddError("JSON Invalid",
"Values stored in private state must be valid JSON")
"Values stored in private state must be valid JSON\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
)

return diags
}
Expand All @@ -147,8 +161,9 @@ func ValidateProviderDataKey(ctx context.Context, key string) diag.Diagnostics {
if isInvalidProviderDataKey(ctx, key) {
return diag.Diagnostics{
diag.NewErrorDiagnostic(
"Restricted Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed",
"Restricted Resource Private State Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
),
}
}
Expand Down
64 changes: 21 additions & 43 deletions internal/privatestate/data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,51 +15,24 @@ import (
func TestData_Bytes(t *testing.T) {
t.Parallel()

empty, _ := json.Marshal(privatestate.Data{})

frameworkData, _ := json.Marshal(privatestate.Data{
Framework: map[string][]byte{
"frameworkKeyOne": []byte("framework value one"),
"frameworkKeyTwo": []byte("framework value two"),
},
})

providerData, _ := json.Marshal(privatestate.Data{
Provider: map[string][]byte{
"providerKeyOne": []byte("provider value one"),
"providerKeyTwo": []byte("provider value two"),
},
})

frameworkProviderData, _ := json.Marshal(privatestate.Data{
Framework: map[string][]byte{
"frameworkKeyOne": []byte("framework value one"),
"frameworkKeyTwo": []byte("framework value two"),
},
Provider: map[string][]byte{
"providerKeyOne": []byte("provider value one"),
"providerKeyTwo": []byte("provider value two"),
},
})

testCases := map[string]struct {
data privatestate.Data
expected []byte
expectedDiags diag.Diagnostics
}{
"empty": {
data: privatestate.Data{},
expected: empty,
expected: []byte(`{}`),
expectedDiags: diag.Diagnostics{},
},
"framework-data": {
data: privatestate.Data{
Framework: map[string][]byte{
"frameworkKeyOne": []byte("framework value one"),
"frameworkKeyTwo": []byte("framework value two"),
".frameworkKeyOne": []byte("framework value one"),
".frameworkKeyTwo": []byte("framework value two"),
},
},
expected: frameworkData,
expected: []byte(`{".frameworkKeyOne":"ZnJhbWV3b3JrIHZhbHVlIG9uZQ==",".frameworkKeyTwo":"ZnJhbWV3b3JrIHZhbHVlIHR3bw=="}`),
expectedDiags: diag.Diagnostics{},
},
"provider-data": {
Expand All @@ -68,20 +41,20 @@ func TestData_Bytes(t *testing.T) {
"providerKeyOne": []byte("provider value one"),
"providerKeyTwo": []byte("provider value two")},
},
expected: providerData,
expected: []byte(`{"providerKeyOne":"cHJvdmlkZXIgdmFsdWUgb25l","providerKeyTwo":"cHJvdmlkZXIgdmFsdWUgdHdv"}`),
expectedDiags: diag.Diagnostics{},
},
"framework-provider-data": {
data: privatestate.Data{
Framework: map[string][]byte{
"frameworkKeyOne": []byte("framework value one"),
"frameworkKeyTwo": []byte("framework value two"),
".frameworkKeyOne": []byte("framework value one"),
".frameworkKeyTwo": []byte("framework value two"),
},
Provider: map[string][]byte{
"providerKeyOne": []byte("provider value one"),
"providerKeyTwo": []byte("provider value two")},
},
expected: frameworkProviderData,
expected: []byte(`{".frameworkKeyOne":"ZnJhbWV3b3JrIHZhbHVlIG9uZQ==",".frameworkKeyTwo":"ZnJhbWV3b3JrIHZhbHVlIHR3bw==","providerKeyOne":"cHJvdmlkZXIgdmFsdWUgb25l","providerKeyTwo":"cHJvdmlkZXIgdmFsdWUgdHdv"}`),
expectedDiags: diag.Diagnostics{},
},
}
Expand Down Expand Up @@ -176,8 +149,9 @@ func TestProviderData_GetKey(t *testing.T) {
key: ".key",
expectedDiags: diag.Diagnostics{
diag.NewErrorDiagnostic(
"Restricted Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed",
"Restricted Resource Private State Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
),
},
},
Expand Down Expand Up @@ -228,8 +202,9 @@ func TestProviderData_SetKey(t *testing.T) {
key: ".key",
expected: diag.Diagnostics{
diag.NewErrorDiagnostic(
"Restricted Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed",
"Restricted Resource Private State Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
),
},
},
Expand All @@ -239,7 +214,8 @@ func TestProviderData_SetKey(t *testing.T) {
expected: diag.Diagnostics{
diag.NewErrorDiagnostic(
"UTF-8 Invalid",
"Values stored in private state must be valid UTF-8",
"Values stored in private state must be valid UTF-8\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
),
},
},
Expand All @@ -249,7 +225,8 @@ func TestProviderData_SetKey(t *testing.T) {
expected: diag.Diagnostics{
diag.NewErrorDiagnostic(
"JSON Invalid",
"Values stored in private state must be valid JSON",
"Values stored in private state must be valid JSON\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
),
},
},
Expand Down Expand Up @@ -282,8 +259,9 @@ func TestValidateProviderDataKey(t *testing.T) {
"namespace-restricted": {
key: ".restricted",
expected: diag.Diagnostics{diag.NewErrorDiagnostic(
"Restricted Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed",
"Restricted Resource Private State Namespace",
"Using a period ('.') as a prefix for a key used in private state is not allowed\n\n"+
"This is always a problem with Terraform or terraform-plugin-framework. Please report this to the provider developer.",
)},
},
"namespace-ok": {
Expand Down
3 changes: 3 additions & 0 deletions internal/privatestate/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package privatestate contains the type used for handling private resource
// state data.
package privatestate

0 comments on commit b73cbd9

Please sign in to comment.