github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/cmd/service/service.go (about) 1 // Package service provides micro service commands 2 package service 3 4 import ( 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/tickoalcantara12/micro/v3/cmd" 10 "github.com/tickoalcantara12/micro/v3/plugin" 11 "github.com/tickoalcantara12/micro/v3/service" 12 "github.com/tickoalcantara12/micro/v3/service/logger" 13 prox "github.com/tickoalcantara12/micro/v3/service/proxy" 14 "github.com/tickoalcantara12/micro/v3/service/proxy/grpc" 15 "github.com/tickoalcantara12/micro/v3/service/proxy/http" 16 "github.com/tickoalcantara12/micro/v3/service/proxy/mucp" 17 rt "github.com/tickoalcantara12/micro/v3/service/runtime" 18 "github.com/tickoalcantara12/micro/v3/service/server" 19 ccli "github.com/urfave/cli/v2" 20 21 // services 22 api "github.com/tickoalcantara12/micro/v3/service/api/server" 23 auth "github.com/tickoalcantara12/micro/v3/service/auth/server" 24 broker "github.com/tickoalcantara12/micro/v3/service/broker/server" 25 config "github.com/tickoalcantara12/micro/v3/service/config/server" 26 events "github.com/tickoalcantara12/micro/v3/service/events/server" 27 network "github.com/tickoalcantara12/micro/v3/service/network/server" 28 proxy "github.com/tickoalcantara12/micro/v3/service/proxy/server" 29 registry "github.com/tickoalcantara12/micro/v3/service/registry/server" 30 runtime "github.com/tickoalcantara12/micro/v3/service/runtime/server" 31 store "github.com/tickoalcantara12/micro/v3/service/store/server" 32 33 // misc commands 34 "github.com/tickoalcantara12/micro/v3/cmd/service/handler/exec" 35 "github.com/tickoalcantara12/micro/v3/cmd/service/handler/file" 36 ) 37 38 // Run starts a micro service sidecar to encapsulate any app 39 func Run(ctx *ccli.Context) { 40 name := ctx.String("name") 41 address := ctx.String("address") 42 endpoint := ctx.String("endpoint") 43 44 metadata := make(map[string]string) 45 for _, md := range ctx.StringSlice("metadata") { 46 parts := strings.Split(md, "=") 47 if len(parts) < 2 { 48 continue 49 } 50 51 key := parts[0] 52 val := strings.Join(parts[1:], "=") 53 54 // set the key/val 55 metadata[key] = val 56 } 57 58 var opts []service.Option 59 if len(metadata) > 0 { 60 opts = append(opts, service.Metadata(metadata)) 61 } 62 if len(name) > 0 { 63 opts = append(opts, service.Name(name)) 64 } 65 if len(address) > 0 { 66 opts = append(opts, service.Address(address)) 67 } 68 69 if len(endpoint) == 0 { 70 endpoint = prox.DefaultEndpoint 71 } 72 73 var p prox.Proxy 74 75 switch { 76 case strings.HasPrefix(endpoint, "grpc"): 77 endpoint = strings.TrimPrefix(endpoint, "grpc://") 78 p = grpc.NewProxy(prox.WithEndpoint(endpoint)) 79 case strings.HasPrefix(endpoint, "http"): 80 p = http.NewProxy(prox.WithEndpoint(endpoint)) 81 case strings.HasPrefix(endpoint, "file"): 82 endpoint = strings.TrimPrefix(endpoint, "file://") 83 p = file.NewProxy(prox.WithEndpoint(endpoint)) 84 case strings.HasPrefix(endpoint, "exec"): 85 endpoint = strings.TrimPrefix(endpoint, "exec://") 86 p = exec.NewProxy(prox.WithEndpoint(endpoint)) 87 default: 88 p = mucp.NewProxy(prox.WithEndpoint(endpoint)) 89 } 90 91 // run the service if asked to 92 if ctx.Args().Len() > 0 { 93 args := []rt.CreateOption{ 94 rt.WithCommand(ctx.Args().Slice()...), 95 rt.WithOutput(os.Stdout), 96 } 97 98 // create new local runtime 99 r := rt.DefaultRuntime 100 101 // start the runtime 102 r.Start() 103 104 // register the service 105 r.Create(&rt.Service{ 106 Name: name, 107 }, args...) 108 109 // stop the runtime 110 defer func() { 111 r.Delete(&rt.Service{ 112 Name: name, 113 }) 114 r.Stop() 115 }() 116 } 117 118 logger.Infof("Service [%s] Serving %s at endpoint %s\n", p.String(), name, endpoint) 119 120 // new service 121 srv := service.New(opts...) 122 123 // create new muxer 124 // muxer := mux.New(name, p) 125 126 // set the router 127 srv.Server().Init( 128 server.WithRouter(p), 129 ) 130 131 // run service 132 srv.Run() 133 } 134 135 type srvCommand struct { 136 Name string 137 Command ccli.ActionFunc 138 Flags []ccli.Flag 139 } 140 141 var srvCommands = []srvCommand{ 142 { 143 Name: "api", 144 Command: api.Run, 145 Flags: api.Flags, 146 }, 147 { 148 Name: "auth", 149 Command: auth.Run, 150 Flags: auth.Flags, 151 }, 152 { 153 Name: "broker", 154 Command: broker.Run, 155 }, 156 { 157 Name: "config", 158 Command: config.Run, 159 Flags: config.Flags, 160 }, 161 { 162 Name: "events", 163 Command: events.Run, 164 }, 165 { 166 Name: "network", 167 Command: network.Run, 168 Flags: network.Flags, 169 }, 170 { 171 Name: "proxy", 172 Command: proxy.Run, 173 Flags: proxy.Flags, 174 }, 175 { 176 Name: "registry", 177 Command: registry.Run, 178 }, 179 { 180 Name: "runtime", 181 Command: runtime.Run, 182 Flags: runtime.Flags, 183 }, 184 { 185 Name: "store", 186 Command: store.Run, 187 }, 188 } 189 190 func init() { 191 // move newAction outside the loop and pass c as an arg to 192 // set the scope of the variable 193 newAction := func(c srvCommand) func(ctx *ccli.Context) error { 194 return func(ctx *ccli.Context) error { 195 // configure the loggerger 196 logger.DefaultLogger.Init(logger.WithFields(map[string]interface{}{"service": c.Name})) 197 198 // run the service 199 c.Command(ctx) 200 return nil 201 } 202 } 203 204 subcommands := make([]*ccli.Command, len(srvCommands)) 205 for i, c := range srvCommands { 206 // construct the command 207 command := &ccli.Command{ 208 Name: c.Name, 209 Flags: c.Flags, 210 Usage: fmt.Sprintf("Run micro %v", c.Name), 211 Action: newAction(c), 212 } 213 214 // setup the plugins 215 for _, p := range plugin.Plugins(plugin.Module(c.Name)) { 216 if cmds := p.Commands(); len(cmds) > 0 { 217 command.Subcommands = append(command.Subcommands, cmds...) 218 } 219 220 if flags := p.Flags(); len(flags) > 0 { 221 command.Flags = append(command.Flags, flags...) 222 } 223 } 224 225 // set the command 226 subcommands[i] = command 227 } 228 229 command := &ccli.Command{ 230 Name: "service", 231 Usage: "Run a micro service", 232 Action: func(ctx *ccli.Context) error { 233 Run(ctx) 234 return nil 235 }, 236 Flags: []ccli.Flag{ 237 &ccli.StringFlag{ 238 Name: "name", 239 Usage: "Name of the service", 240 EnvVars: []string{"MICRO_SERVICE_NAME"}, 241 Value: "service", 242 }, 243 &ccli.StringFlag{ 244 Name: "address", 245 Usage: "Address of the service", 246 EnvVars: []string{"MICRO_SERVICE_ADDRESS"}, 247 }, 248 &ccli.StringFlag{ 249 Name: "endpoint", 250 Usage: "The local service endpoint (Defaults to localhost:9090); {http, grpc, file, exec}://path-or-address e.g http://localhost:9090", 251 EnvVars: []string{"MICRO_SERVICE_ENDPOINT"}, 252 }, 253 &ccli.StringSliceFlag{ 254 Name: "metadata", 255 Usage: "Add metadata as key-value pairs describing the service e.g owner=john@example.com", 256 EnvVars: []string{"MICRO_SERVICE_METADATA"}, 257 }, 258 }, 259 Subcommands: subcommands, 260 } 261 262 // register global plugins and flags 263 for _, p := range plugin.Plugins() { 264 if cmds := p.Commands(); len(cmds) > 0 { 265 command.Subcommands = append(command.Subcommands, cmds...) 266 } 267 268 if flags := p.Flags(); len(flags) > 0 { 269 command.Flags = append(command.Flags, flags...) 270 } 271 } 272 273 cmd.Register(command) 274 }