Files
ziti/controller/persistence/identity_store_test.go
T
2020-06-17 13:49:20 -04:00

186 lines
5.7 KiB
Go

package persistence
import (
"fmt"
"github.com/openziti/edge/eid"
"github.com/openziti/foundation/storage/boltz"
"github.com/pkg/errors"
"go.etcd.io/bbolt"
"testing"
)
func Test_IdentityStore(t *testing.T) {
ctx := NewTestContext(t)
defer ctx.Cleanup()
ctx.Init()
t.Run("test identity service configs", ctx.testIdentityServiceConfigs)
}
func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) {
service := ctx.requireNewService(eid.New())
identity := ctx.requireNewIdentity(eid.New(), false)
clientConfigTypeId := ""
err := ctx.GetDb().Update(func(tx *bbolt.Tx) error {
clientConfigTypeId = string(ctx.stores.ConfigType.GetNameIndex().Read(tx, []byte("ziti-tunneler-client.v1")))
return nil
})
ctx.NoError(err)
serverConfigTypeId := ""
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
serverConfigTypeId = string(ctx.stores.ConfigType.GetNameIndex().Read(tx, []byte("ziti-tunneler-server.v1")))
return nil
})
ctx.NoError(err)
config := newConfig(eid.New(), clientConfigTypeId, map[string]interface{}{
"hostname": "foo.yourcompany.com",
"port": int64(22),
})
ctx.RequireCreate(config)
config2 := newConfig(eid.New(), clientConfigTypeId, map[string]interface{}{
"hostname": "bar.yourcompany.com",
"port": int64(23),
})
ctx.RequireCreate(config2)
config3 := newConfig(eid.New(), serverConfigTypeId, map[string]interface{}{
"hostname": "baz.yourcompany.com",
"port": int64(24),
})
ctx.RequireCreate(config3)
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
err := ctx.stores.Identity.AssignServiceConfigs(tx, identity.Id,
ServiceConfig{ServiceId: service.Id, ConfigId: config.Id},
ServiceConfig{ServiceId: service.Id, ConfigId: config2.Id})
ctx.EqualError(err, fmt.Sprintf("multiple service configs provided for identity %v of config type %v", identity.Id, clientConfigTypeId))
return nil
})
ctx.NoError(err)
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
err := ctx.stores.Identity.AssignServiceConfigs(tx, identity.Id, ServiceConfig{ServiceId: service.Id, ConfigId: config.Id})
ctx.NoError(err)
serviceConfigs := ctx.getServiceConfigs(tx, identity.Id, "all")
ctx.Equal(1, len(serviceConfigs))
serviceMap, ok := serviceConfigs[service.Id]
ctx.True(ok)
ctx.Equal(1, len(serviceMap))
_, ok = serviceMap[config.Type]
ctx.True(ok)
identityServices := ctx.getIdentityServices(tx, config.Id)
ctx.Equal(1, len(identityServices))
ctx.Equal(identity.Id, identityServices[0].identityId)
ctx.Equal(service.Id, identityServices[0].serviceId)
return nil
})
ctx.NoError(err)
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
err := ctx.stores.Identity.RemoveServiceConfigs(tx, identity.Id, ServiceConfig{ServiceId: service.Id, ConfigId: config.Id})
ctx.NoError(err)
serviceConfigs := ctx.getServiceConfigs(tx, identity.Id, "all")
ctx.Equal(0, len(serviceConfigs))
identityServices := ctx.getIdentityServices(tx, config.Id)
ctx.Equal(0, len(identityServices))
return nil
})
ctx.NoError(err)
ctx.RequireDelete(config)
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
serviceConfigs := ctx.getServiceConfigs(tx, identity.Id, "all")
ctx.Equal(0, len(serviceConfigs))
return nil
})
ctx.NoError(err)
ctx.RequireCreate(config)
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
err := ctx.stores.Identity.AssignServiceConfigs(tx, identity.Id,
ServiceConfig{ServiceId: service.Id, ConfigId: config.Id},
ServiceConfig{ServiceId: service.Id, ConfigId: config3.Id})
ctx.NoError(err)
serviceConfigs := ctx.getServiceConfigs(tx, identity.Id, "all")
ctx.Equal(1, len(serviceConfigs))
serviceMap, ok := serviceConfigs[service.Id]
ctx.True(ok)
ctx.Equal(2, len(serviceMap))
_, ok = serviceMap[config.Type]
ctx.True(ok)
_, ok = serviceMap[config3.Type]
ctx.True(ok)
serviceConfigs = ctx.getServiceConfigs(tx, identity.Id, serverConfigTypeId)
ctx.Equal(1, len(serviceConfigs))
serviceMap, ok = serviceConfigs[service.Id]
ctx.True(ok)
ctx.Equal(1, len(serviceMap))
_, ok = serviceMap[config3.Type]
ctx.True(ok)
identityServices := ctx.getIdentityServices(tx, config.Id)
ctx.Equal(1, len(identityServices))
ctx.Equal(identity.Id, identityServices[0].identityId)
ctx.Equal(service.Id, identityServices[0].serviceId)
return nil
})
ctx.NoError(err)
ctx.RequireDelete(identity)
err = ctx.GetDb().Update(func(tx *bbolt.Tx) error {
identityServices := ctx.getIdentityServices(tx, config.Id)
ctx.Equal(0, len(identityServices))
identityServices = ctx.getIdentityServices(tx, config3.Id)
ctx.Equal(0, len(identityServices))
return nil
})
ctx.NoError(err)
}
func (ctx *TestContext) getIdentityServices(tx *bbolt.Tx, configId string) []testIdentityServices {
var result []testIdentityServices
identityServiceSymbol := ctx.stores.Config.GetSymbol(FieldConfigIdentityService).(boltz.EntitySetSymbol)
err := identityServiceSymbol.Map(tx, []byte(configId), func(ctx *boltz.MapContext) {
decoded, err := boltz.DecodeStringSlice(ctx.Value())
if err != nil {
ctx.SetError(err)
return
}
if len(decoded) != 2 {
ctx.SetError(errors.Errorf("expected 2 fields, got %v", len(decoded)))
}
result = append(result, testIdentityServices{identityId: decoded[0], serviceId: decoded[1]})
})
ctx.NoError(err)
return result
}
func (ctx *TestContext) getServiceConfigs(tx *bbolt.Tx, identityId string, configTypes ...string) map[string]map[string]map[string]interface{} {
configTypeMap := map[string]struct{}{}
for _, configType := range configTypes {
configTypeMap[configType] = struct{}{}
}
return ctx.stores.Identity.LoadServiceConfigsByServiceAndType(tx, identityId, configTypeMap)
}
type testIdentityServices struct {
identityId string
serviceId string
}