feat(goctl): Support gateway sample generation (#3049)

master
anqiansong 2 years ago committed by GitHub
parent 95b85336d6
commit 1904af2323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,166 +13,91 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/tsgen"
"github.com/zeromicro/go-zero/tools/goctl/api/validate"
"github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/plugin"
)
var (
// Cmd describes an api command.
Cmd = &cobra.Command{
Use: "api",
Short: "Generate api related files",
RunE: apigen.CreateApiTemplate,
}
dartCmd = &cobra.Command{
Use: "dart",
Short: "Generate dart files for provided api in api file",
RunE: dartgen.DartCommand,
}
docCmd = &cobra.Command{
Use: "doc",
Short: "Generate doc files",
RunE: docgen.DocCommand,
}
formatCmd = &cobra.Command{
Use: "format",
Short: "Format api files",
RunE: format.GoFormatApi,
}
goCmd = &cobra.Command{
Use: "go",
Short: "Generate go files for provided api in api file",
RunE: gogen.GoCommand,
}
newCmd = &cobra.Command{
Use: "new",
Short: "Fast create api service",
Example: "goctl api new [options] service-name",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: func(cmd *cobra.Command, args []string) error {
return new.CreateServiceCommand(args)
},
}
validateCmd = &cobra.Command{
Use: "validate",
Short: "Validate api file",
RunE: validate.GoValidateApi,
}
javaCmd = &cobra.Command{
Use: "java",
Short: "Generate java files for provided api in api file",
Hidden: true,
RunE: javagen.JavaCommand,
}
ktCmd = &cobra.Command{
Use: "kt",
Short: "Generate kotlin code for provided api file",
RunE: ktgen.KtCommand,
}
pluginCmd = &cobra.Command{
Use: "plugin",
Short: "Custom file generator",
RunE: plugin.PluginCommand,
}
tsCmd = &cobra.Command{
Use: "ts",
Short: "Generate ts files for provided api in api file",
RunE: tsgen.TsCommand,
}
Cmd = cobrax.NewCommand("api", cobrax.WithRunE(apigen.CreateApiTemplate))
dartCmd = cobrax.NewCommand("dart", cobrax.WithRunE(dartgen.DartCommand))
docCmd = cobrax.NewCommand("doc", cobrax.WithRunE(docgen.DocCommand))
formatCmd = cobrax.NewCommand("format", cobrax.WithRunE(format.GoFormatApi))
goCmd = cobrax.NewCommand("go", cobrax.WithRunE(gogen.GoCommand))
newCmd = cobrax.NewCommand("new", cobrax.WithRunE(new.CreateServiceCommand),
cobrax.WithArgs(cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)))
validateCmd = cobrax.NewCommand("validate", cobrax.WithRunE(validate.GoValidateApi))
javaCmd = cobrax.NewCommand("java", cobrax.WithRunE(javagen.JavaCommand), cobrax.WithHidden())
ktCmd = cobrax.NewCommand("kt", cobrax.WithRunE(ktgen.KtCommand))
pluginCmd = cobrax.NewCommand("plugin", cobrax.WithRunE(plugin.PluginCommand))
tsCmd = cobrax.NewCommand("ts", cobrax.WithRunE(tsgen.TsCommand))
)
func init() {
Cmd.Flags().StringVar(&apigen.VarStringOutput, "o", "", "Output a sample api file")
Cmd.Flags().StringVar(&apigen.VarStringHome, "home", "", "The goctl home path of the"+
" template, --home and --remote cannot be set at the same time, if they are, --remote has "+
"higher priority")
Cmd.Flags().StringVar(&apigen.VarStringRemote, "remote", "", "The remote git repo of the"+
" template, --home and --remote cannot be set at the same time, if they are, --remote has higher"+
" priority\nThe git repo directory must be consistent with the"+
" https://github.com/zeromicro/go-zero-template directory structure")
Cmd.Flags().StringVar(&apigen.VarStringBranch, "branch", "", "The branch of the "+
"remote repo, it does work with --remote")
dartCmd.Flags().StringVar(&dartgen.VarStringDir, "dir", "", "The target dir")
dartCmd.Flags().StringVar(&dartgen.VarStringAPI, "api", "", "The api file")
dartCmd.Flags().BoolVar(&dartgen.VarStringLegacy, "legacy", false, "Legacy generator for flutter v1")
dartCmd.Flags().StringVar(&dartgen.VarStringHostname, "hostname", "", "hostname of the server")
dartCmd.Flags().StringVar(&dartgen.VarStringScheme, "scheme", "", "scheme of the server")
docCmd.Flags().StringVar(&docgen.VarStringDir, "dir", "", "The target dir")
docCmd.Flags().StringVar(&docgen.VarStringOutput, "o", "", "The output markdown directory")
formatCmd.Flags().StringVar(&format.VarStringDir, "dir", "", "The format target dir")
formatCmd.Flags().BoolVar(&format.VarBoolIgnore, "iu", false, "Ignore update")
formatCmd.Flags().BoolVar(&format.VarBoolUseStdin, "stdin", false, "Use stdin to input api"+
" doc content, press \"ctrl + d\" to send EOF")
formatCmd.Flags().BoolVar(&format.VarBoolSkipCheckDeclare, "declare", false, "Use to skip check "+
"api types already declare")
goCmd.Flags().StringVar(&gogen.VarStringDir, "dir", "", "The target dir")
goCmd.Flags().StringVar(&gogen.VarStringAPI, "api", "", "The api file")
goCmd.Flags().StringVar(&gogen.VarStringHome, "home", "", "The goctl home path of "+
"the template, --home and --remote cannot be set at the same time, if they are, --remote "+
"has higher priority")
goCmd.Flags().StringVar(&gogen.VarStringRemote, "remote", "", "The remote git repo "+
"of the template, --home and --remote cannot be set at the same time, if they are, --remote"+
" has higher priority\nThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
goCmd.Flags().StringVar(&gogen.VarStringBranch, "branch", "", "The branch of "+
"the remote repo, it does work with --remote")
goCmd.Flags().StringVar(&gogen.VarStringStyle, "style", config.DefaultFormat, "The file naming format,"+
" see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]")
javaCmd.Flags().StringVar(&javagen.VarStringDir, "dir", "", "The target dir")
javaCmd.Flags().StringVar(&javagen.VarStringAPI, "api", "", "The api file")
ktCmd.Flags().StringVar(&ktgen.VarStringDir, "dir", "", "The target dir")
ktCmd.Flags().StringVar(&ktgen.VarStringAPI, "api", "", "The api file")
ktCmd.Flags().StringVar(&ktgen.VarStringPKG, "pkg", "", "Define package name for kotlin file")
newCmd.Flags().StringVar(&new.VarStringHome, "home", "", "The goctl home path of "+
"the template, --home and --remote cannot be set at the same time, if they are, --remote "+
"has higher priority")
newCmd.Flags().StringVar(&new.VarStringRemote, "remote", "", "The remote git repo "+
"of the template, --home and --remote cannot be set at the same time, if they are, --remote"+
" has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
newCmd.Flags().StringVar(&new.VarStringBranch, "branch", "", "The branch of "+
"the remote repo, it does work with --remote")
newCmd.Flags().StringVar(&new.VarStringStyle, "style", config.DefaultFormat, "The file naming format,"+
" see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]")
pluginCmd.Flags().StringVarP(&plugin.VarStringPlugin, "plugin", "p", "", "The plugin file")
pluginCmd.Flags().StringVar(&plugin.VarStringDir, "dir", "", "The target dir")
pluginCmd.Flags().StringVar(&plugin.VarStringAPI, "api", "", "The api file")
pluginCmd.Flags().StringVar(&plugin.VarStringStyle, "style", "",
"The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
tsCmd.Flags().StringVar(&tsgen.VarStringDir, "dir", "", "The target dir")
tsCmd.Flags().StringVar(&tsgen.VarStringAPI, "api", "", "The api file")
tsCmd.Flags().StringVar(&tsgen.VarStringCaller, "caller", "", "The web api caller")
tsCmd.Flags().BoolVar(&tsgen.VarBoolUnWrap, "unwrap", false, "Unwrap the webapi caller for import")
validateCmd.Flags().StringVar(&validate.VarStringAPI, "api", "", "Validate target api file")
var (
apiCmdFlags = Cmd.Flags()
dartCmdFlags = dartCmd.Flags()
docCmdFlags = docCmd.Flags()
formatCmdFlags = formatCmd.Flags()
goCmdFlags = goCmd.Flags()
javaCmdFlags = javaCmd.Flags()
ktCmdFlags = ktCmd.Flags()
newCmdFlags = newCmd.Flags()
pluginCmdFlags = pluginCmd.Flags()
tsCmdFlags = tsCmd.Flags()
validateCmdFlags = validateCmd.Flags()
)
apiCmdFlags.StringVar(&apigen.VarStringOutput, "o")
apiCmdFlags.StringVar(&apigen.VarStringHome, "home")
apiCmdFlags.StringVar(&apigen.VarStringRemote, "remote")
apiCmdFlags.StringVar(&apigen.VarStringBranch, "branch")
dartCmdFlags.StringVar(&dartgen.VarStringDir, "dir")
dartCmdFlags.StringVar(&dartgen.VarStringAPI, "api")
dartCmdFlags.BoolVar(&dartgen.VarStringLegacy, "legacy")
dartCmdFlags.StringVar(&dartgen.VarStringHostname, "hostname")
dartCmdFlags.StringVar(&dartgen.VarStringScheme, "scheme")
docCmdFlags.StringVar(&docgen.VarStringDir, "dir")
docCmdFlags.StringVar(&docgen.VarStringOutput, "o")
formatCmdFlags.StringVar(&format.VarStringDir, "dir")
formatCmdFlags.BoolVar(&format.VarBoolIgnore, "iu")
formatCmdFlags.BoolVar(&format.VarBoolUseStdin, "stdin")
formatCmdFlags.BoolVar(&format.VarBoolSkipCheckDeclare, "declare")
goCmdFlags.StringVar(&gogen.VarStringDir, "dir")
goCmdFlags.StringVar(&gogen.VarStringAPI, "api")
goCmdFlags.StringVar(&gogen.VarStringHome, "home")
goCmdFlags.StringVar(&gogen.VarStringRemote, "remote")
goCmdFlags.StringVar(&gogen.VarStringBranch, "branch")
goCmdFlags.StringVarWithDefaultValue(&gogen.VarStringStyle, "style", config.DefaultFormat)
javaCmdFlags.StringVar(&javagen.VarStringDir, "dir")
javaCmdFlags.StringVar(&javagen.VarStringAPI, "api")
ktCmdFlags.StringVar(&ktgen.VarStringDir, "dir")
ktCmdFlags.StringVar(&ktgen.VarStringAPI, "api")
ktCmdFlags.StringVar(&ktgen.VarStringPKG, "pkg")
newCmdFlags.StringVar(&new.VarStringHome, "home")
newCmdFlags.StringVar(&new.VarStringRemote, "remote")
newCmdFlags.StringVar(&new.VarStringBranch, "branch")
newCmdFlags.StringVarWithDefaultValue(&new.VarStringStyle, "style", config.DefaultFormat)
pluginCmdFlags.StringVarP(&plugin.VarStringPlugin, "plugin", "p")
pluginCmdFlags.StringVar(&plugin.VarStringDir, "dir")
pluginCmdFlags.StringVar(&plugin.VarStringAPI, "api")
pluginCmdFlags.StringVar(&plugin.VarStringStyle, "style")
tsCmdFlags.StringVar(&tsgen.VarStringDir, "dir")
tsCmdFlags.StringVar(&tsgen.VarStringAPI, "api")
tsCmdFlags.StringVar(&tsgen.VarStringCaller, "caller")
tsCmdFlags.BoolVar(&tsgen.VarBoolUnWrap, "unwrap")
validateCmdFlags.StringVar(&validate.VarStringAPI, "api")
// Add sub-commands
Cmd.AddCommand(dartCmd)
Cmd.AddCommand(docCmd)
Cmd.AddCommand(formatCmd)
Cmd.AddCommand(goCmd)
Cmd.AddCommand(javaCmd)
Cmd.AddCommand(ktCmd)
Cmd.AddCommand(newCmd)
Cmd.AddCommand(pluginCmd)
Cmd.AddCommand(tsCmd)
Cmd.AddCommand(validateCmd)
Cmd.AddCommand(dartCmd, docCmd, formatCmd, goCmd, javaCmd, ktCmd, newCmd, pluginCmd, tsCmd, validateCmd)
}

@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/api/gogen"
conf "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/util"
@ -29,7 +30,7 @@ var (
)
// CreateServiceCommand fast create service
func CreateServiceCommand(args []string) error {
func CreateServiceCommand(_ *cobra.Command, args []string) error {
dirName := args[0]
if len(VarStringStyle) == 0 {
VarStringStyle = conf.DefaultFormat

@ -1,11 +1,9 @@
package bug
import "github.com/spf13/cobra"
import (
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
)
// Cmd describes a bug command.
var Cmd = &cobra.Command{
Use: "bug",
Short: "Report a bug",
Args: cobra.NoArgs,
RunE: runE,
}
var Cmd = cobrax.NewCommand("bug", cobrax.WithRunE(cobra.NoArgs), cobrax.WithArgs(cobra.NoArgs))

@ -15,6 +15,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/bug"
"github.com/zeromicro/go-zero/tools/goctl/docker"
"github.com/zeromicro/go-zero/tools/goctl/env"
"github.com/zeromicro/go-zero/tools/goctl/gateway"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
"github.com/zeromicro/go-zero/tools/goctl/kube"
"github.com/zeromicro/go-zero/tools/goctl/migrate"
@ -35,14 +37,7 @@ const (
var (
//go:embed usage.tpl
usageTpl string
rootCmd = &cobra.Command{
Use: "goctl",
Short: "A cli tool to generate go-zero code",
Long: "A cli tool to generate api, zrpc, model code\n\n" +
"GitHub: https://github.com/zeromicro/go-zero\n" +
"Site: https://go-zero.dev",
}
rootCmd = cobrax.NewCommand("goctl")
)
// Execute executes the given command
@ -117,16 +112,8 @@ func init() {
runtime.GOOS, runtime.GOARCH)
rootCmd.SetUsageTemplate(usageTpl)
rootCmd.AddCommand(api.Cmd)
rootCmd.AddCommand(bug.Cmd)
rootCmd.AddCommand(docker.Cmd)
rootCmd.AddCommand(kube.Cmd)
rootCmd.AddCommand(env.Cmd)
rootCmd.AddCommand(model.Cmd)
rootCmd.AddCommand(migrate.Cmd)
rootCmd.AddCommand(quickstart.Cmd)
rootCmd.AddCommand(rpc.Cmd)
rootCmd.AddCommand(tpl.Cmd)
rootCmd.AddCommand(upgrade.Cmd)
rootCmd.AddCommand(cobracompletefig.CreateCompletionSpecCommand())
rootCmd.AddCommand(api.Cmd, bug.Cmd, docker.Cmd, kube.Cmd, env.Cmd, gateway.Cmd, model.Cmd)
rootCmd.AddCommand(migrate.Cmd, quickstart.Cmd, rpc.Cmd, tpl.Cmd, upgrade.Cmd)
rootCmd.Command.AddCommand(cobracompletefig.CreateCompletionSpecCommand())
rootCmd.MustInit()
}

@ -1,6 +1,6 @@
package docker
import "github.com/spf13/cobra"
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var (
varExeName string
@ -14,21 +14,18 @@ var (
varStringTZ string
// Cmd describes a docker command.
Cmd = &cobra.Command{
Use: "docker",
Short: "Generate Dockerfile",
RunE: dockerCommand,
}
Cmd = cobrax.NewCommand("docker", cobrax.WithRunE(dockerCommand))
)
func init() {
Cmd.Flags().StringVar(&varExeName, "exe", "", "The executable name in the built image")
Cmd.Flags().StringVar(&varStringGo, "go", "", "The file that contains main function")
Cmd.Flags().StringVar(&varStringBase, "base", "scratch", "The base image to build the docker image, default scratch")
Cmd.Flags().IntVar(&varIntPort, "port", 0, "The port to expose, default none")
Cmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
Cmd.Flags().StringVar(&varStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
Cmd.Flags().StringVar(&varStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
Cmd.Flags().StringVar(&varStringVersion, "version", "", "The goctl builder golang image version")
Cmd.Flags().StringVar(&varStringTZ, "tz", "Asia/Shanghai", "The timezone of the container")
dockerCmdFlags := Cmd.Flags()
dockerCmdFlags.StringVar(&varExeName, "exe")
dockerCmdFlags.StringVar(&varStringGo, "go")
dockerCmdFlags.StringVarWithDefaultValue(&varStringBase, "base", "scratch")
dockerCmdFlags.IntVar(&varIntPort, "port")
dockerCmdFlags.StringVar(&varStringHome, "home")
dockerCmdFlags.StringVar(&varStringRemote, "remote")
dockerCmdFlags.StringVar(&varStringBranch, "branch")
dockerCmdFlags.StringVar(&varStringVersion, "version")
dockerCmdFlags.StringVarWithDefaultValue(&varStringTZ, "tz", "Asia/Shanghai")
}

@ -1,6 +1,6 @@
package env
import "github.com/spf13/cobra"
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var (
sliceVarWriteValue []string
@ -9,38 +9,20 @@ var (
boolVarInstall bool
// Cmd describes an env command.
Cmd = &cobra.Command{
Use: "env",
Short: "Check or edit goctl environment",
RunE: write,
}
installCmd = &cobra.Command{
Use: "install",
Short: "Goctl env installation",
RunE: install,
}
checkCmd = &cobra.Command{
Use: "check",
Short: "Detect goctl env and dependency tools",
RunE: check,
}
Cmd = cobrax.NewCommand("env", cobrax.WithRunE(write))
installCmd = cobrax.NewCommand("install", cobrax.WithRunE(install))
checkCmd = cobrax.NewCommand("check", cobrax.WithRunE(check))
)
func init() {
// The root command flags
Cmd.Flags().StringSliceVarP(&sliceVarWriteValue,
"write", "w", nil, "Edit goctl environment")
Cmd.PersistentFlags().BoolVarP(&boolVarForce,
"force", "f", false,
"Silent installation of non-existent dependencies")
Cmd.PersistentFlags().BoolVarP(&boolVarVerbose,
"verbose", "v", false, "Enable log output")
Cmd.Flags().StringSliceVarP(&sliceVarWriteValue, "write", "w")
Cmd.PersistentFlags().BoolVarP(&boolVarForce, "force", "f")
Cmd.PersistentFlags().BoolVarP(&boolVarVerbose, "verbose", "v")
// The sub-command flags
checkCmd.Flags().BoolVarP(&boolVarInstall, "install", "i",
false, "Install dependencies if not found")
checkCmd.Flags().BoolVarP(&boolVarInstall, "install", "i")
// Add sub-command
Cmd.AddCommand(installCmd)
Cmd.AddCommand(checkCmd)
Cmd.AddCommand(checkCmd, installCmd)
}

@ -7,10 +7,10 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/pkg/env"
)
func write(_ *cobra.Command, _ []string) error {
func write(_ *cobra.Command, args []string) error {
if len(sliceVarWriteValue) > 0 {
return env.WriteEnv(sliceVarWriteValue)
}
fmt.Println(env.Print())
fmt.Println(env.Print(args...))
return nil
}

@ -1,8 +1,6 @@
package env
import (
"github.com/spf13/cobra"
)
import "github.com/spf13/cobra"
func install(_ *cobra.Command, _ []string) error {
return Prepare(true, boolVarForce, boolVarVerbose)

@ -0,0 +1,60 @@
package gateway
import (
_ "embed"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/util/ctx"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
var (
varStringHome string
varStringRemote string
varStringBranch string
varStringDir string
Cmd = cobrax.NewCommand("gateway", cobrax.WithRunE(generateGateway))
)
func init() {
Cmd.PersistentFlags().StringVar(&varStringHome, "home")
Cmd.PersistentFlags().StringVar(&varStringRemote, "remote")
Cmd.PersistentFlags().StringVar(&varStringBranch, "branch")
Cmd.PersistentFlags().StringVar(&varStringDir, "dir")
}
func generateGateway(*cobra.Command, []string) error {
if err:=pathx.MkdirIfNotExist(varStringDir);err!=nil{
return err
}
if _,err:=ctx.Prepare(varStringDir);err!=nil{
return err
}
etcContent, err := pathx.LoadTemplate(category, etcTemplateFileFile, etcTemplate)
if err != nil {
return err
}
mainContent, err := pathx.LoadTemplate(category, mainTemplateFile, mainTemplate)
if err != nil {
return err
}
etcDir := filepath.Join(varStringDir, "etc")
if err := pathx.MkdirIfNotExist(etcDir); err != nil {
return err
}
etcFile := filepath.Join(etcDir, "gateway.yaml")
if err := os.WriteFile(etcFile, []byte(etcContent), 0644); err != nil {
return err
}
mainFile := filepath.Join(varStringDir, "main.go")
return os.WriteFile(mainFile, []byte(mainContent), 0644)
}

@ -0,0 +1,18 @@
Name: gateway-example # gateway name
Host: localhost # gateway host
Port: 8888 # gateway port
Upstreams: # upstreams
- Grpc: # grpc upstream
Target: 0.0.0.0:8080 # grpc target,the direct grpc server address,for only one node
# Endpoints: [0.0.0.0:8080,192.168.120.1:8080] # grpc endpoints, the grpc server address list, for multiple nodes
# Etcd: # etcd config, if you want to use etcd to discover the grpc server address
# Hosts: [127.0.0.1:2378,127.0.0.1:2379] # etcd hosts
# Key: greet.grpc # the discovery key
# protoset mode
ProtoSets:
- hello.pb
# Mappings can also be written in proto options
# Mappings: # routes mapping
# - Method: get
# Path: /ping
# RpcPath: hello.Hello/Ping

@ -0,0 +1,20 @@
package main
import (
"flag"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/gateway"
)
var configFile = flag.String("f", "etc/gateway.yaml", "config file")
func main() {
flag.Parse()
var c gateway.GatewayConf
conf.MustLoad(*configFile, &c)
gw := gateway.MustNewServer(c)
defer gw.Stop()
gw.Start()
}

@ -0,0 +1,62 @@
package gateway
import (
_ "embed"
"fmt"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const (
category = "gateway"
etcTemplateFileFile = "etc.tpl"
mainTemplateFile = "main.tpl"
)
//go:embed conf.yml
var etcTemplate string
//go:embed gateway.tpl
var mainTemplate string
var templates = map[string]string{
etcTemplateFileFile: etcTemplate,
mainTemplateFile: mainTemplate,
}
// GenTemplates is the entry for command goctl template,
// it will create the specified category
func GenTemplates() error {
return pathx.InitTemplates(category, templates)
}
// RevertTemplate restores the deleted template files
func RevertTemplate(name string) error {
content, ok := templates[name]
if !ok {
return fmt.Errorf("%s: no such file name", name)
}
return pathx.CreateTemplate(category, name, content)
}
// Clean deletes all template files
func Clean() error {
return pathx.Clean(category)
}
// Update is used to update the template files, it will delete the existing old templates at first,
// and then create the latest template files
func Update() error {
err := Clean()
if err != nil {
return err
}
return pathx.InitTemplates(category, templates)
}
// Category returns a const string value for rpc template category
func Category() string {
return category
}

@ -10,6 +10,7 @@ require (
github.com/iancoleman/strcase v0.2.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.2
github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1
github.com/zeromicro/antlr v0.0.1
@ -34,6 +35,7 @@ require (
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
@ -69,7 +71,6 @@ require (
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect
go.etcd.io/etcd/api/v3 v3.5.7 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect

@ -101,7 +101,8 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -541,6 +542,7 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

@ -0,0 +1,171 @@
package cobrax
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/zeromicro/go-zero/tools/goctl/internal/flags"
)
type Option func(*cobra.Command)
func WithRunE(runE func(*cobra.Command, []string) error) Option {
return func(cmd *cobra.Command) {
cmd.RunE = runE
}
}
func WithRun(run func(*cobra.Command, []string)) Option {
return func(cmd *cobra.Command) {
cmd.Run = run
}
}
func WithArgs(arg cobra.PositionalArgs) Option {
return func(command *cobra.Command) {
command.Args = arg
}
}
func WithHidden() Option {
return func(command *cobra.Command) {
command.Hidden = true
}
}
type Command struct {
*cobra.Command
}
type FlagSet struct {
*pflag.FlagSet
}
func (f *FlagSet) StringVar(p *string, name string) {
f.StringVarWithDefaultValue(p, name, "")
}
func (f *FlagSet) StringVarWithDefaultValue(p *string, name string, value string) {
f.FlagSet.StringVar(p, name, value, "")
}
func (f *FlagSet) StringVarP(p *string, name, shorthand string) {
f.StringVarPWithDefaultValue(p, name, shorthand, "")
}
func (f *FlagSet) StringVarPWithDefaultValue(p *string, name, shorthand string, value string) {
f.FlagSet.StringVarP(p, name, shorthand, value, "")
}
func (f *FlagSet) BoolVar(p *bool, name string) {
f.BoolVarWithDefaultValue(p, name, false)
}
func (f *FlagSet) BoolVarWithDefaultValue(p *bool, name string, value bool) {
f.FlagSet.BoolVar(p, name, value, "")
}
func (f *FlagSet) BoolVarP(p *bool, name, shorthand string) {
f.BoolVarPWithDefaultValue(p, name, shorthand, false)
}
func (f *FlagSet) BoolVarPWithDefaultValue(p *bool, name, shorthand string, value bool) {
f.FlagSet.BoolVarP(p, name, shorthand, value, "")
}
func (f *FlagSet) IntVar(p *int, name string) {
f.IntVarWithDefaultValue(p, name, 0)
}
func (f *FlagSet) IntVarWithDefaultValue(p *int, name string, value int) {
f.FlagSet.IntVar(p, name, value, "")
}
func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string) {
f.FlagSet.StringSliceVarP(p, name, shorthand, []string{}, "")
}
func (f *FlagSet) StringSliceVarPWithDefaultValue(p *[]string, name, shorthand string, value []string) {
f.FlagSet.StringSliceVarP(p, name, shorthand, value, "")
}
func (f *FlagSet) StringSliceVar(p *[]string, name string) {
f.StringSliceVarWithDefaultValue(p, name, []string{})
}
func (f *FlagSet) StringSliceVarWithDefaultValue(p *[]string, name string, value []string) {
f.FlagSet.StringSliceVar(p, name, value, "")
}
func NewCommand(use string, opts ...Option) *Command {
c := &Command{
Command: &cobra.Command{
Use: use,
},
}
for _, opt := range opts {
opt(c.Command)
}
return c
}
func (c *Command) AddCommand(cmds ...*Command) {
for _, cmd := range cmds {
c.Command.AddCommand(cmd.Command)
}
}
func (c *Command) Flags() *FlagSet {
set := c.Command.Flags()
return &FlagSet{
FlagSet: set,
}
}
func (c *Command) PersistentFlags() *FlagSet {
set := c.Command.PersistentFlags()
return &FlagSet{
FlagSet: set,
}
}
func (c *Command) MustInit() {
commands := append([]*cobra.Command{c.Command}, getCommandsRecursively(c.Command)...)
for _, command := range commands {
commandKey := getCommandName(command)
if len(command.Short) == 0 {
command.Short = flags.Get(commandKey + ".short")
}
if len(command.Long) == 0 {
command.Long = flags.Get(commandKey + ".long")
}
if len(command.Example) == 0 {
command.Example = flags.Get(commandKey + ".example")
}
command.Flags().VisitAll(func(flag *pflag.Flag) {
flag.Usage = flags.Get(fmt.Sprintf("%s.%s", commandKey, flag.Name))
})
command.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
flag.Usage = flags.Get(fmt.Sprintf("%s.%s", commandKey, flag.Name))
})
}
}
func getCommandName(cmd *cobra.Command) string {
if cmd.HasParent() {
return getCommandName(cmd.Parent()) + "." + cmd.Name()
}
return cmd.Name()
}
func getCommandsRecursively(parent *cobra.Command) []*cobra.Command {
var commands []*cobra.Command
for _, cmd := range parent.Commands() {
commands = append(commands, cmd)
commands = append(commands, getCommandsRecursively(cmd)...)
}
return commands
}

@ -0,0 +1,283 @@
{
"goctl": {
"short": "A cli tool to generate go-zero code",
"long": "A cli tool to generate api, zrpc, model code\n\nGitHub: https://github.com/zeromicro/go-zero\nSite: https://go-zero.dev",
"api": {
"short": "Generate api related files",
"o": "Output a sample api file",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"api": "The api file",
"dir": "The target dir",
"dart": {
"short": "Generate dart files for provided api in api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"legacy": "Legacy generator for flutter v1",
"hostname": "hostname of the server",
"scheme": "scheme of the server"
},
"doc": {
"short": "Generate doc files",
"dir": "{{.goctl.api.dir}}",
"o": "The output markdown directory"
},
"format": {
"short": "Format api files",
"dir": "{{.goctl.api.dir}}",
"iu": "Ignore update",
"stdin": "Use stdin to input api doc content, press \"ctrl + d\" to send EOF",
"declare": "Use to skip check api types already declare"
},
"go": {
"short": "Generate go files for provided api in api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"style": "{{.global.style}}"
},
"new": {
"short": "Fast create api service",
"Example": "goctl api new [options] service-name",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"style": "{{.global.style}}"
},
"validate": {
"short": "Validate api file",
"api": "{{.goctl.api.api}}"
},
"kt": {
"short": "Generate kotlin code for provided api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"pkg": "Define package name for kotlin file"
},
"plugin": {
"short": "Custom file generator",
"plugin": "The plugin file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"style": "{{.global.style}}"
},
"ts": {
"short": "Generate ts files for provided api in api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"caller": "The web api caller",
"unwrap": "Unwrap the webapi caller for import"
}
},
"bug": {
"short": "Report a bug"
},
"docker": {
"short": "Generate Dockerfile",
"exe": "The executable name in the built image",
"go": "The file that contains main function",
"base": "The base image to build the docker image, default scratch",
"port": "The port to expose, default none",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"version": "The goctl builder golang image version",
"tz": "The timezone of the container"
},
"kube": {
"short": "Generate kubernetes files",
"deploy": {
"short": "Generate deployment yaml file",
"name": "The name of deployment (required)",
"namespace": "The namespace of deployment (required)",
"image": "The docker image of deployment (required)",
"secret": "The secret to image pull from registry",
"requestCpu": "The request cpu to deploy",
"requestMem": "The request memory to deploy",
"limitCpu": "The limit cpu to deploy",
"limitMem": "The limit memory to deploy",
"o": "The output yaml file (required)",
"replicas": "The number of replicas to deploy",
"revisions": "The number of revision history to limit",
"port": "The port of the deployment to listen on pod (required)",
"nodePort": "The nodePort of the deployment to expose",
"targetPort": "The targetPort of the deployment, default to port",
"minReplicas": "The min replicas to deploy",
"maxReplicas": "The max replicas to deploy",
"imagePullPolicy": "The image pull policy of the deployment, default to IfNotPresent",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"serviceAccount": "TheServiceAccount for the deployment"
}
},
"env": {
"short": "Check or edit goctl environment",
"write": "Edit goctl environment",
"force": "Silent installation of non-existent dependencies",
"verbose": "Enable log output",
"install": {
"short": "Goctl env installation"
},
"check": {
"short": "Detect goctl env and dependency tools",
"install": "Install dependencies if not found"
}
},
"gateway": {
"short": "gateway is a tool to generate gateway code",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"dir": "The output dir",
"protoc": {
"short": "generate gateway code from proto file"
},
"protoset": {
"short": "generate gateway code from protoset file"
},
"server": {
"short": "generate gateway code from grpc server"
}
},
"model": {
"short": "Generate model code",
"dir": "The target dir",
"mysql": {
"short": "Generate mysql model",
"strict": "Generate model in strict mode",
"ignore-columns": "Ignore columns while creating or updating rows",
"datasource": {
"short": "Generate model from datasource",
"url": "The data source of database,like \"root:password@tcp(127.0.0.1:3306)/database",
"table": "The table or table globbing patterns in the database",
"cache": "Generate code with cache [optional]",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"idea": "For idea plugin [optional]",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
},
"ddl": {
"short": "Generate mysql model from ddl",
"src": "The path or path globbing patterns of the ddl",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"cache": "Generate code with cache [optional]",
"idea": "For idea plugin [optional]",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
}
},
"pg": {
"short": "Generate postgresql model",
"datasource": {
"short": "Generate model from datasource",
"url": "The data source of database,like \"root:password@tcp(127.0.0.1:3306)/database",
"table": "The table or table globbing patterns in the database",
"schema": "The schema or schema globbing patterns in the database",
"cache": "Generate code with cache [optional]",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"idea": "For idea plugin [optional]",
"strict": "Generate model in strict mode",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
}
},
"mongo": {
"short": "Generate mongo model",
"type": "Specified model type name",
"cache": "Generate code with cache [optional]",
"easy": "Generate code with auto generated CollectionName for easy declare [optional]",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
}
},
"migrate": {
"short": "Migrate from tal-tech to zeromicro",
"long": "Migrate is a transition command to help users migrate their projects from tal-tech to zeromicro version",
"verbose": "Verbose enables extra logging",
"version": "The target release version of github.com/zeromicro/go-zero to migrate"
},
"quickstart": {
"short": "quickly start a project",
"service-type": "specify the service type, supported values: [mono, micro]"
},
"rpc": {
"short": "Generate rpc code",
"o": "Output a sample proto file",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"new": {
"short": "Generate rpc demo service",
"style": "{{.global.style}}",
"idea": "For idea plugin [optional]",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"verbose": "Enable log output"
},
"template": {
"short": "Generate proto template",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
},
"protoc": {
"short": "Generate grpc code",
"example": "goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.",
"multiple": "Generated in multiple rpc service mode",
"zrpc_out": "The zrpc output directory",
"style": "{{.global.style}}",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"verbose": "Enable log output"
}
},
"template": {
"short": "Template operation",
"home": "The goctl home path of the template",
"init": {
"short": "Initialize the all templates(force update)",
"home": "{{.goctl.template.home}}",
"category": "The category of template, enum [api,rpc,model,docker,kube]"
},
"clean": {
"short": "Clean the all cache templates",
"home": "{{.goctl.template.home}}"
},
"update": {
"short": "Update template of the target category to the latest",
"home": "{{.goctl.template.home}}",
"category": "{{.goctl.template.category}}"
},
"revert": {
"short": "Revert the target template to the latest",
"home": "{{.goctl.template.home}}",
"category": "{{.goctl.template.category}}",
"name": "The target file name of template"
}
},
"upgrade": {
"short": "Upgrade goctl to latest version"
}
},
"global": {
"home": "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority",
"remote": "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure",
"branch": "The branch of the remote repo, it does work with --remote",
"style": "The file naming format, see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]"
}
}

@ -0,0 +1,101 @@
package flags
import (
"bytes"
_ "embed"
"encoding/json"
"fmt"
"io"
"log"
"strings"
"testing"
"github.com/zeromicro/go-zero/tools/goctl/util"
)
//go:embed default_en.json
var defaultEnFlagConfig []byte
type ConfigLoader struct {
conf map[string]any
}
func (cl *ConfigLoader) ReadConfig(in io.Reader) error {
return json.NewDecoder(in).Decode(&cl.conf)
}
func (cl *ConfigLoader) GetString(key string) string {
keyList := strings.FieldsFunc(key, func(r rune) bool {
return r == '.'
})
var conf = cl.conf
for idx, k := range keyList {
val, ok := conf[k]
if !ok {
return ""
}
if idx < len(keyList)-1 {
conf, ok = val.(map[string]any)
if !ok {
return ""
}
continue
}
return fmt.Sprint(val)
}
return ""
}
type Flags struct {
loader *ConfigLoader
}
func MustLoad() *Flags {
loader := &ConfigLoader{
conf: map[string]any{},
}
if err := loader.ReadConfig(bytes.NewBuffer(defaultEnFlagConfig)); err != nil {
log.Fatal(err)
}
return &Flags{
loader: loader,
}
}
func setTestData(t *testing.T, data []byte) {
origin := defaultEnFlagConfig
defaultEnFlagConfig = data
t.Cleanup(func() {
defaultEnFlagConfig = origin
})
}
func (f *Flags) Get(key string) (string, error) {
value := f.loader.GetString(key)
for util.IsTemplateVariable(value) {
value = util.TemplateVariable(value)
if value == key {
return "", fmt.Errorf("the variable can not be self: %q", key)
}
return f.Get(value)
}
return value, nil
}
var flags *Flags
func Get(key string) string {
if flags == nil {
flags = MustLoad()
}
v, err := flags.Get(key)
if err != nil {
log.Fatal(err)
return ""
}
return v
}

@ -0,0 +1,78 @@
package flags
import (
"fmt"
"testing"
"github.com/zeromicro/go-zero/tools/goctl/test"
)
func TestFlags_Get(t *testing.T) {
setTestData(t, []byte(`{"host":"0.0.0.0","port":8888,"service":{"host":"{{.host}}","port":"{{.port}}","invalid":"{{.service.invalid}}"}}`))
f := MustLoad()
executor := test.NewExecutor[string, string]()
executor.Add([]test.Data[string, string]{
{
Name: "key_host",
Input: "host",
Want: "0.0.0.0",
},
{
Name: "key_port",
Input: "port",
Want: "8888",
},
{
Name: "key_service.host",
Input: "service.host",
Want: "0.0.0.0",
},
{
Name: "key_service.port",
Input: "service.port",
Want: "8888",
},
{
Name: "key_not_exists",
Input: "service.port.invalid",
},
{
Name: "key_service.invalid",
Input: "service.invalid",
E: fmt.Errorf("the variable can not be self: %q", "service.invalid"),
},
}...)
executor.RunE(t, f.Get)
}
func Test_Get(t *testing.T) {
setTestData(t, []byte(`{"host":"0.0.0.0","port":8888,"service":{"host":"{{.host}}","port":"{{.port}}","invalid":"{{.service.invalid}}"}}`))
executor := test.NewExecutor[string, string]()
executor.Add([]test.Data[string, string]{
{
Name: "key_host",
Input: "host",
Want: "0.0.0.0",
},
{
Name: "key_port",
Input: "port",
Want: "8888",
},
{
Name: "key_service.host",
Input: "service.host",
Want: "0.0.0.0",
},
{
Name: "key_service.port",
Input: "service.port",
Want: "8888",
},
{
Name: "key_not_exists",
Input: "service.port.invalid",
},
}...)
executor.Run(t, Get)
}

@ -1,6 +1,6 @@
package kube
import "github.com/spf13/cobra"
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var (
varStringName string
@ -26,50 +26,38 @@ var (
varStringImagePullPolicy string
// Cmd describes a kube command.
Cmd = &cobra.Command{
Use: "kube",
Short: "Generate kubernetes files",
}
deployCmd = &cobra.Command{
Use: "deploy",
Short: "Generate deployment yaml file",
RunE: deploymentCommand,
}
Cmd = cobrax.NewCommand("kube")
deployCmd = cobrax.NewCommand("deploy", cobrax.WithRunE(deploymentCommand))
)
func init() {
deployCmd.Flags().StringVar(&varStringName, "name", "", "The name of deployment (required)")
deployCmd.Flags().StringVar(&varStringNamespace, "namespace", "", "The namespace of deployment (required)")
deployCmd.Flags().StringVar(&varStringImage, "image", "", "The docker image of deployment (required)")
deployCmd.Flags().StringVar(&varStringSecret, "secret", "", "The secret to image pull from registry")
deployCmd.Flags().IntVar(&varIntRequestCpu, "requestCpu", 500, "The request cpu to deploy")
deployCmd.Flags().IntVar(&varIntRequestMem, "requestMem", 512, "The request memory to deploy")
deployCmd.Flags().IntVar(&varIntLimitCpu, "limitCpu", 1000, "The limit cpu to deploy")
deployCmd.Flags().IntVar(&varIntLimitMem, "limitMem", 1024, "The limit memory to deploy")
deployCmd.Flags().StringVar(&varStringO, "o", "", "The output yaml file (required)")
deployCmd.Flags().IntVar(&varIntReplicas, "replicas", 3, "The number of replicas to deploy")
deployCmd.Flags().IntVar(&varIntRevisions, "revisions", 5, "The number of revision history to limit")
deployCmd.Flags().IntVar(&varIntPort, "port", 0, "The port of the deployment to listen on pod (required)")
deployCmd.Flags().IntVar(&varIntNodePort, "nodePort", 0, "The nodePort of the deployment to expose")
deployCmd.Flags().IntVar(&varIntTargetPort, "targetPort", 0, "The targetPort of the deployment, default to port")
deployCmd.Flags().IntVar(&varIntMinReplicas, "minReplicas", 3, "The min replicas to deploy")
deployCmd.Flags().IntVar(&varIntMaxReplicas, "maxReplicas", 10, "The max replicas to deploy")
deployCmd.Flags().StringVar(&varStringImagePullPolicy, "imagePullPolicy", "", "Image pull policy. One of Always, Never, IfNotPresent")
deployCmdFlags := deployCmd.Flags()
deployCmdFlags.StringVar(&varStringName, "name")
deployCmdFlags.StringVar(&varStringNamespace, "namespace")
deployCmdFlags.StringVar(&varStringImage, "image")
deployCmdFlags.StringVar(&varStringSecret, "secret")
deployCmdFlags.IntVarWithDefaultValue(&varIntRequestCpu, "requestCpu", 500)
deployCmdFlags.IntVarWithDefaultValue(&varIntRequestMem, "requestMem", 512)
deployCmdFlags.IntVarWithDefaultValue(&varIntLimitCpu, "limitCpu", 1000)
deployCmdFlags.IntVarWithDefaultValue(&varIntLimitMem, "limitMem", 1024)
deployCmdFlags.StringVar(&varStringO, "o")
deployCmdFlags.IntVarWithDefaultValue(&varIntReplicas, "replicas", 3)
deployCmdFlags.IntVarWithDefaultValue(&varIntRevisions, "revisions", 5)
deployCmdFlags.IntVar(&varIntPort, "port")
deployCmdFlags.IntVar(&varIntNodePort, "nodePort")
deployCmdFlags.IntVar(&varIntTargetPort, "targetPort")
deployCmdFlags.IntVarWithDefaultValue(&varIntMinReplicas, "minReplicas", 3)
deployCmdFlags.IntVarWithDefaultValue(&varIntMaxReplicas, "maxReplicas", 10)
deployCmdFlags.StringVar(&varStringImagePullPolicy, "imagePullPolicy")
deployCmdFlags.StringVar(&varStringHome, "home")
deployCmdFlags.StringVar(&varStringRemote, "remote")
deployCmdFlags.StringVar(&varStringBranch, "branch")
deployCmdFlags.StringVar(&varStringServiceAccount, "serviceAccount")
deployCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template, "+
"--home and --remote cannot be set at the same time, if they are, --remote has higher priority")
deployCmd.Flags().StringVar(&varStringRemote, "remote", "", "The remote git repo of the template, "+
"--home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo "+
"directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
deployCmd.Flags().StringVar(&varStringBranch, "branch", "", "The branch of the remote repo, it "+
"does work with --remote")
deployCmd.Flags().StringVar(&varStringServiceAccount, "serviceAccount", "", "The ServiceAccount "+
"for the deployment")
deployCmd.MarkFlagRequired("name")
deployCmd.MarkFlagRequired("namespace")
deployCmd.MarkFlagRequired("o")
deployCmd.MarkFlagRequired("port")
_ = deployCmd.MarkFlagRequired("name")
_ = deployCmd.MarkFlagRequired("namespace")
_ = deployCmd.MarkFlagRequired("o")
_ = deployCmd.MarkFlagRequired("port")
Cmd.AddCommand(deployCmd)
}

@ -1,23 +1,16 @@
package migrate
import "github.com/spf13/cobra"
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var (
boolVarVerbose bool
stringVarVersion string
// Cmd describes a migrate command.
Cmd = &cobra.Command{
Use: "migrate",
Short: "Migrate from tal-tech to zeromicro",
Long: "Migrate is a transition command to help users migrate their " +
"projects from tal-tech to zeromicro version",
RunE: migrate,
}
Cmd = cobrax.NewCommand("migrate", cobrax.WithRunE(migrate))
)
func init() {
Cmd.Flags().BoolVarP(&boolVarVerbose, "verbose", "v",
false, "Verbose enables extra logging")
Cmd.Flags().StringVar(&stringVarVersion, "version", defaultMigrateVersion,
"The target release version of github.com/zeromicro/go-zero to migrate")
migrateCmdFlags := Cmd.Flags()
migrateCmdFlags.BoolVarP(&boolVarVerbose, "verbose", "v")
migrateCmdFlags.StringVarWithDefaultValue(&stringVarVersion, "version", defaultMigrateVersion)
}

@ -1,104 +1,75 @@
package model
import (
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/model/mongo"
"github.com/zeromicro/go-zero/tools/goctl/model/sql/command"
)
var (
// Cmd describes a model command.
Cmd = &cobra.Command{
Use: "model",
Short: "Generate model code",
}
mysqlCmd = &cobra.Command{
Use: "mysql",
Short: "Generate mysql model",
}
ddlCmd = &cobra.Command{
Use: "ddl",
Short: "Generate mysql model from ddl",
RunE: command.MysqlDDL,
}
datasourceCmd = &cobra.Command{
Use: "datasource",
Short: "Generate model from datasource",
RunE: command.MySqlDataSource,
}
pgCmd = &cobra.Command{
Use: "pg",
Short: "Generate postgresql model",
RunE: command.PostgreSqlDataSource,
}
pgDatasourceCmd = &cobra.Command{
Use: "datasource",
Short: "Generate model from datasource",
RunE: command.PostgreSqlDataSource,
}
mongoCmd = &cobra.Command{
Use: "mongo",
Short: "Generate mongo model",
RunE: mongo.Action,
}
Cmd = cobrax.NewCommand("model")
mysqlCmd = cobrax.NewCommand("mysql")
ddlCmd = cobrax.NewCommand("ddl", cobrax.WithRunE(command.MysqlDDL))
datasourceCmd = cobrax.NewCommand("datasource", cobrax.WithRunE(command.MySqlDataSource))
pgCmd = cobrax.NewCommand("pg", cobrax.WithRunE(command.PostgreSqlDataSource))
pgDatasourceCmd = cobrax.NewCommand("datasource", cobrax.WithRunE(command.PostgreSqlDataSource))
mongoCmd = cobrax.NewCommand("mongo", cobrax.WithRunE(mongo.Action))
)
func init() {
ddlCmd.Flags().StringVarP(&command.VarStringSrc, "src", "s", "", "The path or path globbing patterns of the ddl")
ddlCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir")
ddlCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
ddlCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]")
ddlCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]")
ddlCmd.Flags().StringVar(&command.VarStringDatabase, "database", "", "The name of database [optional]")
ddlCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
ddlCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
ddlCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
var (
ddlCmdFlags = ddlCmd.Flags()
datasourceCmdFlags = datasourceCmd.Flags()
pgDatasourceCmdFlags = pgDatasourceCmd.Flags()
mongoCmdFlags = mongoCmd.Flags()
)
ddlCmdFlags.StringVarP(&command.VarStringSrc, "src", "s")
ddlCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")
ddlCmdFlags.StringVar(&command.VarStringStyle, "style")
ddlCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
ddlCmdFlags.BoolVar(&command.VarBoolIdea, "idea")
ddlCmdFlags.StringVar(&command.VarStringDatabase, "database")
ddlCmdFlags.StringVar(&command.VarStringHome, "home")
ddlCmdFlags.StringVar(&command.VarStringRemote, "remote")
ddlCmdFlags.StringVar(&command.VarStringBranch, "branch")
datasourceCmd.Flags().StringVar(&command.VarStringURL, "url", "", `The data source of database,like "root:password@tcp(127.0.0.1:3306)/database"`)
datasourceCmd.Flags().StringSliceVarP(&command.VarStringSliceTable, "table", "t", nil, "The table or table globbing patterns in the database")
datasourceCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]")
datasourceCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir")
datasourceCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
datasourceCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]")
datasourceCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
datasourceCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
datasourceCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
datasourceCmdFlags.StringVar(&command.VarStringURL, "url")
datasourceCmdFlags.StringSliceVarP(&command.VarStringSliceTable, "table", "t")
datasourceCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
datasourceCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")
datasourceCmdFlags.StringVar(&command.VarStringStyle, "style")
datasourceCmdFlags.BoolVar(&command.VarBoolIdea, "idea")
datasourceCmdFlags.StringVar(&command.VarStringHome, "home")
datasourceCmdFlags.StringVar(&command.VarStringRemote, "remote")
datasourceCmdFlags.StringVar(&command.VarStringBranch, "branch")
pgDatasourceCmd.Flags().StringVar(&command.VarStringURL, "url", "", `The data source of database,like "postgres://root:password@127.0.0.1:5432/database?sslmode=disable"`)
pgDatasourceCmd.Flags().StringVarP(&command.VarStringTable, "table", "t", "", "The table or table globbing patterns in the database")
pgDatasourceCmd.Flags().StringVarP(&command.VarStringSchema, "schema", "s", "public", "The table schema")
pgDatasourceCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]")
pgDatasourceCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir")
pgDatasourceCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
pgDatasourceCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]")
pgDatasourceCmd.Flags().BoolVar(&command.VarBoolStrict, "strict", false, "Generate model in strict mode")
pgDatasourceCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
pgDatasourceCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
pgDatasourceCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
pgDatasourceCmdFlags.StringVar(&command.VarStringURL, "url")
pgDatasourceCmdFlags.StringVarP(&command.VarStringTable, "table", "t")
pgDatasourceCmdFlags.StringVarPWithDefaultValue(&command.VarStringSchema, "schema", "s", "public")
pgDatasourceCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
pgDatasourceCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")
pgDatasourceCmdFlags.StringVar(&command.VarStringStyle, "style")
pgDatasourceCmdFlags.BoolVar(&command.VarBoolIdea, "idea")
pgDatasourceCmdFlags.BoolVar(&command.VarBoolStrict, "strict")
pgDatasourceCmdFlags.StringVar(&command.VarStringHome, "home")
pgDatasourceCmdFlags.StringVar(&command.VarStringRemote, "remote")
pgDatasourceCmdFlags.StringVar(&command.VarStringBranch, "branch")
mongoCmd.Flags().StringSliceVarP(&mongo.VarStringSliceType, "type", "t", nil, "Specified model type name")
mongoCmd.Flags().BoolVarP(&mongo.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]")
mongoCmd.Flags().BoolVarP(&mongo.VarBoolEasy, "easy", "e", false, "Generate code with auto generated CollectionName for easy declare [optional]")
mongoCmd.Flags().StringVarP(&mongo.VarStringDir, "dir", "d", "", "The target dir")
mongoCmd.Flags().StringVar(&mongo.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
mongoCmd.Flags().StringVar(&mongo.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
mongoCmd.Flags().StringVar(&mongo.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
mongoCmd.Flags().StringVar(&mongo.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
mongoCmdFlags.StringSliceVarP(&mongo.VarStringSliceType, "type", "t")
mongoCmdFlags.BoolVarP(&mongo.VarBoolCache, "cache", "c")
mongoCmdFlags.BoolVarP(&mongo.VarBoolEasy, "easy", "e")
mongoCmdFlags.StringVarP(&mongo.VarStringDir, "dir", "d")
mongoCmdFlags.StringVar(&mongo.VarStringStyle, "style")
mongoCmdFlags.StringVar(&mongo.VarStringHome, "home")
mongoCmdFlags.StringVar(&mongo.VarStringRemote, "remote")
mongoCmdFlags.StringVar(&mongo.VarStringBranch, "branch")
mysqlCmd.PersistentFlags().BoolVar(&command.VarBoolStrict, "strict", false, "Generate model in strict mode")
mysqlCmd.PersistentFlags().StringSliceVarP(&command.VarStringSliceIgnoreColumns, "ignore-columns", "i", []string{"create_at", "created_at", "create_time", "update_at", "updated_at", "update_time"}, "Ignore columns while creating or updating rows")
mysqlCmd.PersistentFlags().BoolVar(&command.VarBoolStrict, "strict")
mysqlCmd.PersistentFlags().StringSliceVarPWithDefaultValue(&command.VarStringSliceIgnoreColumns, "ignore-columns", "i", []string{"create_at", "created_at", "create_time", "update_at", "updated_at", "update_time"})
mysqlCmd.AddCommand(datasourceCmd)
mysqlCmd.AddCommand(ddlCmd)
mysqlCmd.AddCommand(datasourceCmd, ddlCmd)
pgCmd.AddCommand(pgDatasourceCmd)
Cmd.AddCommand(mysqlCmd)
Cmd.AddCommand(mongoCmd)
Cmd.AddCommand(pgCmd)
Cmd.AddCommand(mysqlCmd, mongoCmd, pgCmd)
}

@ -62,6 +62,7 @@ func init() {
experimental := existsEnv.GetOr(GoctlExperimental, ExperimentalOff)
goctlEnv.SetKV(GoctlExperimental, experimental)
}
if !goctlEnv.HasKey(GoctlHome) {
goctlEnv.SetKV(GoctlHome, defaultGoctlHome)
}
@ -90,8 +91,20 @@ func init() {
goctlEnv.SetKV(ProtocGenGoGRPCVersion, protocGenGoGrpcVer)
}
func Print() string {
return strings.Join(goctlEnv.Format(), "\n")
func Print(args ...string) string {
if len(args) == 0 {
return strings.Join(goctlEnv.Format(), "\n")
}
var values []string
for _, key := range args {
value, ok := goctlEnv.GetString(key)
if !ok {
value = fmt.Sprintf("%s=%%not found%%", key)
}
values = append(values, fmt.Sprintf("%s=%s", key, value))
}
return strings.Join(values, "\n")
}
func Get(key string) string {

@ -1,6 +1,6 @@
package quickstart
import "github.com/spf13/cobra"
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
const (
serviceTypeMono = "mono"
@ -11,15 +11,9 @@ var (
varStringServiceType string
// Cmd describes the command to run.
Cmd = &cobra.Command{
Use: "quickstart",
Short: "quickly start a project",
RunE: run,
}
Cmd = cobrax.NewCommand("quickstart", cobrax.WithRunE(run))
)
func init() {
Cmd.Flags().StringVarP(&varStringServiceType,
"service-type", "t", "mono",
"specify the service type, supported values: [mono, micro]")
Cmd.Flags().StringVarPWithDefaultValue(&varStringServiceType, "service-type", "t", "mono")
}

@ -3,114 +3,70 @@ package rpc
import (
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/rpc/cli"
)
var (
// Cmd describes a rpc command.
Cmd = &cobra.Command{
Use: "rpc",
Short: "Generate rpc code",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.RPCTemplate(true)
},
}
Cmd = cobrax.NewCommand("rpc", cobrax.WithRunE(func(command *cobra.Command, strings []string) error {
return cli.RPCTemplate(true)
}))
templateCmd = cobrax.NewCommand("template", cobrax.WithRunE(func(command *cobra.Command, strings []string) error {
return cli.RPCTemplate(false)
}))
newCmd = &cobra.Command{
Use: "new",
Short: "Generate rpc demo service",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: cli.RPCNew,
}
templateCmd = &cobra.Command{
Use: "template",
Short: "Generate proto template",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.RPCTemplate(false)
},
}
protocCmd = &cobra.Command{
Use: "protoc",
Short: "Generate grpc code",
Example: "goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: cli.ZRPC,
}
newCmd = cobrax.NewCommand("new", cobrax.WithRunE(cli.RPCNew), cobrax.WithArgs(cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)))
protocCmd = cobrax.NewCommand("protoc", cobrax.WithRunE(cli.ZRPC), cobrax.WithArgs(cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)))
)
func init() {
Cmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file")
Cmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of "+
"the template, --home and --remote cannot be set at the same time, if they are, --remote has"+
" higher priority")
Cmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo"+
" of the template, --home and --remote cannot be set at the same time, if they are, --remote"+
" has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
Cmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the "+
"remote repo, it does work with --remote")
var (
rpcCmdFlags = Cmd.Flags()
newCmdFlags = newCmd.Flags()
protocCmdFlags = protocCmd.Flags()
templateCmdFlags = templateCmd.Flags()
)
rpcCmdFlags.StringVar(&cli.VarStringOutput, "o")
rpcCmdFlags.StringVar(&cli.VarStringHome, "home")
rpcCmdFlags.StringVar(&cli.VarStringRemote, "remote")
rpcCmdFlags.StringVar(&cli.VarStringBranch, "branch")
newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "")
newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "")
newCmd.Flags().StringVar(&cli.VarStringStyle, "style", config.DefaultFormat, "The file "+
"naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
newCmd.Flags().BoolVar(&cli.VarBoolIdea, "idea", false, "Whether the command "+
"execution environment is from idea plugin.")
newCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path "+
"of the template, --home and --remote cannot be set at the same time, if they are, --remote "+
"has higher priority")
newCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git "+
"repo of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
newCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "",
"The branch of the remote repo, it does work with --remote")
newCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output")
newCmd.Flags().MarkHidden("go_opt")
newCmd.Flags().MarkHidden("go-grpc_opt")
newCmdFlags.StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt")
newCmdFlags.StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt")
newCmdFlags.StringVarWithDefaultValue(&cli.VarStringStyle, "style", config.DefaultFormat)
newCmdFlags.BoolVar(&cli.VarBoolIdea, "idea")
newCmdFlags.StringVar(&cli.VarStringHome, "home")
newCmdFlags.StringVar(&cli.VarStringRemote, "remote")
newCmdFlags.StringVar(&cli.VarStringBranch, "branch")
newCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
newCmdFlags.MarkHidden("go_opt")
newCmdFlags.MarkHidden("go-grpc_opt")
protocCmd.Flags().BoolVarP(&cli.VarBoolMultiple, "multiple", "m", false,
"Generated in multiple rpc service mode")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOut, "go_out", nil, "")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOut, "go-grpc_out", nil, "")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "")
protocCmd.Flags().StringSliceVar(&cli.VarStringSlicePlugin, "plugin", nil, "")
protocCmd.Flags().StringSliceVarP(&cli.VarStringSliceProtoPath, "proto_path", "I", nil, "")
protocCmd.Flags().StringVar(&cli.VarStringZRPCOut, "zrpc_out", "", "The zrpc output directory")
protocCmd.Flags().StringVar(&cli.VarStringStyle, "style", config.DefaultFormat, "The file "+
"naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
protocCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home "+
"path of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority")
protocCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote "+
"git repo of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
protocCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "",
"The branch of the remote repo, it does work with --remote")
protocCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output")
protocCmd.Flags().MarkHidden("go_out")
protocCmd.Flags().MarkHidden("go-grpc_out")
protocCmd.Flags().MarkHidden("go_opt")
protocCmd.Flags().MarkHidden("go-grpc_opt")
protocCmd.Flags().MarkHidden("plugin")
protocCmd.Flags().MarkHidden("proto_path")
protocCmdFlags.BoolVarP(&cli.VarBoolMultiple, "multiple", "m")
protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoOut, "go_out")
protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoGRPCOut, "go-grpc_out")
protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt")
protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt")
protocCmdFlags.StringSliceVar(&cli.VarStringSlicePlugin, "plugin")
protocCmdFlags.StringSliceVarP(&cli.VarStringSliceProtoPath, "proto_path", "I")
protocCmdFlags.StringVar(&cli.VarStringZRPCOut, "zrpc_out")
protocCmdFlags.StringVar(&cli.VarStringHome, "home")
protocCmdFlags.StringVar(&cli.VarStringRemote, "remote")
protocCmdFlags.StringVar(&cli.VarStringBranch, "branch")
protocCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
protocCmdFlags.MarkHidden("go_out")
protocCmdFlags.MarkHidden("go-grpc_out")
protocCmdFlags.MarkHidden("go_opt")
protocCmdFlags.MarkHidden("go-grpc_opt")
protocCmdFlags.MarkHidden("plugin")
protocCmdFlags.MarkHidden("proto_path")
templateCmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file")
templateCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home"+
" path of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority")
templateCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote "+
"git repo of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
templateCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch"+
" of the remote repo, it does work with --remote")
templateCmdFlags.StringVar(&cli.VarStringOutput, "o")
templateCmdFlags.StringVar(&cli.VarStringHome, "home")
templateCmdFlags.StringVar(&cli.VarStringRemote, "remote")
templateCmdFlags.StringVar(&cli.VarStringBranch, "branch")
Cmd.AddCommand(newCmd)
Cmd.AddCommand(protocCmd)
Cmd.AddCommand(templateCmd)
Cmd.AddCommand(newCmd, protocCmd, templateCmd)
}

