feat: add searcher to scheduler cluster (#462)
* feat: add searcher Signed-off-by: Gaius <gaius.qi@gmail.com>
This commit is contained in:
parent
886c9b51ef
commit
b24f9dc0bd
2
Makefile
2
Makefile
|
|
@ -16,7 +16,7 @@ PROJECT_NAME := "d7y.io/dragonfly/v2"
|
|||
DFGET_NAME := "dfget"
|
||||
VERSION := "2.0.0"
|
||||
PKG := "$(PROJECT_NAME)"
|
||||
PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/ | grep -v '\(/manager/\)' | grep -v '\(/test/\)')
|
||||
PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/ | grep -v '\(/test/\)')
|
||||
GIT_COMMIT := $(shell git rev-parse --verify HEAD --short=7)
|
||||
GIT_COMMIT_LONG := $(shell git rev-parse --verify HEAD)
|
||||
DFGET_ARCHIVE_PREFIX := "$(DFGET_NAME)_$(GIT_COMMIT)"
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -59,6 +59,7 @@ require (
|
|||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
|
||||
golang.org/x/tools v0.1.4 // indirect
|
||||
gonum.org/v1/gonum v0.9.3
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect
|
||||
google.golang.org/grpc v1.36.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
|
|
|
|||
41
go.sum
41
go.sum
|
|
@ -12,6 +12,7 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k
|
|||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
|
|
@ -25,6 +26,7 @@ github.com/VividCortex/mysqlerr v1.0.0 h1:5pZ2TZA+YnzPgzBfiUWGqWmKDVNBdrkf9g+DNe
|
|||
github.com/VividCortex/mysqlerr v1.0.0/go.mod h1:xERx8E4tBhLvpjzdUyQiSfUxeMcATEQrflDAfXsqcAE=
|
||||
github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw=
|
||||
github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
|
|
@ -47,6 +49,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
|
|
@ -94,6 +97,8 @@ github.com/envoyproxy/protoc-gen-validate v0.6.1 h1:4CF52PCseTFt4bE+Yk3dIpdVi7XW
|
|||
github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
|
|
@ -107,12 +112,17 @@ github.com/go-echarts/go-echarts/v2 v2.2.3 h1:H8oPdUpzuiV2K8S4xYZa1JRNjP3U0h7HVq
|
|||
github.com/go-echarts/go-echarts/v2 v2.2.3/go.mod h1:6TOomEztzGDVDkOSCFBq3ed7xOYfbOqhaBzD0YV771A=
|
||||
github.com/go-echarts/statsview v0.3.4 h1:CCuytRAutdnF901NrR4BzSjHXjUp8OyA3/iopgG/1/Y=
|
||||
github.com/go-echarts/statsview v0.3.4/go.mod h1:AehKjL9cTFMeIo5QdV8sQO43vFmfY65X5GMWa3XMciY=
|
||||
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
|
||||
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
|
||||
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
|
||||
github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9yue4+QkG/HQ/W67wvtQmWJ4SDo9aK/GIno=
|
||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
|
|
@ -151,6 +161,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
|||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
|
|
@ -322,6 +333,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
|||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
|
|
@ -431,6 +444,8 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC
|
|||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
|
||||
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
|
@ -473,6 +488,7 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC
|
|||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
|
|
@ -598,16 +614,27 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20201221025956-e89b829e73ea h1:GnGfrp0fiNhiBS/v/aCFTmfEWgkvxW4Qiu8oM2/IfZ4=
|
||||
golang.org/x/exp v0.0.0-20201221025956-e89b829e73ea/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
|
@ -706,6 +733,7 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
@ -720,6 +748,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
|||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
@ -727,8 +756,10 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
|
@ -745,6 +776,7 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
@ -768,6 +800,14 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
|||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/gonum v0.9.3 h1:DnoIG+QAMaF5NvxnGe/oKsgKcAc6PcUyl8q0VetfQ8s=
|
||||
gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||
gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
|
|
@ -872,6 +912,7 @@ k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
|
|||
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ const (
|
|||
|
||||
// PluginMetaKeyType indicates the type of a plugin, currently support: resource
|
||||
PluginMetaKeyType = "type"
|
||||
|
||||
// PluginMetaKeyName indicates the name of a plugin
|
||||
PluginMetaKeyName = "name"
|
||||
)
|
||||
|
|
@ -42,6 +43,7 @@ type PluginType string
|
|||
|
||||
const (
|
||||
PluginTypeResource = PluginType("resource")
|
||||
PluginTypeManager = PluginType("manager")
|
||||
)
|
||||
|
||||
type PluginInitFunc func(option map[string]string) (plugin interface{}, meta map[string]string, err error)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ type SchedulerCluster struct {
|
|||
BIO string `gorm:"column:bio;size:1024" json:"bio"`
|
||||
Config datatypes.JSONMap `gorm:"column:config;not null" json:"config"`
|
||||
ClientConfig datatypes.JSONMap `gorm:"column:client_config;not null" json:"client_config"`
|
||||
Scopes datatypes.JSONMap `gorm:"column:scopes" json:"scopes"`
|
||||
IsDefault bool `gorm:"column:is_default;not null;default:false" json:"is_default"`
|
||||
CDNClusters []CDNCluster `gorm:"many2many:cdn_cluster_scheduler_cluster;" json:"-"`
|
||||
Schedulers []Scheduler `json:"-"`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2020 The Dragonfly Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 searcher
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"d7y.io/dragonfly/v2/internal/dfplugin"
|
||||
)
|
||||
|
||||
const (
|
||||
pluginName = "searcher"
|
||||
)
|
||||
|
||||
func LoadPlugin() (Searcher, error) {
|
||||
client, _, err := dfplugin.Load(dfplugin.PluginTypeManager, pluginName, map[string]string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rc, ok := client.(Searcher); ok {
|
||||
return rc, err
|
||||
}
|
||||
return nil, errors.New("invalid client, not a ResourceClient")
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2020 The Dragonfly Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 searcher
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
testifyassert "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLoadPlugin(t *testing.T) {
|
||||
assert := testifyassert.New(t)
|
||||
defer func() {
|
||||
os.Remove("./testdata/d7y-manager-plugin-searcher.so")
|
||||
os.Remove("./testdata/test")
|
||||
}()
|
||||
|
||||
var (
|
||||
cmd *exec.Cmd
|
||||
output []byte
|
||||
wd string
|
||||
err error
|
||||
)
|
||||
|
||||
// build plugin
|
||||
cmd = exec.Command("go", "build", "-buildmode=plugin", "-o=./testdata/d7y-manager-plugin-searcher.so", "testdata/plugin/searcher.go")
|
||||
output, err = cmd.CombinedOutput()
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
t.Fatalf(string(output))
|
||||
return
|
||||
}
|
||||
|
||||
// build test binary
|
||||
cmd = exec.Command("go", "build", "-o=./testdata/test", "testdata/main.go")
|
||||
output, err = cmd.CombinedOutput()
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
t.Fatalf(string(output))
|
||||
return
|
||||
}
|
||||
|
||||
wd, err = os.Getwd()
|
||||
assert.Nil(err)
|
||||
wd = path.Join(wd, "testdata")
|
||||
|
||||
// execute test binary
|
||||
cmd = exec.Command("./testdata/test", "-plugin-dir", wd)
|
||||
output, err = cmd.CombinedOutput()
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
t.Fatalf(string(output))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright 2020 The Dragonfly Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 searcher
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"d7y.io/dragonfly/v2/manager/model"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"gonum.org/v1/gonum/stat"
|
||||
)
|
||||
|
||||
const (
|
||||
conditionSecurityDomain = "security_domain"
|
||||
conditionLocation = "location"
|
||||
conditionIDC = "idc"
|
||||
)
|
||||
|
||||
const (
|
||||
conditionLocationWeight = 0.7
|
||||
conditionIDCWeight = 0.3
|
||||
)
|
||||
|
||||
type Scopes struct {
|
||||
Location []string `mapstructure:"location"`
|
||||
IDC []string `mapstructure:"idc"`
|
||||
}
|
||||
|
||||
type Searcher interface {
|
||||
FindSchedulerCluster([]model.SchedulerCluster, map[string]string) (model.SchedulerCluster, bool)
|
||||
}
|
||||
|
||||
type searcher struct{}
|
||||
|
||||
func New() Searcher {
|
||||
s, err := LoadPlugin()
|
||||
if err != nil {
|
||||
return &searcher{}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *searcher) FindSchedulerCluster(schedulerClusters []model.SchedulerCluster, conditions map[string]string) (model.SchedulerCluster, bool) {
|
||||
if len(schedulerClusters) <= 0 || len(conditions) <= 0 {
|
||||
return model.SchedulerCluster{}, false
|
||||
}
|
||||
|
||||
// If there are security domain conditions, match clusters of the same security domain.
|
||||
// If the security domain condition does not exist, it matches clusters that does not have a security domain.
|
||||
// Then use clusters sets to score according to scopes.
|
||||
securityDomain := conditions[conditionSecurityDomain]
|
||||
var clusters []model.SchedulerCluster
|
||||
for _, v := range schedulerClusters {
|
||||
if v.SecurityGroup.Domain == securityDomain {
|
||||
clusters = append(clusters, v)
|
||||
}
|
||||
}
|
||||
|
||||
switch len(clusters) {
|
||||
case 0:
|
||||
return model.SchedulerCluster{}, false
|
||||
case 1:
|
||||
return clusters[0], true
|
||||
default:
|
||||
var maxMean float64 = 0
|
||||
cluster := clusters[0]
|
||||
for _, v := range clusters {
|
||||
mean := calculateSchedulerClusterMean(conditions, v.Scopes)
|
||||
if mean > maxMean {
|
||||
maxMean = mean
|
||||
cluster = v
|
||||
}
|
||||
}
|
||||
return cluster, true
|
||||
}
|
||||
}
|
||||
|
||||
func calculateSchedulerClusterMean(conditions map[string]string, rawScopes map[string]interface{}) float64 {
|
||||
var scopes Scopes
|
||||
if err := mapstructure.Decode(rawScopes, &scopes); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
location := conditions[conditionLocation]
|
||||
lx := calculateConditionScore(location, scopes.Location)
|
||||
|
||||
idc := conditions[conditionIDC]
|
||||
ix := calculateConditionScore(idc, scopes.IDC)
|
||||
|
||||
return stat.Mean([]float64{lx, ix}, []float64{conditionLocationWeight, conditionIDCWeight})
|
||||
}
|
||||
|
||||
func calculateConditionScore(value string, scope []string) float64 {
|
||||
if value == "" {
|
||||
return 0
|
||||
}
|
||||
|
||||
if len(scope) <= 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
i := sort.SearchStrings(scope, value)
|
||||
if i < 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright 2020 The Dragonfly Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 searcher
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"d7y.io/dragonfly/v2/manager/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSchedulerCluster(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
schedulerClusters []model.SchedulerCluster
|
||||
conditions map[string]string
|
||||
expect func(t *testing.T, data model.SchedulerCluster, ok bool)
|
||||
}{
|
||||
{
|
||||
name: "conditions is empty",
|
||||
schedulerClusters: []model.SchedulerCluster{{Name: "foo"}},
|
||||
conditions: map[string]string{},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(ok, false)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "scheduler clusters is empty",
|
||||
schedulerClusters: []model.SchedulerCluster{},
|
||||
conditions: map[string]string{"location": "foo"},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(ok, false)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to security_domain condition",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
SecurityGroup: model.SecurityGroup{
|
||||
Domain: "domain-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{"security_domain": "domain-1"},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to location condition",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
Scopes: map[string]interface{}{
|
||||
"location": []string{"location-1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{"location": "location-1"},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to idc condition",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
Scopes: map[string]interface{}{
|
||||
"idc": []string{"idc-1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{"idc": "idc-1"},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to location and idc condition",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
Scopes: map[string]interface{}{
|
||||
"location": []string{"location-1"},
|
||||
"idc": []string{"idc-1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{
|
||||
"location": "location-1",
|
||||
"idc": "idc-1",
|
||||
},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to security_domain and location conditions",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
Scopes: map[string]interface{}{
|
||||
"location": []string{"location-1"},
|
||||
},
|
||||
SecurityGroup: model.SecurityGroup{
|
||||
Domain: "domain-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{
|
||||
"security_domain": "domain-1",
|
||||
"location": "location-1",
|
||||
},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to security_domain and idc conditions",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
Scopes: map[string]interface{}{
|
||||
"idc": []string{"idc-1"},
|
||||
},
|
||||
SecurityGroup: model.SecurityGroup{
|
||||
Domain: "domain-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{
|
||||
"security_domain": "domain-1",
|
||||
"idc": "idc-1",
|
||||
},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to all conditions",
|
||||
schedulerClusters: []model.SchedulerCluster{
|
||||
{
|
||||
Name: "foo",
|
||||
Scopes: map[string]interface{}{
|
||||
"idc": []string{"idc-1"},
|
||||
"location": []string{"location-1"},
|
||||
},
|
||||
SecurityGroup: model.SecurityGroup{
|
||||
Domain: "domain-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
conditions: map[string]string{
|
||||
"security_domain": "domain-1",
|
||||
"idc": "idc-1",
|
||||
"location": "location-1",
|
||||
},
|
||||
expect: func(t *testing.T, data model.SchedulerCluster, ok bool) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(data.Name, "foo")
|
||||
assert.Equal(ok, true)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
searcher := New()
|
||||
clusters, ok := searcher.FindSchedulerCluster(tc.schedulerClusters, tc.conditions)
|
||||
tc.expect(t, clusters, ok)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateSchedulerClusterMean(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
conditions map[string]string
|
||||
rawScopes map[string]interface{}
|
||||
expect func(t *testing.T, mean float64)
|
||||
}{
|
||||
{
|
||||
name: "conditions and rawScopes is empty",
|
||||
conditions: map[string]string{},
|
||||
rawScopes: map[string]interface{}{},
|
||||
expect: func(t *testing.T, mean float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(mean, float64(0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missed matches",
|
||||
conditions: map[string]string{
|
||||
"location": "location-1",
|
||||
},
|
||||
rawScopes: map[string]interface{}{
|
||||
"idc": []string{"idc-1"},
|
||||
},
|
||||
expect: func(t *testing.T, mean float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(mean, float64(0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to location",
|
||||
conditions: map[string]string{
|
||||
"location": "location-1",
|
||||
},
|
||||
rawScopes: map[string]interface{}{
|
||||
"location": []string{"location-1"},
|
||||
},
|
||||
expect: func(t *testing.T, mean float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(mean, float64(conditionLocationWeight))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to idc",
|
||||
conditions: map[string]string{
|
||||
"idc": "idc-1",
|
||||
},
|
||||
rawScopes: map[string]interface{}{
|
||||
"idc": []string{"idc-1"},
|
||||
},
|
||||
expect: func(t *testing.T, mean float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(mean, float64(conditionIDCWeight))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to location and idc",
|
||||
conditions: map[string]string{
|
||||
"location": "location-1",
|
||||
"idc": "idc-1",
|
||||
},
|
||||
rawScopes: map[string]interface{}{
|
||||
"location": []string{"location-1"},
|
||||
"idc": []string{"idc-1"},
|
||||
},
|
||||
expect: func(t *testing.T, mean float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(mean, float64(conditionLocationWeight+conditionIDCWeight))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
mean := calculateSchedulerClusterMean(tc.conditions, tc.rawScopes)
|
||||
tc.expect(t, mean)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateConditionScore(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value string
|
||||
scope []string
|
||||
expect func(t *testing.T, score float64)
|
||||
}{
|
||||
{
|
||||
name: "value is empty",
|
||||
value: "",
|
||||
scope: []string{"foo"},
|
||||
expect: func(t *testing.T, score float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(score, float64(0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "scope is empty",
|
||||
value: "foo",
|
||||
scope: []string{},
|
||||
expect: func(t *testing.T, score float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(score, float64(0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "match according to value",
|
||||
value: "foo",
|
||||
scope: []string{"foo"},
|
||||
expect: func(t *testing.T, score float64) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(score, float64(1))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
score := calculateConditionScore(tc.value, tc.scope)
|
||||
tc.expect(t, score)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2020 The Dragonfly Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"d7y.io/dragonfly/v2/internal/dfpath"
|
||||
"d7y.io/dragonfly/v2/manager/model"
|
||||
"d7y.io/dragonfly/v2/manager/searcher"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&dfpath.PluginsDir, "plugin-dir", ".", "")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
s, err := searcher.LoadPlugin()
|
||||
if err != nil {
|
||||
fmt.Printf("load plugin error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cluster, ok := s.FindSchedulerCluster([]model.SchedulerCluster{}, map[string]string{})
|
||||
if !ok {
|
||||
fmt.Println("scheduler cluster not found")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if cluster.Name != "foo" {
|
||||
fmt.Println("scheduler cluster name wrong")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2020 The Dragonfly Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 main
|
||||
|
||||
import "d7y.io/dragonfly/v2/manager/model"
|
||||
|
||||
type searcher struct{}
|
||||
|
||||
func (s *searcher) FindSchedulerCluster(schedulerClusters []model.SchedulerCluster, conditions map[string]string) (model.SchedulerCluster, bool) {
|
||||
return model.SchedulerCluster{Name: "foo"}, true
|
||||
}
|
||||
|
||||
func DragonflyPluginInit(option map[string]string) (interface{}, map[string]string, error) {
|
||||
return &searcher{}, map[string]string{"type": "manager", "name": "searcher"}, nil
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"d7y.io/dragonfly/v2/manager/cache"
|
||||
"d7y.io/dragonfly/v2/manager/config"
|
||||
"d7y.io/dragonfly/v2/manager/database"
|
||||
"d7y.io/dragonfly/v2/manager/searcher"
|
||||
"d7y.io/dragonfly/v2/manager/service"
|
||||
"d7y.io/dragonfly/v2/pkg/rpc"
|
||||
"d7y.io/dragonfly/v2/pkg/rpc/manager"
|
||||
|
|
@ -49,9 +50,12 @@ func New(cfg *config.Config) (*Server, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Initialize database
|
||||
// Initialize cache
|
||||
cache := cache.New(cfg)
|
||||
|
||||
// Initialize searcher
|
||||
searcher := searcher.New()
|
||||
|
||||
// Initialize REST service
|
||||
restService := service.NewREST(
|
||||
service.WithDatabase(db),
|
||||
|
|
@ -62,6 +66,7 @@ func New(cfg *config.Config) (*Server, error) {
|
|||
grpcService := service.NewGRPC(
|
||||
service.GRPCWithDatabase(db),
|
||||
service.GRPCWithCache(cache),
|
||||
service.GRPCWithSearcher(searcher),
|
||||
)
|
||||
|
||||
// Initialize router
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ func (s *rest) CreateSchedulerCluster(json types.CreateSchedulerClusterRequest)
|
|||
BIO: json.BIO,
|
||||
Config: json.Config,
|
||||
ClientConfig: json.ClientConfig,
|
||||
Scopes: json.Scopes,
|
||||
IsDefault: json.IsDefault,
|
||||
}
|
||||
|
||||
|
|
@ -34,6 +35,7 @@ func (s *rest) CreateSchedulerClusterWithSecurityGroupDomain(json types.CreateSc
|
|||
BIO: json.BIO,
|
||||
Config: json.Config,
|
||||
ClientConfig: json.ClientConfig,
|
||||
Scopes: json.Scopes,
|
||||
IsDefault: json.IsDefault,
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +61,7 @@ func (s *rest) UpdateSchedulerCluster(id uint, json types.UpdateSchedulerCluster
|
|||
BIO: json.BIO,
|
||||
Config: json.Config,
|
||||
ClientConfig: json.ClientConfig,
|
||||
Scopes: json.Scopes,
|
||||
IsDefault: json.IsDefault,
|
||||
}).Error; err != nil {
|
||||
return nil, err
|
||||
|
|
@ -80,6 +83,7 @@ func (s *rest) UpdateSchedulerClusterWithSecurityGroupDomain(id uint, json types
|
|||
BIO: json.BIO,
|
||||
Config: json.Config,
|
||||
ClientConfig: json.ClientConfig,
|
||||
Scopes: json.Scopes,
|
||||
IsDefault: json.IsDefault,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"d7y.io/dragonfly/v2/manager/cache"
|
||||
"d7y.io/dragonfly/v2/manager/database"
|
||||
"d7y.io/dragonfly/v2/manager/model"
|
||||
"d7y.io/dragonfly/v2/manager/searcher"
|
||||
"d7y.io/dragonfly/v2/pkg/rpc/manager"
|
||||
cachev8 "github.com/go-redis/cache/v8"
|
||||
"github.com/go-redis/redis/v8"
|
||||
|
|
@ -23,12 +24,13 @@ type GRPC struct {
|
|||
rdb *redis.Client
|
||||
cache *cache.Cache
|
||||
manager.UnimplementedManagerServer
|
||||
searcher searcher.Searcher
|
||||
}
|
||||
|
||||
// Option is a functional option for rest
|
||||
type GRPCOption func(s *GRPC)
|
||||
|
||||
// WithDatabase set the database client
|
||||
// GRPCWithDatabase set the database client
|
||||
func GRPCWithDatabase(database *database.Database) GRPCOption {
|
||||
return func(s *GRPC) {
|
||||
s.db = database.DB
|
||||
|
|
@ -36,13 +38,20 @@ func GRPCWithDatabase(database *database.Database) GRPCOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithCache set the cache client
|
||||
// GRPCWithCache set the cache client
|
||||
func GRPCWithCache(cache *cache.Cache) GRPCOption {
|
||||
return func(s *GRPC) {
|
||||
s.cache = cache
|
||||
}
|
||||
}
|
||||
|
||||
// GRPCWithSearcher set search client
|
||||
func GRPCWithSearcher(searcher searcher.Searcher) GRPCOption {
|
||||
return func(s *GRPC) {
|
||||
s.searcher = searcher
|
||||
}
|
||||
}
|
||||
|
||||
// NewREST returns a new REST instence
|
||||
func NewGRPC(options ...GRPCOption) *GRPC {
|
||||
s := &GRPC{}
|
||||
|
|
@ -433,9 +442,25 @@ func (s *GRPC) ListSchedulers(ctx context.Context, req *manager.ListSchedulersRe
|
|||
|
||||
// Cache Miss
|
||||
logger.Infof("%s cache miss", cacheKey)
|
||||
var schedulerClusters []model.SchedulerCluster
|
||||
if err := s.db.Preload("SecurityGroup").Find(&schedulerClusters).Error; err != nil {
|
||||
return nil, status.Error(codes.Unknown, err.Error())
|
||||
}
|
||||
|
||||
// Search optimal scheduler cluster
|
||||
schedulerCluster, ok := s.searcher.FindSchedulerCluster(schedulerClusters, req.HostInfo)
|
||||
if !ok {
|
||||
if err := s.db.Find(&schedulerCluster, &model.SchedulerCluster{
|
||||
IsDefault: true,
|
||||
}).Error; err != nil {
|
||||
return nil, status.Error(codes.Unknown, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
schedulers := []model.Scheduler{}
|
||||
if err := s.db.Find(&schedulers, &model.Scheduler{
|
||||
Status: model.SchedulerStatusActive,
|
||||
Status: model.SchedulerStatusActive,
|
||||
SchedulerClusterID: &schedulerCluster.ID,
|
||||
}).Error; err != nil {
|
||||
return nil, status.Error(codes.Unknown, err.Error())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ type CreateSchedulerClusterRequest struct {
|
|||
BIO string `json:"bio" binding:"omitempty"`
|
||||
Config map[string]interface{} `json:"config" binding:"required"`
|
||||
ClientConfig map[string]interface{} `json:"client_config" binding:"required"`
|
||||
Scopes map[string]interface{} `json:"scopes" binding:"omitempty"`
|
||||
IsDefault bool `json:"is_default" binding:"omitempty"`
|
||||
SecurityGroupDomain string `json:"security_group_domain" binding:"omitempty"`
|
||||
}
|
||||
|
|
@ -23,6 +24,7 @@ type UpdateSchedulerClusterRequest struct {
|
|||
BIO string `json:"bio" binding:"omitempty"`
|
||||
Config map[string]interface{} `json:"config" binding:"omitempty"`
|
||||
ClientConfig map[string]interface{} `json:"client_config" binding:"omitempty"`
|
||||
Scopes map[string]interface{} `json:"scopes" binding:"omitempty"`
|
||||
IsDefault bool `json:"is_default" binding:"omitempty"`
|
||||
SecurityGroupDomain string `json:"security_group_domain" binding:"omitempty"`
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue