Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/config/config_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type ConfigHandler interface {
Initialize() error
LoadConfig(path string) error
LoadConfigString(content string) error
LoadContextConfig() error
GetString(key string, defaultValue ...string) string
GetInt(key string, defaultValue ...int) int
GetBool(key string, defaultValue ...bool) bool
Expand Down Expand Up @@ -176,6 +177,11 @@ func (c *BaseConfigHandler) IsLoaded() bool {
return c.loaded
}

// LoadContextConfig provides a base implementation that should be overridden by concrete implementations
func (c *BaseConfigHandler) LoadContextConfig() error {
return fmt.Errorf("LoadContextConfig not implemented in base config handler")
}

// SetSecretsProvider sets the secrets provider for the config handler
func (c *BaseConfigHandler) SetSecretsProvider(provider secrets.SecretsProvider) {
c.secretsProviders = append(c.secretsProviders, provider)
Expand Down
31 changes: 31 additions & 0 deletions pkg/config/config_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,3 +684,34 @@ func TestBaseConfigHandler_SetSecretsProvider(t *testing.T) {
}
})
}

// =============================================================================
// LoadContextConfig Tests
// =============================================================================

func TestBaseConfigHandler_LoadContextConfig(t *testing.T) {
setup := func(t *testing.T) *BaseConfigHandler {
t.Helper()
injector := di.NewInjector()
handler := NewBaseConfigHandler(injector)
return handler
}

t.Run("ReturnsNotImplementedError", func(t *testing.T) {
// Given a BaseConfigHandler
handler := setup(t)

// When LoadContextConfig is called
err := handler.LoadContextConfig()

// Then it should return the expected error
if err == nil {
t.Fatal("LoadContextConfig() expected error, got nil")
}

expectedError := "LoadContextConfig not implemented in base config handler"
if err.Error() != expectedError {
t.Errorf("LoadContextConfig() error = %v, expected '%s'", err, expectedError)
}
})
}
9 changes: 9 additions & 0 deletions pkg/config/mock_config_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type MockConfigHandler struct {
InitializeFunc func() error
LoadConfigFunc func(path string) error
LoadConfigStringFunc func(content string) error
LoadContextConfigFunc func() error
IsLoadedFunc func() bool
GetStringFunc func(key string, defaultValue ...string) string
GetIntFunc func(key string, defaultValue ...int) int
Expand Down Expand Up @@ -68,6 +69,14 @@ func (m *MockConfigHandler) LoadConfigString(content string) error {
return nil
}

// LoadContextConfig calls the mock LoadContextConfigFunc if set, otherwise returns nil
func (m *MockConfigHandler) LoadContextConfig() error {
if m.LoadContextConfigFunc != nil {
return m.LoadContextConfigFunc()
}
return nil
}

// IsLoaded calls the mock IsLoadedFunc if set, otherwise returns false
func (m *MockConfigHandler) IsLoaded() bool {
if m.IsLoadedFunc != nil {
Expand Down
72 changes: 72 additions & 0 deletions pkg/config/mock_config_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,3 +735,75 @@ func TestMockConfigHandler_GenerateContextID(t *testing.T) {
}
})
}

func TestMockConfigHandler_LoadContextConfig(t *testing.T) {
t.Run("WithFuncSet", func(t *testing.T) {
// Given a MockConfigHandler with LoadContextConfigFunc set
mockHandler := NewMockConfigHandler()
expectedError := fmt.Errorf("mocked load context config error")
mockHandler.LoadContextConfigFunc = func() error {
return expectedError
}

// When LoadContextConfig is called
err := mockHandler.LoadContextConfig()

// Then it should return the mocked error
if err != expectedError {
t.Errorf("LoadContextConfig() error = %v, expected %v", err, expectedError)
}
})

t.Run("WithNoFuncSet", func(t *testing.T) {
// Given a MockConfigHandler with no LoadContextConfigFunc set
mockHandler := NewMockConfigHandler()

// When LoadContextConfig is called
err := mockHandler.LoadContextConfig()

// Then it should return nil
if err != nil {
t.Errorf("LoadContextConfig() error = %v, expected nil", err)
}
})
}

