diff --git a/cmd/admin-handlers-config-kv.go b/cmd/admin-handlers-config-kv.go index 35a6fdd1e..552d85ec8 100644 --- a/cmd/admin-handlers-config-kv.go +++ b/cmd/admin-handlers-config-kv.go @@ -64,6 +64,12 @@ func (a adminAPIHandlers) DelConfigKVHandler(w http.ResponseWriter, r *http.Requ return } + subSys, _, _, err := config.GetSubSys(string(kvBytes)) + if err != nil { + writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) + return + } + cfg, err := readServerConfig(ctx, objectAPI) if err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) @@ -74,7 +80,7 @@ func (a adminAPIHandlers) DelConfigKVHandler(w http.ResponseWriter, r *http.Requ writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) return } - if err = validateConfig(cfg, ""); err != nil { + if err = validateConfig(cfg, subSys); err != nil { writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminConfigBadJSON), err.Error(), r.URL) return } @@ -84,15 +90,16 @@ func (a adminAPIHandlers) DelConfigKVHandler(w http.ResponseWriter, r *http.Requ return } - dynamic := config.SubSystemsDynamic.Contains(string(kvBytes)) + dynamic := config.SubSystemsDynamic.Contains(subSys) if dynamic { - applyDynamic(ctx, objectAPI, cfg, r, w) + applyDynamic(ctx, objectAPI, cfg, subSys, r, w) } } -func applyDynamic(ctx context.Context, objectAPI ObjectLayer, cfg config.Config, r *http.Request, w http.ResponseWriter) { +func applyDynamic(ctx context.Context, objectAPI ObjectLayer, cfg config.Config, subSys string, + r *http.Request, w http.ResponseWriter) { // Apply dynamic values. - if err := applyDynamicConfig(GlobalContext, objectAPI, cfg); err != nil { + if err := applyDynamicConfigForSubSys(GlobalContext, objectAPI, cfg, subSys); err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) return } @@ -162,7 +169,7 @@ func (a adminAPIHandlers) SetConfigKVHandler(w http.ResponseWriter, r *http.Requ } if dynamic { - applyDynamic(ctx, objectAPI, cfg, r, w) + applyDynamic(ctx, objectAPI, cfg, subSys, r, w) } writeSuccessResponseHeadersOnly(w) } diff --git a/cmd/config-current.go b/cmd/config-current.go index 353069641..3e268a114 100644 --- a/cmd/config-current.go +++ b/cmd/config-current.go @@ -616,84 +616,80 @@ func lookupConfigs(s config.Config, objAPI ObjectLayer) { } } -// applyDynamicConfig will apply dynamic config values. -// Dynamic systems should be in config.SubSystemsDynamic as well. -func applyDynamicConfig(ctx context.Context, objAPI ObjectLayer, s config.Config) error { - // Read all dynamic configs. - // API - apiConfig, err := api.LookupConfig(s[config.APISubSys][config.Default]) - if err != nil { - logger.LogIf(ctx, fmt.Errorf("Invalid api configuration: %w", err)) - } - - // Compression - cmpCfg, err := compress.LookupConfig(s[config.CompressionSubSys][config.Default]) - if err != nil { - return fmt.Errorf("Unable to setup Compression: %w", err) - } - - // Validate if the object layer supports compression. - if objAPI != nil { - if cmpCfg.Enabled && !objAPI.IsCompressionSupported() { - return fmt.Errorf("Backend does not support compression") +func applyDynamicConfigForSubSys(ctx context.Context, objAPI ObjectLayer, s config.Config, subSys string) error { + switch subSys { + case config.APISubSys: + apiConfig, err := api.LookupConfig(s[config.APISubSys][config.Default]) + if err != nil { + logger.LogIf(ctx, fmt.Errorf("Invalid api configuration: %w", err)) + } + var setDriveCounts []int + if objAPI != nil { + setDriveCounts = objAPI.SetDriveCounts() + } + globalAPIConfig.init(apiConfig, setDriveCounts) + case config.CompressionSubSys: + cmpCfg, err := compress.LookupConfig(s[config.CompressionSubSys][config.Default]) + if err != nil { + return fmt.Errorf("Unable to setup Compression: %w", err) + } + // Validate if the object layer supports compression. + if objAPI != nil { + if cmpCfg.Enabled && !objAPI.IsCompressionSupported() { + return fmt.Errorf("Backend does not support compression") + } + } + globalCompressConfigMu.Lock() + globalCompressConfig = cmpCfg + globalCompressConfigMu.Unlock() + case config.HealSubSys: + healCfg, err := heal.LookupConfig(s[config.HealSubSys][config.Default]) + if err != nil { + return fmt.Errorf("Unable to apply heal config: %w", err) + } + globalHealConfig.Update(healCfg) + case config.ScannerSubSys: + scannerCfg, err := scanner.LookupConfig(s[config.ScannerSubSys][config.Default]) + if err != nil { + return fmt.Errorf("Unable to apply scanner config: %w", err) + } + // update dynamic scanner values. + scannerCycle.Update(scannerCfg.Cycle) + logger.LogIf(ctx, scannerSleeper.Update(scannerCfg.Delay, scannerCfg.MaxWait)) + case config.LoggerWebhookSubSys: + loggerCfg, err := logger.LookupConfig(s) + if err != nil { + logger.LogIf(ctx, fmt.Errorf("Unable to load logger webhook config: %w", err)) + } + userAgent := getUserAgent(getMinioMode()) + for n, l := range loggerCfg.HTTP { + if l.Enabled { + l.LogOnce = logger.LogOnceIf + l.UserAgent = userAgent + l.Transport = NewGatewayHTTPTransportWithClientCerts(l.ClientCert, l.ClientKey) + loggerCfg.HTTP[n] = l + } + } + err = logger.UpdateTargets(loggerCfg) + if err != nil { + logger.LogIf(ctx, fmt.Errorf("Unable to update logger webhook config: %w", err)) } } - - // Heal - healCfg, err := heal.LookupConfig(s[config.HealSubSys][config.Default]) - if err != nil { - return fmt.Errorf("Unable to apply heal config: %w", err) - } - - // Scanner - scannerCfg, err := scanner.LookupConfig(s[config.ScannerSubSys][config.Default]) - if err != nil { - return fmt.Errorf("Unable to apply scanner config: %w", err) - } - - // Logger webhook - loggerCfg, err := logger.LookupConfig(s) - if err != nil { - logger.LogIf(ctx, fmt.Errorf("Unable to load logger webhook config: %w", err)) - } - userAgent := getUserAgent(getMinioMode()) - for n, l := range loggerCfg.HTTP { - if l.Enabled { - l.LogOnce = logger.LogOnceIf - l.UserAgent = userAgent - l.Transport = NewGatewayHTTPTransportWithClientCerts(l.ClientCert, l.ClientKey) - loggerCfg.HTTP[n] = l - } - } - err = logger.UpdateTargets(loggerCfg) - if err != nil { - logger.LogIf(ctx, fmt.Errorf("Unable to update logger webhook config: %w", err)) - } - - // Apply configurations. - // We should not fail after this. - var setDriveCounts []int - if objAPI != nil { - setDriveCounts = objAPI.SetDriveCounts() - } - globalAPIConfig.init(apiConfig, setDriveCounts) - - globalCompressConfigMu.Lock() - globalCompressConfig = cmpCfg - globalCompressConfigMu.Unlock() - - globalHealConfig.Update(healCfg) - - // update dynamic scanner values. - scannerCycle.Update(scannerCfg.Cycle) - logger.LogIf(ctx, scannerSleeper.Update(scannerCfg.Delay, scannerCfg.MaxWait)) - - // Update all dynamic config values in memory. globalServerConfigMu.Lock() defer globalServerConfigMu.Unlock() if globalServerConfig != nil { - for k := range config.SubSystemsDynamic { - globalServerConfig[k] = s[k] + globalServerConfig[subSys] = s[subSys] + } + return nil +} + +// applyDynamicConfig will apply dynamic config values. +// Dynamic systems should be in config.SubSystemsDynamic as well. +func applyDynamicConfig(ctx context.Context, objAPI ObjectLayer, s config.Config) error { + for subSys := range config.SubSystemsDynamic { + err := applyDynamicConfigForSubSys(ctx, objAPI, s, subSys) + if err != nil { + return err } } return nil diff --git a/internal/config/config.go b/internal/config/config.go index 6d4211151..35731150f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -813,18 +813,16 @@ func GetSubSys(s string) (subSys string, inputs []string, tgt string, e error) { return subSys, inputs, tgt, Errorf("input arguments cannot be empty") } inputs = strings.SplitN(s, KvSpaceSeparator, 2) - if len(inputs) <= 1 { - return subSys, inputs, tgt, Errorf("invalid number of arguments '%s'", s) - } - subSystemValue := strings.SplitN(inputs[0], SubSystemSeparator, 2) - if len(subSystemValue) == 0 { - return subSys, inputs, tgt, Errorf("invalid number of arguments %s", s) - } - if !SubSystems.Contains(subSystemValue[0]) { + subSystemValue := strings.SplitN(inputs[0], SubSystemSeparator, 2) + subSys = subSystemValue[0] + if !SubSystems.Contains(subSys) { return subSys, inputs, tgt, Errorf("unknown sub-system %s", s) } - subSys = subSystemValue[0] + + if len(inputs) == 1 { + return subSys, inputs, tgt, nil + } if SubSystemsSingleTargets.Contains(subSystemValue[0]) && len(subSystemValue) == 2 { return subSys, inputs, tgt, Errorf("sub-system '%s' only supports single target", subSystemValue[0])