feat: api 完成

master v0.0.1
icechen 2022-01-06 22:32:03 +08:00
parent 4bfb639866
commit fb2fddba93
10 changed files with 232 additions and 97 deletions

48
api.go
View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"git.icechen.cn/pkg/wdt/util"
"os"
"git.icechen.cn/pkg/wdt/template/api/deploy"
@ -45,24 +46,56 @@ func ActionNewApi(c *cli.Context) error {
appList := c.Args().Slice()
if len(appList) == 0 {
appName := ReadLineWithMessage("请输入要创建的api名称: ")
appName := ""
for {
appName = util.ReadLineWithMessage("请输入要创建的api名称: ")
if appName != "" {
break
} else {
color.Red("应用名称不能为空!")
}
}
appList = append(appList, appName)
}
for _, newApp := range appList {
color.Green("正在创建[%s]API应用...", newApp)
app := config.Api.GetApp(newApp)
app = Api{
Name: newApp,
Root: "app/api/" + newApp,
}
if ExistDir("app/api/"+newApp) && !ReadBoolWithMessage("app/api/"+newApp+"目录已存在,是否要覆盖app文件目录(y/n): ") {
if util.ExistDir(app.Root) && !util.ReadBoolWithMessage(app.Root+"目录已存在,是否要覆盖app文件目录(y/n): ") {
return nil
}
err := os.MkdirAll("app/api/"+newApp, os.ModePerm)
err := os.MkdirAll(app.Root, os.ModePerm)
if err != nil {
return err
}
aliasName := ReadLineWithMessage("请输入应用的简短描述(别名): ")
app.AliasName = util.ReadLineWithMessage("请输入应用的简短描述(别名): ")
for {
app.Type = util.ReadLineWithMessage("请输入应用的类型(默认golang): ")
if app.Type == "golang" || app.Type == "" {
app.Type = "golang"
break
} else {
color.Red("暂不支持: [%s]类型", app.Type)
}
}
for {
app.Port = util.ReadLineWithMessage("请输入应用暴露的端口: ")
if app.Port != "" {
break
} else {
color.Red("端口号不能为空!")
}
}
app.Host = util.ReadLineWithMessage("请输入API应用请求的域名(host,如:api.seamlesser.com,建议为空): ")
app.Path = util.ReadLineWithMessage("请输入API应用请求的路由(path,如:/uwe/core/?(.*),建议为空): ")
err = deploy.GenDeploy(config.Name, newApp, aliasName)
err = deploy.GenDeploy(config.Name, newApp, app.AliasName)
if err != nil {
return err
}
@ -72,6 +105,11 @@ func ActionNewApi(c *cli.Context) error {
return err
}
err = config.AppendAPI(app)
if err != nil {
return err
}
color.Green("[%s]API应用创建成功!!!\n\n", newApp)
}
return nil

View File

@ -1,6 +1,7 @@
package main
import (
"git.icechen.cn/pkg/wdt/util"
"io/ioutil"
"github.com/urfave/cli/v2"
@ -41,22 +42,24 @@ type Config struct {
type (
ApiList []Api
Api struct {
Name string `json:"name" yaml:"name"`
Root string `json:"root" yaml:"root"`
Type string `json:"type" yaml:"type"`
Port string `json:"port" yaml:"port"`
Host string `json:"host,omitempty" yaml:"host,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Name string `json:"name" yaml:"name"`
AliasName string `json:"alias_name" yaml:"aliasName"`
Root string `json:"root" yaml:"root"`
Type string `json:"type" yaml:"type"`
Port string `json:"port" yaml:"port"`
Host string `json:"host,omitempty" yaml:"host,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
}
)
type (
ServiceList []Service
Service struct {
Name string `json:"name" yaml:"name"`
Root string `json:"root" yaml:"root"`
Type string `json:"type" yaml:"type"`
Port string `json:"port" yaml:"port"`
Name string `json:"name" yaml:"name"`
AliasName string `json:"alias_name" yaml:"aliasName"`
Root string `json:"root" yaml:"root"`
Type string `json:"type" yaml:"type"`
Port string `json:"port" yaml:"port"`
}
)
@ -74,15 +77,59 @@ func ReadConfig() error {
return nil
}
func (al ApiList) HasApp(appNameList []string) ApiList {
if len(appNameList) == 0 {
return al
func (c *Config) AppendAPI(api Api) error {
has := false
for i, a := range c.Api {
if a.Name == api.Name {
c.Api[i] = api
has = true
break
}
}
hasApp := make(ApiList, 0, len(al))
if !has {
c.Api = append(c.Api, api)
}
out, err := yaml.Marshal(c)
if err != nil {
return err
}
return util.WriteFileWithNotEdit(DefaultConfigFile, out)
}
func (c *Config) AppendService(service Service) error {
has := false
for i, s := range c.Service {
if s.Name == service.Name {
c.Service[i] = service
has = true
break
}
}
if !has {
c.Service = append(c.Service, service)
}
out, err := yaml.Marshal(c)
if err != nil {
return err
}
return util.WriteFileWithNotEdit(DefaultConfigFile, out)
}
func (sl ApiList) HasApp(appNameList []string) ApiList {
if len(appNameList) == 0 {
return sl
}
hasApp := make(ApiList, 0, len(sl))
al:
for _, api := range al {
for _, api := range sl {
for _, a := range appNameList {
if a == api.Name {
hasApp = append(hasApp, api)
@ -93,6 +140,15 @@ al:
return hasApp
}
func (sl ApiList) GetApp(appName string) Api {
for _, api := range sl {
if api.Name == appName {
return api
}
}
return Api{}
}
func (sl ServiceList) HasApp(appNameList []string) ServiceList {
if len(appNameList) == 0 {
return sl
@ -111,3 +167,12 @@ sl:
}
return hasApp
}
func (sl ServiceList) GetApp(appName string) Service {
for _, service := range sl {
if service.Name == appName {
return service
}
}
return Service{}
}

5
go.mod
View File

@ -3,21 +3,20 @@ module git.icechen.cn/pkg/wdt
go 1.17
require (
github.com/drone/drone-go v1.7.1
github.com/fatih/color v1.13.0
github.com/urfave/cli/v2 v2.3.0
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
require (
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/drone/drone-go v1.7.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect

12
go.sum
View File

@ -91,6 +91,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -110,10 +111,11 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
@ -126,7 +128,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -244,16 +245,19 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -300,6 +304,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@ -381,6 +386,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -2,7 +2,7 @@ package main
import (
"bytes"
"os"
"git.icechen.cn/pkg/wdt/util"
)
type healthResp struct {
@ -22,13 +22,13 @@ func (hr healthResp) String() string {
b := bytes.Buffer{}
if !hr.Dir {
b.WriteString("\t\t应用目录:\t不存在")
b.WriteString("\t\t应用目录:\t不存在\n")
}
if !hr.Deploy {
b.WriteString("\t\t部署文件:\t不存在")
b.WriteString("\t\t部署文件(deploy):\t不存在\n")
}
if !hr.Dockerfile {
b.WriteString("\t\t构建文件:\t不存在")
b.WriteString("\t\t构建文件(Dockerfile):\t不存在\n")
}
return b.String()
}
@ -41,20 +41,17 @@ func healthApi(api Api) healthResp {
}
// Dir 健康度
info, err := os.Stat(api.Root)
if err == nil && info.IsDir() {
if util.ExistDir(api.Root) {
ret.Dir = true
}
// Deploy 健康度
info, err = os.Stat(api.Root + "/deploy")
if err == nil && info.IsDir() {
if util.ExistDir(api.Root + "/deploy") {
ret.Deploy = true
}
// Dockerfile 健康度
info, err = os.Stat(api.Root + "/Dockerfile")
if err == nil && !info.IsDir() {
if util.ExistFile(api.Root + "/Dockerfile") {
ret.Dockerfile = true
}

View File

@ -11,7 +11,14 @@ import (
//go:embed "Dockerfile.tpl"
var dockerfileTemplate string
//go:embed "main.tpl"
var mainGoTemplate string
func GenDockerfile(name string) error {
color.Green("正在生成dockerfile...")
return util.TemplateToFile("app/api/"+name+"/Dockerfile", dockerfileTemplate, map[string]string{"Name": name})
err := util.TemplateToFile("app/api/"+name+"/Dockerfile", dockerfileTemplate, map[string]string{"Name": name})
if err != nil {
return err
}
return util.TemplateToFile("app/api/"+name+"/main.go", mainGoTemplate, nil)
}

View File

@ -0,0 +1,7 @@
package main
import "fmt"
func main() {
fmt.Println("我是个示例")
}

60
util.go
View File

@ -1,61 +1 @@
package main
import (
"bufio"
"fmt"
"os"
"strings"
"github.com/fatih/color"
)
func ReadBool() bool {
read := bufio.NewReader(os.Stdin)
ret, _ := read.ReadByte()
switch ret {
case 'y':
fallthrough
case 'Y':
return true
case 'n':
fallthrough
case 'N':
return false
}
return false
}
func ReadBoolWithMessage(message string) bool {
NoNewLinePrint(color.HiRedString, message)
return ReadBool()
}
func ReadLine() string {
read := bufio.NewReader(os.Stdin)
s, _ := read.ReadString('\n')
return s
}
func ReadLineWithMessage(message string) string {
NoNewLinePrint(color.HiRedString, message)
return ReadLine()
}
// ExistFile 文件是否存在
func ExistFile(filePath string) bool {
info, err := os.Stat(filePath)
return err == nil && !info.IsDir()
}
// ExistDir 目录是否存在
func ExistDir(dirPath string) bool {
info, err := os.Stat(dirPath)
return err == nil && info.IsDir()
}
func NoNewLinePrint(f func(format string, a ...interface{}) string, message string) {
if strings.HasSuffix(message, "\n") {
message = message[:len(message)-1]
}
fmt.Printf(f(message))
}

48
util/common.go 100644
View File

@ -0,0 +1,48 @@
package util
import (
"bufio"
"fmt"
"github.com/fatih/color"
"os"
"strings"
)
func ReadBool() bool {
read := bufio.NewReader(os.Stdin)
ret, _ := read.ReadByte()
switch ret {
case 'y':
fallthrough
case 'Y':
return true
case 'n':
fallthrough
case 'N':
return false
}
return false
}
func ReadBoolWithMessage(message string) bool {
NoNewLinePrint(color.HiRedString, message)
return ReadBool()
}
func ReadLine() string {
read := bufio.NewReader(os.Stdin)
s, _ := read.ReadString('\n')
return s[:len(s)-1]
}
func ReadLineWithMessage(message string) string {
NoNewLinePrint(color.HiRedString, message)
return ReadLine()
}
func NoNewLinePrint(f func(format string, a ...interface{}) string, message string) {
if strings.HasSuffix(message, "\n") {
message = message[:len(message)-1]
}
fmt.Printf(f(message))
}

View File

@ -31,3 +31,31 @@ func TemplateToFile(desFile string, templateContent string, data interface{}) er
}
return nil
}
func WriteFile(filePath string, data []byte) error {
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(data)
return err
}
func WriteFileWithNotEdit(filePath string, data []byte) error {
notEdit := "# Code generated by wujian-develop_tool. DO NOT EDIT.\n\n"
return WriteFile(filePath, []byte(notEdit+string(data)))
}
// ExistFile 文件是否存在
func ExistFile(filePath string) bool {
info, err := os.Stat(filePath)
return err == nil && !info.IsDir()
}
// ExistDir 目录是否存在
func ExistDir(dirPath string) bool {
info, err := os.Stat(dirPath)
return err == nil && info.IsDir()
}