main.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package main
  2. // NativePlanet GroundSeg: Go Edition (goseg)
  3. // 🄯 2023 ~nallux-dozryl & ~sitful-hatred
  4. // This is a Golang rewrite of GroundSeg that serves the v2 json
  5. // object via websocket.
  6. // The v2 rewrite decouples the frontend and backend, which makes it
  7. // straightforward to implement alternative backends.
  8. //
  9. // Under development: reimplementing all pyseg functionality.
  10. // Advantages:
  11. // - Really, really fast
  12. // - Event-driven
  13. // - First-class support for concurrent operations
  14. // - Very good golang Docker libraries
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "goseg/config"
  19. "goseg/docker"
  20. "goseg/rectify"
  21. "goseg/startram"
  22. "goseg/structs"
  23. "goseg/ws"
  24. "io/ioutil"
  25. "log/slog"
  26. "net/http"
  27. "os"
  28. "path/filepath"
  29. "strings"
  30. // "time"
  31. "github.com/gorilla/mux"
  32. )
  33. var (
  34. logger = slog.New(slog.NewJSONHandler(os.Stdout, nil))
  35. DevMode = false
  36. )
  37. func loadService(loadFunc func() error, errMsg string) {
  38. go func() {
  39. if err := loadFunc(); err != nil {
  40. logger.Error(fmt.Sprintf("%s %v", errMsg, err))
  41. }
  42. }()
  43. }
  44. func main() {
  45. // global SysConfig var is managed through config package
  46. conf := config.Conf()
  47. internetAvailable := config.NetCheck("1.1.1.1:53")
  48. availMsg := fmt.Sprintf("Internet available: %t", internetAvailable)
  49. logger.Info(availMsg)
  50. // async operation to retrieve version info if updates are on
  51. versionUpdateChannel := make(chan bool)
  52. remoteVersion := false
  53. if conf.UpdateMode == "auto" {
  54. remoteVersion = true
  55. // get version info from remote server
  56. go func() {
  57. _, versionUpdate := config.CheckVersion()
  58. if versionUpdate {
  59. logger.Info("Version info retrieved")
  60. }
  61. versionUpdateChannel <- versionUpdate
  62. }()
  63. // otherwise use cached if possible, or save hardcoded defaults and use that
  64. } else {
  65. confPath := filepath.Join(config.BasePath, "settings", "version_info.json")
  66. _, err := os.Open(confPath)
  67. if err != nil {
  68. // create a default if it doesn't exist
  69. err = config.CreateDefaultVersion()
  70. if err != nil {
  71. // panic if we can't create it
  72. errmsg := fmt.Sprintf("Unable to write version info! %v", err)
  73. logger.Error(errmsg)
  74. panic(errmsg)
  75. }
  76. }
  77. file, err := ioutil.ReadFile(confPath)
  78. if err != nil {
  79. errmsg := fmt.Sprintf("Unable to load version info: %v", err)
  80. panic(errmsg)
  81. }
  82. var versionStruct structs.Version
  83. if err := json.Unmarshal(file, &versionStruct); err != nil {
  84. errmsg := fmt.Sprintf("Error decoding version JSON: %v", err)
  85. panic(errmsg)
  86. }
  87. // Store in var
  88. releaseChannel := conf.UpdateBranch
  89. targetChan := versionStruct.Groundseg[releaseChannel]
  90. config.VersionInfo = targetChan
  91. }
  92. // infinite version check loop
  93. go config.CheckVersionLoop()
  94. // listen to docker daemon
  95. go docker.DockerListener()
  96. // digest docker events from eventbus
  97. go rectify.DockerSubscriptionHandler()
  98. // just making sure we can parse (debug)
  99. if len(conf.Piers) > 0 {
  100. pierList := strings.Join(conf.Piers, ", ")
  101. logger.Info(fmt.Sprintf("Loaded piers: %s", pierList))
  102. }
  103. // block until returns
  104. if remoteVersion == true {
  105. <-versionUpdateChannel
  106. }
  107. if conf.WgRegistered == true {
  108. startram.Retrieve()
  109. }
  110. // Load Netdata
  111. loadService(docker.LoadNetdata, "Unable to load Netdata!")
  112. // Load Wireguard
  113. loadService(docker.LoadWireguard, "Unable to load Wireguard!")
  114. // Load Urbits
  115. loadService(docker.LoadUrbits, "Unable to load Urbit ships!")
  116. // Load MC
  117. loadService(docker.LoadMC, "Unable to load MinIO Client!")
  118. // Load MinIOs
  119. loadService(docker.LoadMinIOs, "Unable to load MinIO containers!")
  120. // Websocket
  121. r := mux.NewRouter()
  122. r.HandleFunc("/ws", ws.WsHandler)
  123. http.ListenAndServe(":3000", r)
  124. }