2022-03-26 13:23:39 +05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2022-03-28 20:35:55 +05:00
|
|
|
_ "embed"
|
2022-03-26 13:23:39 +05:00
|
|
|
"fmt"
|
2022-03-30 21:06:55 +05:00
|
|
|
"io/fs"
|
2022-03-27 13:12:36 +05:00
|
|
|
"net"
|
2022-03-26 13:23:39 +05:00
|
|
|
"net/http"
|
2022-03-26 16:44:46 +05:00
|
|
|
"os"
|
2022-03-26 13:23:39 +05:00
|
|
|
"time"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
func httpServer(listenAddress string) {
|
2022-03-27 12:39:24 +05:00
|
|
|
if listenAddress == "none" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-03-26 13:23:39 +05:00
|
|
|
http.HandleFunc("/", handler)
|
2022-03-26 20:20:00 +05:00
|
|
|
http.HandleFunc("/reloadJobs", handleReloadJobs)
|
2022-03-26 16:44:46 +05:00
|
|
|
http.HandleFunc("/shutdown", handleShutdown)
|
2022-03-26 13:23:39 +05:00
|
|
|
http.HandleFunc("/start", handleForceStart)
|
2022-03-30 21:06:55 +05:00
|
|
|
http.HandleFunc("/details", handleDetails)
|
2022-03-26 13:23:39 +05:00
|
|
|
log.WithField("job", "http_server").Fatal(http.ListenAndServe(listenAddress, nil))
|
|
|
|
}
|
|
|
|
|
|
|
|
func handler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if r.RequestURI != "/" {
|
2022-03-30 21:06:55 +05:00
|
|
|
fs, err := fs.Sub(siteFS, "webui")
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
http.FileServer(http.FS(fs)).ServeHTTP(w, r)
|
2022-03-26 13:23:39 +05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-03-26 20:20:00 +05:00
|
|
|
globalMutex.RLock()
|
2022-03-26 13:23:39 +05:00
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
jobEntries := c.Entries()
|
|
|
|
var jobs []*Job
|
2022-03-28 19:55:43 +05:00
|
|
|
for _, jobEntry := range jobEntries {
|
|
|
|
job := jobEntry.Job.(*Job)
|
|
|
|
job.NextLaunch = jobEntry.Next.Format(config.TimeFormat)
|
|
|
|
jobs = append(jobs, job)
|
2022-03-26 13:23:39 +05:00
|
|
|
}
|
2022-03-30 21:06:55 +05:00
|
|
|
templates.ExecuteTemplate(buf, "index.htm", jobs)
|
2022-03-26 20:20:00 +05:00
|
|
|
globalMutex.RUnlock()
|
2022-03-26 13:23:39 +05:00
|
|
|
|
|
|
|
buf.WriteTo(w)
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleForceStart(w http.ResponseWriter, r *http.Request) {
|
|
|
|
jobName := r.FormValue("jobName")
|
|
|
|
if jobName == "" {
|
|
|
|
http.Error(w, "job name is not specified", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
jobEntries := c.Entries()
|
|
|
|
|
|
|
|
for _, jobEntry := range jobEntries {
|
|
|
|
job := jobEntry.Job.(*Job)
|
2022-03-29 19:45:31 +05:00
|
|
|
if job.Name == jobName {
|
2022-03-27 13:12:36 +05:00
|
|
|
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
|
|
|
if err != nil {
|
|
|
|
host = r.RemoteAddr
|
|
|
|
}
|
2022-03-29 21:27:29 +05:00
|
|
|
log.WithField("job", "http_server").Printf("Forced start %s from %s.", job.Name, host)
|
2022-03-26 13:23:39 +05:00
|
|
|
go job.Run()
|
|
|
|
time.Sleep(time.Second / 4) // wait some time for job start
|
|
|
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
http.Error(w, fmt.Sprintf("there is no job with name %s", jobName), http.StatusBadRequest)
|
|
|
|
}
|
2022-03-26 16:44:46 +05:00
|
|
|
|
|
|
|
func handleShutdown(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
w.Write([]byte("Application terminated.\n"))
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
log.WithField("job", "http_server").Infoln("Shutdown requested")
|
|
|
|
os.Exit(0)
|
|
|
|
}()
|
|
|
|
}
|
2022-03-26 20:20:00 +05:00
|
|
|
|
|
|
|
func handleReloadJobs(w http.ResponseWriter, r *http.Request) {
|
|
|
|
globalMutex.Lock()
|
|
|
|
defer globalMutex.Unlock()
|
|
|
|
|
|
|
|
c.Stop()
|
|
|
|
|
|
|
|
for _, entry := range c.Entries() {
|
|
|
|
c.Remove(entry.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
err := initJobs()
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, fmt.Sprintf("reload jobs error: %v", err), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Start()
|
|
|
|
|
|
|
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
|
|
|
}
|
2022-03-28 20:35:55 +05:00
|
|
|
|
2022-03-30 21:06:55 +05:00
|
|
|
func handleDetails(w http.ResponseWriter, r *http.Request) {
|
|
|
|
jobName := r.FormValue("jobName")
|
|
|
|
if jobName == "" {
|
|
|
|
http.Error(w, "job name is not specified", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
jobEntries := c.Entries()
|
|
|
|
|
|
|
|
for _, jobEntry := range jobEntries {
|
|
|
|
job := jobEntry.Job.(*Job)
|
|
|
|
if job.Name == jobName {
|
|
|
|
err := templates.ExecuteTemplate(w, "details.htm", job)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
http.Error(w, fmt.Sprintf("there is no job with name %s", jobName), http.StatusBadRequest)
|
2022-03-28 20:35:55 +05:00
|
|
|
}
|