Skip to content

Commit cc67603

Browse files
authored
Merge pull request #2 from Huskydog9988/http-support
2 parents 4097379 + 9e2e02d commit cc67603

File tree

4 files changed

+126
-6
lines changed

4 files changed

+126
-6
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ config:
1414
# optional: allows you to specify the max number of jobs to run at once
1515
jobLimit: 1
1616

17+
# optional: allows you start an http server and trigger jobs via an api
18+
httpServer:
19+
enabled: true
20+
1721
jobs:
1822
# job name
1923
testRegex:
@@ -58,3 +62,19 @@ docker run --rm -it -v "$PWD:$PWD" -w "$PWD" ghcr.io/huskydog9988/docker-db-back
5862
```
5963

6064
The script will then dump the databases to the `out` folder, and continue to run every 5 minutes because of the cron option.
65+
66+
## API
67+
68+
> This feature requires the `httpServer` option to be enabled in the config file
69+
70+
The script can also start an http server and trigger jobs via an api. This is useful if you want to trigger a job elsewhere, like from another backup service.
71+
72+
To trigger a job, send a GET request to `http://localhost:3333/api/v1/queueJob?jobName=JOB_NAME`.
73+
74+
Example using the example config file:
75+
76+
```bash
77+
curl http://localhost:3333/api/v1/queueJob?jobName=testRegex
78+
```
79+
80+
The server will respond with a 200 status code **after** the job has finished running. Currently, there is no way to check if the job has failed or not.

config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ config:
55
# optional: allows you to specify the max number of jobs to run at once
66
jobLimit: 1
77

8+
# optional: allows you start an http server and trigger jobs via an api
9+
httpServer:
10+
enabled: true
11+
812
jobs:
913
testRegex:
1014
# Database type: postgres, mysql, mariadb

http.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/rotisserie/eris"
7+
log "github.com/sirupsen/logrus"
8+
)
9+
10+
var keyServerAddr = "serverAddr"
11+
12+
// handle any unknown requests
13+
func getRoot(w http.ResponseWriter, r *http.Request) {
14+
w.WriteHeader(http.StatusNotFound)
15+
w.Write([]byte("Not found\n"))
16+
}
17+
18+
// start the http server
19+
// handles if the http server is enabled or not
20+
func startHttpServer(httpServer *http.Server, backup *Backup) {
21+
// if the http server is not defined or disabled, return
22+
if !k.Exists("config.httpServer.enabled") {
23+
return
24+
} else if !k.Bool("config.httpServer.enabled") {
25+
return
26+
}
27+
28+
log.Infof("Starting http server")
29+
30+
mux := http.NewServeMux()
31+
httpServer.Handler = mux
32+
33+
mux.HandleFunc("/", getRoot)
34+
mux.HandleFunc("/api/v1/queueJob", func(w http.ResponseWriter, r *http.Request) {
35+
// get the job name
36+
jobName := r.URL.Query().Get("jobName")
37+
if jobName == "" {
38+
w.WriteHeader(http.StatusBadRequest)
39+
w.Write([]byte("jobName is required\n"))
40+
return
41+
}
42+
43+
// get the job config
44+
jobConfig, err := getJobConfig(jobName)
45+
if err != nil {
46+
w.WriteHeader(http.StatusBadRequest)
47+
w.Write([]byte(err.Error() + "\n"))
48+
return
49+
}
50+
51+
// queue the job
52+
// should be completly synchronous
53+
// so when it returns, the job should be completed
54+
backup.QueueJob(jobConfig)
55+
56+
w.WriteHeader(http.StatusOK)
57+
w.Write([]byte("OK\n"))
58+
})
59+
60+
err := httpServer.ListenAndServe()
61+
if err != nil {
62+
if eris.Is(err, http.ErrServerClosed) {
63+
// ignore this error
64+
return
65+
}
66+
log.Fatal(eris.Wrap(err, "error in http server"))
67+
}
68+
}

main.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"net/http"
56
"os"
67
"os/signal"
78
"syscall"
@@ -15,6 +16,9 @@ import (
1516
log "github.com/sirupsen/logrus"
1617
)
1718

19+
// array of job names
20+
var jobs []string
21+
1822
type JobConfig struct {
1923
Name string
2024
Config map[string]string
@@ -61,20 +65,33 @@ func main() {
6165
backup := NewBackup(cli)
6266

6367
// get a list of every job
64-
jobs := k.MapKeys("jobs")
68+
jobs = k.MapKeys("jobs")
69+
70+
// start the http server
71+
// also handles if it is disabled
72+
httpServer := &http.Server{
73+
Addr: ":3333",
74+
}
75+
go startHttpServer(httpServer, backup)
76+
defer func() {
77+
err := httpServer.Shutdown(context.Background())
78+
if err != nil {
79+
log.Error(eris.Wrap(err, "failed to shutdown http server"))
80+
}
81+
}()
6582

6683
// schedule each job
6784
for _, job := range jobs {
6885
log.Infof("Scheduling job: %s", job)
6986

70-
jobConfig := &JobConfig{
71-
Name: job,
72-
Config: k.StringMap("jobs." + job),
87+
jobConfig, err := getJobConfig(job)
88+
if err != nil {
89+
log.Error(eris.Wrapf(err, "failed to get job config for %s", job))
7390
}
7491

75-
_, err := s.NewJob(gocron.CronJob(jobConfig.Config["cron"], false), gocron.NewTask(backup.QueueJob, jobConfig))
92+
_, err = s.NewJob(gocron.CronJob(jobConfig.Config["cron"], false), gocron.NewTask(backup.QueueJob, jobConfig))
7693
if err != nil {
77-
log.Fatal(eris.Wrapf(err, "failed to schedule job %s", jobConfig.Name))
94+
log.Error(eris.Wrapf(err, "failed to schedule job %s", jobConfig.Name))
7895
}
7996
}
8097

@@ -177,3 +194,14 @@ func preprocesContainerName(name string) string {
177194
_, i := utf8.DecodeRuneInString(name)
178195
return name[i:]
179196
}
197+
198+
func getJobConfig(name string) (*JobConfig, error) {
199+
if !k.Exists("jobs." + name) {
200+
return nil, eris.Errorf("Job %s does not exist", name)
201+
}
202+
203+
return &JobConfig{
204+
Name: name,
205+
Config: k.StringMap("jobs." + name),
206+
}, nil
207+
}

0 commit comments

Comments
 (0)