mirror of
https://github.com/openziti/ziti.git
synced 2026-10-12 15:28:05 +00:00
310 lines
8.8 KiB
Go
310 lines
8.8 KiB
Go
/*
|
|
Copyright NetFoundry, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package db
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/google/uuid"
|
|
"github.com/openziti/fabric/controller/xt"
|
|
"github.com/openziti/foundation/storage/boltz"
|
|
"github.com/openziti/foundation/util/stringz"
|
|
"go.etcd.io/bbolt"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func Test_TerminatorStore(t *testing.T) {
|
|
ctx := NewTestContext(t)
|
|
defer ctx.Cleanup()
|
|
|
|
xt.GlobalRegistry().RegisterFactory(&testStrategyFactory{})
|
|
|
|
t.Run("test create invalid terminators", ctx.testCreateInvalidTerminators)
|
|
t.Run("test create/delete terminators", ctx.testCreateTerminators)
|
|
t.Run("test create/delete terminators", ctx.testLoadQueryTerminators)
|
|
t.Run("test update terminators", ctx.testUpdateTerminators)
|
|
t.Run("test delete terminators", ctx.testDeleteTerminators)
|
|
t.Run("test patch terminators", ctx.testPatchTerminator)
|
|
}
|
|
|
|
func (ctx *TestContext) testCreateInvalidTerminators(t *testing.T) {
|
|
ctx.NextTest(t)
|
|
defer ctx.cleanupAll()
|
|
|
|
terminator := &Terminator{
|
|
Binding: uuid.New().String(),
|
|
Address: uuid.New().String(),
|
|
Service: uuid.New().String(),
|
|
Router: uuid.New().String(),
|
|
}
|
|
err := ctx.Update(terminator)
|
|
ctx.EqualError(err, "cannot update terminator with blank id")
|
|
|
|
terminator.Binding = ""
|
|
err = ctx.Create(terminator)
|
|
ctx.EqualError(err, "the value '' for 'binding' is invalid: binding is required")
|
|
|
|
terminator.Binding = uuid.New().String()
|
|
terminator.Address = ""
|
|
err = ctx.Create(terminator)
|
|
ctx.EqualError(err, "the value '' for 'address' is invalid: address is required")
|
|
|
|
terminator.Router = ""
|
|
terminator.Address = uuid.New().String()
|
|
err = ctx.Create(terminator)
|
|
ctx.EqualError(err, "the value '' for 'router' is invalid: router is required")
|
|
|
|
terminator.Service = ""
|
|
terminator.Router = uuid.New().String()
|
|
err = ctx.Create(terminator)
|
|
ctx.EqualError(err, "the value '' for 'service' is invalid: service is required")
|
|
|
|
service := ctx.requireNewService()
|
|
router := ctx.requireNewRouter()
|
|
|
|
terminator.Service = uuid.New().String()
|
|
terminator.Router = router.Id
|
|
err = ctx.Create(terminator)
|
|
ctx.EqualError(err, fmt.Sprintf("service with id %v not found", terminator.Service))
|
|
|
|
terminator.Service = service.Id
|
|
terminator.Router = uuid.New().String()
|
|
err = ctx.Create(terminator)
|
|
ctx.EqualError(err, fmt.Sprintf("router with id %v not found", terminator.Router))
|
|
}
|
|
|
|
type terminatorTestEntities struct {
|
|
service *Service
|
|
service2 *Service
|
|
|
|
router *Router
|
|
router2 *Router
|
|
|
|
terminator *Terminator
|
|
terminator2 *Terminator
|
|
terminator3 *Terminator
|
|
}
|
|
|
|
func (ctx *TestContext) createTestTerminators() *terminatorTestEntities {
|
|
e := &terminatorTestEntities{}
|
|
|
|
e.service = ctx.requireNewService()
|
|
e.router = ctx.requireNewRouter()
|
|
|
|
e.terminator = &Terminator{}
|
|
e.terminator.Service = e.service.Id
|
|
e.terminator.Router = e.router.Id
|
|
e.terminator.Binding = uuid.New().String()
|
|
e.terminator.Address = uuid.New().String()
|
|
e.terminator.Cost = 0
|
|
ctx.RequireCreate(e.terminator)
|
|
|
|
e.router2 = ctx.requireNewRouter()
|
|
|
|
e.terminator2 = &Terminator{}
|
|
e.terminator2.Service = e.service.Id
|
|
e.terminator2.Router = e.router2.Id
|
|
e.terminator2.Binding = uuid.New().String()
|
|
e.terminator2.Address = uuid.New().String()
|
|
e.terminator2.Cost = 100
|
|
ctx.RequireCreate(e.terminator2)
|
|
|
|
e.service2 = ctx.requireNewService()
|
|
|
|
e.terminator3 = &Terminator{}
|
|
e.terminator3.Service = e.service2.Id
|
|
e.terminator3.Router = e.router2.Id
|
|
e.terminator3.Binding = uuid.New().String()
|
|
e.terminator3.Address = uuid.New().String()
|
|
e.terminator3.Cost = math.MaxUint16
|
|
ctx.RequireCreate(e.terminator3)
|
|
|
|
return e
|
|
}
|
|
|
|
func (ctx *TestContext) testCreateTerminators(t *testing.T) {
|
|
ctx.NextTest(t)
|
|
defer ctx.cleanupAll()
|
|
|
|
e := ctx.createTestTerminators()
|
|
|
|
ctx.ValidateBaseline(e.terminator)
|
|
ctx.ValidateBaseline(e.terminator2)
|
|
ctx.ValidateBaseline(e.terminator3)
|
|
|
|
terminatorIds := ctx.GetRelatedIds(e.service, EntityTypeTerminators)
|
|
ctx.EqualValues(2, len(terminatorIds))
|
|
ctx.True(stringz.Contains(terminatorIds, e.terminator.Id))
|
|
ctx.True(stringz.Contains(terminatorIds, e.terminator2.Id))
|
|
|
|
terminatorIds = ctx.GetRelatedIds(e.router, EntityTypeTerminators)
|
|
ctx.EqualValues(1, len(terminatorIds))
|
|
ctx.EqualValues(e.terminator.Id, terminatorIds[0])
|
|
|
|
terminatorIds = ctx.GetRelatedIds(e.router2, EntityTypeTerminators)
|
|
ctx.EqualValues(2, len(terminatorIds))
|
|
ctx.True(stringz.Contains(terminatorIds, e.terminator2.Id))
|
|
ctx.True(stringz.Contains(terminatorIds, e.terminator3.Id))
|
|
|
|
terminatorIds = ctx.GetRelatedIds(e.service2, EntityTypeTerminators)
|
|
ctx.EqualValues(1, len(terminatorIds))
|
|
ctx.EqualValues(e.terminator3.Id, terminatorIds[0])
|
|
|
|
}
|
|
|
|
func (ctx *TestContext) testLoadQueryTerminators(t *testing.T) {
|
|
ctx.NextTest(t)
|
|
defer ctx.cleanupAll()
|
|
|
|
e := ctx.createTestTerminators()
|
|
|
|
err := ctx.GetDb().View(func(tx *bbolt.Tx) error {
|
|
loadedTerminator, err := ctx.stores.Terminator.LoadOneById(tx, e.terminator.Id)
|
|
ctx.NoError(err)
|
|
ctx.NotNil(loadedTerminator)
|
|
ctx.EqualValues(e.terminator.Id, loadedTerminator.Id)
|
|
ctx.EqualValues(e.terminator.Service, loadedTerminator.Service)
|
|
ctx.EqualValues(e.terminator.Router, loadedTerminator.Router)
|
|
ctx.EqualValues(e.terminator.Binding, loadedTerminator.Binding)
|
|
ctx.EqualValues(e.terminator.Address, loadedTerminator.Address)
|
|
ctx.EqualValues(e.terminator.Cost, loadedTerminator.Cost)
|
|
|
|
ids, _, err := ctx.stores.Terminator.QueryIdsf(tx, `service = "%v"`, e.service.Id)
|
|
ctx.NoError(err)
|
|
ctx.EqualValues(2, len(ids))
|
|
ctx.True(stringz.Contains(ids, e.terminator.Id))
|
|
ctx.True(stringz.Contains(ids, e.terminator2.Id))
|
|
|
|
ids, _, err = ctx.stores.Terminator.QueryIdsf(tx, `router = "%v"`, e.router2.Id)
|
|
ctx.NoError(err)
|
|
ctx.EqualValues(2, len(ids))
|
|
ctx.True(stringz.Contains(ids, e.terminator2.Id))
|
|
ctx.True(stringz.Contains(ids, e.terminator3.Id))
|
|
|
|
ids, _, err = ctx.stores.Service.QueryIdsf(tx, `anyOf(terminators) = "%v"`, e.terminator.Id)
|
|
ctx.NoError(err)
|
|
ctx.EqualValues(1, len(ids))
|
|
ctx.True(stringz.Contains(ids, e.service.Id))
|
|
|
|
ids, _, err = ctx.stores.Router.QueryIdsf(tx, `anyOf(terminators) = "%v"`, e.terminator.Id)
|
|
ctx.NoError(err)
|
|
ctx.EqualValues(1, len(ids))
|
|
ctx.True(stringz.Contains(ids, e.router.Id))
|
|
|
|
return nil
|
|
})
|
|
ctx.NoError(err)
|
|
}
|
|
|
|
func (ctx *TestContext) testUpdateTerminators(t *testing.T) {
|
|
ctx.NextTest(t)
|
|
defer ctx.cleanupAll()
|
|
|
|
e := ctx.createTestTerminators()
|
|
|
|
terminator := e.terminator
|
|
ctx.RequireReload(terminator)
|
|
|
|
time.Sleep(time.Millisecond * 10) // ensure updatedAt is after createdAt
|
|
|
|
terminator.Service = e.service2.Id
|
|
terminator.Router = e.router2.Id
|
|
terminator.Binding = uuid.New().String()
|
|
terminator.Address = uuid.New().String()
|
|
terminator.Tags = ctx.CreateTags()
|
|
ctx.RequireUpdate(terminator)
|
|
|
|
terminator.Service = e.service.Id // service should not be updated
|
|
ctx.ValidateUpdated(terminator)
|
|
|
|
}
|
|
|
|
func (ctx *TestContext) testDeleteTerminators(t *testing.T) {
|
|
ctx.NextTest(t)
|
|
defer ctx.cleanupAll()
|
|
|
|
e := ctx.createTestTerminators()
|
|
|
|
ctx.RequireDelete(e.terminator3)
|
|
ctx.RequireDelete(e.router2)
|
|
|
|
ctx.ValidateDeleted(e.terminator2.Id)
|
|
ctx.ValidateDeleted(e.terminator3.Id)
|
|
|
|
ctx.RequireDelete(e.service)
|
|
ctx.ValidateDeleted(e.terminator.Id)
|
|
}
|
|
|
|
func (ctx *TestContext) testPatchTerminator(t *testing.T) {
|
|
service := ctx.requireNewService()
|
|
router := ctx.requireNewRouter()
|
|
|
|
terminator := &Terminator{}
|
|
terminator.Service = service.Id
|
|
terminator.Router = router.Id
|
|
terminator.Binding = uuid.New().String()
|
|
terminator.Address = uuid.New().String()
|
|
terminator.Cost = 0
|
|
terminator.PeerData = map[uint32][]byte{
|
|
1: {1, 2, 3},
|
|
2: {3, 4, 5},
|
|
}
|
|
ctx.RequireCreate(terminator)
|
|
ctx.ValidateBaseline(terminator)
|
|
|
|
terminator.Cost = 100
|
|
checker := boltz.MapFieldChecker{
|
|
FieldTerminatorCost: struct{}{},
|
|
}
|
|
ctx.RequirePatch(terminator, checker)
|
|
ctx.ValidateUpdated(terminator)
|
|
|
|
terminator.PeerData = map[uint32][]byte{
|
|
1: {7, 8, 9},
|
|
}
|
|
|
|
checker = boltz.MapFieldChecker{
|
|
FieldServerPeerData: struct{}{},
|
|
}
|
|
ctx.RequirePatch(terminator, checker)
|
|
ctx.ValidateUpdated(terminator)
|
|
}
|
|
|
|
type testStrategyFactory struct{}
|
|
|
|
func (t testStrategyFactory) GetStrategyName() string {
|
|
return "smartrouting"
|
|
}
|
|
|
|
func (t testStrategyFactory) NewStrategy() xt.Strategy {
|
|
return &testStrategy{}
|
|
}
|
|
|
|
type testStrategy struct{}
|
|
|
|
func (t testStrategy) Select(terminators []xt.CostedTerminator) (xt.Terminator, error) {
|
|
return terminators[0], nil
|
|
}
|
|
|
|
func (t testStrategy) HandleTerminatorChange(xt.StrategyChangeEvent) error {
|
|
return nil
|
|
}
|
|
|
|
func (t testStrategy) NotifyEvent(xt.TerminatorEvent) {
|
|
}
|