mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 07:50:25 +08:00 
			
		
		
		
	阶段性提交
This commit is contained in:
		
							
								
								
									
										11
									
								
								build/build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								build/build.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ROOT=`dirname $0`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# building installer
 | 
				
			||||||
 | 
					architects=( "amd64" "386" )
 | 
				
			||||||
 | 
					for arch in "${architects[@]}"
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
						# TODO support arm, mips ...
 | 
				
			||||||
 | 
						env GOOS=linux GOARCH=${arch} go build --ldflags="-s -w" -o $ROOT/installers/installer-helper-linux-${arch} $ROOT/../cmd/installer-helper/main.go
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
							
								
								
									
										1
									
								
								build/deploy/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								build/deploy/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					*.zip
 | 
				
			||||||
@@ -18,6 +18,7 @@ pub ${ADMIN_PROJECT} node_cluster
 | 
				
			|||||||
pub ${ADMIN_PROJECT} node_grant
 | 
					pub ${ADMIN_PROJECT} node_grant
 | 
				
			||||||
pub ${ADMIN_PROJECT} node_ip_address
 | 
					pub ${ADMIN_PROJECT} node_ip_address
 | 
				
			||||||
pub ${ADMIN_PROJECT} server
 | 
					pub ${ADMIN_PROJECT} server
 | 
				
			||||||
 | 
					pub ${ADMIN_PROJECT} api_node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cp ../internal/rpc/pb/model_*.go ${ADMIN_PROJECT}/internal/rpc/pb/
 | 
					cp ../internal/rpc/pb/model_*.go ${ADMIN_PROJECT}/internal/rpc/pb/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								build/installers/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								build/installers/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					installer-*
 | 
				
			||||||
							
								
								
									
										53
									
								
								cmd/installer-helper/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								cmd/installer-helper/main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"flag"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/utils"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						cmd := ""
 | 
				
			||||||
 | 
						flag.StringVar(&cmd, "cmd", "", "command name: [unzip]")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// unzip
 | 
				
			||||||
 | 
						zipPath := ""
 | 
				
			||||||
 | 
						targetPath := ""
 | 
				
			||||||
 | 
						flag.StringVar(&zipPath, "zip", "", "zip path")
 | 
				
			||||||
 | 
						flag.StringVar(&targetPath, "target", "", "target dir")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// parse
 | 
				
			||||||
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(cmd) == 0 {
 | 
				
			||||||
 | 
							stderr("need '-cmd=COMMAND' argument")
 | 
				
			||||||
 | 
						} else if cmd == "unzip" { // 解压
 | 
				
			||||||
 | 
							if len(zipPath) == 0 {
 | 
				
			||||||
 | 
								stderr("ERROR: need '-zip=PATH' argument")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(targetPath) == 0 {
 | 
				
			||||||
 | 
								stderr("ERROR: need '-target=TARGET' argument")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							unzip := utils.NewUnzip(zipPath, targetPath)
 | 
				
			||||||
 | 
							err := unzip.Run()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								stderr("ERROR: " + err.Error())
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							stdout("ok")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							stderr("ERROR: not recognized command '" + cmd + "'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func stdout(s string) {
 | 
				
			||||||
 | 
						_, _ = os.Stdout.WriteString(s + "\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func stderr(s string) {
 | 
				
			||||||
 | 
						_, _ = os.Stderr.WriteString(s + "\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -7,6 +7,8 @@ require (
 | 
				
			|||||||
	github.com/go-yaml/yaml v2.1.0+incompatible
 | 
						github.com/go-yaml/yaml v2.1.0+incompatible
 | 
				
			||||||
	github.com/golang/protobuf v1.4.2
 | 
						github.com/golang/protobuf v1.4.2
 | 
				
			||||||
	github.com/iwind/TeaGo v0.0.0-20200727075925-7e7e67b44f2d
 | 
						github.com/iwind/TeaGo v0.0.0-20200727075925-7e7e67b44f2d
 | 
				
			||||||
 | 
						github.com/pkg/sftp v1.12.0
 | 
				
			||||||
 | 
						golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
 | 
				
			||||||
	google.golang.org/grpc v1.30.0
 | 
						google.golang.org/grpc v1.30.0
 | 
				
			||||||
	google.golang.org/protobuf v1.25.0
 | 
						google.golang.org/protobuf v1.25.0
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								go.sum
									
									
									
									
									
								
							@@ -4,6 +4,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 | 
				
			|||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 | 
					github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 | 
				
			||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 | 
					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/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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 | 
					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.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/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 | 
				
			||||||
@@ -40,6 +42,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 | 
				
			|||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
					github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
				
			||||||
github.com/iwind/TeaGo v0.0.0-20200727075925-7e7e67b44f2d h1:V7HA0wUOdmZbXJTVpiUEvSD4ARKHwMLMmiCccfkqf24=
 | 
					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-20200727075925-7e7e67b44f2d/go.mod h1:zjM7k+b+Jthhf0T0fKwuF0iy4TWb5SsU1gmKR2l+OmE=
 | 
				
			||||||
 | 
					github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
 | 
				
			||||||
 | 
					github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 | 
				
			||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
					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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 | 
				
			||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
					github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
				
			||||||
@@ -51,10 +55,22 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
 | 
				
			|||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 | 
					github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 | 
				
			||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 | 
					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/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 | 
				
			||||||
 | 
					github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 | 
				
			||||||
 | 
					github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
				
			||||||
 | 
					github.com/pkg/sftp v1.12.0 h1:/f3b24xrDhkhddlaobPe2JgBqfdt+gC/NYl0QY9IOuI=
 | 
				
			||||||
 | 
					github.com/pkg/sftp v1.12.0/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK8=
 | 
				
			||||||
 | 
					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 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
 | 
				
			||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
 | 
					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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 | 
				
			||||||
 | 
					github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
					golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
				
			||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 | 
					golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 | 
				
			||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
					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-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 | 
				
			||||||
@@ -65,6 +81,7 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r
 | 
				
			|||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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 h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
 | 
				
			||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
					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-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
 | 
					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/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
 | 
					golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
 | 
				
			||||||
@@ -76,6 +93,7 @@ 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-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 h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
 | 
					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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
@@ -124,5 +142,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
 | 
				
			|||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
					gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
				
			||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 | 
					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.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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
				
			||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
					honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,6 +57,7 @@ func (this *APINode) listenRPC() error {
 | 
				
			|||||||
	pb.RegisterNodeServiceServer(rpcServer, &services.NodeService{})
 | 
						pb.RegisterNodeServiceServer(rpcServer, &services.NodeService{})
 | 
				
			||||||
	pb.RegisterNodeClusterServiceServer(rpcServer, &services.NodeClusterService{})
 | 
						pb.RegisterNodeClusterServiceServer(rpcServer, &services.NodeClusterService{})
 | 
				
			||||||
	pb.RegisterNodeIPAddressServiceServer(rpcServer, &services.NodeIPAddressService{})
 | 
						pb.RegisterNodeIPAddressServiceServer(rpcServer, &services.NodeIPAddressService{})
 | 
				
			||||||
 | 
						pb.RegisterAPINodeServiceServer(rpcServer, &services.APINodeService{})
 | 
				
			||||||
	err = rpcServer.Serve(listener)
 | 
						err = rpcServer.Serve(listener)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.New("[API]start rpc failed: " + err.Error())
 | 
							return errors.New("[API]start rpc failed: " + err.Error())
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										163
									
								
								internal/db/models/api_node_dao.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								internal/db/models/api_node_dao.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
				
			|||||||
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						_ "github.com/go-sql-driver/mysql"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/dbs"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/rands"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						APINodeStateEnabled  = 1 // 已启用
 | 
				
			||||||
 | 
						APINodeStateDisabled = 0 // 已禁用
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type APINodeDAO dbs.DAO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewAPINodeDAO() *APINodeDAO {
 | 
				
			||||||
 | 
						return dbs.NewDAO(&APINodeDAO{
 | 
				
			||||||
 | 
							DAOObject: dbs.DAOObject{
 | 
				
			||||||
 | 
								DB:     Tea.Env,
 | 
				
			||||||
 | 
								Table:  "edgeApiNodes",
 | 
				
			||||||
 | 
								Model:  new(APINode),
 | 
				
			||||||
 | 
								PkName: "id",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}).(*APINodeDAO)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var SharedAPINodeDAO = NewAPINodeDAO()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 启用条目
 | 
				
			||||||
 | 
					func (this *APINodeDAO) EnableAPINode(id int64) error {
 | 
				
			||||||
 | 
						_, err := this.Query().
 | 
				
			||||||
 | 
							Pk(id).
 | 
				
			||||||
 | 
							Set("state", APINodeStateEnabled).
 | 
				
			||||||
 | 
							Update()
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 禁用条目
 | 
				
			||||||
 | 
					func (this *APINodeDAO) DisableAPINode(id int64) error {
 | 
				
			||||||
 | 
						_, err := this.Query().
 | 
				
			||||||
 | 
							Pk(id).
 | 
				
			||||||
 | 
							Set("state", APINodeStateDisabled).
 | 
				
			||||||
 | 
							Update()
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 查找启用中的条目
 | 
				
			||||||
 | 
					func (this *APINodeDAO) FindEnabledAPINode(id int64) (*APINode, error) {
 | 
				
			||||||
 | 
						result, err := this.Query().
 | 
				
			||||||
 | 
							Pk(id).
 | 
				
			||||||
 | 
							Attr("state", APINodeStateEnabled).
 | 
				
			||||||
 | 
							Find()
 | 
				
			||||||
 | 
						if result == nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return result.(*APINode), err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据主键查找名称
 | 
				
			||||||
 | 
					func (this *APINodeDAO) FindAPINodeName(id int64) (string, error) {
 | 
				
			||||||
 | 
						return this.Query().
 | 
				
			||||||
 | 
							Pk(id).
 | 
				
			||||||
 | 
							Result("name").
 | 
				
			||||||
 | 
							FindStringCol("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建API节点
 | 
				
			||||||
 | 
					func (this *APINodeDAO) CreateAPINode(name string, description string, host string, port int) (nodeId int64, err error) {
 | 
				
			||||||
 | 
						uniqueId, err := this.genUniqueId()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						secret := rands.String(32)
 | 
				
			||||||
 | 
						err = SharedApiTokenDAO.CreateAPIToken(uniqueId, secret, NodeRoleAPI)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						op := NewAPINodeOperator()
 | 
				
			||||||
 | 
						op.IsOn = true
 | 
				
			||||||
 | 
						op.UniqueId = uniqueId
 | 
				
			||||||
 | 
						op.Secret = secret
 | 
				
			||||||
 | 
						op.Name = name
 | 
				
			||||||
 | 
						op.Description = description
 | 
				
			||||||
 | 
						op.Host = host
 | 
				
			||||||
 | 
						op.Port = port
 | 
				
			||||||
 | 
						op.State = NodeStateEnabled
 | 
				
			||||||
 | 
						_, err = this.Save(op)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return types.Int64(op.Id), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 修改API节点
 | 
				
			||||||
 | 
					func (this *APINodeDAO) UpdateAPINode(nodeId int64, name string, description string, host string, port int) error {
 | 
				
			||||||
 | 
						if nodeId <= 0 {
 | 
				
			||||||
 | 
							return errors.New("invalid nodeId")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						op := NewAPINodeOperator()
 | 
				
			||||||
 | 
						op.Id = nodeId
 | 
				
			||||||
 | 
						op.Name = name
 | 
				
			||||||
 | 
						op.Description = description
 | 
				
			||||||
 | 
						op.Host = host
 | 
				
			||||||
 | 
						op.Port = port
 | 
				
			||||||
 | 
						_, err := this.Save(op)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 列出所有可用API节点
 | 
				
			||||||
 | 
					func (this *APINodeDAO) FindAllEnabledAPINodes() (result []*APINode, err error) {
 | 
				
			||||||
 | 
						_, err = this.Query().
 | 
				
			||||||
 | 
							Attr("clusterId", 0). // 非集群专用
 | 
				
			||||||
 | 
							State(APINodeStateEnabled).
 | 
				
			||||||
 | 
							Desc("order").
 | 
				
			||||||
 | 
							AscPk().
 | 
				
			||||||
 | 
							Slice(&result).
 | 
				
			||||||
 | 
							FindAll()
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 计算API节点数量
 | 
				
			||||||
 | 
					func (this *APINodeDAO) CountAllEnabledAPINodes() (int64, error) {
 | 
				
			||||||
 | 
						return this.Query().
 | 
				
			||||||
 | 
							State(APINodeStateEnabled).
 | 
				
			||||||
 | 
							Count()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 列出单页的API节点
 | 
				
			||||||
 | 
					func (this *APINodeDAO) ListEnabledAPINodes(offset int64, size int64) (result []*APINode, err error) {
 | 
				
			||||||
 | 
						_, err = this.Query().
 | 
				
			||||||
 | 
							Attr("clusterId", 0). // 非集群专用
 | 
				
			||||||
 | 
							State(APINodeStateEnabled).
 | 
				
			||||||
 | 
							Offset(offset).
 | 
				
			||||||
 | 
							Limit(size).
 | 
				
			||||||
 | 
							Desc("order").
 | 
				
			||||||
 | 
							DescPk().
 | 
				
			||||||
 | 
							Slice(&result).
 | 
				
			||||||
 | 
							FindAll()
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 生成唯一ID
 | 
				
			||||||
 | 
					func (this *APINodeDAO) genUniqueId() (string, error) {
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							uniqueId := rands.HexString(32)
 | 
				
			||||||
 | 
							ok, err := this.Query().
 | 
				
			||||||
 | 
								Attr("uniqueId", uniqueId).
 | 
				
			||||||
 | 
								Exist()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return "", err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return uniqueId, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								internal/db/models/api_node_dao_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								internal/db/models/api_node_dao_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						_ "github.com/go-sql-driver/mysql"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										34
									
								
								internal/db/models/api_node_model.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								internal/db/models/api_node_model.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					type APINode struct {
 | 
				
			||||||
 | 
						Id          uint32 `field:"id"`          // ID
 | 
				
			||||||
 | 
						IsOn        uint8  `field:"isOn"`        // 是否启用
 | 
				
			||||||
 | 
						ClusterId   uint32 `field:"clusterId"`   // 专用集群ID
 | 
				
			||||||
 | 
						UniqueId    string `field:"uniqueId"`    // 唯一ID
 | 
				
			||||||
 | 
						Secret      string `field:"secret"`      // 密钥
 | 
				
			||||||
 | 
						Name        string `field:"name"`        // 名称
 | 
				
			||||||
 | 
						Description string `field:"description"` // 描述
 | 
				
			||||||
 | 
						Host        string `field:"host"`        // 地址
 | 
				
			||||||
 | 
						Port        uint32 `field:"port"`        // 端口
 | 
				
			||||||
 | 
						Order       uint32 `field:"order"`       // 排序
 | 
				
			||||||
 | 
						State       uint8  `field:"state"`       // 状态
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type APINodeOperator struct {
 | 
				
			||||||
 | 
						Id          interface{} // ID
 | 
				
			||||||
 | 
						IsOn        interface{} // 是否启用
 | 
				
			||||||
 | 
						ClusterId   interface{} // 专用集群ID
 | 
				
			||||||
 | 
						UniqueId    interface{} // 唯一ID
 | 
				
			||||||
 | 
						Secret      interface{} // 密钥
 | 
				
			||||||
 | 
						Name        interface{} // 名称
 | 
				
			||||||
 | 
						Description interface{} // 描述
 | 
				
			||||||
 | 
						Host        interface{} // 地址
 | 
				
			||||||
 | 
						Port        interface{} // 端口
 | 
				
			||||||
 | 
						Order       interface{} // 排序
 | 
				
			||||||
 | 
						State       interface{} // 状态
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewAPINodeOperator() *APINodeOperator {
 | 
				
			||||||
 | 
						return &APINodeOperator{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								internal/db/models/api_node_model_ext.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								internal/db/models/api_node_model_ext.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					package models
 | 
				
			||||||
@@ -66,3 +66,14 @@ func (this *ApiTokenDAO) FindEnabledTokenWithNode(nodeId string) (*ApiToken, err
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil, err
 | 
						return nil, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 保存API Token
 | 
				
			||||||
 | 
					func (this *ApiTokenDAO) CreateAPIToken(nodeId string, secret string, role NodeRole) error {
 | 
				
			||||||
 | 
						op := NewApiTokenOperator()
 | 
				
			||||||
 | 
						op.NodeId = nodeId
 | 
				
			||||||
 | 
						op.Secret = secret
 | 
				
			||||||
 | 
						op.Role = role
 | 
				
			||||||
 | 
						op.State = ApiTokenStateEnabled
 | 
				
			||||||
 | 
						_, err := this.Save(op)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,6 +83,8 @@ func (this *NodeClusterDAO) CreateCluster(name string, grantId int64, installDir
 | 
				
			|||||||
	op.Name = name
 | 
						op.Name = name
 | 
				
			||||||
	op.GrantId = grantId
 | 
						op.GrantId = grantId
 | 
				
			||||||
	op.InstallDir = installDir
 | 
						op.InstallDir = installDir
 | 
				
			||||||
 | 
						op.UseAllAPINodes = 1
 | 
				
			||||||
 | 
						op.ApiNodes = "[]"
 | 
				
			||||||
	op.State = NodeClusterStateEnabled
 | 
						op.State = NodeClusterStateEnabled
 | 
				
			||||||
	_, err = this.Save(op)
 | 
						_, err = this.Save(op)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,23 +2,27 @@ package models
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 节点集群
 | 
					// 节点集群
 | 
				
			||||||
type NodeCluster struct {
 | 
					type NodeCluster struct {
 | 
				
			||||||
	Id         uint32 `field:"id"`         // ID
 | 
						Id             uint32 `field:"id"`             // ID
 | 
				
			||||||
	Name       string `field:"name"`       // 名称
 | 
						Name           string `field:"name"`           // 名称
 | 
				
			||||||
	InstallDir string `field:"installDir"` // 安装目录
 | 
						InstallDir     string `field:"installDir"`     // 安装目录
 | 
				
			||||||
	GrantId    uint32 `field:"grantId"`    // 默认认证方式
 | 
						GrantId        uint32 `field:"grantId"`        // 默认认证方式
 | 
				
			||||||
	Order      uint32 `field:"order"`      // 排序
 | 
						UseAllAPINodes uint8  `field:"useAllAPINodes"` // 是否使用所有API节点
 | 
				
			||||||
	CreatedAt  uint32 `field:"createdAt"`  // 创建时间
 | 
						ApiNodes       string `field:"apiNodes"`       // 使用的API节点
 | 
				
			||||||
	State      uint8  `field:"state"`      // 状态
 | 
						Order          uint32 `field:"order"`          // 排序
 | 
				
			||||||
 | 
						CreatedAt      uint32 `field:"createdAt"`      // 创建时间
 | 
				
			||||||
 | 
						State          uint8  `field:"state"`          // 状态
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type NodeClusterOperator struct {
 | 
					type NodeClusterOperator struct {
 | 
				
			||||||
	Id         interface{} // ID
 | 
						Id             interface{} // ID
 | 
				
			||||||
	Name       interface{} // 名称
 | 
						Name           interface{} // 名称
 | 
				
			||||||
	InstallDir interface{} // 安装目录
 | 
						InstallDir     interface{} // 安装目录
 | 
				
			||||||
	GrantId    interface{} // 默认认证方式
 | 
						GrantId        interface{} // 默认认证方式
 | 
				
			||||||
	Order      interface{} // 排序
 | 
						UseAllAPINodes interface{} // 是否使用所有API节点
 | 
				
			||||||
	CreatedAt  interface{} // 创建时间
 | 
						ApiNodes       interface{} // 使用的API节点
 | 
				
			||||||
	State      interface{} // 状态
 | 
						Order          interface{} // 排序
 | 
				
			||||||
 | 
						CreatedAt      interface{} // 创建时间
 | 
				
			||||||
 | 
						State          interface{} // 状态
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewNodeClusterOperator() *NodeClusterOperator {
 | 
					func NewNodeClusterOperator() *NodeClusterOperator {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,10 +74,18 @@ func (this *NodeDAO) CreateNode(name string, clusterId int64) (nodeId int64, err
 | 
				
			|||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						secret := rands.String(32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 保存API Token
 | 
				
			||||||
 | 
						err = SharedApiTokenDAO.CreateAPIToken(uniqueId, secret, NodeRoleNode)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	op := NewNodeOperator()
 | 
						op := NewNodeOperator()
 | 
				
			||||||
	op.Name = name
 | 
						op.Name = name
 | 
				
			||||||
	op.UniqueId = uniqueId
 | 
						op.UniqueId = uniqueId
 | 
				
			||||||
	op.Secret = rands.String(32)
 | 
						op.Secret = secret
 | 
				
			||||||
	op.ClusterId = clusterId
 | 
						op.ClusterId = clusterId
 | 
				
			||||||
	op.IsOn = 1
 | 
						op.IsOn = 1
 | 
				
			||||||
	op.State = NodeStateEnabled
 | 
						op.State = NodeStateEnabled
 | 
				
			||||||
@@ -260,6 +268,15 @@ func (this *NodeDAO) UpdateNodeStatus(nodeId int64, statusJSON []byte) error {
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 设置节点安装状态
 | 
				
			||||||
 | 
					func (this *NodeDAO) UpdateNodeIsInstalled(nodeId int64, isInstalled bool) error {
 | 
				
			||||||
 | 
						_, err := this.Query().
 | 
				
			||||||
 | 
							Pk(nodeId).
 | 
				
			||||||
 | 
							Set("isInstalled", isInstalled).
 | 
				
			||||||
 | 
							Update()
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 生成唯一ID
 | 
					// 生成唯一ID
 | 
				
			||||||
func (this *NodeDAO) genUniqueId() (string, error) {
 | 
					func (this *NodeDAO) genUniqueId() (string, error) {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								internal/db/models/node_roles.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								internal/db/models/node_roles.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type NodeRole = string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						NodeRoleAdmin    NodeRole = "admin"
 | 
				
			||||||
 | 
						NodeRoleUser     NodeRole = "user"
 | 
				
			||||||
 | 
						NodeRoleProvider NodeRole = "provider"
 | 
				
			||||||
 | 
						NodeRoleAPI      NodeRole = "api"
 | 
				
			||||||
 | 
						NodeRoleDatabase NodeRole = "database"
 | 
				
			||||||
 | 
						NodeRoleLog      NodeRole = "log"
 | 
				
			||||||
 | 
						NodeRoleDNS      NodeRole = "dns"
 | 
				
			||||||
 | 
						NodeRoleMonitor  NodeRole = "monitor"
 | 
				
			||||||
 | 
						NodeRoleNode     NodeRole = "node"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										9
									
								
								internal/installers/credentials.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								internal/installers/credentials.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Credentials struct {
 | 
				
			||||||
 | 
						Host       string
 | 
				
			||||||
 | 
						Port       int
 | 
				
			||||||
 | 
						Username   string
 | 
				
			||||||
 | 
						Password   string
 | 
				
			||||||
 | 
						PrivateKey string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								internal/installers/env.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/installers/env.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Env struct {
 | 
				
			||||||
 | 
						OS         string
 | 
				
			||||||
 | 
						Arch       string
 | 
				
			||||||
 | 
						HelperName string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										168
									
								
								internal/installers/installer_base.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								internal/installers/installer_base.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						stringutil "github.com/iwind/TeaGo/utils/string"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/ssh"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BaseInstaller struct {
 | 
				
			||||||
 | 
						client *SSHClient
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 登录SSH服务
 | 
				
			||||||
 | 
					func (this *BaseInstaller) Login(credentials *Credentials) error {
 | 
				
			||||||
 | 
						var hostKeyCallback ssh.HostKeyCallback = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查参数
 | 
				
			||||||
 | 
						if len(credentials.Host) == 0 {
 | 
				
			||||||
 | 
							return errors.New("'host' should not be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if credentials.Port <= 0 {
 | 
				
			||||||
 | 
							return errors.New("'port' should be greater than 0")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(credentials.Password) == 0 && len(credentials.PrivateKey) == 0 {
 | 
				
			||||||
 | 
							return errors.New("require user 'password' or 'privateKey'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 不使用known_hosts
 | 
				
			||||||
 | 
						if hostKeyCallback == nil {
 | 
				
			||||||
 | 
							hostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 认证
 | 
				
			||||||
 | 
						methods := []ssh.AuthMethod{}
 | 
				
			||||||
 | 
						if len(credentials.Password) > 0 {
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								authMethod := ssh.Password(credentials.Password)
 | 
				
			||||||
 | 
								methods = append(methods, authMethod)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								authMethod := ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
 | 
				
			||||||
 | 
									if len(questions) == 0 {
 | 
				
			||||||
 | 
										return []string{}, nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return []string{credentials.Password}, nil
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								methods = append(methods, authMethod)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							signer, err := ssh.ParsePrivateKey([]byte(credentials.PrivateKey))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return errors.New("parse private key: " + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							authMethod := ssh.PublicKeys(signer)
 | 
				
			||||||
 | 
							methods = append(methods, authMethod)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// SSH客户端
 | 
				
			||||||
 | 
						config := &ssh.ClientConfig{
 | 
				
			||||||
 | 
							User:            credentials.Username,
 | 
				
			||||||
 | 
							Auth:            methods,
 | 
				
			||||||
 | 
							HostKeyCallback: hostKeyCallback,
 | 
				
			||||||
 | 
							Timeout:         5 * time.Second, // TODO 后期可以设置这个超时时间
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sshClient, err := ssh.Dial("tcp", credentials.Host+":"+strconv.Itoa(credentials.Port), config)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := NewSSHClient(sshClient)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.client = client
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 关闭SSH服务
 | 
				
			||||||
 | 
					func (this *BaseInstaller) Close() error {
 | 
				
			||||||
 | 
						if this.client != nil {
 | 
				
			||||||
 | 
							return this.client.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 查找最新的版本的文件
 | 
				
			||||||
 | 
					func (this *BaseInstaller) LookupLatestInstaller(filePrefix string) (string, error) {
 | 
				
			||||||
 | 
						matches, err := filepath.Glob(Tea.Root + Tea.DS + "deploy" + Tea.DS + "*.zip")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pattern, err := regexp.Compile(filePrefix + `-v([\d.]+)\.zip`)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lastVersion := ""
 | 
				
			||||||
 | 
						result := ""
 | 
				
			||||||
 | 
						for _, match := range matches {
 | 
				
			||||||
 | 
							baseName := filepath.Base(match)
 | 
				
			||||||
 | 
							if !pattern.MatchString(baseName) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m := pattern.FindStringSubmatch(baseName)
 | 
				
			||||||
 | 
							if len(m) < 2 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							version := m[1]
 | 
				
			||||||
 | 
							if len(lastVersion) == 0 || stringutil.VersionCompare(version, lastVersion) > 0 {
 | 
				
			||||||
 | 
								lastVersion = version
 | 
				
			||||||
 | 
								result = match
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return result, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 上传安装助手
 | 
				
			||||||
 | 
					func (this *BaseInstaller) InstallHelper(targetDir string) (env *Env, err error) {
 | 
				
			||||||
 | 
						uname, _, err := this.client.Exec("uname -a")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return env, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osName := ""
 | 
				
			||||||
 | 
						archName := ""
 | 
				
			||||||
 | 
						if strings.Index(uname, "Darwin") > 0 {
 | 
				
			||||||
 | 
							osName = "darwin"
 | 
				
			||||||
 | 
						} else if strings.Index(uname, "Linux") >= 0 {
 | 
				
			||||||
 | 
							osName = "linux"
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// TODO 支持freebsd, aix ...
 | 
				
			||||||
 | 
							return env, errors.New("installer not supported os '" + uname + "'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if strings.Index(uname, "x86_64") > 0 {
 | 
				
			||||||
 | 
							archName = "amd64"
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// TODO 支持ARM和MIPS等架构
 | 
				
			||||||
 | 
							archName = "386"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						exeName := "installer-helper-" + osName + "-" + archName
 | 
				
			||||||
 | 
						exePath := Tea.Root + "/installers/" + exeName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = this.client.Copy(exePath, targetDir+"/"+exeName, 0777)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return env, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						env = &Env{
 | 
				
			||||||
 | 
							OS:         osName,
 | 
				
			||||||
 | 
							Arch:       archName,
 | 
				
			||||||
 | 
							HelperName: exeName,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return env, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								internal/installers/installer_base_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								internal/installers/installer_base_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestBaseInstaller_LookupLatest(t *testing.T) {
 | 
				
			||||||
 | 
						installer := &BaseInstaller{}
 | 
				
			||||||
 | 
						result, err := installer.LookupLatestInstaller("edge-node-linux-amd64")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(result) == 0 {
 | 
				
			||||||
 | 
							t.Log("not found")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Log("result:", result)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								internal/installers/installer_interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/installers/installer_interface.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type InstallerInterface interface {
 | 
				
			||||||
 | 
						// 登录SSH服务
 | 
				
			||||||
 | 
						Login(credentials *Credentials) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 安装
 | 
				
			||||||
 | 
						Install(dir string, params interface{}) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 关闭连接的SSH服务
 | 
				
			||||||
 | 
						Close() error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										86
									
								
								internal/installers/installer_node.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								internal/installers/installer_node.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type NodeInstaller struct {
 | 
				
			||||||
 | 
						BaseInstaller
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *NodeInstaller) Install(dir string, params interface{}) error {
 | 
				
			||||||
 | 
						if params == nil {
 | 
				
			||||||
 | 
							return errors.New("'params' required for node installation")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						nodeParams, ok := params.(*NodeParams)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return errors.New("'params' should be *NodeParams")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := nodeParams.Validate()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errors.New("params validation: " + err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 安装助手
 | 
				
			||||||
 | 
						env, err := this.InstallHelper(dir)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 上传安装文件
 | 
				
			||||||
 | 
						filePrefix := "edge-node-" + env.OS + "-" + env.Arch
 | 
				
			||||||
 | 
						zipFile, err := this.LookupLatestInstaller(filePrefix)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(zipFile) == 0 {
 | 
				
			||||||
 | 
							return errors.New("can not find installer file for " + env.OS + "/" + env.Arch)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						targetZip := dir + "/" + filepath.Base(zipFile)
 | 
				
			||||||
 | 
						err = this.client.Copy(zipFile, targetZip, 0777)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 解压
 | 
				
			||||||
 | 
						_, stderr, err := this.client.Exec(dir + "/" + env.HelperName + " -cmd=unzip -zip=\"" + targetZip + "\" -target=\"" + dir + "\"")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(stderr) > 0 {
 | 
				
			||||||
 | 
							return errors.New("unzip installer failed: " + stderr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 修改配置文件
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							templateFile := dir + "/edge-node/configs/api.template.yaml"
 | 
				
			||||||
 | 
							configFile := dir + "/edge-node/configs/api.yaml"
 | 
				
			||||||
 | 
							data, err := this.client.ReadFile(templateFile)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data = bytes.ReplaceAll(data, []byte("${endpoint}"), []byte(nodeParams.Endpoint))
 | 
				
			||||||
 | 
							data = bytes.ReplaceAll(data, []byte("${nodeId}"), []byte(nodeParams.NodeId))
 | 
				
			||||||
 | 
							data = bytes.ReplaceAll(data, []byte("${nodeSecret}"), []byte(nodeParams.Secret))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_, err = this.client.WriteFile(configFile, data)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return errors.New("write 'configs/api.yaml': " + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 启动
 | 
				
			||||||
 | 
						_, stderr, err = this.client.Exec(dir + "/edge-node/bin/edge-node start")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errors.New("start edge node failed: " + err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(stderr) > 0 {
 | 
				
			||||||
 | 
							return errors.New("start edge node failed: " + stderr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								internal/installers/installer_node_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								internal/installers/installer_node_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeInstaller_Install(t *testing.T) {
 | 
				
			||||||
 | 
						var installer InstallerInterface = &NodeInstaller{}
 | 
				
			||||||
 | 
						err := installer.Login(&Credentials{
 | 
				
			||||||
 | 
							Host:       "192.168.2.30",
 | 
				
			||||||
 | 
							Port:       22,
 | 
				
			||||||
 | 
							Username:   "root",
 | 
				
			||||||
 | 
							Password:   "123456",
 | 
				
			||||||
 | 
							PrivateKey: "",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 关闭连接
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							err := installer.Close()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 安装
 | 
				
			||||||
 | 
						err = installer.Install("/opt/edge", &NodeParams{
 | 
				
			||||||
 | 
							Endpoint: "192.168.2.40:8003",
 | 
				
			||||||
 | 
							NodeId:   "313fdb1b90d0a63c736f307b4d1ca358",
 | 
				
			||||||
 | 
							Secret:   "Pl3u5kYqBDZddp7raw6QfHiuGPRCWF54",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								internal/installers/params_node.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								internal/installers/params_node.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type NodeParams struct {
 | 
				
			||||||
 | 
						Endpoint string
 | 
				
			||||||
 | 
						NodeId   string
 | 
				
			||||||
 | 
						Secret   string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *NodeParams) Validate() error {
 | 
				
			||||||
 | 
						if len(this.Endpoint) == 0 {
 | 
				
			||||||
 | 
							return errors.New("'endpoint' should not be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.NodeId) == 0 {
 | 
				
			||||||
 | 
							return errors.New("'nodeId' should not be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.Secret) == 0 {
 | 
				
			||||||
 | 
							return errors.New("'secret' should not be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										149
									
								
								internal/installers/ssh_client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								internal/installers/ssh_client.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					package installers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"github.com/pkg/sftp"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/ssh"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SSHClient struct {
 | 
				
			||||||
 | 
						raw  *ssh.Client
 | 
				
			||||||
 | 
						sftp *sftp.Client
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSSHClient(raw *ssh.Client) (*SSHClient, error) {
 | 
				
			||||||
 | 
						c := &SSHClient{
 | 
				
			||||||
 | 
							raw: raw,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sftpClient, err := sftp.NewClient(raw)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							_ = c.Close()
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.sftp = sftpClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 执行shell命令
 | 
				
			||||||
 | 
					func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error) {
 | 
				
			||||||
 | 
						session, err := this.raw.NewSession()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							_ = session.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stdoutBuf := bytes.NewBuffer([]byte{})
 | 
				
			||||||
 | 
						stderrBuf := bytes.NewBuffer([]byte{})
 | 
				
			||||||
 | 
						session.Stdout = stdoutBuf
 | 
				
			||||||
 | 
						session.Stderr = stderrBuf
 | 
				
			||||||
 | 
						err = session.Run(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return stdoutBuf.String(), stderrBuf.String(), err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings.TrimRight(stdoutBuf.String(), "\n"), stderrBuf.String(), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) Listen(network string, addr string) (net.Listener, error) {
 | 
				
			||||||
 | 
						return this.raw.Listen(network, addr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) Dial(network string, addr string) (net.Conn, error) {
 | 
				
			||||||
 | 
						return this.raw.Dial(network, addr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) Close() error {
 | 
				
			||||||
 | 
						if this.sftp != nil {
 | 
				
			||||||
 | 
							_ = this.sftp.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return this.raw.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) OpenFile(path string, flags int) (*sftp.File, error) {
 | 
				
			||||||
 | 
						return this.sftp.OpenFile(path, flags)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) Stat(path string) (os.FileInfo, error) {
 | 
				
			||||||
 | 
						return this.sftp.Stat(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) Mkdir(path string) error {
 | 
				
			||||||
 | 
						return this.sftp.Mkdir(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) MkdirAll(path string) error {
 | 
				
			||||||
 | 
						return this.sftp.MkdirAll(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SSHClient) Chmod(path string, mode os.FileMode) error {
 | 
				
			||||||
 | 
						return this.sftp.Chmod(path, mode)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 拷贝文件
 | 
				
			||||||
 | 
					func (this *SSHClient) Copy(localPath string, remotePath string, mode os.FileMode) error {
 | 
				
			||||||
 | 
						localFp, err := os.Open(localPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							_ = localFp.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						remoteFp, err := this.sftp.OpenFile(remotePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							_ = remoteFp.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						_, err = io.Copy(remoteFp, localFp)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return this.Chmod(remotePath, mode)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取新Session
 | 
				
			||||||
 | 
					func (this *SSHClient) NewSession() (*ssh.Session, error) {
 | 
				
			||||||
 | 
						return this.raw.NewSession()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 读取文件内容
 | 
				
			||||||
 | 
					func (this *SSHClient) ReadFile(path string) ([]byte, error) {
 | 
				
			||||||
 | 
						fp, err := this.sftp.OpenFile(path, 0444)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							_ = fp.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer := bytes.NewBuffer([]byte{})
 | 
				
			||||||
 | 
						_, err = io.Copy(buffer, fp)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buffer.Bytes(), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 写入文件内容
 | 
				
			||||||
 | 
					func (this *SSHClient) WriteFile(path string, data []byte) (n int, err error) {
 | 
				
			||||||
 | 
						fp, err := this.sftp.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							_ = fp.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n, err = fp.Write(data)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										222
									
								
								internal/rpc/pb/model_api_node.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								internal/rpc/pb/model_api_node.pb.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,222 @@
 | 
				
			|||||||
 | 
					// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
				
			||||||
 | 
					// versions:
 | 
				
			||||||
 | 
					// 	protoc-gen-go v1.25.0
 | 
				
			||||||
 | 
					// 	protoc        v3.12.3
 | 
				
			||||||
 | 
					// source: model_api_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 APINode struct {
 | 
				
			||||||
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
 | 
						unknownFields protoimpl.UnknownFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Id          int64  `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
 | 
				
			||||||
 | 
						IsOn        bool   `protobuf:"varint,2,opt,name=isOn,proto3" json:"isOn,omitempty"`
 | 
				
			||||||
 | 
						ClusterId   int64  `protobuf:"varint,3,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
 | 
				
			||||||
 | 
						UniqueId    string `protobuf:"bytes,4,opt,name=uniqueId,proto3" json:"uniqueId,omitempty"`
 | 
				
			||||||
 | 
						Secret      string `protobuf:"bytes,5,opt,name=secret,proto3" json:"secret,omitempty"`
 | 
				
			||||||
 | 
						Name        string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
 | 
				
			||||||
 | 
						Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
 | 
				
			||||||
 | 
						Host        string `protobuf:"bytes,8,opt,name=host,proto3" json:"host,omitempty"`
 | 
				
			||||||
 | 
						Port        int32  `protobuf:"varint,9,opt,name=port,proto3" json:"port,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) Reset() {
 | 
				
			||||||
 | 
						*x = APINode{}
 | 
				
			||||||
 | 
						if protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							mi := &file_model_api_node_proto_msgTypes[0]
 | 
				
			||||||
 | 
							ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
				
			||||||
 | 
							ms.StoreMessageInfo(mi)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) String() string {
 | 
				
			||||||
 | 
						return protoimpl.X.MessageStringOf(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*APINode) ProtoMessage() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) ProtoReflect() protoreflect.Message {
 | 
				
			||||||
 | 
						mi := &file_model_api_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 APINode.ProtoReflect.Descriptor instead.
 | 
				
			||||||
 | 
					func (*APINode) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return file_model_api_node_proto_rawDescGZIP(), []int{0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetId() int64 {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Id
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetIsOn() bool {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.IsOn
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetClusterId() int64 {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.ClusterId
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetUniqueId() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.UniqueId
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetSecret() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Secret
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetName() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetDescription() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Description
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetHost() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Host
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *APINode) GetPort() int32 {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Port
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var File_model_api_node_proto protoreflect.FileDescriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var file_model_api_node_proto_rawDesc = []byte{
 | 
				
			||||||
 | 
						0x0a, 0x14, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x61, 0x70, 0x69, 0x5f, 0x6e, 0x6f, 0x64, 0x65,
 | 
				
			||||||
 | 
						0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xdd, 0x01, 0x0a, 0x07, 0x41,
 | 
				
			||||||
 | 
						0x50, 0x49, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
 | 
				
			||||||
 | 
						0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x02,
 | 
				
			||||||
 | 
						0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 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, 0x1a, 0x0a, 0x08, 0x75, 0x6e, 0x69, 0x71,
 | 
				
			||||||
 | 
						0x75, 0x65, 0x49, 0x64, 0x18, 0x04, 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, 0x05,
 | 
				
			||||||
 | 
						0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04,
 | 
				
			||||||
 | 
						0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 | 
				
			||||||
 | 
						0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
 | 
				
			||||||
 | 
						0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
 | 
				
			||||||
 | 
						0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
 | 
				
			||||||
 | 
						0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x09,
 | 
				
			||||||
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f,
 | 
				
			||||||
 | 
						0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						file_model_api_node_proto_rawDescOnce sync.Once
 | 
				
			||||||
 | 
						file_model_api_node_proto_rawDescData = file_model_api_node_proto_rawDesc
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func file_model_api_node_proto_rawDescGZIP() []byte {
 | 
				
			||||||
 | 
						file_model_api_node_proto_rawDescOnce.Do(func() {
 | 
				
			||||||
 | 
							file_model_api_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_model_api_node_proto_rawDescData)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return file_model_api_node_proto_rawDescData
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var file_model_api_node_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
 | 
				
			||||||
 | 
					var file_model_api_node_proto_goTypes = []interface{}{
 | 
				
			||||||
 | 
						(*APINode)(nil), // 0: pb.APINode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					var file_model_api_node_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_api_node_proto_init() }
 | 
				
			||||||
 | 
					func file_model_api_node_proto_init() {
 | 
				
			||||||
 | 
						if File_model_api_node_proto != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							file_model_api_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
 | 
				
			||||||
 | 
								switch v := v.(*APINode); 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_api_node_proto_rawDesc,
 | 
				
			||||||
 | 
								NumEnums:      0,
 | 
				
			||||||
 | 
								NumMessages:   1,
 | 
				
			||||||
 | 
								NumExtensions: 0,
 | 
				
			||||||
 | 
								NumServices:   0,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							GoTypes:           file_model_api_node_proto_goTypes,
 | 
				
			||||||
 | 
							DependencyIndexes: file_model_api_node_proto_depIdxs,
 | 
				
			||||||
 | 
							MessageInfos:      file_model_api_node_proto_msgTypes,
 | 
				
			||||||
 | 
						}.Build()
 | 
				
			||||||
 | 
						File_model_api_node_proto = out.File
 | 
				
			||||||
 | 
						file_model_api_node_proto_rawDesc = nil
 | 
				
			||||||
 | 
						file_model_api_node_proto_goTypes = nil
 | 
				
			||||||
 | 
						file_model_api_node_proto_depIdxs = nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1385
									
								
								internal/rpc/pb/service_api_node.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1385
									
								
								internal/rpc/pb/service_api_node.pb.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1066,6 +1066,100 @@ func (x *CountAllEnabledNodesMatchResponse) GetCount() int64 {
 | 
				
			|||||||
	return 0
 | 
						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}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var File_service_node_proto protoreflect.FileDescriptor
 | 
					var File_service_node_proto protoreflect.FileDescriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var file_service_node_proto_rawDesc = []byte{
 | 
					var file_service_node_proto_rawDesc = []byte{
 | 
				
			||||||
@@ -1149,64 +1243,78 @@ var file_service_node_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d,
 | 
						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,
 | 
						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,
 | 
						0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75,
 | 
				
			||||||
	0x6e, 0x74, 0x32, 0x88, 0x07, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69,
 | 
						0x6e, 0x74, 0x22, 0x58, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
 | 
				
			||||||
	0x63, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
 | 
						0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
 | 
				
			||||||
	0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
 | 
						0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
 | 
				
			||||||
	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65,
 | 
						0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73,
 | 
				
			||||||
	0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
 | 
						0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
 | 
				
			||||||
	0x59, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c,
 | 
						0x0b, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x22, 0x1f, 0x0a, 0x1d,
 | 
				
			||||||
	0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x75,
 | 
						0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74,
 | 
				
			||||||
	0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65,
 | 
						0x61, 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe6, 0x07,
 | 
				
			||||||
	0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f,
 | 
						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,
 | 
						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,
 | 
						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,
 | 
						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,
 | 
						0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
 | 
				
			||||||
	0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65,
 | 
						0x5c, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f,
 | 
				
			||||||
	0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e,
 | 
						0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69,
 | 
				
			||||||
	0x70, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c,
 | 
						0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61,
 | 
				
			||||||
	0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
 | 
						0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x62, 0x2e,
 | 
				
			||||||
	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62,
 | 
						0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73,
 | 
				
			||||||
	0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x20, 0x2e,
 | 
						0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a,
 | 
				
			||||||
	0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f,
 | 
						0x0b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x70,
 | 
				
			||||||
	0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
 | 
						0x62, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71,
 | 
				
			||||||
	0x21, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
 | 
						0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c,
 | 
				
			||||||
	0x4e, 0x6f, 0x64, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
 | 
						0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a,
 | 
				
			||||||
	0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64,
 | 
						0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x2e, 0x70, 0x62,
 | 
				
			||||||
	0x65, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f,
 | 
						0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
 | 
				
			||||||
	0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x44,
 | 
						0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f,
 | 
				
			||||||
	0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
 | 
						0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x66, 0x69,
 | 
				
			||||||
	0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
 | 
						0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e,
 | 
				
			||||||
	0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
 | 
						0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f,
 | 
				
			||||||
	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64,
 | 
						0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x46,
 | 
				
			||||||
	0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
 | 
						0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65,
 | 
				
			||||||
	0x4a, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e, 0x6f,
 | 
						0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
 | 
				
			||||||
	0x64, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62,
 | 
						0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x2e, 0x70, 0x62,
 | 
				
			||||||
	0x6c, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
 | 
						0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66,
 | 
				
			||||||
	0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4e,
 | 
						0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x43,
 | 
				
			||||||
	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,
 | 
						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,
 | 
						0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65,
 | 
				
			||||||
	0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d,
 | 
						0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65,
 | 
				
			||||||
	0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43,
 | 
						0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
 | 
				
			||||||
	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a,
 | 
						0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73,
 | 
				
			||||||
	0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x15, 0x2e, 0x70, 0x62,
 | 
						0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x10, 0x75, 0x70, 0x64,
 | 
				
			||||||
	0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
 | 
						0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x2e,
 | 
				
			||||||
	0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65,
 | 
						0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61,
 | 
				
			||||||
	0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4d,
 | 
						0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x62, 0x2e,
 | 
				
			||||||
	0x0a, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74,
 | 
						0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
 | 
				
			||||||
	0x75, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f,
 | 
						0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x1b, 0x73, 0x79, 0x6e, 0x63,
 | 
				
			||||||
	0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
 | 
						0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68,
 | 
				
			||||||
	0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x53,
 | 
						0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e,
 | 
				
			||||||
	0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a,
 | 
						0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74,
 | 
				
			||||||
	0x1b, 0x73, 0x79, 0x6e, 0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
 | 
						0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
 | 
				
			||||||
	0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x70,
 | 
						0x27, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65,
 | 
				
			||||||
	0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69,
 | 
						0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
 | 
				
			||||||
	0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71,
 | 
						0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x15, 0x75, 0x70, 0x64, 0x61,
 | 
				
			||||||
	0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4e, 0x6f,
 | 
						0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65,
 | 
				
			||||||
	0x64, 0x65, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c,
 | 
						0x64, 0x12, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64,
 | 
				
			||||||
	0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a,
 | 
						0x65, 0x49, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75,
 | 
				
			||||||
	0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
						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, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06,
 | 
				
			||||||
 | 
						0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -1221,7 +1329,7 @@ func file_service_node_proto_rawDescGZIP() []byte {
 | 
				
			|||||||
	return file_service_node_proto_rawDescData
 | 
						return file_service_node_proto_rawDescData
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var file_service_node_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
 | 
					var file_service_node_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
 | 
				
			||||||
var file_service_node_proto_goTypes = []interface{}{
 | 
					var file_service_node_proto_goTypes = []interface{}{
 | 
				
			||||||
	(*CreateNodeRequest)(nil),                   // 0: pb.CreateNodeRequest
 | 
						(*CreateNodeRequest)(nil),                   // 0: pb.CreateNodeRequest
 | 
				
			||||||
	(*CreateNodeResponse)(nil),                  // 1: pb.CreateNodeResponse
 | 
						(*CreateNodeResponse)(nil),                  // 1: pb.CreateNodeResponse
 | 
				
			||||||
@@ -1245,14 +1353,16 @@ var file_service_node_proto_goTypes = []interface{}{
 | 
				
			|||||||
	(*SyncNodesVersionWithClusterResponse)(nil), // 19: pb.SyncNodesVersionWithClusterResponse
 | 
						(*SyncNodesVersionWithClusterResponse)(nil), // 19: pb.SyncNodesVersionWithClusterResponse
 | 
				
			||||||
	(*CountAllEnabledNodesMatchRequest)(nil),    // 20: pb.CountAllEnabledNodesMatchRequest
 | 
						(*CountAllEnabledNodesMatchRequest)(nil),    // 20: pb.CountAllEnabledNodesMatchRequest
 | 
				
			||||||
	(*CountAllEnabledNodesMatchResponse)(nil),   // 21: pb.CountAllEnabledNodesMatchResponse
 | 
						(*CountAllEnabledNodesMatchResponse)(nil),   // 21: pb.CountAllEnabledNodesMatchResponse
 | 
				
			||||||
	(*NodeLogin)(nil),                           // 22: pb.NodeLogin
 | 
						(*UpdateNodeIsInstalledRequest)(nil),        // 22: pb.UpdateNodeIsInstalledRequest
 | 
				
			||||||
	(*Node)(nil),                                // 23: pb.Node
 | 
						(*UpdateNodeIsInstalledResponse)(nil),       // 23: pb.UpdateNodeIsInstalledResponse
 | 
				
			||||||
 | 
						(*NodeLogin)(nil),                           // 24: pb.NodeLogin
 | 
				
			||||||
 | 
						(*Node)(nil),                                // 25: pb.Node
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
var file_service_node_proto_depIdxs = []int32{
 | 
					var file_service_node_proto_depIdxs = []int32{
 | 
				
			||||||
	22, // 0: pb.CreateNodeRequest.Login:type_name -> pb.NodeLogin
 | 
						24, // 0: pb.CreateNodeRequest.Login:type_name -> pb.NodeLogin
 | 
				
			||||||
	23, // 1: pb.ListEnabledNodesMatchResponse.nodes:type_name -> pb.Node
 | 
						25, // 1: pb.ListEnabledNodesMatchResponse.nodes:type_name -> pb.Node
 | 
				
			||||||
	22, // 2: pb.UpdateNodeRequest.Login:type_name -> pb.NodeLogin
 | 
						24, // 2: pb.UpdateNodeRequest.Login:type_name -> pb.NodeLogin
 | 
				
			||||||
	23, // 3: pb.FindEnabledNodeResponse.node:type_name -> pb.Node
 | 
						25, // 3: pb.FindEnabledNodeResponse.node:type_name -> pb.Node
 | 
				
			||||||
	0,  // 4: pb.NodeService.createNode:input_type -> pb.CreateNodeRequest
 | 
						0,  // 4: pb.NodeService.createNode:input_type -> pb.CreateNodeRequest
 | 
				
			||||||
	2,  // 5: pb.NodeService.countAllEnabledNodes:input_type -> pb.CountAllEnabledNodesRequest
 | 
						2,  // 5: pb.NodeService.countAllEnabledNodes:input_type -> pb.CountAllEnabledNodesRequest
 | 
				
			||||||
	20, // 6: pb.NodeService.countAllEnabledNodesMatch:input_type -> pb.CountAllEnabledNodesMatchRequest
 | 
						20, // 6: pb.NodeService.countAllEnabledNodesMatch:input_type -> pb.CountAllEnabledNodesMatchRequest
 | 
				
			||||||
@@ -1264,19 +1374,21 @@ var file_service_node_proto_depIdxs = []int32{
 | 
				
			|||||||
	14, // 12: pb.NodeService.nodeStream:input_type -> pb.NodeStreamRequest
 | 
						14, // 12: pb.NodeService.nodeStream:input_type -> pb.NodeStreamRequest
 | 
				
			||||||
	16, // 13: pb.NodeService.updateNodeStatus:input_type -> pb.UpdateNodeStatusRequest
 | 
						16, // 13: pb.NodeService.updateNodeStatus:input_type -> pb.UpdateNodeStatusRequest
 | 
				
			||||||
	18, // 14: pb.NodeService.syncNodesVersionWithCluster:input_type -> pb.SyncNodesVersionWithClusterRequest
 | 
						18, // 14: pb.NodeService.syncNodesVersionWithCluster:input_type -> pb.SyncNodesVersionWithClusterRequest
 | 
				
			||||||
	1,  // 15: pb.NodeService.createNode:output_type -> pb.CreateNodeResponse
 | 
						22, // 15: pb.NodeService.updateNodeIsInstalled:input_type -> pb.UpdateNodeIsInstalledRequest
 | 
				
			||||||
	3,  // 16: pb.NodeService.countAllEnabledNodes:output_type -> pb.CountAllEnabledNodesResponse
 | 
						1,  // 16: pb.NodeService.createNode:output_type -> pb.CreateNodeResponse
 | 
				
			||||||
	21, // 17: pb.NodeService.countAllEnabledNodesMatch:output_type -> pb.CountAllEnabledNodesMatchResponse
 | 
						3,  // 17: pb.NodeService.countAllEnabledNodes:output_type -> pb.CountAllEnabledNodesResponse
 | 
				
			||||||
	5,  // 18: pb.NodeService.listEnabledNodesMatch:output_type -> pb.ListEnabledNodesMatchResponse
 | 
						21, // 18: pb.NodeService.countAllEnabledNodesMatch:output_type -> pb.CountAllEnabledNodesMatchResponse
 | 
				
			||||||
	7,  // 19: pb.NodeService.disableNode:output_type -> pb.DisableNodeResponse
 | 
						5,  // 19: pb.NodeService.listEnabledNodesMatch:output_type -> pb.ListEnabledNodesMatchResponse
 | 
				
			||||||
	9,  // 20: pb.NodeService.updateNode:output_type -> pb.UpdateNodeResponse
 | 
						7,  // 20: pb.NodeService.disableNode:output_type -> pb.DisableNodeResponse
 | 
				
			||||||
	11, // 21: pb.NodeService.findEnabledNode:output_type -> pb.FindEnabledNodeResponse
 | 
						9,  // 21: pb.NodeService.updateNode:output_type -> pb.UpdateNodeResponse
 | 
				
			||||||
	13, // 22: pb.NodeService.composeNodeConfig:output_type -> pb.ComposeNodeConfigResponse
 | 
						11, // 22: pb.NodeService.findEnabledNode:output_type -> pb.FindEnabledNodeResponse
 | 
				
			||||||
	15, // 23: pb.NodeService.nodeStream:output_type -> pb.NodeStreamResponse
 | 
						13, // 23: pb.NodeService.composeNodeConfig:output_type -> pb.ComposeNodeConfigResponse
 | 
				
			||||||
	17, // 24: pb.NodeService.updateNodeStatus:output_type -> pb.UpdateNodeStatusResponse
 | 
						15, // 24: pb.NodeService.nodeStream:output_type -> pb.NodeStreamResponse
 | 
				
			||||||
	19, // 25: pb.NodeService.syncNodesVersionWithCluster:output_type -> pb.SyncNodesVersionWithClusterResponse
 | 
						17, // 25: pb.NodeService.updateNodeStatus:output_type -> pb.UpdateNodeStatusResponse
 | 
				
			||||||
	15, // [15:26] is the sub-list for method output_type
 | 
						19, // 26: pb.NodeService.syncNodesVersionWithCluster:output_type -> pb.SyncNodesVersionWithClusterResponse
 | 
				
			||||||
	4,  // [4:15] is the sub-list for method input_type
 | 
						23, // 27: pb.NodeService.updateNodeIsInstalled:output_type -> pb.UpdateNodeIsInstalledResponse
 | 
				
			||||||
 | 
						16, // [16:28] is the sub-list for method output_type
 | 
				
			||||||
 | 
						4,  // [4:16] 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 type_name
 | 
				
			||||||
	4,  // [4:4] is the sub-list for extension extendee
 | 
						4,  // [4:4] is the sub-list for extension extendee
 | 
				
			||||||
	0,  // [0:4] is the sub-list for field type_name
 | 
						0,  // [0:4] is the sub-list for field type_name
 | 
				
			||||||
@@ -1554,6 +1666,30 @@ func file_service_node_proto_init() {
 | 
				
			|||||||
				return nil
 | 
									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
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	type x struct{}
 | 
						type x struct{}
 | 
				
			||||||
	out := protoimpl.TypeBuilder{
 | 
						out := protoimpl.TypeBuilder{
 | 
				
			||||||
@@ -1561,7 +1697,7 @@ func file_service_node_proto_init() {
 | 
				
			|||||||
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 | 
								GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 | 
				
			||||||
			RawDescriptor: file_service_node_proto_rawDesc,
 | 
								RawDescriptor: file_service_node_proto_rawDesc,
 | 
				
			||||||
			NumEnums:      0,
 | 
								NumEnums:      0,
 | 
				
			||||||
			NumMessages:   22,
 | 
								NumMessages:   24,
 | 
				
			||||||
			NumExtensions: 0,
 | 
								NumExtensions: 0,
 | 
				
			||||||
			NumServices:   1,
 | 
								NumServices:   1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -1609,6 +1745,8 @@ type NodeServiceClient interface {
 | 
				
			|||||||
	UpdateNodeStatus(ctx context.Context, in *UpdateNodeStatusRequest, opts ...grpc.CallOption) (*UpdateNodeStatusResponse, error)
 | 
						UpdateNodeStatus(ctx context.Context, in *UpdateNodeStatusRequest, opts ...grpc.CallOption) (*UpdateNodeStatusResponse, error)
 | 
				
			||||||
	// 同步集群中的节点版本
 | 
						// 同步集群中的节点版本
 | 
				
			||||||
	SyncNodesVersionWithCluster(ctx context.Context, in *SyncNodesVersionWithClusterRequest, opts ...grpc.CallOption) (*SyncNodesVersionWithClusterResponse, error)
 | 
						SyncNodesVersionWithCluster(ctx context.Context, in *SyncNodesVersionWithClusterRequest, opts ...grpc.CallOption) (*SyncNodesVersionWithClusterResponse, error)
 | 
				
			||||||
 | 
						// 修改节点安装状态
 | 
				
			||||||
 | 
						UpdateNodeIsInstalled(ctx context.Context, in *UpdateNodeIsInstalledRequest, opts ...grpc.CallOption) (*UpdateNodeIsInstalledResponse, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type nodeServiceClient struct {
 | 
					type nodeServiceClient struct {
 | 
				
			||||||
@@ -1740,6 +1878,15 @@ func (c *nodeServiceClient) SyncNodesVersionWithCluster(ctx context.Context, in
 | 
				
			|||||||
	return out, nil
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NodeServiceServer is the server API for NodeService service.
 | 
					// NodeServiceServer is the server API for NodeService service.
 | 
				
			||||||
type NodeServiceServer interface {
 | 
					type NodeServiceServer interface {
 | 
				
			||||||
	// 创建节点
 | 
						// 创建节点
 | 
				
			||||||
@@ -1764,6 +1911,8 @@ type NodeServiceServer interface {
 | 
				
			|||||||
	UpdateNodeStatus(context.Context, *UpdateNodeStatusRequest) (*UpdateNodeStatusResponse, error)
 | 
						UpdateNodeStatus(context.Context, *UpdateNodeStatusRequest) (*UpdateNodeStatusResponse, error)
 | 
				
			||||||
	// 同步集群中的节点版本
 | 
						// 同步集群中的节点版本
 | 
				
			||||||
	SyncNodesVersionWithCluster(context.Context, *SyncNodesVersionWithClusterRequest) (*SyncNodesVersionWithClusterResponse, error)
 | 
						SyncNodesVersionWithCluster(context.Context, *SyncNodesVersionWithClusterRequest) (*SyncNodesVersionWithClusterResponse, error)
 | 
				
			||||||
 | 
						// 修改节点安装状态
 | 
				
			||||||
 | 
						UpdateNodeIsInstalled(context.Context, *UpdateNodeIsInstalledRequest) (*UpdateNodeIsInstalledResponse, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnimplementedNodeServiceServer can be embedded to have forward compatible implementations.
 | 
					// UnimplementedNodeServiceServer can be embedded to have forward compatible implementations.
 | 
				
			||||||
@@ -1803,6 +1952,9 @@ func (*UnimplementedNodeServiceServer) UpdateNodeStatus(context.Context, *Update
 | 
				
			|||||||
func (*UnimplementedNodeServiceServer) SyncNodesVersionWithCluster(context.Context, *SyncNodesVersionWithClusterRequest) (*SyncNodesVersionWithClusterResponse, error) {
 | 
					func (*UnimplementedNodeServiceServer) SyncNodesVersionWithCluster(context.Context, *SyncNodesVersionWithClusterRequest) (*SyncNodesVersionWithClusterResponse, error) {
 | 
				
			||||||
	return nil, status.Errorf(codes.Unimplemented, "method SyncNodesVersionWithCluster not implemented")
 | 
						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 RegisterNodeServiceServer(s *grpc.Server, srv NodeServiceServer) {
 | 
					func RegisterNodeServiceServer(s *grpc.Server, srv NodeServiceServer) {
 | 
				
			||||||
	s.RegisterService(&_NodeService_serviceDesc, srv)
 | 
						s.RegisterService(&_NodeService_serviceDesc, srv)
 | 
				
			||||||
@@ -2014,6 +2166,24 @@ func _NodeService_SyncNodesVersionWithCluster_Handler(srv interface{}, ctx conte
 | 
				
			|||||||
	return interceptor(ctx, in, info, handler)
 | 
						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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _NodeService_serviceDesc = grpc.ServiceDesc{
 | 
					var _NodeService_serviceDesc = grpc.ServiceDesc{
 | 
				
			||||||
	ServiceName: "pb.NodeService",
 | 
						ServiceName: "pb.NodeService",
 | 
				
			||||||
	HandlerType: (*NodeServiceServer)(nil),
 | 
						HandlerType: (*NodeServiceServer)(nil),
 | 
				
			||||||
@@ -2058,6 +2228,10 @@ var _NodeService_serviceDesc = grpc.ServiceDesc{
 | 
				
			|||||||
			MethodName: "syncNodesVersionWithCluster",
 | 
								MethodName: "syncNodesVersionWithCluster",
 | 
				
			||||||
			Handler:    _NodeService_SyncNodesVersionWithCluster_Handler,
 | 
								Handler:    _NodeService_SyncNodesVersionWithCluster_Handler,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MethodName: "updateNodeIsInstalled",
 | 
				
			||||||
 | 
								Handler:    _NodeService_UpdateNodeIsInstalled_Handler,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	Streams: []grpc.StreamDesc{
 | 
						Streams: []grpc.StreamDesc{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								internal/rpc/protos/model_api_node.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/rpc/protos/model_api_node.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					syntax = "proto3";
 | 
				
			||||||
 | 
					option go_package = "./pb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message APINode {
 | 
				
			||||||
 | 
						int64 id = 1;
 | 
				
			||||||
 | 
						bool isOn = 2;
 | 
				
			||||||
 | 
						int64 clusterId = 3;
 | 
				
			||||||
 | 
						string uniqueId = 4;
 | 
				
			||||||
 | 
						string secret = 5;
 | 
				
			||||||
 | 
						string name = 6;
 | 
				
			||||||
 | 
						string description = 7;
 | 
				
			||||||
 | 
						string host = 8;
 | 
				
			||||||
 | 
						int32 port = 9;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										99
									
								
								internal/rpc/protos/service_api_node.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								internal/rpc/protos/service_api_node.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					syntax = "proto3";
 | 
				
			||||||
 | 
					option go_package = "./pb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pb;
 | 
				
			||||||
 | 
					import "model_api_node.proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					service APINodeService {
 | 
				
			||||||
 | 
						// 创建API节点
 | 
				
			||||||
 | 
						rpc createAPINode (CreateAPINodeRequest) returns (CreateAPINodeResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 修改API节点
 | 
				
			||||||
 | 
						rpc updateAPINode (UpdateAPINodeRequest) returns (UpdateAPINodeResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 删除API节点
 | 
				
			||||||
 | 
						rpc deleteAPINode (DeleteAPINodeRequest) returns (DeleteAPINodeResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 列出所有可用API节点
 | 
				
			||||||
 | 
						rpc findAllEnabledAPINodes (FindAllEnabledAPINodesRequest) returns (FindAllEnabledAPINodesResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 计算API节点数量
 | 
				
			||||||
 | 
						rpc countAllEnabledAPINodes (CountAllEnabledAPINodesRequest) returns (CountAllEnabledAPINodesResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 列出单页的API节点
 | 
				
			||||||
 | 
						rpc listEnabledAPINodes (ListEnabledAPINodesRequest) returns (ListEnabledAPINodesResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 根据ID查找节点
 | 
				
			||||||
 | 
						rpc findEnabledAPINode (FindEnabledAPINodeRequest) returns (FindEnabledAPINodeResponse);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建API节点
 | 
				
			||||||
 | 
					message CreateAPINodeRequest {
 | 
				
			||||||
 | 
						string name = 1;
 | 
				
			||||||
 | 
						string description = 2;
 | 
				
			||||||
 | 
						string host = 3;
 | 
				
			||||||
 | 
						int32 port = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message CreateAPINodeResponse {
 | 
				
			||||||
 | 
						int64 nodeId = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 修改API节点
 | 
				
			||||||
 | 
					message UpdateAPINodeRequest {
 | 
				
			||||||
 | 
						int64 nodeId = 1;
 | 
				
			||||||
 | 
						string name = 2;
 | 
				
			||||||
 | 
						string description = 3;
 | 
				
			||||||
 | 
						string host = 4;
 | 
				
			||||||
 | 
						int32 port = 5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message UpdateAPINodeResponse {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 删除API节点
 | 
				
			||||||
 | 
					message DeleteAPINodeRequest {
 | 
				
			||||||
 | 
						int64 nodeId = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message DeleteAPINodeResponse {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 列出所有可用API节点
 | 
				
			||||||
 | 
					message FindAllEnabledAPINodesRequest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message FindAllEnabledAPINodesResponse {
 | 
				
			||||||
 | 
						repeated APINode nodes = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 计算API节点数量
 | 
				
			||||||
 | 
					message CountAllEnabledAPINodesRequest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message CountAllEnabledAPINodesResponse {
 | 
				
			||||||
 | 
						int64 count = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 列出单页的API节点
 | 
				
			||||||
 | 
					message ListEnabledAPINodesRequest {
 | 
				
			||||||
 | 
						int64 offset = 1;
 | 
				
			||||||
 | 
						int64 size = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message ListEnabledAPINodesResponse {
 | 
				
			||||||
 | 
						repeated APINode nodes = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据ID查找节点
 | 
				
			||||||
 | 
					message FindEnabledAPINodeRequest {
 | 
				
			||||||
 | 
						int64 nodeId = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message FindEnabledAPINodeResponse {
 | 
				
			||||||
 | 
						APINode node = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -38,6 +38,9 @@ service NodeService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// 同步集群中的节点版本
 | 
						// 同步集群中的节点版本
 | 
				
			||||||
	rpc syncNodesVersionWithCluster (SyncNodesVersionWithClusterRequest) returns (SyncNodesVersionWithClusterResponse);
 | 
						rpc syncNodesVersionWithCluster (SyncNodesVersionWithClusterRequest) returns (SyncNodesVersionWithClusterResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 修改节点安装状态
 | 
				
			||||||
 | 
						rpc updateNodeIsInstalled (UpdateNodeIsInstalledRequest) returns (UpdateNodeIsInstalledResponse);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 创建节点
 | 
					// 创建节点
 | 
				
			||||||
@@ -144,4 +147,14 @@ message CountAllEnabledNodesMatchRequest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
message CountAllEnabledNodesMatchResponse {
 | 
					message CountAllEnabledNodesMatchResponse {
 | 
				
			||||||
	int64 count = 1;
 | 
						int64 count = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 修改节点安装状态
 | 
				
			||||||
 | 
					message UpdateNodeIsInstalledRequest {
 | 
				
			||||||
 | 
						int64 nodeId = 1;
 | 
				
			||||||
 | 
						bool isInstalled = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message UpdateNodeIsInstalledResponse {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										161
									
								
								internal/rpc/services/service_api_node.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								internal/rpc/services/service_api_node.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
				
			|||||||
 | 
					package services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/db/models"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/rpc/pb"
 | 
				
			||||||
 | 
						rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type APINodeService struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建API节点
 | 
				
			||||||
 | 
					func (this *APINodeService) CreateAPINode(ctx context.Context, req *pb.CreateAPINodeRequest) (*pb.CreateAPINodeResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nodeId, err := models.SharedAPINodeDAO.CreateAPINode(req.Name, req.Description, req.Host, int(req.Port))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.CreateAPINodeResponse{NodeId: nodeId}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 修改API节点
 | 
				
			||||||
 | 
					func (this *APINodeService) UpdateAPINode(ctx context.Context, req *pb.UpdateAPINodeRequest) (*pb.UpdateAPINodeResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = models.SharedAPINodeDAO.UpdateAPINode(req.NodeId, req.Name, req.Description, req.Host, int(req.Port))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.UpdateAPINodeResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 删除API节点
 | 
				
			||||||
 | 
					func (this *APINodeService) DeleteAPINode(ctx context.Context, req *pb.DeleteAPINodeRequest) (*pb.DeleteAPINodeResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = models.SharedAPINodeDAO.DisableAPINode(req.NodeId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.DeleteAPINodeResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 列出所有可用API节点
 | 
				
			||||||
 | 
					func (this *APINodeService) FindAllEnabledAPINodes(ctx context.Context, req *pb.FindAllEnabledAPINodesRequest) (*pb.FindAllEnabledAPINodesResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nodes, err := models.SharedAPINodeDAO.FindAllEnabledAPINodes()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := []*pb.APINode{}
 | 
				
			||||||
 | 
						for _, node := range nodes {
 | 
				
			||||||
 | 
							result = append(result, &pb.APINode{
 | 
				
			||||||
 | 
								Id:          int64(node.Id),
 | 
				
			||||||
 | 
								IsOn:        node.IsOn == 1,
 | 
				
			||||||
 | 
								ClusterId:   int64(node.ClusterId),
 | 
				
			||||||
 | 
								UniqueId:    node.UniqueId,
 | 
				
			||||||
 | 
								Secret:      node.Secret,
 | 
				
			||||||
 | 
								Name:        node.Name,
 | 
				
			||||||
 | 
								Description: node.Description,
 | 
				
			||||||
 | 
								Host:        node.Host,
 | 
				
			||||||
 | 
								Port:        int32(node.Port),
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.FindAllEnabledAPINodesResponse{Nodes: result}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 计算API节点数量
 | 
				
			||||||
 | 
					func (this *APINodeService) CountAllEnabledAPINodes(ctx context.Context, req *pb.CountAllEnabledAPINodesRequest) (*pb.CountAllEnabledAPINodesResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.SharedAPINodeDAO.CountAllEnabledAPINodes()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.CountAllEnabledAPINodesResponse{Count: count}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 列出单页的API节点
 | 
				
			||||||
 | 
					func (this *APINodeService) ListEnabledAPINodes(ctx context.Context, req *pb.ListEnabledAPINodesRequest) (*pb.ListEnabledAPINodesResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nodes, err := models.SharedAPINodeDAO.ListEnabledAPINodes(req.Offset, req.Size)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := []*pb.APINode{}
 | 
				
			||||||
 | 
						for _, node := range nodes {
 | 
				
			||||||
 | 
							result = append(result, &pb.APINode{
 | 
				
			||||||
 | 
								Id:          int64(node.Id),
 | 
				
			||||||
 | 
								IsOn:        node.IsOn == 1,
 | 
				
			||||||
 | 
								ClusterId:   int64(node.ClusterId),
 | 
				
			||||||
 | 
								UniqueId:    node.UniqueId,
 | 
				
			||||||
 | 
								Secret:      node.Secret,
 | 
				
			||||||
 | 
								Name:        node.Name,
 | 
				
			||||||
 | 
								Description: node.Description,
 | 
				
			||||||
 | 
								Host:        node.Host,
 | 
				
			||||||
 | 
								Port:        int32(node.Port),
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.ListEnabledAPINodesResponse{Nodes: result}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据ID查找节点
 | 
				
			||||||
 | 
					func (this *APINodeService) FindEnabledAPINode(ctx context.Context, req *pb.FindEnabledAPINodeRequest) (*pb.FindEnabledAPINodeResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						node, err := models.SharedAPINodeDAO.FindEnabledAPINode(req.NodeId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if node == nil {
 | 
				
			||||||
 | 
							return &pb.FindEnabledAPINodeResponse{Node: nil}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := &pb.APINode{
 | 
				
			||||||
 | 
							Id:          int64(node.Id),
 | 
				
			||||||
 | 
							IsOn:        node.IsOn == 1,
 | 
				
			||||||
 | 
							ClusterId:   int64(node.ClusterId),
 | 
				
			||||||
 | 
							UniqueId:    node.UniqueId,
 | 
				
			||||||
 | 
							Secret:      node.Secret,
 | 
				
			||||||
 | 
							Name:        node.Name,
 | 
				
			||||||
 | 
							Description: node.Description,
 | 
				
			||||||
 | 
							Host:        node.Host,
 | 
				
			||||||
 | 
							Port:        int32(node.Port),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &pb.FindEnabledAPINodeResponse{Node: result}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -308,3 +308,18 @@ func (this *NodeService) SyncNodesVersionWithCluster(ctx context.Context, req *p
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return &pb.SyncNodesVersionWithClusterResponse{}, nil
 | 
						return &pb.SyncNodesVersionWithClusterResponse{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 修改节点安装状态
 | 
				
			||||||
 | 
					func (this *NodeService) UpdateNodeIsInstalled(ctx context.Context, req *pb.UpdateNodeIsInstalledRequest) (*pb.UpdateNodeIsInstalledResponse, error) {
 | 
				
			||||||
 | 
						_, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = models.SharedNodeDAO.UpdateNodeIsInstalled(req.NodeId, req.IsInstalled)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.UpdateNodeIsInstalledResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,7 @@ func ValidateRequest(ctx context.Context, userTypes ...UserType) (userType UserT
 | 
				
			|||||||
	nodeId := nodeIds[0]
 | 
						nodeId := nodeIds[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 获取角色Node信息
 | 
						// 获取角色Node信息
 | 
				
			||||||
 | 
						// TODO 缓存节点ID相关信息
 | 
				
			||||||
	apiToken, err := models.SharedApiTokenDAO.FindEnabledTokenWithNode(nodeId)
 | 
						apiToken, err := models.SharedApiTokenDAO.FindEnabledTokenWithNode(nodeId)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		utils.PrintError(err)
 | 
							utils.PrintError(err)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								internal/utils/unzip.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								internal/utils/unzip.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"archive/zip"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Unzip struct {
 | 
				
			||||||
 | 
						zipFile   string
 | 
				
			||||||
 | 
						targetDir string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewUnzip(zipFile string, targetDir string) *Unzip {
 | 
				
			||||||
 | 
						return &Unzip{
 | 
				
			||||||
 | 
							zipFile:   zipFile,
 | 
				
			||||||
 | 
							targetDir: targetDir,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Unzip) Run() error {
 | 
				
			||||||
 | 
						if len(this.zipFile) == 0 {
 | 
				
			||||||
 | 
							return errors.New("zip file should not be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.targetDir) == 0 {
 | 
				
			||||||
 | 
							return errors.New("target dir should not be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reader, err := zip.OpenReader(this.zipFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							_ = reader.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, file := range reader.File {
 | 
				
			||||||
 | 
							info := file.FileInfo()
 | 
				
			||||||
 | 
							target := this.targetDir + "/" + file.Name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 目录
 | 
				
			||||||
 | 
							if info.IsDir() {
 | 
				
			||||||
 | 
								stat, err := os.Stat(target)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if !os.IsNotExist(err) {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										err = os.MkdirAll(target, info.Mode())
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if !stat.IsDir() {
 | 
				
			||||||
 | 
									err = os.MkdirAll(target, info.Mode())
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 文件
 | 
				
			||||||
 | 
							err := func(file *zip.File, target string) error {
 | 
				
			||||||
 | 
								fileReader, err := file.Open()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									_ = fileReader.Close()
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								fileWriter, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, file.FileInfo().Mode())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									_ = fileWriter.Close()
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								_, err = io.Copy(fileWriter, fileReader)
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}(file, target)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								internal/utils/unzip_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/utils/unzip_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestUnzip_Run(t *testing.T) {
 | 
				
			||||||
 | 
						unzip := NewUnzip(Tea.Root+"/deploy/edge-node-v0.0.1.zip", Tea.Root+"/deploy/")
 | 
				
			||||||
 | 
						err := unzip.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log("OK")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user