github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/cmd/server/server.go (about) 1 // Package server is the micro server which runs the whole system 2 package server 3 4 import ( 5 "os" 6 "os/signal" 7 "strings" 8 "syscall" 9 "time" 10 11 "github.com/tickoalcantara12/micro/v3/cmd" 12 "github.com/tickoalcantara12/micro/v3/service/auth" 13 log "github.com/tickoalcantara12/micro/v3/service/logger" 14 "github.com/tickoalcantara12/micro/v3/service/runtime" 15 "github.com/urfave/cli/v2" 16 ) 17 18 var ( 19 // list of services managed 20 services = []string{ 21 "registry", // :8000 22 "broker", // :8003 23 "network", // :8443 24 "runtime", // :8088 25 "config", // :8001 26 "store", // :8002 27 "events", // :unset 28 "auth", // :8010 29 "proxy", // :8081 30 "api", // :8080 31 } 32 ) 33 34 var ( 35 // Name of the server microservice 36 Name = "server" 37 // Address is the server address 38 Address = ":10001" 39 ) 40 41 func init() { 42 command := &cli.Command{ 43 Name: "server", 44 Usage: "Run the micro server", 45 Description: `Launching the micro server ('micro server') will enable one to connect to it by 46 setting the appropriate Micro environment (see 'micro env' && 'micro env --help') commands.`, 47 Flags: []cli.Flag{ 48 &cli.StringFlag{ 49 Name: "address", 50 Usage: "Set the micro server address :10001", 51 EnvVars: []string{"MICRO_SERVER_ADDRESS"}, 52 }, 53 &cli.StringFlag{ 54 Name: "image", 55 Usage: "Set the micro server image", 56 EnvVars: []string{"MICRO_SERVER_IMAGE"}, 57 Value: "micro/micro:latest", 58 }, 59 }, 60 Action: func(ctx *cli.Context) error { 61 Run(ctx) 62 return nil 63 }, 64 } 65 66 for _, p := range Plugins() { 67 if cmds := p.Commands(); len(cmds) > 0 { 68 command.Subcommands = append(command.Subcommands, cmds...) 69 } 70 71 if flags := p.Flags(); len(flags) > 0 { 72 command.Flags = append(command.Flags, flags...) 73 } 74 } 75 76 cmd.Register(command) 77 } 78 79 // Run runs the entire platform 80 func Run(context *cli.Context) error { 81 if context.Args().Len() > 0 { 82 cli.ShowSubcommandHelp(context) 83 os.Exit(1) 84 } 85 86 // TODO: reimplement peering of servers e.g --peer=node1,node2,node3 87 // peers are configured as network nodes to cluster between 88 log.Info("Starting server") 89 90 // parse the env vars 91 var envvars []string 92 for _, val := range os.Environ() { 93 comps := strings.Split(val, "=") 94 if len(comps) != 2 { 95 continue 96 } 97 98 // only process MICRO_ values 99 if !strings.HasPrefix(comps[0], "MICRO_") { 100 continue 101 } 102 103 // skip the profile and proxy, that's set below since it can be service specific 104 if comps[0] == "MICRO_PROFILE" || comps[0] == "MICRO_PROXY" { 105 continue 106 } 107 108 envvars = append(envvars, val) 109 } 110 111 // save the runtime 112 runtimeServer := runtime.DefaultRuntime 113 // get the runtime environment 114 runtimeEnv := runtimeServer.String() 115 // exit after starting 116 runtimeExit := false 117 118 // start the services 119 for _, service := range services { 120 log.Infof("Registering %s", service) 121 122 // all things run by the server are `micro service [name]` 123 cmdArgs := []string{"service"} 124 125 // TODO: remove hacks 126 profile := context.String("profile") 127 128 env := envvars 129 env = append(env, "MICRO_PROFILE="+profile) 130 131 // set the proxy address, default to the network running locally 132 if service != "network" { 133 proxy := context.String("proxy_address") 134 if len(proxy) == 0 { 135 proxy = "127.0.0.1:8443" 136 } 137 env = append(env, "MICRO_PROXY="+proxy) 138 } 139 140 // for kubernetes we want to provide a port and instruct the service to bind to it. we don't do 141 // this locally because the services are not isolated and the ports will conflict 142 var port string 143 144 if runtimeEnv == "kubernetes" { 145 switch service { 146 case "api": 147 // run the api on :443, the standard port for HTTPs 148 port = "443" 149 env = append(env, "MICRO_API_ADDRESS=:443") 150 // pass :8080 for the internal service address, since this is the default port used for the 151 // static (k8s) router. Because the http api will register on :443 it won't conflict 152 env = append(env, "MICRO_SERVICE_ADDRESS=:8080") 153 case "proxy": 154 // run the proxy on :443, the standard port for HTTPs 155 port = "443" 156 env = append(env, "MICRO_PROXY_ADDRESS=:443") 157 // pass :8080 for the internal service address, since this is the default port used for the 158 // static (k8s) router. Because the grpc proxy will register on :443 it won't conflict 159 env = append(env, "MICRO_SERVICE_ADDRESS=:8080") 160 case "network": 161 port = "8443" 162 env = append(env, "MICRO_SERVICE_ADDRESS=:8443") 163 default: 164 port = "8080" 165 env = append(env, "MICRO_SERVICE_ADDRESS=:8080") 166 } 167 168 // exit after starting services 169 runtimeExit = true 170 } 171 172 // we want to pass through the global args so go up one level in the context lineage 173 if len(context.Lineage()) > 1 { 174 globCtx := context.Lineage()[1] 175 for _, f := range globCtx.FlagNames() { 176 cmdArgs = append(cmdArgs, "--"+f, context.String(f)) 177 } 178 } 179 cmdArgs = append(cmdArgs, service) 180 181 // runtime based on environment we run the service in 182 args := []runtime.CreateOption{ 183 runtime.WithCommand(os.Args[0]), 184 runtime.WithArgs(cmdArgs...), 185 runtime.WithEnv(env), 186 runtime.WithPort(port), 187 runtime.WithRetries(10), 188 runtime.WithServiceAccount("micro"), 189 runtime.WithVolume("store-pvc", "/store"), 190 runtime.CreateImage(context.String("image")), 191 runtime.CreateNamespace("micro"), 192 runtime.WithSecret("MICRO_AUTH_PUBLIC_KEY", auth.DefaultAuth.Options().PublicKey), 193 runtime.WithSecret("MICRO_AUTH_PRIVATE_KEY", auth.DefaultAuth.Options().PrivateKey), 194 } 195 196 // NOTE: we use Version right now to check for the latest release 197 muService := &runtime.Service{Name: service, Version: "latest"} 198 if err := runtimeServer.Create(muService, args...); err != nil { 199 log.Errorf("Failed to create runtime environment: %v", err) 200 return err 201 } 202 } 203 204 // server is deployed as a job in k8s, meaning it should exit once the services have been created. 205 if runtimeExit { 206 return nil 207 } 208 209 log.Info("Starting server runtime") 210 211 // start the runtime 212 if err := runtimeServer.Start(); err != nil { 213 log.Fatal(err) 214 return err 215 } 216 217 ch := make(chan os.Signal, 1) 218 signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL) 219 <-ch 220 221 runtimeServer.Stop() 222 log.Info("Stopped server") 223 224 // just wait 1 sec 225 <-time.After(time.Second) 226 227 return nil 228 }