config.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package config
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "goseg/defaults"
  6. "goseg/structs"
  7. "io/ioutil"
  8. "log/slog"
  9. "net"
  10. "os"
  11. "path/filepath"
  12. "runtime"
  13. "sync"
  14. "time"
  15. )
  16. var (
  17. globalConfig structs.SysConfig
  18. logger = slog.New(slog.NewJSONHandler(os.Stdout, nil))
  19. BasePath = os.Getenv("GS_BASE_PATH")
  20. Architecture = getArchitecture()
  21. StartramConfig structs.StartramRetrieve
  22. DebugMode = false
  23. Ready = false
  24. GSContainers = make(map[string]structs.ContainerState)
  25. checkInterval = 5 * time.Minute
  26. confMutex sync.Mutex
  27. contMutex sync.Mutex
  28. versMutex sync.Mutex
  29. )
  30. // try initializing from system.json on disk
  31. func init() {
  32. logger.Info("Starting GroundSeg")
  33. logger.Info("Urbit is love <3")
  34. for _, arg := range os.Args[1:] {
  35. // trigger this with `./groundseg dev`
  36. if arg == "dev" {
  37. logger.Info("Starting GroundSeg in debug mode")
  38. DebugMode = true
  39. }
  40. }
  41. if BasePath == "" {
  42. // default base path
  43. BasePath = "/opt/nativeplanet/groundseg"
  44. }
  45. pathMsg := fmt.Sprintf("Loading configs from %s", BasePath)
  46. logger.Info(pathMsg)
  47. confPath := filepath.Join(BasePath, "settings", "system.json")
  48. file, err := os.Open(confPath)
  49. if err != nil {
  50. // create a default if it doesn't exist
  51. err = createDefaultConf()
  52. if err != nil {
  53. // panic if we can't create it
  54. errmsg := fmt.Sprintf("Unable to create config! Please elevate permissions. %v", err)
  55. logger.Error(errmsg)
  56. panic(errmsg)
  57. }
  58. }
  59. defer file.Close()
  60. // read the sysconfig to memory
  61. decoder := json.NewDecoder(file)
  62. err = decoder.Decode(&globalConfig)
  63. if err != nil {
  64. errmsg := fmt.Sprintf("Error decoding JSON: %v", err)
  65. logger.Error(errmsg)
  66. }
  67. }
  68. // return the global conf var
  69. func Conf() structs.SysConfig {
  70. confMutex.Lock()
  71. defer confMutex.Unlock()
  72. return globalConfig
  73. }
  74. // tell if we're amd64 or arm64
  75. func getArchitecture() string {
  76. switch runtime.GOARCH {
  77. case "arm64", "aarch64":
  78. return "arm64"
  79. default:
  80. return "amd64"
  81. }
  82. }
  83. // update by passing in a map of key:values you want to modify
  84. func UpdateConf(values map[string]interface{}) error {
  85. // mutex lock to avoid race conditions
  86. confMutex.Lock()
  87. defer confMutex.Unlock()
  88. confPath := filepath.Join(BasePath, "settings", "system.json")
  89. file, err := ioutil.ReadFile(confPath)
  90. if err != nil {
  91. errmsg := fmt.Sprintf("Unable to load config: %v", err)
  92. logger.Error(errmsg)
  93. return err
  94. }
  95. // unmarshal the config to struct
  96. var configMap map[string]interface{}
  97. if err := json.Unmarshal(file, &configMap); err != nil {
  98. errmsg := fmt.Sprintf("Error decoding JSON: %v", err)
  99. logger.Error(errmsg)
  100. return err
  101. }
  102. // update our unmarshaled struct
  103. for key, value := range values {
  104. configMap[key] = value
  105. }
  106. // marshal and persist it
  107. updatedJSON, err := json.MarshalIndent(configMap, "", " ")
  108. if err != nil {
  109. errmsg := fmt.Sprintf("Error encoding JSON: %v", err)
  110. logger.Error(errmsg)
  111. return err
  112. }
  113. // update the globalConfig var
  114. if err := json.Unmarshal(updatedJSON, &globalConfig); err != nil {
  115. errmsg := fmt.Sprintf("Error updating global config: %v", err)
  116. logger.Error(errmsg)
  117. return err
  118. }
  119. if err := ioutil.WriteFile(confPath, updatedJSON, 0644); err != nil {
  120. errmsg := fmt.Sprintf("Error writing to file: %v", err)
  121. logger.Error(errmsg)
  122. return err
  123. }
  124. return nil
  125. }
  126. // we keep map[string]structs.ContainerState in memory to keep track of the containers
  127. // eg if they're running and whether they should be
  128. // modify the desired/actual state of containers
  129. func UpdateContainerState(name string, containerState structs.ContainerState) {
  130. contMutex.Lock()
  131. defer contMutex.Unlock()
  132. GSContainers[name] = containerState
  133. res, _ := json.Marshal(containerState)
  134. logger.Info(fmt.Sprintf("%s:%s", name, string(res)))
  135. }
  136. // get the current container state
  137. func GetContainerState() map[string]structs.ContainerState {
  138. contMutex.Lock()
  139. defer contMutex.Unlock()
  140. return GSContainers
  141. }
  142. // write a default conf to disk
  143. func createDefaultConf() error {
  144. defaultConfig := defaults.SysConfig(BasePath)
  145. path := filepath.Join(BasePath, "settings", "system.json")
  146. if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
  147. return err
  148. }
  149. file, err := os.Create(path)
  150. if err != nil {
  151. return err
  152. }
  153. defer file.Close()
  154. encoder := json.NewEncoder(file)
  155. encoder.SetIndent("", " ")
  156. if err := encoder.Encode(&defaultConfig); err != nil {
  157. return err
  158. }
  159. return nil
  160. }
  161. // check outbound tcp connectivity
  162. // takes ip:port
  163. func NetCheck(netCheck string) bool {
  164. logger.Info("Checking internet access")
  165. internet := false
  166. timeout := 3 * time.Second
  167. conn, err := net.DialTimeout("tcp", netCheck, timeout)
  168. if err != nil {
  169. errmsg := fmt.Sprintf("Check internet access error: %v", err)
  170. logger.Error(errmsg)
  171. } else {
  172. internet = true
  173. _ = conn.Close()
  174. }
  175. return internet
  176. }