@ -0,0 +1,86 @@
package test
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
type Data[T, Y any] struct {
Name string
Input T
Want Y
E error
}
type Option[T, Y any] func(*Executor[T, Y])
type assertFn[Y any] func(t *testing.T, expected, actual Y) bool
func WithComparison[T, Y any](comparisonFn assertFn[Y]) Option[T, Y] {
return func(e *Executor[T, Y]) {
e.equalFn = comparisonFn
}
}
type Executor[T, Y any] struct {
list []Data[T, Y]
equalFn assertFn[Y]
}
func NewExecutor[T, Y any](opt ...Option[T, Y]) *Executor[T, Y] {
e := &Executor[T, Y]{}
opt = append(opt, WithComparison[T, Y](func(t *testing.T, expected, actual Y) bool {
gotBytes, err := json.Marshal(actual)
if err != nil {
t.Fatal(err)
return false
}
wantBytes, err := json.Marshal(expected)
if err != nil {
t.Fatal(err)
return false
}
return assert.JSONEq(t, string(wantBytes), string(gotBytes))
}))
for _, o := range opt {
o(e)
}
return e
}
func (e *Executor[T, Y]) Add(data ...Data[T, Y]) {
e.list = append(e.list, data...)
}
func (e *Executor[T, Y]) Run(t *testing.T, do func(T) Y) {
if do == nil {
panic("execution body is nil")
return
}
for _, v := range e.list {
t.Run(v.Name, func(t *testing.T) {
inner := do
e.equalFn(t, v.Want, inner(v.Input))
})
}
}
func (e *Executor[T, Y]) RunE(t *testing.T, do func(T) (Y, error)) {
if do == nil {
panic("execution body is nil")
return
}
for _, v := range e.list {
t.Run(v.Name, func(t *testing.T) {
inner := do
got, err := inner(v.Input)
if v.E != nil {
assert.Equal(t, v.E, err)
return
}
e.equalFn(t, v.Want, got)
})
}
}

