138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"regexp"
|
|
|
|
"github.com/joint-online-judge/JOJ3/internal/stage"
|
|
"github.com/koding/multiconfig"
|
|
)
|
|
|
|
type Conf struct {
|
|
SandboxExecServer string `default:"localhost:5051"`
|
|
SandboxToken string `default:""`
|
|
LogLevel int `default:"0"`
|
|
OutputPath string `default:"joj3_result.json"`
|
|
Stages []struct {
|
|
Name string
|
|
Executor struct {
|
|
Name string
|
|
With struct {
|
|
Default stage.Cmd
|
|
Cases []OptionalCmd
|
|
}
|
|
}
|
|
Parser struct {
|
|
Name string
|
|
With interface{}
|
|
}
|
|
}
|
|
}
|
|
|
|
type OptionalCmd struct {
|
|
Args *[]string
|
|
Env *[]string
|
|
Stdin *stage.CmdFile
|
|
Stdout *stage.CmdFile
|
|
Stderr *stage.CmdFile
|
|
|
|
CPULimit *uint64
|
|
RealCPULimit *uint64
|
|
ClockLimit *uint64
|
|
MemoryLimit *uint64
|
|
StackLimit *uint64
|
|
ProcLimit *uint64
|
|
CPURateLimit *uint64
|
|
CPUSetLimit *string
|
|
|
|
CopyIn *map[string]stage.CmdFile
|
|
CopyInCached *map[string]string
|
|
CopyInDir *string
|
|
|
|
CopyOut *[]string
|
|
CopyOutCached *[]string
|
|
CopyOutMax *uint64
|
|
CopyOutDir *string
|
|
|
|
TTY *bool
|
|
StrictMemoryLimit *bool
|
|
DataSegmentLimit *bool
|
|
AddressSpaceLimit *bool
|
|
}
|
|
|
|
// TODO: add other fields to match? not only limit to latest commit message
|
|
type MetaConf struct {
|
|
Patterns []struct {
|
|
Filename string
|
|
Regex string
|
|
}
|
|
}
|
|
|
|
func parseMetaConfFile(path string) (metaConf MetaConf, err error) {
|
|
// FIXME: remove this default meta config, it is only for demonstration
|
|
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
|
|
return MetaConf{
|
|
Patterns: []struct {
|
|
Filename string
|
|
Regex string
|
|
}{
|
|
{
|
|
Filename: "conf.json",
|
|
Regex: ".*",
|
|
},
|
|
},
|
|
}, nil
|
|
}
|
|
d := &multiconfig.DefaultLoader{}
|
|
d.Loader = multiconfig.NewWithPath(path)
|
|
d.Validator = multiconfig.MultiValidator(&multiconfig.RequiredValidator{})
|
|
if err = d.Load(&metaConf); err != nil {
|
|
slog.Error("parse meta conf", "error", err)
|
|
return
|
|
}
|
|
if err = d.Validate(&metaConf); err != nil {
|
|
slog.Error("validate meta conf", "error", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func parseConfFile(path string) (conf Conf, err error) {
|
|
d := &multiconfig.DefaultLoader{}
|
|
d.Loader = multiconfig.MultiLoader(
|
|
&multiconfig.TagLoader{},
|
|
&multiconfig.JSONLoader{Path: path},
|
|
)
|
|
d.Validator = multiconfig.MultiValidator(&multiconfig.RequiredValidator{})
|
|
if err = d.Load(&conf); err != nil {
|
|
slog.Error("parse stages conf", "error", err)
|
|
return
|
|
}
|
|
if err = d.Validate(&conf); err != nil {
|
|
slog.Error("validate stages conf", "error", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func msgToConf(metaConfPath string, msg string) (conf Conf, err error) {
|
|
slog.Info("msg to conf", "msg", msg)
|
|
metaConf, err := parseMetaConfFile(metaConfPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, pattern := range metaConf.Patterns {
|
|
if matched, _ := regexp.MatchString(pattern.Regex, msg); matched {
|
|
slog.Debug("pattern matched",
|
|
"pattern", pattern, "filename", pattern.Filename)
|
|
slog.Info("pattern matched", "filename", pattern.Filename)
|
|
return parseConfFile(pattern.Filename)
|
|
}
|
|
}
|
|
err = fmt.Errorf("no pattern matched")
|
|
return
|
|
}
|