2019-09-27 08:19:24 +02:00
|
|
|
package serv
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2019-09-28 17:34:03 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2019-09-27 08:19:24 +02:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
rice "github.com/GeertJohan/go.rice"
|
|
|
|
"github.com/spf13/cobra"
|
2019-09-28 17:34:03 +02:00
|
|
|
"github.com/valyala/fasttemplate"
|
2019-09-27 08:19:24 +02:00
|
|
|
)
|
|
|
|
|
2019-09-28 17:34:03 +02:00
|
|
|
func cmdNew(cmd *cobra.Command, args []string) {
|
2019-09-27 08:19:24 +02:00
|
|
|
if len(args) != 1 {
|
|
|
|
cmd.Help()
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpl := newTempl(map[string]string{
|
|
|
|
"app_name": strings.Title(strings.Join(args, " ")),
|
|
|
|
"app_name_slug": strings.ToLower(strings.Join(args, "_")),
|
|
|
|
})
|
|
|
|
|
|
|
|
// Create app folder and add relevant files
|
|
|
|
|
|
|
|
name := args[0]
|
|
|
|
appPath := path.Join("./", name)
|
|
|
|
|
|
|
|
ifNotExists(appPath, func(p string) error {
|
|
|
|
return os.Mkdir(p, os.ModePerm)
|
|
|
|
})
|
|
|
|
|
2019-09-28 17:34:03 +02:00
|
|
|
ifNotExists(path.Join(appPath, "Dockerfile"), func(p string) error {
|
|
|
|
if v, err := tmpl.get("Dockerfile"); err == nil {
|
2019-09-27 08:19:24 +02:00
|
|
|
return ioutil.WriteFile(p, v, 0644)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
ifNotExists(path.Join(appPath, "docker-compose.yml"), func(p string) error {
|
|
|
|
if v, err := tmpl.get("docker-compose.yml"); err == nil {
|
|
|
|
return ioutil.WriteFile(p, v, 0644)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Create app config folder and add relevant files
|
|
|
|
|
|
|
|
appConfigPath := path.Join(appPath, "config")
|
|
|
|
|
|
|
|
ifNotExists(appConfigPath, func(p string) error {
|
|
|
|
return os.Mkdir(p, os.ModePerm)
|
|
|
|
})
|
|
|
|
|
|
|
|
ifNotExists(path.Join(appConfigPath, "dev.yml"), func(p string) error {
|
|
|
|
if v, err := tmpl.get("dev.yml"); err == nil {
|
|
|
|
return ioutil.WriteFile(p, v, 0644)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
ifNotExists(path.Join(appConfigPath, "prod.yml"), func(p string) error {
|
|
|
|
if v, err := tmpl.get("prod.yml"); err == nil {
|
|
|
|
return ioutil.WriteFile(p, v, 0644)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-09-28 17:34:03 +02:00
|
|
|
ifNotExists(path.Join(appConfigPath, "seed.js"), func(p string) error {
|
|
|
|
if v, err := tmpl.get("docker-compose.yml"); err == nil {
|
|
|
|
return ioutil.WriteFile(p, v, 0644)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-09-27 08:19:24 +02:00
|
|
|
// Create app migrations folder and add relevant files
|
|
|
|
|
|
|
|
appMigrationsPath := path.Join(appConfigPath, "migrations")
|
|
|
|
|
|
|
|
ifNotExists(appMigrationsPath, func(p string) error {
|
|
|
|
return os.Mkdir(p, os.ModePerm)
|
|
|
|
})
|
|
|
|
|
|
|
|
ifNotExists(path.Join(appMigrationsPath, "100_init.sql"), func(p string) error {
|
|
|
|
if v, err := tmpl.get("100_init.sql"); err == nil {
|
|
|
|
return ioutil.WriteFile(p, v, 0644)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
logger.Info().Msgf("app '%s' initialized", name)
|
|
|
|
}
|
|
|
|
|
|
|
|
type Templ struct {
|
|
|
|
*rice.Box
|
|
|
|
data map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
func newTempl(data map[string]string) *Templ {
|
|
|
|
return &Templ{rice.MustFindBox("../tmpl"), data}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Templ) get(name string) ([]byte, error) {
|
|
|
|
v := t.MustString(name)
|
|
|
|
b := bytes.Buffer{}
|
2019-09-28 17:34:03 +02:00
|
|
|
tmpl := fasttemplate.New(v, "{%", "%}")
|
2019-09-27 08:19:24 +02:00
|
|
|
|
2019-09-28 17:34:03 +02:00
|
|
|
tmpl.ExecuteFunc(&b, func(w io.Writer, tag string) (int, error) {
|
|
|
|
if val, ok := t.data[strings.TrimSpace(tag)]; ok {
|
|
|
|
return w.Write([]byte(val))
|
|
|
|
}
|
|
|
|
return 0, fmt.Errorf("unknown template variable '%s'", tag)
|
|
|
|
})
|
2019-09-27 08:19:24 +02:00
|
|
|
|
|
|
|
return b.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ifNotExists(filePath string, doFn func(string) error) {
|
|
|
|
_, err := os.Stat(filePath)
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
logger.Info().Err(err).Msgf("create skipped '%s' exists", filePath)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if os.IsNotExist(err) == false {
|
|
|
|
logger.Fatal().Err(err).Msgf("unable to check if '%s' exists", filePath)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = doFn(filePath)
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatal().Err(err).Msgf("unable to create '%s'", filePath)
|
|
|
|
}
|
|
|
|
logger.Info().Msgf("created '%s'", filePath)
|
|
|
|
}
|