@ -0,0 +1,101 @@
package test
import (
"errors"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestExecutor_Run(t *testing.T) {
executor := NewExecutor[string, string]()
executor.Add([]Data[string, string]{
{
Name: "empty",
},
{
Name: "snake_case",
input: "A_B_C",
want: "a_b_c",
},
{
Name: "camel_case",
input: "AaBbCc",
want: "aabbcc",
},
}...)
executor.Run(t, func(s string) string {
return strings.ToLower(s)
})
}
func TestExecutor_RunE(t *testing.T) {
var dummyError = errors.New("dummy error")
executor := NewExecutor[string, string]()
executor.Add([]Data[string, string]{
{
Name: "empty",
},
{
Name: "snake_case",
input: "A_B_C",
want: "a_b_c",
},
{
Name: "camel_case",
input: "AaBbCc",
want: "aabbcc",
},
{
Name: "invalid_input",
input: "😄",
E: dummyError,
},
}...)
executor.RunE(t, func(s string) (string, error) {
for _, r := range s {
if r == '_' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' {
continue
}
return "", dummyError
}
return strings.ToLower(s), nil
})
}
func TestWithComparison(t *testing.T) {
var dummyError = errors.New("dummy error")
executor := NewExecutor[string, string](WithComparison[string, string](func(t *testing.T, expected, actual string) bool {
return assert.Equal(t, expected, actual)
}))
executor.Add([]Data[string, string]{
{
Name: "empty",
},
{
Name: "snake_case",
input: "A_B_C",
want: "a_b_c",
},
{
Name: "camel_case",
input: "AaBbCc",
want: "aabbcc",
},
{
Name: "invalid_input",
input: "😄",
E: dummyError,
},
}...)
executor.RunE(t, func(s string) (string, error) {
for _, r := range s {
if r == '_' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' {
continue
}
return "", dummyError
}
return strings.ToLower(s), nil
})
}