func TestMockConfigHandler_YamlMarshalWithDefinedPaths(t *testing.T) {
t.Run("WithFuncSet", func(t *testing.T) {
// Given a MockConfigHandler with YamlMarshalWithDefinedPathsFunc set
mockHandler := NewMockConfigHandler()
expectedResult := []byte("mocked: yaml")
expectedError := fmt.Errorf("mocked marshal error")
mockHandler.YamlMarshalWithDefinedPathsFunc = func(v any) ([]byte, error) {
return expectedResult, expectedError
}

// When YamlMarshalWithDefinedPaths is called
result, err := mockHandler.YamlMarshalWithDefinedPaths("test")

// Then it should return the mocked result and error
if string(result) != string(expectedResult) {
t.Errorf("YamlMarshalWithDefinedPaths() result = %v, expected %v", result, expectedResult)
}
if err != expectedError {
t.Errorf("YamlMarshalWithDefinedPaths() error = %v, expected %v", err, expectedError)
}
})

t.Run("WithNoFuncSet", func(t *testing.T) {
// Given a MockConfigHandler with no YamlMarshalWithDefinedPathsFunc set
mockHandler := NewMockConfigHandler()

// When YamlMarshalWithDefinedPaths is called
result, err := mockHandler.YamlMarshalWithDefinedPaths("test")

// Then it should return the default YAML content and no error
expectedDefault := []byte("contexts:\n mock-context:\n dns:\n domain: mock.domain.com")
if string(result) != string(expectedDefault) {
t.Errorf("YamlMarshalWithDefinedPaths() result = %v, expected %v", result, expectedDefault)
}
if err != nil {
t.Errorf("YamlMarshalWithDefinedPaths() error = %v, expected nil", err)
}
})
}
54 changes: 54 additions & 0 deletions pkg/config/yaml_config_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,60 @@ func (y *YamlConfigHandler) LoadConfig(path string) error {
return y.LoadConfigString(string(data))
}

// LoadContextConfig loads context-specific windsor.yaml configuration and merges it with the existing configuration.
// It looks for windsor.yaml files in the current context's directory (contexts/<context>/windsor.yaml).
// The context-specific configuration is expected to contain only the context configuration values without
// the top-level "contexts" key. These values are merged into the current context configuration.
func (y *YamlConfigHandler) LoadContextConfig() error {
if y.shell == nil {
return fmt.Errorf("shell not initialized")
}

projectRoot, err := y.shell.GetProjectRoot()
if err != nil {
return fmt.Errorf("error retrieving project root: %w", err)
}

contextName := y.GetContext()
contextConfigDir := filepath.Join(projectRoot, "contexts", contextName)

yamlPath := filepath.Join(contextConfigDir, "windsor.yaml")
ymlPath := filepath.Join(contextConfigDir, "windsor.yml")

var contextConfigPath string
if _, err := y.shims.Stat(yamlPath); err == nil {
contextConfigPath = yamlPath
} else if _, err := y.shims.Stat(ymlPath); err == nil {
contextConfigPath = ymlPath
}

if contextConfigPath == "" {
return nil
}

data, err := y.shims.ReadFile(contextConfigPath)
if err != nil {
return fmt.Errorf("error reading context config file: %w", err)
}

var contextConfig v1alpha1.Context
if err := y.shims.YamlUnmarshal(data, &contextConfig); err != nil {
return fmt.Errorf("error unmarshalling context yaml: %w", err)
}

if y.config.Contexts == nil {
y.config.Contexts = make(map[string]*v1alpha1.Context)
}

if y.config.Contexts[contextName] == nil {
y.config.Contexts[contextName] = &v1alpha1.Context{}
}

y.config.Contexts[contextName].Merge(&contextConfig)

return nil
}

// SaveConfig saves the current configuration to the specified path. If the path is empty, it uses the previously loaded path.
// If overwrite is false and the file exists, it will not overwrite the file
func (y *YamlConfigHandler) SaveConfig(path string, overwrite ...bool) error {
Expand Down
Loading
Loading