mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-09-08 19:58:46 -04:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eba5e87047 | ||
|
|
b9fd10c202 |
No files matched your search
@@ -0,0 +1,55 @@
|
||||
// Package binder binds OpenCloud yaml config files to config structs, as a leaf
|
||||
// package that avoids importing the aggregate service config in pkg/config.
|
||||
package binder
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
gofig "github.com/gookit/config/v2"
|
||||
gooyaml "github.com/gookit/config/v2/yaml"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/defaults"
|
||||
)
|
||||
|
||||
// decoderConfigTagName sets the tag name to be used from the config structs
|
||||
// currently we only support "yaml" because we only support config loading
|
||||
// from yaml files and the yaml parser has no simple way to set a custom tag name to use
|
||||
const decoderConfigTagName = "yaml"
|
||||
|
||||
// BindSourcesToStructs assigns any config value from a config file / env variable to struct `dst`.
|
||||
func BindSourcesToStructs(service string, dst any) error {
|
||||
fileSystem := os.DirFS("/")
|
||||
filePath := strings.TrimLeft(path.Join(defaults.BaseConfigPath(), service+".yaml"), "/")
|
||||
return BindSourcesToStructsFS(fileSystem, filePath, service, dst)
|
||||
}
|
||||
|
||||
// BindSourcesToStructsFS is like BindSourcesToStructs but reads from the given fs.FS and path.
|
||||
func BindSourcesToStructsFS(fileSystem fs.FS, filePath, service string, dst any) error {
|
||||
cnf := gofig.NewWithOptions(service)
|
||||
cnf.WithOptions(func(options *gofig.Options) {
|
||||
options.ParseEnv = true
|
||||
options.DecoderConfig.TagName = decoderConfigTagName
|
||||
})
|
||||
cnf.AddDriver(gooyaml.Driver)
|
||||
|
||||
yamlContent, err := fs.ReadFile(fileSystem, filePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
// the error is ignored on purpose, matching the pre-extraction behavior:
|
||||
// an unparseable yaml file binds nothing instead of failing the startup
|
||||
_ = cnf.LoadSources("yaml", yamlContent)
|
||||
|
||||
err = cnf.BindStruct("", &dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
type TestConfig struct {
|
||||
A string `yaml:"a"`
|
||||
B string `yaml:"b"`
|
||||
C string `yaml:"c"`
|
||||
}
|
||||
|
||||
func TestBindSourcesToStructs(t *testing.T) {
|
||||
// setup test env: one var set to pin env expansion, two deliberately
|
||||
// unset to pin the defaults
|
||||
t.Setenv("BINDER_TEST_SET_VAR", "from-env")
|
||||
yaml := `
|
||||
a: "${BINDER_TEST_SET_VAR|no-foo}"
|
||||
b: "${BINDER_TEST_UNSET_VAR|no-bar}"
|
||||
c: "${BINDER_TEST_OTHER_UNSET_VAR|code}"
|
||||
`
|
||||
filePath := "etc/opencloud/foo.yaml"
|
||||
fs := fstest.MapFS{
|
||||
filePath: {Data: []byte(yaml)},
|
||||
}
|
||||
// perform test
|
||||
c := TestConfig{}
|
||||
err := BindSourcesToStructsFS(fs, filePath, "foo", &c)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, c.A, "from-env")
|
||||
assert.Equal(t, c.B, "no-bar")
|
||||
assert.Equal(t, c.C, "code")
|
||||
}
|
||||
|
||||
func TestBindSourcesToStructs_UnknownFile(t *testing.T) {
|
||||
// setup test env
|
||||
filePath := "etc/opencloud/foo.yaml"
|
||||
fs := fstest.MapFS{}
|
||||
// perform test
|
||||
c := TestConfig{}
|
||||
err := BindSourcesToStructsFS(fs, filePath, "foo", &c)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, c.A, "")
|
||||
assert.Equal(t, c.B, "")
|
||||
assert.Equal(t, c.C, "")
|
||||
}
|
||||
+3
-42
@@ -1,54 +1,15 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
gofig "github.com/gookit/config/v2"
|
||||
gooyaml "github.com/gookit/config/v2/yaml"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/defaults"
|
||||
)
|
||||
|
||||
var (
|
||||
// decoderConfigTagName sets the tag name to be used from the config structs
|
||||
// currently we only support "yaml" because we only support config loading
|
||||
// from yaml files and the yaml parser has no simple way to set a custom tag name to use
|
||||
decoderConfigTagName = "yaml"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/binder"
|
||||
)
|
||||
|
||||
// BindSourcesToStructs assigns any config value from a config file / env variable to struct `dst`.
|
||||
// The implementation lives in pkg/config/binder.
|
||||
func BindSourcesToStructs(service string, dst any) error {
|
||||
fileSystem := os.DirFS("/")
|
||||
filePath := strings.TrimLeft(path.Join(defaults.BaseConfigPath(), service+".yaml"), "/")
|
||||
return bindSourcesToStructs(fileSystem, filePath, service, dst)
|
||||
}
|
||||
|
||||
func bindSourcesToStructs(fileSystem fs.FS, filePath, service string, dst any) error {
|
||||
cnf := gofig.NewWithOptions(service)
|
||||
cnf.WithOptions(func(options *gofig.Options) {
|
||||
options.ParseEnv = true
|
||||
options.DecoderConfig.TagName = decoderConfigTagName
|
||||
})
|
||||
cnf.AddDriver(gooyaml.Driver)
|
||||
|
||||
yamlContent, err := fs.ReadFile(fileSystem, filePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
_ = cnf.LoadSources("yaml", yamlContent)
|
||||
|
||||
err = cnf.BindStruct("", &dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return binder.BindSourcesToStructs(service, dst)
|
||||
}
|
||||
|
||||
// LocalEndpoint returns the local endpoint for a given protocol and address.
|
||||
|
||||
@@ -4,54 +4,10 @@ import (
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/binder"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
type TestConfig struct {
|
||||
A string `yaml:"a"`
|
||||
B string `yaml:"b"`
|
||||
C string `yaml:"c"`
|
||||
}
|
||||
|
||||
func TestBindSourcesToStructs(t *testing.T) {
|
||||
// setup test env
|
||||
yaml := `
|
||||
a: "${FOO_VAR|no-foo}"
|
||||
b: "${BAR_VAR|no-bar}"
|
||||
c: "${CODE_VAR|code}"
|
||||
`
|
||||
filePath := "etc/opencloud/foo.yaml"
|
||||
fs := fstest.MapFS{
|
||||
filePath: {Data: []byte(yaml)},
|
||||
}
|
||||
// perform test
|
||||
c := TestConfig{}
|
||||
err := bindSourcesToStructs(fs, filePath, "foo", &c)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, c.A, "no-foo")
|
||||
assert.Equal(t, c.B, "no-bar")
|
||||
assert.Equal(t, c.C, "code")
|
||||
}
|
||||
|
||||
func TestBindSourcesToStructs_UnknownFile(t *testing.T) {
|
||||
// setup test env
|
||||
filePath := "etc/opencloud/foo.yaml"
|
||||
fs := fstest.MapFS{}
|
||||
// perform test
|
||||
c := TestConfig{}
|
||||
err := bindSourcesToStructs(fs, filePath, "foo", &c)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, c.A, "")
|
||||
assert.Equal(t, c.B, "")
|
||||
assert.Equal(t, c.C, "")
|
||||
}
|
||||
|
||||
func TestBindSourcesToStructs_NoEnvVar(t *testing.T) {
|
||||
// setup test env
|
||||
yaml := `
|
||||
@@ -180,7 +136,7 @@ clientlog:
|
||||
}
|
||||
// perform test
|
||||
c := Config{}
|
||||
err := bindSourcesToStructs(fs, filePath, "foo", &c)
|
||||
err := binder.BindSourcesToStructsFS(fs, filePath, "foo", &c)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user