switch ocs to struct tag based env config

This commit is contained in:
Willy Kloucek
2021-12-16 18:53:06 +01:00
committed by Jörn Friedrich Dreyer
parent cb27090cea
commit 161dd949fc
18 changed files with 101 additions and 193 deletions

View File

@@ -82,7 +82,7 @@ func ParseConfig(c *cli.Context, cfg *config.Config) error {
}
// merge environment variable config on top of the current config
if err := mergo.Merge(cfg, envCfg, mergo.WithOverride); err != nil {
if err := mergo.Merge(cfg, envCfg, mergo.WithOverride); err != nil && err.Error() != "none of the target fields were set from environment variables" {
return err
}

View File

@@ -4,10 +4,9 @@ import (
"context"
"strings"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/oklog/run"
"github.com/owncloud/ocis/accounts/pkg/config"
"github.com/owncloud/ocis/accounts/pkg/logging"
"github.com/owncloud/ocis/accounts/pkg/metrics"
"github.com/owncloud/ocis/accounts/pkg/server/grpc"
"github.com/owncloud/ocis/accounts/pkg/server/http"
@@ -16,18 +15,6 @@ import (
"github.com/urfave/cli/v2"
)
// TODO: don't redeclare from ocis-pkg/log/log.go
// LoggerFromConfig initializes a service-specific logger instance.
func LoggerFromConfig(name string, cfg config.Log) log.Logger {
return log.NewLogger(
log.Name(name),
log.Level(cfg.Level),
log.Pretty(cfg.Pretty),
log.Color(cfg.Color),
log.File(cfg.File),
)
}
// Server is the entry point for the server command.
func Server(cfg *config.Config) *cli.Command {
return &cli.Command{
@@ -48,7 +35,7 @@ func Server(cfg *config.Config) *cli.Command {
return nil
},
Action: func(c *cli.Context) error {
logger := LoggerFromConfig("accounts", cfg.Log)
logger := logging.Configure(cfg.Service.Name, cfg.Log)
err := tracing.Configure(cfg)
if err != nil {
return err

View File

@@ -0,0 +1,17 @@
package logging
import (
"github.com/owncloud/ocis/accounts/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/log"
)
// LoggerFromConfig initializes a service-specific logger instance.
func Configure(name string, cfg config.Log) log.Logger {
return log.NewLogger(
log.Name(name),
log.Level(cfg.Level),
log.Pretty(cfg.Pretty),
log.Color(cfg.Color),
log.File(cfg.File),
)
}

View File

@@ -12,11 +12,12 @@ import (
mgrpcc "github.com/asim/go-micro/plugins/client/grpc/v4"
empty "github.com/golang/protobuf/ptypes/empty"
"github.com/owncloud/ocis/accounts/pkg/command"
"github.com/owncloud/ocis/accounts/pkg/config"
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
svc "github.com/owncloud/ocis/accounts/pkg/service/v0"
oclog "github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/ocis-pkg/shared"
settings "github.com/owncloud/ocis/settings/pkg/proto/v0"
"github.com/stretchr/testify/assert"
"go-micro.dev/v4/client"
@@ -85,7 +86,7 @@ func init() {
var hdlr *svc.Service
var err error
if hdlr, err = svc.New(svc.Logger(command.LoggerFromConfig("accounts", cfg.Log)), svc.Config(cfg), svc.RoleService(buildRoleServiceMock())); err != nil {
if hdlr, err = svc.New(svc.Logger(oclog.LoggerFromConfig("accounts", shared.Log(cfg.Log))), svc.Config(cfg), svc.RoleService(buildRoleServiceMock())); err != nil {
log.Fatalf("Could not create new service")
}

View File

@@ -64,7 +64,6 @@ type Backend struct {
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Log *shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
Service Service `ocisConfig:"service"`

View File

@@ -46,7 +46,6 @@ type GraphExplorer struct {
// Config combines all available configuration parts.
type Config struct {
File string `ocisConfig:"file"`
Log shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
HTTP HTTP `ocisConfig:"http"`

View File

@@ -81,7 +81,6 @@ type Identity struct {
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Log *shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
HTTP HTTP `ocisConfig:"http"`

View File

@@ -100,7 +100,6 @@ type Settings struct {
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Log *shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
HTTP HTTP `ocisConfig:"http"`

View File

@@ -4,14 +4,14 @@ import (
"context"
"os"
"github.com/owncloud/ocis/ocis-pkg/shared"
"github.com/imdario/mergo"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/version"
"github.com/owncloud/ocis/ocs/pkg/config"
"github.com/thejerf/suture/v4"
"github.com/urfave/cli/v2"
"github.com/wkloucek/envdecode"
)
// Execute is the entry point for the ocis-ocs command.
@@ -67,28 +67,35 @@ func NewLogger(cfg *config.Config) log.Logger {
// ParseConfig loads idp configuration from known paths.
func ParseConfig(c *cli.Context, cfg *config.Config) error {
conf, err := ociscfg.BindSourcesToStructs("ocs", cfg)
_, err := ociscfg.BindSourcesToStructs("ocs", cfg)
if err != nil {
return err
}
// provide with defaults for shared logging, since we need a valid destination address for BindEnv.
if cfg.Log == nil && cfg.Commons != nil && cfg.Commons.Log != nil {
cfg.Log = &shared.Log{
Level: cfg.Commons.Log.Level,
Pretty: cfg.Commons.Log.Pretty,
Color: cfg.Commons.Log.Color,
File: cfg.Commons.Log.File,
}
} else if cfg.Log == nil && cfg.Commons == nil {
cfg.Log = &shared.Log{}
}
//if cfg.Log == nil && cfg.Commons != nil && cfg.Commons.Log != nil {
// cfg.Log = &shared.Log{
// Level: cfg.Commons.Log.Level,
// Pretty: cfg.Commons.Log.Pretty,
// Color: cfg.Commons.Log.Color,
// File: cfg.Commons.Log.File,
// }
//} else if cfg.Log == nil && cfg.Commons == nil {
// cfg.Log = &shared.Log{}
//}
// load all env variables relevant to the config in the current context.
conf.LoadOSEnv(config.GetEnv(cfg), false)
envCfg := config.Config{}
if err := envdecode.Decode(&envCfg); err != nil {
return err
}
bindings := config.StructMappings(cfg)
return ociscfg.BindEnv(conf, bindings)
// merge environment variable config on top of the current config
if err := mergo.Merge(cfg, envCfg, mergo.WithOverride); err != nil && err.Error() != "none of the target fields were set from environment variables" {
return err
}
return nil
}
// SutureService allows for the ocs command to be embedded and supervised by a suture supervisor tree.

View File

@@ -4,6 +4,7 @@ import (
"context"
"strings"
"github.com/owncloud/ocis/ocs/pkg/logging"
"github.com/owncloud/ocis/ocs/pkg/tracing"
"github.com/oklog/run"
@@ -31,9 +32,9 @@ func Server(cfg *config.Config) *cli.Command {
return nil
},
Action: func(c *cli.Context) error {
logger := NewLogger(cfg)
if err := tracing.Configure(cfg); err != nil {
logger := logging.Configure(cfg.Service.Name, cfg.Log)
err := tracing.Configure(cfg)
if err != nil {
return err
}

View File

@@ -8,10 +8,10 @@ import (
// Debug defines the available debug configuration.
type Debug struct {
Addr string `ocisConfig:"addr"`
Token string `ocisConfig:"token"`
Pprof bool `ocisConfig:"pprof"`
Zpages bool `ocisConfig:"zpages"`
Addr string `ocisConfig:"addr" env:"OCS_DEBUG_ADDR"`
Token string `ocisConfig:"token" env:"OCS_DEBUG_TOKEN"`
Pprof bool `ocisConfig:"pprof" env:"OCS_DEBUG_PPROF"`
Zpages bool `ocisConfig:"zpages" env:"OCS_DEBUG_ZPAGES"`
}
// CORS defines the available cors configuration.
@@ -24,60 +24,67 @@ type CORS struct {
// HTTP defines the available http configuration.
type HTTP struct {
Addr string `ocisConfig:"addr"`
Root string `ocisConfig:"root"`
Namespace string `ocisConfig:"namespace"`
CORS CORS `ocisConfig:"cors"`
Addr string `ocisConfig:"addr" env:"OCS_HTTP_ADDR"`
Root string `ocisConfig:"root" env:"OCS_HTTP_ROOT"`
Namespace string
CORS CORS `ocisConfig:"cors"`
}
// Service defines the available service configuration.
type Service struct {
Name string `ocisConfig:"name"`
Version string `ocisConfig:"version"`
Name string
Version string
}
// Tracing defines the available tracing configuration.
type Tracing struct {
Enabled bool `ocisConfig:"enabled"`
Type string `ocisConfig:"type"`
Endpoint string `ocisConfig:"endpoint"`
Collector string `ocisConfig:"collector"`
Service string `ocisConfig:"service"`
Enabled bool `ocisConfig:"enabled" env:"OCIS_TRACING_ENABLED;OCS_TRACING_ENABLED"`
Type string `ocisConfig:"type" env:"OCIS_TRACING_TYPE;OCS_TRACING_TYPE"`
Endpoint string `ocisConfig:"endpoint" env:"OCIS_TRACING_ENDPOINT;OCS_TRACING_ENDPOINT"`
Collector string `ocisConfig:"collector" env:"OCIS_TRACING_COLLECTOR;OCS_TRACING_COLLECTOR"`
Service string `ocisConfig:"service" env:"OCS_TRACING_SERVICE"`
}
// Log defines the available log configuration.
type Log struct {
Level string `mapstructure:"level" env:"OCIS_LOG_LEVEL;OCS_LOG_LEVEL"`
Pretty bool `mapstructure:"pretty" env:"OCIS_LOG_PRETTY;OCS_LOG_PRETTY"`
Color bool `mapstructure:"color" env:"OCIS_LOG_COLOR;OCS_LOG_COLOR"`
File string `mapstructure:"file" env:"OCIS_LOG_FILE;OCS_LOG_FILE"`
}
// Reva defines all available REVA configuration.
type Reva struct {
Address string `ocisConfig:"address"`
Address string `ocisConfig:"address" env:"REVA_GATEWAY"`
}
// TokenManager is the config for using the reva token manager
type TokenManager struct {
JWTSecret string `ocisConfig:"jwt_secret"`
JWTSecret string `ocisConfig:"jwt_secret" env:"OCIS_JWT_SECRET;OCS_JWT_SECRET"`
}
// IdentityManagement keeps track of the OIDC address. This is because Reva requisite of uniqueness for users
// is based in the combination of IDP hostname + UserID. For more information see:
// https://github.com/cs3org/reva/blob/4fd0229f13fae5bc9684556a82dbbd0eced65ef9/pkg/storage/utils/decomposedfs/node/node.go#L856-L865
type IdentityManagement struct {
Address string `ocisConfig:"address"`
Address string `ocisConfig:"address" env:"OCIS_URL;OCS_IDM_ADDRESS"`
}
// Config combines all available configuration parts.
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Log *shared.Log `ocisConfig:"log"`
Log Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
HTTP HTTP `ocisConfig:"http"`
Tracing Tracing `ocisConfig:"tracing"`
TokenManager TokenManager `ocisConfig:"token_manager"`
Service Service `ocisConfig:"service"`
AccountBackend string `ocisConfig:"account_backend"`
Reva Reva `ocisConfig:"reva"`
StorageUsersDriver string `ocisConfig:"storage_users_driver"`
MachineAuthAPIKey string `ocisConfig:"machine_auth_api_key"`
IdentityManagement IdentityManagement `ocisConfig:"identity_management"`
AccountBackend string `ocisConfig:"account_backend" env:"OCS_ACCOUNT_BACKEND_TYPE"`
StorageUsersDriver string `ocisConfig:"storage_users_driver" env:"STORAGE_USERS_DRIVER;OCS_STORAGE_USERS_DRIVER"`
MachineAuthAPIKey string `ocisConfig:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;OCS_MACHINE_AUTH_API_KEY"`
Context context.Context
Supervised bool

View File

@@ -1,119 +0,0 @@
package config
import "github.com/owncloud/ocis/ocis-pkg/shared"
// GetEnv fetches a list of known env variables for this extension. It is to be used by gookit, as it provides a list
// with all the environment variables an extension supports.
func GetEnv(cfg *Config) []string {
var r = make([]string, len(structMappings(cfg)))
for i := range structMappings(cfg) {
r = append(r, structMappings(cfg)[i].EnvVars...)
}
return r
}
// StructMappings binds a set of environment variables to a destination on cfg. Iterating over this set and editing the
// Destination value of a binding will alter the original value, as it is a pointer to its memory address. This lets
// us propagate changes easier.
func StructMappings(cfg *Config) []shared.EnvBinding {
return structMappings(cfg)
}
// structMappings binds a set of environment variables to a destination on cfg.
func structMappings(cfg *Config) []shared.EnvBinding {
return []shared.EnvBinding{
{
EnvVars: []string{"OCIS_LOG_FILE", "OCS_LOG_FILE"},
Destination: &cfg.Log.File,
},
{
EnvVars: []string{"OCIS_LOG_LEVEL", "OCS_LOG_LEVEL"},
Destination: &cfg.Log.Level,
},
{
EnvVars: []string{"OCIS_LOG_PRETTY", "OCS_LOG_PRETTY"},
Destination: &cfg.Log.Pretty,
},
{
EnvVars: []string{"OCIS_LOG_COLOR", "OCS_LOG_COLOR"},
Destination: &cfg.Log.Color,
},
{
EnvVars: []string{"OCS_CONFIG_FILE"},
Destination: &cfg.File,
},
{
EnvVars: []string{"OCIS_TRACING_ENABLED", "OCS_TRACING_ENABLED"},
Destination: &cfg.Tracing.Enabled,
},
{
EnvVars: []string{"OCIS_TRACING_TYPE", "OCS_TRACING_TYPE"},
Destination: &cfg.Tracing.Type,
},
{
EnvVars: []string{"OCIS_TRACING_ENDPOINT", "OCS_TRACING_ENDPOINT"},
Destination: &cfg.Tracing.Endpoint,
},
{
EnvVars: []string{"OCIS_TRACING_COLLECTOR", "OCS_TRACING_COLLECTOR"},
Destination: &cfg.Tracing.Collector,
},
{
EnvVars: []string{"OCS_TRACING_SERVICE"},
Destination: &cfg.Tracing.Service,
},
{
EnvVars: []string{"OCS_DEBUG_ADDR"},
Destination: &cfg.Debug.Addr,
},
{
EnvVars: []string{"OCS_DEBUG_TOKEN"},
Destination: &cfg.Debug.Token,
},
{
EnvVars: []string{"OCS_DEBUG_PPROF"},
Destination: &cfg.Debug.Pprof,
},
{
EnvVars: []string{"OCS_DEBUG_ZPAGES"},
Destination: &cfg.Debug.Zpages,
},
{
EnvVars: []string{"OCS_HTTP_ADDR"},
Destination: &cfg.HTTP.Addr,
},
{
EnvVars: []string{"OCS_HTTP_NAMESPACE"},
Destination: &cfg.HTTP.Namespace,
},
{
EnvVars: []string{"OCS_HTTP_ROOT"},
Destination: &cfg.HTTP.Root,
},
{
EnvVars: []string{"OCIS_JWT_SECRET", "OCS_JWT_SECRET"},
Destination: &cfg.TokenManager.JWTSecret,
},
{
EnvVars: []string{"OCS_ACCOUNT_BACKEND_TYPE"},
Destination: &cfg.AccountBackend,
},
{
EnvVars: []string{"REVA_GATEWAY"},
Destination: &cfg.Reva.Address,
},
{
EnvVars: []string{"OCIS_MACHINE_AUTH_API_KEY", "OCS_MACHINE_AUTH_API_KEY"},
Destination: &cfg.MachineAuthAPIKey,
},
{
EnvVars: []string{"OCIS_URL", "OCS_IDM_ADDRESS"},
Destination: &cfg.IdentityManagement.Address,
},
{
EnvVars: []string{"STORAGE_USERS_DRIVER", "OCS_STORAGE_USERS_DRIVER"},
Destination: &cfg.StorageUsersDriver,
},
}
}

View File

@@ -0,0 +1,17 @@
package logging
import (
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocs/pkg/config"
)
// LoggerFromConfig initializes a service-specific logger instance.
func Configure(name string, cfg config.Log) log.Logger {
return log.NewLogger(
log.Name(name),
log.Level(cfg.Level),
log.Pretty(cfg.Pretty),
log.Color(cfg.Color),
log.File(cfg.File),
)
}

View File

@@ -14,8 +14,6 @@ import (
"strings"
"testing"
"github.com/owncloud/ocis/ocis-pkg/shared"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/auth/scope"
@@ -23,10 +21,10 @@ import (
"github.com/cs3org/reva/pkg/token/manager/jwt"
"github.com/golang/protobuf/ptypes/empty"
accountsCfg "github.com/owncloud/ocis/accounts/pkg/config"
accountsLogging "github.com/owncloud/ocis/accounts/pkg/logging"
accountsProto "github.com/owncloud/ocis/accounts/pkg/proto/v0"
accountsSvc "github.com/owncloud/ocis/accounts/pkg/service/v0"
ocisLog "github.com/owncloud/ocis/ocis-pkg/log"
oclog "github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/ocs/pkg/config"
svc "github.com/owncloud/ocis/ocs/pkg/service/v0"
@@ -565,7 +563,7 @@ func init() {
Path: dataPath,
},
},
Log: &shared.Log{
Log: accountsCfg.Log{
Level: "info",
Pretty: true,
Color: true,
@@ -576,7 +574,7 @@ func init() {
var err error
if hdlr, err = accountsSvc.New(
accountsSvc.Logger(oclog.LoggerFromConfig("accounts", *c.Log)),
accountsSvc.Logger(accountsLogging.Configure("accounts", c.Log)),
accountsSvc.Config(c),
accountsSvc.RoleService(buildRoleServiceMock()),
); err != nil {
@@ -712,7 +710,7 @@ func getService() svc.Service {
TokenManager: config.TokenManager{
JWTSecret: jwtSecret,
},
Log: &shared.Log{
Log: config.Log{
Level: "debug",
},
}

View File

@@ -70,7 +70,6 @@ type TokenManager struct {
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Service Service `ocisConfig:"service"`
Log *shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`

View File

@@ -507,7 +507,6 @@ type Asset struct {
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Log *shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
Reva Reva `ocisConfig:"reva"`

View File

@@ -40,7 +40,6 @@ type Tracing struct {
// Config combines all available configuration parts.
type Config struct {
File string `ocisConfig:"file"`
Log shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
GRPC GRPC `ocisConfig:"grpc"`

View File

@@ -94,7 +94,6 @@ type Web struct {
type Config struct {
*shared.Commons
File string `ocisConfig:"file"`
Log *shared.Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
HTTP HTTP `ocisConfig:"http"`