This is an automated email from the ASF dual-hosted git repository.
chenjunxu pushed a commit to branch refactor
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/refactor by this push:
new 79348d9 feat: add store hub and flake id (#534)
79348d9 is described below
commit 79348d9ecbc9991db3a1df73e2c8ba24ae35a6bc
Author: Vinci Xu <[email protected]>
AuthorDate: Fri Oct 2 09:48:11 2020 +0800
feat: add store hub and flake id (#534)
* feat: add store hub and flake id
* feat: add store interface to easy est
---
api/go.mod | 2 +
api/go.sum | 5 ++
api/internal/core/entity/entity.go | 16 ++++-
api/internal/core/store/store.go | 27 ++++++++-
api/internal/core/store/store_test.go | 26 +++++---
api/internal/core/store/storehub.go | 41 +++++++++++++
.../store/{validator_mock.go => validate_mock.go} | 0
api/internal/handler/consumer/consumer.go | 21 +------
api/internal/handler/route/route.go | 44 ++++++++------
api/internal/handler/service/service.go | 21 +------
api/internal/handler/ssl/ssl.go | 21 +------
api/internal/handler/upstream/upstream.go | 21 +------
api/internal/utils/utils.go | 63 ++++++++++++++++++++
api/internal/utils/utils_test.go | 16 +++++
api/main.go | 69 ++++++++++++++++++++++
15 files changed, 287 insertions(+), 106 deletions(-)
diff --git a/api/go.mod b/api/go.mod
index 1c935ff..face2f0 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -4,6 +4,7 @@ go 1.13
require (
github.com/api7/apitest v1.4.9
+ github.com/api7/go-jsonpatch v0.0.0-20180223123257-a8710867776e
github.com/coreos/etcd v3.3.25+incompatible // indirect
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf //
indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
@@ -20,6 +21,7 @@ require (
github.com/shiningrush/droplet v0.1.2
github.com/shiningrush/droplet/wrapper/gin v0.1.0
github.com/sirupsen/logrus v1.6.0
+ github.com/sony/sonyflake v1.0.0
github.com/spf13/viper v1.7.1
github.com/steinfletcher/apitest v1.4.10 // indirect
github.com/stretchr/testify v1.6.1
diff --git a/api/go.sum b/api/go.sum
index 50b3cdf..6201e29 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -18,6 +18,8 @@ github.com/alecthomas/template
v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod
h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/api7/apitest v1.4.9 h1:FYTUQJ1hgeB9UvMFif1jjbfiA+XqHPEBfsjhDskytA8=
github.com/api7/apitest v1.4.9/go.mod
h1:YZruZ+jDMFL6rNgMWiuhwCTugNN0mJkLCYCHG3ICYlE=
+github.com/api7/go-jsonpatch v0.0.0-20180223123257-a8710867776e
h1:TX/8xM53DHaIIBr4wU+ifYI8IkUzS8+HrX8kzIzaaG0=
+github.com/api7/go-jsonpatch v0.0.0-20180223123257-a8710867776e/go.mod
h1:yc49guNPyTy2deyszk3erQN+2vO2NwLKPNicXurj7Hs=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod
h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod
h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod
h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
@@ -46,6 +48,7 @@ github.com/coreos/pkg
v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/davecgh/go-spew v1.1.0/go.mod
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/deckarep/golang-set v1.7.1/go.mod
h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd
h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod
h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible
h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
@@ -291,6 +294,8 @@ github.com/smartystreets/goconvey v1.6.4
h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
github.com/smartystreets/goconvey v1.6.4/go.mod
h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
github.com/soheilhy/cmux v0.1.4/go.mod
h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/sony/sonyflake v1.0.0
h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM=
+github.com/sony/sonyflake v1.0.0/go.mod
h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod
h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod
h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
diff --git a/api/internal/core/entity/entity.go
b/api/internal/core/entity/entity.go
index baad4aa..5dca9c8 100644
--- a/api/internal/core/entity/entity.go
+++ b/api/internal/core/entity/entity.go
@@ -16,8 +16,22 @@
*/
package entity
+type BaseInfo struct {
+ ID string `json:"id"`
+ CreateTime int64 `json:"create_time"`
+ UpdateTime int64 `json:"update_time"`
+}
+
+func (info *BaseInfo) GetBaseInfo() *BaseInfo {
+ return info
+}
+
+type BaseInfoGetter interface {
+ GetBaseInfo() *BaseInfo
+}
+
type Route struct {
- ID string `json:"id"`
+ BaseInfo
URI string `json:"uri,omitempty" validate:"uri"`
Uris []string `json:"uris,omitempty"`
Name string `json:"name,omitempty" validate:"max=50"`
diff --git a/api/internal/core/store/store.go b/api/internal/core/store/store.go
index 6b63e6a..3d2d4b9 100644
--- a/api/internal/core/store/store.go
+++ b/api/internal/core/store/store.go
@@ -20,12 +20,23 @@ import (
"context"
"encoding/json"
"fmt"
+ "github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/storage"
+ "github.com/apisix/manager-api/internal/utils"
+ "github.com/shiningrush/droplet/data"
"log"
"reflect"
"time"
)
+type Interface interface {
+ Get(key string) (interface{}, error)
+ List(input ListInput) (*ListOutput, error)
+ Create(ctx context.Context, obj interface{}) error
+ Update(ctx context.Context, obj interface{}) error
+ BatchDelete(ctx context.Context, keys []string) error
+}
+
type GenericStore struct {
Stg storage.Interface
@@ -114,7 +125,7 @@ func (s *GenericStore) Init() error {
func (s *GenericStore) Get(key string) (interface{}, error) {
ret, ok := s.cache[key]
if !ok {
- return nil, fmt.Errorf("id:%s not found", key)
+ return nil, data.ErrNotFound
}
return ret, nil
}
@@ -193,6 +204,15 @@ func (s *GenericStore) Create(ctx context.Context, obj
interface{}) error {
return fmt.Errorf("key: %s is conflicted", key)
}
+ if getter, ok := obj.(entity.BaseInfoGetter); ok {
+ info := getter.GetBaseInfo()
+ if info.ID == "" {
+ info.ID = utils.GetFlakeUidStr()
+ }
+ info.CreateTime = time.Now().Unix()
+ info.UpdateTime = time.Now().Unix()
+ }
+
bs, err := json.Marshal(obj)
if err != nil {
return fmt.Errorf("json marshal failed: %s", err)
@@ -218,6 +238,11 @@ func (s *GenericStore) Update(ctx context.Context, obj
interface{}) error {
return fmt.Errorf("key: %s is not found", key)
}
+ if getter, ok := obj.(entity.BaseInfoGetter); ok {
+ info := getter.GetBaseInfo()
+ info.UpdateTime = time.Now().Unix()
+ }
+
bs, err := json.Marshal(obj)
if err != nil {
return fmt.Errorf("json marshal failed: %s", err)
diff --git a/api/internal/core/store/store_test.go
b/api/internal/core/store/store_test.go
index cc074cb..38ab343 100644
--- a/api/internal/core/store/store_test.go
+++ b/api/internal/core/store/store_test.go
@@ -18,7 +18,9 @@ package store
import (
"context"
+ "encoding/json"
"fmt"
+ "github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/storage"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -99,6 +101,7 @@ func TestNewGenericStore(t *testing.T) {
}
type TestStruct struct {
+ entity.BaseInfo
Field1 string
Field2 string
}
@@ -408,7 +411,8 @@ func TestGenericStore_List(t *testing.T) {
for _, tc := range tests {
ret, err := tc.giveStore.List(tc.giveInput)
- assert.Equal(t, tc.wantRet, ret, tc.caseDesc)
+ assert.Equal(t, tc.wantRet.TotalSize, ret.TotalSize,
tc.caseDesc)
+ assert.ElementsMatch(t, tc.wantRet.Rows, ret.Rows, tc.caseDesc)
assert.Equal(t, tc.wantErr, err, tc.caseDesc)
}
}
@@ -472,7 +476,6 @@ func TestGenericStore_Create(t *testing.T) {
giveErr error
giveValidateErr error
wantKey string
- wantStr string
wantErr error
}{
{
@@ -490,7 +493,6 @@ func TestGenericStore_Create(t *testing.T) {
},
},
wantKey: "test/path/test1",
- wantStr: `{"Field1":"test1","Field2":"test2"}`,
},
{
caseDesc: "create failed",
@@ -508,7 +510,6 @@ func TestGenericStore_Create(t *testing.T) {
},
giveErr: fmt.Errorf("create failed"),
wantKey: "test/path/test1",
- wantStr: `{"Field1":"test1","Field2":"test2"}`,
wantErr: fmt.Errorf("create failed"),
},
{
@@ -553,7 +554,13 @@ func TestGenericStore_Create(t *testing.T) {
mStorage.On("Create", mock.Anything, mock.Anything,
mock.Anything).Run(func(args mock.Arguments) {
createCalled = true
assert.Equal(t, tc.wantKey, args[1], tc.caseDesc)
- assert.Equal(t, tc.wantStr, args[2], tc.caseDesc)
+ input := TestStruct{}
+ _ = json.Unmarshal([]byte(args[2].(string)), &input)
+ assert.Equal(t, tc.giveObj.Field1, input.Field1,
tc.caseDesc)
+ assert.Equal(t, tc.giveObj.Field2, input.Field2,
tc.caseDesc)
+ assert.NotEqual(t, 0, len(input.ID), tc.caseDesc)
+ assert.NotEqual(t, 0, input.CreateTime, tc.caseDesc)
+ assert.NotEqual(t, 0, input.UpdateTime, tc.caseDesc)
}).Return(tc.giveErr)
mValidator := &MockValidator{}
@@ -582,7 +589,6 @@ func TestGenericStore_Update(t *testing.T) {
giveErr error
giveValidateErr error
wantKey string
- wantStr string
wantErr error
}{
{
@@ -603,7 +609,6 @@ func TestGenericStore_Update(t *testing.T) {
},
},
wantKey: "test/path/test1",
- wantStr: `{"Field1":"test1","Field2":"test2"}`,
},
{
caseDesc: "create failed",
@@ -624,7 +629,6 @@ func TestGenericStore_Update(t *testing.T) {
},
giveErr: fmt.Errorf("create failed"),
wantKey: "test/path/test1",
- wantStr: `{"Field1":"test1","Field2":"test2"}`,
wantErr: fmt.Errorf("create failed"),
},
{
@@ -654,7 +658,11 @@ func TestGenericStore_Update(t *testing.T) {
mStorage.On("Update", mock.Anything, mock.Anything,
mock.Anything).Run(func(args mock.Arguments) {
createCalled = true
assert.Equal(t, tc.wantKey, args[1], tc.caseDesc)
- assert.Equal(t, tc.wantStr, args[2], tc.caseDesc)
+ input := TestStruct{}
+ _ = json.Unmarshal([]byte(args[2].(string)), &input)
+ assert.Equal(t, tc.giveObj.Field1, input.Field1,
tc.caseDesc)
+ assert.Equal(t, tc.giveObj.Field2, input.Field2,
tc.caseDesc)
+ assert.NotEqual(t, 0, input.UpdateTime, tc.caseDesc)
}).Return(tc.giveErr)
mValidator := &MockValidator{}
diff --git a/api/internal/core/store/storehub.go
b/api/internal/core/store/storehub.go
new file mode 100644
index 0000000..5b26bd3
--- /dev/null
+++ b/api/internal/core/store/storehub.go
@@ -0,0 +1,41 @@
+package store
+
+import (
+ "fmt"
+ "github.com/apisix/manager-api/internal/utils"
+)
+
+type HubKey string
+
+const (
+ HubKeyConsumer HubKey = "consumer"
+ HubKeyRoute HubKey = "route"
+ HubKeyService HubKey = "service"
+ HubKeySsl HubKey = "ssl"
+ HubKeyUpstream HubKey = "upstream"
+)
+
+var (
+ storeHub = map[HubKey]*GenericStore{}
+)
+
+func InitStore(key HubKey, opt GenericStoreOption) error {
+ s, err := NewGenericStore(opt)
+ if err != nil {
+ return err
+ }
+ if err := s.Init(); err != nil {
+ return err
+ }
+
+ utils.AppendToClosers(s.Close)
+ storeHub[key] = s
+ return nil
+}
+
+func GetStore(key HubKey) *GenericStore {
+ if s, ok := storeHub[key]; ok {
+ return s
+ }
+ panic(fmt.Sprintf("no store with key: %s", key))
+}
diff --git a/api/internal/core/store/validator_mock.go
b/api/internal/core/store/validate_mock.go
similarity index 100%
rename from api/internal/core/store/validator_mock.go
rename to api/internal/core/store/validate_mock.go
diff --git a/api/internal/handler/consumer/consumer.go
b/api/internal/handler/consumer/consumer.go
index 048b1cc..ed55d39 100644
--- a/api/internal/handler/consumer/consumer.go
+++ b/api/internal/handler/consumer/consumer.go
@@ -29,32 +29,15 @@ import (
"github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/store"
"github.com/apisix/manager-api/internal/handler"
- "github.com/apisix/manager-api/internal/utils"
)
type Handler struct {
- consumerStore *store.GenericStore
+ consumerStore store.Interface
}
func NewHandler() (handler.RouteRegister, error) {
- s, err := store.NewGenericStore(store.GenericStoreOption{
- BasePath: "/apisix/consumers",
- ObjType: reflect.TypeOf(entity.Consumer{}),
- KeyFunc: func(obj interface{}) string {
- r := obj.(*entity.Consumer)
- return r.Username
- },
- })
- if err != nil {
- return nil, err
- }
- if err := s.Init(); err != nil {
- return nil, err
- }
-
- utils.AppendToClosers(s.Close)
return &Handler{
- consumerStore: s,
+ consumerStore: store.GetStore(store.HubKeyConsumer),
}, nil
}
diff --git a/api/internal/handler/route/route.go
b/api/internal/handler/route/route.go
index 7107555..c46ad12 100644
--- a/api/internal/handler/route/route.go
+++ b/api/internal/handler/route/route.go
@@ -17,6 +17,7 @@
package route
import (
+ "fmt"
"reflect"
"strings"
@@ -29,32 +30,19 @@ import (
"github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/store"
"github.com/apisix/manager-api/internal/handler"
- "github.com/apisix/manager-api/internal/utils"
)
type Handler struct {
- routeStore *store.GenericStore
+ routeStore store.Interface
+ svcStore store.Interface
+ upstreamStore store.Interface
}
func NewHandler() (handler.RouteRegister, error) {
- s, err := store.NewGenericStore(store.GenericStoreOption{
- BasePath: "/apisix/routes",
- ObjType: reflect.TypeOf(entity.Route{}),
- KeyFunc: func(obj interface{}) string {
- r := obj.(*entity.Route)
- return r.ID
- },
- })
- if err != nil {
- return nil, err
- }
- if err := s.Init(); err != nil {
- return nil, err
- }
-
- utils.AppendToClosers(s.Close)
return &Handler{
- routeStore: s,
+ routeStore: store.GetStore(store.HubKeyRoute),
+ svcStore: store.GetStore(store.HubKeyService),
+ upstreamStore: store.GetStore(store.HubKeyUpstream),
}, nil
}
@@ -112,6 +100,24 @@ func (h *Handler) List(c droplet.Context) (interface{},
error) {
func (h *Handler) Create(c droplet.Context) (interface{}, error) {
input := c.Input().(*entity.Route)
+ if input.ServiceID != "" {
+ _, err := h.upstreamStore.Get(input.ServiceID)
+ if err != nil {
+ if err == data.ErrNotFound {
+ return nil, fmt.Errorf("service id: %s not
found", input.ServiceID)
+ }
+ return nil, err
+ }
+ }
+ if input.UpstreamID != "" {
+ _, err := h.upstreamStore.Get(input.ServiceID)
+ if err != nil {
+ if err == data.ErrNotFound {
+ return nil, fmt.Errorf("upstream id: %s not
found", input.UpstreamID)
+ }
+ return nil, err
+ }
+ }
if err := h.routeStore.Create(c.Context(), input); err != nil {
return nil, err
diff --git a/api/internal/handler/service/service.go
b/api/internal/handler/service/service.go
index 2255bdd..ee8b5c5 100644
--- a/api/internal/handler/service/service.go
+++ b/api/internal/handler/service/service.go
@@ -30,32 +30,15 @@ import (
"github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/store"
"github.com/apisix/manager-api/internal/handler"
- "github.com/apisix/manager-api/internal/utils"
)
type Handler struct {
- serviceStore *store.GenericStore
+ serviceStore store.Interface
}
func NewHandler() (handler.RouteRegister, error) {
- s, err := store.NewGenericStore(store.GenericStoreOption{
- BasePath: "/apisix/services",
- ObjType: reflect.TypeOf(entity.Service{}),
- KeyFunc: func(obj interface{}) string {
- r := obj.(*entity.Service)
- return r.ID
- },
- })
- if err != nil {
- return nil, err
- }
- if err := s.Init(); err != nil {
- return nil, err
- }
-
- utils.AppendToClosers(s.Close)
return &Handler{
- serviceStore: s,
+ serviceStore: store.GetStore(store.HubKeyService),
}, nil
}
diff --git a/api/internal/handler/ssl/ssl.go b/api/internal/handler/ssl/ssl.go
index 46d4126..52162fb 100644
--- a/api/internal/handler/ssl/ssl.go
+++ b/api/internal/handler/ssl/ssl.go
@@ -35,32 +35,15 @@ import (
"github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/store"
"github.com/apisix/manager-api/internal/handler"
- "github.com/apisix/manager-api/internal/utils"
)
type Handler struct {
- sslStore *store.GenericStore
+ sslStore store.Interface
}
func NewHandler() (handler.RouteRegister, error) {
- s, err := store.NewGenericStore(store.GenericStoreOption{
- BasePath: "/apisix/ssl",
- ObjType: reflect.TypeOf(entity.SSL{}),
- KeyFunc: func(obj interface{}) string {
- r := obj.(*entity.SSL)
- return r.ID
- },
- })
- if err != nil {
- return nil, err
- }
- if err := s.Init(); err != nil {
- return nil, err
- }
-
- utils.AppendToClosers(s.Close)
return &Handler{
- sslStore: s,
+ sslStore: store.GetStore(store.HubKeySsl),
}, nil
}
diff --git a/api/internal/handler/upstream/upstream.go
b/api/internal/handler/upstream/upstream.go
index 1c0b41b..87a8dd0 100644
--- a/api/internal/handler/upstream/upstream.go
+++ b/api/internal/handler/upstream/upstream.go
@@ -30,32 +30,15 @@ import (
"github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/store"
"github.com/apisix/manager-api/internal/handler"
- "github.com/apisix/manager-api/internal/utils"
)
type Handler struct {
- upstreamStore *store.GenericStore
+ upstreamStore store.Interface
}
func NewHandler() (handler.RouteRegister, error) {
- s, err := store.NewGenericStore(store.GenericStoreOption{
- BasePath: "/apisix/upstreams",
- ObjType: reflect.TypeOf(entity.Upstream{}),
- KeyFunc: func(obj interface{}) string {
- r := obj.(*entity.Upstream)
- return r.ID
- },
- })
- if err != nil {
- return nil, err
- }
- if err := s.Init(); err != nil {
- return nil, err
- }
-
- utils.AppendToClosers(s.Close)
return &Handler{
- upstreamStore: s,
+ upstreamStore: store.GetStore(store.HubKeyUpstream),
}, nil
}
diff --git a/api/internal/utils/utils.go b/api/internal/utils/utils.go
new file mode 100644
index 0000000..f28c1bf
--- /dev/null
+++ b/api/internal/utils/utils.go
@@ -0,0 +1,63 @@
+package utils
+
+import (
+ "github.com/sony/sonyflake"
+ "net"
+ "os"
+ "strconv"
+)
+
+var _sf *sonyflake.Sonyflake
+
+func init() {
+ saltStr, ok := os.LookupEnv("FLAKE_SALT")
+ var salt uint16
+ if ok {
+ i, err := strconv.Atoi(saltStr)
+ if err != nil {
+ panic(err)
+ }
+ salt = uint16(i)
+ }
+
+ _sf = sonyflake.NewSonyflake(sonyflake.Settings{
+ MachineID: func() (u uint16, e error) {
+ return sumIP(GetOutboundIP()) + salt, nil
+ },
+ })
+ if _sf == nil {
+ panic("sonyflake init failed")
+ }
+}
+
+func sumIP(ip net.IP) uint16 {
+ total := 0
+ for i := range ip {
+ total += int(ip[i])
+ }
+ return uint16(total)
+}
+
+// Get preferred outbound ip of this machine
+func GetOutboundIP() net.IP {
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ panic(err)
+ }
+ defer conn.Close()
+
+ localAddr := conn.LocalAddr().(*net.UDPAddr)
+ return localAddr.IP
+}
+
+func GetFlakeUid() uint64 {
+ uid, err := _sf.NextID()
+ if err != nil {
+ panic("get sony flake uid failed:" + err.Error())
+ }
+ return uid
+}
+
+func GetFlakeUidStr() string {
+ return strconv.FormatUint(GetFlakeUid(), 10)
+}
diff --git a/api/internal/utils/utils_test.go b/api/internal/utils/utils_test.go
new file mode 100644
index 0000000..f88a6e4
--- /dev/null
+++ b/api/internal/utils/utils_test.go
@@ -0,0 +1,16 @@
+package utils
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestGetFlakeUid(t *testing.T) {
+ id := GetFlakeUid()
+ assert.NotEqual(t, 0, id)
+}
+
+func TestGetFlakeUidStr(t *testing.T) {
+ id := GetFlakeUidStr()
+ assert.NotEqual(t, "", id)
+}
diff --git a/api/main.go b/api/main.go
index 9638045..36541b7 100644
--- a/api/main.go
+++ b/api/main.go
@@ -18,10 +18,13 @@ package main
import (
"fmt"
+ "github.com/apisix/manager-api/internal/core/entity"
"github.com/apisix/manager-api/internal/core/storage"
+ "github.com/apisix/manager-api/internal/core/store"
"github.com/apisix/manager-api/internal/utils"
"github.com/spf13/viper"
"net/http"
+ "reflect"
"strings"
"time"
@@ -41,6 +44,9 @@ func main() {
if err :=
storage.InitETCDClient(strings.Split(viper.GetString("etcd_endpoints"), ","));
err != nil {
panic(err)
}
+ if err := initStores(); err != nil {
+ panic(err)
+ }
// init
//conf.InitializeMysql()
@@ -59,3 +65,66 @@ func main() {
utils.CloseAll()
}
+
+func initStores() error {
+ err := store.InitStore(store.HubKeyConsumer, store.GenericStoreOption{
+ BasePath: "/apisix/consumers",
+ ObjType: reflect.TypeOf(entity.Consumer{}),
+ KeyFunc: func(obj interface{}) string {
+ r := obj.(*entity.Consumer)
+ return r.Username
+ },
+ })
+ if err != nil {
+ return err
+ }
+
+ err = store.InitStore(store.HubKeyRoute, store.GenericStoreOption{
+ BasePath: "/apisix/routes",
+ ObjType: reflect.TypeOf(entity.Route{}),
+ KeyFunc: func(obj interface{}) string {
+ r := obj.(*entity.Route)
+ return r.ID
+ },
+ })
+ if err != nil {
+ return err
+ }
+
+ err = store.InitStore(store.HubKeyService, store.GenericStoreOption{
+ BasePath: "/apisix/services",
+ ObjType: reflect.TypeOf(entity.Service{}),
+ KeyFunc: func(obj interface{}) string {
+ r := obj.(*entity.Service)
+ return r.ID
+ },
+ })
+ if err != nil {
+ return err
+ }
+
+ err = store.InitStore(store.HubKeySsl, store.GenericStoreOption{
+ BasePath: "/apisix/ssl",
+ ObjType: reflect.TypeOf(entity.SSL{}),
+ KeyFunc: func(obj interface{}) string {
+ r := obj.(*entity.SSL)
+ return r.ID
+ },
+ })
+ if err != nil {
+ return err
+ }
+
+ err = store.InitStore(store.HubKeyUpstream, store.GenericStoreOption{
+ BasePath: "/apisix/upstreams",
+ ObjType: reflect.TypeOf(entity.Upstream{}),
+ KeyFunc: func(obj interface{}) string {
+ r := obj.(*entity.Upstream)
+ return r.ID
+ },
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}