mirror of Walter-Sparrow / lunar-tear
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 235 lines 5.9 kB view raw
1package main 2 3import ( 4 "bufio" 5 "context" 6 "flag" 7 "fmt" 8 "io" 9 "log" 10 "os" 11 "os/exec" 12 "os/signal" 13 "path/filepath" 14 "runtime" 15 "sync" 16 "syscall" 17) 18 19var ( 20 colorReset = "\033[0m" 21 colorRed = "\033[31m" 22 colorGreen = "\033[32m" 23 colorYellow = "\033[33m" 24 colorCyan = "\033[36m" 25) 26 27type service struct { 28 label string 29 color string 30 cmd *exec.Cmd 31} 32 33func binExt() string { 34 if runtime.GOOS == "windows" { 35 return ".exe" 36 } 37 return "" 38} 39 40func buildAll() { 41 if err := os.MkdirAll("bin", 0755); err != nil { 42 log.Fatalf("create bin/: %v", err) 43 } 44 45 type target struct { 46 name string 47 pkg string 48 } 49 targets := []target{ 50 {"auth-server", "./cmd/auth-server"}, 51 {"octo-cdn", "./cmd/octo-cdn"}, 52 {"lunar-tear", "./cmd/lunar-tear"}, 53 } 54 55 ext := binExt() 56 var wg sync.WaitGroup 57 errs := make(chan error, len(targets)) 58 59 for _, t := range targets { 60 wg.Add(1) 61 go func(t target) { 62 defer wg.Done() 63 out := filepath.Join("bin", t.name+ext) 64 cmd := exec.Command("go", "build", "-o", out, t.pkg) 65 cmd.Stdout = os.Stdout 66 cmd.Stderr = os.Stderr 67 if err := cmd.Run(); err != nil { 68 errs <- fmt.Errorf("build %s: %w", t.name, err) 69 } 70 }(t) 71 } 72 wg.Wait() 73 close(errs) 74 75 for err := range errs { 76 log.Fatal(err) 77 } 78} 79 80func main() { 81 // auth-server flags 82 authListen := flag.String("auth.listen", "0.0.0.0:3000", "auth-server listen address (host:port)") 83 authDB := flag.String("auth.db", "db/auth.db", "auth-server SQLite database path") 84 85 // octo-cdn flags 86 cdnListen := flag.String("cdn.listen", "0.0.0.0:8080", "octo-cdn local bind address") 87 cdnPublicAddr := flag.String("cdn.public-addr", "10.0.2.2:8080", "octo-cdn externally-reachable address") 88 89 // lunar-tear (grpc) flags 90 grpcListen := flag.String("grpc.listen", "0.0.0.0:8003", "lunar-tear gRPC listen address (host:port)") 91 grpcPublicAddr := flag.String("grpc.public-addr", "10.0.2.2:8003", "lunar-tear externally-reachable address") 92 grpcDB := flag.String("grpc.db", "db/game.db", "lunar-tear SQLite database path") 93 grpcOctoURL := flag.String("grpc.octo-url", "", "Octo CDN base URL passed to lunar-tear (default: derived from cdn.public-addr)") 94 grpcAuthURL := flag.String("grpc.auth-url", "", "auth server base URL passed to lunar-tear (default: derived from auth.listen)") 95 96 // admin webhook is opt-in; empty leaves lunar-tear's own default in place 97 // (the listener still only binds if LUNAR_ADMIN_TOKEN is set in the env). 98 adminListen := flag.String("admin.listen", "", "lunar-tear admin webhook listen address (host:port). Empty = leave default; webhook only binds when LUNAR_ADMIN_TOKEN is set in the env.") 99 100 // Controlled server access 101 noRegister := flag.Bool("no-register", false, "Disallow new account registrations for clients, when present. Default = false") 102 103 // dev utility output config 104 noColor := flag.Bool("no-color", false, "disable colored output") 105 106 flag.Parse() 107 108 if *grpcOctoURL == "" { 109 *grpcOctoURL = fmt.Sprintf("http://%s", *cdnPublicAddr) 110 } 111 if *grpcAuthURL == "" { 112 *grpcAuthURL = fmt.Sprintf("http://%s", *authListen) 113 } 114 115 if *noColor || !colorSupported() { 116 colorReset = "" 117 colorRed = "" 118 colorGreen = "" 119 colorYellow = "" 120 colorCyan = "" 121 } 122 123 log.Println("building services...") 124 buildAll() 125 126 ext := binExt() 127 ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) 128 defer stop() 129 130 noreg_s := "" 131 if *noRegister { 132 noreg_s = "--no-register" 133 } 134 135 services := []service{ 136 { 137 label: "auth", 138 color: colorGreen, 139 cmd: exec.CommandContext(ctx, filepath.Join("bin", "auth-server"+ext), 140 "--listen", *authListen, 141 "--db", *authDB, 142 noreg_s, 143 ), 144 }, 145 { 146 label: "cdn", 147 color: colorCyan, 148 cmd: exec.CommandContext(ctx, filepath.Join("bin", "octo-cdn"+ext), 149 "--listen", *cdnListen, 150 "--public-addr", *cdnPublicAddr, 151 ), 152 }, 153 { 154 label: "grpc", 155 color: colorYellow, 156 cmd: exec.CommandContext(ctx, filepath.Join("bin", "lunar-tear"+ext), 157 grpcArgs(*grpcListen, *grpcPublicAddr, *grpcDB, *grpcOctoURL, *grpcAuthURL, *adminListen, *noRegister)..., 158 ), 159 }, 160 } 161 162 var wg sync.WaitGroup 163 errCh := make(chan error, len(services)) 164 165 for i := range services { 166 svc := &services[i] 167 stdout, err := svc.cmd.StdoutPipe() 168 if err != nil { 169 log.Fatalf("[%s] stdout pipe: %v", svc.label, err) 170 } 171 stderr, err := svc.cmd.StderrPipe() 172 if err != nil { 173 log.Fatalf("[%s] stderr pipe: %v", svc.label, err) 174 } 175 176 if err := svc.cmd.Start(); err != nil { 177 log.Fatalf("[%s] start: %v", svc.label, err) 178 } 179 180 prefix := fmt.Sprintf("%s[%s]%s ", svc.color, svc.label, colorReset) 181 wg.Add(2) 182 go prefixLines(&wg, prefix, stdout) 183 go prefixLines(&wg, prefix, stderr) 184 185 wg.Add(1) 186 go func(s *service) { 187 defer wg.Done() 188 if err := s.cmd.Wait(); err != nil { 189 errCh <- fmt.Errorf("[%s] %w", s.label, err) 190 } 191 }(svc) 192 193 log.Printf("%s%s started (pid %d)%s", svc.color, svc.label, svc.cmd.Process.Pid, colorReset) 194 } 195 196 select { 197 case <-ctx.Done(): 198 log.Println("shutting down all services...") 199 case err := <-errCh: 200 log.Printf("%s%s%s", colorRed, err, colorReset) 201 stop() 202 } 203 204 wg.Wait() 205} 206 207func prefixLines(wg *sync.WaitGroup, prefix string, r io.Reader) { 208 defer wg.Done() 209 scanner := bufio.NewScanner(r) 210 for scanner.Scan() { 211 fmt.Printf("%s%s\n", prefix, scanner.Text()) 212 } 213} 214 215// grpcArgs assembles the argv for the lunar-tear subprocess. The admin flag 216// is appended only when --admin.listen was supplied so we don't override 217// lunar-tear's own default when the operator hasn't opted in. 218func grpcArgs(listen, publicAddr, db, octoURL, authURL, adminListen string, noRegister bool) []string { 219 args := []string{ 220 "--listen", listen, 221 "--public-addr", publicAddr, 222 "--db", db, 223 "--octo-url", octoURL, 224 "--auth-url", authURL, 225 } 226 227 if adminListen != "" { 228 args = append(args, "--admin-listen", adminListen) 229 } 230 231 if noRegister { 232 args = append(args, "--no-register") 233 } 234 return args 235}