New file |
| | |
| | | package api |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "bee-config/controller" |
| | | "bee-config/routers" |
| | | "github.com/gin-gonic/gin" |
| | | "net/http" |
| | | "sync" |
| | | ) |
| | | |
| | | var ( |
| | | routines []routers.IRouter = []routers.IRouter{} |
| | | ) |
| | | |
| | | func init() { |
| | | routines = append(routines, controller.AddNode, controller.QueryNode) |
| | | } |
| | | |
| | | func InitRouter(wg *sync.WaitGroup) *http.Server { |
| | | r := gin.Default() |
| | | |
| | | for _, v := range routines { |
| | | methods := v.GetMethods() |
| | | if len(methods) > 0 && len(methods) > 0 { |
| | | for _, m := range methods { |
| | | r.Handle(m, v.GetPath(), v.GetHandles()...) |
| | | } |
| | | } |
| | | } |
| | | |
| | | server := &http.Server{ |
| | | Addr: ":8080", |
| | | Handler: r, |
| | | } |
| | | |
| | | wg.Add(1) |
| | | go func() { |
| | | if err := server.ListenAndServe(); nil != err { |
| | | if err != http.ErrServerClosed { |
| | | logger.Fatal("InitRouter failed with error:", err) |
| | | } else { |
| | | logger.Info("InitRouter exited by user") |
| | | } |
| | | } |
| | | |
| | | wg.Done() |
| | | }() |
| | | |
| | | return server |
| | | } |
New file |
| | |
| | | package config |
| | | |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "bytes" |
| | | "embed" |
| | | "fmt" |
| | | "gopkg.in/ini.v1" |
| | | "io" |
| | | "io/ioutil" |
| | | "os" |
| | | "path" |
| | | "path/filepath" |
| | | "strconv" |
| | | ) |
| | | |
| | | var ( |
| | | baseDir string |
| | | configFile string |
| | | baseApiPort uint16 |
| | | baseP2pPort uint16 |
| | | baseDebugPort uint16 |
| | | ) |
| | | |
| | | const ( |
| | | defaultRootDir = "/var/lib/bee" |
| | | nodePrefix = "node" |
| | | |
| | | defaultPortStep uint16 = 10 |
| | | defaultApiPort uint16 = 1633 |
| | | defaultP2pPort uint16 = 1634 |
| | | defaultDebugPort uint16 = 1635 |
| | | ) |
| | | |
| | | //go:embed static |
| | | var local embed.FS |
| | | |
| | | func init() { |
| | | dir, err := filepath.Abs(filepath.Dir(os.Args[0])) |
| | | if nil != err { |
| | | os.Exit(1) |
| | | } |
| | | configFile = path.Join(dir, "config.ini") |
| | | cfg, err := ini.LooseLoad(configFile) |
| | | if nil != err { |
| | | logger.Error("failed to load ini file, err:", err) |
| | | os.Exit(2) |
| | | } |
| | | |
| | | baseDir := cfg.Section("data").Key("dir").MustString(defaultRootDir); |
| | | err = os.MkdirAll(baseDir, os.ModePerm) |
| | | if nil != err { |
| | | logger.Error("failed to mkdir path:", baseDir, ", err:", err) |
| | | os.Exit(3) |
| | | } |
| | | |
| | | fmt.Println("base dir:", baseDir) |
| | | |
| | | baseApiPort = uint16(cfg.Section("port").Key("api").MustUint(uint(defaultApiPort))) |
| | | baseP2pPort = uint16(cfg.Section("port").Key("p2p").MustUint(uint(defaultP2pPort))) |
| | | baseDebugPort = uint16(cfg.Section("port").Key("debug").MustUint(uint(defaultDebugPort))) |
| | | } |
| | | |
| | | func GetNodeDir(id uint8) string { |
| | | dir := fmt.Sprintf("%s%d", nodePrefix, id) |
| | | |
| | | return path.Join(baseDir, dir) |
| | | } |
| | | |
| | | func GetApiPort(id uint8) uint16 { |
| | | port := baseApiPort + (uint16(id) - 1) * defaultPortStep |
| | | |
| | | return port |
| | | } |
| | | |
| | | func GetP2pPort(id uint8) uint16 { |
| | | port := baseP2pPort + (uint16(id) - 1) * defaultPortStep |
| | | |
| | | return port |
| | | } |
| | | |
| | | func GetDebugPort(id uint8) uint16 { |
| | | port := baseDebugPort + (uint16(id) - 1) * defaultPortStep |
| | | |
| | | return port |
| | | } |
| | | |
| | | func GenerateDockerFile(dir string, id uint8) error { |
| | | dockerFile := path.Join(dir, "docker-compose.yml") |
| | | err := copyResource(dockerFile, "static/docker-compose.yml", "") |
| | | if nil != err { |
| | | logger.Error("copyResource failed to read static resource, err:", err) |
| | | return err |
| | | } |
| | | |
| | | multipleLine := generateEnvVariable(id) |
| | | envFile := path.Join(dir, ".env") |
| | | err = copyResource(envFile, "static/env", multipleLine) |
| | | |
| | | return nil |
| | | } |
| | | |
| | | func generateEnvVariable(id uint8) string { |
| | | var b bytes.Buffer |
| | | |
| | | apiPort := strconv.Itoa(int(GetApiPort(id))) |
| | | p2pPort := strconv.Itoa(int(GetP2pPort(id))) |
| | | debugPort := strconv.Itoa(int(GetDebugPort(id))) |
| | | |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | b.WriteString(`## HTTP API listen "address" (default :1633)`) |
| | | b.WriteString("\r\n") |
| | | b.WriteString(` BEE_API_ADDR=:`) |
| | | b.WriteString(apiPort) |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | b.WriteString(`## P2P listen address (default :1634)`) |
| | | b.WriteString("\r\n") |
| | | b.WriteString(` BEE_P2P_ADDR=:`) |
| | | b.WriteString(p2pPort) |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | b.WriteString(`## debug HTTP API listen address (default :1635)`) |
| | | b.WriteString("\r\n") |
| | | b.WriteString(` BEE_DEBUG_API_ADDR=:`) |
| | | b.WriteString(debugPort) |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | b.WriteString(` API_ADDR=:`) |
| | | b.WriteString(apiPort) |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | b.WriteString(` P2P_ADDR=:`) |
| | | b.WriteString(p2pPort) |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | b.WriteString(` DEBUG_API_ADDR=:`) |
| | | b.WriteString(debugPort) |
| | | b.WriteString("\r\n") |
| | | b.WriteString("\r\n") |
| | | |
| | | return b.String() |
| | | } |
| | | |
| | | func copyResource(dest, src string, content string) error { |
| | | in, err := local.Open(src) |
| | | if nil != err { |
| | | logger.Error("copyResource failed to read static resource, err:", err) |
| | | return err |
| | | } |
| | | defer in.Close() |
| | | |
| | | out, err := os.Create(dest) |
| | | if nil != err { |
| | | logger.Error("copyResource failed to create local copy, err:", err) |
| | | return err |
| | | } |
| | | defer out.Close() |
| | | |
| | | if len(content) > 0 { |
| | | bytes, err := ioutil.ReadAll(in) |
| | | if nil != err { |
| | | logger.Error("copyResource failed to read from source file, err:", err) |
| | | return err |
| | | } |
| | | |
| | | _, err = out.WriteString(string(bytes)) |
| | | if nil != err { |
| | | logger.Error("copyResource failed to write , err:", err) |
| | | return err |
| | | } |
| | | |
| | | _, err = out.WriteString(content) |
| | | if nil != err { |
| | | logger.Error("copyResource failed to read from source file, err:", err) |
| | | return err |
| | | } |
| | | } else { |
| | | _, err = io.Copy(out, in) |
| | | if nil != err { |
| | | logger.Error("copyResource failed to copy file, err:", err) |
| | | return err |
| | | } |
| | | } |
| | | |
| | | return nil |
| | | } |
New file |
| | |
| | | version: "3" |
| | | |
| | | services: |
| | | clef-1: |
| | | image: ethersphere/clef:0.4.12 |
| | | restart: unless-stopped |
| | | environment: |
| | | - CLEF_CHAINID |
| | | volumes: |
| | | - clef-1:/app/data |
| | | command: full |
| | | |
| | | bee-1: |
| | | image: ethersphere/bee:beta |
| | | restart: unless-stopped |
| | | environment: |
| | | - BEE_API_ADDR |
| | | - BEE_BOOTNODE |
| | | - BEE_BOOTNODE_MODE |
| | | - BEE_CLEF_SIGNER_ENABLE |
| | | - BEE_CLEF_SIGNER_ENDPOINT=http://clef-1:8550 |
| | | - BEE_CONFIG |
| | | - BEE_CORS_ALLOWED_ORIGINS |
| | | - BEE_DATA_DIR |
| | | - BEE_CACHE_CAPACITY |
| | | - BEE_DB_OPEN_FILES_LIMIT |
| | | - BEE_DB_BLOCK_CACHE_CAPACITY |
| | | - BEE_DB_WRITE_BUFFER_SIZE |
| | | - BEE_DB_DISABLE_SEEKS_COMPACTION |
| | | - BEE_DEBUG_API_ADDR |
| | | - BEE_DEBUG_API_ENABLE |
| | | - BEE_GATEWAY_MODE |
| | | - BEE_GLOBAL_PINNING_ENABLE |
| | | - BEE_NAT_ADDR |
| | | - BEE_NETWORK_ID |
| | | - BEE_P2P_ADDR |
| | | - BEE_P2P_QUIC_ENABLE |
| | | - BEE_P2P_WS_ENABLE |
| | | - BEE_PASSWORD |
| | | - BEE_PASSWORD_FILE |
| | | - BEE_PAYMENT_EARLY |
| | | - BEE_PAYMENT_THRESHOLD |
| | | - BEE_PAYMENT_TOLERANCE |
| | | - BEE_RESOLVER_OPTIONS |
| | | - BEE_STANDALONE |
| | | - BEE_SWAP_ENABLE |
| | | - BEE_SWAP_ENDPOINT |
| | | - BEE_SWAP_FACTORY_ADDRESS |
| | | - BEE_SWAP_INITIAL_DEPOSIT |
| | | - BEE_TRACING_ENABLE |
| | | - BEE_TRACING_ENDPOINT |
| | | - BEE_TRACING_SERVICE_NAME |
| | | - BEE_VERBOSITY |
| | | - BEE_WELCOME_MESSAGE |
| | | - BEE_FULL_NODE |
| | | ports: |
| | | - "${API_ADDR:-1833}${BEE_API_ADDR:-:1833}" |
| | | - "${P2P_ADDR:-1834}${BEE_P2P_ADDR:-:1834}" |
| | | - "${DEBUG_API_ADDR:-127.0.0.1:1835}${BEE_DEBUG_API_ADDR:-:1835}" |
| | | volumes: |
| | | - bee-1:/home/bee/.bee |
| | | command: start |
| | | depends_on: |
| | | - clef-1 |
| | | |
| | | volumes: |
| | | clef-1: |
| | | bee-1: |
| | | |
New file |
| | |
| | | # Copy this file to .env, then update it with your own settings |
| | | |
| | | ### CLEF |
| | | |
| | | ## chain id to use for signing (1=mainnet, 3=ropsten, 4=rinkeby, 5=goerli) (default: 12345) |
| | | CLEF_CHAINID=5 |
| | | |
| | | ### BEE |
| | | |
| | | ## HTTP API listen address (default :1633) |
| | | # BEE_API_ADDR=:1633 |
| | | ## chain block time (default 15) |
| | | # BEE_BLOCK_TIME=15 |
| | | ## initial nodes to connect to (default [/dnsaddr/bootnode.ethswarm.org]) |
| | | # BEE_BOOTNODE=[/dnsaddr/bootnode.ethswarm.org] |
| | | ## cause the node to always accept incoming connections |
| | | # BEE_BOOTNODE_MODE=false |
| | | ## enable clef signer |
| | | BEE_CLEF_SIGNER_ENABLE=true |
| | | ## clef signer endpoint |
| | | # BEE_CLEF_SIGNER_ENDPOINT= |
| | | ## config file (default is /home/<user>/.bee.yaml) |
| | | # BEE_CONFIG=/home/bee/.bee.yaml |
| | | ## origins with CORS headers enabled |
| | | # BEE_CORS_ALLOWED_ORIGINS=[] |
| | | ## data directory (default /home/<user>/.bee) |
| | | # BEE_DATA_DIR=/home/bee/.bee |
| | | ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes |
| | | # BEE_CACHE_CAPACITY=1000000 |
| | | ## number of open files allowed by database |
| | | # BEE_DB_OPEN_FILES_LIMIT=200 |
| | | ## size of block cache of the database in bytes |
| | | # BEE_DB_BLOCK_CACHE_CAPACITY=33554432 |
| | | ## size of the database write buffer in bytes |
| | | # BEE_DB_WRITE_BUFFER_SIZE=33554432 |
| | | ## disables db compactions triggered by seeks |
| | | # BEE_DB_DISABLE_SEEKS_COMPACTION=false |
| | | ## debug HTTP API listen address (default :1635) |
| | | BEE_DEBUG_API_ADDR=:1635 |
| | | ## enable debug HTTP API |
| | | BEE_DEBUG_API_ENABLE=true |
| | | ## disable a set of sensitive features in the api |
| | | # BEE_GATEWAY_MODE=false |
| | | ## enable global pinning |
| | | # BEE_GLOBAL_PINNING_ENABLE=false |
| | | ## cause the node to start in full mode |
| | | BEE_FULL_NODE=true |
| | | ## NAT exposed address |
| | | # BEE_NAT_ADDR= |
| | | ## ID of the Swarm network (default 1) |
| | | # BEE_NETWORK_ID=1 |
| | | ## P2P listen address (default :1634) |
| | | # BEE_P2P_ADDR=:1634 |
| | | ## enable P2P QUIC protocol |
| | | # BEE_P2P_QUIC_ENABLE=false |
| | | ## enable P2P WebSocket transport |
| | | # BEE_P2P_WS_ENABLE=false |
| | | ## password for decrypting keys |
| | | BEE_PASSWORD=123 |
| | | ## path to a file that contains password for decrypting keys |
| | | # BEE_PASSWORD_FILE= |
| | | ## amount in BZZ below the peers payment threshold when we initiate settlement (default 1000000000000) |
| | | # BEE_PAYMENT_EARLY=1000000000000 |
| | | ## threshold in BZZ where you expect to get paid from your peers (default 10000000000000) |
| | | # BEE_PAYMENT_THRESHOLD=10000000000000 |
| | | ## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000000000000) |
| | | # BEE_PAYMENT_TOLERANCE=10000000000000 |
| | | ## postage stamp contract address |
| | | # BEE_POSTAGE_STAMP_ADDRESS= |
| | | ## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url |
| | | # BEE_RESOLVER_OPTIONS=[] |
| | | ## whether we want the node to start with no listen addresses for p2p |
| | | # BEE_STANDALONE=false |
| | | ## enable swap (default true) |
| | | # BEE_SWAP_ENABLE=true |
| | | ## swap ethereum blockchain endpoint (default ws://localhost:8546) |
| | | BEE_SWAP_ENDPOINT=wss://goerli.infura.io/ws/v3/a2ff57de9e7f43d4a06dd3328bb4ecf6 |
| | | ## swap factory address |
| | | # BEE_SWAP_FACTORY_ADDRESS= |
| | | ## legacy swap factory addresses |
| | | # BEE_SWAP_LEGACY_FACTORY_ADDRESSES= |
| | | ## initial deposit if deploying a new chequebook (default 10000000000000000) |
| | | # BEE_SWAP_INITIAL_DEPOSIT=10000000000000000 |
| | | ## gas price in wei to use for deployment and funding (default "") |
| | | # BEE_SWAP_DEPLOYMENT_GAS_PRICE= |
| | | ## enable tracing |
| | | # BEE_TRACING_ENABLE=false |
| | | ## endpoint to send tracing data (default 127.0.0.1:6831) |
| | | # BEE_TRACING_ENDPOINT=127.0.0.1:6831 |
| | | ## service name identifier for tracing (default bee) |
| | | # BEE_TRACING_SERVICE_NAME=bee |
| | | ## proof-of-identity transaction hash |
| | | # BEE_TRANSACTION= |
| | | ## log verbosity level 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace (default info) |
| | | # BEE_VERBOSITY=info |
| | | ## send a welcome message string during handshakes |
| | | BEE_WELCOME_MESSAGE=Hello,BZZ |
| | | |
New file |
| | |
| | | package controller |
| | | |
| | | import ( |
| | | "bee-config/models" |
| | | "bee-config/routers" |
| | | "bee-config/service" |
| | | "github.com/gin-gonic/gin" |
| | | "net/http" |
| | | "path" |
| | | ) |
| | | |
| | | type ( |
| | | NodeRouter struct { |
| | | routers.Router |
| | | } |
| | | ) |
| | | |
| | | const ( |
| | | basePath = "/nodes" |
| | | ) |
| | | |
| | | var ( |
| | | AddNode *NodeRouter |
| | | QueryNode *NodeRouter |
| | | ) |
| | | |
| | | func init() { |
| | | AddNode = &NodeRouter{ |
| | | routers.Router{ |
| | | Methods: []string{http.MethodGet, http.MethodPost}, |
| | | Path: "add", |
| | | Handles: []gin.HandlerFunc{addNode}, |
| | | }, |
| | | } |
| | | |
| | | QueryNode = &NodeRouter{ |
| | | routers.Router{ |
| | | Methods: []string{http.MethodGet}, |
| | | Path: "query", |
| | | Handles: []gin.HandlerFunc{queryNode}, |
| | | }, |
| | | } |
| | | } |
| | | |
| | | func (r *NodeRouter)GetPath() string { |
| | | return path.Join(basePath, r.Path) |
| | | } |
| | | |
| | | func addNode(c *gin.Context) { |
| | | address, err := service.AddNode() |
| | | if nil != err { |
| | | c.JSON(http.StatusOK, gin.H { |
| | | "code": 600, |
| | | "msg": err.Error(), |
| | | "data": &struct { |
| | | }{}, |
| | | }) |
| | | } else { |
| | | data := map[string]interface{}{} |
| | | data["address"] = address |
| | | |
| | | c.JSON(http.StatusOK, gin.H { |
| | | "code": http.StatusOK, |
| | | "msg": "ok", |
| | | "data": data, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | func queryNode(c *gin.Context) { |
| | | var node models.BeeNode |
| | | arr, err := node.FindAll() |
| | | if nil != err { |
| | | c.JSON(http.StatusOK, gin.H { |
| | | "code": 600, |
| | | "msg": err.Error(), |
| | | "data": &struct { |
| | | }{}, |
| | | }) |
| | | } else { |
| | | c.JSON(http.StatusOK, gin.H { |
| | | "code": http.StatusOK, |
| | | "msg": "ok", |
| | | "data": arr, |
| | | }) |
| | | } |
| | | } |
New file |
| | |
| | | module bee-config |
| | | |
| | | go 1.16 |
| | | |
| | | require ( |
| | | basic.com/valib/logger.git v0.0.0-20201221081153-494dab566ec8 |
| | | github.com/BurntSushi/toml v0.3.1 // indirect |
| | | github.com/gin-gonic/gin v1.7.2 |
| | | github.com/jinzhu/gorm v1.9.16 |
| | | github.com/natefinch/lumberjack v2.0.0+incompatible // indirect |
| | | github.com/smartystreets/goconvey v1.6.4 // indirect |
| | | go.uber.org/zap v1.17.0 // indirect |
| | | golang.org/x/tools v0.1.2 |
| | | gopkg.in/ini.v1 v1.62.0 |
| | | gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect |
| | | ) |
New file |
| | |
| | | basic.com/valib/logger.git v0.0.0-20201221081153-494dab566ec8 h1:tM91RTIBqt+PoMEVC4ojUNpp1DB+558DLHj5GbhIck0= |
| | | basic.com/valib/logger.git v0.0.0-20201221081153-494dab566ec8/go.mod h1:SPlOGUUlxCscwF1dkqmLb0oJXVqg1uJ8hsPXLFxrw1M= |
| | | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= |
| | | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= |
| | | github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= |
| | | github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= |
| | | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
| | | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
| | | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
| | | github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= |
| | | github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= |
| | | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= |
| | | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= |
| | | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= |
| | | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= |
| | | github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA= |
| | | github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= |
| | | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= |
| | | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= |
| | | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= |
| | | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= |
| | | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= |
| | | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= |
| | | github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= |
| | | github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= |
| | | github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= |
| | | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= |
| | | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= |
| | | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= |
| | | github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= |
| | | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= |
| | | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= |
| | | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= |
| | | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
| | | github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= |
| | | github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= |
| | | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= |
| | | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= |
| | | github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= |
| | | github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= |
| | | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= |
| | | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= |
| | | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= |
| | | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= |
| | | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= |
| | | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= |
| | | github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= |
| | | github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= |
| | | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= |
| | | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= |
| | | github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= |
| | | github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= |
| | | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= |
| | | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= |
| | | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= |
| | | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= |
| | | github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= |
| | | github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= |
| | | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= |
| | | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
| | | 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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= |
| | | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= |
| | | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= |
| | | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= |
| | | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
| | | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= |
| | | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= |
| | | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= |
| | | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
| | | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= |
| | | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= |
| | | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= |
| | | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= |
| | | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= |
| | | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= |
| | | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= |
| | | go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= |
| | | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= |
| | | go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= |
| | | go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= |
| | | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
| | | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
| | | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= |
| | | golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= |
| | | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= |
| | | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= |
| | | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= |
| | | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
| | | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
| | | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
| | | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
| | | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
| | | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= |
| | | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= |
| | | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
| | | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
| | | 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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
| | | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
| | | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
| | | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
| | | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= |
| | | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
| | | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= |
| | | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
| | | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= |
| | | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= |
| | | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
| | | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
| | | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= |
| | | golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= |
| | | golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= |
| | | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
| | | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
| | | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
| | | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |
| | | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
| | | gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= |
| | | gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= |
| | | gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= |
| | | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= |
| | | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
| | | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= |
| | | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
| | | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
| | | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= |
| | | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
New file |
| | |
| | | package main |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "bee-config/api" |
| | | "bee-config/models" |
| | | "bee-config/monitor" |
| | | "context" |
| | | "flag" |
| | | "os" |
| | | "os/signal" |
| | | "path" |
| | | "path/filepath" |
| | | "sync" |
| | | "syscall" |
| | | ) |
| | | |
| | | func init() { |
| | | flag.Parse() |
| | | |
| | | executable := filepath.Base(os.Args[0]) |
| | | dir, err := filepath.Abs(filepath.Dir(os.Args[0])) |
| | | if nil != err { |
| | | dir = "./" |
| | | } |
| | | |
| | | dir = path.Join(dir, "logs") |
| | | if _, err := os.Stat(dir); os.IsNotExist(err) { |
| | | _ = os.MkdirAll(dir, os.ModePerm) |
| | | } |
| | | |
| | | var logFile = path.Join(dir, executable + ".log") |
| | | logger.InitLogger(logFile, logger.InfoLevel, 128, 10, 3) |
| | | logger.Info("log init success !") |
| | | } |
| | | |
| | | func main() { |
| | | models.Init() |
| | | defer models.CloseDB() |
| | | |
| | | wg := &sync.WaitGroup{} |
| | | q := make(chan os.Signal, 1) |
| | | signal.Notify(q, os.Interrupt, os.Kill, syscall.SIGTERM) |
| | | ctx, cancel := context.WithCancel(context.Background()) |
| | | |
| | | monitor.Init(ctx, wg) |
| | | server := api.InitRouter(wg) |
| | | <-q |
| | | logger.Info("user signalled...") |
| | | |
| | | // shutdown http service gracefully |
| | | if err := server.Shutdown(ctx); nil != err { |
| | | logger.Fatal("server shutdown failed, err:", err) |
| | | } |
| | | |
| | | cancel() |
| | | wg.Wait() |
| | | logger.Info("all sub threads exited...") |
| | | } |
New file |
| | |
| | | package models |
| | | |
| | | import ( |
| | | "sync" |
| | | ) |
| | | |
| | | const ( |
| | | RUNNING_Currupted = 0 |
| | | RUNNING_Stopped = 1 |
| | | RUNNING_Started = 2 |
| | | ) |
| | | |
| | | type BeeNode struct { |
| | | Id int `gorm:"column:id;primary_key;unique;not null;autoIncrement" json:"id"` // 节点id |
| | | Address string `gorm:"column:address;not null;default:''" json:"address"` // 程序目录 |
| | | Dir string `gorm:"column:dir;not null;default:''" json:"dir"` // 程序目录 |
| | | ApiPort uint16 `gorm:"column:api_port" json:"apiPort"` // api port number |
| | | P2PPort uint16 `gorm:"column:p2p_port" json:"p2pPort"` // p2p port number |
| | | DebugPort uint16 `gorm:"column:debug_port" json:"debugPort"` // debug port number |
| | | Status uint8 `gorm:"column:status" json:"status"` // status |
| | | Del uint8 `gorm:"column:del" json:"del"` // del |
| | | } |
| | | |
| | | var ( |
| | | m sync.RWMutex |
| | | ) |
| | | |
| | | func (BeeNode) TableName() string { |
| | | return "t_node" |
| | | } |
| | | |
| | | func (a *BeeNode) FindAll() ([]BeeNode, error) { |
| | | var rows []BeeNode |
| | | |
| | | m.RLock() |
| | | defer m.RUnlock() |
| | | if err := db.Table(a.TableName()).Find(&rows).Error; err != nil { |
| | | return nil, err |
| | | } |
| | | |
| | | return rows, nil |
| | | } |
| | | |
| | | func (a *BeeNode) Save() error { |
| | | m.Lock() |
| | | defer m.Unlock() |
| | | |
| | | return db.Create(a).Error |
| | | } |
| | | |
| | | func (a *BeeNode) Update(status uint8) error { |
| | | m.Lock() |
| | | defer m.Unlock() |
| | | |
| | | return db.Model(a).Update("Status", status).Error |
| | | } |
New file |
| | |
| | | package models |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "github.com/jinzhu/gorm" |
| | | ) |
| | | |
| | | var db *gorm.DB |
| | | |
| | | |
| | | func Init() { |
| | | var err error |
| | | db, err = gorm.Open("sqlite3", "./version.db") |
| | | if err != nil { |
| | | logger.Error("Db Init failed", err) |
| | | return; |
| | | } else { |
| | | logger.Info("Db Init ok", err) |
| | | } |
| | | |
| | | db.LogMode(true) |
| | | db.AutoMigrate(&BeeNode{}) |
| | | } |
| | | |
| | | func GetDB() *gorm.DB { |
| | | return db |
| | | } |
| | | |
| | | func CloseDB() { |
| | | _ = db.Close() |
| | | } |
New file |
| | |
| | | package monitor |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "bee-config/config" |
| | | "bee-config/models" |
| | | "bee-config/utils" |
| | | "context" |
| | | "os" |
| | | "strings" |
| | | "sync" |
| | | "time" |
| | | ) |
| | | |
| | | func Init(ctx context.Context, wg *sync.WaitGroup) { |
| | | wg.Add(1) |
| | | go monitorLoop(ctx, wg) |
| | | } |
| | | |
| | | func monitorLoop(ctx context.Context, wg *sync.WaitGroup) { |
| | | t := time.NewTicker(time.Second * 2) |
| | | for { |
| | | select { |
| | | case <-ctx.Done(): |
| | | t.Stop() |
| | | wg.Done() |
| | | return |
| | | case <- t.C: |
| | | syncStatus() |
| | | } |
| | | } |
| | | } |
| | | |
| | | func syncStatus() { |
| | | var node models.BeeNode |
| | | arr, err := node.FindAll() |
| | | if nil != err { |
| | | logger.Error("syncStatus failed to read all data, err:", err) |
| | | return |
| | | } |
| | | |
| | | nodes := make([]*models.BeeNode, len(arr)) |
| | | |
| | | for _, v := range arr { |
| | | nodes = append(nodes, &v) |
| | | |
| | | id := uint8(v.Id) |
| | | dir := config.GetNodeDir(id) |
| | | if _, err := os.Stat(dir); os.IsNotExist(err) { |
| | | continue |
| | | } |
| | | |
| | | output, err := utils.ShellExecute(dir, "docker-compose", "ps", "-a") |
| | | if nil != err { |
| | | logger.Error("syncStatus failed to invoke docker-compose, err:", err) |
| | | continue |
| | | } |
| | | |
| | | containers := parseDockerCompose(output) |
| | | if len(containers) < 2 { |
| | | logger.Error("syncStatus no enough containers") |
| | | continue |
| | | } |
| | | |
| | | var beeStatus, clefStatus string |
| | | for _, v := range containers { |
| | | words := strings.Split(v, " ") |
| | | if len(words) < 5 { |
| | | continue |
| | | } |
| | | |
| | | if strings.Contains(words[0], "bee-1") { |
| | | beeStatus = words[3] |
| | | } |
| | | |
| | | if strings.Contains(words[0], "clef-1") { |
| | | clefStatus = words[3] |
| | | } |
| | | } |
| | | |
| | | if len(beeStatus) < 1 { |
| | | logger.Error("syncStatus failed to find bee container") |
| | | continue |
| | | } |
| | | |
| | | if len(clefStatus) < 1 { |
| | | logger.Error("syncStatus failed to find clefStatus container") |
| | | continue |
| | | } |
| | | } |
| | | } |
| | | |
| | | func parseDockerCompose(output string) []string { |
| | | lines := strings.Split(output, "\n") |
| | | for i, v := range lines { |
| | | if strings.HasPrefix(v, "------") { |
| | | index := i + 1 |
| | | return lines[index:] |
| | | } |
| | | } |
| | | |
| | | return []string{} |
| | | } |
New file |
| | |
| | | package routers |
| | | |
| | | import ( |
| | | "github.com/gin-gonic/gin" |
| | | ) |
| | | |
| | | type ( |
| | | IRouter interface { |
| | | GetMethods() []string |
| | | GetPath() string |
| | | GetHandles() gin.HandlersChain |
| | | } |
| | | |
| | | Router struct { |
| | | Methods []string |
| | | Path string |
| | | Handles gin.HandlersChain |
| | | } |
| | | ) |
| | | |
| | | func (r *Router)GetMethods() []string { |
| | | return r.Methods |
| | | } |
| | | |
| | | func (r *Router)GetPath() string { |
| | | return r.Path |
| | | } |
| | | |
| | | func (r *Router)GetHandles() gin.HandlersChain { |
| | | return r.Handles |
| | | } |
New file |
| | |
| | | package service |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "bee-config/config" |
| | | "bee-config/models" |
| | | "bee-config/utils" |
| | | "os" |
| | | "strings" |
| | | "time" |
| | | ) |
| | | |
| | | func AddNode() (string, error) { |
| | | var node models.BeeNode |
| | | arr, err := node.FindAll() |
| | | if nil != err { |
| | | logger.Error("AddNode failed to read all data, err:", err) |
| | | return "", err |
| | | } |
| | | |
| | | id := uint8(getNextId(arr)) |
| | | dir := config.GetNodeDir(id) |
| | | if _, err := os.Stat(dir); os.IsNotExist(err) { |
| | | _ = os.MkdirAll(dir, os.ModePerm) |
| | | } |
| | | |
| | | err = config.GenerateDockerFile(dir, id) |
| | | if nil != err { |
| | | logger.Error("AddNode failed to generate docker file, err:", err) |
| | | return "", err |
| | | } |
| | | |
| | | _, err = utils.ShellExecute(dir, "docker-compose", "up", "-d") |
| | | if nil != err { |
| | | logger.Error("AddNode failed to invoke docker-compose up, err:", err) |
| | | return "", err |
| | | } |
| | | |
| | | address, err := utils.ShellExecuteEx(1 * time.Minute, terminate, dir, "docker-compose", "logs", "-f", "bee-1") |
| | | if nil != err { |
| | | logger.Error("AddNode failed to invoke docker-compose logs, err:", err) |
| | | return "", err |
| | | } |
| | | |
| | | n := models.BeeNode { |
| | | Id: int(id), |
| | | Address: address, |
| | | Dir: dir, |
| | | ApiPort: uint16(config.GetApiPort(id)), |
| | | P2PPort: uint16(config.GetP2pPort(id)), |
| | | DebugPort: uint16(config.GetDebugPort(id)), |
| | | Status: 0, |
| | | Del: 0, |
| | | } |
| | | |
| | | err = n.Save() |
| | | if nil != err { |
| | | logger.Error("AddNode failed to save to db, err:", err) |
| | | return "", err |
| | | } |
| | | |
| | | return address, nil |
| | | } |
| | | |
| | | func terminate(line string) string { |
| | | token := "using ethereum address" |
| | | length := len("b02363e9ec1b2eba9415786a4fab459122d50aa1") |
| | | |
| | | index := strings.Index(line, token) |
| | | if -1 == index { |
| | | return "" |
| | | } |
| | | |
| | | index += len(token) |
| | | |
| | | substring := line[index:] |
| | | index = 0 |
| | | for { |
| | | if substring[index] == ' ' { |
| | | index++ |
| | | continue |
| | | } |
| | | |
| | | break; |
| | | } |
| | | |
| | | substring = substring[index:] |
| | | substring = substring[:length] |
| | | |
| | | return substring |
| | | } |
| | | |
| | | func getNextId(arr []models.BeeNode) int { |
| | | nextId := len(arr) + 1 |
| | | |
| | | if len(arr) == 0 { |
| | | return nextId |
| | | } |
| | | |
| | | maxId := arr[0].Id |
| | | conflicts := false |
| | | for _, v := range arr { |
| | | if v.Id == nextId { |
| | | conflicts = true |
| | | } |
| | | |
| | | if v.Id > maxId { |
| | | maxId = v.Id |
| | | } |
| | | } |
| | | |
| | | if conflicts { |
| | | nextId = maxId + 1 |
| | | } |
| | | |
| | | return nextId |
| | | } |
New file |
| | |
| | | package utils |
| | | |
| | | import ( |
| | | "bufio" |
| | | "bytes" |
| | | "errors" |
| | | "fmt" |
| | | "io" |
| | | "os" |
| | | "os/exec" |
| | | "time" |
| | | ) |
| | | |
| | | |
| | | |
| | | func ShellExecute(dir, exe string, args ...string) (string, error) { |
| | | cmd := exec.Command(exe, args...) |
| | | stdout, err := cmd.StdoutPipe(); |
| | | if nil != err { |
| | | msg := fmt.Sprintf("ShellExecute cmd.StdoutPipe err:%v", err) |
| | | return "", errors.New(msg) |
| | | } |
| | | |
| | | cmd.Stderr = os.Stderr |
| | | if "" != dir { |
| | | cmd.Dir = dir |
| | | } |
| | | |
| | | err = cmd.Start() |
| | | if nil != err { |
| | | msg := fmt.Sprintf("ShellExecute cmd.Start err:%v", err) |
| | | return "", errors.New(msg) |
| | | } |
| | | |
| | | var buffer bytes.Buffer |
| | | reader := bufio.NewReader(stdout) |
| | | for { |
| | | line, err2 := reader.ReadString('\n') |
| | | if io.EOF == err2 { |
| | | break |
| | | } |
| | | |
| | | if nil != err2 { |
| | | msg := fmt.Sprintf("ShellExecute reader.ReadString err:%v", err2) |
| | | return "", errors.New(msg) |
| | | } |
| | | |
| | | buffer.WriteString(line) |
| | | } |
| | | |
| | | err = cmd.Wait() |
| | | if nil != err { |
| | | msg := fmt.Sprintf("ShellExecute cmd.Wait err:%v", err) |
| | | return "", errors.New(msg) |
| | | } |
| | | |
| | | return buffer.String(), nil |
| | | } |
| | | |
| | | type TerminateFunc func(string) string |
| | | |
| | | func ShellExecuteEx(d time.Duration, t TerminateFunc, dir, exe string, args ...string) (string, error) { |
| | | cmd := exec.Command(exe, args...) |
| | | stdout, err := cmd.StdoutPipe(); |
| | | if nil != err { |
| | | msg := fmt.Sprintf("ShellExecuteEx cmd.StdoutPipe err:%v", err) |
| | | return "", errors.New(msg) |
| | | } |
| | | |
| | | cmd.Stderr = os.Stderr |
| | | if "" != dir { |
| | | cmd.Dir = dir |
| | | } |
| | | |
| | | err = cmd.Start() |
| | | if nil != err { |
| | | msg := fmt.Sprintf("ShellExecuteEx cmd.Start err:%v", err) |
| | | return "", errors.New(msg) |
| | | } |
| | | |
| | | ch := make(chan string) |
| | | go func(out io.ReadCloser, command *exec.Cmd) { |
| | | reader := bufio.NewReader(out) |
| | | for { |
| | | line, err2 := reader.ReadString('\n') |
| | | if io.EOF == err2 { |
| | | ch <- "" |
| | | break |
| | | } |
| | | |
| | | if nil != err2 { |
| | | break |
| | | } |
| | | |
| | | address := t(line) |
| | | if len(address) > 0 { |
| | | err := cmd.Process.Signal(os.Kill) |
| | | if nil != err { |
| | | fmt.Println("failed to send signal to child process", err) |
| | | } |
| | | ch <- address |
| | | break |
| | | } |
| | | } |
| | | }(stdout, cmd) |
| | | |
| | | var address string |
| | | select { |
| | | case address = <-ch: |
| | | err = nil |
| | | break |
| | | case <-time.After(d): |
| | | _ = cmd.Process.Signal(os.Kill) |
| | | err = errors.New("Timeout error") |
| | | break |
| | | } |
| | | |
| | | _ = cmd.Wait() |
| | | |
| | | return address, err |
| | | } |