@ -1,55 +1,27 @@
package tpl
import (
"github.com/spf13/cobra"
)
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var (
varStringHome string
varStringCategory string
varStringName string
// Cmd describes a template command.
Cmd = &cobra.Command{
Use: "template",
Short: "Template operation",
}
initCmd = &cobra.Command{
Use: "init",
Short: "Initialize the all templates(force update)",
RunE: genTemplates,
}
cleanCmd = &cobra.Command{
Use: "clean",
Short: "Clean the all cache templates",
RunE: cleanTemplates,
}
updateCmd = &cobra.Command{
Use: "update",
Short: "Update template of the target category to the latest",
RunE: updateTemplates,
}
revertCmd = &cobra.Command{
Use: "revert",
Short: "Revert the target template to the latest",
RunE: revertTemplates,
}
Cmd = cobrax.NewCommand("template")
initCmd = cobrax.NewCommand("init", cobrax.WithRunE(genTemplates))
cleanCmd = cobrax.NewCommand("clean", cobrax.WithRunE(cleanTemplates))
updateCmd = cobrax.NewCommand("update", cobrax.WithRunE(updateTemplates))
revertCmd = cobrax.NewCommand("revert", cobrax.WithRunE(revertTemplates))
)
func init() {
initCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template")
cleanCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template")
updateCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template")
updateCmd.Flags().StringVarP(&varStringCategory, "category", "c", "", "The category of template, enum [api,rpc,model,docker,kube]")
revertCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template")
revertCmd.Flags().StringVarP(&varStringCategory, "category", "c", "", "The category of template, enum [api,rpc,model,docker,kube]")
revertCmd.Flags().StringVarP(&varStringName, "name", "n", "", "The target file name of template")
Cmd.AddCommand(cleanCmd)
Cmd.AddCommand(initCmd)
Cmd.AddCommand(revertCmd)
Cmd.AddCommand(updateCmd)
initCmd.Flags().StringVar(&varStringHome, "home")
cleanCmd.Flags().StringVar(&varStringHome, "home")
updateCmd.Flags().StringVar(&varStringHome, "home")
updateCmd.Flags().StringVarP(&varStringCategory, "category", "c")
revertCmd.Flags().StringVar(&varStringHome, "home")
revertCmd.Flags().StringVarP(&varStringCategory, "category", "c")
revertCmd.Flags().StringVarP(&varStringName, "name", "n")
Cmd.AddCommand(cleanCmd, initCmd, revertCmd, updateCmd)
}

