diff --git a/cmd/s3-gw/app.go b/cmd/s3-gw/app.go index 3645220c..3e94b42d 100644 --- a/cmd/s3-gw/app.go +++ b/cmd/s3-gw/app.go @@ -65,7 +65,7 @@ type ( App struct { ctr s3middleware.Center log *zap.Logger - cfg *viper.Viper + cfg *appCfg pool *pool.Pool treePool *treepool.Pool key *keys.PrivateKey @@ -161,15 +161,15 @@ func (s *loggerSettings) setMetrics(appMetrics *metrics.AppMetrics) { s.appMetrics = appMetrics } -func newApp(ctx context.Context, v *viper.Viper) *App { +func newApp(ctx context.Context, cfg *appCfg) *App { logSettings := &loggerSettings{} - log := pickLogger(v, logSettings) - settings := newAppSettings(log, v) - appCache := layer.NewCache(getCacheOptions(v, log.logger)) + log := pickLogger(cfg.config(), logSettings) + settings := newAppSettings(log, cfg.config()) + appCache := layer.NewCache(getCacheOptions(cfg.config(), log.logger)) app := &App{ log: log.logger, - cfg: v, + cfg: cfg, cache: appCache, webDone: make(chan struct{}, 1), @@ -184,6 +184,10 @@ func newApp(ctx context.Context, v *viper.Viper) *App { return app } +func (a *App) config() *viper.Viper { + return a.cfg.config() +} + func (a *App) init(ctx context.Context) { a.initPools(ctx) a.initResolver() @@ -198,7 +202,7 @@ func (a *App) init(ctx context.Context) { } func (a *App) initAuthCenter(ctx context.Context) { - if a.cfg.IsSet(cfgContainersAccessBox) { + if a.config().IsSet(cfgContainersAccessBox) { cnrID, err := a.resolveContainerID(ctx, cfgContainersAccessBox) if err != nil { a.log.Fatal(logs.CouldNotFetchAccessBoxContainerInfo, zap.Error(err)) @@ -209,11 +213,11 @@ func (a *App) initAuthCenter(ctx context.Context) { cfg := tokens.Config{ FrostFS: frostfs.NewAuthmateFrostFS(frostfs.NewFrostFS(a.pool, a.key), a.log), Key: a.key, - CacheConfig: getAccessBoxCacheConfig(a.cfg, a.log), - RemovingCheckAfterDurations: fetchRemovingCheckInterval(a.cfg, a.log), + CacheConfig: getAccessBoxCacheConfig(a.config(), a.log), + RemovingCheckAfterDurations: fetchRemovingCheckInterval(a.config(), a.log), } - a.ctr = auth.New(tokens.New(cfg), a.cfg.GetStringSlice(cfgAllowedAccessKeyIDPrefixes), a.settings) + a.ctr = auth.New(tokens.New(cfg), a.config().GetStringSlice(cfgAllowedAccessKeyIDPrefixes), a.settings) } func (a *App) initLayer(ctx context.Context) { @@ -227,7 +231,7 @@ func (a *App) initLayer(ctx context.Context) { user.IDFromKey(&gateOwner, a.key.PrivateKey.PublicKey) var corsCnrInfo *data.BucketInfo - if a.cfg.IsSet(cfgContainersCORS) { + if a.config().IsSet(cfgContainersCORS) { corsCnrInfo, err = a.fetchContainerInfo(ctx, cfgContainersCORS) if err != nil { a.log.Fatal(logs.CouldNotFetchCORSContainerInfo, zap.Error(err)) @@ -235,7 +239,7 @@ func (a *App) initLayer(ctx context.Context) { } var lifecycleCnrInfo *data.BucketInfo - if a.cfg.IsSet(cfgContainersLifecycle) { + if a.config().IsSet(cfgContainersLifecycle) { lifecycleCnrInfo, err = a.fetchContainerInfo(ctx, cfgContainersLifecycle) if err != nil { a.log.Fatal(logs.CouldNotFetchLifecycleContainerInfo, zap.Error(err)) @@ -599,7 +603,7 @@ func (a *App) initMetrics() { Logger: a.log, PoolStatistics: frostfs.NewPoolStatistic(a.pool), TreeStatistic: a.treePool, - Enabled: a.cfg.GetBool(cfgPrometheusEnabled), + Enabled: a.config().GetBool(cfgPrometheusEnabled), } a.metrics = metrics.NewAppMetrics(cfg) @@ -609,9 +613,9 @@ func (a *App) initMetrics() { func (a *App) initFrostfsID(ctx context.Context) { cli, err := ffidcontract.New(ctx, ffidcontract.Config{ - RPCAddress: a.cfg.GetString(cfgRPCEndpoint), - Contract: a.cfg.GetString(cfgFrostfsIDContract), - ProxyContract: a.cfg.GetString(cfgProxyContract), + RPCAddress: a.config().GetString(cfgRPCEndpoint), + Contract: a.config().GetString(cfgFrostfsIDContract), + ProxyContract: a.config().GetString(cfgProxyContract), Key: a.key, Waiter: commonclient.WaiterOptions{ IgnoreAlreadyExistsError: false, @@ -623,7 +627,7 @@ func (a *App) initFrostfsID(ctx context.Context) { } a.frostfsid, err = frostfsid.NewFrostFSID(frostfsid.Config{ - Cache: cache.NewFrostfsIDCache(getFrostfsIDCacheConfig(a.cfg, a.log)), + Cache: cache.NewFrostfsIDCache(getFrostfsIDCacheConfig(a.config(), a.log)), FrostFSID: cli, Logger: a.log, }) @@ -634,9 +638,9 @@ func (a *App) initFrostfsID(ctx context.Context) { func (a *App) initPolicyStorage(ctx context.Context) { policyContract, err := contract.New(ctx, contract.Config{ - RPCAddress: a.cfg.GetString(cfgRPCEndpoint), - Contract: a.cfg.GetString(cfgPolicyContract), - ProxyContract: a.cfg.GetString(cfgProxyContract), + RPCAddress: a.config().GetString(cfgRPCEndpoint), + Contract: a.config().GetString(cfgPolicyContract), + ProxyContract: a.config().GetString(cfgProxyContract), Key: a.key, Waiter: commonclient.WaiterOptions{ IgnoreAlreadyExistsError: false, @@ -649,7 +653,7 @@ func (a *App) initPolicyStorage(ctx context.Context) { a.policyStorage = policy.NewStorage(policy.StorageConfig{ Contract: policyContract, - Cache: cache.NewMorphPolicyCache(getMorphPolicyCacheConfig(a.cfg, a.log)), + Cache: cache.NewMorphPolicyCache(getMorphPolicyCacheConfig(a.config(), a.log)), Log: a.log, }) } @@ -665,13 +669,13 @@ func (a *App) initResolver() { func (a *App) getResolverConfig() *resolver.Config { return &resolver.Config{ FrostFS: frostfs.NewResolverFrostFS(a.pool), - RPCAddress: a.cfg.GetString(cfgRPCEndpoint), + RPCAddress: a.config().GetString(cfgRPCEndpoint), } } func (a *App) getResolverOrder() []string { - order := a.cfg.GetStringSlice(cfgResolveOrder) - if a.cfg.GetString(cfgRPCEndpoint) == "" { + order := a.config().GetStringSlice(cfgResolveOrder) + if a.config().GetString(cfgRPCEndpoint) == "" { order = remove(order, resolver.NNSResolver) a.log.Warn(logs.ResolverNNSWontBeUsedSinceRPCEndpointIsntProvided) } @@ -689,15 +693,15 @@ func (a *App) initTracing(ctx context.Context) { instanceID = a.servers[0].Address() } cfg := tracing.Config{ - Enabled: a.cfg.GetBool(cfgTracingEnabled), - Exporter: tracing.Exporter(a.cfg.GetString(cfgTracingExporter)), - Endpoint: a.cfg.GetString(cfgTracingEndpoint), + Enabled: a.config().GetBool(cfgTracingEnabled), + Exporter: tracing.Exporter(a.config().GetString(cfgTracingExporter)), + Endpoint: a.config().GetString(cfgTracingEndpoint), Service: "frostfs-s3-gw", InstanceID: instanceID, Version: version.Version, } - if trustedCa := a.cfg.GetString(cfgTracingTrustedCa); trustedCa != "" { + if trustedCa := a.config().GetString(cfgTracingTrustedCa); trustedCa != "" { caBytes, err := os.ReadFile(trustedCa) if err != nil { a.log.Warn(logs.FailedToInitializeTracing, zap.Error(err)) @@ -712,7 +716,7 @@ func (a *App) initTracing(ctx context.Context) { cfg.ServerCaCertPool = certPool } - attributes, err := fetchTracingAttributes(a.cfg) + attributes, err := fetchTracingAttributes(a.config()) if err != nil { a.log.Warn(logs.FailedToInitializeTracing, zap.Error(err)) return @@ -760,8 +764,8 @@ func (a *App) initPools(ctx context.Context) { var prm pool.InitParameters var prmTree treepool.InitParameters - password := wallet.GetPassword(a.cfg, cfgWalletPassphrase) - key, err := wallet.GetKeyFromPath(a.cfg.GetString(cfgWalletPath), a.cfg.GetString(cfgWalletAddress), password) + password := wallet.GetPassword(a.config(), cfgWalletPassphrase) + key, err := wallet.GetKeyFromPath(a.config().GetString(cfgWalletPath), a.config().GetString(cfgWalletAddress), password) if err != nil { a.log.Fatal(logs.CouldNotLoadFrostFSPrivateKey, zap.Error(err)) } @@ -770,36 +774,36 @@ func (a *App) initPools(ctx context.Context) { prmTree.SetKey(key) a.log.Info(logs.UsingCredentials, zap.String("FrostFS", hex.EncodeToString(key.PublicKey().Bytes()))) - for _, peer := range fetchPeers(a.log, a.cfg) { + for _, peer := range fetchPeers(a.log, a.config()) { prm.AddNode(peer) prmTree.AddNode(peer) } - connTimeout := fetchConnectTimeout(a.cfg) + connTimeout := fetchConnectTimeout(a.config()) prm.SetNodeDialTimeout(connTimeout) prmTree.SetNodeDialTimeout(connTimeout) - streamTimeout := fetchStreamTimeout(a.cfg) + streamTimeout := fetchStreamTimeout(a.config()) prm.SetNodeStreamTimeout(streamTimeout) prmTree.SetNodeStreamTimeout(streamTimeout) - healthCheckTimeout := fetchHealthCheckTimeout(a.cfg) + healthCheckTimeout := fetchHealthCheckTimeout(a.config()) prm.SetHealthcheckTimeout(healthCheckTimeout) prmTree.SetHealthcheckTimeout(healthCheckTimeout) - rebalanceInterval := fetchRebalanceInterval(a.cfg) + rebalanceInterval := fetchRebalanceInterval(a.config()) prm.SetClientRebalanceInterval(rebalanceInterval) prmTree.SetClientRebalanceInterval(rebalanceInterval) - errorThreshold := fetchErrorThreshold(a.cfg) + errorThreshold := fetchErrorThreshold(a.config()) prm.SetErrorThreshold(errorThreshold) - prm.SetGracefulCloseOnSwitchTimeout(fetchSetGracefulCloseOnSwitchTimeout(a.cfg)) + prm.SetGracefulCloseOnSwitchTimeout(fetchSetGracefulCloseOnSwitchTimeout(a.config())) prm.SetLogger(a.log) prmTree.SetLogger(a.log) - prmTree.SetMaxRequestAttempts(a.cfg.GetInt(cfgTreePoolMaxAttempts)) + prmTree.SetMaxRequestAttempts(a.config().GetInt(cfgTreePoolMaxAttempts)) interceptors := []grpc.DialOption{ grpc.WithUnaryInterceptor(grpctracing.NewUnaryClientInteceptor()), @@ -818,7 +822,7 @@ func (a *App) initPools(ctx context.Context) { a.log.Fatal(logs.FailedToDialConnectionPool, zap.Error(err)) } - if a.cfg.GetBool(cfgTreePoolNetmapSupport) { + if a.config().GetBool(cfgTreePoolNetmapSupport) { prmTree.SetNetMapInfoSource(frostfs.NewSource(frostfs.NewFrostFS(p, key), a.cache)) } @@ -895,10 +899,10 @@ func (a *App) Serve(ctx context.Context) { srv := new(http.Server) srv.Handler = chiRouter srv.ErrorLog = zap.NewStdLog(a.log) - srv.ReadTimeout = a.cfg.GetDuration(cfgWebReadTimeout) - srv.ReadHeaderTimeout = a.cfg.GetDuration(cfgWebReadHeaderTimeout) - srv.WriteTimeout = a.cfg.GetDuration(cfgWebWriteTimeout) - srv.IdleTimeout = a.cfg.GetDuration(cfgWebIdleTimeout) + srv.ReadTimeout = a.config().GetDuration(cfgWebReadTimeout) + srv.ReadHeaderTimeout = a.config().GetDuration(cfgWebReadHeaderTimeout) + srv.WriteTimeout = a.config().GetDuration(cfgWebWriteTimeout) + srv.IdleTimeout = a.config().GetDuration(cfgWebIdleTimeout) a.startServices() @@ -951,11 +955,11 @@ func shutdownContext() (context.Context, context.CancelFunc) { func (a *App) configReload(ctx context.Context) { a.log.Info(logs.SIGHUPConfigReloadStarted) - if !a.cfg.IsSet(cmdConfig) && !a.cfg.IsSet(cmdConfigDir) { + if !a.config().IsSet(cmdConfig) && !a.config().IsSet(cmdConfigDir) { a.log.Warn(logs.FailedToReloadConfigBecauseItsMissed) return } - if err := readInConfig(a.cfg); err != nil { + if err := a.cfg.reload(); err != nil { a.log.Warn(logs.FailedToReloadConfig, zap.Error(err)) return } @@ -975,7 +979,7 @@ func (a *App) configReload(ctx context.Context) { a.updateSettings() - a.metrics.SetEnabled(a.cfg.GetBool(cfgPrometheusEnabled)) + a.metrics.SetEnabled(a.config().GetBool(cfgPrometheusEnabled)) a.initTracing(ctx) a.setHealthStatus() @@ -983,33 +987,33 @@ func (a *App) configReload(ctx context.Context) { } func (a *App) updateSettings() { - if lvl, err := getLogLevel(a.cfg); err != nil { + if lvl, err := getLogLevel(a.config()); err != nil { a.log.Warn(logs.LogLevelWontBeUpdated, zap.Error(err)) } else { a.settings.logLevel.SetLevel(lvl) } - if err := a.settings.dialerSource.Update(fetchMultinetConfig(a.cfg, a.log)); err != nil { + if err := a.settings.dialerSource.Update(fetchMultinetConfig(a.config(), a.log)); err != nil { a.log.Warn(logs.MultinetConfigWontBeUpdated, zap.Error(err)) } - a.settings.update(a.cfg, a.log) + a.settings.update(a.config(), a.log) } func (a *App) startServices() { a.services = a.services[:0] - pprofService := NewPprofService(a.cfg, a.log) + pprofService := NewPprofService(a.config(), a.log) a.services = append(a.services, pprofService) go pprofService.Start() - prometheusService := NewPrometheusService(a.cfg, a.log, a.metrics.Handler()) + prometheusService := NewPrometheusService(a.config(), a.log, a.metrics.Handler()) a.services = append(a.services, prometheusService) go prometheusService.Start() } func (a *App) initServers(ctx context.Context) { - serversInfo := fetchServers(a.cfg, a.log) + serversInfo := fetchServers(a.config(), a.log) a.servers = make([]Server, 0, len(serversInfo)) for _, serverInfo := range serversInfo { @@ -1036,7 +1040,7 @@ func (a *App) initServers(ctx context.Context) { } func (a *App) updateServers() error { - serversInfo := fetchServers(a.cfg, a.log) + serversInfo := fetchServers(a.config(), a.log) a.mu.Lock() defer a.mu.Unlock() @@ -1171,7 +1175,7 @@ func (a *App) setRuntimeParameters() { return } - softMemoryLimit := fetchSoftMemoryLimit(a.cfg) + softMemoryLimit := fetchSoftMemoryLimit(a.config()) previous := debug.SetMemoryLimit(softMemoryLimit) if softMemoryLimit != previous { a.log.Info(logs.RuntimeSoftMemoryLimitUpdated, @@ -1247,7 +1251,7 @@ func (a *App) fetchContainerInfo(ctx context.Context, cfgKey string) (info *data } func (a *App) resolveContainerID(ctx context.Context, cfgKey string) (cid.ID, error) { - containerString := a.cfg.GetString(cfgKey) + containerString := a.config().GetString(cfgKey) var id cid.ID if err := id.DecodeString(containerString); err != nil { diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go index 87e715cd..8ef38089 100644 --- a/cmd/s3-gw/app_settings.go +++ b/cmd/s3-gw/app_settings.go @@ -10,6 +10,7 @@ import ( "sort" "strconv" "strings" + "sync" "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api" @@ -301,6 +302,49 @@ var ignore = map[string]struct{}{ cmdVersion: {}, } +type appCfg struct { + flags *pflag.FlagSet + + mu sync.RWMutex + settings *viper.Viper +} + +func (a *appCfg) reload() error { + old := a.config() + + v, err := newViper(a.flags) + if err != nil { + return err + } + + if old.IsSet(cmdConfig) { + v.Set(cmdConfig, old.Get(cmdConfig)) + } + if old.IsSet(cmdConfigDir) { + v.Set(cmdConfigDir, old.Get(cmdConfigDir)) + } + + if err = readInConfig(v); err != nil { + return err + } + + a.setConfig(v) + return nil +} + +func (a *appCfg) config() *viper.Viper { + a.mu.RLock() + defer a.mu.RUnlock() + + return a.settings +} + +func (a *appCfg) setConfig(v *viper.Viper) { + a.mu.Lock() + a.settings = v + a.mu.Unlock() +} + func fetchConnectTimeout(cfg *viper.Viper) time.Duration { connTimeout := cfg.GetDuration(cfgConnectTimeout) if connTimeout <= 0 { @@ -878,7 +922,7 @@ func fetchTombstoneWorkerPoolSize(v *viper.Viper) int { return tombstoneWorkerPoolSize } -func newSettings() *viper.Viper { +func newViper(flags *pflag.FlagSet) (*viper.Viper, error) { v := viper.New() v.AutomaticEnv() @@ -887,6 +931,16 @@ func newSettings() *viper.Viper { v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.AllowEmptyEnv(true) + setDefaults(v, flags) + + if v.IsSet(cfgServer+".0."+cfgTLSKeyFile) && v.IsSet(cfgServer+".0."+cfgTLSCertFile) { + v.Set(cfgServer+".0."+cfgTLSEnabled, true) + } + + return v, bindFlags(v, flags) +} + +func newSettings() *appCfg { // flags setup: flags := pflag.NewFlagSet("commandline", pflag.ExitOnError) flags.SetOutput(os.Stdout) @@ -914,15 +968,71 @@ func newSettings() *viper.Viper { flags.String(cfgTLSCertFile, "", "TLS certificate file to use") flags.String(cfgTLSKeyFile, "", "TLS key file to use") - peers := flags.StringArrayP(cfgPeers, "p", nil, "set FrostFS nodes") + flags.StringArrayP(cfgPeers, "p", nil, "set FrostFS nodes") flags.StringP(cfgRPCEndpoint, "r", "", "set RPC endpoint") - resolveMethods := flags.StringSlice(cfgResolveOrder, []string{resolver.DNSResolver}, "set bucket name resolve order") + flags.StringSlice(cfgResolveOrder, []string{resolver.DNSResolver}, "set bucket name resolve order") - domains := flags.StringSliceP(cfgListenDomains, "d", nil, "set domains to be listened") + flags.StringSliceP(cfgListenDomains, "d", nil, "set domains to be listened") - // set defaults: + if err := flags.Parse(os.Args); err != nil { + panic(err) + } + v, err := newViper(flags) + if err != nil { + panic(fmt.Errorf("bind flags: %w", err)) + } + + switch { + case help != nil && *help: + fmt.Printf("FrostFS S3 gateway %s\n", version.Version) + flags.PrintDefaults() + + fmt.Println() + fmt.Println("Default environments:") + fmt.Println() + keys := v.AllKeys() + sort.Strings(keys) + + for i := range keys { + if _, ok := ignore[keys[i]]; ok { + continue + } + + defaultValue := v.GetString(keys[i]) + if len(defaultValue) == 0 { + continue + } + + k := strings.Replace(keys[i], ".", "_", -1) + fmt.Printf("%s_%s = %s\n", envPrefix, strings.ToUpper(k), defaultValue) + } + + fmt.Println() + fmt.Println("Peers preset:") + fmt.Println() + + fmt.Printf("%s_%s_[N]_ADDRESS = string\n", envPrefix, strings.ToUpper(cfgPeers)) + fmt.Printf("%s_%s_[N]_WEIGHT = 0..1 (float)\n", envPrefix, strings.ToUpper(cfgPeers)) + + os.Exit(0) + case versionFlag != nil && *versionFlag: + fmt.Printf("FrostFS S3 Gateway\nVersion: %s\nGoVersion: %s\n", version.Version, runtime.Version()) + os.Exit(0) + } + + if err = readInConfig(v); err != nil { + panic(err) + } + + return &appCfg{ + flags: flags, + settings: v, + } +} + +func setDefaults(v *viper.Viper, flags *pflag.FlagSet) { v.SetDefault(cfgAccessBoxCacheRemovingCheckInterval, defaultAccessBoxCacheRemovingCheckInterval) // logger: @@ -986,78 +1096,21 @@ func newSettings() *viper.Viper { // multinet v.SetDefault(cfgMultinetFallbackDelay, defaultMultinetFallbackDelay) - // Bind flags - if err := bindFlags(v, flags); err != nil { - panic(fmt.Errorf("bind flags: %w", err)) + if resolveMethods, err := flags.GetStringSlice(cfgResolveOrder); err == nil { + v.SetDefault(cfgResolveOrder, resolveMethods) } - if err := flags.Parse(os.Args); err != nil { - panic(err) - } - - if v.IsSet(cfgServer+".0."+cfgTLSKeyFile) && v.IsSet(cfgServer+".0."+cfgTLSCertFile) { - v.Set(cfgServer+".0."+cfgTLSEnabled, true) - } - - if resolveMethods != nil { - v.SetDefault(cfgResolveOrder, *resolveMethods) - } - - if peers != nil && len(*peers) > 0 { - for i := range *peers { - v.SetDefault(cfgPeers+"."+strconv.Itoa(i)+".address", (*peers)[i]) + if peers, err := flags.GetStringArray(cfgPeers); err == nil { + for i := range peers { + v.SetDefault(cfgPeers+"."+strconv.Itoa(i)+".address", peers[i]) v.SetDefault(cfgPeers+"."+strconv.Itoa(i)+".weight", 1) v.SetDefault(cfgPeers+"."+strconv.Itoa(i)+".priority", 1) } } - if domains != nil && len(*domains) > 0 { - v.SetDefault(cfgListenDomains, *domains) + if domains, err := flags.GetStringSlice(cfgListenDomains); err == nil && len(domains) > 0 { + v.SetDefault(cfgListenDomains, domains) } - - switch { - case help != nil && *help: - fmt.Printf("FrostFS S3 gateway %s\n", version.Version) - flags.PrintDefaults() - - fmt.Println() - fmt.Println("Default environments:") - fmt.Println() - keys := v.AllKeys() - sort.Strings(keys) - - for i := range keys { - if _, ok := ignore[keys[i]]; ok { - continue - } - - defaultValue := v.GetString(keys[i]) - if len(defaultValue) == 0 { - continue - } - - k := strings.Replace(keys[i], ".", "_", -1) - fmt.Printf("%s_%s = %s\n", envPrefix, strings.ToUpper(k), defaultValue) - } - - fmt.Println() - fmt.Println("Peers preset:") - fmt.Println() - - fmt.Printf("%s_%s_[N]_ADDRESS = string\n", envPrefix, strings.ToUpper(cfgPeers)) - fmt.Printf("%s_%s_[N]_WEIGHT = 0..1 (float)\n", envPrefix, strings.ToUpper(cfgPeers)) - - os.Exit(0) - case versionFlag != nil && *versionFlag: - fmt.Printf("FrostFS S3 Gateway\nVersion: %s\nGoVersion: %s\n", version.Version, runtime.Version()) - os.Exit(0) - } - - if err := readInConfig(v); err != nil { - panic(err) - } - - return v } func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error { diff --git a/cmd/s3-gw/app_settings_test.go b/cmd/s3-gw/app_settings_test.go new file mode 100644 index 00000000..f00b8e8c --- /dev/null +++ b/cmd/s3-gw/app_settings_test.go @@ -0,0 +1,50 @@ +package main + +import ( + "os" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/resolver" + "github.com/stretchr/testify/require" +) + +func TestConfigReload(t *testing.T) { + f, err := os.CreateTemp("", "conf") + require.NoError(t, err) + defer func() { + require.NoError(t, os.Remove(f.Name())) + }() + + confData := ` +pprof: + enabled: true + +frostfsid: + contract: name.nns + +resolve_order: + - nns +` + + _, err = f.WriteString(confData) + require.NoError(t, err) + require.NoError(t, f.Close()) + + cfg := newSettings() + + require.NoError(t, cfg.flags.Parse([]string{"--config", f.Name(), "--max_clients_count", "10"})) + require.NoError(t, cfg.reload()) + + require.True(t, cfg.config().GetBool(cfgPProfEnabled)) + require.Equal(t, "name.nns", cfg.config().GetString(cfgFrostfsIDContract)) + require.Equal(t, []string{resolver.NNSResolver}, cfg.config().GetStringSlice(cfgResolveOrder)) + require.Equal(t, 10, cfg.config().GetInt(cfgMaxClientsCount)) + + require.NoError(t, os.Truncate(f.Name(), 0)) + require.NoError(t, cfg.reload()) + + require.False(t, cfg.config().GetBool(cfgPProfEnabled)) + require.Equal(t, "frostfsid.frostfs", cfg.config().GetString(cfgFrostfsIDContract)) + require.Equal(t, []string{resolver.DNSResolver}, cfg.config().GetStringSlice(cfgResolveOrder)) + require.Equal(t, 10, cfg.config().GetInt(cfgMaxClientsCount)) +} diff --git a/cmd/s3-gw/main.go b/cmd/s3-gw/main.go index 927ceb9e..788c861a 100644 --- a/cmd/s3-gw/main.go +++ b/cmd/s3-gw/main.go @@ -8,9 +8,9 @@ import ( func main() { g, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) - v := newSettings() + cfg := newSettings() - a := newApp(g, v) + a := newApp(g, cfg) go a.Serve(g)