gitea-page/internal/promote/promote.go

160 lines
3.8 KiB
Go

package promote
import (
"bytes"
"fmt"
"gitea-page/internal/config"
"github.com/rs/zerolog/log"
"html/template"
"os"
"os/exec"
"time"
)
type Promote struct {
Config config.GiteaPagesConfig
}
type PromoterData struct {
Config config.GiteaPagesConfig
Repo string
Owner string
Domain string
Path string
SSL struct{
Active bool
Cert string
Key string
}
}
func (p Promote) PromoteRepo(name, owner string) {
log.Debug().Str("name", name).Str("owner", owner).Msg("Promote")
url := p.getDefaultURL(name, owner)
log.Debug().Str("url", url).Msg("Promote URL")
content := p.getContent(name, owner, url)
updated := p.updateContent(url, content)
if updated {
p.reloadServer()
}
log.Debug().Bool("Need to Reload", updated).Msg("File Created")
}
func (p Promote) reloadServer() {
reload, err := exec.Command(p.Config.Promoter.Reload.Name, p.Config.Promoter.Reload.Args...).Output()
if err != nil {
log.Error().Err(err).Msg("Cant reload Server")
}
log.Debug().Str("output", string(reload)).Msg("Reloaded Server")
}
func (p Promote) getSSL(domain, path string) (cert, key string, active bool) {
if _, err := os.Stat(p.getCertPath(domain, "cer")); err == nil {
return p.getCertPath(domain, "cer"), p.getCertPath(domain, "key"), true
}
return "", "", false
}
func (p Promote) requestSSL(domain, path, name, owner string) {
log.Debug().Msg("Try to get SSL Zertifikat")
output, err := exec.Command("/root/.acme.sh/acme.sh", "--issue", "-d", domain, "-w", path).Output()
if err != nil {
log.Error().Str("output", string(output)).Err(err).Msg("Cant issue ssl certificat")
} else {
log.Info().Str("output", string(output)).Msg("Got SSL zertifikat")
p.PromoteRepo(name, owner)
}
}
func (p Promote) updateContent(domain, content string) bool {
fileName := fmt.Sprintf("%s/%s.conf", p.Config.Promoter.Path, domain)
log.Debug().Str("filename", fileName).Msg("Promote to File")
if _, err := os.Stat(fileName); err == nil {
c, _ := os.ReadFile(fileName)
if string(c) == content {
return false
}
}
os.WriteFile(fileName, []byte(content), 0644)
return true
}
func (p Promote) getContent(name, owner, domain string) string {
templateContent, err := os.ReadFile(p.Config.Promoter.Template)
if err != nil {
log.Panic().Err(err).Msg("Cant get promoter template")
}
var b bytes.Buffer
templ, err := template.New("").Parse(string(templateContent))
if err != nil {
log.Panic().Err(err).Msg("Cant parse Prmoter Template")
}
path := fmt.Sprintf("%s/%s/%s", p.Config.RootPath, owner, name)
promoterData := PromoterData{
Config: p.Config,
Repo: name,
Owner: owner,
Domain: domain,
Path: path,
}
cert, key, active := p.getSSL(domain, path)
promoterData.SSL.Active = active
promoterData.SSL.Cert = cert
promoterData.SSL.Key = key
err = templ.Execute(&b, promoterData)
if err != nil {
log.Panic().Err(err).Msg("Cant parse Promoter Template")
}
if active == false {
go func() {
time.Sleep(10*time.Second)
p.requestSSL(domain, path, name, owner)
}()
}
return b.String()
}
func (p Promote) getCertPath(domain, typ string) string {
var b bytes.Buffer
templ, err := template.New("").Parse(p.Config.Promoter.CertPath)
if err != nil {
log.Panic().Err(err).Msg("Cant parse Cert Path String")
}
err = templ.Execute(&b, map[string]interface{}{
"domain": domain,
"typ": typ,
})
if err != nil {
log.Panic().Err(err).Msg("Cant get cert path")
}
return b.String()
}
func (p Promote) getDefaultURL(name, owner string) string {
log.Debug().Str("domain", p.Config.Domain).Msg("get Default URL")
var b bytes.Buffer
templ, err := template.New("").Parse(p.Config.Domain)
if err != nil {
log.Panic().Err(err).Msg("Cant parse Config String")
}
err = templ.Execute(&b, map[string]interface{}{
"repro": name,
"owner": owner,
})
if err != nil {
log.Panic().Err(err).Msg("Cant get default URL")
}
return b.String()
}