diff --git a/build/build.sh b/build/build.sh new file mode 100755 index 0000000..ad694c5 --- /dev/null +++ b/build/build.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +function build() { + VERSION_DATA=$(cat ../internal/const/const.go) + re="Version[ ]+=[ ]+\"([0-9.]+)\"" + if [[ $VERSION_DATA =~ $re ]]; then + VERSION=${BASH_REMATCH[1]} + else + echo "could not match version" + exit + fi + + echo "checking ..." + ZIP_PATH=$(which zip) + if [ -z $ZIP_PATH ]; then + echo "we need 'zip' command to compress files" + exit + fi + + echo "building v${VERSION}/${1}/${2} ..." + NAME="edge-node" + DIST="../dist/${NAME}" + ZIP="${NAME}-${1}-${2}-v${VERSION}.zip" + + echo "copying ..." + if [ ! -d $DIST ]; then + mkdir $DIST + mkdir $DIST/bin + mkdir $DIST/configs + mkdir $DIST/logs + fi + + cp configs/api.template.yaml $DIST/configs + cp -R www $DIST/ + + echo "building ..." + env GOOS=${1} GOARCH=${2} go build -o $DIST/bin/${NAME} -ldflags="-s -w" ../cmd/edge-node/main.go + + echo "zip files" + cd "${DIST}/../" || exit + if [ -f "${ZIP}" ]; then + rm -f "${ZIP}" + fi + zip -r -X -q "${ZIP}" ${NAME}/ + rm -rf ${NAME} + cd - || exit + + echo "OK" +} + +build "linux" "amd64" \ No newline at end of file diff --git a/build/config.sh b/build/config.sh new file mode 100755 index 0000000..c9e1711 --- /dev/null +++ b/build/config.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +TARGET=../../EdgeAdmin/internal/serverconfigs +if [ -d ${TARGET} ] +then + rm -rf ../../EdgeAdmin/internal/serverconfigs +fi +cp -R ../internal/configs/serverconfigs ../../EdgeAdmin/internal/configs/ \ No newline at end of file diff --git a/build/configs/README.md b/build/configs/README.md new file mode 100644 index 0000000..b6b482e --- /dev/null +++ b/build/configs/README.md @@ -0,0 +1 @@ +* `global.yaml` - 全局配置 \ No newline at end of file diff --git a/build/configs/api.template.yaml b/build/configs/api.template.yaml index a5f96fd..62387a6 100644 --- a/build/configs/api.template.yaml +++ b/build/configs/api.template.yaml @@ -1,4 +1,4 @@ rpc: - endpoints: [ "127.0.0.1:8003" ] - nodeId: "" - secret: "" \ No newline at end of file + endpoints: [ ${endpoints} ] +nodeId: "${nodeId}" +secret: "${nodeSecret}" \ No newline at end of file diff --git a/build/configs/node.template.yaml b/build/configs/node.template.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/build/logs/.gitignore b/build/logs/.gitignore new file mode 100644 index 0000000..bf0824e --- /dev/null +++ b/build/logs/.gitignore @@ -0,0 +1 @@ +*.log \ No newline at end of file diff --git a/cmd/edge-node/main.go b/cmd/edge-node/main.go index ab80008..0e0741f 100644 --- a/cmd/edge-node/main.go +++ b/cmd/edge-node/main.go @@ -1,11 +1,29 @@ package main import ( + "fmt" + "github.com/TeaOSLab/EdgeNode/internal/apps" + teaconst "github.com/TeaOSLab/EdgeNode/internal/const" "github.com/TeaOSLab/EdgeNode/internal/nodes" _ "github.com/iwind/TeaGo/bootstrap" ) func main() { - node := nodes.NewNode() - node.Start() + app := apps.NewAppCmd(). + Version(teaconst.Version). + Product(teaconst.ProductName). + Usage(teaconst.ProcessName + " [-v|start|stop|restart|sync|update]") + + app.On("sync", func() { + // TODO + fmt.Println("not implemented yet") + }) + app.On("update", func() { + // TODO + fmt.Println("not implemented yet") + }) + app.Run(func() { + node := nodes.NewNode() + node.Start() + }) } diff --git a/dist/.gitignore b/dist/.gitignore new file mode 100644 index 0000000..6f66c74 --- /dev/null +++ b/dist/.gitignore @@ -0,0 +1 @@ +*.zip \ No newline at end of file diff --git a/go.mod b/go.mod index 925d7bd..078a0ca 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,19 @@ module github.com/TeaOSLab/EdgeNode go 1.14 require ( + github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect + github.com/go-ole/go-ole v1.2.4 // indirect + github.com/go-redis/redis v6.15.8+incompatible // indirect github.com/go-yaml/yaml v2.1.0+incompatible github.com/golang/protobuf v1.4.2 - github.com/iwind/TeaGo v0.0.0-20200722010955-47dd648dc761 + github.com/iwind/TeaGo v0.0.0-20200822074248-b1cf7248c98a + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect + github.com/shirou/gopsutil v2.20.7+incompatible + github.com/stretchr/testify v1.6.1 // indirect + golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 google.golang.org/grpc v1.30.0 google.golang.org/protobuf v1.25.0 + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c ) diff --git a/go.sum b/go.sum index 210f3a5..9ee4170 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,30 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 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= +github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60= +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200624174652-8d2f3be8b2d9/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= +github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= @@ -33,34 +48,71 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/iwind/TeaGo v0.0.0-20200722010955-47dd648dc761 h1:70Iaf6iVF4CiH1P5Au3hqile/2Ea0XIkR4SPpdiaKI0= -github.com/iwind/TeaGo v0.0.0-20200722010955-47dd648dc761/go.mod h1:zjM7k+b+Jthhf0T0fKwuF0iy4TWb5SsU1gmKR2l+OmE= +github.com/iwind/TeaGo v0.0.0-20200727075925-7e7e67b44f2d h1:V7HA0wUOdmZbXJTVpiUEvSD4ARKHwMLMmiCccfkqf24= +github.com/iwind/TeaGo v0.0.0-20200727075925-7e7e67b44f2d/go.mod h1:zjM7k+b+Jthhf0T0fKwuF0iy4TWb5SsU1gmKR2l+OmE= +github.com/iwind/TeaGo v0.0.0-20200822074248-b1cf7248c98a h1:VaWcMNOzHHT1y8MeTA2fWhG6GEfAdy6CwF2tW+KiY5Y= +github.com/iwind/TeaGo v0.0.0-20200822074248-b1cf7248c98a/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/shirou/gopsutil v2.20.7+incompatible h1:Ymv4OD12d6zm+2yONe39VSmp2XooJe8za7ngOLW/o/w= +github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +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/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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -71,8 +123,12 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= @@ -86,12 +142,15 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm 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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -111,12 +170,17 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/apps/app_cmd.go b/internal/apps/app_cmd.go new file mode 100644 index 0000000..7e67151 --- /dev/null +++ b/internal/apps/app_cmd.go @@ -0,0 +1,234 @@ +package apps + +import ( + "fmt" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/logs" + "os" + "os/exec" + "runtime" + "strconv" + "time" +) + +// App命令帮助 +type AppCmd struct { + product string + version string + usage string + options []*CommandHelpOption + appendStrings []string + + directives []*Directive +} + +func NewAppCmd() *AppCmd { + return &AppCmd{} +} + +type CommandHelpOption struct { + Code string + Description string +} + +// 产品 +func (this *AppCmd) Product(product string) *AppCmd { + this.product = product + return this +} + +// 版本 +func (this *AppCmd) Version(version string) *AppCmd { + this.version = version + return this +} + +// 使用方法 +func (this *AppCmd) Usage(usage string) *AppCmd { + this.usage = usage + return this +} + +// 选项 +func (this *AppCmd) Option(code string, description string) *AppCmd { + this.options = append(this.options, &CommandHelpOption{ + Code: code, + Description: description, + }) + return this +} + +// 附加内容 +func (this *AppCmd) Append(appendString string) *AppCmd { + this.appendStrings = append(this.appendStrings, appendString) + return this +} + +// 打印 +func (this *AppCmd) Print() { + fmt.Println(this.product + " v" + this.version) + + usage := this.usage + fmt.Println("Usage:", "\n "+usage) + + if len(this.options) > 0 { + fmt.Println("") + fmt.Println("Options:") + + spaces := 20 + max := 40 + for _, option := range this.options { + l := len(option.Code) + if l < max && l > spaces { + spaces = l + 4 + } + } + + for _, option := range this.options { + if len(option.Code) > max { + fmt.Println("") + fmt.Println(" " + option.Code) + option.Code = "" + } + + fmt.Printf(" %-"+strconv.Itoa(spaces)+"s%s\n", option.Code, ": "+option.Description) + } + } + + if len(this.appendStrings) > 0 { + fmt.Println("") + for _, s := range this.appendStrings { + fmt.Println(s) + } + } +} + +// 添加指令 +func (this *AppCmd) On(arg string, callback func()) { + this.directives = append(this.directives, &Directive{ + Arg: arg, + Callback: callback, + }) +} + +// 运行 +func (this *AppCmd) Run(main func()) { + // 获取参数 + args := os.Args[1:] + if len(args) > 0 { + switch args[0] { + case "-v", "version", "-version", "--version": + this.runVersion() + return + case "?", "help", "-help", "h", "-h": + this.runHelp() + return + case "start": + this.runStart() + return + case "stop": + this.runStop() + return + case "restart": + this.runRestart() + return + case "status": + this.runStatus() + return + } + + // 查找指令 + for _, directive := range this.directives { + if directive.Arg == args[0] { + directive.Callback() + return + } + } + + fmt.Println("unknown command '" + args[0] + "'") + + return + } + + // 记录PID + _ = this.writePid() + + // 日志 + writer := new(LogWriter) + writer.Init() + logs.SetWriter(writer) + + // 运行主函数 + main() +} + +// 版本号 +func (this *AppCmd) runVersion() { + fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")") +} + +// 帮助 +func (this *AppCmd) runHelp() { + this.Print() +} + +// 启动 +func (this *AppCmd) runStart() { + proc := this.checkPid() + if proc != nil { + fmt.Println(this.product+" already started, pid:", proc.Pid) + return + } + + cmd := exec.Command(os.Args[0]) + err := cmd.Start() + if err != nil { + fmt.Println(this.product+" start failed:", err.Error()) + return + } + + fmt.Println(this.product+" started ok, pid:", cmd.Process.Pid) +} + +// 停止 +func (this *AppCmd) runStop() { + proc := this.checkPid() + if proc == nil { + fmt.Println(this.product + " not started yet") + return + } + + // 停止进程 + _ = proc.Kill() + + // 在Windows上经常不能及时释放资源 + _ = DeletePid(Tea.Root + "/bin/pid") + fmt.Println(this.product+" stopped ok, pid:", proc.Pid) +} + +// 重启 +func (this *AppCmd) runRestart() { + this.runStop() + time.Sleep(1 * time.Second) + this.runStart() +} + +// 状态 +func (this *AppCmd) runStatus() { + proc := this.checkPid() + if proc == nil { + fmt.Println(this.product + " not started yet") + } else { + fmt.Println(this.product + " is running, pid: " + fmt.Sprintf("%d", proc.Pid)) + } +} + +// 检查PID +func (this *AppCmd) checkPid() *os.Process { + return CheckPid(Tea.Root + "/bin/pid") +} + +// 写入PID +func (this *AppCmd) writePid() error { + return WritePid(Tea.Root + "/bin/pid") +} diff --git a/internal/apps/directive.go b/internal/apps/directive.go new file mode 100644 index 0000000..9df644e --- /dev/null +++ b/internal/apps/directive.go @@ -0,0 +1,6 @@ +package apps + +type Directive struct { + Arg string + Callback func() +} diff --git a/internal/apps/file_others.go b/internal/apps/file_others.go new file mode 100644 index 0000000..73bf2fe --- /dev/null +++ b/internal/apps/file_others.go @@ -0,0 +1,17 @@ +// +build !windows + +package apps + +import ( + "os" + "syscall" +) + +// lock file +func LockFile(fp *os.File) error { + return syscall.Flock(int(fp.Fd()), syscall.LOCK_EX|syscall.LOCK_NB) +} + +func UnlockFile(fp *os.File) error { + return syscall.Flock(int(fp.Fd()), syscall.LOCK_UN) +} diff --git a/internal/apps/file_windows.go b/internal/apps/file_windows.go new file mode 100644 index 0000000..fa2028f --- /dev/null +++ b/internal/apps/file_windows.go @@ -0,0 +1,17 @@ +// +build windows + +package apps + +import ( + "errors" + "os" +) + +// lock file +func LockFile(fp *os.File) error { + return errors.New("not implemented on windows") +} + +func UnlockFile(fp *os.File) error { + return errors.New("not implemented on windows") +} diff --git a/internal/apps/log_writer.go b/internal/apps/log_writer.go new file mode 100644 index 0000000..ac45c5a --- /dev/null +++ b/internal/apps/log_writer.go @@ -0,0 +1,51 @@ +package apps + +import ( + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/files" + "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/utils/time" + "log" +) + +type LogWriter struct { + fileAppender *files.Appender +} + +func (this *LogWriter) Init() { + // 创建目录 + dir := files.NewFile(Tea.LogDir()) + if !dir.Exists() { + err := dir.Mkdir() + if err != nil { + log.Println("[error]" + err.Error()) + } + } + + logFile := files.NewFile(Tea.LogFile("run.log")) + + // 打开要写入的日志文件 + appender, err := logFile.Appender() + if err != nil { + logs.Error(err) + } else { + this.fileAppender = appender + } +} + +func (this *LogWriter) Write(message string) { + log.Println(message) + + if this.fileAppender != nil { + _, err := this.fileAppender.AppendString(timeutil.Format("Y/m/d H:i:s ") + message + "\n") + if err != nil { + log.Println("[error]" + err.Error()) + } + } +} + +func (this *LogWriter) Close() { + if this.fileAppender != nil { + _ = this.fileAppender.Close() + } +} diff --git a/internal/apps/pid.go b/internal/apps/pid.go new file mode 100644 index 0000000..d5076ee --- /dev/null +++ b/internal/apps/pid.go @@ -0,0 +1,113 @@ +package apps + +import ( + "fmt" + "github.com/iwind/TeaGo/types" + "io/ioutil" + "os" + "runtime" +) + +var pidFileList = []*os.File{} + +// 检查Pid +func CheckPid(path string) *os.Process { + // windows上打开的文件是不能删除的 + if runtime.GOOS == "windows" { + if os.Remove(path) == nil { + return nil + } + } + + file, err := os.Open(path) + if err != nil { + return nil + } + + defer func() { + _ = file.Close() + }() + + // 是否能取得Lock + err = LockFile(file) + if err == nil { + _ = UnlockFile(file) + return nil + } + + pidBytes, err := ioutil.ReadAll(file) + if err != nil { + return nil + } + pid := types.Int(string(pidBytes)) + + if pid <= 0 { + return nil + } + + proc, _ := os.FindProcess(pid) + return proc +} + +// 写入Pid +func WritePid(path string) error { + fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) + if err != nil { + return err + } + + if runtime.GOOS != "windows" { + err = LockFile(fp) + if err != nil { + return err + } + } + pidFileList = append(pidFileList, fp) // hold the file pointers + + _, err = fp.WriteString(fmt.Sprintf("%d", os.Getpid())) + if err != nil { + return err + } + + return nil +} + +// 写入Ppid +func WritePpid(path string) error { + fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) + if err != nil { + return err + } + + if runtime.GOOS != "windows" { + err = LockFile(fp) + if err != nil { + return err + } + } + pidFileList = append(pidFileList, fp) // hold the file pointers + + _, err = fp.WriteString(fmt.Sprintf("%d", os.Getppid())) + if err != nil { + return err + } + + return nil +} + +// 删除Pid +func DeletePid(path string) error { + _, err := os.Stat(path) + if err != nil { + if !os.IsNotExist(err) { + return nil + } + return err + } + + for _, fp := range pidFileList { + _ = UnlockFile(fp) + _ = fp.Close() + } + return os.Remove(path) +} diff --git a/internal/configs/api_config.go b/internal/configs/api_config.go index 9f6d85d..5c89cc5 100644 --- a/internal/configs/api_config.go +++ b/internal/configs/api_config.go @@ -10,6 +10,8 @@ type APIConfig struct { RPC struct { Endpoints []string `yaml:"endpoints"` } `yaml:"rpc"` + NodeId string `yaml:"nodeId"` + Secret string `yaml:"secret"` } func LoadAPIConfig() (*APIConfig, error) { diff --git a/internal/configs/node_config.go b/internal/configs/node_config.go index e239ddb..cf6e979 100644 --- a/internal/configs/node_config.go +++ b/internal/configs/node_config.go @@ -1,6 +1,7 @@ package configs import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" "github.com/go-yaml/yaml" "github.com/iwind/TeaGo/Tea" "io/ioutil" @@ -9,10 +10,13 @@ import ( var sharedNodeConfig *NodeConfig = nil type NodeConfig struct { - Id string `yaml:"id"` - Servers []*ServerConfig `yaml:"servers"` + Id string `yaml:"id" json:"id"` + IsOn bool `yaml:"isOn" json:"isOn"` + Servers []*serverconfigs.ServerConfig `yaml:"servers" json:"servers"` + Version int `yaml:"version" json:"version"` } +// 取得当前节点配置单例 func SharedNodeConfig() (*NodeConfig, error) { sharedLocker.Lock() defer sharedLocker.Unlock() @@ -36,9 +40,19 @@ func SharedNodeConfig() (*NodeConfig, error) { return config, nil } +// 刷新当前节点配置 +func ReloadNodeConfig() error { + sharedLocker.Lock() + sharedNodeConfig = nil + sharedLocker.Unlock() + + _, err := SharedNodeConfig() + return err +} + // 根据网络地址和协议分组 -func (this *NodeConfig) AvailableGroups() []*ServerGroup { - groupMapping := map[string]*ServerGroup{} // protocol://addr => Server Group +func (this *NodeConfig) AvailableGroups() []*serverconfigs.ServerGroup { + groupMapping := map[string]*serverconfigs.ServerGroup{} // protocol://addr => Server Group for _, server := range this.Servers { if !server.IsOn { continue @@ -48,15 +62,39 @@ func (this *NodeConfig) AvailableGroups() []*ServerGroup { if ok { group.Add(server) } else { - group = NewServerGroup(addr) + group = serverconfigs.NewServerGroup(addr) group.Add(server) } groupMapping[addr] = group } } - result := []*ServerGroup{} + result := []*serverconfigs.ServerGroup{} for _, group := range groupMapping { result = append(result, group) } return result } + +func (this *NodeConfig) Init() error { + for _, server := range this.Servers { + err := server.Init() + if err != nil { + return err + } + } + + return nil +} + +// 写入到文件 +func (this *NodeConfig) Save() error { + sharedLocker.Lock() + defer sharedLocker.Unlock() + + data, err := yaml.Marshal(this) + if err != nil { + return err + } + + return ioutil.WriteFile(Tea.ConfigFile("node.yaml"), data, 0777) +} diff --git a/internal/configs/node_config_test.go b/internal/configs/node_config_test.go index 0efa4d3..51c47b5 100644 --- a/internal/configs/node_config_test.go +++ b/internal/configs/node_config_test.go @@ -1,6 +1,7 @@ package configs import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" _ "github.com/iwind/TeaGo/bootstrap" "github.com/iwind/TeaGo/logs" "testing" @@ -27,18 +28,37 @@ func TestSharedNodeConfig(t *testing.T) { func TestNodeConfig_Groups(t *testing.T) { config := &NodeConfig{} - config.Servers = []*ServerConfig{ + config.Servers = []*serverconfigs.ServerConfig{ { IsOn: true, - HTTP: &HTTPProtocolConfig{ - IsOn: true, - Listen: []string{"127.0.0.1:1234", ":8080"}, + HTTP: &serverconfigs.HTTPProtocolConfig{ + BaseProtocol: serverconfigs.BaseProtocol{ + IsOn: true, + Listen: []*serverconfigs.NetworkAddressConfig{ + { + Protocol: serverconfigs.ProtocolHTTP, + Host: "127.0.0.1", + PortRange: "1234", + }, + { + Protocol: serverconfigs.ProtocolHTTP, + PortRange: "8080", + }, + }, + }, }, }, { - HTTP: &HTTPProtocolConfig{ - IsOn: true, - Listen: []string{":8080"}, + HTTP: &serverconfigs.HTTPProtocolConfig{ + BaseProtocol: serverconfigs.BaseProtocol{ + IsOn: true, + Listen: []*serverconfigs.NetworkAddressConfig{ + { + Protocol: serverconfigs.ProtocolHTTP, + PortRange: "8080", + }, + }, + }, }, }, } diff --git a/internal/configs/origin_server_config.go b/internal/configs/origin_server_config.go deleted file mode 100644 index 9c87e63..0000000 --- a/internal/configs/origin_server_config.go +++ /dev/null @@ -1,4 +0,0 @@ -package configs - -type OriginServerConfig struct { -} diff --git a/internal/configs/protocol_http_config.go b/internal/configs/protocol_http_config.go deleted file mode 100644 index d06cb76..0000000 --- a/internal/configs/protocol_http_config.go +++ /dev/null @@ -1,22 +0,0 @@ -package configs - -type HTTPProtocolConfig struct { - IsOn bool `yaml:"isOn"` // 是否开启 - IPVersion IPVersion `yaml:"ipVersion"` // 4, 6 - Listen []string `yaml:"listen" json:"listen"` // 监听地址 -} - -func (this *HTTPProtocolConfig) Addresses() []string { - result := []string{} - for _, listen := range this.Listen { - switch this.IPVersion { - case IPv4: - result = append(result, ProtocolHTTP4+"://"+listen) - case IPv6: - result = append(result, ProtocolHTTP6+"://"+listen) - default: - result = append(result, ProtocolHTTP+"://"+listen) - } - } - return result -} diff --git a/internal/configs/protocol_https_config.go b/internal/configs/protocol_https_config.go deleted file mode 100644 index 0c22bf2..0000000 --- a/internal/configs/protocol_https_config.go +++ /dev/null @@ -1,22 +0,0 @@ -package configs - -type HTTPSProtocolConfig struct { - IsOn bool `yaml:"isOn"` // 是否开启 - IPVersion string `yaml:"ipVersion"` // 4, 6 - Listen []string `yaml:"listen" json:"listen"` // 监听地址 -} - -func (this *HTTPSProtocolConfig) Addresses() []string { - result := []string{} - for _, listen := range this.Listen { - switch this.IPVersion { - case IPv4: - result = append(result, ProtocolHTTPS4+"://"+listen) - case IPv6: - result = append(result, ProtocolHTTPS6+"://"+listen) - default: - result = append(result, ProtocolHTTPS+"://"+listen) - } - } - return result -} diff --git a/internal/configs/protocol_tcp_config.go b/internal/configs/protocol_tcp_config.go deleted file mode 100644 index 71f2cd8..0000000 --- a/internal/configs/protocol_tcp_config.go +++ /dev/null @@ -1,22 +0,0 @@ -package configs - -type TCPProtocolConfig struct { - IsOn bool `yaml:"isOn"` // 是否开启 - IPVersion IPVersion `yaml:"ipVersion"` // 4, 6 - Listen []string `yaml:"listen" json:"listen"` // 监听地址 -} - -func (this *TCPProtocolConfig) Addresses() []string { - result := []string{} - for _, listen := range this.Listen { - switch this.IPVersion { - case IPv4: - result = append(result, ProtocolTCP4+"://"+listen) - case IPv6: - result = append(result, ProtocolTCP6+"://"+listen) - default: - result = append(result, ProtocolTCP+"://"+listen) - } - } - return result -} diff --git a/internal/configs/protocol_tls_config.go b/internal/configs/protocol_tls_config.go deleted file mode 100644 index 44f497f..0000000 --- a/internal/configs/protocol_tls_config.go +++ /dev/null @@ -1,22 +0,0 @@ -package configs - -type TLSProtocolConfig struct { - IsOn bool `yaml:"isOn"` // 是否开启 - IPVersion string `yaml:"ipVersion"` // 4, 6 - Listen []string `yaml:"listen" json:"listen"` // 监听地址 -} - -func (this *TLSProtocolConfig) Addresses() []string { - result := []string{} - for _, listen := range this.Listen { - switch this.IPVersion { - case IPv4: - result = append(result, ProtocolTLS4+"://"+listen) - case IPv6: - result = append(result, ProtocolTLS6+"://"+listen) - default: - result = append(result, ProtocolTLS+"://"+listen) - } - } - return result -} diff --git a/internal/configs/protocol_udp_config.go b/internal/configs/protocol_udp_config.go deleted file mode 100644 index fa9c8ac..0000000 --- a/internal/configs/protocol_udp_config.go +++ /dev/null @@ -1,14 +0,0 @@ -package configs - -type UDPProtocolConfig struct { - IsOn bool `yaml:"isOn"` // 是否开启 - Listen []string `yaml:"listen" json:"listen"` // 监听地址 -} - -func (this *UDPProtocolConfig) Addresses() []string { - result := []string{} - for _, listen := range this.Listen { - result = append(result, ProtocolUDP+"://"+listen) - } - return result -} diff --git a/internal/configs/protocol_unix_config.go b/internal/configs/protocol_unix_config.go deleted file mode 100644 index e09131b..0000000 --- a/internal/configs/protocol_unix_config.go +++ /dev/null @@ -1,14 +0,0 @@ -package configs - -type UnixProtocolConfig struct { - IsOn bool `yaml:"isOn"` // 是否开启 - Listen []string `yaml:"listen" json:"listen"` // 监听地址 -} - -func (this *UnixProtocolConfig) Addresses() []string { - result := []string{} - for _, listen := range this.Listen { - result = append(result, ProtocolUnix+":"+listen) - } - return result -} diff --git a/internal/configs/server_config.go b/internal/configs/server_config.go deleted file mode 100644 index 9990f10..0000000 --- a/internal/configs/server_config.go +++ /dev/null @@ -1,54 +0,0 @@ -package configs - -type ServerConfig struct { - Id string `yaml:"id"` // ID - IsOn bool `yaml:"isOn"` // 是否开启 - Components []*ComponentConfig `yaml:"components"` // 组件 - Filters []*FilterConfig `yaml:"filters"` // 过滤器 - Name string `yaml:"name"` // 名称 - Description string `yaml:"description"` // 描述 - ServerNames []string `yaml:"serverNames"` // 域名 - - // 协议 - HTTP *HTTPProtocolConfig `yaml:"http"` // HTTP配置 - HTTPS *HTTPSProtocolConfig `yaml:"https"` // HTTPS配置 - TCP *TCPProtocolConfig `yaml:"tcp"` // TCP配置 - TLS *TLSProtocolConfig `yaml:"tls"` // TLS配置 - Unix *UnixProtocolConfig `yaml:"unix"` // Unix配置 - UDP *UDPProtocolConfig `yaml:"udp"` // UDP配置 - - // Web配置 - Web *WebConfig `yaml:"web"` -} - -func NewServerConfig() *ServerConfig { - return &ServerConfig{} -} - -func (this *ServerConfig) Init() error { - return nil -} - -func (this *ServerConfig) FullAddresses() []string { - result := []Protocol{} - if this.HTTP != nil && this.HTTP.IsOn { - result = append(result, this.HTTP.Addresses()...) - } - if this.HTTPS != nil && this.HTTPS.IsOn { - result = append(result, this.HTTPS.Addresses()...) - } - if this.TCP != nil && this.TCP.IsOn { - result = append(result, this.TCP.Addresses()...) - } - if this.TLS != nil && this.TLS.IsOn { - result = append(result, this.TLS.Addresses()...) - } - if this.Unix != nil && this.Unix.IsOn { - result = append(result, this.Unix.Addresses()...) - } - if this.UDP != nil && this.UDP.IsOn { - result = append(result, this.UDP.Addresses()...) - } - - return result -} diff --git a/internal/configs/server_config_test.go b/internal/configs/server_config_test.go deleted file mode 100644 index d25fcdf..0000000 --- a/internal/configs/server_config_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package configs - -import "testing" - -func TestServerConfig_Protocols(t *testing.T) { - { - server := NewServerConfig() - t.Log(server.FullAddresses()) - } - - { - server := NewServerConfig() - server.HTTP = &HTTPProtocolConfig{IsOn: true, Listen: []string{"127.0.0.1:1234"}} - server.HTTPS = &HTTPSProtocolConfig{IsOn: true, Listen: []string{"127.0.0.1:1234"}} - server.TCP = &TCPProtocolConfig{IsOn: true, Listen: []string{"127.0.0.1:1234"}} - server.TLS = &TLSProtocolConfig{IsOn: true, Listen: []string{"127.0.0.1:1234"}} - server.Unix = &UnixProtocolConfig{IsOn: true, Listen: []string{"127.0.0.1:1234"}} - server.UDP = &UDPProtocolConfig{IsOn: true, Listen: []string{"127.0.0.1:1234"}} - t.Log(server.FullAddresses()) - } -} diff --git a/internal/configs/server_group.go b/internal/configs/server_group.go deleted file mode 100644 index 19353c9..0000000 --- a/internal/configs/server_group.go +++ /dev/null @@ -1,41 +0,0 @@ -package configs - -import "strings" - -type ServerGroup struct { - fullAddr string - Servers []*ServerConfig -} - -func NewServerGroup(fullAddr string) *ServerGroup { - return &ServerGroup{fullAddr: fullAddr} -} - -// 添加服务 -func (this *ServerGroup) Add(server *ServerConfig) { - this.Servers = append(this.Servers, server) -} - -// 获取完整的地址 -func (this *ServerGroup) FullAddr() string { - return this.fullAddr -} - -// 获取当前分组的协议 -func (this *ServerGroup) Protocol() Protocol { - for _, p := range AllProtocols() { - if strings.HasPrefix(this.fullAddr, p+":") { - return p - } - } - return ProtocolHTTP -} - -// 获取当前分组的地址 -func (this *ServerGroup) Addr() string { - protocol := this.Protocol() - if protocol == ProtocolUnix { - return strings.TrimPrefix(this.fullAddr, protocol+":") - } - return strings.TrimPrefix(this.fullAddr, protocol+"://") -} diff --git a/internal/configs/component_config.go b/internal/configs/serverconfigs/component_config.go similarity index 60% rename from internal/configs/component_config.go rename to internal/configs/serverconfigs/component_config.go index 5a8329e..ad42b4b 100644 --- a/internal/configs/component_config.go +++ b/internal/configs/serverconfigs/component_config.go @@ -1,4 +1,4 @@ -package configs +package serverconfigs type ComponentConfig struct { } diff --git a/internal/configs/serverconfigs/configutils/copy.go b/internal/configs/serverconfigs/configutils/copy.go new file mode 100644 index 0000000..732565f --- /dev/null +++ b/internal/configs/serverconfigs/configutils/copy.go @@ -0,0 +1,20 @@ +package configutils + +import ( + "reflect" +) + +// 拷贝同类型struct指针对象中的字段 +func CopyStructObject(destPtr, sourcePtr interface{}) { + value := reflect.ValueOf(destPtr) + value2 := reflect.ValueOf(sourcePtr) + + countFields := value2.Elem().NumField() + for i := 0; i < countFields; i++ { + v := value2.Elem().Field(i) + if !v.IsValid() || !v.CanSet() { + continue + } + value.Elem().Field(i).Set(v) + } +} diff --git a/internal/configs/serverconfigs/configutils/copy_test.go b/internal/configs/serverconfigs/configutils/copy_test.go new file mode 100644 index 0000000..549e26a --- /dev/null +++ b/internal/configs/serverconfigs/configutils/copy_test.go @@ -0,0 +1,28 @@ +package configutils + +import ( + "github.com/iwind/TeaGo/logs" + "testing" +) + +func TestCopyStructObject(t *testing.T) { + type Book struct { + Name string + Price int + Year int + Author string + press string + } + + book1 := &Book{ + Name: "Hello Golang", + Price: 100, + Year: 2020, + Author: "Liu", + press: "Beijing", + } + book2 := new(Book) + CopyStructObject(book2, book1) + logs.PrintAsJSON(book2, t) + logs.PrintAsJSON(book1, t) +} diff --git a/internal/configs/serverconfigs/configutils/domain.go b/internal/configs/serverconfigs/configutils/domain.go new file mode 100644 index 0000000..5a8ddcd --- /dev/null +++ b/internal/configs/serverconfigs/configutils/domain.go @@ -0,0 +1,59 @@ +package configutils + +import ( + "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/utils/string" + "strings" +) + +// 从一组规则中匹配域名 +// 支持的格式:example.com, www.example.com, .example.com, *.example.com, ~(\d+).example.com +// 更多参考:http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name +func MatchDomains(patterns []string, domain string) (isMatched bool) { + if len(patterns) == 0 { + return + } + for _, pattern := range patterns { + if matchDomain(pattern, domain) { + return true + } + } + return +} + +// 匹配单个域名规则 +func matchDomain(pattern string, domain string) (isMatched bool) { + if len(pattern) == 0 { + return + } + + // 正则表达式 + if pattern[0] == '~' { + reg, err := stringutil.RegexpCompile(strings.TrimSpace(pattern[1:])) + if err != nil { + logs.Error(err) + return false + } + return reg.MatchString(domain) + } + + if pattern[0] == '.' { + return strings.HasSuffix(domain, pattern) + } + + // 其他匹配 + patternPieces := strings.Split(pattern, ".") + domainPieces := strings.Split(domain, ".") + if len(patternPieces) != len(domainPieces) { + return + } + isMatched = true + for index, patternPiece := range patternPieces { + if patternPiece == "" || patternPiece == "*" || patternPiece == domainPieces[index] { + continue + } + isMatched = false + break + } + return isMatched +} diff --git a/internal/configs/serverconfigs/configutils/domain_test.go b/internal/configs/serverconfigs/configutils/domain_test.go new file mode 100644 index 0000000..c0ead00 --- /dev/null +++ b/internal/configs/serverconfigs/configutils/domain_test.go @@ -0,0 +1,79 @@ +package configutils + +import ( + "github.com/iwind/TeaGo/assert" + "testing" +) + +func TestMatchDomain(t *testing.T) { + a := assert.NewAssertion(t) + { + ok := MatchDomains([]string{}, "example.com") + a.IsFalse(ok) + } + + { + ok := MatchDomains([]string{"example.com"}, "example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{"www.example.com"}, "example.com") + a.IsFalse(ok) + } + + { + ok := MatchDomains([]string{".example.com"}, "www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{".example.com"}, "a.www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{".example.com"}, "a.www.example123.com") + a.IsFalse(ok) + } + + { + ok := MatchDomains([]string{"*.example.com"}, "www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{"*.*.com"}, "www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{"www.*.com"}, "www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{"gallery.*.com"}, "www.example.com") + a.IsFalse(ok) + } + + { + ok := MatchDomains([]string{"~\\w+.example.com"}, "www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{"~\\w+.example.com"}, "a.www.example.com") + a.IsTrue(ok) + } + + { + ok := MatchDomains([]string{"~^\\d+.example.com$"}, "www.example.com") + a.IsFalse(ok) + } + + { + ok := MatchDomains([]string{"~^\\d+.example.com$"}, "123.example.com") + a.IsTrue(ok) + } +} diff --git a/internal/configs/serverconfigs/configutils/log.go b/internal/configs/serverconfigs/configutils/log.go new file mode 100644 index 0000000..422903a --- /dev/null +++ b/internal/configs/serverconfigs/configutils/log.go @@ -0,0 +1,11 @@ +package configutils + +import "github.com/iwind/TeaGo/logs" + +// 记录错误 +func LogError(arg ...interface{}) { + if len(arg) == 0 { + return + } + logs.Println(arg...) +} diff --git a/internal/configs/serverconfigs/configutils/match.go b/internal/configs/serverconfigs/configutils/match.go new file mode 100644 index 0000000..961d7f8 --- /dev/null +++ b/internal/configs/serverconfigs/configutils/match.go @@ -0,0 +1,25 @@ +package configutils + +import ( + "regexp" + "strings" +) + +var whitespaceReg = regexp.MustCompile(`\s+`) + +// 关键词匹配 +func MatchKeyword(source, keyword string) bool { + if len(keyword) == 0 { + return false + } + + pieces := whitespaceReg.Split(keyword, -1) + source = strings.ToLower(source) + for _, piece := range pieces { + if strings.Index(source, strings.ToLower(piece)) > -1 { + return true + } + } + + return false +} diff --git a/internal/configs/serverconfigs/configutils/match_test.go b/internal/configs/serverconfigs/configutils/match_test.go new file mode 100644 index 0000000..26c4507 --- /dev/null +++ b/internal/configs/serverconfigs/configutils/match_test.go @@ -0,0 +1,13 @@ +package configutils + +import ( + "github.com/iwind/TeaGo/assert" + "testing" +) + +func TestMatchKeyword(t *testing.T) { + a := assert.NewAssertion(t) + a.IsTrue(MatchKeyword("a b c", "a")) + a.IsFalse(MatchKeyword("a b c", "")) + a.IsTrue(MatchKeyword("abc", "BC")) +} diff --git a/internal/configs/serverconfigs/configutils/yaml.go b/internal/configs/serverconfigs/configutils/yaml.go new file mode 100644 index 0000000..678c56d --- /dev/null +++ b/internal/configs/serverconfigs/configutils/yaml.go @@ -0,0 +1,14 @@ +package configutils + +import ( + "github.com/go-yaml/yaml" + "io/ioutil" +) + +func UnmarshalYamlFile(file string, ptr interface{}) error { + data, err := ioutil.ReadFile(file) + if err != nil { + return err + } + return yaml.Unmarshal(data, ptr) +} diff --git a/internal/configs/filter_config.go b/internal/configs/serverconfigs/filter_config.go similarity index 57% rename from internal/configs/filter_config.go rename to internal/configs/serverconfigs/filter_config.go index d90f7fc..ba9268c 100644 --- a/internal/configs/filter_config.go +++ b/internal/configs/serverconfigs/filter_config.go @@ -1,4 +1,4 @@ -package configs +package serverconfigs type FilterConfig struct { } diff --git a/internal/configs/serverconfigs/global_config.go b/internal/configs/serverconfigs/global_config.go new file mode 100644 index 0000000..63dc101 --- /dev/null +++ b/internal/configs/serverconfigs/global_config.go @@ -0,0 +1,43 @@ +package serverconfigs + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/configutils" + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/shared" +) + +var globalConfig *GlobalConfig = nil +var globalConfigFile = "global.yaml" + +// 全局设置 +type GlobalConfig struct { + HTTPAll struct { + MatchDomainStrictly bool `yaml:"matchDomainStrictly"` + } `yaml:"httpAll"` + HTTP struct{} `yaml:"http"` + HTTPS struct{} `yaml:"https"` + TCPAll struct{} `yaml:"tcpAll"` + TCP struct{} `yaml:"tcp"` + TLS struct{} `yaml:"tls"` + Unix struct{} `yaml:"unix"` + UDP struct{} `yaml:"udp"` +} + +func SharedGlobalConfig() *GlobalConfig { + shared.Locker.Lock() + defer shared.Locker.Unlock() + + if globalConfig != nil { + return globalConfig + } + + err := configutils.UnmarshalYamlFile(globalConfigFile, globalConfig) + if err != nil { + configutils.LogError("[SharedGlobalConfig]" + err.Error()) + globalConfig = &GlobalConfig{} + } + return globalConfig +} + +func (this *GlobalConfig) Init() error { + return nil +} diff --git a/internal/configs/ip_version.go b/internal/configs/serverconfigs/ip_version.go similarity index 78% rename from internal/configs/ip_version.go rename to internal/configs/serverconfigs/ip_version.go index 24dbd0e..6471ea0 100644 --- a/internal/configs/ip_version.go +++ b/internal/configs/serverconfigs/ip_version.go @@ -1,4 +1,4 @@ -package configs +package serverconfigs type IPVersion = string diff --git a/internal/configs/location_config.go b/internal/configs/serverconfigs/location_config.go similarity index 59% rename from internal/configs/location_config.go rename to internal/configs/serverconfigs/location_config.go index edca6c1..4a7c636 100644 --- a/internal/configs/location_config.go +++ b/internal/configs/serverconfigs/location_config.go @@ -1,4 +1,4 @@ -package configs +package serverconfigs type LocationConfig struct { } diff --git a/internal/configs/serverconfigs/network_address_config.go b/internal/configs/serverconfigs/network_address_config.go new file mode 100644 index 0000000..c34da8c --- /dev/null +++ b/internal/configs/serverconfigs/network_address_config.go @@ -0,0 +1,70 @@ +package serverconfigs + +import ( + "github.com/iwind/TeaGo/types" + "regexp" + "strconv" + "strings" +) + +var regexpSinglePort = regexp.MustCompile(`^\d+$`) + +// 网络地址配置 +type NetworkAddressConfig struct { + Protocol string `yaml:"protocol" json:"protocol"` // 协议,http、tcp、tcp4、tcp6、unix、udp等 + Host string `yaml:"host" json:"host"` // 主机地址或主机名 + PortRange string `yaml:"portRange" json:"portRange"` // 端口范围,支持 8080、8080-8090、8080:8090 + + minPort int + maxPort int +} + +func (this *NetworkAddressConfig) Init() error { + // 8080 + if regexpSinglePort.MatchString(this.PortRange) { + this.minPort = types.Int(this.PortRange) + this.maxPort = this.minPort + return nil + } + + // 8080:8090 + if strings.Contains(this.PortRange, ":") { + pieces := strings.SplitN(this.PortRange, ":", 2) + minPort := types.Int(pieces[0]) + maxPort := types.Int(pieces[1]) + if minPort > maxPort { + minPort, maxPort = maxPort, minPort + } + this.minPort = minPort + this.maxPort = maxPort + return nil + } + + // 8080-8090 + if strings.Contains(this.PortRange, "-") { + pieces := strings.SplitN(this.PortRange, "-", 2) + minPort := types.Int(pieces[0]) + maxPort := types.Int(pieces[1]) + if minPort > maxPort { + minPort, maxPort = maxPort, minPort + } + this.minPort = minPort + this.maxPort = maxPort + return nil + } + + return nil +} + +func (this *NetworkAddressConfig) FullAddresses() []string { + if this.Protocol == ProtocolUnix { + return []string{this.Protocol + ":" + this.Host} + } + + result := []string{} + for i := this.minPort; i <= this.maxPort; i++ { + host := this.Host + result = append(result, this.Protocol+"://"+host+":"+strconv.Itoa(i)) + } + return result +} diff --git a/internal/configs/serverconfigs/network_address_config_test.go b/internal/configs/serverconfigs/network_address_config_test.go new file mode 100644 index 0000000..bb14dba --- /dev/null +++ b/internal/configs/serverconfigs/network_address_config_test.go @@ -0,0 +1,57 @@ +package serverconfigs + +import "testing" + +func TestNetworkAddressConfig_FullAddresses(t *testing.T) { + { + addr := &NetworkAddressConfig{ + Protocol: "http", + Host: "127.0.0.1", + PortRange: "8080", + } + err := addr.Init() + if err != nil { + t.Fatal(err) + } + t.Log(addr.FullAddresses()) + } + + { + addr := &NetworkAddressConfig{ + Protocol: "http", + Host: "127.0.0.1", + PortRange: "8080:8090", + } + err := addr.Init() + if err != nil { + t.Fatal(err) + } + t.Log(addr.FullAddresses()) + } + + { + addr := &NetworkAddressConfig{ + Protocol: "http", + Host: "127.0.0.1", + PortRange: "8080-8090", + } + err := addr.Init() + if err != nil { + t.Fatal(err) + } + t.Log(addr.FullAddresses()) + } + + { + addr := &NetworkAddressConfig{ + Protocol: "http", + Host: "127.0.0.1", + PortRange: "8080-8070", + } + err := addr.Init() + if err != nil { + t.Fatal(err) + } + t.Log(addr.FullAddresses()) + } +} diff --git a/internal/configs/serverconfigs/origin_server_config.go b/internal/configs/serverconfigs/origin_server_config.go new file mode 100644 index 0000000..3b03966 --- /dev/null +++ b/internal/configs/serverconfigs/origin_server_config.go @@ -0,0 +1,10 @@ +package serverconfigs + +// 源站服务配置 +type OriginServerConfig struct { + Id string `yaml:"id" json:"id"` // ID + IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 + Name string `yaml:"name" json:"name"` // 名称 TODO + Addr *NetworkAddressConfig `yaml:"addr" json:"addr"` // 地址 + Description string `yaml:"description" json:"description"` // 描述 TODO +} diff --git a/internal/configs/serverconfigs/origin_server_group_config.go b/internal/configs/serverconfigs/origin_server_group_config.go new file mode 100644 index 0000000..08701ea --- /dev/null +++ b/internal/configs/serverconfigs/origin_server_group_config.go @@ -0,0 +1,6 @@ +package serverconfigs + +// TODO 需要实现 +type OriginServerGroupConfig struct { + Origins []*OriginServerConfig `yaml:"origins" json:"origins"` // 源站列表 +} diff --git a/internal/configs/protocol.go b/internal/configs/serverconfigs/protocol.go similarity index 97% rename from internal/configs/protocol.go rename to internal/configs/serverconfigs/protocol.go index f5987c8..d2dfcf7 100644 --- a/internal/configs/protocol.go +++ b/internal/configs/serverconfigs/protocol.go @@ -1,4 +1,4 @@ -package configs +package serverconfigs type Protocol = string diff --git a/internal/configs/serverconfigs/protocol_base.go b/internal/configs/serverconfigs/protocol_base.go new file mode 100644 index 0000000..c0f6a05 --- /dev/null +++ b/internal/configs/serverconfigs/protocol_base.go @@ -0,0 +1,32 @@ +package serverconfigs + +// 协议基础数据结构 +type BaseProtocol struct { + IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启 + Listen []*NetworkAddressConfig `yaml:"listen" json:"listen"` // 绑定的网络地址 +} + +// 初始化 +func (this *BaseProtocol) InitBase() error { + for _, addr := range this.Listen { + err := addr.Init() + if err != nil { + return err + } + } + return nil +} + +// 获取完整的地址列表 +func (this *BaseProtocol) FullAddresses() []string { + result := []string{} + for _, addr := range this.Listen { + result = append(result, addr.FullAddresses()...) + } + return result +} + +// 添加地址 +func (this *BaseProtocol) AddListen(addr ...*NetworkAddressConfig) { + this.Listen = append(this.Listen, addr...) +} diff --git a/internal/configs/serverconfigs/protocol_http_config.go b/internal/configs/serverconfigs/protocol_http_config.go new file mode 100644 index 0000000..9af8a8e --- /dev/null +++ b/internal/configs/serverconfigs/protocol_http_config.go @@ -0,0 +1,14 @@ +package serverconfigs + +type HTTPProtocolConfig struct { + BaseProtocol `yaml:",inline"` +} + +func (this *HTTPProtocolConfig) Init() error { + err := this.InitBase() + if err != nil { + return err + } + + return nil +} diff --git a/internal/configs/serverconfigs/protocol_https_config.go b/internal/configs/serverconfigs/protocol_https_config.go new file mode 100644 index 0000000..ab175b7 --- /dev/null +++ b/internal/configs/serverconfigs/protocol_https_config.go @@ -0,0 +1,24 @@ +package serverconfigs + +import "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/sslconfigs" + +// TLS Version +type TLSVersion = string + +// Cipher Suites +type TLSCipherSuite = string + +type HTTPSProtocolConfig struct { + BaseProtocol `yaml:",inline"` + + SSL *sslconfigs.SSLConfig `yaml:"ssl"` +} + +func (this *HTTPSProtocolConfig) Init() error { + err := this.InitBase() + if err != nil { + return err + } + + return nil +} diff --git a/internal/configs/serverconfigs/protocol_tcp_config.go b/internal/configs/serverconfigs/protocol_tcp_config.go new file mode 100644 index 0000000..6d6fd09 --- /dev/null +++ b/internal/configs/serverconfigs/protocol_tcp_config.go @@ -0,0 +1,14 @@ +package serverconfigs + +type TCPProtocolConfig struct { + BaseProtocol `yaml:",inline"` +} + +func (this *TCPProtocolConfig) Init() error { + err := this.InitBase() + if err != nil { + return err + } + + return nil +} diff --git a/internal/configs/serverconfigs/protocol_tls_config.go b/internal/configs/serverconfigs/protocol_tls_config.go new file mode 100644 index 0000000..b90f0cc --- /dev/null +++ b/internal/configs/serverconfigs/protocol_tls_config.go @@ -0,0 +1,18 @@ +package serverconfigs + +import "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/sslconfigs" + +type TLSProtocolConfig struct { + BaseProtocol `yaml:",inline"` + + SSL *sslconfigs.SSLConfig `yaml:"ssl"` +} + +func (this *TLSProtocolConfig) Init() error { + err := this.InitBase() + if err != nil { + return err + } + + return nil +} diff --git a/internal/configs/serverconfigs/protocol_udp_config.go b/internal/configs/serverconfigs/protocol_udp_config.go new file mode 100644 index 0000000..29dc854 --- /dev/null +++ b/internal/configs/serverconfigs/protocol_udp_config.go @@ -0,0 +1,14 @@ +package serverconfigs + +type UDPProtocolConfig struct { + BaseProtocol `yaml:",inline"` +} + +func (this *UDPProtocolConfig) Init() error { + err := this.InitBase() + if err != nil { + return err + } + + return nil +} diff --git a/internal/configs/serverconfigs/protocol_unix_config.go b/internal/configs/serverconfigs/protocol_unix_config.go new file mode 100644 index 0000000..63ac398 --- /dev/null +++ b/internal/configs/serverconfigs/protocol_unix_config.go @@ -0,0 +1,14 @@ +package serverconfigs + +type UnixProtocolConfig struct { + BaseProtocol `yaml:",inline"` +} + +func (this *UnixProtocolConfig) Init() error { + err := this.InitBase() + if err != nil { + return err + } + + return nil +} diff --git a/internal/configs/serverconfigs/reverse_proxy_config.go b/internal/configs/serverconfigs/reverse_proxy_config.go new file mode 100644 index 0000000..dc9b4d7 --- /dev/null +++ b/internal/configs/serverconfigs/reverse_proxy_config.go @@ -0,0 +1,6 @@ +package serverconfigs + +type ReverseProxyConfig struct { + IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 + Origins []*OriginServerConfig `yaml:"origins" json:"origins"` // 源站列表 +} diff --git a/internal/configs/serverconfigs/server_config.go b/internal/configs/serverconfigs/server_config.go new file mode 100644 index 0000000..170c583 --- /dev/null +++ b/internal/configs/serverconfigs/server_config.go @@ -0,0 +1,178 @@ +package serverconfigs + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/sslconfigs" +) + +type ServerConfig struct { + Id string `yaml:"id" json:"id"` // ID + IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启 + Components []*ComponentConfig `yaml:"components" json:"components"` // 组件 + Filters []*FilterConfig `yaml:"filters" json:"filters"` // 过滤器 + Name string `yaml:"name" json:"name"` // 名称 + Description string `yaml:"description" json:"description"` // 描述 + ServerNames []*ServerNameConfig `yaml:"serverNames" json:"serverNames"` // 域名 + + // 前端协议 + HTTP *HTTPProtocolConfig `yaml:"http" json:"http"` // HTTP配置 + HTTPS *HTTPSProtocolConfig `yaml:"https" json:"https"` // HTTPS配置 + TCP *TCPProtocolConfig `yaml:"tcp" json:"tcp"` // TCP配置 + TLS *TLSProtocolConfig `yaml:"tls" json:"tls"` // TLS配置 + Unix *UnixProtocolConfig `yaml:"unix" json:"unix"` // Unix配置 + UDP *UDPProtocolConfig `yaml:"udp" json:"udp"` // UDP配置 + + // Web配置 + Web *WebConfig `yaml:"web" json:"web"` + + // 反向代理配置 + ReverseProxy *ReverseProxyConfig `yaml:"reverseProxy" json:"reverseProxy"` +} + +func NewServerConfig() *ServerConfig { + return &ServerConfig{} +} + +func (this *ServerConfig) Init() error { + if this.HTTP != nil { + err := this.HTTP.Init() + if err != nil { + return err + } + } + + if this.HTTPS != nil { + err := this.HTTPS.Init() + if err != nil { + return err + } + } + + if this.TCP != nil { + err := this.TCP.Init() + if err != nil { + return err + } + } + + if this.TLS != nil { + err := this.TLS.Init() + if err != nil { + return err + } + } + + if this.Unix != nil { + err := this.Unix.Init() + if err != nil { + return err + } + } + + if this.UDP != nil { + err := this.UDP.Init() + if err != nil { + return err + } + } + + return nil +} + +func (this *ServerConfig) FullAddresses() []string { + result := []Protocol{} + if this.HTTP != nil && this.HTTP.IsOn { + result = append(result, this.HTTP.FullAddresses()...) + } + if this.HTTPS != nil && this.HTTPS.IsOn { + result = append(result, this.HTTPS.FullAddresses()...) + } + if this.TCP != nil && this.TCP.IsOn { + result = append(result, this.TCP.FullAddresses()...) + } + if this.TLS != nil && this.TLS.IsOn { + result = append(result, this.TLS.FullAddresses()...) + } + if this.Unix != nil && this.Unix.IsOn { + result = append(result, this.Unix.FullAddresses()...) + } + if this.UDP != nil && this.UDP.IsOn { + result = append(result, this.UDP.FullAddresses()...) + } + + return result +} + +func (this *ServerConfig) Listen() []*NetworkAddressConfig { + result := []*NetworkAddressConfig{} + if this.HTTP != nil { + result = append(result, this.HTTP.Listen...) + } + if this.HTTPS != nil { + result = append(result, this.HTTPS.Listen...) + } + if this.TCP != nil { + result = append(result, this.TCP.Listen...) + } + if this.TLS != nil { + result = append(result, this.TLS.Listen...) + } + if this.Unix != nil { + result = append(result, this.Unix.Listen...) + } + if this.UDP != nil { + result = append(result, this.UDP.Listen...) + } + return result +} + +func (this *ServerConfig) AsJSON() ([]byte, error) { + return json.Marshal(this) +} + +func (this *ServerConfig) IsHTTP() bool { + return this.HTTP != nil || this.HTTPS != nil +} + +func (this *ServerConfig) IsTCP() bool { + return this.TCP != nil || this.TLS != nil +} + +func (this *ServerConfig) IsUnix() bool { + return this.Unix != nil +} + +func (this *ServerConfig) IsUDP() bool { + return this.UDP != nil +} + +// 判断是否和域名匹配 +func (this *ServerConfig) MatchName(name string) bool { + for _, serverName := range this.ServerNames { + if serverName.Match(name) { + return true + } + } + return false +} + +// 判断是否严格匹配 +func (this *ServerConfig) MatchNameStrictly(name string) bool { + for _, serverName := range this.ServerNames { + if serverName.Name == name { + return true + } + } + return false +} + +// SSL信息 +func (this *ServerConfig) SSLConfig() *sslconfigs.SSLConfig { + if this.HTTPS != nil { + return this.HTTPS.SSL + } + if this.TLS != nil { + return this.TLS.SSL + } + return nil +} diff --git a/internal/configs/serverconfigs/server_config_test.go b/internal/configs/serverconfigs/server_config_test.go new file mode 100644 index 0000000..33da9e1 --- /dev/null +++ b/internal/configs/serverconfigs/server_config_test.go @@ -0,0 +1,74 @@ +package serverconfigs + +import "testing" + +func TestServerConfig_Protocols(t *testing.T) { + { + server := NewServerConfig() + t.Log(server.FullAddresses()) + } + + { + server := NewServerConfig() + server.HTTP = &HTTPProtocolConfig{BaseProtocol: BaseProtocol{ + IsOn: true, + Listen: []*NetworkAddressConfig{ + { + Protocol: ProtocolHTTP, + PortRange: "1234", + }, + }, + }} + server.HTTPS = &HTTPSProtocolConfig{BaseProtocol: BaseProtocol{ + IsOn: true, + Listen: []*NetworkAddressConfig{ + { + Protocol: ProtocolUnix, + Host: "/hello.sock", + PortRange: "1235", + }, + }, + }} + server.TCP = &TCPProtocolConfig{BaseProtocol: BaseProtocol{ + IsOn: true, + Listen: []*NetworkAddressConfig{ + { + Protocol: ProtocolHTTPS, + PortRange: "1236", + }, + }, + }} + server.TLS = &TLSProtocolConfig{BaseProtocol: BaseProtocol{ + IsOn: true, + Listen: []*NetworkAddressConfig{ + { + Protocol: ProtocolTCP, + PortRange: "1234", + }, + }, + }} + server.Unix = &UnixProtocolConfig{BaseProtocol: BaseProtocol{ + IsOn: true, + Listen: []*NetworkAddressConfig{ + { + Protocol: ProtocolTLS, + PortRange: "1234", + }, + }, + }} + server.UDP = &UDPProtocolConfig{BaseProtocol: BaseProtocol{ + IsOn: true, + Listen: []*NetworkAddressConfig{ + { + Protocol: ProtocolUDP, + PortRange: "1234", + }, + }, + }} + err := server.Init() + if err != nil { + t.Fatal(err) + } + t.Log(server.FullAddresses()) + } +} diff --git a/internal/configs/serverconfigs/server_group.go b/internal/configs/serverconfigs/server_group.go new file mode 100644 index 0000000..0939f40 --- /dev/null +++ b/internal/configs/serverconfigs/server_group.go @@ -0,0 +1,85 @@ +package serverconfigs + +import "strings" + +type ServerGroup struct { + fullAddr string + Servers []*ServerConfig +} + +func NewServerGroup(fullAddr string) *ServerGroup { + return &ServerGroup{fullAddr: fullAddr} +} + +// 添加服务 +func (this *ServerGroup) Add(server *ServerConfig) { + this.Servers = append(this.Servers, server) +} + +// 获取完整的地址 +func (this *ServerGroup) FullAddr() string { + return this.fullAddr +} + +// 获取当前分组的协议 +func (this *ServerGroup) Protocol() Protocol { + for _, p := range AllProtocols() { + if strings.HasPrefix(this.fullAddr, p+":") { + return p + } + } + return ProtocolHTTP +} + +// 获取当前分组的地址 +func (this *ServerGroup) Addr() string { + protocol := this.Protocol() + if protocol == ProtocolUnix { + return strings.TrimPrefix(this.fullAddr, protocol+":") + } + return strings.TrimPrefix(this.fullAddr, protocol+"://") +} + +// 判断当前分组是否为HTTP +func (this *ServerGroup) IsHTTP() bool { + p := this.Protocol() + return p == ProtocolHTTP || p == ProtocolHTTP4 || p == ProtocolHTTP6 +} + +// 判断当前分组是否为HTTPS +func (this *ServerGroup) IsHTTPS() bool { + p := this.Protocol() + return p == ProtocolHTTPS || p == ProtocolHTTPS4 || p == ProtocolHTTPS6 +} + +// 判断当前分组是否为TCP +func (this *ServerGroup) IsTCP() bool { + p := this.Protocol() + return p == ProtocolTCP || p == ProtocolTCP4 || p == ProtocolTCP6 +} + +// 判断当前分组是否为TLS +func (this *ServerGroup) IsTLS() bool { + p := this.Protocol() + return p == ProtocolTLS || p == ProtocolTLS4 || p == ProtocolTLS6 +} + +// 判断当前分组是否为Unix +func (this *ServerGroup) IsUnix() bool { + p := this.Protocol() + return p == ProtocolUnix +} + +// 判断当前分组是否为UDP +func (this *ServerGroup) IsUDP() bool { + p := this.Protocol() + return p == ProtocolUDP +} + +// 获取第一个Server +func (this *ServerGroup) FirstServer() *ServerConfig { + if len(this.Servers) > 0 { + return this.Servers[0] + } + return nil +} diff --git a/internal/configs/server_group_test.go b/internal/configs/serverconfigs/server_group_test.go similarity index 97% rename from internal/configs/server_group_test.go rename to internal/configs/serverconfigs/server_group_test.go index 36d49ac..2340750 100644 --- a/internal/configs/server_group_test.go +++ b/internal/configs/serverconfigs/server_group_test.go @@ -1,4 +1,4 @@ -package configs +package serverconfigs import ( "github.com/iwind/TeaGo/assert" diff --git a/internal/configs/serverconfigs/server_name_config.go b/internal/configs/serverconfigs/server_name_config.go new file mode 100644 index 0000000..faac288 --- /dev/null +++ b/internal/configs/serverconfigs/server_name_config.go @@ -0,0 +1,23 @@ +package serverconfigs + +import "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/configutils" + +type ServerNameType = string + +const ( + ServerNameTypeFull = "full" // 完整的域名,包含通配符等 + ServerNameTypePrefix = "prefix" // 前缀 + ServerNameTypeSuffix = "suffix" // 后缀 + ServerNameTypeMatch = "match" // 正则匹配 +) + +// 主机名(域名)配置 +type ServerNameConfig struct { + Name string `yaml:"name" json:"name"` // 名称 + Type string `yaml:"type" json:"type"` // 类型 +} + +// 判断主机名是否匹配 +func (this *ServerNameConfig) Match(name string) bool { + return configutils.MatchDomains([]string{this.Name}, name) +} diff --git a/internal/configs/serverconfigs/shared/locker.go b/internal/configs/serverconfigs/shared/locker.go new file mode 100644 index 0000000..5011d56 --- /dev/null +++ b/internal/configs/serverconfigs/shared/locker.go @@ -0,0 +1,21 @@ +package shared + +import ( + "sync" +) + +var Locker = new(FileLocker) + +// global file modify locker +type FileLocker struct { + locker sync.Mutex +} + +// lock +func (this *FileLocker) Lock() { + this.locker.Lock() +} + +func (this *FileLocker) Unlock() { + this.locker.Unlock() +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl.go b/internal/configs/serverconfigs/sslconfigs/ssl.go new file mode 100644 index 0000000..e953ce1 --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl.go @@ -0,0 +1,207 @@ +package sslconfigs + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "github.com/iwind/TeaGo/types" + "io/ioutil" + "net" + "regexp" + "strconv" + "strings" +) + +// TLS Version +type TLSVersion = string + +// Cipher Suites +type TLSCipherSuite = string + +// SSL配置 +type SSLConfig struct { + IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启 + + Certs []*SSLCertConfig `yaml:"certs" json:"certs"` + ClientAuthType SSLClientAuthType `yaml:"clientAuthType" json:"clientAuthType"` // 客户端认证类型 + ClientCACertIds []string `yaml:"clientCACertIds" json:"clientCACertIds"` // 客户端认证CA + + Listen []string `yaml:"listen" json:"listen"` // 网络地址 + MinVersion TLSVersion `yaml:"minVersion" json:"minVersion"` // 支持的最小版本 + CipherSuites []TLSCipherSuite `yaml:"cipherSuites" json:"cipherSuites"` // 加密算法套件 + + HSTS *HSTSConfig `yaml:"hsts2" json:"hsts"` // HSTS配置,yaml之所以使用hsts2,是因为要和以前的版本分开 + HTTP2Disabled bool `yaml:"http2Disabled" json:"http2Disabled"` // 是否禁用HTTP2 + + nameMapping map[string]*tls.Certificate // dnsName => cert + + minVersion uint16 + cipherSuites []uint16 + + clientCAPool *x509.CertPool +} + +// 获取新对象 +func NewSSLConfig() *SSLConfig { + return &SSLConfig{} +} + +// 校验配置 +func (this *SSLConfig) Init() error { + if !this.IsOn { + return nil + } + + if len(this.Certs) == 0 { + return errors.New("no certificates in https config") + } + + for _, cert := range this.Certs { + err := cert.Init() + if err != nil { + return err + } + } + + if this.Listen == nil { + this.Listen = []string{} + } else { + for index, addr := range this.Listen { + _, _, err := net.SplitHostPort(addr) + if err != nil { + this.Listen[index] = strings.TrimSuffix(addr, ":") + ":443" + } + } + } + + // min version + this.convertMinVersion() + + // cipher suite categories + this.initCipherSuites() + + // hsts + if this.HSTS != nil { + err := this.HSTS.Init() + if err != nil { + return err + } + } + + // CA证书 + if len(this.ClientCACertIds) > 0 && this.ClientAuthType != SSLClientAuthTypeNoClientCert { + this.clientCAPool = x509.NewCertPool() + list := SharedSSLCertList() + for _, certId := range this.ClientCACertIds { + cert := list.FindCert(certId) + if cert == nil { + continue + } + if !cert.On { + continue + } + data, err := ioutil.ReadFile(cert.FullCertPath()) + if err != nil { + return err + } + this.clientCAPool.AppendCertsFromPEM(data) + } + } + + return nil +} + +// 取得最小版本 +func (this *SSLConfig) TLSMinVersion() uint16 { + return this.minVersion +} + +// 套件 +func (this *SSLConfig) TLSCipherSuites() []uint16 { + return this.cipherSuites +} + +// 校验是否匹配某个域名 +func (this *SSLConfig) MatchDomain(domain string) (cert *tls.Certificate, ok bool) { + for _, cert := range this.Certs { + if cert.MatchDomain(domain) { + return cert.CertObject(), true + } + } + return nil, false +} + +// 取得第一个证书 +func (this *SSLConfig) FirstCert() *tls.Certificate { + for _, cert := range this.Certs { + return cert.CertObject() + } + return nil +} + +// 是否包含某个证书或密钥路径 +func (this *SSLConfig) ContainsFile(file string) bool { + for _, cert := range this.Certs { + if cert.CertFile == file || cert.KeyFile == file { + return true + } + } + return false +} + +// 删除证书文件 +func (this *SSLConfig) DeleteFiles() error { + var resultErr error = nil + + for _, cert := range this.Certs { + err := cert.DeleteFiles() + if err != nil { + resultErr = err + } + } + + return resultErr +} + +// 查找单个证书配置 +func (this *SSLConfig) FindCert(certId string) *SSLCertConfig { + for _, cert := range this.Certs { + if cert.Id == certId { + return cert + } + } + return nil +} + +// 添加证书 +func (this *SSLConfig) AddCert(cert *SSLCertConfig) { + this.Certs = append(this.Certs, cert) +} + +// CA证书Pool,用于TLS对客户端进行认证 +func (this *SSLConfig) CAPool() *x509.CertPool { + return this.clientCAPool +} + +// 分解所有监听地址 +func (this *SSLConfig) ParseListenAddresses() []string { + result := []string{} + var reg = regexp.MustCompile(`\[\s*(\d+)\s*[,:-]\s*(\d+)\s*]$`) + for _, addr := range this.Listen { + match := reg.FindStringSubmatch(addr) + if len(match) == 0 { + result = append(result, addr) + } else { + min := types.Int(match[1]) + max := types.Int(match[2]) + if min > max { + min, max = max, min + } + for i := min; i <= max; i++ { + newAddr := reg.ReplaceAllString(addr, ":"+strconv.Itoa(i)) + result = append(result, newAddr) + } + } + } + return result +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_auth.go b/internal/configs/serverconfigs/sslconfigs/ssl_auth.go new file mode 100644 index 0000000..1298029 --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_auth.go @@ -0,0 +1,75 @@ +package sslconfigs + +import ( + "crypto/tls" + "github.com/iwind/TeaGo/maps" +) + +// 认证类型 +type SSLClientAuthType = int + +const ( + SSLClientAuthTypeNoClientCert SSLClientAuthType = 0 + SSLClientAuthTypeRequestClientCert SSLClientAuthType = 1 + SSLClientAuthTypeRequireAnyClientCert SSLClientAuthType = 2 + SSLClientAuthTypeVerifyClientCertIfGiven SSLClientAuthType = 3 + SSLClientAuthTypeRequireAndVerifyClientCert SSLClientAuthType = 4 +) + +// 所有的客户端认证类型 +func AllSSLClientAuthTypes() []maps.Map { + return []maps.Map{ + { + "name": "不需要客户端证书", + "type": SSLClientAuthTypeNoClientCert, + "requireCA": false, + }, + { + "name": "请求客户端证书", + "type": SSLClientAuthTypeRequestClientCert, + "requireCA": true, + }, + { + "name": "需要客户端证书,但不校验", + "type": SSLClientAuthTypeRequireAnyClientCert, + "requireCA": true, + }, + { + "name": "有客户端证书的时候才校验", + "type": SSLClientAuthTypeVerifyClientCertIfGiven, + "requireCA": true, + }, + { + "name": "校验客户端提供的证书", + "type": SSLClientAuthTypeRequireAndVerifyClientCert, + "requireCA": true, + }, + } +} + +// 查找单个认证方式的名称 +func FindSSLClientAuthTypeName(authType SSLClientAuthType) string { + for _, m := range AllSSLClientAuthTypes() { + if m.GetInt("type") == authType { + return m.GetString("name") + } + } + return "" +} + +// 认证类型和tls包内类型的映射 +func GoSSLClientAuthType(authType SSLClientAuthType) tls.ClientAuthType { + switch authType { + case SSLClientAuthTypeNoClientCert: + return tls.NoClientCert + case SSLClientAuthTypeRequestClientCert: + return tls.RequestClientCert + case SSLClientAuthTypeRequireAnyClientCert: + return tls.RequireAnyClientCert + case SSLClientAuthTypeVerifyClientCertIfGiven: + return tls.VerifyClientCertIfGiven + case SSLClientAuthTypeRequireAndVerifyClientCert: + return tls.RequireAndVerifyClientCert + } + return tls.NoClientCert +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_cert.go b/internal/configs/serverconfigs/sslconfigs/ssl_cert.go new file mode 100644 index 0000000..90ea334 --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_cert.go @@ -0,0 +1,271 @@ +package sslconfigs + +import ( + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/configutils" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/files" + "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/utils/string" + "io/ioutil" + "strings" + "time" +) + +// SSL证书 +type SSLCertConfig struct { + Id string `yaml:"id" json:"id"` + On bool `yaml:"on" json:"on"` + Description string `yaml:"description" json:"description"` // 说明 + CertFile string `yaml:"certFile" json:"certFile"` + KeyFile string `yaml:"keyFile" json:"keyFile"` + IsLocal bool `yaml:"isLocal" json:"isLocal"` // 是否为本地文件 + TaskId string `yaml:"taskId" json:"taskId"` // 生成证书任务ID + IsShared bool `yaml:"isShared" json:"isShared"` // 是否为公用组件 + ServerName string `yaml:"serverName" json:"serverName"` // 证书使用的主机名,在请求TLS服务器时需要 + IsCA bool `yaml:"isCA" json:"isCA"` // 是否为CA证书 + + dnsNames []string + cert *tls.Certificate + timeBefore time.Time + timeAfter time.Time + issuer pkix.Name +} + +// 获取新的SSL证书 +func NewSSLCertConfig(certFile string, keyFile string) *SSLCertConfig { + return &SSLCertConfig{ + On: true, + Id: stringutil.Rand(16), + CertFile: certFile, + KeyFile: keyFile, + } +} + +// 校验 +func (this *SSLCertConfig) Init() error { + if this.IsShared { + shared := this.FindShared() + if shared == nil { + return errors.New("the shared cert has been deleted") + } + + // 拷贝之前需要保留的 + serverName := this.ServerName + + // copy + configutils.CopyStructObject(this, shared) + this.ServerName = serverName + } + + this.dnsNames = []string{} + + if len(this.CertFile) == 0 { + return errors.New("cert file should not be empty") + } + + // 分析证书 + if this.IsCA { // CA证书 + data, err := ioutil.ReadFile(this.FullCertPath()) + if err != nil { + return err + } + + index := -1 + this.cert = &tls.Certificate{ + Certificate: [][]byte{}, + } + for { + index++ + + block, rest := pem.Decode(data) + if block == nil { + break + } + if len(rest) == 0 { + break + } + this.cert.Certificate = append(this.cert.Certificate, block.Bytes) + data = rest + c, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return err + } + if c == nil { + return errors.New("no available certificates in file") + } + + dnsNames := c.DNSNames + if len(dnsNames) > 0 { + for _, dnsName := range dnsNames { + if !lists.ContainsString(this.dnsNames, dnsName) { + this.dnsNames = append(this.dnsNames, dnsName) + } + } + } + + if index == 0 { + this.timeBefore = c.NotBefore + this.timeAfter = c.NotAfter + this.issuer = c.Issuer + } + } + } else { // 证书+私钥 + if len(this.KeyFile) == 0 { + return errors.New("key file should not be empty") + } + cert, err := tls.LoadX509KeyPair(this.FullCertPath(), this.FullKeyPath()) + if err != nil { + return errors.New("load certificate '" + this.CertFile + "', '" + this.KeyFile + "' failed:" + err.Error()) + } + + for index, data := range cert.Certificate { + c, err := x509.ParseCertificate(data) + if err != nil { + continue + } + dnsNames := c.DNSNames + if len(dnsNames) > 0 { + for _, dnsName := range dnsNames { + if !lists.ContainsString(this.dnsNames, dnsName) { + this.dnsNames = append(this.dnsNames, dnsName) + } + } + } + + if index == 0 { + this.timeBefore = c.NotBefore + this.timeAfter = c.NotAfter + this.issuer = c.Issuer + } + } + + this.cert = &cert + } + return nil +} + +// 查找共享的证书 +func (this *SSLCertConfig) FindShared() *SSLCertConfig { + if !this.IsShared { + return nil + } + return SharedSSLCertList().FindCert(this.Id) +} + +// 证书文件路径 +func (this *SSLCertConfig) FullCertPath() string { + if len(this.CertFile) == 0 { + return "" + } + if !strings.ContainsAny(this.CertFile, "/\\") { + return Tea.ConfigFile(this.CertFile) + } + return this.CertFile +} + +// 密钥文件路径 +func (this *SSLCertConfig) FullKeyPath() string { + if len(this.KeyFile) == 0 { + return "" + } + if !strings.ContainsAny(this.KeyFile, "/\\") { + return Tea.ConfigFile(this.KeyFile) + } + return this.KeyFile +} + +// 校验是否匹配某个域名 +func (this *SSLCertConfig) MatchDomain(domain string) bool { + if len(this.dnsNames) == 0 { + return false + } + return configutils.MatchDomains(this.dnsNames, domain) +} + +// 证书中的域名 +func (this *SSLCertConfig) DNSNames() []string { + return this.dnsNames +} + +// 获取证书对象 +func (this *SSLCertConfig) CertObject() *tls.Certificate { + return this.cert +} + +// 开始时间 +func (this *SSLCertConfig) TimeBefore() time.Time { + return this.timeBefore +} + +// 结束时间 +func (this *SSLCertConfig) TimeAfter() time.Time { + return this.timeAfter +} + +// 发行信息 +func (this *SSLCertConfig) Issuer() pkix.Name { + return this.issuer +} + +// 删除文件 +func (this *SSLCertConfig) DeleteFiles() error { + if this.IsLocal { + return nil + } + + var resultErr error = nil + if len(this.CertFile) > 0 && !strings.ContainsAny(this.CertFile, "/\\") { + err := files.NewFile(this.FullCertPath()).Delete() + if err != nil { + resultErr = err + } + } + + if len(this.KeyFile) > 0 && !strings.ContainsAny(this.KeyFile, "/\\") { + err := files.NewFile(this.FullKeyPath()).Delete() + if err != nil { + resultErr = err + } + } + return resultErr +} + +// 读取证书文件 +func (this *SSLCertConfig) ReadCert() ([]byte, error) { + if len(this.CertFile) == 0 { + return nil, errors.New("cert file should not be empty") + } + + if this.IsLocal { + return ioutil.ReadFile(this.CertFile) + } + + return ioutil.ReadFile(Tea.ConfigFile(this.CertFile)) +} + +// 读取密钥文件 +func (this *SSLCertConfig) ReadKey() ([]byte, error) { + if len(this.KeyFile) == 0 { + return nil, errors.New("key file should not be empty") + } + + if this.IsLocal { + return ioutil.ReadFile(this.KeyFile) + } + + return ioutil.ReadFile(Tea.ConfigFile(this.KeyFile)) +} + +// 匹配关键词 +func (this *SSLCertConfig) MatchKeyword(keyword string) (matched bool, name string, tags []string) { + if configutils.MatchKeyword(this.Description, keyword) { + matched = true + name = this.Description + } + return +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_cert_list.go b/internal/configs/serverconfigs/sslconfigs/ssl_cert_list.go new file mode 100644 index 0000000..e1eddbc --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_cert_list.go @@ -0,0 +1,86 @@ +package sslconfigs + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/shared" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/logs" + "gopkg.in/yaml.v3" + "io/ioutil" +) + +const ( + sslCertListFilename = "ssl.certs.conf" +) + +// 获取证书列表实例 +// 一定会返回不为nil的值 +func SharedSSLCertList() *SSLCertList { + data, err := ioutil.ReadFile(Tea.ConfigFile(sslCertListFilename)) + if err != nil { + return NewSSLCertList() + } + + list := &SSLCertList{} + err = yaml.Unmarshal(data, list) + if err != nil { + logs.Error(err) + return NewSSLCertList() + } + + return list +} + +// 公共的SSL证书列表 +type SSLCertList struct { + Certs []*SSLCertConfig `yaml:"certs" json:"certs"` // 证书 +} + +// 获取新对象 +func NewSSLCertList() *SSLCertList { + return &SSLCertList{ + Certs: []*SSLCertConfig{}, + } +} + +// 添加证书 +func (this *SSLCertList) AddCert(cert *SSLCertConfig) { + this.Certs = append(this.Certs, cert) +} + +// 删除证书 +func (this *SSLCertList) RemoveCert(certId string) { + result := []*SSLCertConfig{} + for _, cert := range this.Certs { + if cert.Id == certId { + continue + } + result = append(result, cert) + } + this.Certs = result +} + +// 查找证书 +func (this *SSLCertList) FindCert(certId string) *SSLCertConfig { + if len(certId) == 0 { + return nil + } + for _, cert := range this.Certs { + if cert.Id == certId { + return cert + } + } + return nil +} + +// 保存 +func (this *SSLCertList) Save() error { + shared.Locker.Lock() + defer shared.Locker.Unlock() + + data, err := yaml.Marshal(this) + if err != nil { + return err + } + + return ioutil.WriteFile(Tea.ConfigFile(sslCertListFilename), data, 0777) +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_go_1.11.go b/internal/configs/serverconfigs/sslconfigs/ssl_go_1.11.go new file mode 100644 index 0000000..fbeade1 --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_go_1.11.go @@ -0,0 +1,124 @@ +// +build !go1.12 + +package sslconfigs + +import "crypto/tls" + +var AllTlsVersions = []TLSVersion{"SSL 3.0", "TLS 1.0", "TLS 1.1", "TLS 1.2"} + +var AllTLSCipherSuites = []TLSCipherSuite{ + "TLS_RSA_WITH_RC4_128_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_RSA_WITH_RC4_128_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", +} + +var TLSModernCipherSuites = []string{ + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", +} + +var TLSIntermediateCipherSuites = []string{ + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", +} + +func (this *SSLConfig) convertMinVersion() { + switch this.MinVersion { + case "SSL 3.0": + this.minVersion = tls.VersionSSL30 + case "TLS 1.0": + this.minVersion = tls.VersionTLS10 + case "TLS 1.1": + this.minVersion = tls.VersionTLS11 + case "TLS 1.2": + this.minVersion = tls.VersionTLS12 + default: + this.minVersion = tls.VersionTLS10 + } +} + +func (this *SSLConfig) initCipherSuites() { + // cipher suites + suites := []uint16{} + for _, suite := range this.CipherSuites { + switch suite { + case "TLS_RSA_WITH_RC4_128_SHA": + suites = append(suites, tls.TLS_RSA_WITH_RC4_128_SHA) + case "TLS_RSA_WITH_3DES_EDE_CBC_SHA": + suites = append(suites, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA) + case "TLS_RSA_WITH_AES_128_CBC_SHA": + suites = append(suites, tls.TLS_RSA_WITH_AES_128_CBC_SHA) + case "TLS_RSA_WITH_AES_256_CBC_SHA": + suites = append(suites, tls.TLS_RSA_WITH_AES_256_CBC_SHA) + case "TLS_RSA_WITH_AES_128_CBC_SHA256": + suites = append(suites, tls.TLS_RSA_WITH_AES_128_CBC_SHA256) + case "TLS_RSA_WITH_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_RSA_WITH_AES_128_GCM_SHA256) + case "TLS_RSA_WITH_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_RSA_WITH_AES_256_GCM_SHA384) + case "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) + case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) + case "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) + case "TLS_ECDHE_RSA_WITH_RC4_128_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA) + case "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + case "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) + case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + case "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + case "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + case "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) + case "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + case "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305) + case "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) + } + } + this.cipherSuites = suites +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_go_1.12.go b/internal/configs/serverconfigs/sslconfigs/ssl_go_1.12.go new file mode 100644 index 0000000..b84809f --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_go_1.12.go @@ -0,0 +1,148 @@ +// +build go1.12 + +package sslconfigs + +import ( + "crypto/tls" + "os" +) + +var AllTlsVersions = []TLSVersion{"SSL 3.0", "TLS 1.0", "TLS 1.1", "TLS 1.2", "TLS 1.3"} + +var AllTLSCipherSuites = []TLSCipherSuite{ + "TLS_RSA_WITH_RC4_128_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_RSA_WITH_RC4_128_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", +} + +var TLSModernCipherSuites = []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_AES_256_GCM_SHA384", + + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", +} + +var TLSIntermediateCipherSuites = []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_AES_256_GCM_SHA384", + + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", +} + +func (this *SSLConfig) convertMinVersion() { + switch this.MinVersion { + case "SSL 3.0": + this.minVersion = tls.VersionSSL30 + case "TLS 1.0": + this.minVersion = tls.VersionTLS10 + case "TLS 1.1": + this.minVersion = tls.VersionTLS11 + case "TLS 1.2": + this.minVersion = tls.VersionTLS12 + case "TLS 1.3": + this.minVersion = tls.VersionTLS13 + + os.Setenv("GODEBUG", "tls13=1") // TODO should be removed in go 1.14, in go 1.12 tls IS NOT FULL IMPLEMENTED YET + default: + this.minVersion = tls.VersionTLS10 + } +} + +func (this *SSLConfig) initCipherSuites() { + // cipher suites + suites := []uint16{} + for _, suite := range this.CipherSuites { + switch suite { + case "TLS_RSA_WITH_RC4_128_SHA": + suites = append(suites, tls.TLS_RSA_WITH_RC4_128_SHA) + case "TLS_RSA_WITH_3DES_EDE_CBC_SHA": + suites = append(suites, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA) + case "TLS_RSA_WITH_AES_128_CBC_SHA": + suites = append(suites, tls.TLS_RSA_WITH_AES_128_CBC_SHA) + case "TLS_RSA_WITH_AES_256_CBC_SHA": + suites = append(suites, tls.TLS_RSA_WITH_AES_256_CBC_SHA) + case "TLS_RSA_WITH_AES_128_CBC_SHA256": + suites = append(suites, tls.TLS_RSA_WITH_AES_128_CBC_SHA256) + case "TLS_RSA_WITH_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_RSA_WITH_AES_128_GCM_SHA256) + case "TLS_RSA_WITH_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_RSA_WITH_AES_256_GCM_SHA384) + case "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) + case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) + case "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) + case "TLS_ECDHE_RSA_WITH_RC4_128_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA) + case "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + case "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) + case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + case "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + case "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + case "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) + case "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + case "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": + suites = append(suites, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305) + case "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": + suites = append(suites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) + case "TLS_AES_128_GCM_SHA256": + suites = append(suites, tls.TLS_AES_128_GCM_SHA256) + case "TLS_AES_256_GCM_SHA384": + suites = append(suites, tls.TLS_AES_256_GCM_SHA384) + case "TLS_CHACHA20_POLY1305_SHA256": + suites = append(suites, tls.TLS_CHACHA20_POLY1305_SHA256) + } + } + this.cipherSuites = suites +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_hsts.go b/internal/configs/serverconfigs/sslconfigs/ssl_hsts.go new file mode 100644 index 0000000..d54303a --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_hsts.go @@ -0,0 +1,63 @@ +package sslconfigs + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/configutils" + "strconv" + "strings" +) + +// HSTS设置 +// 参考: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security +type HSTSConfig struct { + On bool `yaml:"on" json:"on"` + MaxAge int `yaml:"maxAge" json:"maxAge"` // 单位秒 + IncludeSubDomains bool `yaml:"includeSubDomains" json:"includeSubDomains"` + Preload bool `yaml:"preload" json:"preload"` + Domains []string `yaml:"domains" json:"domains"` + + hasDomains bool + headerValue string +} + +// 校验 +func (this *HSTSConfig) Init() error { + this.hasDomains = len(this.Domains) > 0 + this.headerValue = this.asHeaderValue() + return nil +} + +// 判断是否匹配域名 +func (this *HSTSConfig) Match(domain string) bool { + if !this.hasDomains { + return true + } + return configutils.MatchDomains(this.Domains, domain) +} + +// Header Key +func (this *HSTSConfig) HeaderKey() string { + return "Strict-Transport-Security" +} + +// 取得当前的Header值 +func (this *HSTSConfig) HeaderValue() string { + return this.headerValue +} + +// 转换为Header值 +func (this *HSTSConfig) asHeaderValue() string { + b := strings.Builder{} + b.WriteString("max-age=") + if this.MaxAge > 0 { + b.WriteString(strconv.Itoa(this.MaxAge)) + } else { + b.WriteString("31536000") // 1 year + } + if this.IncludeSubDomains { + b.WriteString("; includeSubDomains") + } + if this.Preload { + b.WriteString("; preload") + } + return b.String() +} diff --git a/internal/configs/serverconfigs/sslconfigs/ssl_hsts_test.go b/internal/configs/serverconfigs/sslconfigs/ssl_hsts_test.go new file mode 100644 index 0000000..506a2b1 --- /dev/null +++ b/internal/configs/serverconfigs/sslconfigs/ssl_hsts_test.go @@ -0,0 +1,39 @@ +package sslconfigs + +import ( + "github.com/iwind/TeaGo/assert" + "testing" +) + +func TestHSTSConfig(t *testing.T) { + h := &HSTSConfig{} + h.Init() + t.Log(h.HeaderValue()) + + h.IncludeSubDomains = true + h.Init() + t.Log(h.HeaderValue()) + + h.Preload = true + h.Init() + t.Log(h.HeaderValue()) + + h.IncludeSubDomains = false + h.Init() + t.Log(h.HeaderValue()) + + h.MaxAge = 86400 + h.Init() + t.Log(h.HeaderValue()) + + a := assert.NewAssertion(t) + a.IsTrue(h.Match("abc.com")) + + h.Domains = []string{"abc.com"} + h.Init() + a.IsTrue(h.Match("abc.com")) + + h.Domains = []string{"1.abc.com"} + h.Init() + a.IsFalse(h.Match("abc.com")) +} diff --git a/internal/configs/serverconfigs/web_config.go b/internal/configs/serverconfigs/web_config.go new file mode 100644 index 0000000..5daec68 --- /dev/null +++ b/internal/configs/serverconfigs/web_config.go @@ -0,0 +1,10 @@ +package serverconfigs + +type WebConfig struct { + IsOn bool `yaml:"isOn" json:"isOn"` + + Locations []*LocationConfig `yaml:"locations" json:"locations"` // 路径规则 TODO + + // 本地静态资源配置 + Root string `yaml:"root" json:"root"` // 资源根目录 TODO +} diff --git a/internal/configs/web_config.go b/internal/configs/web_config.go deleted file mode 100644 index e4c6e30..0000000 --- a/internal/configs/web_config.go +++ /dev/null @@ -1,8 +0,0 @@ -package configs - -type WebConfig struct { - Locations []*LocationConfig `yaml:"locations"` // 路径规则 - - // 本地静态资源配置 - Root string `yaml:"root" json:"root"` // 资源根目录 -} diff --git a/internal/const/const.go b/internal/const/const.go new file mode 100644 index 0000000..0775da4 --- /dev/null +++ b/internal/const/const.go @@ -0,0 +1,13 @@ +package teaconst + +const ( + Version = "0.0.1" + + ProductName = "Edge Node" + ProcessName = "edge-node" + + Role = "node" + + EncryptKey = "8f983f4d69b83aaa0d74b21a212f6967" + EncryptMethod = "aes-256-cfb" +) diff --git a/internal/encrypt/magic_key.go b/internal/encrypt/magic_key.go new file mode 100644 index 0000000..bf610ef --- /dev/null +++ b/internal/encrypt/magic_key.go @@ -0,0 +1,41 @@ +package encrypt + +import ( + "github.com/iwind/TeaGo/logs" +) + +const ( + MagicKey = "f1c8eafb543f03023e97b7be864a4e9b" +) + +// 加密特殊信息 +func MagicKeyEncode(data []byte) []byte { + method, err := NewMethodInstance("aes-256-cfb", MagicKey, MagicKey[:16]) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + + dst, err := method.Encrypt(data) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + return dst +} + +// 解密特殊信息 +func MagicKeyDecode(data []byte) []byte { + method, err := NewMethodInstance("aes-256-cfb", MagicKey, MagicKey[:16]) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + + src, err := method.Decrypt(data) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + return src +} diff --git a/internal/encrypt/magic_key_test.go b/internal/encrypt/magic_key_test.go new file mode 100644 index 0000000..2d182de --- /dev/null +++ b/internal/encrypt/magic_key_test.go @@ -0,0 +1,11 @@ +package encrypt + +import "testing" + +func TestMagicKeyEncode(t *testing.T) { + dst := MagicKeyEncode([]byte("Hello,World")) + t.Log("dst:", string(dst)) + + src := MagicKeyDecode(dst) + t.Log("src:", string(src)) +} diff --git a/internal/encrypt/method.go b/internal/encrypt/method.go new file mode 100644 index 0000000..a939b97 --- /dev/null +++ b/internal/encrypt/method.go @@ -0,0 +1,12 @@ +package encrypt + +type MethodInterface interface { + // 初始化 + Init(key []byte, iv []byte) error + + // 加密 + Encrypt(src []byte) (dst []byte, err error) + + // 解密 + Decrypt(dst []byte) (src []byte, err error) +} diff --git a/internal/encrypt/method_aes_128_cfb.go b/internal/encrypt/method_aes_128_cfb.go new file mode 100644 index 0000000..6f3eab4 --- /dev/null +++ b/internal/encrypt/method_aes_128_cfb.go @@ -0,0 +1,73 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" +) + +type AES128CFBMethod struct { + iv []byte + block cipher.Block +} + +func (this *AES128CFBMethod) Init(key, iv []byte) error { + // 判断key是否为32长度 + l := len(key) + if l > 16 { + key = key[:16] + } else if l < 16 { + key = append(key, bytes.Repeat([]byte{' '}, 16-l)...) + } + + // 判断iv长度 + l2 := len(iv) + if l2 > aes.BlockSize { + iv = iv[:aes.BlockSize] + } else if l2 < aes.BlockSize { + iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-l2)...) + } + + this.iv = iv + + // block + block, err := aes.NewCipher(key) + if err != nil { + return err + } + this.block = block + + return nil +} + +func (this *AES128CFBMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + dst = make([]byte, len(src)) + encrypter := cipher.NewCFBEncrypter(this.block, this.iv) + encrypter.XORKeyStream(dst, src) + + return +} + +func (this *AES128CFBMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + src = make([]byte, len(dst)) + encrypter := cipher.NewCFBDecrypter(this.block, this.iv) + encrypter.XORKeyStream(src, dst) + + return +} diff --git a/internal/encrypt/method_aes_128_cfb_test.go b/internal/encrypt/method_aes_128_cfb_test.go new file mode 100644 index 0000000..9e1b8f7 --- /dev/null +++ b/internal/encrypt/method_aes_128_cfb_test.go @@ -0,0 +1,92 @@ +package encrypt + +import ( + "runtime" + "strings" + "testing" +) + +func TestAES128CFBMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("aes-128-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src = make([]byte, len(src)) + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} + +func TestAES128CFBMethod_Encrypt2(t *testing.T) { + method, err := NewMethodInstance("aes-128-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + + sources := [][]byte{} + + { + a := []byte{1} + _, err = method.Encrypt(a) + if err != nil { + t.Fatal(err) + } + } + + for i := 0; i < 10; i++ { + src := []byte(strings.Repeat("Hello", 1)) + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + + sources = append(sources, dst) + } + + { + + a := []byte{1} + _, err = method.Decrypt(a) + if err != nil { + t.Fatal(err) + } + } + + for _, dst := range sources { + dst2 := append([]byte{}, dst...) + src2 := make([]byte, len(dst2)) + src2, err := method.Decrypt(dst2) + if err != nil { + t.Fatal(err) + } + t.Log(string(src2)) + } +} + +func BenchmarkAES128CFBMethod_Encrypt(b *testing.B) { + runtime.GOMAXPROCS(1) + + method, err := NewMethodInstance("aes-128-cfb", "abc", "123") + if err != nil { + b.Fatal(err) + } + + src := []byte(strings.Repeat("Hello", 1024)) + for i := 0; i < b.N; i++ { + dst, err := method.Encrypt(src) + if err != nil { + b.Fatal(err) + } + _ = dst + } +} diff --git a/internal/encrypt/method_aes_192_cfb.go b/internal/encrypt/method_aes_192_cfb.go new file mode 100644 index 0000000..1ac4be3 --- /dev/null +++ b/internal/encrypt/method_aes_192_cfb.go @@ -0,0 +1,74 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" +) + +type AES192CFBMethod struct { + block cipher.Block + iv []byte +} + +func (this *AES192CFBMethod) Init(key, iv []byte) error { + // 判断key是否为24长度 + l := len(key) + if l > 24 { + key = key[:24] + } else if l < 24 { + key = append(key, bytes.Repeat([]byte{' '}, 24-l)...) + } + + block, err := aes.NewCipher(key) + if err != nil { + return err + } + this.block = block + + // 判断iv长度 + l2 := len(iv) + if l2 > aes.BlockSize { + iv = iv[:aes.BlockSize] + } else if l2 < aes.BlockSize { + iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-l2)...) + } + + this.iv = iv + + return nil +} + +func (this *AES192CFBMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + dst = make([]byte, len(src)) + + encrypter := cipher.NewCFBEncrypter(this.block, this.iv) + encrypter.XORKeyStream(dst, src) + + return +} + +func (this *AES192CFBMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + src = make([]byte, len(dst)) + + decrypter := cipher.NewCFBDecrypter(this.block, this.iv) + decrypter.XORKeyStream(src, dst) + + return +} diff --git a/internal/encrypt/method_aes_192_cfb_test.go b/internal/encrypt/method_aes_192_cfb_test.go new file mode 100644 index 0000000..968b396 --- /dev/null +++ b/internal/encrypt/method_aes_192_cfb_test.go @@ -0,0 +1,45 @@ +package encrypt + +import ( + "runtime" + "strings" + "testing" +) + +func TestAES192CFBMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("aes-192-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} + +func BenchmarkAES192CFBMethod_Encrypt(b *testing.B) { + runtime.GOMAXPROCS(1) + + method, err := NewMethodInstance("aes-192-cfb", "abc", "123") + if err != nil { + b.Fatal(err) + } + + src := []byte(strings.Repeat("Hello", 1024)) + for i := 0; i < b.N; i++ { + dst, err := method.Encrypt(src) + if err != nil { + b.Fatal(err) + } + _ = dst + } +} diff --git a/internal/encrypt/method_aes_256_cfb.go b/internal/encrypt/method_aes_256_cfb.go new file mode 100644 index 0000000..fb266f6 --- /dev/null +++ b/internal/encrypt/method_aes_256_cfb.go @@ -0,0 +1,72 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" +) + +type AES256CFBMethod struct { + block cipher.Block + iv []byte +} + +func (this *AES256CFBMethod) Init(key, iv []byte) error { + // 判断key是否为32长度 + l := len(key) + if l > 32 { + key = key[:32] + } else if l < 32 { + key = append(key, bytes.Repeat([]byte{' '}, 32-l)...) + } + + block, err := aes.NewCipher(key) + if err != nil { + return err + } + this.block = block + + // 判断iv长度 + l2 := len(iv) + if l2 > aes.BlockSize { + iv = iv[:aes.BlockSize] + } else if l2 < aes.BlockSize { + iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-l2)...) + } + this.iv = iv + + return nil +} + +func (this *AES256CFBMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + dst = make([]byte, len(src)) + + encrypter := cipher.NewCFBEncrypter(this.block, this.iv) + encrypter.XORKeyStream(dst, src) + + return +} + +func (this *AES256CFBMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + src = make([]byte, len(dst)) + decrypter := cipher.NewCFBDecrypter(this.block, this.iv) + decrypter.XORKeyStream(src, dst) + + return +} diff --git a/internal/encrypt/method_aes_256_cfb_test.go b/internal/encrypt/method_aes_256_cfb_test.go new file mode 100644 index 0000000..a694e49 --- /dev/null +++ b/internal/encrypt/method_aes_256_cfb_test.go @@ -0,0 +1,42 @@ +package encrypt + +import "testing" + +func TestAES256CFBMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("aes-256-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} + +func TestAES256CFBMethod_Encrypt2(t *testing.T) { + method, err := NewMethodInstance("aes-256-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} diff --git a/internal/encrypt/method_raw.go b/internal/encrypt/method_raw.go new file mode 100644 index 0000000..b9fb0b9 --- /dev/null +++ b/internal/encrypt/method_raw.go @@ -0,0 +1,26 @@ +package encrypt + +type RawMethod struct { +} + +func (this *RawMethod) Init(key, iv []byte) error { + return nil +} + +func (this *RawMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + dst = make([]byte, len(src)) + copy(dst, src) + return +} + +func (this *RawMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + src = make([]byte, len(dst)) + copy(src, dst) + return +} diff --git a/internal/encrypt/method_raw_test.go b/internal/encrypt/method_raw_test.go new file mode 100644 index 0000000..b9403f6 --- /dev/null +++ b/internal/encrypt/method_raw_test.go @@ -0,0 +1,23 @@ +package encrypt + +import "testing" + +func TestRawMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("raw", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} diff --git a/internal/encrypt/method_utils.go b/internal/encrypt/method_utils.go new file mode 100644 index 0000000..99879ad --- /dev/null +++ b/internal/encrypt/method_utils.go @@ -0,0 +1,43 @@ +package encrypt + +import ( + "errors" + "reflect" +) + +var methods = map[string]reflect.Type{ + "raw": reflect.TypeOf(new(RawMethod)).Elem(), + "aes-128-cfb": reflect.TypeOf(new(AES128CFBMethod)).Elem(), + "aes-192-cfb": reflect.TypeOf(new(AES192CFBMethod)).Elem(), + "aes-256-cfb": reflect.TypeOf(new(AES256CFBMethod)).Elem(), +} + +func NewMethodInstance(method string, key string, iv string) (MethodInterface, error) { + valueType, ok := methods[method] + if !ok { + return nil, errors.New("method '" + method + "' not found") + } + instance, ok := reflect.New(valueType).Interface().(MethodInterface) + if !ok { + return nil, errors.New("method '" + method + "' must implement MethodInterface") + } + err := instance.Init([]byte(key), []byte(iv)) + return instance, err +} + +func RecoverMethodPanic(err interface{}) error { + if err != nil { + s, ok := err.(string) + if ok { + return errors.New(s) + } + + e, ok := err.(error) + if ok { + return e + } + + return errors.New("unknown error") + } + return nil +} diff --git a/internal/encrypt/method_utils_test.go b/internal/encrypt/method_utils_test.go new file mode 100644 index 0000000..faf7e1d --- /dev/null +++ b/internal/encrypt/method_utils_test.go @@ -0,0 +1,8 @@ +package encrypt + +import "testing" + +func TestFindMethodInstance(t *testing.T) { + t.Log(NewMethodInstance("a", "b", "")) + t.Log(NewMethodInstance("aes-256-cfb", "123456", "")) +} diff --git a/internal/nodes/listener.go b/internal/nodes/listener.go index 03f3eaa..b389d93 100644 --- a/internal/nodes/listener.go +++ b/internal/nodes/listener.go @@ -3,17 +3,16 @@ package nodes import ( "context" "errors" - "github.com/TeaOSLab/EdgeNode/internal/configs" + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" "github.com/iwind/TeaGo/logs" "net" - "net/http" "sync" ) type Listener struct { - group *configs.ServerGroup + group *serverconfigs.ServerGroup isListening bool - listener interface{} // 监听器 + listener ListenerImpl // 监听器 locker sync.RWMutex } @@ -22,7 +21,7 @@ func NewListener() *Listener { return &Listener{} } -func (this *Listener) Reload(group *configs.ServerGroup) { +func (this *Listener) Reload(group *serverconfigs.ServerGroup) { this.locker.Lock() defer this.locker.Unlock() this.group = group @@ -40,78 +39,67 @@ func (this *Listener) Listen() error { return nil } protocol := this.group.Protocol() - switch protocol { - case configs.ProtocolHTTP, configs.ProtocolHTTP4, configs.ProtocolHTTP6: - return this.listenHTTP() - case configs.ProtocolHTTPS, configs.ProtocolHTTPS4, configs.ProtocolHTTPS6: - return this.ListenHTTPS() - case configs.ProtocolTCP, configs.ProtocolTCP4, configs.ProtocolTCP6: - return this.listenTCP() - case configs.ProtocolTLS, configs.ProtocolTLS4, configs.ProtocolTLS6: - return this.listenTLS() - case configs.ProtocolUnix: - return this.listenUnix() - case configs.ProtocolUDP: - return this.listenUDP() - default: - return errors.New("unknown protocol '" + protocol + "'") - } -} -func (this *Listener) Close() error { - // TODO 需要实现 - return nil -} - -func (this *Listener) listenHTTP() error { - listener, err := this.createListener() + netListener, err := this.createListener() if err != nil { return err } - mux := http.NewServeMux() - mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { - _, _ = writer.Write([]byte("Hello, World")) - }) - server := &http.Server{ - Addr: this.group.Addr(), - Handler: mux, + switch protocol { + case serverconfigs.ProtocolHTTP, serverconfigs.ProtocolHTTP4, serverconfigs.ProtocolHTTP6: + this.listener = &HTTPListener{ + Group: this.group, + Listener: netListener, + } + case serverconfigs.ProtocolHTTPS, serverconfigs.ProtocolHTTPS4, serverconfigs.ProtocolHTTPS6: + this.listener = &HTTPListener{ + Group: this.group, + Listener: netListener, + } + case serverconfigs.ProtocolTCP, serverconfigs.ProtocolTCP4, serverconfigs.ProtocolTCP6: + this.listener = &TCPListener{ + Group: this.group, + Listener: netListener, + } + case serverconfigs.ProtocolTLS, serverconfigs.ProtocolTLS4, serverconfigs.ProtocolTLS6: + this.listener = &TCPListener{ + Group: this.group, + Listener: netListener, + } + case serverconfigs.ProtocolUnix: + this.listener = &UnixListener{ + Group: this.group, + Listener: netListener, + } + case serverconfigs.ProtocolUDP: + this.listener = &UDPListener{ + Group: this.group, + Listener: netListener, + } + default: + return errors.New("unknown protocol '" + protocol + "'") } + this.listener.Init() + go func() { - err = server.Serve(listener) + err := this.listener.Serve() if err != nil { logs.Println("[LISTENER]" + err.Error()) } }() + return nil } -func (this *Listener) ListenHTTPS() error { - // TODO 需要实现 - return nil -} - -func (this *Listener) listenTCP() error { - // TODO 需要实现 - return nil -} - -func (this *Listener) listenTLS() error { - // TODO 需要实现 - return nil -} - -func (this *Listener) listenUnix() error { - // TODO 需要实现 - return nil -} - -func (this *Listener) listenUDP() error { - // TODO 需要实现 - return nil +func (this *Listener) Close() error { + if this.listener == nil { + return nil + } + return this.listener.Close() } +// 创建监听器 func (this *Listener) createListener() (net.Listener, error) { listenConfig := net.ListenConfig{ Control: nil, @@ -119,9 +107,9 @@ func (this *Listener) createListener() (net.Listener, error) { } switch this.group.Protocol() { - case configs.ProtocolHTTP4, configs.ProtocolHTTPS4, configs.ProtocolTLS4: + case serverconfigs.ProtocolHTTP4, serverconfigs.ProtocolHTTPS4, serverconfigs.ProtocolTLS4: return listenConfig.Listen(context.Background(), "tcp4", this.group.Addr()) - case configs.ProtocolHTTP6, configs.ProtocolHTTPS6, configs.ProtocolTLS6: + case serverconfigs.ProtocolHTTP6, serverconfigs.ProtocolHTTPS6, serverconfigs.ProtocolTLS6: return listenConfig.Listen(context.Background(), "tcp6", this.group.Addr()) } diff --git a/internal/nodes/listener_base.go b/internal/nodes/listener_base.go new file mode 100644 index 0000000..a3a968c --- /dev/null +++ b/internal/nodes/listener_base.go @@ -0,0 +1,195 @@ +package nodes + +import ( + "crypto/tls" + "errors" + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs/sslconfigs" + http2 "golang.org/x/net/http2" + "sync" +) + +type BaseListener struct { + serversLocker sync.RWMutex + namedServersLocker sync.RWMutex + namedServers map[string]*NamedServer // 域名 => server +} + +// 初始化 +func (this *BaseListener) Init() { + this.namedServers = map[string]*NamedServer{} +} + +// 构造TLS配置 +func (this *BaseListener) buildTLSConfig(group *serverconfigs.ServerGroup) *tls.Config { + return &tls.Config{ + Certificates: nil, + GetConfigForClient: func(info *tls.ClientHelloInfo) (config *tls.Config, e error) { + ssl, _, err := this.matchSSL(group, info.ServerName) + if err != nil { + return nil, err + } + + cipherSuites := ssl.TLSCipherSuites() + if len(cipherSuites) == 0 { + cipherSuites = nil + } + + nextProto := []string{} + if !ssl.HTTP2Disabled { + nextProto = []string{http2.NextProtoTLS} + } + return &tls.Config{ + Certificates: nil, + MinVersion: ssl.TLSMinVersion(), + CipherSuites: cipherSuites, + GetCertificate: func(info *tls.ClientHelloInfo) (certificate *tls.Certificate, e error) { + _, cert, err := this.matchSSL(group, info.ServerName) + if err != nil { + return nil, err + } + if cert == nil { + return nil, errors.New("[proxy]no certs found for '" + info.ServerName + "'") + } + return cert, nil + }, + ClientAuth: sslconfigs.GoSSLClientAuthType(ssl.ClientAuthType), + ClientCAs: ssl.CAPool(), + + NextProtos: nextProto, + }, nil + }, + GetCertificate: func(info *tls.ClientHelloInfo) (certificate *tls.Certificate, e error) { + _, cert, err := this.matchSSL(group, info.ServerName) + if err != nil { + return nil, err + } + if cert == nil { + return nil, errors.New("[proxy]no certs found for '" + info.ServerName + "'") + } + return cert, nil + }, + } +} + +// 根据域名匹配证书 +func (this *BaseListener) matchSSL(group *serverconfigs.ServerGroup, domain string) (*sslconfigs.SSLConfig, *tls.Certificate, error) { + this.serversLocker.RLock() + defer this.serversLocker.RUnlock() + + // 如果域名为空,则取第一个 + // 通常域名为空是因为是直接通过IP访问的 + if len(domain) == 0 { + if serverconfigs.SharedGlobalConfig().HTTPAll.MatchDomainStrictly { + return nil, nil, errors.New("no tls server name matched") + } + + firstServer := group.FirstServer() + if firstServer == nil { + return nil, nil, errors.New("no server available") + } + sslConfig := firstServer.SSLConfig() + + if sslConfig != nil { + return sslConfig, sslConfig.FirstCert(), nil + + } + return nil, nil, errors.New("no tls server name found") + } + + // 通过代理服务域名配置匹配 + server, _ := this.findNamedServer(group, domain) + if server == nil || server.SSLConfig() == nil || !server.SSLConfig().IsOn { + // 搜索所有的Server,通过SSL证书内容中的DNSName匹配 + for _, server := range group.Servers { + if server.SSLConfig() == nil || !server.SSLConfig().IsOn { + continue + } + cert, ok := server.SSLConfig().MatchDomain(domain) + if ok { + return server.SSLConfig(), cert, nil + } + } + + return nil, nil, errors.New("[proxy]no server found for '" + domain + "'") + } + + // 证书是否匹配 + sslConfig := server.SSLConfig() + cert, ok := sslConfig.MatchDomain(domain) + if ok { + return sslConfig, cert, nil + } + + return sslConfig, sslConfig.FirstCert(), nil +} + +// 根据域名来查找匹配的域名 +func (this *BaseListener) findNamedServer(group *serverconfigs.ServerGroup, name string) (serverConfig *serverconfigs.ServerConfig, serverName string) { + // 读取缓存 + this.namedServersLocker.RLock() + namedServer, found := this.namedServers[name] + if found { + this.namedServersLocker.RUnlock() + return namedServer.Server, namedServer.Name + } + this.namedServersLocker.RUnlock() + + this.serversLocker.RLock() + defer this.serversLocker.RUnlock() + + currentServers := group.Servers + countServers := len(currentServers) + if countServers == 0 { + return nil, "" + } + + // 只记录N个记录,防止内存耗尽 + maxNamedServers := 10240 + + // 是否严格匹配域名 + matchDomainStrictly := serverconfigs.SharedGlobalConfig().HTTPAll.MatchDomainStrictly + + // 如果只有一个server,则默认为这个 + if countServers == 1 && !matchDomainStrictly { + return currentServers[0], name + } + + // 精确查找 + for _, server := range currentServers { + if server.MatchNameStrictly(name) { + this.namedServersLocker.Lock() + if len(this.namedServers) < maxNamedServers { + this.namedServers[name] = &NamedServer{ + Name: name, + Server: server, + } + } + this.namedServersLocker.Unlock() + return server, name + } + } + + // 模糊查找 + for _, server := range currentServers { + if matched := server.MatchName(name); matched { + this.namedServersLocker.Lock() + if len(this.namedServers) < maxNamedServers { + this.namedServers[name] = &NamedServer{ + Name: name, + Server: server, + } + } + this.namedServersLocker.Unlock() + return server, name + } + } + + // 找不到而且域名严格匹配模式下不返回Server + if matchDomainStrictly { + return nil, name + } + + // 如果没有找到,则匹配到第一个 + return currentServers[0], name +} diff --git a/internal/nodes/listener_http.go b/internal/nodes/listener_http.go new file mode 100644 index 0000000..7f9984b --- /dev/null +++ b/internal/nodes/listener_http.go @@ -0,0 +1,68 @@ +package nodes + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" + "github.com/iwind/TeaGo/logs" + "golang.org/x/net/http2" + "net" + "net/http" + "time" +) + +type HTTPListener struct { + BaseListener + + Group *serverconfigs.ServerGroup + Listener net.Listener + + httpServer *http.Server +} + +func (this *HTTPListener) Serve() error { + handler := http.NewServeMux() + handler.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { + this.handleHTTP(writer, request) + }) + + this.httpServer = &http.Server{ + Addr: this.Group.Addr(), + Handler: handler, + IdleTimeout: 2 * time.Minute, + } + this.httpServer.SetKeepAlivesEnabled(true) + + // HTTP协议 + if this.Group.IsHTTP() { + err := this.httpServer.Serve(this.Listener) + if err != nil && err != http.ErrServerClosed { + return err + } + } + + // HTTPS协议 + if this.Group.IsHTTPS() { + this.httpServer.TLSConfig = this.buildTLSConfig(this.Group) + + // support http/2 + err := http2.ConfigureServer(this.httpServer, nil) + if err != nil { + logs.Println("[HTTP_LISTENER]configure http2 error: " + err.Error()) + } + + err = this.httpServer.ServeTLS(this.Listener, "", "") + if err != nil && err != http.ErrServerClosed { + return err + } + } + + return nil +} + +func (this *HTTPListener) Close() error { + // TODO + return nil +} + +func (this *HTTPListener) handleHTTP(writer http.ResponseWriter, req *http.Request) { + writer.Write([]byte("Hello, World")) +} diff --git a/internal/nodes/listener_impl.go b/internal/nodes/listener_impl.go new file mode 100644 index 0000000..38ed2ba --- /dev/null +++ b/internal/nodes/listener_impl.go @@ -0,0 +1,13 @@ +package nodes + +// 各协议监听器的具体实现 +type ListenerImpl interface { + // 初始化 + Init() + + // 监听 + Serve() error + + // 关闭 + Close() error +} diff --git a/internal/nodes/listener_manager.go b/internal/nodes/listener_manager.go index 63030fd..002450d 100644 --- a/internal/nodes/listener_manager.go +++ b/internal/nodes/listener_manager.go @@ -4,6 +4,8 @@ import ( "github.com/TeaOSLab/EdgeNode/internal/configs" "github.com/iwind/TeaGo/lists" "github.com/iwind/TeaGo/logs" + "net/url" + "regexp" "sync" ) @@ -12,6 +14,7 @@ var sharedListenerManager = NewListenerManager() type ListenerManager struct { listenersMap map[string]*Listener // addr => *Listener locker sync.Mutex + lastConfig *configs.NodeConfig } func NewListenerManager() *ListenerManager { @@ -24,6 +27,18 @@ func (this *ListenerManager) Start(node *configs.NodeConfig) error { this.locker.Lock() defer this.locker.Unlock() + // 检查是否有变化 + if this.lastConfig != nil && this.lastConfig.Version == node.Version { + return nil + } + this.lastConfig = node + + // 初始化 + err := node.Init() + if err != nil { + return err + } + // 所有的新地址 groupAddrs := []string{} for _, group := range node.AvailableGroups() { @@ -45,15 +60,16 @@ func (this *ListenerManager) Start(node *configs.NodeConfig) error { addr := group.FullAddr() listener, ok := this.listenersMap[addr] if ok { - logs.Println("[LISTENER_MANAGER]reload '" + addr + "'") + logs.Println("[LISTENER_MANAGER]reload '" + this.prettyAddress(addr) + "'") listener.Reload(group) } else { - logs.Println("[LISTENER_MANAGER]listen '" + addr + "'") + logs.Println("[LISTENER_MANAGER]listen '" + this.prettyAddress(addr) + "'") listener = NewListener() listener.Reload(group) err := listener.Listen() if err != nil { - return err + logs.Println("[LISTENER_MANAGER]" + err.Error()) + continue } this.listenersMap[addr] = listener } @@ -61,3 +77,14 @@ func (this *ListenerManager) Start(node *configs.NodeConfig) error { return nil } + +func (this *ListenerManager) prettyAddress(addr string) string { + u, err := url.Parse(addr) + if err != nil { + return addr + } + if regexp.MustCompile(`^:\d+$`).MatchString(u.Host) { + u.Host = "*" + u.Host + } + return u.String() +} diff --git a/internal/nodes/listener_manager_test.go b/internal/nodes/listener_manager_test.go index 9966597..6ad167e 100644 --- a/internal/nodes/listener_manager_test.go +++ b/internal/nodes/listener_manager_test.go @@ -12,15 +12,29 @@ func TestListenerManager_Listen(t *testing.T) { { IsOn: true, HTTP: &configs.HTTPProtocolConfig{ - IsOn: true, - Listen: []string{"127.0.0.1:1234"}, + BaseProtocol: configs.BaseProtocol{ + IsOn: true, + Listen: []*configs.NetworkAddressConfig{ + { + Protocol: configs.ProtocolHTTP, + PortRange: "1234", + }, + }, + }, }, }, { IsOn: true, HTTP: &configs.HTTPProtocolConfig{ - IsOn: true, - Listen: []string{"127.0.0.1:1235"}, + BaseProtocol: configs.BaseProtocol{ + IsOn: true, + Listen: []*configs.NetworkAddressConfig{ + { + Protocol: configs.ProtocolHTTP, + PortRange: "1235", + }, + }, + }, }, }, }, @@ -34,15 +48,29 @@ func TestListenerManager_Listen(t *testing.T) { { IsOn: true, HTTP: &configs.HTTPProtocolConfig{ - IsOn: true, - Listen: []string{"127.0.0.1:1234"}, + BaseProtocol: configs.BaseProtocol{ + IsOn: true, + Listen: []*configs.NetworkAddressConfig{ + { + Protocol: configs.ProtocolHTTP, + PortRange: "1234", + }, + }, + }, }, }, { IsOn: true, HTTP: &configs.HTTPProtocolConfig{ - IsOn: true, - Listen: []string{"127.0.0.1:1236"}, + BaseProtocol: configs.BaseProtocol{ + IsOn: true, + Listen: []*configs.NetworkAddressConfig{ + { + Protocol: configs.ProtocolHTTP, + PortRange: "1236", + }, + }, + }, }, }, }, diff --git a/internal/nodes/listener_tcp.go b/internal/nodes/listener_tcp.go new file mode 100644 index 0000000..f0eb92b --- /dev/null +++ b/internal/nodes/listener_tcp.go @@ -0,0 +1,23 @@ +package nodes + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" + "net" +) + +type TCPListener struct { + BaseListener + + Group *serverconfigs.ServerGroup + Listener net.Listener +} + +func (this *TCPListener) Serve() error { + // TODO + return nil +} + +func (this *TCPListener) Close() error { + // TODO + return nil +} diff --git a/internal/nodes/listener_udp.go b/internal/nodes/listener_udp.go new file mode 100644 index 0000000..e274b63 --- /dev/null +++ b/internal/nodes/listener_udp.go @@ -0,0 +1,23 @@ +package nodes + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" + "net" +) + +type UDPListener struct { + BaseListener + + Group *serverconfigs.ServerGroup + Listener net.Listener +} + +func (this *UDPListener) Serve() error { + // TODO + return nil +} + +func (this *UDPListener) Close() error { + // TODO + return nil +} diff --git a/internal/nodes/listener_unix.go b/internal/nodes/listener_unix.go new file mode 100644 index 0000000..bf6a5cb --- /dev/null +++ b/internal/nodes/listener_unix.go @@ -0,0 +1,23 @@ +package nodes + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" + "net" +) + +type UnixListener struct { + BaseListener + + Group *serverconfigs.ServerGroup + Listener net.Listener +} + +func (this *UnixListener) Serve() error { + // TODO + return nil +} + +func (this *UnixListener) Close() error { + // TODO + return nil +} diff --git a/internal/nodes/named_server.go b/internal/nodes/named_server.go new file mode 100644 index 0000000..f65441a --- /dev/null +++ b/internal/nodes/named_server.go @@ -0,0 +1,9 @@ +package nodes + +import "github.com/TeaOSLab/EdgeNode/internal/configs/serverconfigs" + +// 域名和服务映射 +type NamedServer struct { + Name string // 匹配后的域名 + Server *serverconfigs.ServerConfig // 匹配后的服务配置 +} diff --git a/internal/nodes/node.go b/internal/nodes/node.go index f0b797f..f2c620e 100644 --- a/internal/nodes/node.go +++ b/internal/nodes/node.go @@ -1,14 +1,20 @@ package nodes import ( + "encoding/json" + "errors" "github.com/TeaOSLab/EdgeNode/internal/configs" + "github.com/TeaOSLab/EdgeNode/internal/rpc" + "github.com/TeaOSLab/EdgeNode/internal/rpc/pb" "github.com/TeaOSLab/EdgeNode/internal/utils" "github.com/iwind/TeaGo/logs" + "time" ) -var sharedNodeConfig *configs.NodeConfig = nil var stop = make(chan bool) +var lastVersion = -1 +// 节点 type Node struct { } @@ -17,13 +23,24 @@ func NewNode() *Node { } func (this *Node) Start() { + // 读取API配置 + err := this.syncConfig(false) + if err != nil { + logs.Println(err.Error()) + } + + // 启动同步计时器 + this.startSyncTimer() + + // 状态变更计时器 + go NewNodeStatusExecutor().Listen() + // 读取配置 nodeConfig, err := configs.SharedNodeConfig() if err != nil { logs.Println("[NODE]start failed: read node config failed: " + err.Error()) return } - sharedNodeConfig = nodeConfig // 设置rlimit _ = utils.SetRLimit(1024 * 1024) @@ -37,3 +54,59 @@ func (this *Node) Start() { // hold住进程 <-stop } + +// 读取API配置 +func (this *Node) syncConfig(isFirstTime bool) error { + rpcClient, err := rpc.SharedRPC() + if err != nil { + return errors.New("[NODE]create rpc client failed: " + err.Error()) + } + configResp, err := rpcClient.NodeRPC().ComposeNodeConfig(rpcClient.Context(), &pb.ComposeNodeConfigRequest{}) + if err != nil { + return errors.New("[NODE]read config from rpc failed: " + err.Error()) + } + configBytes := configResp.ConfigJSON + nodeConfig := &configs.NodeConfig{} + err = json.Unmarshal(configBytes, nodeConfig) + if err != nil { + return errors.New("[NODE]decode config failed: " + err.Error()) + } + + // 写入到文件中 + err = nodeConfig.Save() + if err != nil { + return err + } + + // 如果版本相同,则只是保存 + if lastVersion == nodeConfig.Version { + return nil + } + lastVersion = nodeConfig.Version + + // 刷新配置 + err = configs.ReloadNodeConfig() + if err != nil { + return err + } + + if !isFirstTime { + return sharedListenerManager.Start(nodeConfig) + } + + return nil +} + +// 启动同步计时器 +func (this *Node) startSyncTimer() { + ticker := time.NewTicker(60 * time.Second) + go func() { + for range ticker.C { + err := this.syncConfig(false) + if err != nil { + logs.Println("[NODE]sync config error: " + err.Error()) + continue + } + } + }() +} diff --git a/internal/nodes/node_status.go b/internal/nodes/node_status.go new file mode 100644 index 0000000..8dd237b --- /dev/null +++ b/internal/nodes/node_status.go @@ -0,0 +1,24 @@ +package nodes + +// 节点状态 +type NodeStatus struct { + Version string `json:"version"` + Hostname string `json:"hostname"` + HostIP string `json:"hostIP"` + CPUUsage float64 `json:"cpuUsage"` + CPULogicalCount int `json:"cpuLogicalCount"` + CPUPhysicalCount int `json:"cpuPhysicalCount"` + MemoryUsage float64 `json:"memoryUsage"` + MemoryTotal uint64 `json:"memoryTotal"` + DiskUsage float64 `json:"diskUsage"` + DiskMaxUsage float64 `json:"diskMaxUsage"` + DiskMaxUsagePartition string `json:"diskMaxUsagePartition"` + DiskTotal uint64 `json:"diskTotal"` + UpdatedAt int64 `json:"updatedAt"` + Load1m float64 `json:"load1m"` + Load5m float64 `json:"load5m"` + Load15m float64 `json:"load15m"` + + IsActive bool `json:"isActive"` + Error string `json:"error"` +} diff --git a/internal/nodes/node_status_executor.go b/internal/nodes/node_status_executor.go new file mode 100644 index 0000000..0726578 --- /dev/null +++ b/internal/nodes/node_status_executor.go @@ -0,0 +1,172 @@ +package nodes + +import ( + "encoding/json" + teaconst "github.com/TeaOSLab/EdgeNode/internal/const" + "github.com/TeaOSLab/EdgeNode/internal/rpc" + "github.com/TeaOSLab/EdgeNode/internal/rpc/pb" + "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/logs" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "os" + "runtime" + "strings" + "time" +) + +type NodeStatusExecutor struct { + isFirstTime bool + + cpuUpdatedTime time.Time + cpuLogicalCount int + cpuPhysicalCount int +} + +func NewNodeStatusExecutor() *NodeStatusExecutor { + return &NodeStatusExecutor{} +} + +func (this *NodeStatusExecutor) Listen() { + this.isFirstTime = true + this.cpuUpdatedTime = time.Now() + this.update() + + ticker := time.NewTicker(60 * time.Second) + for range ticker.C { + this.isFirstTime = false + this.update() + } +} + +func (this *NodeStatusExecutor) update() { + status := &NodeStatus{} + status.Version = teaconst.Version + status.IsActive = true + + hostname, _ := os.Hostname() + status.Hostname = hostname + + this.updateCPU(status) + this.updateMem(status) + this.updateLoad(status) + this.updateDisk(status) + status.UpdatedAt = time.Now().Unix() + + // 发送数据 + jsonData, err := json.Marshal(status) + if err != nil { + logs.Println("[NODE]serial NodeStatus fail: " + err.Error()) + return + } + rpcClient, err := rpc.SharedRPC() + if err != nil { + logs.Println("[NODE]failed to open rpc: " + err.Error()) + return + } + _, err = rpcClient.NodeRPC().UpdateNodeStatus(rpcClient.Context(), &pb.UpdateNodeStatusRequest{ + StatusJSON: jsonData, + }) + if err != nil { + logs.Println("[NODE]rpc UpdateNodeStatus() failed: " + err.Error()) + return + } +} + +// 更新CPU +func (this *NodeStatusExecutor) updateCPU(status *NodeStatus) { + duration := time.Duration(0) + if this.isFirstTime { + duration = 100 * time.Millisecond + } + percents, err := cpu.Percent(duration, false) + if err != nil { + status.Error = err.Error() + return + } + if len(percents) == 0 { + return + } + status.CPUUsage = percents[0] / 100 + + if time.Since(this.cpuUpdatedTime) > 300*time.Second { // 每隔5分钟才会更新一次 + this.cpuUpdatedTime = time.Now() + + status.CPULogicalCount, err = cpu.Counts(true) + if err != nil { + status.Error = err.Error() + return + } + status.CPUPhysicalCount, err = cpu.Counts(false) + if err != nil { + status.Error = err.Error() + return + } + this.cpuLogicalCount = status.CPULogicalCount + this.cpuPhysicalCount = status.CPUPhysicalCount + } else { + status.CPULogicalCount = this.cpuLogicalCount + status.CPUPhysicalCount = this.cpuPhysicalCount + } +} + +// 更新硬盘 +func (this *NodeStatusExecutor) updateDisk(status *NodeStatus) { + partitions, err := disk.Partitions(false) + if err != nil { + logs.Error(err) + return + } + lists.Sort(partitions, func(i int, j int) bool { + p1 := partitions[i] + p2 := partitions[j] + return p1.Mountpoint > p2.Mountpoint + }) + + // 当前TeaWeb所在的fs + rootFS := "" + rootTotal := uint64(0) + if lists.ContainsString([]string{"darwin", "linux", "freebsd"}, runtime.GOOS) { + for _, p := range partitions { + if p.Mountpoint == "/" { + rootFS = p.Fstype + usage, _ := disk.Usage(p.Mountpoint) + if usage != nil { + rootTotal = usage.Total + } + break + } + } + } + + total := rootTotal + totalUsage := uint64(0) + maxUsage := float64(0) + for _, partition := range partitions { + if runtime.GOOS != "windows" && !strings.Contains(partition.Device, "/") && !strings.Contains(partition.Device, "\\") { + continue + } + + // 跳过不同fs的 + if len(rootFS) > 0 && rootFS != partition.Fstype { + continue + } + + usage, err := disk.Usage(partition.Mountpoint) + if err != nil { + continue + } + + if partition.Mountpoint != "/" && (usage.Total != rootTotal || total == 0) { + total += usage.Total + } + totalUsage += usage.Used + if usage.UsedPercent >= maxUsage { + maxUsage = usage.UsedPercent + status.DiskMaxUsagePartition = partition.Mountpoint + } + } + status.DiskTotal = total + status.DiskUsage = float64(totalUsage) / float64(total) + status.DiskMaxUsage = maxUsage / 100 +} diff --git a/internal/nodes/node_status_executor_unix.go b/internal/nodes/node_status_executor_unix.go new file mode 100644 index 0000000..947efdd --- /dev/null +++ b/internal/nodes/node_status_executor_unix.go @@ -0,0 +1,40 @@ +// +build !windows + +package nodes + +import ( + "github.com/shirou/gopsutil/load" + "github.com/shirou/gopsutil/mem" +) + +// 更新内存 +func (this *NodeStatusExecutor) updateMem(status *NodeStatus) { + stat, err := mem.VirtualMemory() + if err != nil { + return + } + + // 重新计算内存 + if stat.Total > 0 { + stat.Used = stat.Total - stat.Free - stat.Buffers - stat.Cached + status.MemoryUsage = float64(stat.Used) / float64(stat.Total) + } + + status.MemoryTotal = stat.Total +} + +// 更新负载 +func (this *NodeStatusExecutor) updateLoad(status *NodeStatus) { + stat, err := load.Avg() + if err != nil { + status.Error = err.Error() + return + } + if stat == nil { + status.Error = "load is nil" + return + } + status.Load1m = stat.Load1 + status.Load5m = stat.Load5 + status.Load15m = stat.Load15 +} diff --git a/internal/nodes/node_status_executor_windows.go b/internal/nodes/node_status_executor_windows.go new file mode 100644 index 0000000..c49a912 --- /dev/null +++ b/internal/nodes/node_status_executor_windows.go @@ -0,0 +1,101 @@ +// +build windows + +package agent + +import ( + "context" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/mem" + "math" + "sync" + "time" +) + +type WindowsLoadValue struct { + Timestamp int64 + Value int +} + +var windowsLoadValues = []*WindowsLoadValue{} +var windowsLoadLocker = &sync.Mutex{} + +// 更新内存 +func (this *NodeStatusExecutor) updateMem(status *NodeStatus) { + stat, err := mem.VirtualMemory() + if err != nil { + status.Error = err.Error() + return + } + status.MemoryUsage = stat.UsedPercent + status.MemoryTotal = stat.Total +} + +// 更新负载 +func (this *NodeStatusExecutor) updateLoad(status *NodeStatus) { + timestamp := time.Now().Unix() + + currentLoad := 0 + info, err := cpu.ProcInfo() + if err == nil && len(info) > 0 && info[0].ProcessorQueueLength < 1000 { + currentLoad = int(info[0].ProcessorQueueLength) + } + + // 删除15分钟之前的数据 + windowsLoadLocker.Lock() + result := []*WindowsLoadValue{} + for _, v := range windowsLoadValues { + if timestamp-v.Timestamp > 15*60 { + continue + } + result = append(result, v) + } + result = append(result, &WindowsLoadValue{ + Timestamp: timestamp, + Value: currentLoad, + }) + windowsLoadValues = result + + total1 := 0 + count1 := 0 + total5 := 0 + count5 := 0 + total15 := 0 + count15 := 0 + for _, v := range result { + if timestamp-v.Timestamp <= 60 { + total1 += v.Value + count1++ + } + + if timestamp-v.Timestamp <= 300 { + total5 += v.Value + count5++ + } + + total15 += v.Value + count15++ + } + + load1 := float64(0) + load5 := float64(0) + load15 := float64(0) + if count1 > 0 { + load1 = math.Round(float64(total1*100)/float64(count1)) / 100 + } + if count5 > 0 { + load5 = math.Round(float64(total5*100)/float64(count5)) / 100 + } + if count15 > 0 { + load15 = math.Round(float64(total15*100)/float64(count15)) / 100 + } + + windowsLoadLocker.Unlock() + + // 在老Windows上不显示错误 + if err == context.DeadlineExceeded { + err = nil + } + status.Load1m = load1 + status.Load5m = load5 + status.Load15m = load15 +} diff --git a/internal/nodes/rpc_client.go b/internal/nodes/rpc_client.go deleted file mode 100644 index 7b62be2..0000000 --- a/internal/nodes/rpc_client.go +++ /dev/null @@ -1,50 +0,0 @@ -package nodes - -import ( - "context" - "errors" - "github.com/TeaOSLab/EdgeNode/internal/configs" - "github.com/TeaOSLab/EdgeNode/internal/rpc/node" - "github.com/iwind/TeaGo/rands" - "google.golang.org/grpc" -) - -type RPCClient struct { - nodeClients []node.ServiceClient -} - -func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) { - nodeClients := []node.ServiceClient{} - - conns := []*grpc.ClientConn{} - for _, endpoint := range apiConfig.RPC.Endpoints { - conn, err := grpc.Dial(endpoint, grpc.WithInsecure()) - if err != nil { - return nil, err - } - conns = append(conns, conn) - } - if len(conns) == 0 { - return nil, errors.New("[RPC]no available endpoints") - } - - // node clients - for _, conn := range conns { - nodeClients = append(nodeClients, node.NewServiceClient(conn)) - } - - return &RPCClient{ - nodeClients: nodeClients, - }, nil -} - -func (this *RPCClient) NodeRPC() node.ServiceClient { - if len(this.nodeClients) > 0 { - return this.nodeClients[rands.Int(0, len(this.nodeClients)-1)] - } - return nil -} - -func (this *RPCClient) Context() context.Context { - return context.Background() -} diff --git a/internal/nodes/rpc_client_test.go b/internal/nodes/rpc_client_test.go deleted file mode 100644 index 7a51e01..0000000 --- a/internal/nodes/rpc_client_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package nodes - -import ( - "github.com/TeaOSLab/EdgeNode/internal/configs" - "github.com/TeaOSLab/EdgeNode/internal/rpc/node" - "testing" - "time" -) - -func TestRPCClient_NodeRPC(t *testing.T) { - before := time.Now() - defer func() { - t.Log(time.Since(before).Seconds()*1000, "ms") - }() - config, err := configs.LoadAPIConfig() - if err != nil { - t.Fatal(err) - } - rpc, err := NewRPCClient(config) - if err != nil { - t.Fatal(err) - } - resp, err := rpc.NodeRPC().Config(rpc.Context(), &node.ConfigRequest{ - NodeId: "123456", - }) - if err != nil { - t.Fatal(err) - } - t.Log(resp) -} diff --git a/internal/rpc/node/service.pb.go b/internal/rpc/node/service.pb.go deleted file mode 100644 index 629cd5b..0000000 --- a/internal/rpc/node/service.pb.go +++ /dev/null @@ -1,299 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.12.3 -// source: node/service.proto - -package node - -import ( - context "context" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type ConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` -} - -func (x *ConfigRequest) Reset() { - *x = ConfigRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_node_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConfigRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConfigRequest) ProtoMessage() {} - -func (x *ConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_node_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConfigRequest.ProtoReflect.Descriptor instead. -func (*ConfigRequest) Descriptor() ([]byte, []int) { - return file_node_service_proto_rawDescGZIP(), []int{0} -} - -func (x *ConfigRequest) GetNodeId() string { - if x != nil { - return x.NodeId - } - return "" -} - -type ConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *ConfigResponse) Reset() { - *x = ConfigResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_node_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConfigResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConfigResponse) ProtoMessage() {} - -func (x *ConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_node_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConfigResponse.ProtoReflect.Descriptor instead. -func (*ConfigResponse) Descriptor() ([]byte, []int) { - return file_node_service_proto_rawDescGZIP(), []int{1} -} - -func (x *ConfigResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -var File_node_service_proto protoreflect.FileDescriptor - -var file_node_service_proto_rawDesc = []byte{ - 0x0a, 0x12, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x27, 0x0a, 0x0d, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, - 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, - 0x65, 0x49, 0x64, 0x22, 0x20, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x32, 0x40, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x13, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x14, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x6e, 0x6f, 0x64, - 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_node_service_proto_rawDescOnce sync.Once - file_node_service_proto_rawDescData = file_node_service_proto_rawDesc -) - -func file_node_service_proto_rawDescGZIP() []byte { - file_node_service_proto_rawDescOnce.Do(func() { - file_node_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_node_service_proto_rawDescData) - }) - return file_node_service_proto_rawDescData -} - -var file_node_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_node_service_proto_goTypes = []interface{}{ - (*ConfigRequest)(nil), // 0: node.ConfigRequest - (*ConfigResponse)(nil), // 1: node.ConfigResponse -} -var file_node_service_proto_depIdxs = []int32{ - 0, // 0: node.Service.config:input_type -> node.ConfigRequest - 1, // 1: node.Service.config:output_type -> node.ConfigResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_node_service_proto_init() } -func file_node_service_proto_init() { - if File_node_service_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_node_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_node_service_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_node_service_proto_goTypes, - DependencyIndexes: file_node_service_proto_depIdxs, - MessageInfos: file_node_service_proto_msgTypes, - }.Build() - File_node_service_proto = out.File - file_node_service_proto_rawDesc = nil - file_node_service_proto_goTypes = nil - file_node_service_proto_depIdxs = nil -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// ServiceClient is the client API for Service service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ServiceClient interface { - Config(ctx context.Context, in *ConfigRequest, opts ...grpc.CallOption) (*ConfigResponse, error) -} - -type serviceClient struct { - cc grpc.ClientConnInterface -} - -func NewServiceClient(cc grpc.ClientConnInterface) ServiceClient { - return &serviceClient{cc} -} - -func (c *serviceClient) Config(ctx context.Context, in *ConfigRequest, opts ...grpc.CallOption) (*ConfigResponse, error) { - out := new(ConfigResponse) - err := c.cc.Invoke(ctx, "/node.Service/config", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ServiceServer is the server API for Service service. -type ServiceServer interface { - Config(context.Context, *ConfigRequest) (*ConfigResponse, error) -} - -// UnimplementedServiceServer can be embedded to have forward compatible implementations. -type UnimplementedServiceServer struct { -} - -func (*UnimplementedServiceServer) Config(context.Context, *ConfigRequest) (*ConfigResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Config not implemented") -} - -func RegisterServiceServer(s *grpc.Server, srv ServiceServer) { - s.RegisterService(&_Service_serviceDesc, srv) -} - -func _Service_Config_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ConfigRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ServiceServer).Config(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/node.Service/Config", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServiceServer).Config(ctx, req.(*ConfigRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Service_serviceDesc = grpc.ServiceDesc{ - ServiceName: "node.Service", - HandlerType: (*ServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "config", - Handler: _Service_Config_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "node/service.proto", -} diff --git a/internal/rpc/node/service.proto b/internal/rpc/node/service.proto deleted file mode 100644 index e706eb2..0000000 --- a/internal/rpc/node/service.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto3"; - -package node; - -option go_package = "./node"; - -service Service { - rpc config (ConfigRequest) returns (ConfigResponse) { - - } -} - -message ConfigRequest { - string nodeId = 1; -} - -message ConfigResponse { - string id = 1; -} \ No newline at end of file diff --git a/internal/rpc/pb/model_node.pb.go b/internal/rpc/pb/model_node.pb.go new file mode 100644 index 0000000..dd6d6bf --- /dev/null +++ b/internal/rpc/pb/model_node.pb.go @@ -0,0 +1,260 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: model_node.proto + +package pb + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type Node struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + InstallDir string `protobuf:"bytes,4,opt,name=installDir,proto3" json:"installDir,omitempty"` + IsInstalled bool `protobuf:"varint,5,opt,name=isInstalled,proto3" json:"isInstalled,omitempty"` + Code string `protobuf:"bytes,6,opt,name=code,proto3" json:"code,omitempty"` + UniqueId string `protobuf:"bytes,7,opt,name=uniqueId,proto3" json:"uniqueId,omitempty"` + Secret string `protobuf:"bytes,8,opt,name=secret,proto3" json:"secret,omitempty"` + Cluster *NodeCluster `protobuf:"bytes,32,opt,name=cluster,proto3" json:"cluster,omitempty"` + Login *NodeLogin `protobuf:"bytes,33,opt,name=login,proto3" json:"login,omitempty"` + InstallStatus *NodeInstallStatus `protobuf:"bytes,34,opt,name=installStatus,proto3" json:"installStatus,omitempty"` +} + +func (x *Node) Reset() { + *x = Node{} + if protoimpl.UnsafeEnabled { + mi := &file_model_node_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Node) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Node) ProtoMessage() {} + +func (x *Node) ProtoReflect() protoreflect.Message { + mi := &file_model_node_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Node.ProtoReflect.Descriptor instead. +func (*Node) Descriptor() ([]byte, []int) { + return file_model_node_proto_rawDescGZIP(), []int{0} +} + +func (x *Node) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Node) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Node) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *Node) GetInstallDir() string { + if x != nil { + return x.InstallDir + } + return "" +} + +func (x *Node) GetIsInstalled() bool { + if x != nil { + return x.IsInstalled + } + return false +} + +func (x *Node) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *Node) GetUniqueId() string { + if x != nil { + return x.UniqueId + } + return "" +} + +func (x *Node) GetSecret() string { + if x != nil { + return x.Secret + } + return "" +} + +func (x *Node) GetCluster() *NodeCluster { + if x != nil { + return x.Cluster + } + return nil +} + +func (x *Node) GetLogin() *NodeLogin { + if x != nil { + return x.Login + } + return nil +} + +func (x *Node) GetInstallStatus() *NodeInstallStatus { + if x != nil { + return x.InstallStatus + } + return nil +} + +var File_model_node_proto protoreflect.FileDescriptor + +var file_model_node_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x18, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x16, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6c, 0x6f, 0x67, + 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x02, 0x0a, 0x04, 0x4e, 0x6f, + 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, + 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x12, 0x20, + 0x0a, 0x0b, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x05, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x21, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x52, 0x05, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x3b, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_model_node_proto_rawDescOnce sync.Once + file_model_node_proto_rawDescData = file_model_node_proto_rawDesc +) + +func file_model_node_proto_rawDescGZIP() []byte { + file_model_node_proto_rawDescOnce.Do(func() { + file_model_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_model_node_proto_rawDescData) + }) + return file_model_node_proto_rawDescData +} + +var file_model_node_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_model_node_proto_goTypes = []interface{}{ + (*Node)(nil), // 0: pb.Node + (*NodeCluster)(nil), // 1: pb.NodeCluster + (*NodeLogin)(nil), // 2: pb.NodeLogin + (*NodeInstallStatus)(nil), // 3: pb.NodeInstallStatus +} +var file_model_node_proto_depIdxs = []int32{ + 1, // 0: pb.Node.cluster:type_name -> pb.NodeCluster + 2, // 1: pb.Node.login:type_name -> pb.NodeLogin + 3, // 2: pb.Node.installStatus:type_name -> pb.NodeInstallStatus + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_model_node_proto_init() } +func file_model_node_proto_init() { + if File_model_node_proto != nil { + return + } + file_model_node_cluster_proto_init() + file_model_node_login_proto_init() + file_model_node_install_status_proto_init() + if !protoimpl.UnsafeEnabled { + file_model_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Node); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_model_node_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_model_node_proto_goTypes, + DependencyIndexes: file_model_node_proto_depIdxs, + MessageInfos: file_model_node_proto_msgTypes, + }.Build() + File_model_node_proto = out.File + file_model_node_proto_rawDesc = nil + file_model_node_proto_goTypes = nil + file_model_node_proto_depIdxs = nil +} diff --git a/internal/rpc/pb/model_node_cluster.pb.go b/internal/rpc/pb/model_node_cluster.pb.go new file mode 100644 index 0000000..4c4ec07 --- /dev/null +++ b/internal/rpc/pb/model_node_cluster.pb.go @@ -0,0 +1,185 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: model_node_cluster.proto + +package pb + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type NodeCluster struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + CreatedAt int64 `protobuf:"varint,3,opt,name=createdAt,proto3" json:"createdAt,omitempty"` + GrantId int64 `protobuf:"varint,4,opt,name=grantId,proto3" json:"grantId,omitempty"` + InstallDir string `protobuf:"bytes,5,opt,name=installDir,proto3" json:"installDir,omitempty"` +} + +func (x *NodeCluster) Reset() { + *x = NodeCluster{} + if protoimpl.UnsafeEnabled { + mi := &file_model_node_cluster_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeCluster) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeCluster) ProtoMessage() {} + +func (x *NodeCluster) ProtoReflect() protoreflect.Message { + mi := &file_model_node_cluster_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeCluster.ProtoReflect.Descriptor instead. +func (*NodeCluster) Descriptor() ([]byte, []int) { + return file_model_node_cluster_proto_rawDescGZIP(), []int{0} +} + +func (x *NodeCluster) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *NodeCluster) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *NodeCluster) GetCreatedAt() int64 { + if x != nil { + return x.CreatedAt + } + return 0 +} + +func (x *NodeCluster) GetGrantId() int64 { + if x != nil { + return x.GrantId + } + return 0 +} + +func (x *NodeCluster) GetInstallDir() string { + if x != nil { + return x.InstallDir + } + return "" +} + +var File_model_node_cluster_proto protoreflect.FileDescriptor + +var file_model_node_cluster_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0x89, + 0x01, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_model_node_cluster_proto_rawDescOnce sync.Once + file_model_node_cluster_proto_rawDescData = file_model_node_cluster_proto_rawDesc +) + +func file_model_node_cluster_proto_rawDescGZIP() []byte { + file_model_node_cluster_proto_rawDescOnce.Do(func() { + file_model_node_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_model_node_cluster_proto_rawDescData) + }) + return file_model_node_cluster_proto_rawDescData +} + +var file_model_node_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_model_node_cluster_proto_goTypes = []interface{}{ + (*NodeCluster)(nil), // 0: pb.NodeCluster +} +var file_model_node_cluster_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_model_node_cluster_proto_init() } +func file_model_node_cluster_proto_init() { + if File_model_node_cluster_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_model_node_cluster_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeCluster); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_model_node_cluster_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_model_node_cluster_proto_goTypes, + DependencyIndexes: file_model_node_cluster_proto_depIdxs, + MessageInfos: file_model_node_cluster_proto_msgTypes, + }.Build() + File_model_node_cluster_proto = out.File + file_model_node_cluster_proto_rawDesc = nil + file_model_node_cluster_proto_goTypes = nil + file_model_node_cluster_proto_depIdxs = nil +} diff --git a/internal/rpc/pb/model_node_grant.pb.go b/internal/rpc/pb/model_node_grant.pb.go new file mode 100644 index 0000000..cb227aa --- /dev/null +++ b/internal/rpc/pb/model_node_grant.pb.go @@ -0,0 +1,223 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: model_node_grant.proto + +package pb + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type NodeGrant struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Method string `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"` + Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,5,opt,name=password,proto3" json:"password,omitempty"` + Su bool `protobuf:"varint,6,opt,name=su,proto3" json:"su,omitempty"` + PrivateKey string `protobuf:"bytes,7,opt,name=privateKey,proto3" json:"privateKey,omitempty"` + Description string `protobuf:"bytes,8,opt,name=description,proto3" json:"description,omitempty"` + NodeId int64 `protobuf:"varint,9,opt,name=nodeId,proto3" json:"nodeId,omitempty"` +} + +func (x *NodeGrant) Reset() { + *x = NodeGrant{} + if protoimpl.UnsafeEnabled { + mi := &file_model_node_grant_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeGrant) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeGrant) ProtoMessage() {} + +func (x *NodeGrant) ProtoReflect() protoreflect.Message { + mi := &file_model_node_grant_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeGrant.ProtoReflect.Descriptor instead. +func (*NodeGrant) Descriptor() ([]byte, []int) { + return file_model_node_grant_proto_rawDescGZIP(), []int{0} +} + +func (x *NodeGrant) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *NodeGrant) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *NodeGrant) GetMethod() string { + if x != nil { + return x.Method + } + return "" +} + +func (x *NodeGrant) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *NodeGrant) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *NodeGrant) GetSu() bool { + if x != nil { + return x.Su + } + return false +} + +func (x *NodeGrant) GetPrivateKey() string { + if x != nil { + return x.PrivateKey + } + return "" +} + +func (x *NodeGrant) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *NodeGrant) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +var File_model_node_grant_proto protoreflect.FileDescriptor + +var file_model_node_grant_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xe9, 0x01, 0x0a, + 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x0e, + 0x0a, 0x02, 0x73, 0x75, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x73, 0x75, 0x12, 0x1e, + 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_model_node_grant_proto_rawDescOnce sync.Once + file_model_node_grant_proto_rawDescData = file_model_node_grant_proto_rawDesc +) + +func file_model_node_grant_proto_rawDescGZIP() []byte { + file_model_node_grant_proto_rawDescOnce.Do(func() { + file_model_node_grant_proto_rawDescData = protoimpl.X.CompressGZIP(file_model_node_grant_proto_rawDescData) + }) + return file_model_node_grant_proto_rawDescData +} + +var file_model_node_grant_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_model_node_grant_proto_goTypes = []interface{}{ + (*NodeGrant)(nil), // 0: pb.NodeGrant +} +var file_model_node_grant_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_model_node_grant_proto_init() } +func file_model_node_grant_proto_init() { + if File_model_node_grant_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_model_node_grant_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeGrant); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_model_node_grant_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_model_node_grant_proto_goTypes, + DependencyIndexes: file_model_node_grant_proto_depIdxs, + MessageInfos: file_model_node_grant_proto_msgTypes, + }.Build() + File_model_node_grant_proto = out.File + file_model_node_grant_proto_rawDesc = nil + file_model_node_grant_proto_goTypes = nil + file_model_node_grant_proto_depIdxs = nil +} diff --git a/internal/rpc/pb/model_node_install_status.pb.go b/internal/rpc/pb/model_node_install_status.pb.go new file mode 100644 index 0000000..331e6db --- /dev/null +++ b/internal/rpc/pb/model_node_install_status.pb.go @@ -0,0 +1,187 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: model_node_install_status.proto + +package pb + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type NodeInstallStatus struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsRunning bool `protobuf:"varint,1,opt,name=isRunning,proto3" json:"isRunning,omitempty"` + IsFinished bool `protobuf:"varint,2,opt,name=isFinished,proto3" json:"isFinished,omitempty"` + IsOk bool `protobuf:"varint,3,opt,name=isOk,proto3" json:"isOk,omitempty"` + Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` + UpdatedAt int64 `protobuf:"varint,5,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"` +} + +func (x *NodeInstallStatus) Reset() { + *x = NodeInstallStatus{} + if protoimpl.UnsafeEnabled { + mi := &file_model_node_install_status_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInstallStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInstallStatus) ProtoMessage() {} + +func (x *NodeInstallStatus) ProtoReflect() protoreflect.Message { + mi := &file_model_node_install_status_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeInstallStatus.ProtoReflect.Descriptor instead. +func (*NodeInstallStatus) Descriptor() ([]byte, []int) { + return file_model_node_install_status_proto_rawDescGZIP(), []int{0} +} + +func (x *NodeInstallStatus) GetIsRunning() bool { + if x != nil { + return x.IsRunning + } + return false +} + +func (x *NodeInstallStatus) GetIsFinished() bool { + if x != nil { + return x.IsFinished + } + return false +} + +func (x *NodeInstallStatus) GetIsOk() bool { + if x != nil { + return x.IsOk + } + return false +} + +func (x *NodeInstallStatus) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *NodeInstallStatus) GetUpdatedAt() int64 { + if x != nil { + return x.UpdatedAt + } + return 0 +} + +var File_model_node_install_status_proto protoreflect.FileDescriptor + +var file_model_node_install_status_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0x99, 0x01, 0x0a, 0x11, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, + 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x46, + 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, + 0x73, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, + 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_model_node_install_status_proto_rawDescOnce sync.Once + file_model_node_install_status_proto_rawDescData = file_model_node_install_status_proto_rawDesc +) + +func file_model_node_install_status_proto_rawDescGZIP() []byte { + file_model_node_install_status_proto_rawDescOnce.Do(func() { + file_model_node_install_status_proto_rawDescData = protoimpl.X.CompressGZIP(file_model_node_install_status_proto_rawDescData) + }) + return file_model_node_install_status_proto_rawDescData +} + +var file_model_node_install_status_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_model_node_install_status_proto_goTypes = []interface{}{ + (*NodeInstallStatus)(nil), // 0: pb.NodeInstallStatus +} +var file_model_node_install_status_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_model_node_install_status_proto_init() } +func file_model_node_install_status_proto_init() { + if File_model_node_install_status_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_model_node_install_status_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInstallStatus); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_model_node_install_status_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_model_node_install_status_proto_goTypes, + DependencyIndexes: file_model_node_install_status_proto_depIdxs, + MessageInfos: file_model_node_install_status_proto_msgTypes, + }.Build() + File_model_node_install_status_proto = out.File + file_model_node_install_status_proto_rawDesc = nil + file_model_node_install_status_proto_goTypes = nil + file_model_node_install_status_proto_depIdxs = nil +} diff --git a/internal/rpc/pb/model_node_login.pb.go b/internal/rpc/pb/model_node_login.pb.go new file mode 100644 index 0000000..75582e2 --- /dev/null +++ b/internal/rpc/pb/model_node_login.pb.go @@ -0,0 +1,174 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: model_node_login.proto + +package pb + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type NodeLogin struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Params []byte `protobuf:"bytes,4,opt,name=params,proto3" json:"params,omitempty"` +} + +func (x *NodeLogin) Reset() { + *x = NodeLogin{} + if protoimpl.UnsafeEnabled { + mi := &file_model_node_login_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeLogin) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeLogin) ProtoMessage() {} + +func (x *NodeLogin) ProtoReflect() protoreflect.Message { + mi := &file_model_node_login_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeLogin.ProtoReflect.Descriptor instead. +func (*NodeLogin) Descriptor() ([]byte, []int) { + return file_model_node_login_proto_rawDescGZIP(), []int{0} +} + +func (x *NodeLogin) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *NodeLogin) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *NodeLogin) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *NodeLogin) GetParams() []byte { + if x != nil { + return x.Params + } + return nil +} + +var File_model_node_login_proto protoreflect.FileDescriptor + +var file_model_node_login_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6c, 0x6f, 0x67, + 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0x5b, 0x0a, 0x09, + 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_model_node_login_proto_rawDescOnce sync.Once + file_model_node_login_proto_rawDescData = file_model_node_login_proto_rawDesc +) + +func file_model_node_login_proto_rawDescGZIP() []byte { + file_model_node_login_proto_rawDescOnce.Do(func() { + file_model_node_login_proto_rawDescData = protoimpl.X.CompressGZIP(file_model_node_login_proto_rawDescData) + }) + return file_model_node_login_proto_rawDescData +} + +var file_model_node_login_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_model_node_login_proto_goTypes = []interface{}{ + (*NodeLogin)(nil), // 0: pb.NodeLogin +} +var file_model_node_login_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_model_node_login_proto_init() } +func file_model_node_login_proto_init() { + if File_model_node_login_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_model_node_login_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeLogin); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_model_node_login_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_model_node_login_proto_goTypes, + DependencyIndexes: file_model_node_login_proto_depIdxs, + MessageInfos: file_model_node_login_proto_msgTypes, + }.Build() + File_model_node_login_proto = out.File + file_model_node_login_proto_rawDesc = nil + file_model_node_login_proto_goTypes = nil + file_model_node_login_proto_depIdxs = nil +} diff --git a/internal/rpc/pb/service_node.pb.go b/internal/rpc/pb/service_node.pb.go new file mode 100644 index 0000000..b893319 --- /dev/null +++ b/internal/rpc/pb/service_node.pb.go @@ -0,0 +1,2426 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: service_node.proto + +package pb + +import ( + context "context" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +// 创建节点 +type CreateNodeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + ClusterId int64 `protobuf:"varint,2,opt,name=clusterId,proto3" json:"clusterId,omitempty"` + Login *NodeLogin `protobuf:"bytes,3,opt,name=Login,proto3" json:"Login,omitempty"` +} + +func (x *CreateNodeRequest) Reset() { + *x = CreateNodeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateNodeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateNodeRequest) ProtoMessage() {} + +func (x *CreateNodeRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateNodeRequest.ProtoReflect.Descriptor instead. +func (*CreateNodeRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateNodeRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CreateNodeRequest) GetClusterId() int64 { + if x != nil { + return x.ClusterId + } + return 0 +} + +func (x *CreateNodeRequest) GetLogin() *NodeLogin { + if x != nil { + return x.Login + } + return nil +} + +type CreateNodeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` +} + +func (x *CreateNodeResponse) Reset() { + *x = CreateNodeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateNodeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateNodeResponse) ProtoMessage() {} + +func (x *CreateNodeResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateNodeResponse.ProtoReflect.Descriptor instead. +func (*CreateNodeResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateNodeResponse) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +// 节点数量 +type CountAllEnabledNodesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CountAllEnabledNodesRequest) Reset() { + *x = CountAllEnabledNodesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountAllEnabledNodesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountAllEnabledNodesRequest) ProtoMessage() {} + +func (x *CountAllEnabledNodesRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CountAllEnabledNodesRequest.ProtoReflect.Descriptor instead. +func (*CountAllEnabledNodesRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{2} +} + +type CountAllEnabledNodesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` +} + +func (x *CountAllEnabledNodesResponse) Reset() { + *x = CountAllEnabledNodesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountAllEnabledNodesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountAllEnabledNodesResponse) ProtoMessage() {} + +func (x *CountAllEnabledNodesResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CountAllEnabledNodesResponse.ProtoReflect.Descriptor instead. +func (*CountAllEnabledNodesResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{3} +} + +func (x *CountAllEnabledNodesResponse) GetCount() int64 { + if x != nil { + return x.Count + } + return 0 +} + +// 列出单页节点 +type ListEnabledNodesMatchRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Offset int64 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"` + Size int64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"` + ClusterId int64 `protobuf:"varint,3,opt,name=clusterId,proto3" json:"clusterId,omitempty"` + InstallState int32 `protobuf:"varint,4,opt,name=installState,proto3" json:"installState,omitempty"` +} + +func (x *ListEnabledNodesMatchRequest) Reset() { + *x = ListEnabledNodesMatchRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListEnabledNodesMatchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListEnabledNodesMatchRequest) ProtoMessage() {} + +func (x *ListEnabledNodesMatchRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListEnabledNodesMatchRequest.ProtoReflect.Descriptor instead. +func (*ListEnabledNodesMatchRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{4} +} + +func (x *ListEnabledNodesMatchRequest) GetOffset() int64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *ListEnabledNodesMatchRequest) GetSize() int64 { + if x != nil { + return x.Size + } + return 0 +} + +func (x *ListEnabledNodesMatchRequest) GetClusterId() int64 { + if x != nil { + return x.ClusterId + } + return 0 +} + +func (x *ListEnabledNodesMatchRequest) GetInstallState() int32 { + if x != nil { + return x.InstallState + } + return 0 +} + +type ListEnabledNodesMatchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Nodes []*Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` +} + +func (x *ListEnabledNodesMatchResponse) Reset() { + *x = ListEnabledNodesMatchResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListEnabledNodesMatchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListEnabledNodesMatchResponse) ProtoMessage() {} + +func (x *ListEnabledNodesMatchResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListEnabledNodesMatchResponse.ProtoReflect.Descriptor instead. +func (*ListEnabledNodesMatchResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{5} +} + +func (x *ListEnabledNodesMatchResponse) GetNodes() []*Node { + if x != nil { + return x.Nodes + } + return nil +} + +// 禁用节点 +type DisableNodeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` +} + +func (x *DisableNodeRequest) Reset() { + *x = DisableNodeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisableNodeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisableNodeRequest) ProtoMessage() {} + +func (x *DisableNodeRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DisableNodeRequest.ProtoReflect.Descriptor instead. +func (*DisableNodeRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{6} +} + +func (x *DisableNodeRequest) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +type DisableNodeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DisableNodeResponse) Reset() { + *x = DisableNodeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisableNodeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisableNodeResponse) ProtoMessage() {} + +func (x *DisableNodeResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DisableNodeResponse.ProtoReflect.Descriptor instead. +func (*DisableNodeResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{7} +} + +// 修改节点 +type UpdateNodeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + ClusterId int64 `protobuf:"varint,3,opt,name=clusterId,proto3" json:"clusterId,omitempty"` + Login *NodeLogin `protobuf:"bytes,4,opt,name=Login,proto3" json:"Login,omitempty"` +} + +func (x *UpdateNodeRequest) Reset() { + *x = UpdateNodeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateNodeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNodeRequest) ProtoMessage() {} + +func (x *UpdateNodeRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateNodeRequest.ProtoReflect.Descriptor instead. +func (*UpdateNodeRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{8} +} + +func (x *UpdateNodeRequest) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *UpdateNodeRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *UpdateNodeRequest) GetClusterId() int64 { + if x != nil { + return x.ClusterId + } + return 0 +} + +func (x *UpdateNodeRequest) GetLogin() *NodeLogin { + if x != nil { + return x.Login + } + return nil +} + +type UpdateNodeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *UpdateNodeResponse) Reset() { + *x = UpdateNodeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateNodeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNodeResponse) ProtoMessage() {} + +func (x *UpdateNodeResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateNodeResponse.ProtoReflect.Descriptor instead. +func (*UpdateNodeResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{9} +} + +// 查找节点 +type FindEnabledNodeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` +} + +func (x *FindEnabledNodeRequest) Reset() { + *x = FindEnabledNodeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindEnabledNodeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindEnabledNodeRequest) ProtoMessage() {} + +func (x *FindEnabledNodeRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindEnabledNodeRequest.ProtoReflect.Descriptor instead. +func (*FindEnabledNodeRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{10} +} + +func (x *FindEnabledNodeRequest) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +type FindEnabledNodeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` +} + +func (x *FindEnabledNodeResponse) Reset() { + *x = FindEnabledNodeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindEnabledNodeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindEnabledNodeResponse) ProtoMessage() {} + +func (x *FindEnabledNodeResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindEnabledNodeResponse.ProtoReflect.Descriptor instead. +func (*FindEnabledNodeResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{11} +} + +func (x *FindEnabledNodeResponse) GetNode() *Node { + if x != nil { + return x.Node + } + return nil +} + +// 组合单个节点配置 +type ComposeNodeConfigRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ComposeNodeConfigRequest) Reset() { + *x = ComposeNodeConfigRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComposeNodeConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComposeNodeConfigRequest) ProtoMessage() {} + +func (x *ComposeNodeConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComposeNodeConfigRequest.ProtoReflect.Descriptor instead. +func (*ComposeNodeConfigRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{12} +} + +type ComposeNodeConfigResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConfigJSON []byte `protobuf:"bytes,1,opt,name=configJSON,proto3" json:"configJSON,omitempty"` +} + +func (x *ComposeNodeConfigResponse) Reset() { + *x = ComposeNodeConfigResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComposeNodeConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComposeNodeConfigResponse) ProtoMessage() {} + +func (x *ComposeNodeConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComposeNodeConfigResponse.ProtoReflect.Descriptor instead. +func (*ComposeNodeConfigResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{13} +} + +func (x *ComposeNodeConfigResponse) GetConfigJSON() []byte { + if x != nil { + return x.ConfigJSON + } + return nil +} + +// 节点stream +type NodeStreamRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *NodeStreamRequest) Reset() { + *x = NodeStreamRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeStreamRequest) ProtoMessage() {} + +func (x *NodeStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeStreamRequest.ProtoReflect.Descriptor instead. +func (*NodeStreamRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{14} +} + +type NodeStreamResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *NodeStreamResponse) Reset() { + *x = NodeStreamResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeStreamResponse) ProtoMessage() {} + +func (x *NodeStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeStreamResponse.ProtoReflect.Descriptor instead. +func (*NodeStreamResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{15} +} + +// 更新节点状态 +type UpdateNodeStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` + StatusJSON []byte `protobuf:"bytes,2,opt,name=statusJSON,proto3" json:"statusJSON,omitempty"` +} + +func (x *UpdateNodeStatusRequest) Reset() { + *x = UpdateNodeStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateNodeStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNodeStatusRequest) ProtoMessage() {} + +func (x *UpdateNodeStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateNodeStatusRequest.ProtoReflect.Descriptor instead. +func (*UpdateNodeStatusRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{16} +} + +func (x *UpdateNodeStatusRequest) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *UpdateNodeStatusRequest) GetStatusJSON() []byte { + if x != nil { + return x.StatusJSON + } + return nil +} + +type UpdateNodeStatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *UpdateNodeStatusResponse) Reset() { + *x = UpdateNodeStatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateNodeStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNodeStatusResponse) ProtoMessage() {} + +func (x *UpdateNodeStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateNodeStatusResponse.ProtoReflect.Descriptor instead. +func (*UpdateNodeStatusResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{17} +} + +// 同步集群中的节点版本 +type SyncNodesVersionWithClusterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"` +} + +func (x *SyncNodesVersionWithClusterRequest) Reset() { + *x = SyncNodesVersionWithClusterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncNodesVersionWithClusterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncNodesVersionWithClusterRequest) ProtoMessage() {} + +func (x *SyncNodesVersionWithClusterRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncNodesVersionWithClusterRequest.ProtoReflect.Descriptor instead. +func (*SyncNodesVersionWithClusterRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{18} +} + +func (x *SyncNodesVersionWithClusterRequest) GetClusterId() int64 { + if x != nil { + return x.ClusterId + } + return 0 +} + +type SyncNodesVersionWithClusterResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SyncNodesVersionWithClusterResponse) Reset() { + *x = SyncNodesVersionWithClusterResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncNodesVersionWithClusterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncNodesVersionWithClusterResponse) ProtoMessage() {} + +func (x *SyncNodesVersionWithClusterResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncNodesVersionWithClusterResponse.ProtoReflect.Descriptor instead. +func (*SyncNodesVersionWithClusterResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{19} +} + +// 计算匹配的节点数量 +type CountAllEnabledNodesMatchRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"` + InstallState int32 `protobuf:"varint,2,opt,name=installState,proto3" json:"installState,omitempty"` +} + +func (x *CountAllEnabledNodesMatchRequest) Reset() { + *x = CountAllEnabledNodesMatchRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountAllEnabledNodesMatchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountAllEnabledNodesMatchRequest) ProtoMessage() {} + +func (x *CountAllEnabledNodesMatchRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CountAllEnabledNodesMatchRequest.ProtoReflect.Descriptor instead. +func (*CountAllEnabledNodesMatchRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{20} +} + +func (x *CountAllEnabledNodesMatchRequest) GetClusterId() int64 { + if x != nil { + return x.ClusterId + } + return 0 +} + +func (x *CountAllEnabledNodesMatchRequest) GetInstallState() int32 { + if x != nil { + return x.InstallState + } + return 0 +} + +type CountAllEnabledNodesMatchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` +} + +func (x *CountAllEnabledNodesMatchResponse) Reset() { + *x = CountAllEnabledNodesMatchResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountAllEnabledNodesMatchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountAllEnabledNodesMatchResponse) ProtoMessage() {} + +func (x *CountAllEnabledNodesMatchResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CountAllEnabledNodesMatchResponse.ProtoReflect.Descriptor instead. +func (*CountAllEnabledNodesMatchResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{21} +} + +func (x *CountAllEnabledNodesMatchResponse) GetCount() int64 { + if x != nil { + return x.Count + } + return 0 +} + +// 修改节点安装状态 +type UpdateNodeIsInstalledRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` + IsInstalled bool `protobuf:"varint,2,opt,name=isInstalled,proto3" json:"isInstalled,omitempty"` +} + +func (x *UpdateNodeIsInstalledRequest) Reset() { + *x = UpdateNodeIsInstalledRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateNodeIsInstalledRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNodeIsInstalledRequest) ProtoMessage() {} + +func (x *UpdateNodeIsInstalledRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateNodeIsInstalledRequest.ProtoReflect.Descriptor instead. +func (*UpdateNodeIsInstalledRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{22} +} + +func (x *UpdateNodeIsInstalledRequest) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *UpdateNodeIsInstalledRequest) GetIsInstalled() bool { + if x != nil { + return x.IsInstalled + } + return false +} + +type UpdateNodeIsInstalledResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *UpdateNodeIsInstalledResponse) Reset() { + *x = UpdateNodeIsInstalledResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateNodeIsInstalledResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNodeIsInstalledResponse) ProtoMessage() {} + +func (x *UpdateNodeIsInstalledResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateNodeIsInstalledResponse.ProtoReflect.Descriptor instead. +func (*UpdateNodeIsInstalledResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{23} +} + +// 安装节点 +type InstallNodeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` +} + +func (x *InstallNodeRequest) Reset() { + *x = InstallNodeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InstallNodeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstallNodeRequest) ProtoMessage() {} + +func (x *InstallNodeRequest) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InstallNodeRequest.ProtoReflect.Descriptor instead. +func (*InstallNodeRequest) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{24} +} + +func (x *InstallNodeRequest) GetNodeId() int64 { + if x != nil { + return x.NodeId + } + return 0 +} + +type InstallNodeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *InstallNodeResponse) Reset() { + *x = InstallNodeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_service_node_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InstallNodeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstallNodeResponse) ProtoMessage() {} + +func (x *InstallNodeResponse) ProtoReflect() protoreflect.Message { + mi := &file_service_node_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InstallNodeResponse.ProtoReflect.Descriptor instead. +func (*InstallNodeResponse) Descriptor() ([]byte, []int) { + return file_service_node_proto_rawDescGZIP(), []int{25} +} + +var File_service_node_proto protoreflect.FileDescriptor + +var file_service_node_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x10, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x05, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x22, 0x2c, + 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x1d, 0x0a, 0x1b, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, + 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x1c, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x22, 0x3f, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, + 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1e, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x22, 0x2c, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, + 0x15, 0x0a, 0x13, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x22, 0x14, 0x0a, 0x12, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x30, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, + 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, + 0x65, 0x49, 0x64, 0x22, 0x37, 0x0a, 0x17, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, + 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, + 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x1a, 0x0a, 0x18, + 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x19, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, + 0x53, 0x4f, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x4a, 0x53, 0x4f, 0x4e, 0x22, 0x13, 0x0a, 0x11, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4e, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x51, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, + 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, + 0x65, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4a, 0x53, 0x4f, + 0x4e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4a, + 0x53, 0x4f, 0x4e, 0x22, 0x1a, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x42, 0x0a, 0x22, 0x53, 0x79, 0x6e, 0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x64, 0x22, 0x25, 0x0a, 0x23, 0x53, 0x79, 0x6e, 0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x0a, 0x20, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, + 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, + 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x22, 0x39, 0x0a, 0x21, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x58, 0x0a, 0x1c, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, + 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, + 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x12, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa6, 0x08, 0x0a, 0x0b, + 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x12, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x19, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x12, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, + 0x15, 0x6c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, + 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x64, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x2e, + 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x64, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x62, + 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, + 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x6f, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x62, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x1b, 0x73, 0x79, 0x6e, 0x63, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4e, + 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x15, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, + 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, + 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4e, + 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x62, + 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_service_node_proto_rawDescOnce sync.Once + file_service_node_proto_rawDescData = file_service_node_proto_rawDesc +) + +func file_service_node_proto_rawDescGZIP() []byte { + file_service_node_proto_rawDescOnce.Do(func() { + file_service_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_node_proto_rawDescData) + }) + return file_service_node_proto_rawDescData +} + +var file_service_node_proto_msgTypes = make([]protoimpl.MessageInfo, 26) +var file_service_node_proto_goTypes = []interface{}{ + (*CreateNodeRequest)(nil), // 0: pb.CreateNodeRequest + (*CreateNodeResponse)(nil), // 1: pb.CreateNodeResponse + (*CountAllEnabledNodesRequest)(nil), // 2: pb.CountAllEnabledNodesRequest + (*CountAllEnabledNodesResponse)(nil), // 3: pb.CountAllEnabledNodesResponse + (*ListEnabledNodesMatchRequest)(nil), // 4: pb.ListEnabledNodesMatchRequest + (*ListEnabledNodesMatchResponse)(nil), // 5: pb.ListEnabledNodesMatchResponse + (*DisableNodeRequest)(nil), // 6: pb.DisableNodeRequest + (*DisableNodeResponse)(nil), // 7: pb.DisableNodeResponse + (*UpdateNodeRequest)(nil), // 8: pb.UpdateNodeRequest + (*UpdateNodeResponse)(nil), // 9: pb.UpdateNodeResponse + (*FindEnabledNodeRequest)(nil), // 10: pb.FindEnabledNodeRequest + (*FindEnabledNodeResponse)(nil), // 11: pb.FindEnabledNodeResponse + (*ComposeNodeConfigRequest)(nil), // 12: pb.ComposeNodeConfigRequest + (*ComposeNodeConfigResponse)(nil), // 13: pb.ComposeNodeConfigResponse + (*NodeStreamRequest)(nil), // 14: pb.NodeStreamRequest + (*NodeStreamResponse)(nil), // 15: pb.NodeStreamResponse + (*UpdateNodeStatusRequest)(nil), // 16: pb.UpdateNodeStatusRequest + (*UpdateNodeStatusResponse)(nil), // 17: pb.UpdateNodeStatusResponse + (*SyncNodesVersionWithClusterRequest)(nil), // 18: pb.SyncNodesVersionWithClusterRequest + (*SyncNodesVersionWithClusterResponse)(nil), // 19: pb.SyncNodesVersionWithClusterResponse + (*CountAllEnabledNodesMatchRequest)(nil), // 20: pb.CountAllEnabledNodesMatchRequest + (*CountAllEnabledNodesMatchResponse)(nil), // 21: pb.CountAllEnabledNodesMatchResponse + (*UpdateNodeIsInstalledRequest)(nil), // 22: pb.UpdateNodeIsInstalledRequest + (*UpdateNodeIsInstalledResponse)(nil), // 23: pb.UpdateNodeIsInstalledResponse + (*InstallNodeRequest)(nil), // 24: pb.InstallNodeRequest + (*InstallNodeResponse)(nil), // 25: pb.InstallNodeResponse + (*NodeLogin)(nil), // 26: pb.NodeLogin + (*Node)(nil), // 27: pb.Node +} +var file_service_node_proto_depIdxs = []int32{ + 26, // 0: pb.CreateNodeRequest.Login:type_name -> pb.NodeLogin + 27, // 1: pb.ListEnabledNodesMatchResponse.nodes:type_name -> pb.Node + 26, // 2: pb.UpdateNodeRequest.Login:type_name -> pb.NodeLogin + 27, // 3: pb.FindEnabledNodeResponse.node:type_name -> pb.Node + 0, // 4: pb.NodeService.createNode:input_type -> pb.CreateNodeRequest + 2, // 5: pb.NodeService.countAllEnabledNodes:input_type -> pb.CountAllEnabledNodesRequest + 20, // 6: pb.NodeService.countAllEnabledNodesMatch:input_type -> pb.CountAllEnabledNodesMatchRequest + 4, // 7: pb.NodeService.listEnabledNodesMatch:input_type -> pb.ListEnabledNodesMatchRequest + 6, // 8: pb.NodeService.disableNode:input_type -> pb.DisableNodeRequest + 8, // 9: pb.NodeService.updateNode:input_type -> pb.UpdateNodeRequest + 10, // 10: pb.NodeService.findEnabledNode:input_type -> pb.FindEnabledNodeRequest + 12, // 11: pb.NodeService.composeNodeConfig:input_type -> pb.ComposeNodeConfigRequest + 14, // 12: pb.NodeService.nodeStream:input_type -> pb.NodeStreamRequest + 16, // 13: pb.NodeService.updateNodeStatus:input_type -> pb.UpdateNodeStatusRequest + 18, // 14: pb.NodeService.syncNodesVersionWithCluster:input_type -> pb.SyncNodesVersionWithClusterRequest + 22, // 15: pb.NodeService.updateNodeIsInstalled:input_type -> pb.UpdateNodeIsInstalledRequest + 24, // 16: pb.NodeService.installNode:input_type -> pb.InstallNodeRequest + 1, // 17: pb.NodeService.createNode:output_type -> pb.CreateNodeResponse + 3, // 18: pb.NodeService.countAllEnabledNodes:output_type -> pb.CountAllEnabledNodesResponse + 21, // 19: pb.NodeService.countAllEnabledNodesMatch:output_type -> pb.CountAllEnabledNodesMatchResponse + 5, // 20: pb.NodeService.listEnabledNodesMatch:output_type -> pb.ListEnabledNodesMatchResponse + 7, // 21: pb.NodeService.disableNode:output_type -> pb.DisableNodeResponse + 9, // 22: pb.NodeService.updateNode:output_type -> pb.UpdateNodeResponse + 11, // 23: pb.NodeService.findEnabledNode:output_type -> pb.FindEnabledNodeResponse + 13, // 24: pb.NodeService.composeNodeConfig:output_type -> pb.ComposeNodeConfigResponse + 15, // 25: pb.NodeService.nodeStream:output_type -> pb.NodeStreamResponse + 17, // 26: pb.NodeService.updateNodeStatus:output_type -> pb.UpdateNodeStatusResponse + 19, // 27: pb.NodeService.syncNodesVersionWithCluster:output_type -> pb.SyncNodesVersionWithClusterResponse + 23, // 28: pb.NodeService.updateNodeIsInstalled:output_type -> pb.UpdateNodeIsInstalledResponse + 25, // 29: pb.NodeService.installNode:output_type -> pb.InstallNodeResponse + 17, // [17:30] is the sub-list for method output_type + 4, // [4:17] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_service_node_proto_init() } +func file_service_node_proto_init() { + if File_service_node_proto != nil { + return + } + file_model_node_proto_init() + file_model_node_login_proto_init() + if !protoimpl.UnsafeEnabled { + file_service_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateNodeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateNodeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountAllEnabledNodesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountAllEnabledNodesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEnabledNodesMatchRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEnabledNodesMatchResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DisableNodeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DisableNodeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateNodeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateNodeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindEnabledNodeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindEnabledNodeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComposeNodeConfigRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComposeNodeConfigResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeStreamRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeStreamResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateNodeStatusRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateNodeStatusResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SyncNodesVersionWithClusterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SyncNodesVersionWithClusterResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountAllEnabledNodesMatchRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountAllEnabledNodesMatchResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateNodeIsInstalledRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateNodeIsInstalledResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InstallNodeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_node_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InstallNodeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_service_node_proto_rawDesc, + NumEnums: 0, + NumMessages: 26, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_node_proto_goTypes, + DependencyIndexes: file_service_node_proto_depIdxs, + MessageInfos: file_service_node_proto_msgTypes, + }.Build() + File_service_node_proto = out.File + file_service_node_proto_rawDesc = nil + file_service_node_proto_goTypes = nil + file_service_node_proto_depIdxs = nil +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConnInterface + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion6 + +// NodeServiceClient is the client API for NodeService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type NodeServiceClient interface { + // 创建节点 + CreateNode(ctx context.Context, in *CreateNodeRequest, opts ...grpc.CallOption) (*CreateNodeResponse, error) + // 节点数量 + CountAllEnabledNodes(ctx context.Context, in *CountAllEnabledNodesRequest, opts ...grpc.CallOption) (*CountAllEnabledNodesResponse, error) + // 计算匹配的节点数量 + CountAllEnabledNodesMatch(ctx context.Context, in *CountAllEnabledNodesMatchRequest, opts ...grpc.CallOption) (*CountAllEnabledNodesMatchResponse, error) + // 列出单页节点 + ListEnabledNodesMatch(ctx context.Context, in *ListEnabledNodesMatchRequest, opts ...grpc.CallOption) (*ListEnabledNodesMatchResponse, error) + // 禁用节点 + DisableNode(ctx context.Context, in *DisableNodeRequest, opts ...grpc.CallOption) (*DisableNodeResponse, error) + // 修改节点 + UpdateNode(ctx context.Context, in *UpdateNodeRequest, opts ...grpc.CallOption) (*UpdateNodeResponse, error) + // 查看单个节点 + FindEnabledNode(ctx context.Context, in *FindEnabledNodeRequest, opts ...grpc.CallOption) (*FindEnabledNodeResponse, error) + // 组合单个节点配置 + ComposeNodeConfig(ctx context.Context, in *ComposeNodeConfigRequest, opts ...grpc.CallOption) (*ComposeNodeConfigResponse, error) + // 节点stream + NodeStream(ctx context.Context, opts ...grpc.CallOption) (NodeService_NodeStreamClient, error) + // 更新节点状态 + UpdateNodeStatus(ctx context.Context, in *UpdateNodeStatusRequest, opts ...grpc.CallOption) (*UpdateNodeStatusResponse, error) + // 同步集群中的节点版本 + SyncNodesVersionWithCluster(ctx context.Context, in *SyncNodesVersionWithClusterRequest, opts ...grpc.CallOption) (*SyncNodesVersionWithClusterResponse, error) + // 修改节点安装状态 + UpdateNodeIsInstalled(ctx context.Context, in *UpdateNodeIsInstalledRequest, opts ...grpc.CallOption) (*UpdateNodeIsInstalledResponse, error) + // 安装节点 + InstallNode(ctx context.Context, in *InstallNodeRequest, opts ...grpc.CallOption) (*InstallNodeResponse, error) +} + +type nodeServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewNodeServiceClient(cc grpc.ClientConnInterface) NodeServiceClient { + return &nodeServiceClient{cc} +} + +func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeRequest, opts ...grpc.CallOption) (*CreateNodeResponse, error) { + out := new(CreateNodeResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/createNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) CountAllEnabledNodes(ctx context.Context, in *CountAllEnabledNodesRequest, opts ...grpc.CallOption) (*CountAllEnabledNodesResponse, error) { + out := new(CountAllEnabledNodesResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/countAllEnabledNodes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) CountAllEnabledNodesMatch(ctx context.Context, in *CountAllEnabledNodesMatchRequest, opts ...grpc.CallOption) (*CountAllEnabledNodesMatchResponse, error) { + out := new(CountAllEnabledNodesMatchResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/countAllEnabledNodesMatch", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) ListEnabledNodesMatch(ctx context.Context, in *ListEnabledNodesMatchRequest, opts ...grpc.CallOption) (*ListEnabledNodesMatchResponse, error) { + out := new(ListEnabledNodesMatchResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/listEnabledNodesMatch", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) DisableNode(ctx context.Context, in *DisableNodeRequest, opts ...grpc.CallOption) (*DisableNodeResponse, error) { + out := new(DisableNodeResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/disableNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeRequest, opts ...grpc.CallOption) (*UpdateNodeResponse, error) { + out := new(UpdateNodeResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/updateNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) FindEnabledNode(ctx context.Context, in *FindEnabledNodeRequest, opts ...grpc.CallOption) (*FindEnabledNodeResponse, error) { + out := new(FindEnabledNodeResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/findEnabledNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) ComposeNodeConfig(ctx context.Context, in *ComposeNodeConfigRequest, opts ...grpc.CallOption) (*ComposeNodeConfigResponse, error) { + out := new(ComposeNodeConfigResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/composeNodeConfig", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) NodeStream(ctx context.Context, opts ...grpc.CallOption) (NodeService_NodeStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &_NodeService_serviceDesc.Streams[0], "/pb.NodeService/nodeStream", opts...) + if err != nil { + return nil, err + } + x := &nodeServiceNodeStreamClient{stream} + return x, nil +} + +type NodeService_NodeStreamClient interface { + Send(*NodeStreamRequest) error + Recv() (*NodeStreamResponse, error) + grpc.ClientStream +} + +type nodeServiceNodeStreamClient struct { + grpc.ClientStream +} + +func (x *nodeServiceNodeStreamClient) Send(m *NodeStreamRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *nodeServiceNodeStreamClient) Recv() (*NodeStreamResponse, error) { + m := new(NodeStreamResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *nodeServiceClient) UpdateNodeStatus(ctx context.Context, in *UpdateNodeStatusRequest, opts ...grpc.CallOption) (*UpdateNodeStatusResponse, error) { + out := new(UpdateNodeStatusResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/updateNodeStatus", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) SyncNodesVersionWithCluster(ctx context.Context, in *SyncNodesVersionWithClusterRequest, opts ...grpc.CallOption) (*SyncNodesVersionWithClusterResponse, error) { + out := new(SyncNodesVersionWithClusterResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/syncNodesVersionWithCluster", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) UpdateNodeIsInstalled(ctx context.Context, in *UpdateNodeIsInstalledRequest, opts ...grpc.CallOption) (*UpdateNodeIsInstalledResponse, error) { + out := new(UpdateNodeIsInstalledResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/updateNodeIsInstalled", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeServiceClient) InstallNode(ctx context.Context, in *InstallNodeRequest, opts ...grpc.CallOption) (*InstallNodeResponse, error) { + out := new(InstallNodeResponse) + err := c.cc.Invoke(ctx, "/pb.NodeService/installNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NodeServiceServer is the server API for NodeService service. +type NodeServiceServer interface { + // 创建节点 + CreateNode(context.Context, *CreateNodeRequest) (*CreateNodeResponse, error) + // 节点数量 + CountAllEnabledNodes(context.Context, *CountAllEnabledNodesRequest) (*CountAllEnabledNodesResponse, error) + // 计算匹配的节点数量 + CountAllEnabledNodesMatch(context.Context, *CountAllEnabledNodesMatchRequest) (*CountAllEnabledNodesMatchResponse, error) + // 列出单页节点 + ListEnabledNodesMatch(context.Context, *ListEnabledNodesMatchRequest) (*ListEnabledNodesMatchResponse, error) + // 禁用节点 + DisableNode(context.Context, *DisableNodeRequest) (*DisableNodeResponse, error) + // 修改节点 + UpdateNode(context.Context, *UpdateNodeRequest) (*UpdateNodeResponse, error) + // 查看单个节点 + FindEnabledNode(context.Context, *FindEnabledNodeRequest) (*FindEnabledNodeResponse, error) + // 组合单个节点配置 + ComposeNodeConfig(context.Context, *ComposeNodeConfigRequest) (*ComposeNodeConfigResponse, error) + // 节点stream + NodeStream(NodeService_NodeStreamServer) error + // 更新节点状态 + UpdateNodeStatus(context.Context, *UpdateNodeStatusRequest) (*UpdateNodeStatusResponse, error) + // 同步集群中的节点版本 + SyncNodesVersionWithCluster(context.Context, *SyncNodesVersionWithClusterRequest) (*SyncNodesVersionWithClusterResponse, error) + // 修改节点安装状态 + UpdateNodeIsInstalled(context.Context, *UpdateNodeIsInstalledRequest) (*UpdateNodeIsInstalledResponse, error) + // 安装节点 + InstallNode(context.Context, *InstallNodeRequest) (*InstallNodeResponse, error) +} + +// UnimplementedNodeServiceServer can be embedded to have forward compatible implementations. +type UnimplementedNodeServiceServer struct { +} + +func (*UnimplementedNodeServiceServer) CreateNode(context.Context, *CreateNodeRequest) (*CreateNodeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateNode not implemented") +} +func (*UnimplementedNodeServiceServer) CountAllEnabledNodes(context.Context, *CountAllEnabledNodesRequest) (*CountAllEnabledNodesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CountAllEnabledNodes not implemented") +} +func (*UnimplementedNodeServiceServer) CountAllEnabledNodesMatch(context.Context, *CountAllEnabledNodesMatchRequest) (*CountAllEnabledNodesMatchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CountAllEnabledNodesMatch not implemented") +} +func (*UnimplementedNodeServiceServer) ListEnabledNodesMatch(context.Context, *ListEnabledNodesMatchRequest) (*ListEnabledNodesMatchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListEnabledNodesMatch not implemented") +} +func (*UnimplementedNodeServiceServer) DisableNode(context.Context, *DisableNodeRequest) (*DisableNodeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableNode not implemented") +} +func (*UnimplementedNodeServiceServer) UpdateNode(context.Context, *UpdateNodeRequest) (*UpdateNodeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateNode not implemented") +} +func (*UnimplementedNodeServiceServer) FindEnabledNode(context.Context, *FindEnabledNodeRequest) (*FindEnabledNodeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindEnabledNode not implemented") +} +func (*UnimplementedNodeServiceServer) ComposeNodeConfig(context.Context, *ComposeNodeConfigRequest) (*ComposeNodeConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ComposeNodeConfig not implemented") +} +func (*UnimplementedNodeServiceServer) NodeStream(NodeService_NodeStreamServer) error { + return status.Errorf(codes.Unimplemented, "method NodeStream not implemented") +} +func (*UnimplementedNodeServiceServer) UpdateNodeStatus(context.Context, *UpdateNodeStatusRequest) (*UpdateNodeStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateNodeStatus not implemented") +} +func (*UnimplementedNodeServiceServer) SyncNodesVersionWithCluster(context.Context, *SyncNodesVersionWithClusterRequest) (*SyncNodesVersionWithClusterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SyncNodesVersionWithCluster not implemented") +} +func (*UnimplementedNodeServiceServer) UpdateNodeIsInstalled(context.Context, *UpdateNodeIsInstalledRequest) (*UpdateNodeIsInstalledResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateNodeIsInstalled not implemented") +} +func (*UnimplementedNodeServiceServer) InstallNode(context.Context, *InstallNodeRequest) (*InstallNodeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InstallNode not implemented") +} + +func RegisterNodeServiceServer(s *grpc.Server, srv NodeServiceServer) { + s.RegisterService(&_NodeService_serviceDesc, srv) +} + +func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateNodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).CreateNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/CreateNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).CreateNode(ctx, req.(*CreateNodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_CountAllEnabledNodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CountAllEnabledNodesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).CountAllEnabledNodes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/CountAllEnabledNodes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).CountAllEnabledNodes(ctx, req.(*CountAllEnabledNodesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_CountAllEnabledNodesMatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CountAllEnabledNodesMatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).CountAllEnabledNodesMatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/CountAllEnabledNodesMatch", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).CountAllEnabledNodesMatch(ctx, req.(*CountAllEnabledNodesMatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_ListEnabledNodesMatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListEnabledNodesMatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).ListEnabledNodesMatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/ListEnabledNodesMatch", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).ListEnabledNodesMatch(ctx, req.(*ListEnabledNodesMatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_DisableNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DisableNodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).DisableNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/DisableNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).DisableNode(ctx, req.(*DisableNodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateNodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).UpdateNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/UpdateNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).UpdateNode(ctx, req.(*UpdateNodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_FindEnabledNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindEnabledNodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).FindEnabledNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/FindEnabledNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).FindEnabledNode(ctx, req.(*FindEnabledNodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_ComposeNodeConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ComposeNodeConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).ComposeNodeConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/ComposeNodeConfig", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).ComposeNodeConfig(ctx, req.(*ComposeNodeConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_NodeStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(NodeServiceServer).NodeStream(&nodeServiceNodeStreamServer{stream}) +} + +type NodeService_NodeStreamServer interface { + Send(*NodeStreamResponse) error + Recv() (*NodeStreamRequest, error) + grpc.ServerStream +} + +type nodeServiceNodeStreamServer struct { + grpc.ServerStream +} + +func (x *nodeServiceNodeStreamServer) Send(m *NodeStreamResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *nodeServiceNodeStreamServer) Recv() (*NodeStreamRequest, error) { + m := new(NodeStreamRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _NodeService_UpdateNodeStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateNodeStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).UpdateNodeStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/UpdateNodeStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).UpdateNodeStatus(ctx, req.(*UpdateNodeStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_SyncNodesVersionWithCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SyncNodesVersionWithClusterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).SyncNodesVersionWithCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/SyncNodesVersionWithCluster", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).SyncNodesVersionWithCluster(ctx, req.(*SyncNodesVersionWithClusterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_UpdateNodeIsInstalled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateNodeIsInstalledRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).UpdateNodeIsInstalled(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/UpdateNodeIsInstalled", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).UpdateNodeIsInstalled(ctx, req.(*UpdateNodeIsInstalledRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeService_InstallNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InstallNodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).InstallNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.NodeService/InstallNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).InstallNode(ctx, req.(*InstallNodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _NodeService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pb.NodeService", + HandlerType: (*NodeServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "createNode", + Handler: _NodeService_CreateNode_Handler, + }, + { + MethodName: "countAllEnabledNodes", + Handler: _NodeService_CountAllEnabledNodes_Handler, + }, + { + MethodName: "countAllEnabledNodesMatch", + Handler: _NodeService_CountAllEnabledNodesMatch_Handler, + }, + { + MethodName: "listEnabledNodesMatch", + Handler: _NodeService_ListEnabledNodesMatch_Handler, + }, + { + MethodName: "disableNode", + Handler: _NodeService_DisableNode_Handler, + }, + { + MethodName: "updateNode", + Handler: _NodeService_UpdateNode_Handler, + }, + { + MethodName: "findEnabledNode", + Handler: _NodeService_FindEnabledNode_Handler, + }, + { + MethodName: "composeNodeConfig", + Handler: _NodeService_ComposeNodeConfig_Handler, + }, + { + MethodName: "updateNodeStatus", + Handler: _NodeService_UpdateNodeStatus_Handler, + }, + { + MethodName: "syncNodesVersionWithCluster", + Handler: _NodeService_SyncNodesVersionWithCluster_Handler, + }, + { + MethodName: "updateNodeIsInstalled", + Handler: _NodeService_UpdateNodeIsInstalled_Handler, + }, + { + MethodName: "installNode", + Handler: _NodeService_InstallNode_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "nodeStream", + Handler: _NodeService_NodeStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "service_node.proto", +} diff --git a/internal/rpc/protos/service_node.proto b/internal/rpc/protos/service_node.proto new file mode 100644 index 0000000..7368e20 --- /dev/null +++ b/internal/rpc/protos/service_node.proto @@ -0,0 +1,174 @@ +syntax = "proto3"; +option go_package = "./pb"; + +package pb; +import "model_node.proto"; +import "model_node_login.proto"; + +service NodeService { + // 创建节点 + rpc createNode (CreateNodeRequest) returns (CreateNodeResponse); + + // 节点数量 + rpc countAllEnabledNodes (CountAllEnabledNodesRequest) returns (CountAllEnabledNodesResponse); + + // 计算匹配的节点数量 + rpc countAllEnabledNodesMatch (CountAllEnabledNodesMatchRequest) returns (CountAllEnabledNodesMatchResponse); + + // 列出单页节点 + rpc listEnabledNodesMatch (ListEnabledNodesMatchRequest) returns (ListEnabledNodesMatchResponse); + + // 禁用节点 + rpc disableNode (DisableNodeRequest) returns (DisableNodeResponse); + + // 修改节点 + rpc updateNode (UpdateNodeRequest) returns (UpdateNodeResponse); + + // 查看单个节点 + rpc findEnabledNode (FindEnabledNodeRequest) returns (FindEnabledNodeResponse); + + // 组合单个节点配置 + rpc composeNodeConfig (ComposeNodeConfigRequest) returns (ComposeNodeConfigResponse); + + // 节点stream + rpc nodeStream (stream NodeStreamRequest) returns (stream NodeStreamResponse); + + // 更新节点状态 + rpc updateNodeStatus (UpdateNodeStatusRequest) returns (UpdateNodeStatusResponse); + + // 同步集群中的节点版本 + rpc syncNodesVersionWithCluster (SyncNodesVersionWithClusterRequest) returns (SyncNodesVersionWithClusterResponse); + + // 修改节点安装状态 + rpc updateNodeIsInstalled (UpdateNodeIsInstalledRequest) returns (UpdateNodeIsInstalledResponse); + + // 安装节点 + rpc installNode (InstallNodeRequest) returns (InstallNodeResponse); +} + +// 创建节点 +message CreateNodeRequest { + string name = 1; + int64 clusterId = 2; + NodeLogin Login = 3; +} + +message CreateNodeResponse { + int64 nodeId = 1; +} + +// 节点数量 +message CountAllEnabledNodesRequest { + +} + +message CountAllEnabledNodesResponse { + int64 count = 1; +} + +// 列出单页节点 +message ListEnabledNodesMatchRequest { + int64 offset = 1; + int64 size = 2; + int64 clusterId = 3; + int32 installState = 4; +} + +message ListEnabledNodesMatchResponse { + repeated Node nodes = 1; +} + +// 禁用节点 +message DisableNodeRequest { + int64 nodeId = 1; +} + +message DisableNodeResponse { + +} + +// 修改节点 +message UpdateNodeRequest { + int64 nodeId = 1; + string name = 2; + int64 clusterId = 3; + NodeLogin Login = 4; +} + +message UpdateNodeResponse { + +} + +// 查找节点 +message FindEnabledNodeRequest { + int64 nodeId = 1; +} + +message FindEnabledNodeResponse { + Node node = 1; +} + +// 组合单个节点配置 +message ComposeNodeConfigRequest { + +} + +message ComposeNodeConfigResponse { + bytes configJSON = 1; +} + +// 节点stream +message NodeStreamRequest { + +} + +message NodeStreamResponse { + +} + +// 更新节点状态 +message UpdateNodeStatusRequest { + int64 nodeId = 1; + bytes statusJSON = 2; +} + +message UpdateNodeStatusResponse { + +} + +// 同步集群中的节点版本 +message SyncNodesVersionWithClusterRequest { + int64 clusterId = 1; +} + +message SyncNodesVersionWithClusterResponse { +} + +// 计算匹配的节点数量 +message CountAllEnabledNodesMatchRequest { + int64 clusterId = 1; + int32 installState = 2; +} + +message CountAllEnabledNodesMatchResponse { + int64 count = 1; +} + +// 修改节点安装状态 +message UpdateNodeIsInstalledRequest { + int64 nodeId = 1; + bool isInstalled = 2; +} + +message UpdateNodeIsInstalledResponse { + +} + +// 安装节点 +message InstallNodeRequest { + int64 nodeId = 1; +} + +message InstallNodeResponse { + +} diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go new file mode 100644 index 0000000..dca0496 --- /dev/null +++ b/internal/rpc/rpc_client.go @@ -0,0 +1,81 @@ +package rpc + +import ( + "context" + "encoding/base64" + "errors" + "github.com/TeaOSLab/EdgeNode/internal/configs" + teaconst "github.com/TeaOSLab/EdgeNode/internal/const" + "github.com/TeaOSLab/EdgeNode/internal/encrypt" + "github.com/TeaOSLab/EdgeNode/internal/rpc/pb" + "github.com/TeaOSLab/EdgeNode/internal/utils" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/rands" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + "time" +) + +type RPCClient struct { + apiConfig *configs.APIConfig + nodeClients []pb.NodeServiceClient +} + +func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) { + if apiConfig == nil { + return nil, errors.New("api config should not be nil") + } + + nodeClients := []pb.NodeServiceClient{} + + conns := []*grpc.ClientConn{} + for _, endpoint := range apiConfig.RPC.Endpoints { + conn, err := grpc.Dial(endpoint, grpc.WithInsecure()) + if err != nil { + return nil, err + } + conns = append(conns, conn) + } + if len(conns) == 0 { + return nil, errors.New("[RPC]no available endpoints") + } + + // node clients + for _, conn := range conns { + nodeClients = append(nodeClients, pb.NewNodeServiceClient(conn)) + } + + return &RPCClient{ + apiConfig: apiConfig, + nodeClients: nodeClients, + }, nil +} + +func (this *RPCClient) NodeRPC() pb.NodeServiceClient { + if len(this.nodeClients) > 0 { + return this.nodeClients[rands.Int(0, len(this.nodeClients)-1)] + } + return nil +} + +func (this *RPCClient) Context() context.Context { + ctx := context.Background() + m := maps.Map{ + "timestamp": time.Now().Unix(), + "type": "node", + "userId": 0, + } + method, err := encrypt.NewMethodInstance(teaconst.EncryptMethod, this.apiConfig.Secret, this.apiConfig.NodeId) + if err != nil { + utils.PrintError(err) + return context.Background() + } + data, err := method.Encrypt(m.AsJSON()) + if err != nil { + utils.PrintError(err) + return context.Background() + } + token := base64.StdEncoding.EncodeToString(data) + ctx = metadata.AppendToOutgoingContext(ctx, "nodeId", this.apiConfig.NodeId, "token", token) + return ctx +} diff --git a/internal/rpc/rpc_client_test.go b/internal/rpc/rpc_client_test.go new file mode 100644 index 0000000..e45f7b6 --- /dev/null +++ b/internal/rpc/rpc_client_test.go @@ -0,0 +1,51 @@ +package rpc + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs" + "github.com/TeaOSLab/EdgeNode/internal/rpc/pb" + _ "github.com/iwind/TeaGo/bootstrap" + "testing" + "time" +) + +func TestRPCClient_NodeRPC(t *testing.T) { + before := time.Now() + defer func() { + t.Log(time.Since(before).Seconds()*1000, "ms") + }() + config, err := configs.LoadAPIConfig() + if err != nil { + t.Fatal(err) + } + rpc, err := NewRPCClient(config) + if err != nil { + t.Fatal(err) + } + resp, err := rpc.NodeRPC().ComposeNodeConfig(rpc.Context(), &pb.ComposeNodeConfigRequest{}) + if err != nil { + t.Fatal(err) + } + t.Log(resp) +} + +func TestSharedRPC_Stream(t *testing.T) { + config, err := configs.LoadAPIConfig() + if err != nil { + t.Fatal(err) + } + rpc, err := NewRPCClient(config) + if err != nil { + t.Fatal(err) + } + client, err := rpc.NodeRPC().NodeStream(rpc.Context()) + if err != nil { + t.Fatal(err) + } + for { + resp, err := client.Recv() + if err != nil { + t.Fatal(err) + } + t.Log("recv:", resp) + } +} diff --git a/internal/rpc/rpc_utils.go b/internal/rpc/rpc_utils.go new file mode 100644 index 0000000..71eb607 --- /dev/null +++ b/internal/rpc/rpc_utils.go @@ -0,0 +1,30 @@ +package rpc + +import ( + "github.com/TeaOSLab/EdgeNode/internal/configs" + "sync" +) + +var sharedRPC *RPCClient = nil +var locker = &sync.Mutex{} + +func SharedRPC() (*RPCClient, error) { + locker.Lock() + defer locker.Unlock() + + if sharedRPC != nil { + return sharedRPC, nil + } + + config, err := configs.LoadAPIConfig() + if err != nil { + return nil, err + } + client, err := NewRPCClient(config) + if err != nil { + return nil, err + } + + sharedRPC = client + return sharedRPC, nil +} diff --git a/internal/utils/errors.go b/internal/utils/errors.go new file mode 100644 index 0000000..a54ddda --- /dev/null +++ b/internal/utils/errors.go @@ -0,0 +1,8 @@ +package utils + +import "github.com/iwind/TeaGo/logs" + +func PrintError(err error) { + // TODO 记录调用的文件名、行数 + logs.Println("[ERROR]" + err.Error()) +}