Skip to content

Commit

Permalink
Merge pull request #2210 from ripienaar/execution
Browse files Browse the repository at this point in the history
(#2209) Adds a basic long running execution framework supervisor
  • Loading branch information
ripienaar authored Jan 22, 2025
2 parents ba4af62 + f517f56 commit 22056a8
Show file tree
Hide file tree
Showing 7 changed files with 844 additions and 34 deletions.
27 changes: 16 additions & 11 deletions choria/framework.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, R.I. Pienaar and the Choria Project contributors
// Copyright (c) 2017-2025, R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -479,25 +479,30 @@ func (fw *Framework) SetLogWriter(out io.Writer) {
}

func (fw *Framework) commonLogOpener() error {
return CommonLogOpener(fw.Config.LogFile, fw.log)
}

// CommonLogOpener opens a logfile
func CommonLogOpener(logFile string, logger *log.Logger) error {
switch {
case strings.ToLower(fw.Config.LogFile) == "discard":
fw.log.SetOutput(io.Discard)
case strings.ToLower(logFile) == "discard":
log.SetOutput(io.Discard)

case strings.ToLower(fw.Config.LogFile) == "stdout":
fw.log.SetOutput(os.Stdout)
case strings.ToLower(logFile) == "stdout":
log.SetOutput(os.Stdout)

case strings.ToLower(fw.Config.LogFile) == "stderr":
fw.log.SetOutput(os.Stderr)
case strings.ToLower(logFile) == "stderr":
log.SetOutput(os.Stderr)

case fw.Config.LogFile != "":
fw.log.Formatter = &log.JSONFormatter{}
case logFile != "":
logger.Formatter = &log.JSONFormatter{}

file, err := os.OpenFile(fw.Config.LogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return fmt.Errorf("could not set up logging: %s", err)
}

fw.log.SetOutput(file)
logger.SetOutput(file)
}

return nil
Expand Down
13 changes: 7 additions & 6 deletions cmd/buildinfo.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
// Copyright (c) 2017-2024, R.I. Pienaar and the Choria Project contributors
// Copyright (c) 2017-2025, R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"fmt"
"github.com/choria-io/go-choria/config"
iu "github.com/choria-io/go-choria/internal/util"
"github.com/choria-io/go-choria/protocol"
"github.com/choria-io/go-choria/providers/provtarget"
gnatsd "github.com/nats-io/nats-server/v2/server"
"runtime"
rd "runtime/debug"
"sort"
"strings"
"sync"

"github.com/choria-io/go-choria/config"
iu "github.com/choria-io/go-choria/internal/util"
"github.com/choria-io/go-choria/protocol"
"github.com/choria-io/go-choria/providers/provtarget"
gnatsd "github.com/nats-io/nats-server/v2/server"
)

type buildinfoCommand struct {
Expand Down
68 changes: 68 additions & 0 deletions cmd/exec-supervisor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2025, R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"fmt"
"sync"
"time"

"github.com/choria-io/go-choria/providers/execution"
"github.com/choria-io/go-choria/submission"
)

type execSupervisorCommand struct {
command

hb time.Duration
output bool
cmdID string
env map[string]string
}

func init() {
cli.commands = append(cli.commands, &execSupervisorCommand{})
}

func (b *execSupervisorCommand) Setup() (err error) {
b.env = map[string]string{}

b.cmd = cli.app.Command("exec-supervisor", "Executes and supervises shell commands").Hidden()
b.cmd.Flag("config", "Config file to use").PlaceHolder("FILE").ExistingFileVar(&configFile)
b.cmd.Flag("heartbeat", "Interval to heartbeat about running commands").Default("5m").DurationVar(&b.hb)
b.cmd.Flag("track-output", "Tracks command output and Submit to Choria").UnNegatableBoolVar(&b.output)
b.cmd.Flag("process", "Unique ID for this command").Required().StringVar(&b.cmdID)

return
}

func (b *execSupervisorCommand) Configure() (err error) {
return commonConfigure()
}

func (b *execSupervisorCommand) Run(wg *sync.WaitGroup) (err error) {
defer wg.Done()

log := c.Logger("exec-supervisor")
proc, err := execution.LoadWithChoria(c, b.cmdID)
if err != nil {
log.Errorf("Could not start supervisor: %s", err)
return fmt.Errorf("could not start supervisor: %s", err)
}

submit, err := submission.NewFromChoria(c, submission.Directory)
if err != nil {
log.Errorf("Could not start supervisor: %s", err)
return fmt.Errorf("could not start supervisor: %s", err)
}

err = proc.StartSupervised(ctx, cfg.Choria.ExecutorSpool, submit, b.hb, b.output, log)
if err != nil {
log.Errorf("Could not start supervisor: %s", err)
return fmt.Errorf("could not start supervisor: %s", err)
}

return nil
}
4 changes: 3 additions & 1 deletion config/choria.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023, R.I. Pienaar and the Choria Project contributors
// Copyright (c) 2018-2025, R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -164,6 +164,8 @@ type ChoriaPluginConfig struct {
RPCAuditLogfileGroup string `confkey:"plugin.rpcaudit.logfile.group"` // User group to set file ownership to
RPCAuditLogFileMode string `confkey:"plugin.rpcaudit.logfile.mode" default:"0600"` // File mode to apply to the file

ExecutorSpool string `confkey:"plugin.choria.executor.spool" type:"path_string"` // Path where the command executor writes state

AutonomousAgentsDownload bool `confkey:"plugin.machines.download"` // Activate run-time installation of Autonomous Agents
AutonomousAgentsBucket string `confkey:"plugin.machines.bucket" default:"CHORIA_PLUGINS"` // The KV bucket to query for plugins to install
AutonomousAgentsKey string `confkey:"plugin.machines.key" default:"machines"` // The Key to query in KV bucket for plugins to install
Expand Down
Loading

0 comments on commit 22056a8

Please sign in to comment.