From 70c8bd9ca5a8d67017d8382d1b0e97b3d3b44f94 Mon Sep 17 00:00:00 2001 From: Yann Stepienik Date: Fri, 29 Mar 2024 17:35:18 +0000 Subject: [PATCH] [release] v0.15.0-unstable26 --- changelog.md | 1 + client/src/pages/cron/jobsManage.jsx | 2 +- package.json | 2 +- src/cron/index.go | 78 +++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index ca90e1a..85afc2f 100644 --- a/changelog.md +++ b/changelog.md @@ -23,6 +23,7 @@ - Added optionals vars to DNS challenge setup (like timeout) - Added a check on hostname to prevent protocols - Added hint to TCP proxying + - Fix issue with favicon retrieval post-migration to host mode ## Version 0.14.6 - Fix custom back-up folder logic diff --git a/client/src/pages/cron/jobsManage.jsx b/client/src/pages/cron/jobsManage.jsx index da4ad8c..7151629 100644 --- a/client/src/pages/cron/jobsManage.jsx +++ b/client/src/pages/cron/jobsManage.jsx @@ -128,7 +128,7 @@ export const CronManager = () => { field: (r) => { return
{{ 'running': } severity={'info'} color={'info'}>Running since {r.LastStarted}, - 'success': Last run finished on {r.LastRun}, + 'success': Last run finished on {r.LastRun}, duration {(new Date(r.LastRun).getTime() - new Date(r.LastStarted).getTime()) / 1000}s, 'error': Last run exited with an error on {r.LastRun}, 'never': Never ran diff --git a/package.json b/package.json index 8fdf3bb..b06f5d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cosmos-server", - "version": "0.15.0-unstable25", + "version": "0.15.0-unstable26", "description": "", "main": "test-server.js", "bugs": { diff --git a/src/cron/index.go b/src/cron/index.go index 823e756..5c5d10f 100644 --- a/src/cron/index.go +++ b/src/cron/index.go @@ -8,10 +8,14 @@ import ( "io" "bufio" "os/exec" + "fmt" "github.com/go-co-op/gocron/v2" + "github.com/azukaar/cosmos-server/src/docker" "github.com/azukaar/cosmos-server/src/utils" + + "github.com/docker/docker/api/types" ) var scheduler gocron.Scheduler @@ -32,6 +36,7 @@ type ConfigJob struct { Logs []string Ctx context.Context `json:"-"` CancelFunc context.CancelFunc `json:"-"` + Container string } var jobsList = map[string]map[string]ConfigJob{} @@ -108,6 +113,75 @@ func JobFromCommand(command string, args ...string) func(OnLog func(string), OnF } } +func JobFromContainerCommand(containerID string, command string, args ...string) func(OnLog func(string), OnFail func(error), OnSuccess func(), ctx context.Context, cancel context.CancelFunc) { + return func(OnLog func(string), OnFail func(error), OnSuccess func(), ctx context.Context, cancel context.CancelFunc) { + // Connect to Docker + err := docker.Connect() + if err != nil { + OnFail(err) + return + } + + // Check if the container is running + containerJSON, err := docker.DockerClient.ContainerInspect(ctx, containerID) + if err != nil { + OnFail(err) + return + } + + if !containerJSON.State.Running { + OnFail(fmt.Errorf("Container %s is not running", containerID)) + return + } + + // Create exec configuration + execConfig := types.ExecConfig{ + Cmd: append([]string{command}, args...), + AttachStdout: true, + AttachStderr: true, + } + + // Create exec instance + execID, err := docker.DockerClient.ContainerExecCreate(ctx, containerID, execConfig) + if err != nil { + OnFail(err) + return + } + + // Attach to exec instance + execAttach, err := docker.DockerClient.ContainerExecAttach(ctx, execID.ID, types.ExecStartCheck{}) + if err != nil { + OnFail(err) + return + } + defer execAttach.Close() + + // Stream logs from exec + go streamLogs(execAttach.Reader, OnLog) + + // Inspect exec process to wait for completion + for { + execInspect, err := docker.DockerClient.ContainerExecInspect(ctx, execID.ID) + if err != nil { + OnFail(err) + return + } + + if !execInspect.Running { + if execInspect.ExitCode == 0 { + OnSuccess() + } else { + OnFail(fmt.Errorf("exec process exited with code %d", execInspect.ExitCode)) + } + break + } + + // Don't spam the API + time.Sleep(500 * time.Millisecond) + } + } +} + func InitJobs() { CRONLock <- true defer func() { <-CRONLock }() @@ -122,8 +196,9 @@ func InitJobs() { for _, job := range configJobsList { cmd := JobFromCommand("sh", "-c", job.Command) + if job.Container != "" { - cmd = JobFromCommand("docker", "exec", job.Container, "sh", "-c", job.Command) + cmd = JobFromContainerCommand(job.Container, "sh", "-c", job.Command) } if job.Enabled { @@ -143,6 +218,7 @@ func InitJobs() { LastStarted: time.Time{}, Logs: []string{}, Disabled: !job.Enabled, + Container: job.Container, } if CustomScheduler, ok := jobsList["Custom"]; ok {