From f95e553e9dcff82bea4ee909b300a76173b27675 Mon Sep 17 00:00:00 2001 From: Sarthak Agarwal Date: Fri, 8 Nov 2024 22:50:36 +0000 Subject: [PATCH 1/4] Print config at server startup after setting defaults --- launchers/launcher.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/launchers/launcher.go b/launchers/launcher.go index c8868b498..6206ac4f2 100644 --- a/launchers/launcher.go +++ b/launchers/launcher.go @@ -60,13 +60,6 @@ func LaunchModules(ctx context.Context, modules server_structs.ServerType) (serv config.LogPelicanVersion() - // Print Pelican config at server start if it's in debug or info level - if log.GetLevel() >= log.InfoLevel { - if err = config.PrintConfig(); err != nil { - return - } - } - egrp.Go(func() error { _ = config.RestartFlag log.Debug("Will shutdown process on signal") @@ -97,6 +90,13 @@ func LaunchModules(ctx context.Context, modules server_structs.ServerType) (serv return } + // Print Pelican config at server start if it's in debug or info level + if log.GetLevel() >= log.InfoLevel { + if err = config.PrintConfig(); err != nil { + return + } + } + // Set up necessary APIs to support Web UI, including auth and metrics if err = web_ui.ConfigureServerWebAPI(ctx, engine, egrp); err != nil { return From e5c2e7a77e090135a97654a3b9af7042c92603ae Mon Sep 17 00:00:00 2001 From: Sarthak Agarwal Date: Sat, 9 Nov 2024 22:42:53 +0000 Subject: [PATCH 2/4] Add debug-level config print in InitClient --- config/config.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/config.go b/config/config.go index a51d53697..fc4ade31d 100644 --- a/config/config.go +++ b/config/config.go @@ -1515,6 +1515,13 @@ func InitClient() error { clientInitialized = true + // Print Pelican configuration after client config initialization if log level is set to debug + if log.GetLevel() == log.DebugLevel { + if err = PrintConfig(); err != nil { + return err + } + } + return nil } From eb99b23e01c4a55d15df81adf57d986e8ad43bc8 Mon Sep 17 00:00:00 2001 From: Sarthak Agarwal Date: Fri, 15 Nov 2024 21:22:48 +0000 Subject: [PATCH 3/4] Add component based config filtering --- config/config.go | 112 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/config/config.go b/config/config.go index fc4ade31d..2d5c123e7 100644 --- a/config/config.go +++ b/config/config.go @@ -32,6 +32,7 @@ import ( "net/url" "os" "path/filepath" + "reflect" "slices" "sort" "strconv" @@ -50,6 +51,7 @@ import ( "github.com/spf13/viper" "golang.org/x/sync/errgroup" + "github.com/pelicanplatform/pelican/docs" "github.com/pelicanplatform/pelican/param" "github.com/pelicanplatform/pelican/pelican_url" "github.com/pelicanplatform/pelican/server_structs" @@ -171,7 +173,8 @@ var ( "": true, } - clientInitialized = false + clientInitialized = false + printClientConfigOnce sync.Once ) func init() { @@ -922,6 +925,100 @@ func PrintConfig() error { return nil } +func contains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} + +// GetComponentConfig filters the full config and returns only the config parameters related to the given component. +// The filtering is based on whether the given component is part of the components in docs.parameters.yaml. +func GetComponentConfig(component string) (map[string]interface{}, error) { + rawConfig, err := param.UnmarshalConfig(viper.GetViper()) + if err != nil { + return nil, err + } + value, hasValue := filterConfigRecursive(reflect.ValueOf(rawConfig), "", component) + if hasValue { + return (*value).(map[string]interface{}), nil + } + return nil, nil +} + +// filterConfigRecursive is a helper function for GetComponentConfig. +// It recursively creates a nested config map of the parameters that relate to the given component. +func filterConfigRecursive(v reflect.Value, currentPath string, component string) (*interface{}, bool) { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + switch v.Kind() { + case reflect.Struct: + t := v.Type() + result := make(map[string]interface{}) + hasField := false + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + fieldType := t.Field(i) + if !fieldType.IsExported() { + continue + } + + fieldName := strings.ToLower(fieldType.Name) + + var newPath string + if currentPath == "" { + newPath = fieldName + } else { + newPath = currentPath + "." + fieldName + } + + fieldValue, fieldHasValue := filterConfigRecursive(field, newPath, component) + if fieldHasValue && fieldValue != nil { + result[fieldName] = *fieldValue + hasField = true + } + } + if hasField { + resultInterface := interface{}(result) + return &resultInterface, true + } + return nil, false + default: + lowerPath := strings.ToLower(currentPath) + paramDoc, exists := docs.ParsedParameters[lowerPath] + if exists && contains(paramDoc.Components, component) { + resultValue := v.Interface() + resultInterface := interface{}(resultValue) + return &resultInterface, true + } + return nil, false + } +} + +// PrintClientConfig prints the client config in JSON format to stderr. +func PrintClientConfig() error { + + clientConfig, err := GetComponentConfig("client") + if err != nil { + return err + } + + bytes, err := json.MarshalIndent(clientConfig, "", " ") + if err != nil { + return err + } + fmt.Fprintln(os.Stderr, + "================ Pelican Client Configuration ================\n", + string(bytes), + "\n", + "============= End of Pelican Client Configuration ============") + return nil +} + func SetServerDefaults(v *viper.Viper) error { configDir := v.GetString("ConfigDir") v.SetConfigType("yaml") @@ -1515,11 +1612,16 @@ func InitClient() error { clientInitialized = true - // Print Pelican configuration after client config initialization if log level is set to debug - if log.GetLevel() == log.DebugLevel { - if err = PrintConfig(); err != nil { - return err + var printClientConfigErr error + printClientConfigOnce.Do(func() { + if log.GetLevel() == log.DebugLevel { + printClientConfigErr = PrintClientConfig() } + }) + + // Return any error encountered during PrintClientConfig + if printClientConfigErr != nil { + return printClientConfigErr } return nil From 6412cc4a60e0fb21df72622fcbd91fc729711a0f Mon Sep 17 00:00:00 2001 From: Sarthak Agarwal Date: Mon, 18 Nov 2024 17:05:26 -0600 Subject: [PATCH 4/4] Remove extra new line --- config/config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config/config.go b/config/config.go index 2d5c123e7..353cdec28 100644 --- a/config/config.go +++ b/config/config.go @@ -1001,7 +1001,6 @@ func filterConfigRecursive(v reflect.Value, currentPath string, component string // PrintClientConfig prints the client config in JSON format to stderr. func PrintClientConfig() error { - clientConfig, err := GetComponentConfig("client") if err != nil { return err