Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: reddec/compose-scheduler
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0
Choose a base ref
...
head repository: reddec/compose-scheduler
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 8 commits
  • 6 files changed
  • 4 contributors

Commits on Jan 23, 2023

  1. docs: update README.md

    reddec committed Jan 23, 2023
    Copy the full SHA
    737a97d View commit details

Commits on Dec 26, 2023

  1. fix typo and reword log

    Signed-off-by: rare-magma <[email protected]>
    rare-magma committed Dec 26, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    Copy the full SHA
    e181251 View commit details

Commits on Dec 27, 2023

  1. Merge pull request #4 from rare-magma/typos

    fix typo and reword log
    reddec authored Dec 27, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f7cc467 View commit details

Commits on Dec 29, 2023

  1. bump alpine version to 3.19 (#5)

    * bump alpine version and run as normal user
    
    Signed-off-by: rare-magma <[email protected]>
    
    * revert setup as normal user
    
    Signed-off-by: rare-magma <[email protected]>
    
    ---------
    
    Signed-off-by: rare-magma <[email protected]>
    rare-magma authored Dec 29, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a9585ae View commit details

Commits on Jan 9, 2024

  1. Update scheduler.go (#7)

    Fix issue when containerID returns `/../..`, so that when it filters the returned string, it identifies containerID `..`, and then fails at the end, bc this is invalid container id
    lorado authored Jan 9, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e138df9 View commit details

Commits on May 3, 2024

  1. Add timezone support (#10)

    * Update Dockerfile.build
    
    Add timezone support
    
    * Update docker-compose.yaml
    
    Add timezone to compose file
    
    * Update Dockerfile.build
    
    Co-authored-by: Aleksandr Baryshnikov <[email protected]>
    
    ---------
    
    Co-authored-by: Aleksandr Baryshnikov <[email protected]>
    y0no and reddec authored May 3, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    3353d7d View commit details

Commits on Jun 22, 2024

  1. Print command output to logs (#9)

    * Update scheduler.go
    
    Fix issue when containerID returns `/../..`, so that when it filters the returned string, it identifies containerID `..`, and then fails at the end, bc this is invalid container id
    
    * print out stdout/stderr to container logs
    
    * add changes suggested by @3timeslazy:
    
    This code fixes the case when the exec command fails (if command not found, for instance), but scheduler thinks it finished successfully
    
    * make logging opt in
    
    * use strconv to parse bool value of logsLabel
    
    * refactor execService:
    
    - use old approach with ContainerExecStart if logging disabled
    - use new approach with ContainerExecAttach if logging enabled
    
    * format with gofmt
    lorado authored Jun 22, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    a2d38ad View commit details
  2. fix build

    reddec committed Jun 22, 2024
    Copy the full SHA
    f272b07 View commit details
Showing with 62 additions and 12 deletions.
  1. +1 −1 .github/workflows/release.yaml
  2. +3 −3 Dockerfile
  3. +3 −2 Dockerfile.build
  4. +1 −1 README.md
  5. +4 −1 docker-compose.yaml
  6. +50 −4 scheduler.go
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -41,6 +41,6 @@ jobs:
uses: goreleaser/goreleaser-action@v2
with:
version: latest
args: release --rm-dist
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM alpine:3.17 AS certs
RUN apk add --no-cache ca-certificates && update-ca-certificates
FROM alpine:3.19 AS certs
RUN apk add --no-cache ca-certificates && update-ca-certificates

FROM scratch
ENTRYPOINT ["/scheduler"]
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
ADD scheduler /
COPY scheduler /
5 changes: 3 additions & 2 deletions Dockerfile.build
Original file line number Diff line number Diff line change
@@ -6,10 +6,11 @@ RUN go mod download && go mod verify
COPY . .
RUN CGO_ENABLED=0 go build -v -o /usr/local/bin/app ./cmd/...

FROM alpine:3.17 AS certs
RUN apk add --no-cache ca-certificates && update-ca-certificates
FROM alpine:3.19 AS certs
RUN apk add --no-cache tzdata ca-certificates && update-ca-certificates

FROM scratch
ENTRYPOINT ["/app"]
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=certs /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /usr/local/bin/app /app
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ services:
- "net.reddec.scheduler.cron=* * * * *"

scheduler:
image: ghcr.io/reddec/compose-scheduler:1
image: ghcr.io/reddec/compose-scheduler:1.0.0
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
5 changes: 4 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ services:
labels:
- "net.reddec.scheduler.cron=* * * * *"
- "net.reddec.scheduler.exec=nginx -s reload"
- "net.reddec.scheduler.logs=true"
date:
image: busybox
restart: "no"
@@ -15,4 +16,6 @@ services:
dockerfile: Dockerfile.build
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- TZ=Europe/Paris
54 changes: 50 additions & 4 deletions scheduler.go
Original file line number Diff line number Diff line change
@@ -3,10 +3,12 @@ package scheduler
import (
"context"
"fmt"
"io"
"log"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync/atomic"
"time"
@@ -24,6 +26,7 @@ const (
composeServiceLabel = "com.docker.compose.service"
schedulerLabel = "net.reddec.scheduler.cron"
commandLabel = "net.reddec.scheduler.exec"
logsLabel = "net.reddec.scheduler.logs"
)

func Create(ctx context.Context, options ...Option) (*Scheduler, error) {
@@ -57,6 +60,7 @@ type Task struct {
Container string
Schedule string
Command []string
logging bool
}

type Scheduler struct {
@@ -81,7 +85,7 @@ func (sc *Scheduler) Run(ctx context.Context) error {
engine := cron.New()

for _, t := range tasks {
log.Println("task for service", t.Service, "at", t.Schedule)
log.Println("task for service", t.Service, "at", t.Schedule, "| logging:", t.logging)
running := new(int32)
t := t
_, err = engine.AddFunc(t.Schedule, func() {
@@ -108,7 +112,7 @@ func (sc *Scheduler) runJob(ctx context.Context, running *int32, t Task) {
errMessage = err.Error()
log.Println("service", t.Service, "failed after", end.Sub(started), "with error:", err)
} else {
log.Println("service", t.Service, "finished after", end.Sub(started), "without error")
log.Println("service", t.Service, "finished after", end.Sub(started), "successfully")
}
if sc.notification == nil {
return
@@ -145,6 +149,14 @@ func (sc *Scheduler) runTask(ctx context.Context, running *int32, task Task) err
}

func (sc *Scheduler) execService(ctx context.Context, task Task) error {
if task.logging {
return sc.execAttachService(ctx, task)
} else {
return sc.execStartService(ctx, task)
}
}

func (sc *Scheduler) execStartService(ctx context.Context, task Task) error {
execID, err := sc.client.ContainerExecCreate(ctx, task.Container, types.ExecConfig{
Cmd: task.Command,
})
@@ -159,6 +171,33 @@ func (sc *Scheduler) execService(ctx context.Context, task Task) error {
return nil
}

func (sc *Scheduler) execAttachService(ctx context.Context, task Task) error {
execID, err := sc.client.ContainerExecCreate(ctx, task.Container, types.ExecConfig{
Cmd: task.Command,
AttachStderr: true,
AttachStdout: true,
})
if err != nil {
return fmt.Errorf("create exec for %s: %w", task.Service, err)
}

attach, err := sc.client.ContainerExecAttach(ctx, execID.ID, types.ExecStartCheck{})
if err != nil {
return fmt.Errorf("exec for %s: %w", task.Service, err)
}
defer attach.Close()
io.Copy(log.Writer(), attach.Reader)

inspect, err := sc.client.ContainerExecInspect(ctx, execID.ID)
if err != nil {
return fmt.Errorf("inspect exec for %s: %w", task.Service, err)
}
if inspect.ExitCode != 0 {
return fmt.Errorf("command returned non-zero code %d", inspect.ExitCode)
}
return nil
}

func (sc *Scheduler) runService(ctx context.Context, task Task) error {
err := sc.client.ContainerStart(ctx, task.Container, types.ContainerStartOptions{})
if err != nil {
@@ -171,7 +210,7 @@ func (sc *Scheduler) runService(ctx context.Context, task Task) error {
return fmt.Errorf("service %s: %s", task.Service, res.Error.Message)
}
if res.StatusCode != 0 {
return fmt.Errorf("sevice %s: status code %d", task.Service, res.StatusCode)
return fmt.Errorf("service %s: status code %d", task.Service, res.StatusCode)
}
case err = <-failed:
return fmt.Errorf("wait for service %s: %w", task.Service, err)
@@ -202,11 +241,18 @@ func (sc *Scheduler) listTasks(ctx context.Context) ([]Task, error) {
}
args = cmd
}

isLoggingEnabled, err := strconv.ParseBool(c.Labels[logsLabel])
if err != nil {
isLoggingEnabled = false
}

ans = append(ans, Task{
Container: c.ID,
Schedule: c.Labels[schedulerLabel],
Service: service,
Command: args,
logging: isLoggingEnabled,
})
}

@@ -220,7 +266,7 @@ func containerID() (string, error) {
return "", fmt.Errorf("detect container ID: %w", err)
}
id := filepath.Base(strings.TrimSpace(string(data)))
if id == "/" {
if id == "/" || id == ".." {
return "", fmt.Errorf("calculate container ID from %s: %w", string(data), err)
}