mirror of
https://github.com/go-micro/go-micro.git
synced 2025-05-31 21:59:42 +02:00
remove cli
This commit is contained in:
parent
efa2c4f2d2
commit
62c2981baf
33
cmd/micro/.gitignore
vendored
33
cmd/micro/.gitignore
vendored
@ -1,33 +0,0 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
_build
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
||||||
*.prof
|
|
||||||
|
|
||||||
# ignore go build and test outputs
|
|
||||||
coverage.txt
|
|
||||||
coverage.out
|
|
||||||
|
|
||||||
# ignore locally built binaries
|
|
||||||
dist
|
|
||||||
micro
|
|
@ -1,384 +0,0 @@
|
|||||||
# Micro CLI
|
|
||||||
|
|
||||||
Micro CLI is the command line interface for developing [Go Micro][1] projects.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
[Download][2] and install **Go**. Version `1.16` or higher is required.
|
|
||||||
|
|
||||||
Installation is done by using the [`go install`][3] command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install go-micro.dev/v4/cmd/micro@master
|
|
||||||
```
|
|
||||||
|
|
||||||
Let's create a new service using the `new` command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
micro new service helloworld
|
|
||||||
```
|
|
||||||
|
|
||||||
Follow the on-screen instructions. Next, we can run the program.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd helloworld
|
|
||||||
make proto tidy
|
|
||||||
micro run
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally we can call the service.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
micro call helloworld Helloworld.Call '{"name": "John"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
That's all you need to know to get started. Refer to the [Go Micro][1]
|
|
||||||
documentation for more info on developing services.
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
You will need protoc-gen-micro for code generation
|
|
||||||
|
|
||||||
* [protobuf][4]
|
|
||||||
* [protoc-gen-go][5]
|
|
||||||
* [protoc-gen-micro][6]
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download latest proto release
|
|
||||||
# https://github.com/protocolbuffers/protobuf/releases
|
|
||||||
go get -u google.golang.org/protobuf/proto
|
|
||||||
go install github.com/golang/protobuf/protoc-gen-go@latest
|
|
||||||
go install go-micro.dev/v4/cmd/protoc-gen-micro@v4
|
|
||||||
```
|
|
||||||
|
|
||||||
## Creating A Service
|
|
||||||
|
|
||||||
To create a new service, use the `micro new service` command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro new service helloworld
|
|
||||||
creating service helloworld
|
|
||||||
|
|
||||||
download protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:
|
|
||||||
|
|
||||||
visit https://github.com/protocolbuffers/protobuf/releases/latest
|
|
||||||
|
|
||||||
download protobuf for go-micro:
|
|
||||||
|
|
||||||
go get -u google.golang.org/protobuf/proto
|
|
||||||
go install github.com/golang/protobuf/protoc-gen-go@latest
|
|
||||||
go install go-micro.dev/cmd/protoc-gen-micro/v4@latest
|
|
||||||
|
|
||||||
compile the proto file helloworld.proto:
|
|
||||||
|
|
||||||
cd helloworld
|
|
||||||
make proto tidy
|
|
||||||
```
|
|
||||||
|
|
||||||
To create a new function, use the `micro new function` command. Functions differ
|
|
||||||
from services in that they exit after returning.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro new function helloworld
|
|
||||||
creating function helloworld
|
|
||||||
|
|
||||||
download protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:
|
|
||||||
|
|
||||||
visit https://github.com/protocolbuffers/protobuf/releases/latest
|
|
||||||
|
|
||||||
download protobuf for go-micro:
|
|
||||||
|
|
||||||
go get -u google.golang.org/protobuf/proto
|
|
||||||
go install github.com/golang/protobuf/protoc-gen-go@latest
|
|
||||||
go install go-micro.dev/cmd/protoc-gen-micro/v4@latest
|
|
||||||
|
|
||||||
compile the proto file helloworld.proto:
|
|
||||||
|
|
||||||
cd helloworld
|
|
||||||
make proto tidy
|
|
||||||
```
|
|
||||||
|
|
||||||
### Jaeger
|
|
||||||
|
|
||||||
To create a new service with [Jaeger][7] integration, pass the `--jaeger` flag
|
|
||||||
to the `micro new service` or `micro new function` commands. You may configure
|
|
||||||
the Jaeger client using [environment variables][8].
|
|
||||||
|
|
||||||
```bash
|
|
||||||
micro new service --jaeger helloworld
|
|
||||||
```
|
|
||||||
|
|
||||||
You may invoke `trace.NewSpan(context.Context).Finish()` to nest spans. For
|
|
||||||
example, consider the following handler implementing a greeter.
|
|
||||||
|
|
||||||
`handler/helloworld.go`
|
|
||||||
|
|
||||||
```go
|
|
||||||
package helloworld
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
log "go-micro.dev/v4/logger"
|
|
||||||
|
|
||||||
"helloworld/greeter"
|
|
||||||
pb "helloworld/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Helloworld struct{}
|
|
||||||
|
|
||||||
func (e *Helloworld) Call(ctx context.Context, req pb.CallRequest, rsp *pb.CallResponse) error {
|
|
||||||
log.Infof("Received Helloworld.Call request: %v", req)
|
|
||||||
rsp.Msg = greeter.Greet(ctx, req.Name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`greeter/greeter.go`
|
|
||||||
|
|
||||||
```go
|
|
||||||
package greeter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"go-micro.dev/v4/cmd/micro/debug/trace"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Greet(ctx context.Context, name string) string {
|
|
||||||
defer trace.NewSpan(ctx).Finish()
|
|
||||||
return fmt.Sprint("Hello " + name)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Skaffold
|
|
||||||
|
|
||||||
To create a new service with [Skaffold][9] files, pass the `--skaffold` flag to
|
|
||||||
the `micro new service` or `micro new function` commands.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
micro new service --skaffold helloworld
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running A Service
|
|
||||||
|
|
||||||
To run a service, use the `micro run` command to build and run your service
|
|
||||||
continuously.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro run
|
|
||||||
2021-08-20 14:05:54 file=v3@v3.5.2/service.go:199 level=info Starting [service] helloworld
|
|
||||||
2021-08-20 14:05:54 file=server/rpc_server.go:820 level=info Transport [http] Listening on [::]:34531
|
|
||||||
2021-08-20 14:05:54 file=server/rpc_server.go:840 level=info Broker [http] Connected to 127.0.0.1:44975
|
|
||||||
2021-08-20 14:05:54 file=server/rpc_server.go:654 level=info Registry [mdns] Registering node: helloworld-45f43a6f-5fc0-4b0d-af73-e4a10c36ef54
|
|
||||||
```
|
|
||||||
|
|
||||||
### With Docker
|
|
||||||
|
|
||||||
To run a service with Docker, build the Docker image and run the Docker
|
|
||||||
container.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ make docker
|
|
||||||
$ docker run helloworld:latest
|
|
||||||
2021-08-20 12:07:31 file=v3@v3.5.2/service.go:199 level=info Starting [service] helloworld
|
|
||||||
2021-08-20 12:07:31 file=server/rpc_server.go:820 level=info Transport [http] Listening on [::]:36037
|
|
||||||
2021-08-20 12:07:31 file=server/rpc_server.go:840 level=info Broker [http] Connected to 127.0.0.1:46157
|
|
||||||
2021-08-20 12:07:31 file=server/rpc_server.go:654 level=info Registry [mdns] Registering node: helloworld-31f58714-72f5-4d12-b2eb-98f66aea7a34
|
|
||||||
```
|
|
||||||
|
|
||||||
### With Skaffold
|
|
||||||
|
|
||||||
When you've created your service using the `--skaffold` flag, you may run the
|
|
||||||
Skaffold pipeline using the `skaffold` command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
skaffold dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Creating A Client
|
|
||||||
|
|
||||||
To create a new client, use the `micro new client` command. The name is the
|
|
||||||
service you'd like to create a client project for.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro new client helloworld
|
|
||||||
creating client helloworld
|
|
||||||
cd helloworld-client
|
|
||||||
make tidy
|
|
||||||
```
|
|
||||||
|
|
||||||
You may optionally pass the fully qualified package name of the service you'd
|
|
||||||
like to create a client project for.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro new client github.com/auditemarlow/helloworld
|
|
||||||
creating client helloworld
|
|
||||||
cd helloworld-client
|
|
||||||
make tidy
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running A Client
|
|
||||||
|
|
||||||
To run a client, use the `micro run` command to build and run your client
|
|
||||||
continuously.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro run
|
|
||||||
2021-09-03 12:52:23 file=helloworld-client/main.go:33 level=info msg:"Hello John"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Generating Files
|
|
||||||
|
|
||||||
To generate Go Micro project template files after the fact, use the `micro
|
|
||||||
generate` command. It will place the generated files in the current working
|
|
||||||
directory.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro generate skaffold
|
|
||||||
skaffold project template files generated
|
|
||||||
```
|
|
||||||
|
|
||||||
## Listing Services
|
|
||||||
|
|
||||||
To list services, use the `micro services` command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro services
|
|
||||||
helloworld
|
|
||||||
```
|
|
||||||
|
|
||||||
## Describing A Service
|
|
||||||
|
|
||||||
To describe a service, use the `micro describe service` command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro describe service helloworld
|
|
||||||
{
|
|
||||||
"name": "helloworld",
|
|
||||||
"version": "latest",
|
|
||||||
"metadata": null,
|
|
||||||
"endpoints": [
|
|
||||||
{
|
|
||||||
"name": "Helloworld.Call",
|
|
||||||
"request": {
|
|
||||||
"name": "CallRequest",
|
|
||||||
"type": "CallRequest",
|
|
||||||
"values": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"type": "string",
|
|
||||||
"values": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"response": {
|
|
||||||
"name": "CallResponse",
|
|
||||||
"type": "CallResponse",
|
|
||||||
"values": [
|
|
||||||
{
|
|
||||||
"name": "msg",
|
|
||||||
"type": "string",
|
|
||||||
"values": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": "helloworld-9660f06a-d608-43d9-9f44-e264ff63c554",
|
|
||||||
"address": "172.26.165.161:45059",
|
|
||||||
"metadata": {
|
|
||||||
"broker": "http",
|
|
||||||
"protocol": "mucp",
|
|
||||||
"registry": "mdns",
|
|
||||||
"server": "mucp",
|
|
||||||
"transport": "http"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You may pass the `--format=yaml` flag to output a YAML formatted object.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro describe service --format=yaml helloworld
|
|
||||||
name: helloworld
|
|
||||||
version: latest
|
|
||||||
metadata: {}
|
|
||||||
endpoints:
|
|
||||||
- name: Helloworld.Call
|
|
||||||
request:
|
|
||||||
name: CallRequest
|
|
||||||
type: CallRequest
|
|
||||||
values:
|
|
||||||
- name: name
|
|
||||||
type: string
|
|
||||||
values: []
|
|
||||||
response:
|
|
||||||
name: CallResponse
|
|
||||||
type: CallResponse
|
|
||||||
values:
|
|
||||||
- name: msg
|
|
||||||
type: string
|
|
||||||
values: []
|
|
||||||
nodes:
|
|
||||||
- id: helloworld-9660f06a-d608-43d9-9f44-e264ff63c554
|
|
||||||
address: 172.26.165.161:45059
|
|
||||||
metadata:
|
|
||||||
broker: http
|
|
||||||
protocol: mucp
|
|
||||||
registry: mdns
|
|
||||||
server: mucp
|
|
||||||
transport: http
|
|
||||||
```
|
|
||||||
|
|
||||||
## Calling A Service
|
|
||||||
|
|
||||||
To call a service, use the `micro call` command. This will send a single request
|
|
||||||
and expect a single response.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro call helloworld Helloworld.Call '{"name": "John"}'
|
|
||||||
{"msg":"Hello John"}
|
|
||||||
```
|
|
||||||
|
|
||||||
To call a service's server stream, use the `micro stream server` command. This
|
|
||||||
will send a single request and expect a stream of responses.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro stream server helloworld Helloworld.ServerStream '{"count": 10}'
|
|
||||||
{"count":0}
|
|
||||||
{"count":1}
|
|
||||||
{"count":2}
|
|
||||||
{"count":3}
|
|
||||||
{"count":4}
|
|
||||||
{"count":5}
|
|
||||||
{"count":6}
|
|
||||||
{"count":7}
|
|
||||||
{"count":8}
|
|
||||||
{"count":9}
|
|
||||||
```
|
|
||||||
|
|
||||||
To call a service's bidirectional stream, use the `micro stream bidi` command.
|
|
||||||
This will send a stream of requests and expect a stream of responses.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ micro stream bidi helloworld Helloworld.BidiStream '{"stroke": 1}' '{"stroke": 2}' '{"stroke": 3}'
|
|
||||||
{"stroke":1}
|
|
||||||
{"stroke":2}
|
|
||||||
{"stroke":3}
|
|
||||||
```
|
|
||||||
|
|
||||||
[1]: https://go-micro.dev
|
|
||||||
[2]: https://golang.org/dl/
|
|
||||||
[3]: https://golang.org/cmd/go/#hdr-Compile_and_install_packages_and_dependencies
|
|
||||||
[4]: https://grpc.io/docs/protoc-installation/
|
|
||||||
[5]: https://micro.mu/github.com/golang/protobuf/protoc-gen-go
|
|
||||||
[6]: https://go-micro.dev/tree/master/cmd/protoc-gen-micro
|
|
||||||
[7]: https://www.jaegertracing.io/
|
|
||||||
[8]: https://github.com/jaegertracing/jaeger-client-go#environment-variables
|
|
||||||
[9]: https://skaffold.dev/
|
|
@ -1,63 +0,0 @@
|
|||||||
package call
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
"go-micro.dev/v4"
|
|
||||||
"go-micro.dev/v4/client"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "call",
|
|
||||||
Usage: "Call a service, e.g. " + mcli.App().Name + " call helloworld Helloworld.Call '{\"name\": \"John\"}'",
|
|
||||||
Action: RunCall,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunCall calls a service endpoint and prints its response. Exits on error.
|
|
||||||
func RunCall(ctx *cli.Context) error {
|
|
||||||
args := ctx.Args().Slice()
|
|
||||||
if len(args) < 2 {
|
|
||||||
return cli.ShowSubcommandHelp(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
service := args[0]
|
|
||||||
endpoint := args[1]
|
|
||||||
req := strings.Join(args[2:], " ")
|
|
||||||
if len(req) == 0 {
|
|
||||||
req = `{}`
|
|
||||||
}
|
|
||||||
|
|
||||||
d := json.NewDecoder(strings.NewReader(req))
|
|
||||||
d.UseNumber()
|
|
||||||
|
|
||||||
var creq map[string]interface{}
|
|
||||||
if err := d.Decode(&creq); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := micro.NewService()
|
|
||||||
srv.Init()
|
|
||||||
c := srv.Client()
|
|
||||||
|
|
||||||
request := c.NewRequest(service, endpoint, creq, client.WithContentType("application/json"))
|
|
||||||
var response map[string]interface{}
|
|
||||||
|
|
||||||
if err := c.Call(context.Background(), request, &response); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := json.Marshal(response)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(b))
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcmd "go-micro.dev/v4/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultCLI is the default, unmodified root command.
|
|
||||||
DefaultCLI CLI = NewCLI()
|
|
||||||
|
|
||||||
name string = "micro"
|
|
||||||
description string = "The Go Micro CLI tool"
|
|
||||||
version string = "latest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CLI is the interface that wraps the cli app.
|
|
||||||
//
|
|
||||||
// CLI embeds the Cmd interface from the go-micro.dev/v4/cmd
|
|
||||||
// package and adds a Run method.
|
|
||||||
//
|
|
||||||
// Run runs the cli app within this command and exits on error.
|
|
||||||
type CLI interface {
|
|
||||||
mcmd.Cmd
|
|
||||||
Run() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type cmd struct {
|
|
||||||
app *cli.App
|
|
||||||
opts mcmd.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
// App returns the cli app within this command.
|
|
||||||
func (c *cmd) App() *cli.App {
|
|
||||||
return c.app
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options returns the options set within this command.
|
|
||||||
func (c *cmd) Options() mcmd.Options {
|
|
||||||
return c.opts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init adds options, parses flags and exits on error.
|
|
||||||
func (c *cmd) Init(opts ...mcmd.Option) error {
|
|
||||||
return mcmd.Init(opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run runs the cli app within this command and exits on error.
|
|
||||||
func (c *cmd) Run() error {
|
|
||||||
return c.app.Run(os.Args)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultOptions returns the options passed to the default command.
|
|
||||||
func DefaultOptions() mcmd.Options {
|
|
||||||
return DefaultCLI.Options()
|
|
||||||
}
|
|
||||||
|
|
||||||
// App returns the cli app within the default command.
|
|
||||||
func App() *cli.App {
|
|
||||||
return DefaultCLI.App()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register appends commands to the default app.
|
|
||||||
func Register(cmds ...*cli.Command) {
|
|
||||||
app := DefaultCLI.App()
|
|
||||||
app.Commands = append(app.Commands, cmds...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run runs the cli app within the default command. On error, it prints the
|
|
||||||
// error message and exits.
|
|
||||||
func Run() {
|
|
||||||
if err := DefaultCLI.Run(); err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCLI returns a new command.
|
|
||||||
func NewCLI(opts ...mcmd.Option) CLI {
|
|
||||||
options := mcmd.DefaultOptions()
|
|
||||||
|
|
||||||
// Clear the name, version and description parameters from the default
|
|
||||||
// options so the options passed may override them.
|
|
||||||
options.Name = ""
|
|
||||||
options.Version = ""
|
|
||||||
options.Description = ""
|
|
||||||
|
|
||||||
for _, o := range opts {
|
|
||||||
o(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(options.Name) == 0 {
|
|
||||||
options.Name = name
|
|
||||||
}
|
|
||||||
if len(options.Description) == 0 {
|
|
||||||
options.Description = description
|
|
||||||
}
|
|
||||||
if len(options.Version) == 0 {
|
|
||||||
options.Version = version
|
|
||||||
}
|
|
||||||
|
|
||||||
c := new(cmd)
|
|
||||||
c.opts = options
|
|
||||||
c.app = cli.NewApp()
|
|
||||||
c.app.Name = c.opts.Name
|
|
||||||
c.app.Usage = c.opts.Description
|
|
||||||
c.app.Version = c.opts.Version
|
|
||||||
c.app.Flags = mcmd.DefaultFlags
|
|
||||||
|
|
||||||
if len(options.Version) == 0 {
|
|
||||||
c.app.HideVersion = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package describe
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var flags []cli.Flag = []cli.Flag{
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Value: "json",
|
|
||||||
Usage: "output a formatted description, e.g. json or yaml",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "describe",
|
|
||||||
Usage: "Describe a resource",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "service",
|
|
||||||
Aliases: []string{"s"},
|
|
||||||
Usage: "Describe a service resource, e.g. " + mcli.App().Name + " describe service helloworld",
|
|
||||||
Action: Service,
|
|
||||||
Flags: flags,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package describe
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Service fetches information for a service from the registry and prints it in
|
|
||||||
// either JSON or YAML, depending on the format flag passed. Exits on error.
|
|
||||||
func Service(ctx *cli.Context) error {
|
|
||||||
args := ctx.Args().Slice()
|
|
||||||
if len(args) < 1 {
|
|
||||||
return cli.ShowSubcommandHelp(ctx)
|
|
||||||
}
|
|
||||||
if ctx.String("format") != "json" && ctx.String("format") != "yaml" {
|
|
||||||
return cli.ShowSubcommandHelp(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := *mcli.DefaultOptions().Registry
|
|
||||||
srvs, err := r.GetService(args[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(srvs) == 0 {
|
|
||||||
return fmt.Errorf("service %s not found", args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, srv := range srvs {
|
|
||||||
var b []byte
|
|
||||||
var err error
|
|
||||||
if ctx.String("format") == "json" {
|
|
||||||
b, err = json.MarshalIndent(srv, "", " ")
|
|
||||||
} else if ctx.String("format") == "yaml" {
|
|
||||||
b, err = yaml.Marshal(srv)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,142 +0,0 @@
|
|||||||
package generate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
"go-micro.dev/v4/cmd/micro/generator"
|
|
||||||
tmpl "go-micro.dev/v4/cmd/micro/generator/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "generate",
|
|
||||||
Usage: "Generate project template files after the fact",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "kubernetes",
|
|
||||||
Usage: "Generate Kubernetes resource template files",
|
|
||||||
Action: Kubernetes,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "skaffold",
|
|
||||||
Usage: "Generate Skaffold template files",
|
|
||||||
Action: Skaffold,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kubernetes generates Kubernetes resource template files in the current
|
|
||||||
// working directory. Exits on error.
|
|
||||||
func Kubernetes(ctx *cli.Context) error {
|
|
||||||
service, err := getService()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vendor, err := getServiceVendor(service)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
g := generator.New(
|
|
||||||
generator.Service(service),
|
|
||||||
generator.Vendor(vendor),
|
|
||||||
generator.Directory("."),
|
|
||||||
generator.Client(strings.HasSuffix(service, "-client")),
|
|
||||||
)
|
|
||||||
|
|
||||||
files := []generator.File{
|
|
||||||
{"plugins.go", tmpl.Plugins},
|
|
||||||
{"resources/clusterrole.yaml", tmpl.KubernetesClusterRole},
|
|
||||||
{"resources/configmap.yaml", tmpl.KubernetesEnv},
|
|
||||||
{"resources/deployment.yaml", tmpl.KubernetesDeployment},
|
|
||||||
{"resources/rolebinding.yaml", tmpl.KubernetesRoleBinding},
|
|
||||||
}
|
|
||||||
|
|
||||||
g.Generate(files)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skaffold generates Skaffold template files in the current working directory.
|
|
||||||
// Exits on error.
|
|
||||||
func Skaffold(ctx *cli.Context) error {
|
|
||||||
service, err := getService()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vendor, err := getServiceVendor(service)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
g := generator.New(
|
|
||||||
generator.Service(service),
|
|
||||||
generator.Vendor(vendor),
|
|
||||||
generator.Directory("."),
|
|
||||||
generator.Client(strings.HasSuffix(service, "-client")),
|
|
||||||
generator.Skaffold(true),
|
|
||||||
)
|
|
||||||
|
|
||||||
files := []generator.File{
|
|
||||||
{".dockerignore", tmpl.DockerIgnore},
|
|
||||||
{"go.mod", tmpl.Module},
|
|
||||||
{"plugins.go", tmpl.Plugins},
|
|
||||||
{"resources/clusterrole.yaml", tmpl.KubernetesClusterRole},
|
|
||||||
{"resources/configmap.yaml", tmpl.KubernetesEnv},
|
|
||||||
{"resources/deployment.yaml", tmpl.KubernetesDeployment},
|
|
||||||
{"resources/rolebinding.yaml", tmpl.KubernetesRoleBinding},
|
|
||||||
{"skaffold.yaml", tmpl.SkaffoldCFG},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.Generate(files); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("skaffold project template files generated")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getService() (string, error) {
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return dir[strings.LastIndex(dir, "/")+1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceVendor(s string) (string, error) {
|
|
||||||
f, err := os.Open("go.mod")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
line := ""
|
|
||||||
scanner := bufio.NewScanner(f)
|
|
||||||
for scanner.Scan() {
|
|
||||||
if strings.HasPrefix(scanner.Text(), "module ") {
|
|
||||||
line = scanner.Text()
|
|
||||||
break
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if line == "" {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
module := line[strings.LastIndex(line, " ")+1:]
|
|
||||||
if module == s {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return module[:strings.LastIndex(module, "/")] + "/", nil
|
|
||||||
}
|
|
@ -1,204 +0,0 @@
|
|||||||
package new
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
"go-micro.dev/v4/cmd/micro/generator"
|
|
||||||
tmpl "go-micro.dev/v4/cmd/micro/generator/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
var flags []cli.Flag = []cli.Flag{
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "jaeger",
|
|
||||||
Usage: "Generate Jaeger tracer files",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "kubernetes",
|
|
||||||
Usage: "Generate Kubernetes resource files",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skaffold",
|
|
||||||
Usage: "Generate Skaffold files",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCommand returns a new new cli command.
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "new",
|
|
||||||
Usage: "Create a project template",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "client",
|
|
||||||
Usage: "Create a client template, e.g. " + mcli.App().Name + " new client [github.com/auditemarlow/]helloworld",
|
|
||||||
Action: Client,
|
|
||||||
Flags: flags,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "function",
|
|
||||||
Usage: "Create a function template, e.g. " + mcli.App().Name + " new function [github.com/auditemarlow/]helloworld",
|
|
||||||
Action: Function,
|
|
||||||
Flags: flags,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "service",
|
|
||||||
Usage: "Create a service template, e.g. " + mcli.App().Name + " new service [github.com/auditemarlow/]helloworld",
|
|
||||||
Action: Service,
|
|
||||||
Flags: flags,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Client(ctx *cli.Context) error {
|
|
||||||
return createProject(ctx, "client")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function creates a new function project template. Exits on error.
|
|
||||||
func Function(ctx *cli.Context) error {
|
|
||||||
return createProject(ctx, "function")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service creates a new service project template. Exits on error.
|
|
||||||
func Service(ctx *cli.Context) error {
|
|
||||||
return createProject(ctx, "service")
|
|
||||||
}
|
|
||||||
|
|
||||||
func createProject(ctx *cli.Context, pt string) error {
|
|
||||||
arg := ctx.Args().First()
|
|
||||||
if len(arg) == 0 {
|
|
||||||
return cli.ShowSubcommandHelp(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := pt == "client"
|
|
||||||
name, vendor := getNameAndVendor(arg)
|
|
||||||
|
|
||||||
dir := name
|
|
||||||
if client {
|
|
||||||
dir += "-client"
|
|
||||||
}
|
|
||||||
|
|
||||||
if path.IsAbs(dir) {
|
|
||||||
fmt.Println("must provide a relative path as service name")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(dir); !os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("%s already exists", dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("creating %s %s\n", pt, name)
|
|
||||||
|
|
||||||
g := generator.New(
|
|
||||||
generator.Service(name),
|
|
||||||
generator.Vendor(vendor),
|
|
||||||
generator.Directory(dir),
|
|
||||||
generator.Client(client),
|
|
||||||
generator.Jaeger(ctx.Bool("jaeger")),
|
|
||||||
generator.Skaffold(ctx.Bool("skaffold")),
|
|
||||||
)
|
|
||||||
|
|
||||||
files := []generator.File{
|
|
||||||
{".dockerignore", tmpl.DockerIgnore},
|
|
||||||
{".gitignore", tmpl.GitIgnore},
|
|
||||||
{"Dockerfile", tmpl.Dockerfile},
|
|
||||||
{"Makefile", tmpl.Makefile},
|
|
||||||
{"go.mod", tmpl.Module},
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pt {
|
|
||||||
case "client":
|
|
||||||
files = append(files, []generator.File{
|
|
||||||
{"main.go", tmpl.MainCLT},
|
|
||||||
}...)
|
|
||||||
case "function":
|
|
||||||
files = append(files, []generator.File{
|
|
||||||
{"handler/" + name + ".go", tmpl.HandlerFNC},
|
|
||||||
{"main.go", tmpl.MainFNC},
|
|
||||||
{"proto/" + name + ".proto", tmpl.ProtoFNC},
|
|
||||||
}...)
|
|
||||||
case "service":
|
|
||||||
files = append(files, []generator.File{
|
|
||||||
{"handler/" + name + ".go", tmpl.HandlerSRV},
|
|
||||||
{"main.go", tmpl.MainSRV},
|
|
||||||
{"proto/" + name + ".proto", tmpl.ProtoSRV},
|
|
||||||
}...)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("%s project type not supported", pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Bool("kubernetes") || ctx.Bool("skaffold") {
|
|
||||||
files = append(files, []generator.File{
|
|
||||||
{"plugins.go", tmpl.Plugins},
|
|
||||||
{"resources/clusterrole.yaml", tmpl.KubernetesClusterRole},
|
|
||||||
{"resources/configmap.yaml", tmpl.KubernetesEnv},
|
|
||||||
{"resources/deployment.yaml", tmpl.KubernetesDeployment},
|
|
||||||
{"resources/rolebinding.yaml", tmpl.KubernetesRoleBinding},
|
|
||||||
}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Bool("skaffold") {
|
|
||||||
files = append(files, []generator.File{
|
|
||||||
{"skaffold.yaml", tmpl.SkaffoldCFG},
|
|
||||||
}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.Generate(files); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var comments []string
|
|
||||||
if client {
|
|
||||||
comments = clientComments(name, dir)
|
|
||||||
} else {
|
|
||||||
comments = protoComments(name, dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, comment := range comments {
|
|
||||||
fmt.Println(comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func clientComments(name, dir string) []string {
|
|
||||||
return []string{
|
|
||||||
"\ninstall dependencies:",
|
|
||||||
"\ncd " + dir,
|
|
||||||
"make update tidy",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func protoComments(name, dir string) []string {
|
|
||||||
return []string{
|
|
||||||
"\ndownload protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:",
|
|
||||||
"\nvisit https://github.com/protocolbuffers/protobuf/releases/latest",
|
|
||||||
"\ndownload protobuf for go-micro:",
|
|
||||||
"\ngo get -u google.golang.org/protobuf/proto",
|
|
||||||
"go install github.com/golang/protobuf/protoc-gen-go@latest",
|
|
||||||
"go install go-micro.dev/v4/cmd/protoc-gen-micro@v4",
|
|
||||||
"\ncompile the proto file " + name + ".proto and install dependencies:",
|
|
||||||
"\ncd " + dir,
|
|
||||||
"make proto update tidy",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNameAndVendor(s string) (string, string) {
|
|
||||||
var n string
|
|
||||||
var v string
|
|
||||||
|
|
||||||
if i := strings.LastIndex(s, "/"); i == -1 {
|
|
||||||
n = s
|
|
||||||
v = ""
|
|
||||||
} else {
|
|
||||||
n = s[i+1:]
|
|
||||||
v = s[:i+1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return n, v
|
|
||||||
}
|
|
@ -1,158 +0,0 @@
|
|||||||
package run
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
"go-micro.dev/v4/runtime"
|
|
||||||
"go-micro.dev/v4/runtime/local/git"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultRetries = 3
|
|
||||||
|
|
||||||
flags []cli.Flag = []cli.Flag{
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "command",
|
|
||||||
Usage: "command to execute",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "args",
|
|
||||||
Usage: "command arguments",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "type",
|
|
||||||
Usage: "the type of service to operate on",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "run",
|
|
||||||
Usage: "Build and run a service continuously, e.g. " + mcli.App().Name + " run [github.com/auditemarlow/helloworld]",
|
|
||||||
Flags: flags,
|
|
||||||
Action: Run,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run runs a service and watches the project directory for change events. On
|
|
||||||
// write, the service is restarted. Exits on error.
|
|
||||||
func Run(ctx *cli.Context) error {
|
|
||||||
wd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
source, err := git.ParseSourceLocal(wd, ctx.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := &runtime.Service{
|
|
||||||
Name: source.RuntimeName(),
|
|
||||||
Source: source.RuntimeSource(),
|
|
||||||
Version: source.Ref,
|
|
||||||
Metadata: make(map[string]string),
|
|
||||||
}
|
|
||||||
|
|
||||||
typ := ctx.String("type")
|
|
||||||
command := strings.TrimSpace(ctx.String("command"))
|
|
||||||
args := strings.TrimSpace(ctx.String("args"))
|
|
||||||
|
|
||||||
r := *mcli.DefaultCLI.Options().Runtime
|
|
||||||
|
|
||||||
var retries = DefaultRetries
|
|
||||||
if ctx.IsSet("retries") {
|
|
||||||
retries = ctx.Int("retries")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := []runtime.CreateOption{
|
|
||||||
runtime.WithOutput(os.Stdout),
|
|
||||||
runtime.WithRetries(retries),
|
|
||||||
runtime.CreateType(typ),
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(command) > 0 {
|
|
||||||
opts = append(opts, runtime.WithCommand(command))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
|
||||||
opts = append(opts, runtime.WithArgs(args))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := r.Create(svc, opts...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
done := make(chan bool)
|
|
||||||
if r.String() == "local" {
|
|
||||||
sig := make(chan os.Signal)
|
|
||||||
signal.Notify(sig, os.Interrupt)
|
|
||||||
go func() {
|
|
||||||
<-sig
|
|
||||||
r.Delete(svc)
|
|
||||||
done <- true
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if source.Local {
|
|
||||||
watcher, err := fsnotify.NewWatcher()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
defer watcher.Close()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case event, ok := <-watcher.Events:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
|
||||||
r.Update(svc)
|
|
||||||
}
|
|
||||||
if event.Op&fsnotify.Create == fsnotify.Create {
|
|
||||||
watcher.Add(event.Name)
|
|
||||||
}
|
|
||||||
if event.Op&fsnotify.Remove == fsnotify.Remove {
|
|
||||||
watcher.Remove(event.Name)
|
|
||||||
}
|
|
||||||
case err, ok := <-watcher.Errors:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println("ERROR", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var files []string
|
|
||||||
filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
files = append(files, path)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
if err := watcher.Add(file); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.String() == "local" {
|
|
||||||
<-done
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "services",
|
|
||||||
Usage: "List services in the registry",
|
|
||||||
Action: List,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// List fetches running services from the registry and lists them. Exits on
|
|
||||||
// error.
|
|
||||||
func List(ctx *cli.Context) error {
|
|
||||||
r := *mcli.DefaultOptions().Registry
|
|
||||||
srvs, err := r.ListServices()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var services []string
|
|
||||||
for _, srv := range srvs {
|
|
||||||
services = append(services, srv.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(services)
|
|
||||||
for _, srv := range services {
|
|
||||||
fmt.Println(srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package stream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
"go-micro.dev/v4"
|
|
||||||
"go-micro.dev/v4/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bidirectional streams client requests and prints the server stream responses
|
|
||||||
// it receives. Exits on error.
|
|
||||||
func Bidirectional(ctx *cli.Context) error {
|
|
||||||
args := ctx.Args().Slice()
|
|
||||||
if len(args) < 2 {
|
|
||||||
return cli.ShowSubcommandHelp(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
service := args[0]
|
|
||||||
endpoint := args[1]
|
|
||||||
requests := args[2:]
|
|
||||||
|
|
||||||
srv := micro.NewService()
|
|
||||||
srv.Init()
|
|
||||||
c := srv.Client()
|
|
||||||
|
|
||||||
var r interface{}
|
|
||||||
request := c.NewRequest(service, endpoint, r, client.WithContentType("application/json"))
|
|
||||||
var rsp map[string]interface{}
|
|
||||||
stream, err := c.Stream(ctx.Context, request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, req := range requests {
|
|
||||||
d := json.NewDecoder(strings.NewReader(req))
|
|
||||||
d.UseNumber()
|
|
||||||
|
|
||||||
var creq map[string]interface{}
|
|
||||||
if err := d.Decode(&creq); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := stream.Send(creq); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err := stream.Recv(&rsp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := json.Marshal(rsp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
|
||||||
if stream.Error() != nil {
|
|
||||||
return stream.Error()
|
|
||||||
}
|
|
||||||
if err := stream.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package stream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
"go-micro.dev/v4"
|
|
||||||
"go-micro.dev/v4/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Server sends a single client request and prints the server stream responses
|
|
||||||
// it receives. Exits on error.
|
|
||||||
func Server(ctx *cli.Context) error {
|
|
||||||
args := ctx.Args().Slice()
|
|
||||||
if len(args) < 2 {
|
|
||||||
return cli.ShowSubcommandHelp(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
service := args[0]
|
|
||||||
endpoint := args[1]
|
|
||||||
req := strings.Join(args[2:], " ")
|
|
||||||
if len(req) == 0 {
|
|
||||||
req = `{}`
|
|
||||||
}
|
|
||||||
|
|
||||||
d := json.NewDecoder(strings.NewReader(req))
|
|
||||||
d.UseNumber()
|
|
||||||
|
|
||||||
var creq map[string]interface{}
|
|
||||||
if err := d.Decode(&creq); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := micro.NewService()
|
|
||||||
srv.Init()
|
|
||||||
c := srv.Client()
|
|
||||||
|
|
||||||
var r interface{}
|
|
||||||
request := c.NewRequest(service, endpoint, r, client.WithContentType("application/json"))
|
|
||||||
|
|
||||||
stream, err := c.Stream(context.Background(), request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := stream.Send(creq); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for stream.Error() == nil {
|
|
||||||
rsp := &map[string]interface{}{}
|
|
||||||
err := stream.Recv(rsp)
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b, err := json.Marshal(rsp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
|
||||||
if stream.Error() != nil {
|
|
||||||
return stream.Error()
|
|
||||||
}
|
|
||||||
if err := stream.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package stream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
mcli "go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mcli.Register(&cli.Command{
|
|
||||||
Name: "stream",
|
|
||||||
Usage: "Create a service stream",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "bidi",
|
|
||||||
Aliases: []string{"b"},
|
|
||||||
Usage: "Create a bidirectional service stream, e.g. " + mcli.App().Name + " stream bidirectional helloworld Helloworld.PingPong '{\"stroke\": 1}' '{\"stroke\": 2}'",
|
|
||||||
Action: Bidirectional,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "server",
|
|
||||||
Aliases: []string{"s"},
|
|
||||||
Usage: "Create a server service stream, e.g. " + mcli.App().Name + " stream server helloworld Helloworld.ServerStream '{\"count\": 10}'",
|
|
||||||
Action: Server,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package jaeger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
jaegercfg "github.com/uber/jaeger-client-go/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewTracer returns a new Jaeger tracer based on the current configuration,
|
|
||||||
// using the given options, and a closer func that can be used to flush buffers
|
|
||||||
// before shutdown.
|
|
||||||
func NewTracer(opts ...Option) (opentracing.Tracer, io.Closer, error) {
|
|
||||||
options := newOptions(opts...)
|
|
||||||
|
|
||||||
cfg := &jaegercfg.Configuration{}
|
|
||||||
if options.FromEnv {
|
|
||||||
c, err := jaegercfg.FromEnv()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
cfg = c
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Name != "" {
|
|
||||||
cfg.ServiceName = options.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
var jOptions []jaegercfg.Option
|
|
||||||
if options.Logger != nil {
|
|
||||||
jOptions = append(jOptions, jaegercfg.Logger(options.Logger))
|
|
||||||
}
|
|
||||||
if options.Metrics != nil {
|
|
||||||
jOptions = append(jOptions, jaegercfg.Metrics(options.Metrics))
|
|
||||||
}
|
|
||||||
|
|
||||||
tracer, closer, err := cfg.NewTracer(jOptions...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.GlobalTracer {
|
|
||||||
opentracing.SetGlobalTracer(tracer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tracer, closer, nil
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package jaeger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/uber/jaeger-client-go"
|
|
||||||
"github.com/uber/jaeger-lib/metrics"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultLogger is the default Jaeger logger.
|
|
||||||
DefaultLogger = jaeger.StdLogger
|
|
||||||
|
|
||||||
// DefaultMetrics is the default Jaeger metrics factory.
|
|
||||||
DefaultMetrics = metrics.NullFactory
|
|
||||||
)
|
|
||||||
|
|
||||||
// Options represents the options passed to the Jaeger tracer.
|
|
||||||
type Options struct {
|
|
||||||
Name string
|
|
||||||
FromEnv bool
|
|
||||||
GlobalTracer bool
|
|
||||||
Logger jaeger.Logger
|
|
||||||
Metrics metrics.Factory
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option manipulates the passed Options struct.
|
|
||||||
type Option func(o *Options)
|
|
||||||
|
|
||||||
func newOptions(opts ...Option) Options {
|
|
||||||
options := Options{
|
|
||||||
Logger: DefaultLogger,
|
|
||||||
Metrics: DefaultMetrics,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, o := range opts {
|
|
||||||
o(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name sets the service name for the Jaeger tracer.
|
|
||||||
func Name(s string) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Name = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromEnv determines whether the Jaeger tracer configuration should use
|
|
||||||
// environment variables.
|
|
||||||
func FromEnv(e bool) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.FromEnv = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalTracer determines whether the Jaeger tracer should be set as the
|
|
||||||
// global tracer.
|
|
||||||
func GlobalTracer(e bool) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.GlobalTracer = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logger sets the logger for the Jaeger tracer.
|
|
||||||
func Logger(l jaeger.Logger) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Logger = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metrics sets the metrics factory for the Jaeger tracer.
|
|
||||||
func Metrics(m metrics.Factory) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Metrics = m
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package trace
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewSpan accepts a context and returns an OpenTracing span. Can be used to
|
|
||||||
// nest spans.
|
|
||||||
func NewSpan(ctx context.Context) opentracing.Span {
|
|
||||||
pc := make([]uintptr, 10) // at least 1 entry needed
|
|
||||||
runtime.Callers(2, pc)
|
|
||||||
span := opentracing.StartSpan(
|
|
||||||
runtime.FuncForPC(pc[0]).Name(),
|
|
||||||
opentracing.ChildOf(opentracing.SpanFromContext(ctx).Context()),
|
|
||||||
)
|
|
||||||
return span
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Generator is the interface that generates project template files.
|
|
||||||
//
|
|
||||||
// Generate accepts a list of files and generates them based on their template.
|
|
||||||
type Generator interface {
|
|
||||||
Generate([]File) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type generator struct {
|
|
||||||
opts Options
|
|
||||||
}
|
|
||||||
|
|
||||||
// File represents a file to generate.
|
|
||||||
type File struct {
|
|
||||||
// Path specifies where the file will reside.
|
|
||||||
Path string
|
|
||||||
// Template is the template used to generate the file.
|
|
||||||
Template string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate generates project template files.
|
|
||||||
func (g *generator) Generate(files []File) error {
|
|
||||||
for _, file := range files {
|
|
||||||
fp := filepath.Join(g.opts.Directory, file.Path)
|
|
||||||
dir := filepath.Dir(fp)
|
|
||||||
|
|
||||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create(fp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fn := template.FuncMap{
|
|
||||||
"dehyphen": func(s string) string {
|
|
||||||
return strings.ReplaceAll(s, "-", "")
|
|
||||||
},
|
|
||||||
"lower": strings.ToLower,
|
|
||||||
"title": func(s string) string {
|
|
||||||
return strings.ReplaceAll(strings.Title(s), "-", "")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
t, err := template.New(fp).Funcs(fn).Parse(file.Template)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = t.Execute(f, g.opts)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new generator struct.
|
|
||||||
func New(opts ...Option) Generator {
|
|
||||||
var options Options
|
|
||||||
for _, o := range opts {
|
|
||||||
o(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &generator{
|
|
||||||
opts: options,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
package generator
|
|
||||||
|
|
||||||
// Options represents the options for the generator.
|
|
||||||
type Options struct {
|
|
||||||
// Service is the name of the service the generator will generate files
|
|
||||||
// for.
|
|
||||||
Service string
|
|
||||||
// Vendor is the service vendor.
|
|
||||||
Vendor string
|
|
||||||
// Directory is the directory where the files will be generated to.
|
|
||||||
Directory string
|
|
||||||
|
|
||||||
// Client determines whether or not the project is a client project.
|
|
||||||
Client bool
|
|
||||||
// Jaeger determines whether or not Jaeger integration is enabled.
|
|
||||||
Jaeger bool
|
|
||||||
// Jaeger determines whether or not Skaffold integration is enabled.
|
|
||||||
Skaffold bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option manipulates the Options passed.
|
|
||||||
type Option func(o *Options)
|
|
||||||
|
|
||||||
// Service sets the service name.
|
|
||||||
func Service(s string) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Service = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vendor sets the service vendor.
|
|
||||||
func Vendor(v string) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Vendor = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Directory sets the directory in which files are generated.
|
|
||||||
func Directory(d string) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Directory = d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client sets whether or not the project is a client project.
|
|
||||||
func Client(c bool) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Client = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jaeger sets whether or not Jaeger integration is enabled.
|
|
||||||
func Jaeger(j bool) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Jaeger = j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skaffold sets whether or not Skaffold integration is enabled.
|
|
||||||
func Skaffold(s bool) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Skaffold = s
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// Dockerfile is the Dockerfile template used for new projects.
|
|
||||||
var Dockerfile = `FROM golang:alpine AS builder
|
|
||||||
ENV CGO_ENABLED=0 GOOS=linux
|
|
||||||
WORKDIR /go/src/{{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
RUN apk --update --no-cache add ca-certificates gcc libtool make musl-dev protoc
|
|
||||||
COPY {{if not .Client}}Makefile {{end}}go.mod go.sum ./
|
|
||||||
RUN {{if not .Client}}make init && {{end}}go mod download
|
|
||||||
COPY . .
|
|
||||||
RUN make {{if not .Client}}proto {{end}}tidy build
|
|
||||||
|
|
||||||
FROM scratch
|
|
||||||
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
|
|
||||||
COPY --from=builder /go/src/{{.Service}}{{if .Client}}-client{{end}}/{{.Service}}{{if .Client}}-client{{end}} /{{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
ENTRYPOINT ["/{{.Service}}{{if .Client}}-client{{end}}"]
|
|
||||||
CMD []
|
|
||||||
`
|
|
||||||
|
|
||||||
// DockerIgnore is the .dockerignore template used for new projects.
|
|
||||||
var DockerIgnore = `.gitignore
|
|
||||||
Dockerfile{{if .Skaffold}}
|
|
||||||
resources/
|
|
||||||
skaffold.yaml{{end}}
|
|
||||||
`
|
|
@ -1,6 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// GitIgnore is the .gitignore template used for new projects.
|
|
||||||
var GitIgnore = `# don't commit the service binary to vcs
|
|
||||||
{{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
`
|
|
@ -1,89 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// HandlerFNC is the handler template used for new function projects.
|
|
||||||
var HandlerFNC = `package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
log "go-micro.dev/v4/logger"
|
|
||||||
|
|
||||||
pb "{{.Vendor}}{{.Service}}/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type {{title .Service}} struct{}
|
|
||||||
|
|
||||||
func (e *{{title .Service}}) Call(ctx context.Context, req *pb.CallRequest, rsp *pb.CallResponse) error {
|
|
||||||
log.Infof("Received {{title .Service}}.Call request: %v", req)
|
|
||||||
rsp.Msg = "Hello " + req.Name
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// HandlerSRV is the handler template used for new service projects.
|
|
||||||
var HandlerSRV = `package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
log "go-micro.dev/v4/logger"
|
|
||||||
|
|
||||||
pb "{{.Vendor}}{{.Service}}/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type {{title .Service}} struct{}
|
|
||||||
|
|
||||||
func (e *{{title .Service}}) Call(ctx context.Context, req *pb.CallRequest, rsp *pb.CallResponse) error {
|
|
||||||
log.Infof("Received {{title .Service}}.Call request: %v", req)
|
|
||||||
rsp.Msg = "Hello " + req.Name
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *{{title .Service}}) ClientStream(ctx context.Context, stream pb.{{title .Service}}_ClientStreamStream) error {
|
|
||||||
var count int64
|
|
||||||
for {
|
|
||||||
req, err := stream.Recv()
|
|
||||||
if err == io.EOF {
|
|
||||||
log.Infof("Got %v pings total", count)
|
|
||||||
return stream.SendMsg(&pb.ClientStreamResponse{Count: count})
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Infof("Got ping %v", req.Stroke)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *{{title .Service}}) ServerStream(ctx context.Context, req *pb.ServerStreamRequest, stream pb.{{title .Service}}_ServerStreamStream) error {
|
|
||||||
log.Infof("Received {{title .Service}}.ServerStream request: %v", req)
|
|
||||||
for i := 0; i < int(req.Count); i++ {
|
|
||||||
log.Infof("Sending %d", i)
|
|
||||||
if err := stream.Send(&pb.ServerStreamResponse{
|
|
||||||
Count: int64(i),
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 250)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *{{title .Service}}) BidiStream(ctx context.Context, stream pb.{{title .Service}}_BidiStreamStream) error {
|
|
||||||
for {
|
|
||||||
req, err := stream.Recv()
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Infof("Got ping %v", req.Stroke)
|
|
||||||
if err := stream.Send(&pb.BidiStreamResponse{Stroke: req.Stroke}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
@ -1,78 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// KubernetesEnv is a Kubernetes configmap manifest template used for
|
|
||||||
// environment variables in new projects.
|
|
||||||
var KubernetesEnv = `---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: {{.Service}}{{if .Client}}-client{{end}}-env
|
|
||||||
data:
|
|
||||||
MICRO_REGISTRY: kubernetes
|
|
||||||
`
|
|
||||||
|
|
||||||
// KubernetesClusterRole is a Kubernetes cluster role manifest template
|
|
||||||
// required for the Kubernetes registry plugin to function correctly.
|
|
||||||
var KubernetesClusterRole = `---
|
|
||||||
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: micro-registry
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- patch
|
|
||||||
- watch
|
|
||||||
`
|
|
||||||
|
|
||||||
// KubernetesRoleBinding is a Kubernetes role binding manifest template
|
|
||||||
// required for the Kubernetes registry plugin to function correctly.
|
|
||||||
var KubernetesRoleBinding = `---
|
|
||||||
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: micro-registry
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: micro-registry
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: default
|
|
||||||
namespace: default
|
|
||||||
`
|
|
||||||
|
|
||||||
// KubernetesDeployment is a Kubernetes deployment manifest template used for
|
|
||||||
// new projects.
|
|
||||||
var KubernetesDeployment = `---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
labels:
|
|
||||||
app: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
image: {{.Service}}{{if .Client}}-client{{end}}:latest
|
|
||||||
envFrom:
|
|
||||||
- configMapRef:
|
|
||||||
name: {{.Service}}{{if .Client}}-client{{end}}-env
|
|
||||||
`
|
|
@ -1,144 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// MainCLT is the main template used for new client projects.
|
|
||||||
var MainCLT = `package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
pb "{{.Vendor}}{{lower .Service}}/proto"
|
|
||||||
|
|
||||||
"go-micro.dev/v4"
|
|
||||||
log "go-micro.dev/v4/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
service = "{{lower .Service}}"
|
|
||||||
version = "latest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Create service
|
|
||||||
srv := micro.NewService()
|
|
||||||
srv.Init()
|
|
||||||
|
|
||||||
// Create client
|
|
||||||
c := pb.NewHelloworldService(service, srv.Client())
|
|
||||||
|
|
||||||
for {
|
|
||||||
// Call service
|
|
||||||
rsp, err := c.Call(context.Background(), &pb.CallRequest{Name: "John"})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info(rsp)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// MainFNC is the main template used for new function projects.
|
|
||||||
var MainFNC = `package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"{{.Vendor}}{{.Service}}/handler"
|
|
||||||
|
|
||||||
{{if .Jaeger}} ot "github.com/asim/go-micro/plugins/wrapper/trace/opentracing/v4"
|
|
||||||
{{end}} "go-micro.dev/v4"
|
|
||||||
log "go-micro.dev/v4/logger"{{if .Jaeger}}
|
|
||||||
|
|
||||||
"go-micro.dev/v4/cmd/micro/debug/trace/jaeger"{{end}}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
service = "{{lower .Service}}"
|
|
||||||
version = "latest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
{{if .Jaeger}} // Create tracer
|
|
||||||
tracer, closer, err := jaeger.NewTracer(
|
|
||||||
jaeger.Name(service),
|
|
||||||
jaeger.FromEnv(true),
|
|
||||||
jaeger.GlobalTracer(true),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer closer.Close()
|
|
||||||
|
|
||||||
{{end}} // Create function
|
|
||||||
fnc := micro.NewFunction(
|
|
||||||
micro.Name(service),
|
|
||||||
micro.Version(version),
|
|
||||||
{{if .Jaeger}} micro.WrapCall(ot.NewCallWrapper(tracer)),
|
|
||||||
micro.WrapClient(ot.NewClientWrapper(tracer)),
|
|
||||||
micro.WrapHandler(ot.NewHandlerWrapper(tracer)),
|
|
||||||
micro.WrapSubscriber(ot.NewSubscriberWrapper(tracer)),
|
|
||||||
{{end}} )
|
|
||||||
fnc.Init()
|
|
||||||
|
|
||||||
// Handle function
|
|
||||||
fnc.Handle(new(handler.{{title .Service}}))
|
|
||||||
|
|
||||||
// Run function
|
|
||||||
if err := fnc.Run(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// MainSRV is the main template used for new service projects.
|
|
||||||
var MainSRV = `package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"{{.Vendor}}{{.Service}}/handler"
|
|
||||||
pb "{{.Vendor}}{{.Service}}/proto"
|
|
||||||
|
|
||||||
{{if .Jaeger}} ot "github.com/asim/go-micro/plugins/wrapper/trace/opentracing/v4"
|
|
||||||
{{end}} "go-micro.dev/v4"
|
|
||||||
log "go-micro.dev/v4/logger"{{if .Jaeger}}
|
|
||||||
|
|
||||||
"go-micro.dev/v4/cmd/micro/debug/trace/jaeger"{{end}}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
service = "{{lower .Service}}"
|
|
||||||
version = "latest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
{{if .Jaeger}} // Create tracer
|
|
||||||
tracer, closer, err := jaeger.NewTracer(
|
|
||||||
jaeger.Name(service),
|
|
||||||
jaeger.FromEnv(true),
|
|
||||||
jaeger.GlobalTracer(true),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer closer.Close()
|
|
||||||
|
|
||||||
{{end}} // Create service
|
|
||||||
srv := micro.NewService(
|
|
||||||
micro.Name(service),
|
|
||||||
micro.Version(version),
|
|
||||||
{{if .Jaeger}} micro.WrapCall(ot.NewCallWrapper(tracer)),
|
|
||||||
micro.WrapClient(ot.NewClientWrapper(tracer)),
|
|
||||||
micro.WrapHandler(ot.NewHandlerWrapper(tracer)),
|
|
||||||
micro.WrapSubscriber(ot.NewSubscriberWrapper(tracer)),
|
|
||||||
{{end}} )
|
|
||||||
srv.Init()
|
|
||||||
|
|
||||||
// Register handler
|
|
||||||
pb.Register{{title .Service}}Handler(srv.Server(), new(handler.{{title .Service}}))
|
|
||||||
|
|
||||||
// Run service
|
|
||||||
if err := srv.Run(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
@ -1,35 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// Makefile is the Makefile template used for new projects.
|
|
||||||
var Makefile = `GOPATH:=$(shell go env GOPATH)
|
|
||||||
|
|
||||||
.PHONY: init
|
|
||||||
init:
|
|
||||||
@go get -u google.golang.org/protobuf/proto
|
|
||||||
@go install github.com/golang/protobuf/protoc-gen-go@latest
|
|
||||||
@go install github.com/asim/go-micro/cmd/protoc-gen-micro/v4@latest
|
|
||||||
|
|
||||||
.PHONY: proto
|
|
||||||
proto:
|
|
||||||
@protoc --proto_path=. --micro_out=. --go_out=:. proto/{{.Service}}.proto
|
|
||||||
|
|
||||||
.PHONY: update
|
|
||||||
update:
|
|
||||||
@go get -u
|
|
||||||
|
|
||||||
.PHONY: tidy
|
|
||||||
tidy:
|
|
||||||
@go mod tidy
|
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build:
|
|
||||||
@go build -o {{.Service}}{{if .Client}}-client{{end}} *.go
|
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
test:
|
|
||||||
@go test -v ./... -cover
|
|
||||||
|
|
||||||
.PHONY: docker
|
|
||||||
docker:
|
|
||||||
@docker build -t {{.Service}}{{if .Client}}-client{{end}}:latest .
|
|
||||||
`
|
|
@ -1,17 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// Module is the go.mod template used for new projects.
|
|
||||||
var Module = `module {{.Vendor}}{{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
|
|
||||||
go 1.16
|
|
||||||
|
|
||||||
require (
|
|
||||||
go-micro.dev/v4 v4.1.0
|
|
||||||
)
|
|
||||||
|
|
||||||
// This can be removed once etcd becomes go gettable, version 3.4 and 3.5 is not,
|
|
||||||
// see https://github.com/etcd-io/etcd/issues/11154 and https://github.com/etcd-io/etcd/issues/11931.
|
|
||||||
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0{{if .Vendor}}{{if not .Skaffold}}
|
|
||||||
|
|
||||||
replace {{.Vendor}}{{lower .Service}} => ../{{lower .Service}}{{end}}{{end}}
|
|
||||||
`
|
|
@ -1,9 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// Plugins is the plugins template used for new projects.
|
|
||||||
var Plugins = `package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "github.com/asim/go-micro/plugins/registry/kubernetes/v4"
|
|
||||||
)
|
|
||||||
`
|
|
@ -1,68 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// ProtoFNC is the .proto file template used for new function projects.
|
|
||||||
var ProtoFNC = `syntax = "proto3";
|
|
||||||
|
|
||||||
package {{dehyphen .Service}};
|
|
||||||
|
|
||||||
option go_package = "./proto;{{dehyphen .Service}}";
|
|
||||||
|
|
||||||
service {{title .Service}} {
|
|
||||||
rpc Call(CallRequest) returns (CallResponse) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
message CallRequest {
|
|
||||||
string name = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CallResponse {
|
|
||||||
string msg = 1;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
// ProtoSRV is the .proto file template used for new service projects.
|
|
||||||
var ProtoSRV = `syntax = "proto3";
|
|
||||||
|
|
||||||
package {{dehyphen .Service}};
|
|
||||||
|
|
||||||
option go_package = "./proto;{{dehyphen .Service}}";
|
|
||||||
|
|
||||||
service {{title .Service}} {
|
|
||||||
rpc Call(CallRequest) returns (CallResponse) {}
|
|
||||||
rpc ClientStream(stream ClientStreamRequest) returns (ClientStreamResponse) {}
|
|
||||||
rpc ServerStream(ServerStreamRequest) returns (stream ServerStreamResponse) {}
|
|
||||||
rpc BidiStream(stream BidiStreamRequest) returns (stream BidiStreamResponse) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
message CallRequest {
|
|
||||||
string name = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CallResponse {
|
|
||||||
string msg = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ClientStreamRequest {
|
|
||||||
int64 stroke = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ClientStreamResponse {
|
|
||||||
int64 count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ServerStreamRequest {
|
|
||||||
int64 count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ServerStreamResponse {
|
|
||||||
int64 count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message BidiStreamRequest {
|
|
||||||
int64 stroke = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message BidiStreamResponse {
|
|
||||||
int64 stroke = 1;
|
|
||||||
}
|
|
||||||
`
|
|
@ -1,17 +0,0 @@
|
|||||||
package template
|
|
||||||
|
|
||||||
// SkaffoldCFG is the Skaffold config template used for new projects.
|
|
||||||
var SkaffoldCFG = `---
|
|
||||||
|
|
||||||
apiVersion: skaffold/v2beta21
|
|
||||||
kind: Config
|
|
||||||
metadata:
|
|
||||||
name: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
build:
|
|
||||||
artifacts:
|
|
||||||
- image: {{.Service}}{{if .Client}}-client{{end}}
|
|
||||||
deploy:
|
|
||||||
kubectl:
|
|
||||||
manifests:
|
|
||||||
- resources/*.yaml
|
|
||||||
`
|
|
@ -1,18 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-micro.dev/v4/cmd/micro/cli"
|
|
||||||
|
|
||||||
// register commands
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/call"
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/describe"
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/generate"
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/new"
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/run"
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/services"
|
|
||||||
_ "go-micro.dev/v4/cmd/micro/cli/stream"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cli.Run()
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user