193 lines
4.7 KiB
Go
193 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"math"
|
|
"net/http"
|
|
"os"
|
|
|
|
"gitea.antoine-langlois.net/${REPO_OWNER}/${REPO_NAME}/controllers"
|
|
"github.com/joho/godotenv"
|
|
"github.com/urfave/cli/v2"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
var app = &cli.App{
|
|
Name: "${REPO_NAME}",
|
|
Usage: "${REPO_DESCRIPTION}",
|
|
Version: "0.1.0",
|
|
Before: func(ctx *cli.Context) error {
|
|
dotenvFile := ".env"
|
|
if v := os.Getenv("${REPO_NAME_UPPER}_DOTENV"); v != "" {
|
|
dotenvFile = v
|
|
}
|
|
|
|
if err := godotenv.Overload(dotenvFile); err != nil && !os.IsNotExist(err) {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
},
|
|
Commands: []*cli.Command{
|
|
{
|
|
Name: "serve",
|
|
Usage: "Start the web server",
|
|
Flags: []cli.Flag{
|
|
&cli.UintFlag{
|
|
Name: "port",
|
|
Usage: "Port to listen on",
|
|
Category: "server",
|
|
Aliases: []string{"P"},
|
|
Value: 8080,
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_HTTP_PORT"},
|
|
Action: func(ctx *cli.Context, p uint) error {
|
|
if p > math.MaxUint16 {
|
|
return cli.Exit("Port number must be between 0 and 65535", 1)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "host",
|
|
Usage: "Host to listen on",
|
|
Category: "server",
|
|
Aliases: []string{"H"},
|
|
Value: "localhost",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_HTTP_HOST"},
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "log-level",
|
|
Usage: "Log verbosity level (debug, info, warn, error)",
|
|
Category: "logging",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_LOG_LEVEL"},
|
|
Value: "info",
|
|
Action: func(ctx *cli.Context, l string) error {
|
|
switch l {
|
|
case "debug", "info", "warn", "error":
|
|
return nil
|
|
default:
|
|
return cli.Exit("Log level must be one of debug, info, warn or error", 1)
|
|
}
|
|
},
|
|
},
|
|
&cli.PathFlag{
|
|
Name: "log-file",
|
|
Usage: "Log file",
|
|
Category: "logging",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_LOG_FILE"},
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "db-host",
|
|
Usage: "Database host",
|
|
Category: "database",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_DB_HOST"},
|
|
Value: "localhost",
|
|
},
|
|
&cli.UintFlag{
|
|
Name: "db-port",
|
|
Usage: "Database port",
|
|
Category: "database",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_DB_PORT"},
|
|
Value: 5432,
|
|
Action: func(ctx *cli.Context, p uint) error {
|
|
if p > math.MaxUint16 {
|
|
return cli.Exit("Port number must be between 0 and 65535", 1)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "db-user",
|
|
Usage: "Database user",
|
|
Category: "database",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_DB_USER"},
|
|
Value: "${REPO_NAME_LOWER}",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "db-password",
|
|
Usage: "Database password",
|
|
Category: "database",
|
|
EnvVars: []string{"${REPO_NAME_UPPER}_DB_PASSWORD"},
|
|
Value: "${REPO_NAME_LOWER}",
|
|
},
|
|
},
|
|
Action: func(ctx *cli.Context) error {
|
|
var logLevel slog.Level
|
|
switch ctx.String("log-level") {
|
|
case "debug":
|
|
logLevel = slog.LevelDebug
|
|
case "info":
|
|
logLevel = slog.LevelInfo
|
|
case "warn":
|
|
logLevel = slog.LevelWarn
|
|
case "error":
|
|
logLevel = slog.LevelError
|
|
default:
|
|
panic("invalid log level")
|
|
}
|
|
|
|
logWriter := os.Stdout
|
|
if logFile := ctx.Path("log-file"); logFile != "" {
|
|
var err error
|
|
logWriter, err = os.Open(ctx.Path("log-file"))
|
|
if err != nil {
|
|
return cli.Exit(err, 1)
|
|
}
|
|
}
|
|
defer logWriter.Close()
|
|
|
|
logger := slog.NewTextHandler(logWriter, &slog.HandlerOptions{
|
|
Level: logLevel,
|
|
})
|
|
|
|
_, err := openDB(
|
|
ctx.String("db-host"),
|
|
uint16(ctx.Uint("db-port")),
|
|
ctx.String("db-user"),
|
|
ctx.String("db-password"),
|
|
"${REPO_NAME_LOWER}",
|
|
)
|
|
if err != nil {
|
|
return cli.Exit(err, 1)
|
|
}
|
|
|
|
c, err := controllers.Register(logger, fmt.Sprintf("http://%s:%d", ctx.String("host"), ctx.Uint("port")))
|
|
if err != nil {
|
|
return cli.Exit(err, 1)
|
|
}
|
|
|
|
fmt.Printf("Server started at http://%s:%d\n", ctx.String("host"), ctx.Uint("port"))
|
|
addr := fmt.Sprintf("%s:%d", ctx.String("host"), ctx.Uint("port"))
|
|
return http.ListenAndServe(addr, c)
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
func main() {
|
|
if err := app.Run(os.Args); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
|
|
}
|
|
}
|
|
|
|
func openDB(
|
|
host string,
|
|
port uint16,
|
|
user, password, dbname string,
|
|
) (*gorm.DB, error) {
|
|
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Europe/Paris", host, user, password, dbname, port)
|
|
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return db, nil
|
|
}
|