-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add licenses in kong state and sync diff
- Loading branch information
1 parent
db31fc4
commit 151cdba
Showing
8 changed files
with
598 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
|
||
} |
Oops, something went wrong.