From a8425e8d9342c112ba387ec735ce169ca4645d3a Mon Sep 17 00:00:00 2001 From: Ryan VanGundy Date: Sat, 19 Jul 2025 10:22:27 -0400 Subject: [PATCH] fix(config): Fixes error when running --set to a boolean value When running things like `windsor init --set dns.enabled=false`, we were seeing type errors using a string as a bool. This likely emerged in the recent pipeline refactor. Performs additional internal casting to accommodate. --- pkg/config/yaml_config_handler.go | 13 ++++++++--- pkg/config/yaml_config_handler_test.go | 30 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/pkg/config/yaml_config_handler.go b/pkg/config/yaml_config_handler.go index 5fc1b69ce..e632341eb 100644 --- a/pkg/config/yaml_config_handler.go +++ b/pkg/config/yaml_config_handler.go @@ -480,7 +480,9 @@ func setValueByPath(currValue reflect.Value, pathKeys []string, value any, fullP return nil } -// assignValue assigns a value to a field, converting types if necessary. +// assignValue assigns a value to a struct field, performing type conversion if necessary. +// It supports string-to-type conversion, pointer assignment, and type compatibility checks. +// Returns a reflect.Value suitable for assignment or an error if conversion is not possible. func assignValue(fieldValue reflect.Value, value any) (reflect.Value, error) { if !fieldValue.CanSet() { return reflect.Value{}, fmt.Errorf("cannot set field") @@ -489,17 +491,22 @@ func assignValue(fieldValue reflect.Value, value any) (reflect.Value, error) { fieldType := fieldValue.Type() valueType := reflect.TypeOf(value) + if strValue, ok := value.(string); ok { + convertedValue, err := convertValue(strValue, fieldType) + if err == nil { + return reflect.ValueOf(convertedValue), nil + } + } + if fieldType.Kind() == reflect.Ptr { elemType := fieldType.Elem() newValue := reflect.New(elemType) val := reflect.ValueOf(value) - // If the value is already a pointer of the correct type, use it directly if valueType.AssignableTo(fieldType) { return val, nil } - // If the value is convertible to the element type, convert and wrap in pointer if val.Type().ConvertibleTo(elemType) { val = val.Convert(elemType) newValue.Elem().Set(val) diff --git a/pkg/config/yaml_config_handler_test.go b/pkg/config/yaml_config_handler_test.go index 1467c19b5..57fc4ccd8 100644 --- a/pkg/config/yaml_config_handler_test.go +++ b/pkg/config/yaml_config_handler_test.go @@ -2004,6 +2004,36 @@ func TestYamlConfigHandler_SetContextValue(t *testing.T) { t.Errorf("Expected 6.28, got %v", val) } }) + + t.Run("ConvertStringToBoolPointer", func(t *testing.T) { + // Given a handler with a default context + handler, _ := setup(t) + handler.context = "default" + handler.config.Contexts = map[string]*v1alpha1.Context{ + "default": {}, + } + + // When setting a string "false" to a bool pointer field (dns.enabled) + if err := handler.SetContextValue("dns.enabled", "false"); err != nil { + t.Fatalf("Failed to set dns.enabled=false from string: %v", err) + } + + // Then the value should be correctly set as a boolean + config := handler.GetConfig() + if config.DNS == nil || config.DNS.Enabled == nil || *config.DNS.Enabled != false { + t.Errorf("Expected dns.enabled to be false, got %v", config.DNS.Enabled) + } + + // And when setting "true" as well + if err := handler.SetContextValue("dns.enabled", "true"); err != nil { + t.Fatalf("Failed to set dns.enabled=true from string: %v", err) + } + + config = handler.GetConfig() + if config.DNS == nil || config.DNS.Enabled == nil || *config.DNS.Enabled != true { + t.Errorf("Expected dns.enabled to be true, got %v", config.DNS.Enabled) + } + }) } func TestYamlConfigHandler_LoadConfigString(t *testing.T) {