Skip to content

Commit

Permalink
add licenses in kong state and sync diff
Browse files Browse the repository at this point in the history
  • Loading branch information
randmonkey committed Feb 21, 2024
1 parent db31fc4 commit 151cdba
Show file tree
Hide file tree
Showing 8 changed files with 598 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pkg/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func (sc *Syncer) init() error {
types.HMACAuth, types.JWTAuth, types.OAuth2Cred,
types.MTLSAuth,

types.Vault,
types.Vault, types.License,

types.RBACRole, types.RBACEndpointPermission,

Expand Down
146 changes: 146 additions & 0 deletions pkg/state/license.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package state

import (
"errors"
"fmt"

memdb "github.com/hashicorp/go-memdb"
"github.com/kong/go-database-reconciler/pkg/utils"
)

const (
licenseTableName = "license"
)

var licenseTableSchema = &memdb.TableSchema{
Name: licenseTableName,
Indexes: map[string]*memdb.IndexSchema{
"id": {
Name: "id",
Unique: true,
Indexer: &memdb.StringFieldIndex{Field: "ID"},
},
all: allIndex,
},
}

type LicensesCollection collection

func getLicense(txn *memdb.Txn, id string) (*License, error) {
res, err := multiIndexLookupUsingTxn(txn, licenseTableName, []string{"id"}, id)
if err != nil {
return nil, err
}
l, ok := res.(*License)
if !ok {
panic(unexpectedType)
}
return &License{License: *l.DeepCopy()}, nil
}

func (k *LicensesCollection) Add(l License) error {
if utils.Empty(l.ID) {
return errIDRequired
}
txn := k.db.Txn(true)
defer txn.Abort()

_, err := getLicense(txn, *l.ID)
if err == nil {
return fmt.Errorf("inserting license %v: %w", l.Console(), ErrAlreadyExists)
}
if !errors.Is(err, ErrNotFound) {
return err
}
err = txn.Insert(licenseTableName, &l)
if err != nil {
return err
}
txn.Commit()
return nil
}

func (k *LicensesCollection) Get(id string) (*License, error) {
if id == "" {
return nil, errIDRequired
}
txn := k.db.Txn(false)
defer txn.Abort()

l, err := getLicense(txn, id)

if err != nil {
if errors.Is(err, ErrNotFound) {
return nil, ErrNotFound
}
return nil, err
}
txn.Commit()
return l, nil
}

func deleteLicense(txn *memdb.Txn, id string) error {
l, err := getLicense(txn, id)
if err != nil {
return err
}

return txn.Delete(licenseTableName, l)
}

func (k *LicensesCollection) Update(l License) error {
if utils.Empty(l.ID) {
return errIDRequired
}
txn := k.db.Txn(true)
defer txn.Abort()

err := deleteLicense(txn, *l.ID)
if err != nil {
return err
}

err = txn.Insert(licenseTableName, &l)
if err != nil {
return err
}
txn.Commit()
return nil
}

func (k *LicensesCollection) Delete(id string) error {
if id == "" {
return errIDRequired
}
txn := k.db.Txn(true)
defer txn.Abort()

err := deleteLicense(txn, id)
if err != nil {
return err
}

txn.Commit()
return err
}

func (k *LicensesCollection) GetAll() ([]*License, error) {
txn := k.db.Txn(false)
defer txn.Abort()
iter, err := txn.Get(licenseTableName, all, true)
if err != nil {
return nil, err
}

var res []*License
for el := iter.Next(); el != nil; el = iter.Next() {
l, ok := el.(*License)
if !ok {
panic(unexpectedType)
}
res = append(res, &License{License: *l.DeepCopy()})
}
txn.Commit()
return res, nil

}
220 changes: 220 additions & 0 deletions pkg/state/license_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package state

import (
"testing"

"github.com/kong/go-kong/kong"
"github.com/stretchr/testify/assert"
)

var presetLicense = License{
License: kong.License{
ID: kong.String("license-preset"),
Payload: kong.String("preset-license-payload"),
},
}

func TestLicenseCollection_Add(t *testing.T) {
testCases := []struct {
name string
license *License
expectedError error
}{
{
name: "insert with no ID",
license: &License{
License: kong.License{},
},
expectedError: errIDRequired,
},
{
name: "insert with ID and payload",
license: &License{
License: kong.License{
ID: kong.String("1234"),
Payload: kong.String("license-test"),
},
},
},
{
name: "insert a license with existing ID",
license: &License{
License: kong.License{
ID: kong.String("license-preset"),
Payload: kong.String("license-test"),
},
},
expectedError: ErrAlreadyExists,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
initialState := state()
c := initialState.Licenses
err := c.Add(presetLicense)
assert.NoError(t, err)

err = c.Add(*tc.license)
if tc.expectedError != nil {
assert.ErrorAs(t, err, &tc.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}

func TestLicenseCollection_Get(t *testing.T) {
testCases := []struct {
name string
id string
expectedPayload string
expectedError error
}{
{
name: "get existing license",
id: "license-preset",
expectedPayload: "preset-license-payload",
},
{
name: "get non existing license",
id: "license-non-exist",
expectedError: ErrNotFound,
},
{
name: "get with empty ID",
id: "",
expectedError: errIDRequired,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
initialState := state()
c := initialState.Licenses
err := c.Add(presetLicense)
assert.NoError(t, err)

l, err := c.Get(tc.id)
if tc.expectedError == nil {
assert.NoError(t, err)
assert.Equal(t, tc.id, *l.ID)
assert.Equal(t, tc.expectedPayload, *l.Payload)
} else {
assert.ErrorAs(t, err, &tc.expectedError)
}
})
}
}

func TestLicenseCollection_Update(t *testing.T) {
testCases := []struct {
name string
license License
expectedError error
}{
{
name: "update with no ID",
license: License{},
expectedError: errIDRequired,
},
{
name: "update non existing license",
license: License{
License: kong.License{
ID: kong.String("license-non-exist"),
Payload: kong.String("updated-payload"),
},
},
expectedError: ErrNotFound,
},
{
name: "update existing license",
license: License{
License: kong.License{
ID: kong.String("license-preset"),
Payload: kong.String("updated-payload"),
},
},
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
initialState := state()
c := initialState.Licenses
err := c.Add(presetLicense)
assert.NoError(t, err)

err = c.Update(tc.license)
if tc.expectedError == nil {
assert.NoError(t, err)
updatedLicense, err := c.Get(*tc.license.ID)
assert.NoError(t, err)
assert.Equal(t, *tc.license.Payload, *updatedLicense.Payload)
} else {
assert.ErrorAs(t, err, &tc.expectedError)
}
})
}
}

func TestLicenseCollection_Delete(t *testing.T) {
testCases := []struct {
name string
id string
expectedError error
}{
{
name: "delete with no ID",
id: "",
expectedError: errIDRequired,
},
{
name: "delete non existing license",
id: "license-non-exist",
expectedError: ErrNotFound,
},
{
name: "delete existing license",
id: "license-preset",
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
initialState := state()
c := initialState.Licenses
err := c.Add(presetLicense)
assert.NoError(t, err)

err = c.Delete(tc.id)
if tc.expectedError == nil {
assert.NoError(t, err)
} else {
assert.ErrorAs(t, err, &tc.expectedError)
}
})
}
}

func TestLicenseCollection_GetAll(t *testing.T) {
initialState := state()
c := initialState.Licenses
licenses, err := c.GetAll()
assert.NoError(t, err)
assert.Len(t, licenses, 0, "Should have no licenses")

err = c.Add(presetLicense)
assert.NoError(t, err)

licenses, err = c.GetAll()
assert.NoError(t, err)
assert.Len(t, licenses, 1, "Should have 1 license after adding")

}
Loading

0 comments on commit 151cdba

Please sign in to comment.