hoster/cmd/hoster_cli/commands/new.go

118 lines
2.6 KiB
Go
Raw Normal View History

package commands
import (
"fmt"
"hoster/internals/conf"
"hoster/internals/helpers"
"hoster/internals/templates"
"hoster/internals/types"
"os"
"path/filepath"
"slices"
"github.com/gookit/goutil/fsutil"
"github.com/gookit/goutil/sysutil/cmdr"
"github.com/kataras/golog"
"github.com/urfave/cli/v2"
)
func CmdNew(c *cli.Context) error {
name := c.String("name")
domain := c.String("domain")
projectRoot := conf.App.MustString("projects.root")
sitesAvail := conf.App.MustString("nginx.sitesAvailable")
sitesEnabled := conf.App.MustString("nginx.sitesEnabled")
nginxFile := filepath.Join(sitesAvail, name)
projectFolder := filepath.Join(projectRoot, name)
existingProjects, err := helpers.FindHostConfigs(sitesAvail)
if err != nil {
return err
}
usedPorts := []int{}
for _, project := range existingProjects {
usedPorts = append(usedPorts, project.InternalPort)
}
port := conf.App.Int("nginx.portRangeStart")
freePort := 0
for port <= conf.App.Int("nginx.portRangeEnd") {
if !slices.Contains(usedPorts, port) && helpers.IsFreePort(port) {
freePort = port
break
}
port++
}
if freePort == 0 {
return fmt.Errorf("no free port available")
}
if !fsutil.IsDir(projectFolder) {
golog.Infof("Creating project folder '%s'", projectFolder)
err := os.MkdirAll(projectFolder, 0755)
if err != nil {
return err
}
}
if fsutil.IsFile(nginxFile) {
return fmt.Errorf("the nginx config file '%s' already exists", nginxFile)
}
// Set owner and group of project folder
err = os.Chown(projectFolder, conf.App.Int("projects.owner"), conf.App.Int("projects.group"))
if err != nil {
return err
}
project := types.Project{
Name: name,
Domain: domain,
InternalPort: freePort,
}
// Create nginx config file
err = templates.Execute("nginx", nginxFile, project)
if err != nil {
return err
}
// Symlink nginx config file
err = os.Symlink(nginxFile, filepath.Join(sitesEnabled, name))
if err != nil {
return err
}
// Execute certbot command: "systemctl stop nginx && sudo certbot certonly --standalone --preferred-challenges http -d {domain} && sudo systemctl start nginx"
com := cmdr.NewCmd("systemctl").
WithArgs([]string{"stop", "nginx"})
_, err = com.Output()
if err != nil {
return err
}
com = cmdr.NewCmd("certbot").
WithArgs([]string{"certonly", "--standalone", "--preferred-challenges", "http", "-d", domain})
_, err = com.Output()
if err != nil {
return err
}
com = cmdr.NewCmd("systemctl").
WithArgs([]string{"start", "nginx"})
_, err = com.Output()
if err != nil {
return err
}
golog.Infof("Project successfully '%s' created. Uses port %d.", name, freePort)
return nil
}