Skip to content

Commit

Permalink
feat: dynamic task connection
Browse files Browse the repository at this point in the history
  • Loading branch information
FMotalleb committed Jun 10, 2024
1 parent 594ba36 commit 9173743
Show file tree
Hide file tree
Showing 13 changed files with 335 additions and 157 deletions.
14 changes: 14 additions & 0 deletions abstraction/cmd_connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package abstraction

import (
"context"

"github.com/FMotalleb/crontab-go/config"
)

type CmdConnection interface {
Prepare(context.Context, *config.Task) error
Connect() error
Execute() ([]byte, error)
Disconnect() error
}
7 changes: 3 additions & 4 deletions config.local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
jobs:
- name: Test Job
tasks:
- command: ip a
env:
SHELL: C:\WINDOWS\System32\OpenSSH\ssh.exe
SHELL_ARGS: "-i;C:/Users/Motalleb/.xpipe/storage/data/id_rsa_old;[email protected];-p;9011"
- command: ip a -pt
retries: 5
retry-delay: 5s
schedulers:
- on-init: true
- interval: 10m10s
62 changes: 0 additions & 62 deletions config/compiler/compiler.go

This file was deleted.

34 changes: 34 additions & 0 deletions config/compiler/scheduler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cfgcompiler

import (
"github.com/robfig/cron/v3"
"github.com/sirupsen/logrus"

"github.com/FMotalleb/crontab-go/abstraction"
"github.com/FMotalleb/crontab-go/config"
"github.com/FMotalleb/crontab-go/core/schedule"
)

func CompileScheduler(sh *config.JobScheduler, cr *cron.Cron, logger *logrus.Entry) abstraction.Scheduler {
switch {
case sh.Cron != "":
scheduler := schedule.NewCron(
sh.Cron,
cr,
logger,
)
return &scheduler
case sh.Interval != 0:
scheduler := schedule.NewInterval(
sh.Interval,
logger,
)
return &scheduler

case sh.OnInit:
scheduler := schedule.Init{}
return &scheduler
}

return nil
}
36 changes: 36 additions & 0 deletions config/compiler/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cfgcompiler

import (
"github.com/sirupsen/logrus"

"github.com/FMotalleb/crontab-go/abstraction"
"github.com/FMotalleb/crontab-go/config"
"github.com/FMotalleb/crontab-go/core/task"
)

func CompileTask(t *config.Task, logger *logrus.Entry) abstraction.Executable {
var exe abstraction.Executable
switch {
case t.Command != "":
exe = task.NewCommand(t, logger)
case t.Get != "":
exe = task.NewGet(t, logger)
case t.Post != "":
exe = task.NewPost(t, logger)
default:
logger.Fatalln("cannot handle given task config", t)
}

onDone := []abstraction.Executable{}
for _, d := range t.OnDone {
onDone = append(onDone, CompileTask(&d, logger))
}
exe.SetDoneHooks(onDone)
onFail := []abstraction.Executable{}
for _, d := range t.OnFail {
onFail = append(onFail, CompileTask(&d, logger))
}
exe.SetFailHooks(onFail)

return exe
}
30 changes: 19 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,30 @@ type (
}

Task struct {
Post string `mapstructure:"post" json:"post,omitempty"`
Get string `mapstructure:"get" json:"get,omitempty"`
// Http Requests
Post string `mapstructure:"post" json:"post,omitempty"`
Get string `mapstructure:"get" json:"get,omitempty"`
Headers map[string]string `mapstructure:"headers" json:"headers,omitempty"`
Data any `mapstructure:"data" json:"data,omitempty"`

// Command params
Command string `mapstructure:"command" json:"command,omitempty"`
WorkingDirectory string `mapstructure:"working-dir" json:"working_directory,omitempty"`
Headers map[string]string `mapstructure:"headers" json:"headers,omitempty"`
Data any `mapstructure:"data" json:"data,omitempty"`

UserName string `mapstructure:"user" json:"user,omitempty"`
GroupName string `mapstructure:"group" json:"group,omitempty"`
UserName string `mapstructure:"user" json:"user,omitempty"`
GroupName string `mapstructure:"group" json:"group,omitempty"`
Env map[string]string `mapstructure:"env" json:"env,omitempty"`
Connections []TaskConnection `mapstructure:"connections" json:"connections,omitempty"`

Retries uint `mapstructure:"retries" json:"retries,omitempty"`
RetryDelay time.Duration `mapstructure:"retry-delay" json:"retry_delay,omitempty"`
Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"`
Env map[string]string `mapstructure:"env" json:"env,omitempty"`
// Retry & Timeout config
Retries uint `mapstructure:"retries" json:"retries,omitempty"`
RetryDelay time.Duration `mapstructure:"retry-delay" json:"retry_delay,omitempty"`
Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"`

// Hooks
OnDone []Task `mapstructure:"on-done" json:"on_done,omitempty"`
OnFail []Task `mapstructure:"on-fail" json:"on_fail,omitempty"`
}
TaskConnection struct {
Local bool
}
)
18 changes: 18 additions & 0 deletions core/cmd_connection/compiler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package connection

