[#541] Use default value if config param is unset after SIGHUP #541

Open
mbiryukova wants to merge 1 commit from mbiryukova/frostfs-s3-gw:feature/fix_sighup into master
Member

Signed-off-by: Marina Biryukova m.biryukova@yadro.com

Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
mbiryukova self-assigned this 2024-11-05 14:34:44 +00:00
mbiryukova added 1 commit 2024-11-05 14:34:45 +00:00
[#xxx] Use default value if config param is unset after SIGHUP
Some checks failed
/ DCO (pull_request) Failing after 1m3s
/ Vulncheck (pull_request) Successful in 1m12s
/ Builds (pull_request) Successful in 1m42s
/ Lint (pull_request) Successful in 3m29s
/ Tests (pull_request) Successful in 2m11s
1c8a9f2d5f
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
mbiryukova force-pushed feature/fix_sighup from 1c8a9f2d5f to 574e50b6c3 2024-11-05 14:35:10 +00:00 Compare
mbiryukova changed title from [#xxx] Use default value if config param is unset after SIGHUP to [#541] Use default value if config param is unset after SIGHUP 2024-11-05 14:35:34 +00:00
mbiryukova requested review from storage-services-committers 2024-11-06 07:12:20 +00:00
mbiryukova requested review from storage-services-developers 2024-11-06 07:12:21 +00:00
dkirillov reviewed 2024-11-11 08:51:08 +00:00
@ -1009,2 +1024,2 @@
if v.IsSet(cmdConfig) {
if err := readConfig(v); err != nil {
func readInConfig(cfg *appCfg) error {
if err := cfg.settings.MergeConfigMap(cfg.defaults.AllSettings()); err != nil {
Member

This way we must set all default values (false, empty string, etc). It's easy to forget.
I suggest implement creating and filling new viper instance on SIGHUP and replace it under mutex. Something like that:

diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go
index d6bbde74..259a6c9c 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"
@@ -286,10 +287,42 @@ var ignore = map[string]struct{}{
 }
 
 type appCfg struct {
-	defaults *viper.Viper
+	mu       *sync.RWMutex
 	settings *viper.Viper
 }
 
+func (a *appCfg) reload() error {
+	old := a.Config()
+
+	v := newViper()
+	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 {
@@ -784,15 +817,20 @@ func fetchMultinetConfig(v *viper.Viper, logger *zap.Logger) (cfg internalnet.Co
 	return
 }
 
-func newSettings() *appCfg {
+func newViper() *viper.Viper {
 	v := viper.New()
-
 	v.AutomaticEnv()
 	v.SetEnvPrefix(envPrefix)
 	v.SetConfigType("yaml")
 	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
 	v.AllowEmptyEnv(true)
 
+	return v
+}
+
+func newSettings() *appCfg {
+	v := newViper()
+
 	// flags setup:
 	flags := pflag.NewFlagSet("commandline", pflag.ExitOnError)
 	flags.SetOutput(os.Stdout)
@@ -878,16 +916,11 @@ func newSettings() *appCfg {
 		os.Exit(0)
 	}
 
-	cfg := &appCfg{
-		defaults: getDefaults(resolveMethods, peers, domains),
-		settings: v,
-	}
-
-	if err := readInConfig(cfg); err != nil {
+	if err := readInConfig(v); err != nil {
 		panic(err)
 	}
 
-	return cfg
+	return &appCfg{settings: v}
 }
 
 func getDefaults(resolveMethods, peers, domains *[]string) *viper.Viper {
@@ -1021,19 +1054,15 @@ func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error {
 	return v.BindPFlag(cfgServer+".0."+cfgTLSCertFile, flags.Lookup(cfgTLSCertFile))
 }
 
-func readInConfig(cfg *appCfg) error {
-	if err := cfg.settings.MergeConfigMap(cfg.defaults.AllSettings()); err != nil {
-		return err
-	}
-
-	if cfg.settings.IsSet(cmdConfig) {
-		if err := readConfig(cfg.settings); err != nil {
+func readInConfig(v *viper.Viper) error {
+	if v.IsSet(cmdConfig) {
+		if err := readConfig(v); err != nil {
 			return err
 		}
 	}
 
-	if cfg.settings.IsSet(cmdConfigDir) {
-		if err := readConfigDir(cfg.settings); err != nil {
+	if v.IsSet(cmdConfigDir) {
+		if err := readConfigDir(v); err != nil {
 			return err
 		}
 	}

This way we must set all default values (false, empty string, etc). It's easy to forget. I suggest implement creating and filling new viper instance on SIGHUP and replace it under mutex. Something like that: ```diff diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go index d6bbde74..259a6c9c 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" @@ -286,10 +287,42 @@ var ignore = map[string]struct{}{ } type appCfg struct { - defaults *viper.Viper + mu *sync.RWMutex settings *viper.Viper } +func (a *appCfg) reload() error { + old := a.Config() + + v := newViper() + 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 { @@ -784,15 +817,20 @@ func fetchMultinetConfig(v *viper.Viper, logger *zap.Logger) (cfg internalnet.Co return } -func newSettings() *appCfg { +func newViper() *viper.Viper { v := viper.New() - v.AutomaticEnv() v.SetEnvPrefix(envPrefix) v.SetConfigType("yaml") v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.AllowEmptyEnv(true) + return v +} + +func newSettings() *appCfg { + v := newViper() + // flags setup: flags := pflag.NewFlagSet("commandline", pflag.ExitOnError) flags.SetOutput(os.Stdout) @@ -878,16 +916,11 @@ func newSettings() *appCfg { os.Exit(0) } - cfg := &appCfg{ - defaults: getDefaults(resolveMethods, peers, domains), - settings: v, - } - - if err := readInConfig(cfg); err != nil { + if err := readInConfig(v); err != nil { panic(err) } - return cfg + return &appCfg{settings: v} } func getDefaults(resolveMethods, peers, domains *[]string) *viper.Viper { @@ -1021,19 +1054,15 @@ func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error { return v.BindPFlag(cfgServer+".0."+cfgTLSCertFile, flags.Lookup(cfgTLSCertFile)) } -func readInConfig(cfg *appCfg) error { - if err := cfg.settings.MergeConfigMap(cfg.defaults.AllSettings()); err != nil { - return err - } - - if cfg.settings.IsSet(cmdConfig) { - if err := readConfig(cfg.settings); err != nil { +func readInConfig(v *viper.Viper) error { + if v.IsSet(cmdConfig) { + if err := readConfig(v); err != nil { return err } } - if cfg.settings.IsSet(cmdConfigDir) { - if err := readConfigDir(cfg.settings); err != nil { + if v.IsSet(cmdConfigDir) { + if err := readConfigDir(v); err != nil { return err } } ```
Author
Member

In this case, won’t we lose all default values ​​and values ​​that were set via flags after SIGHUP?

In this case, won’t we lose all default values ​​and values ​​that were set via flags after SIGHUP?
Member

Well, then I suppose keep flags also (env variables not reloadable and new viper instance get them also)

diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go
index d6bbde74..78eb8407 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"
@@ -286,10 +287,48 @@ var ignore = map[string]struct{}{
 }
 
 type appCfg struct {
-	defaults *viper.Viper
+	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 {
@@ -784,15 +823,24 @@ func fetchMultinetConfig(v *viper.Viper, logger *zap.Logger) (cfg internalnet.Co
 	return
 }
 
-func newSettings() *appCfg {
+func newViper(flags *pflag.FlagSet) (*viper.Viper, error) {
 	v := viper.New()
-
 	v.AutomaticEnv()
 	v.SetEnvPrefix(envPrefix)
 	v.SetConfigType("yaml")
 	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)
@@ -820,24 +868,20 @@ func newSettings() *appCfg {
 	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")
-
-	// Bind flags
-	if err := bindFlags(v, flags); err != nil {
-		panic(fmt.Errorf("bind flags: %w", err))
-	}
+	flags.StringSliceP(cfgListenDomains, "d", nil, "set domains to be listened")
 
 	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)
+	v, err := newViper(flags)
+	if err != nil {
+		panic(fmt.Errorf("bind flags: %w", err))
 	}
 
 	switch {
@@ -878,21 +922,17 @@ func newSettings() *appCfg {
 		os.Exit(0)
 	}
 
-	cfg := &appCfg{
-		defaults: getDefaults(resolveMethods, peers, domains),
-		settings: v,
-	}
-
-	if err := readInConfig(cfg); err != nil {
+	if err = readInConfig(v); err != nil {
 		panic(err)
 	}
 
-	return cfg
+	return &appCfg{
+		flags:    flags,
+		settings: v,
+	}
 }
 
-func getDefaults(resolveMethods, peers, domains *[]string) *viper.Viper {
-	v := viper.New()
-
+func setDefaults(v *viper.Viper, flags *pflag.FlagSet) {
 	// set defaults:
 
 	v.SetDefault(cfgAccessBoxCacheRemovingCheckInterval, defaultAccessBoxCacheRemovingCheckInterval)
@@ -955,23 +995,21 @@ func getDefaults(resolveMethods, peers, domains *[]string) *viper.Viper {
 	// multinet
 	v.SetDefault(cfgMultinetFallbackDelay, defaultMultinetFallbackDelay)
 
-	if resolveMethods != nil {
-		v.SetDefault(cfgResolveOrder, *resolveMethods)
+	if resolveMethods, err := flags.GetStringSlice(cfgResolveOrder); err == 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)
 	}
-
-	return v
 }
 
 func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error {
@@ -1021,19 +1059,15 @@ func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error {
 	return v.BindPFlag(cfgServer+".0."+cfgTLSCertFile, flags.Lookup(cfgTLSCertFile))
 }
 
-func readInConfig(cfg *appCfg) error {
-	if err := cfg.settings.MergeConfigMap(cfg.defaults.AllSettings()); err != nil {
-		return err
-	}
-
-	if cfg.settings.IsSet(cmdConfig) {
-		if err := readConfig(cfg.settings); err != nil {
+func readInConfig(v *viper.Viper) error {
+	if v.IsSet(cmdConfig) {
+		if err := readConfig(v); err != nil {
 			return err
 		}
 	}
 
-	if cfg.settings.IsSet(cmdConfigDir) {
-		if err := readConfigDir(cfg.settings); err != nil {
+	if v.IsSet(cmdConfigDir) {
+		if err := readConfigDir(v); err != nil {
 			return err
 		}
 	}

Well, then I suppose keep flags also (env variables not reloadable and new viper instance get them also) ```diff diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go index d6bbde74..78eb8407 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" @@ -286,10 +287,48 @@ var ignore = map[string]struct{}{ } type appCfg struct { - defaults *viper.Viper + 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 { @@ -784,15 +823,24 @@ func fetchMultinetConfig(v *viper.Viper, logger *zap.Logger) (cfg internalnet.Co return } -func newSettings() *appCfg { +func newViper(flags *pflag.FlagSet) (*viper.Viper, error) { v := viper.New() - v.AutomaticEnv() v.SetEnvPrefix(envPrefix) v.SetConfigType("yaml") 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) @@ -820,24 +868,20 @@ func newSettings() *appCfg { 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") - - // Bind flags - if err := bindFlags(v, flags); err != nil { - panic(fmt.Errorf("bind flags: %w", err)) - } + flags.StringSliceP(cfgListenDomains, "d", nil, "set domains to be listened") 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) + v, err := newViper(flags) + if err != nil { + panic(fmt.Errorf("bind flags: %w", err)) } switch { @@ -878,21 +922,17 @@ func newSettings() *appCfg { os.Exit(0) } - cfg := &appCfg{ - defaults: getDefaults(resolveMethods, peers, domains), - settings: v, - } - - if err := readInConfig(cfg); err != nil { + if err = readInConfig(v); err != nil { panic(err) } - return cfg + return &appCfg{ + flags: flags, + settings: v, + } } -func getDefaults(resolveMethods, peers, domains *[]string) *viper.Viper { - v := viper.New() - +func setDefaults(v *viper.Viper, flags *pflag.FlagSet) { // set defaults: v.SetDefault(cfgAccessBoxCacheRemovingCheckInterval, defaultAccessBoxCacheRemovingCheckInterval) @@ -955,23 +995,21 @@ func getDefaults(resolveMethods, peers, domains *[]string) *viper.Viper { // multinet v.SetDefault(cfgMultinetFallbackDelay, defaultMultinetFallbackDelay) - if resolveMethods != nil { - v.SetDefault(cfgResolveOrder, *resolveMethods) + if resolveMethods, err := flags.GetStringSlice(cfgResolveOrder); err == 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) } - - return v } func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error { @@ -1021,19 +1059,15 @@ func bindFlags(v *viper.Viper, flags *pflag.FlagSet) error { return v.BindPFlag(cfgServer+".0."+cfgTLSCertFile, flags.Lookup(cfgTLSCertFile)) } -func readInConfig(cfg *appCfg) error { - if err := cfg.settings.MergeConfigMap(cfg.defaults.AllSettings()); err != nil { - return err - } - - if cfg.settings.IsSet(cmdConfig) { - if err := readConfig(cfg.settings); err != nil { +func readInConfig(v *viper.Viper) error { + if v.IsSet(cmdConfig) { + if err := readConfig(v); err != nil { return err } } - if cfg.settings.IsSet(cmdConfigDir) { - if err := readConfigDir(cfg.settings); err != nil { + if v.IsSet(cmdConfigDir) { + if err := readConfigDir(v); err != nil { return err } } ```
dkirillov marked this conversation as resolved
mbiryukova force-pushed feature/fix_sighup from 574e50b6c3 to ef946b02f0 2024-11-15 09:08:55 +00:00 Compare
Member

Please, rebase

Please, rebase
mbiryukova force-pushed feature/fix_sighup from ef946b02f0 to efc6795fc5 2024-11-18 15:57:35 +00:00 Compare
mbiryukova force-pushed feature/fix_sighup from efc6795fc5 to d99c1cf9d3 2024-11-18 15:59:48 +00:00 Compare
alexvanin added this to the v0.32.0 milestone 2024-11-20 12:23:40 +00:00
dkirillov approved these changes 2024-11-21 06:52:23 +00:00
dkirillov left a comment
Member

LGTM

LGTM
r.loginov approved these changes 2024-11-21 08:44:19 +00:00
All checks were successful
/ DCO (pull_request) Successful in 1m28s
/ Vulncheck (pull_request) Successful in 1m47s
/ Builds (pull_request) Successful in 1m54s
/ Lint (pull_request) Successful in 2m25s
/ Tests (pull_request) Successful in 1m54s
This pull request has changes conflicting with the target branch.
  • cmd/s3-gw/app.go
  • cmd/s3-gw/main.go
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u feature/fix_sighup:mbiryukova-feature/fix_sighup
git checkout mbiryukova-feature/fix_sighup
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: TrueCloudLab/frostfs-s3-gw#541
No description provided.