mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
Fix: Index structure map[string]string,Mongo resulting in inconsistent results obtained by filtering non-string type by index. (#5274)
Signed-off-by: old.prince <di7zhang@gmail.com> Signed-off-by: old.prince <di7zhang@gmail.com>
This commit is contained in:
@@ -59,8 +59,8 @@ func (a *Application) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *Application) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *Application) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Name != "" {
|
||||
index["name"] = a.Name
|
||||
}
|
||||
@@ -154,8 +154,8 @@ func (a *ApplicationComponent) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *ApplicationComponent) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *ApplicationComponent) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Name != "" {
|
||||
index["name"] = a.Name
|
||||
}
|
||||
@@ -202,8 +202,8 @@ func (a *ApplicationPolicy) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *ApplicationPolicy) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *ApplicationPolicy) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Name != "" {
|
||||
index["name"] = a.Name
|
||||
}
|
||||
@@ -348,8 +348,8 @@ func (a *ApplicationRevision) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *ApplicationRevision) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *ApplicationRevision) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Version != "" {
|
||||
index["version"] = a.Version
|
||||
}
|
||||
@@ -434,8 +434,8 @@ func (w *ApplicationTrigger) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (w *ApplicationTrigger) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (w *ApplicationTrigger) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if w.AppPrimaryKey != "" {
|
||||
index["appPrimaryKey"] = w.AppPrimaryKey
|
||||
}
|
||||
|
||||
@@ -93,8 +93,8 @@ func (c *Cluster) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index set to nil for list
|
||||
func (c *Cluster) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (c *Cluster) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if c.Name != "" {
|
||||
index["name"] = c.Name
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ func (p *Env) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Env) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *Env) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ func (e *EnvBinding) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (e *EnvBinding) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (e *EnvBinding) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if e.Name != "" {
|
||||
index["name"] = e.Name
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ func (p Pipeline) ShortTableName() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p Pipeline) Index() map[string]string {
|
||||
var index = make(map[string]string)
|
||||
func (p Pipeline) Index() map[string]interface{} {
|
||||
var index = make(map[string]interface{})
|
||||
if p.Project != "" {
|
||||
index["project"] = p.Project
|
||||
}
|
||||
@@ -102,8 +102,8 @@ func (c *PipelineContext) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (c *PipelineContext) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (c *PipelineContext) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if c.ProjectName != "" {
|
||||
index["project_name"] = c.ProjectName
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ func (p *Project) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Project) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *Project) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
|
||||
@@ -146,8 +146,8 @@ func (u *SystemInfo) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (u *SystemInfo) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (u *SystemInfo) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if u.InstallID != "" {
|
||||
index["installID"] = u.InstallID
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ func (d *Target) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (d *Target) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (d *Target) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if d.Name != "" {
|
||||
index["name"] = d.Name
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ func (u *User) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (u *User) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (u *User) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if u.Name != "" {
|
||||
index["name"] = u.Name
|
||||
}
|
||||
@@ -106,8 +106,8 @@ func (u *ProjectUser) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (u *ProjectUser) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (u *ProjectUser) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if u.Username != "" {
|
||||
index["username"] = u.Username
|
||||
}
|
||||
@@ -177,8 +177,8 @@ func (r *Role) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (r *Role) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (r *Role) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if r.Name != "" {
|
||||
index["name"] = r.Name
|
||||
}
|
||||
@@ -207,8 +207,8 @@ func (p *Permission) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Permission) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *Permission) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
@@ -250,8 +250,8 @@ func (p *PermissionTemplate) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *PermissionTemplate) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *PermissionTemplate) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
@@ -88,8 +87,8 @@ func (w *Workflow) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom primary key
|
||||
func (w *Workflow) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (w *Workflow) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if w.Name != "" {
|
||||
index["name"] = w.Name
|
||||
}
|
||||
@@ -100,7 +99,7 @@ func (w *Workflow) Index() map[string]string {
|
||||
index["envName"] = w.EnvName
|
||||
}
|
||||
if w.Default != nil {
|
||||
index["default"] = strconv.FormatBool(*w.Default)
|
||||
index["default"] = *w.Default
|
||||
}
|
||||
|
||||
return index
|
||||
@@ -161,8 +160,8 @@ func (w *WorkflowRecord) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom primary key
|
||||
func (w *WorkflowRecord) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (w *WorkflowRecord) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if w.Name != "" {
|
||||
index["name"] = w.Name
|
||||
}
|
||||
|
||||
@@ -866,8 +866,8 @@ func (w *workflowServiceImpl) RollbackRecord(ctx context.Context, appModel *mode
|
||||
if len(revisions) == 0 {
|
||||
return nil, bcode.ErrApplicationNoReadyRevision
|
||||
}
|
||||
revisionVersion = revisions[0].Index()["version"]
|
||||
klog.Infof("select lastest complete revision %s", revisions[0].Index()["version"])
|
||||
revisionVersion = pkgUtils.ToString(revisions[0].Index()["version"])
|
||||
klog.Infof("select lastest complete revision %s", revisionVersion)
|
||||
}
|
||||
|
||||
var record = &model.WorkflowRecord{
|
||||
|
||||
@@ -74,7 +74,7 @@ type Entity interface {
|
||||
PrimaryKey() string
|
||||
TableName() string
|
||||
ShortTableName() string
|
||||
Index() map[string]string
|
||||
Index() map[string]interface{}
|
||||
}
|
||||
|
||||
// NewEntity Create a new object based on the input type
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
|
||||
pkgUtils "github.com/oam-dev/kubevela/pkg/utils"
|
||||
)
|
||||
|
||||
type kubeapi struct {
|
||||
@@ -81,7 +82,7 @@ func generateName(entity datastore.Entity) string {
|
||||
|
||||
func (m *kubeapi) generateConfigMap(entity datastore.Entity) *corev1.ConfigMap {
|
||||
data, _ := json.Marshal(entity)
|
||||
labels := entity.Index()
|
||||
labels := convertIndex2Labels(entity.Index())
|
||||
if labels == nil {
|
||||
labels = make(map[string]string)
|
||||
}
|
||||
@@ -176,7 +177,7 @@ func (m *kubeapi) Put(ctx context.Context, entity datastore.Entity) error {
|
||||
return datastore.ErrTableNameEmpty
|
||||
}
|
||||
// update labels
|
||||
labels := entity.Index()
|
||||
labels := convertIndex2Labels(entity.Index())
|
||||
if labels == nil {
|
||||
labels = make(map[string]string)
|
||||
}
|
||||
@@ -350,8 +351,8 @@ func (m *kubeapi) List(ctx context.Context, entity datastore.Entity, op *datasto
|
||||
|
||||
rq, _ := labels.NewRequirement(MigrateKey, selection.DoesNotExist, []string{"ok"})
|
||||
selector = selector.Add(*rq)
|
||||
|
||||
for k, v := range entity.Index() {
|
||||
metedataLabels := convertIndex2Labels(entity.Index())
|
||||
for k, v := range metedataLabels {
|
||||
rq, err := labels.NewRequirement(k, selection.Equals, []string{verifyValue(v)})
|
||||
if err != nil {
|
||||
return nil, datastore.ErrIndexInvalid
|
||||
@@ -441,7 +442,8 @@ func (m *kubeapi) Count(ctx context.Context, entity datastore.Entity, filterOpti
|
||||
if err != nil {
|
||||
return 0, datastore.NewDBError(err)
|
||||
}
|
||||
for k, v := range entity.Index() {
|
||||
metedataLabels := convertIndex2Labels(entity.Index())
|
||||
for k, v := range metedataLabels {
|
||||
rq, err := labels.NewRequirement(k, selection.Equals, []string{verifyValue(v)})
|
||||
if err != nil {
|
||||
return 0, datastore.ErrIndexInvalid
|
||||
@@ -494,3 +496,19 @@ func verifyValue(v string) string {
|
||||
s = strings.ReplaceAll(s, " ", "-")
|
||||
return strings.ToLower(s)
|
||||
}
|
||||
|
||||
func convertIndex2Labels(index map[string]interface{}) map[string]string {
|
||||
if index == nil {
|
||||
return nil
|
||||
}
|
||||
ret := make(map[string]string, len(index))
|
||||
for k, v := range index {
|
||||
value := pkgUtils.ToString(v)
|
||||
if value == "" {
|
||||
klog.Warningf("unable to cast %#v of type %T to string", v, v)
|
||||
continue
|
||||
}
|
||||
ret[k] = pkgUtils.ToString(v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -72,20 +72,38 @@ var _ = Describe("Test kubeapi datastore driver", func() {
|
||||
err := kubeStore.Put(context.TODO(), &model.Application{Name: "kubevela-app", Description: "this is demo"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
It("Test index", func() {
|
||||
It("Test application index", func() {
|
||||
var app = model.Application{
|
||||
Name: "test",
|
||||
}
|
||||
selector, err := labels.Parse(fmt.Sprintf("table=%s", app.TableName()))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(cmp.Diff(app.Index()["name"], "test")).Should(BeEmpty())
|
||||
for k, v := range app.Index() {
|
||||
index := convertIndex2Labels(app.Index())
|
||||
for k, v := range index {
|
||||
rq, err := labels.NewRequirement(k, selection.Equals, []string{v})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
selector = selector.Add(*rq)
|
||||
}
|
||||
Expect(cmp.Diff(selector.String(), "name=test,table=vela_application")).Should(BeEmpty())
|
||||
})
|
||||
It("Test workflow index", func() {
|
||||
defaultPtr := false
|
||||
var workflow = model.Workflow{
|
||||
Name: "test",
|
||||
Default: &defaultPtr,
|
||||
}
|
||||
selector, err := labels.Parse(fmt.Sprintf("table=%s", workflow.TableName()))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(cmp.Diff(workflow.Index()["name"], "test")).Should(BeEmpty())
|
||||
index := convertIndex2Labels(workflow.Index())
|
||||
for k, v := range index {
|
||||
rq, err := labels.NewRequirement(k, selection.Equals, []string{v})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
selector = selector.Add(*rq)
|
||||
}
|
||||
Expect(cmp.Diff(selector.String(), "default=false,name=test,table=vela_workflow")).Should(BeEmpty())
|
||||
})
|
||||
It("Test list function", func() {
|
||||
var app model.Application
|
||||
list, err := kubeStore.List(context.TODO(), &app, &datastore.ListOptions{Page: -1})
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -80,6 +81,55 @@ func SliceIncludeSlice(a, b []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ToString convery an interface to a string type.
|
||||
func ToString(i interface{}) string {
|
||||
if i == nil {
|
||||
return ""
|
||||
}
|
||||
v := reflect.ValueOf(i)
|
||||
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
i = v.Interface()
|
||||
switch s := i.(type) {
|
||||
case string:
|
||||
return s
|
||||
case bool:
|
||||
return strconv.FormatBool(s)
|
||||
case float64:
|
||||
return strconv.FormatFloat(s, 'f', -1, 64)
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(s), 'f', -1, 32)
|
||||
case int:
|
||||
return strconv.Itoa(s)
|
||||
case int64:
|
||||
return strconv.FormatInt(s, 10)
|
||||
case int32:
|
||||
return strconv.Itoa(int(s))
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(s), 10)
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(s), 10)
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint64:
|
||||
// nolint
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case []byte:
|
||||
return string(s)
|
||||
case nil:
|
||||
return ""
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// MapKey2Array convery map keys to array
|
||||
func MapKey2Array(source map[string]string) []string {
|
||||
var list []string
|
||||
|
||||
@@ -137,3 +137,40 @@ func TestJoinURL(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
type Obj struct {
|
||||
k string
|
||||
}
|
||||
obj := &Obj{"foo"}
|
||||
boolPtr := true
|
||||
caseA := []struct {
|
||||
input interface{}
|
||||
expect string
|
||||
}{
|
||||
{int(666), "666"},
|
||||
{int8(6), "6"},
|
||||
{int16(6), "6"},
|
||||
{int32(6), "6"},
|
||||
{int64(6), "6"},
|
||||
{uint(6), "6"},
|
||||
{uint8(6), "6"},
|
||||
{uint16(6), "6"},
|
||||
{uint32(6), "6"},
|
||||
{uint64(6), "6"},
|
||||
{float32(3.14), "3.14"},
|
||||
{float64(3.14), "3.14"},
|
||||
{true, "true"},
|
||||
{false, "false"},
|
||||
{&boolPtr, "true"},
|
||||
{nil, ""},
|
||||
{[]byte("one time"), "one time"},
|
||||
{"one more time", "one more time"},
|
||||
{obj, ""},
|
||||
}
|
||||
|
||||
for _, test := range caseA {
|
||||
v := ToString(test.input)
|
||||
assert.Equal(t, test.expect, v)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user