diff --git a/cmd/coordinator/main.go b/cmd/coordinator/main.go index fb4b2947..a6e8fdbf 100644 --- a/cmd/coordinator/main.go +++ b/cmd/coordinator/main.go @@ -14,11 +14,10 @@ func main() { conf.ParseFlags() log := logger.NewConsole(conf.Coordinator.Debug, "c", false) - log.Info().Msgf("version %s", Version) - log.Info().Msgf("conf version: %v", conf.Version) + log.Info().Msgf("conf: v%v", conf.Version) if log.GetLevel() < logger.InfoLevel { - log.Debug().Msgf("config: %+v", conf) + log.Debug().Msgf("conf: %+v", conf) } c := coordinator.New(conf, log) c.Start() diff --git a/cmd/worker/main.go b/cmd/worker/main.go index 5dc60ce5..a697b4f4 100644 --- a/cmd/worker/main.go +++ b/cmd/worker/main.go @@ -18,9 +18,9 @@ func run() { log := logger.NewConsole(conf.Worker.Debug, "w", false) log.Info().Msgf("version %s", Version) - log.Info().Msgf("conf version: %v", conf.Version) + log.Info().Msgf("conf: v%v", conf.Version) if log.GetLevel() < logger.InfoLevel { - log.Debug().Msgf("config: %+v", conf) + log.Debug().Msgf("conf: %+v", conf) } done := os.ExpectTermination() diff --git a/configs/config.yaml b/configs/config.yaml index a0fe7051..cd8c2f1a 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -1,3 +1,4 @@ +LOL123L: yolo # # Application configuration file # @@ -179,7 +180,8 @@ emulator: # their tick rate (1/system FPS), but OpenGL cores like N64 may have significant # frame rendering time inconsistencies. In general, VFR for CFR cores leads to # noticeable video stutter (with the current frame rendering time calculations). - # - options ([]string) a list of Libretro core options for tweaking + # - options ([]string) a list of Libretro core options for tweaking. + # All keys of the options should be in the double quotes in order to preserve upper-case symbols. list: gba: lib: mgba_libretro @@ -191,8 +193,8 @@ emulator: folder: psx # see: https://github.com/libretro/pcsx_rearmed/blob/master/frontend/libretro_core_options.h options: - pcsx_rearmed_drc: enabled - pcsx_rearmed_display_internal_fps: disabled + "pcsx_rearmed_drc": enabled + "pcsx_rearmed_display_internal_fps": disabled # MAME core requires additional manual setup, please read: # https://docs.libretro.com/library/fbneo/ mame: @@ -213,21 +215,21 @@ emulator: vfr: true # see: https://github.com/libretro/mupen64plus-libretro-nx/blob/master/libretro/libretro_core_options.h options: - mupen64plus-169screensize: 640x360 - mupen64plus-43screensize: 320x240 - mupen64plus-EnableCopyColorToRDRAM: Off - mupen64plus-EnableCopyDepthToRDRAM: Off - mupen64plus-EnableEnhancedTextureStorage: True - mupen64plus-EnableFBEmulation: True - mupen64plus-EnableLegacyBlending: True - mupen64plus-FrameDuping: False - mupen64plus-MaxTxCacheSize: 8000 - mupen64plus-ThreadedRenderer: False - mupen64plus-cpucore: dynamic_recompiler - mupen64plus-pak1: memory - mupen64plus-rdp-plugin: gliden64 - mupen64plus-rsp-plugin: hle - mupen64plus-astick-sensitivity: 100 + "mupen64plus-169screensize": 640x360 + "mupen64plus-43screensize": 320x240 + "mupen64plus-EnableCopyColorToRDRAM": Off + "mupen64plus-EnableCopyDepthToRDRAM": Off + "mupen64plus-EnableEnhancedTextureStorage": True + "mupen64plus-EnableFBEmulation": True + "mupen64plus-EnableLegacyBlending": True + "mupen64plus-FrameDuping": False + "mupen64plus-MaxTxCacheSize": 8000 + "mupen64plus-ThreadedRenderer": False + "mupen64plus-cpucore": dynamic_recompiler + "mupen64plus-pak1": memory + "mupen64plus-rdp-plugin": gliden64 + "mupen64plus-rsp-plugin": hle + "mupen64plus-astick-sensitivity": 100 encoder: audio: diff --git a/pkg/config/loader.go b/pkg/config/loader.go index d75ddf0c..3ba6c3df 100644 --- a/pkg/config/loader.go +++ b/pkg/config/loader.go @@ -12,33 +12,72 @@ import ( const EnvPrefix = "CLOUD_GAME_" +type Kv = map[string]any +type Bytes []byte + +func (b *Bytes) ReadBytes() ([]byte, error) { return *b, nil } +func (b *Bytes) Read() (Kv, error) { return nil, nil } + type File string -func (f *File) ReadBytes() ([]byte, error) { return os.ReadFile(string(*f)) } -func (f *File) Read() (map[string]interface{}, error) { return nil, nil } +func (f *File) ReadBytes() ([]byte, error) { return os.ReadFile(string(*f)) } +func (f *File) Read() (Kv, error) { return nil, nil } type YAML struct{} -func (p *YAML) Marshal(map[string]interface{}) ([]byte, error) { return nil, nil } -func (p *YAML) Unmarshal(b []byte) (map[string]interface{}, error) { - var out map[string]interface{} - if err := yaml.Unmarshal(b, &out); err != nil { +func (p *YAML) Marshal(Kv) ([]byte, error) { return nil, nil } +func (p *YAML) Unmarshal(b []byte) (Kv, error) { + var out Kv + klw := keysToLower(b) + if err := yaml.Unmarshal(klw, &out); err != nil { return nil, err } return out, nil } +// keysToLower iterates YAML bytes and tries to lower the keys. +// Used for merging with environment vars which are lowered as well. +func keysToLower(in []byte) []byte { + l, r, ignore := 0, 0, false + for i, b := range in { + switch b { + case '#': // skip comments + ignore = true + case ':': // lower left chunk before the next : symbol + if ignore { + continue + } + r = i + ignore = true + for j := l; j <= r; j++ { + c := in[j] + // we skip the line with the first explicit " string symbol + if c == '"' { + break + } + if 'A' <= c && c <= 'Z' { + in[j] += 'a' - 'A' + } + } + case '\n': + l = i + ignore = false + } + } + return in +} + type Env string func (e *Env) ReadBytes() ([]byte, error) { return nil, nil } -func (e *Env) Read() (map[string]interface{}, error) { +func (e *Env) Read() (Kv, error) { var keys []string for _, k := range os.Environ() { if strings.HasPrefix(k, string(*e)) { keys = append(keys, k) } } - mp := make(map[string]interface{}) + mp := make(Kv) for _, k := range keys { parts := strings.SplitN(k, "=", 2) n := strings.ToLower(strings.TrimPrefix(parts[0], string(*e))) @@ -65,10 +104,10 @@ var k = koanf.New("_") // LoadConfig loads a configuration file into the given struct. // The path param specifies a custom path to the configuration file. // Reads and puts environment variables with the prefix CLOUD_GAME_. -func LoadConfig(config any, path string) error { - dirs := []string{path} - if path == "" { - dirs = append(dirs, ".", "configs", "../../../configs") +func LoadConfig(config any, path string) (err error) { + dirs := []string{".", "configs", "../../../configs"} + if path != "" { + dirs = append([]string{path}, dirs...) } homeDir := "" diff --git a/pkg/config/loader_test.go b/pkg/config/loader_test.go index c0e7a116..b97fed5d 100644 --- a/pkg/config/loader_test.go +++ b/pkg/config/loader_test.go @@ -2,6 +2,7 @@ package config import ( "os" + "reflect" "testing" ) @@ -30,3 +31,28 @@ func TestConfigEnv(t *testing.T) { t.Errorf("%v is not x", v) } } + +func Test_keysToLower(t *testing.T) { + type args struct { + in []byte + } + tests := []struct { + name string + args args + want []byte + }{ + {name: "empty", args: args{in: []byte{}}, want: []byte{}}, + {name: "case", args: args{ + in: []byte("KEY:1\n#Comment with:\n KeY123_NamE: 1\n\n\n\nAAA:123\n \"KeyKey\":2\n"), + }, + want: []byte("key:1\n#Comment with:\n key123_name: 1\n\n\n\naaa:123\n \"KeyKey\":2\n"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := keysToLower(tt.args.in); !reflect.DeepEqual(got, tt.want) { + t.Errorf("keysToLower() = %v, want %v", string(got), string(tt.want)) + } + }) + } +}