fix(db): fix marshalling code so that we're compatible with the existing db (#6286)

* special handling for non-json types

* added tests for json MarshalObject

* another attempt

* Fix marshal/unmarshal code for VERSION bucket

* use short form

* don't discard err

* fix the json_test.go

* remove duplicate string

* added uuid tests

* updated case for strings

Co-authored-by: zees-dev <dev.786zshan@gmail.com>
pull/6295/head
Matt Hook 3 years ago committed by GitHub
parent 187b66f5cb
commit 33a29159d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,12 +8,29 @@ import (
// MarshalObject encodes an object to binary format // MarshalObject encodes an object to binary format
func MarshalObject(object interface{}) ([]byte, error) { func MarshalObject(object interface{}) ([]byte, error) {
// Special case for the VERSION bucket. Here we're not using json
if v, ok := object.(string); ok {
return []byte(v), nil
}
return json.Marshal(object) return json.Marshal(object)
} }
// UnmarshalObject decodes an object from binary data // UnmarshalObject decodes an object from binary data
func UnmarshalObject(data []byte, object interface{}) error { func UnmarshalObject(data []byte, object interface{}) error {
return json.Unmarshal(data, object) // Special case for the VERSION bucket. Here we're not using json
// So we need to return it as a string
err := json.Unmarshal(data, object)
if err != nil {
if s, ok := object.(*string); ok {
*s = string(data)
return nil
}
return err
}
return nil
} }
// UnmarshalObjectWithJsoniter decodes an object from binary data // UnmarshalObjectWithJsoniter decodes an object from binary data

@ -0,0 +1,122 @@
package boltdb
import (
"fmt"
"testing"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
)
const jsonobject = `{"LogoURL":"","BlackListedLabels":[],"AuthenticationMethod":1,"LDAPSettings":{"AnonymousMode":true,"ReaderDN":"","URL":"","TLSConfig":{"TLS":false,"TLSSkipVerify":false},"StartTLS":false,"SearchSettings":[{"BaseDN":"","Filter":"","UserNameAttribute":""}],"GroupSearchSettings":[{"GroupBaseDN":"","GroupFilter":"","GroupAttribute":""}],"AutoCreateUsers":true},"OAuthSettings":{"ClientID":"","AccessTokenURI":"","AuthorizationURI":"","ResourceURI":"","RedirectURI":"","UserIdentifier":"","Scopes":"","OAuthAutoCreateUsers":false,"DefaultTeamID":0,"SSO":true,"LogoutURI":"","KubeSecretKey":"j0zLVtY/lAWBk62ByyF0uP80SOXaitsABP0TTJX8MhI="},"OpenAMTConfiguration":{"Enabled":false,"MPSServer":"","Credentials":{"MPSUser":"","MPSPassword":"","MPSToken":""},"DomainConfiguration":{"CertFileText":"","CertPassword":"","DomainName":""},"WirelessConfiguration":null},"FeatureFlagSettings":{},"SnapshotInterval":"5m","TemplatesURL":"https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json","EdgeAgentCheckinInterval":5,"EnableEdgeComputeFeatures":false,"UserSessionTimeout":"8h","KubeconfigExpiry":"0","EnableTelemetry":true,"HelmRepositoryURL":"https://charts.bitnami.com/bitnami","KubectlShellImage":"portainer/kubectl-shell","DisplayDonationHeader":false,"DisplayExternalContributors":false,"EnableHostManagementFeatures":false,"AllowVolumeBrowserForRegularUsers":false,"AllowBindMountsForRegularUsers":false,"AllowPrivilegedModeForRegularUsers":false,"AllowHostNamespaceForRegularUsers":false,"AllowStackManagementForRegularUsers":false,"AllowDeviceMappingForRegularUsers":false,"AllowContainerCapabilitiesForRegularUsers":false}`
func Test_MarshalObject(t *testing.T) {
is := assert.New(t)
uuid := uuid.Must(uuid.NewV4())
tests := []struct {
object interface{}
expected string
}{
{
object: nil,
expected: `null`,
},
{
object: true,
expected: `true`,
},
{
object: false,
expected: `false`,
},
{
object: 123,
expected: `123`,
},
{
object: "456",
expected: "456",
},
{
object: uuid,
expected: "\"" + uuid.String() + "\"",
},
{
object: uuid.String(),
expected: uuid.String(),
},
{
object: map[string]interface{}{"key": "value"},
expected: `{"key":"value"}`,
},
{
object: []bool{true, false},
expected: `[true,false]`,
},
{
object: []int{1, 2, 3},
expected: `[1,2,3]`,
},
{
object: []string{"1", "2", "3"},
expected: `["1","2","3"]`,
},
{
object: []map[string]interface{}{{"key1": "value1"}, {"key2": "value2"}},
expected: `[{"key1":"value1"},{"key2":"value2"}]`,
},
{
object: []interface{}{1, "2", false, map[string]interface{}{"key1": "value1"}},
expected: `[1,"2",false,{"key1":"value1"}]`,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%s -> %s", test.object, test.expected), func(t *testing.T) {
data, err := MarshalObject(test.object)
is.NoError(err)
is.Equal(test.expected, string(data))
})
}
}
func Test_UnMarshalObject(t *testing.T) {
is := assert.New(t)
// Based on actual data entering and what we expect out of the function
tests := []struct {
object []byte
expected string
}{
{
object: []byte(""),
expected: "",
},
{
object: []byte("35"),
expected: "35",
},
{
// An unmarshalled byte string should return the same without error
object: []byte("9ca4a1dd-a439-4593-b386-a7dfdc2e9fc6"),
expected: "9ca4a1dd-a439-4593-b386-a7dfdc2e9fc6",
},
{
// An unmarshalled json object string should return the same as a string without error also
object: []byte(jsonobject),
expected: jsonobject,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%s -> %s", test.object, test.expected), func(t *testing.T) {
var object string
err := UnmarshalObject(test.object, &object)
is.NoError(err)
is.Equal(test.expected, string(object))
})
}
}
Loading…
Cancel
Save