Skip to content

Commit

Permalink
fix(scripts): 🐛 actually warn about script parsing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuar committed Feb 1, 2025
1 parent 4a95ae0 commit 101b2a8
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 38 deletions.
26 changes: 16 additions & 10 deletions internal/scripts/scripts.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@ func (s *Script) parse() (*scriptOutput, error) {

output := &scriptOutput{}

err = output.Unmarshal(out)
if err != nil {
return nil, fmt.Errorf("could not parse script output: %w", err)
if err := output.Unmarshal(out); err != nil {
return nil, fmt.Errorf("parse error: %w", err)
}

return output, nil
Expand Down Expand Up @@ -98,21 +97,28 @@ type scriptOutput struct {
// Unmarshal will attempt to take the raw output from a script execution and
// format it as either JSON or YAML. If successful, this format can then be used
// as a sensor.
//
//revive:disable:indent-error-flow // errors need to be gathered.
func (o *scriptOutput) Unmarshal(scriptOutput []byte) error {
jsonErr := json.Unmarshal(scriptOutput, &o)
if jsonErr == nil {
var parseError error

if err := json.Unmarshal(scriptOutput, o); err == nil {
return nil
} else {
parseError = errors.Join(parseError, fmt.Errorf("not valid JSON: %w", err))
}

yamlErr := yaml.Unmarshal(scriptOutput, &o)
if yamlErr == nil {
if err := yaml.Unmarshal(scriptOutput, o); err == nil {
return nil
} else {
parseError = errors.Join(parseError, fmt.Errorf("not valid YAML: %w", err))
}

tomlErr := toml.Unmarshal(scriptOutput, &o)
if tomlErr == nil {
if err := toml.Unmarshal(scriptOutput, o); err == nil {
return nil
} else {
parseError = errors.Join(parseError, fmt.Errorf("not valid TOML: %w", err))
}

return errors.Join(jsonErr, yamlErr, tomlErr)
return parseError
}
56 changes: 28 additions & 28 deletions internal/scripts/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,37 +167,11 @@ func (c *Worker) Stop() error {
return nil
}

// NewScriptController creates a new sensor worker for scripts.
func NewScriptsWorker(ctx context.Context) (*Worker, error) {
scriptPath := filepath.Join(preferences.PathFromCtx(ctx), "scripts")

worker := &Worker{
scheduler: cron.New(),
logger: logging.FromContext(ctx).With(slog.String("controller", "scripts")),
}

scripts, err := findScripts(scriptPath)
if err != nil {
return nil, fmt.Errorf("could not find scripts: %w", err)
}

worker.jobs = make([]job, 0, len(scripts))

for _, s := range scripts {
logAttrs := slog.Group("job", slog.String("script", s.path), slog.String("schedule", s.schedule))
worker.jobs = append(worker.jobs, job{Script: *s, logAttrs: logAttrs})
}

return worker, nil
}

// findScripts locates scripts and returns a slice of scripts that the agent can
// run.
func findScripts(path string) ([]*Script, error) {
func (c *Worker) findScripts(path string) ([]*Script, error) {
var sensorScripts []*Script

var errs error

files, err := filepath.Glob(path + "/*")
if err != nil {
return nil, fmt.Errorf("could not search for scripts: %w", err)
Expand All @@ -207,7 +181,9 @@ func findScripts(path string) ([]*Script, error) {
if isExecutable(scriptFile) {
script, err := NewScript(scriptFile)
if err != nil {
errs = errors.Join(errs, err)
c.logger.Warn("Script error.",
slog.Any("error", err),
)

continue
}
Expand All @@ -219,6 +195,30 @@ func findScripts(path string) ([]*Script, error) {
return sensorScripts, nil
}

// NewScriptController creates a new sensor worker for scripts.
func NewScriptsWorker(ctx context.Context) (*Worker, error) {
scriptPath := filepath.Join(preferences.PathFromCtx(ctx), "scripts")

worker := &Worker{
scheduler: cron.New(),
logger: logging.FromContext(ctx).WithGroup("scripts_worker"),
}

scripts, err := worker.findScripts(scriptPath)
if err != nil {
return nil, fmt.Errorf("could not find scripts: %w", err)
}

worker.jobs = make([]job, 0, len(scripts))

for _, s := range scripts {
logAttrs := slog.Group("job", slog.String("path", s.path), slog.String("schedule", s.schedule))
worker.jobs = append(worker.jobs, job{Script: *s, logAttrs: logAttrs})
}

return worker, nil
}

// isExecutable is helper to determine if a (script) file is executable.
func isExecutable(filename string) bool {
fi, err := os.Stat(filename)
Expand Down

0 comments on commit 101b2a8

Please sign in to comment.