github.com/ppphp/yayagf@v0.0.1/internal/file/file.go (about) 1 package file 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "regexp" 10 "strings" 11 12 "github.com/ppphp/yayagf/internal/blueprint" 13 "github.com/ppphp/yayagf/internal/command" 14 "github.com/ppphp/yayagf/internal/log" 15 "github.com/ppphp/yayagf/internal/swagger" 16 ) 17 18 var ErrNoRoot = errors.New("cannot find root") 19 20 func GetAppRoot() (string, error) { 21 pwd, err := os.Getwd() 22 if err != nil { 23 return "", err 24 } 25 return FindAppRoot(pwd) 26 } 27 28 // find dir contains go.mod 29 func FindAppRoot(path string) (string, error) { 30 if _, err := os.Open(filepath.Join(path, "go.mod")); os.IsNotExist(err) { 31 if path != "/" { 32 return FindAppRoot(filepath.Dir(path)) 33 } else { 34 return "", errors.New("no project, sb") 35 } 36 } else if err != nil { 37 return "", err 38 } else { 39 return path, nil 40 } 41 } 42 43 var goModRegexp = regexp.MustCompile("^module (.+)$") 44 45 // 不看源码了,internal没法直接import,意思意思得了 46 func GetMod(path string) (string, error) { 47 root, err := FindAppRoot(path) 48 if err != nil { 49 return "", err 50 } 51 file, err := ioutil.ReadFile(filepath.Join(root, "go.mod")) 52 if err != nil { 53 return "", err 54 } 55 for _, line := range strings.Split(string(file), "\n") { 56 if goModRegexp.MatchString(line) { 57 return goModRegexp.FindAllStringSubmatch(line, -1)[0][1], nil 58 } 59 } 60 return "", errors.New("no error") 61 } 62 63 type ProjectInfo struct { 64 // 项目根文件夹,全称 65 Root string 66 // 项目模块名 67 Mod string 68 // 项目bin的名称 69 BinName string 70 } 71 72 func GetProjectInfo() ProjectInfo { 73 root, _ := GetAppRoot() 74 mod, _ := GetMod(root) 75 return ProjectInfo{ 76 Root: root, 77 Mod: mod, 78 BinName: filepath.Base(root), 79 } 80 } 81 82 func ExtractMod(arg1 string) (string, string, string) { 83 namespace, name := filepath.Split(arg1) 84 mod := filepath.Join(namespace, name) 85 return mod, namespace, name 86 } 87 88 func InitProject(mod, dir, name string) (int, error) { 89 log.Printf("init project") 90 if err, o, e := command.DoCommand("go", "mod", "init", mod); err != nil { 91 log.Errorf("go mod failed %v %v\n", o, e) 92 return 1, err 93 } 94 95 log.Printf("create %v", filepath.Join(dir, "main.go")) 96 if err := blueprint.WriteFileWithTmpl(filepath.Join(dir, "main.go"), MainGo, struct{ Mod string }{mod}); err != nil { 97 log.Println(err.Error()) 98 return 1, err 99 } 100 log.Printf("create %v", filepath.Join(dir, "app", "router", "router.go")) 101 if err := blueprint.WriteFileWithTmpl(filepath.Join(dir, "app", "router", "router.go"), RouterGo, nil); err != nil { 102 log.Println(err.Error()) 103 return 1, err 104 } 105 106 if err := blueprint.WriteFileWithTmpl(filepath.Join(dir, "app", "config", "config.go"), ConfigGo, nil); err != nil { 107 log.Println(err.Error()) 108 return 1, err 109 } 110 if err := blueprint.WriteFileWithTmpl(filepath.Join(dir, "conf.toml"), fmt.Sprintf(` 111 db="" 112 port=8080 113 [log] 114 filename="./log/%v.log" 115 level=5 116 `, name), nil); err != nil { 117 log.Println(err.Error()) 118 return 1, err 119 } 120 121 log.Printf("init swagger") 122 root, err := GetAppRoot() 123 if err != nil { 124 return 1, err 125 } 126 if err := swagger.GenerateSwagger(root); err != nil { 127 log.Errorf("swag failed %v", err) 128 return 1, err 129 } 130 131 log.Printf("init git") 132 if err, _, errs := command.DoCommand("git", "init"); err != nil { 133 log.Errorf("git failed %v", errs) 134 return 1, err 135 } 136 if err := blueprint.WriteFileWithTmpl(filepath.Join(dir, ".gitignore"), ` 137 {{.Name}} 138 {{.Name}}.tar 139 *.log 140 `, struct{ Name string }{name}); err != nil { 141 log.Errorf("gitignore failed %v", err) 142 return 1, err 143 } 144 145 log.Printf("init docker") 146 if err := ioutil.WriteFile(filepath.Join(dir, "Dockerfile"), []byte(fmt.Sprintf(` 147 FROM golang as back 148 149 ENV GOPROXY=https://goproxy.io 150 ENV GOSUMDB=off 151 ENV GOPRIVATE=gitlab.papegames.com/* 152 ENV CGO_ENABLED=0 153 ENV GOOS=linux 154 ENV GOARCH=amd64 155 ENV GO111MODULE=on 156 157 WORKDIR /main 158 159 ADD go.mod ./ 160 ADD go.sum ./ 161 RUN go mod download 162 163 ADD app ./app/ 164 ADD main.go ./ 165 RUN go build -o /main/main 166 167 FROM scratch 168 WORKDIR /main 169 COPY --from=back /main/main . 170 171 CMD ["/main/main"] 172 173 `)), 0644); err != nil { 174 log.Errorf("docker failed %v", err) 175 return 1, err 176 } 177 178 if err := ioutil.WriteFile(filepath.Join(dir, "README.md"), []byte("\n"), 0644); err != nil { 179 log.Errorf("readme failed %v", err) 180 return 1, err 181 } 182 return 0, nil 183 } 184 185 const ( 186 MainGo = `package main 187 188 import ( 189 "fmt" 190 191 // {{.Mod}}/app/crud" 192 "github.com/ppphp/yayagf/pkg/handlers" 193 "github.com/ppphp/yayagf/pkg/log" 194 "github.com/ppphp/yayagf/pkg/maotai" 195 "github.com/ppphp/yayagf/pkg/model" 196 "github.com/ppphp/yayagf/pkg/prom" 197 "github.com/gin-gonic/gin" 198 "{{.Mod}}/app/config" 199 "{{.Mod}}/app/doc" 200 "{{.Mod}}/app/router" 201 ) 202 // @title "{{.Mod}} API 203 // @version master 204 // @description This is a {{.Mod}} server 205 206 // @contact.name 风车 207 // @contact.url https://{{.Mod}} 208 // @contact.email liukaiwen@papegames.net 209 210 // @host localhost:8080 211 // @BasePath /api/v1 212 213 func main() { 214 if err := config.LoadConfig(); err != nil { 215 log.Errorf("load config failed (%v)", err) 216 return 217 } 218 219 log.Tweak(config.GetConfig().Log) 220 gin.DefaultWriter = log.GetLogger().Out 221 r := maotai.Default("{{.Mod}}") 222 router.RegisterRouter(r) 223 224 drv, err := model.Open("mysql", config.GetConfig().DB) 225 if err != nil { 226 log.Errorf("create sql driver failed (%v)", err) 227 return 228 } 229 //crud.C = crud.NewClient(crud.Driver(drv)) 230 //if err := crud.C.Schema.Create(context.Background()); err != nil { 231 // log.Errorf(err) 232 // return 233 //} 234 handlers.MountALotOfThingToEndpoint(r.Group("admin"), 235 handlers.WithMetric(r.TTLHist, r.URLConn, 236 prom.SysCPU(), prom.SysMem(), prom.SysDisk(), prom.SysLoad(), prom.GoRoutine(), prom.GoMem(), 237 prom.DbConnection(config.GetConfig().DB, drv.DB()), prom.DBWaitCount(config.GetConfig().DB, drv.DB()), 238 prom.DBWaitDuration(config.GetConfig().DB, drv.DB()), prom.DbClose(config.GetConfig().DB, drv.DB()), 239 prom.BuildInfo()), 240 handlers.WithSwagger(doc.Swagger), 241 ) 242 243 if err := r.Run(fmt.Sprintf(":%v", config.GetConfig().Port)); err != nil { 244 log.Errorf("run app failed (%v)", err) 245 return 246 } 247 } 248 ` 249 250 RouterGo = `package router 251 252 import ( 253 "github.com/gin-contrib/cors" 254 "github.com/ppphp/yayagf/pkg/log" 255 "github.com/ppphp/yayagf/pkg/maotai" 256 "github.com/ppphp/yayagf/pkg/middleware" 257 ) 258 259 func RegisterRouter(r *maotai.MaoTai) { 260 r.Use(cors.Default()) 261 api := r.Group("/") 262 api.Use(middleware.Ginrus(log.GetLogger())) 263 264 } 265 ` 266 267 ConfigGo = `package config 268 269 import ( 270 "sync" 271 272 "github.com/ppphp/yayagf/pkg/config" 273 "github.com/ppphp/yayagf/pkg/log" 274 ) 275 276 var lock sync.RWMutex 277 278 type Config struct { 279 DB string 280 Port int 281 Log log.Config 282 } 283 284 var conf = new(Config) 285 286 // only support ini like config 287 func LoadConfig() error { 288 lock.Lock() 289 defer lock.Unlock() 290 if err := config.LoadConfig(conf); err != nil { 291 return err 292 } 293 294 log.Infof("%v", conf) 295 296 return nil 297 } 298 299 func GetConfig() Config { 300 lock.RLock() 301 defer lock.RUnlock() 302 return *conf 303 } 304 ` 305 )