import (
"log"

"github.com/sirupsen/logrus"

"github.com/FMotalleb/crontab-go/abstraction"
"github.com/FMotalleb/crontab-go/config"
)

func CompileConnection(conn *config.TaskConnection, logger *logrus.Entry) abstraction.CmdConnection {
if conn.Local {
return NewLocalCMDConn(logger)
}
log.Fatalln("cannot compile given taskConnection", conn)
return nil
}
100 changes: 100 additions & 0 deletions core/cmd_connection/local.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package connection

import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"strings"

"github.com/sirupsen/logrus"

"github.com/FMotalleb/crontab-go/abstraction"
"github.com/FMotalleb/crontab-go/cmd"
"github.com/FMotalleb/crontab-go/config"
credential "github.com/FMotalleb/crontab-go/core/os_credential"
)

type Local struct {
log *logrus.Entry
cmd *exec.Cmd
}

func NewLocalCMDConn(log *logrus.Entry) abstraction.CmdConnection {
return &Local{
log: log.WithField(
"connection", "local",
),
}
}

// Prepare implements abstraction.CmdConnection.
func (l *Local) Prepare(ctx context.Context, task *config.Task) error {
shell := cmd.CFG.Shell
shellArgs := cmd.CFG.ShellArgs
env := os.Environ()
for key, val := range task.Env {
env = append(env, fmt.Sprintf("%s=%s", key, val))
switch strings.ToLower(key) {
case "shell":
l.log.Info("you've used `SHELL` env variable in command environments, overriding the global shell with:", val)
shell = val
case "shell_args":
l.log.Info("you've used `SHELL_ARGS` env variable in command environments, overriding the global shell_args with: ", val)
shellArgs = strings.Split(val, ";")
}
}
workingDir := task.WorkingDirectory
if workingDir == "" {
var e error
workingDir, e = os.Getwd()
if e != nil {
return fmt.Errorf("cannot get current working directory: %s", e)
}
}
l.cmd = exec.CommandContext(
ctx,
shell,
append(shellArgs, task.Command)...,
)
l.log = l.log.WithFields(
logrus.Fields{
"working_directory": workingDir,
"shell": shell,
"shell_args": shellArgs,
},
)
credential.SetUser(l.log, l.cmd, task.UserName, task.GroupName)
l.cmd.Env = env
l.cmd.Dir = workingDir

return nil
}

// Connect implements abstraction.CmdConnection.
func (l *Local) Connect() error {
return nil
}

// Disconnect implements abstraction.CmdConnection.
func (l *Local) Disconnect() error {
return nil
}

// Execute implements abstraction.CmdConnection.
func (l *Local) Execute() ([]byte, error) {
var res bytes.Buffer
l.cmd.Stdout = &res
l.cmd.Stderr = &res
if err := l.cmd.Start(); err != nil {
l.log.Warn("failed to start the command ", err)
return []byte{}, err
} else if err := l.cmd.Wait(); err != nil {
l.log.Warnf("command failed with answer: %s", strings.TrimSpace(res.String()))
l.log.Warn("failed to execute the command", err)
return res.Bytes(), err
} else {
return res.Bytes(), nil
}
}
Loading

0 comments on commit 9173743

Please sign in to comment.