@ -11,6 +11,7 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/gogen"
apinew "github.com/zeromicro/go-zero/tools/goctl/api/new"
"github.com/zeromicro/go-zero/tools/goctl/docker"
"github.com/zeromicro/go-zero/tools/goctl/gateway"
"github.com/zeromicro/go-zero/tools/goctl/kube"
mongogen "github.com/zeromicro/go-zero/tools/goctl/model/mongo/generate"
modelgen "github.com/zeromicro/go-zero/tools/goctl/model/sql/gen"
@ -52,6 +53,9 @@ func genTemplates(_ *cobra.Command, _ []string) error {
func() error {
return apinew.GenTemplates()
},
func() error {
return gateway.GenTemplates()
},
); err != nil {
return err
}
@ -104,6 +108,9 @@ func cleanTemplates(_ *cobra.Command, _ []string) error {
func() error {
return apinew.Clean()
},
func() error {
return gateway.Clean()
},
)
if err != nil {
return err
@ -144,6 +151,8 @@ func updateTemplates(_ *cobra.Command, _ []string) (err error) {
return apigen.Update()
case apinew.Category():
return apinew.Update()
case gateway.Category():
return gateway.Update()
default:
err = fmt.Errorf("unexpected category: %s", category)
return
@ -181,6 +190,8 @@ func revertTemplates(_ *cobra.Command, _ []string) (err error) {
return apigen.RevertTemplate(filename)
case apinew.Category():
return apinew.RevertTemplate(filename)
case gateway.Category():
return gateway.RevertTemplate(filename)
default:
err = fmt.Errorf("unexpected category: %s", category)
return

@ -1,10 +1,6 @@
package upgrade
import "github.com/spf13/cobra"
import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
// Cmd describes an upgrade command.
var Cmd = &cobra.Command{
Use: "upgrade",
Short: "Upgrade goctl to latest version",
RunE: upgrade,
}
var Cmd = cobrax.NewCommand("upgrade", cobrax.WithRunE(upgrade))

@ -140,3 +140,15 @@ func ContainsAny(s string, runes ...rune) bool {
func ContainsWhiteSpace(s string) bool {
return ContainsAny(s, WhiteSpace...)
}
func IsWhiteSpace(text string) bool {
if len(text) == 0 {
return true
}
for _, r := range text {
if !unicode.IsSpace(r) {
return false
}
}
return true
}

@ -4,6 +4,7 @@ import (
"bytes"
goformat "go/format"
"io/ioutil"
"regexp"
"text/template"
"github.com/zeromicro/go-zero/tools/goctl/internal/errorx"
@ -77,3 +78,18 @@ func (t *DefaultTemplate) Execute(data any) (*bytes.Buffer, error) {
buf.Write(formatOutput)
return buf, nil
}
// IsTemplateVariable returns true if the text is a template variable.
// The text must start with a dot and be a valid template.
func IsTemplateVariable(text string) bool {
match, _ := regexp.MatchString(`(?m)^{{(\.\w+)+}}$`, text)
return match
}
// TemplateVariable returns the variable name of the template.
func TemplateVariable(text string) string {
if IsTemplateVariable(text) {
return text[3 : len(text)-2]
}
return ""
}

@ -0,0 +1,93 @@
package util
import (
"testing"
"github.com/zeromicro/go-zero/tools/goctl/test"
)
func TestIsTemplate(t *testing.T) {
executor := test.NewExecutor[string, bool]()
executor.Add([]test.Data[string, bool]{
{
Name: "empty",
Want: false,
},
{
Name: "invalid",
Input: "{foo}",
Want: false,
},
{
Name: "invalid",
Input: "{.foo}",
Want: false,
},
{
Name: "invalid",
Input: "$foo",
Want: false,
},
{
Name: "invalid",
Input: "{{foo}}",
Want: false,
},
{
Name: "invalid",
Input: "{{.}}",
Want: false,
},
{
Name: "valid",
Input: "{{.foo}}",
Want: true,
},
{
Name: "valid",
Input: "{{.foo.bar}}",
Want: true,
},
}...)
executor.Run(t, IsTemplateVariable)
}
func TestTemplateVariable(t *testing.T) {
executor := test.NewExecutor[string, string]()
executor.Add([]test.Data[string, string]{
{
Name: "empty",
},
{
Name: "invalid",
Input: "{foo}",
},
{
Name: "invalid",
Input: "{.foo}",
},
{
Name: "invalid",
Input: "$foo",
},
{
Name: "invalid",
Input: "{{foo}}",
},
{
Name: "invalid",
Input: "{{.}}",
},
{
Name: "valid",
Input: "{{.foo}}",
Want: "foo",
},
{
Name: "valid",
Input: "{{.foo.bar}}",
Want: "foo.bar",
},
}...)
executor.Run(t, TemplateVariable)
}
Loading…
Cancel
Save