Skip to content

Commit

Permalink
Merge pull request #2 from Huskydog9988/http-support
Browse files Browse the repository at this point in the history
  • Loading branch information
Huskydog9988 authored Feb 3, 2024
2 parents 4097379 + 9e2e02d commit cc67603
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 6 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ config:
# optional: allows you to specify the max number of jobs to run at once
jobLimit: 1

# optional: allows you start an http server and trigger jobs via an api
httpServer:
enabled: true

jobs:
# job name
testRegex:
Expand Down Expand Up @@ -58,3 +62,19 @@ docker run --rm -it -v "$PWD:$PWD" -w "$PWD" ghcr.io/huskydog9988/docker-db-back
```

The script will then dump the databases to the `out` folder, and continue to run every 5 minutes because of the cron option.

## API

> This feature requires the `httpServer` option to be enabled in the config file
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.

To trigger a job, send a GET request to `http://localhost:3333/api/v1/queueJob?jobName=JOB_NAME`.

Example using the example config file:

```bash
curl http://localhost:3333/api/v1/queueJob?jobName=testRegex
```

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.
4 changes: 4 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ config:
# optional: allows you to specify the max number of jobs to run at once
jobLimit: 1

# optional: allows you start an http server and trigger jobs via an api
httpServer:
enabled: true

jobs:
testRegex:
# Database type: postgres, mysql, mariadb
Expand Down
68 changes: 68 additions & 0 deletions http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"net/http"

"github.com/rotisserie/eris"
log "github.com/sirupsen/logrus"
)

var keyServerAddr = "serverAddr"

// handle any unknown requests
func getRoot(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not found\n"))
}

// start the http server
// handles if the http server is enabled or not
func startHttpServer(httpServer *http.Server, backup *Backup) {
// if the http server is not defined or disabled, return
if !k.Exists("config.httpServer.enabled") {
return
} else if !k.Bool("config.httpServer.enabled") {
return
}

log.Infof("Starting http server")

mux := http.NewServeMux()
httpServer.Handler = mux

mux.HandleFunc("/", getRoot)
mux.HandleFunc("/api/v1/queueJob", func(w http.ResponseWriter, r *http.Request) {
// get the job name
jobName := r.URL.Query().Get("jobName")
if jobName == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("jobName is required\n"))
return
}

// get the job config
jobConfig, err := getJobConfig(jobName)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error() + "\n"))
return
}

// queue the job
// should be completly synchronous
// so when it returns, the job should be completed
backup.QueueJob(jobConfig)

w.WriteHeader(http.StatusOK)
w.Write([]byte("OK\n"))
})

err := httpServer.ListenAndServe()
if err != nil {
if eris.Is(err, http.ErrServerClosed) {
// ignore this error
return
}
log.Fatal(eris.Wrap(err, "error in http server"))
}
}
40 changes: 34 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
Expand All @@ -15,6 +16,9 @@ import (
log "github.com/sirupsen/logrus"
)

// array of job names
var jobs []string

type JobConfig struct {
Name string
Config map[string]string
Expand Down Expand Up @@ -61,20 +65,33 @@ func main() {
backup := NewBackup(cli)

// get a list of every job
jobs := k.MapKeys("jobs")
jobs = k.MapKeys("jobs")

// start the http server
// also handles if it is disabled
httpServer := &http.Server{
Addr: ":3333",
}
go startHttpServer(httpServer, backup)
defer func() {
err := httpServer.Shutdown(context.Background())
if err != nil {
log.Error(eris.Wrap(err, "failed to shutdown http server"))
}
}()

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

jobConfig := &JobConfig{
Name: job,
Config: k.StringMap("jobs." + job),
jobConfig, err := getJobConfig(job)
if err != nil {
log.Error(eris.Wrapf(err, "failed to get job config for %s", job))
}

_, err := s.NewJob(gocron.CronJob(jobConfig.Config["cron"], false), gocron.NewTask(backup.QueueJob, jobConfig))
_, err = s.NewJob(gocron.CronJob(jobConfig.Config["cron"], false), gocron.NewTask(backup.QueueJob, jobConfig))
if err != nil {
log.Fatal(eris.Wrapf(err, "failed to schedule job %s", jobConfig.Name))
log.Error(eris.Wrapf(err, "failed to schedule job %s", jobConfig.Name))
}
}

Expand Down Expand Up @@ -177,3 +194,14 @@ func preprocesContainerName(name string) string {
_, i := utf8.DecodeRuneInString(name)
return name[i:]
}

func getJobConfig(name string) (*JobConfig, error) {
if !k.Exists("jobs." + name) {
return nil, eris.Errorf("Job %s does not exist", name)
}

return &JobConfig{
Name: name,
Config: k.StringMap("jobs." + name),
}, nil
}

0 comments on commit cc67603

Please sign in to comment.