mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 15:51:26 +00:00
Build real cron engine + service-detail Cron UI
The cron backend was a stub: calculateNextRun returned now+1h for any input and executeCronJob slept 2s then wrote "success" without running the command. Now robfig/cron parses and validates schedules (400 on invalid), a 60s scheduler goroutine executes due enabled jobs, and commands run via docker exec sh -c inside the service's container with stdout+stderr captured into cron_executions. Added Client.ExecRun for attached output capture. UI: Cron tab on the service detail page with create/edit/enable-toggle, manual Run, and execution history with logs. Verified e2e against real Postgres + Docker (trigger and scheduler tick both produce real captured output). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
aab785afc1
commit
a1e43524f5
9 files changed
+498
-26
No files matched your search
@@ -1,6 +1,7 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
)
|
||||
|
||||
// Client wraps the Docker client with additional functionality
|
||||
@@ -313,6 +315,36 @@ func (c *Client) ExecInspect(ctx context.Context, execID string) (container.Exec
|
||||
return c.cli.ContainerExecInspect(ctx, execID)
|
||||
}
|
||||
|
||||
// ExecRun runs a command in a container and returns its combined
|
||||
// stdout/stderr output and exit code.
|
||||
func (c *Client) ExecRun(ctx context.Context, containerID string, cmd []string) (string, int, error) {
|
||||
exec, err := c.cli.ContainerExecCreate(ctx, containerID, container.ExecOptions{
|
||||
Cmd: cmd,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
})
|
||||
if err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
|
||||
resp, err := c.cli.ContainerExecAttach(ctx, exec.ID, container.ExecAttachOptions{})
|
||||
if err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
defer resp.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
if _, err := stdcopy.StdCopy(&buf, &buf, resp.Reader); err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
|
||||
inspect, err := c.cli.ContainerExecInspect(ctx, exec.ID)
|
||||
if err != nil {
|
||||
return buf.String(), -1, err
|
||||
}
|
||||
return buf.String(), inspect.ExitCode, nil
|
||||
}
|
||||
|
||||
// GetImageInfo returns information about a Docker image
|
||||
func (c *Client) GetImageInfo(ctx context.Context, imageName string) (*ImageInfo, error) {
|
||||
images, err := c.cli.ImageList(ctx, image.ListOptions{})
|
||||
|
||||
Reference in new issue
Block a user