Skip to content

Commit ad6c2e2

Browse files
yroblataskbot
andauthored
add new noop state storage for k8s (#1731)
add new noop state and config storage for k8s It will avoid any errors when trying to create state or config files in a read-only filesystem in k8s Related-to: #1638 Co-authored-by: taskbot <[email protected]>
1 parent 84656eb commit ad6c2e2

File tree

7 files changed

+752
-11
lines changed

7 files changed

+752
-11
lines changed

pkg/config/config.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,37 @@ func applyBackwardCompatibility(config *Config) error {
140140
// LoadOrCreateConfig fetches the application configuration.
141141
// If it does not already exist - it will create a new config file with default values.
142142
func LoadOrCreateConfig() (*Config, error) {
143-
return LoadOrCreateConfigWithPath("")
143+
provider := NewProvider()
144+
return provider.LoadOrCreateConfig()
145+
}
146+
147+
// LoadOrCreateConfigWithDefaultPath is the internal implementation for loading config with the default path.
148+
// This avoids circular dependency issues.
149+
func LoadOrCreateConfigWithDefaultPath() (*Config, error) {
150+
configPath, err := getConfigPath()
151+
if err != nil {
152+
return nil, fmt.Errorf("unable to fetch config path: %w", err)
153+
}
154+
return LoadOrCreateConfigFromPath(configPath)
144155
}
145156

146157
// LoadOrCreateConfigWithPath fetches the application configuration from a specific path.
147158
// If configPath is empty, it uses the default path.
148159
// If it does not already exist - it will create a new config file with default values.
149160
func LoadOrCreateConfigWithPath(configPath string) (*Config, error) {
150-
var config Config
151-
var err error
152-
153161
if configPath == "" {
154-
configPath, err = getConfigPath()
155-
if err != nil {
156-
return nil, fmt.Errorf("unable to fetch config path: %w", err)
157-
}
162+
// When no path is specified, use the provider pattern to handle runtime-specific behavior
163+
return LoadOrCreateConfig()
158164
}
159165

166+
return LoadOrCreateConfigFromPath(configPath)
167+
}
168+
169+
// LoadOrCreateConfigFromPath is the core implementation for loading/creating config from a specific path
170+
func LoadOrCreateConfigFromPath(configPath string) (*Config, error) {
171+
var config Config
172+
var err error
173+
160174
// Check to see if the config file already exists.
161175
configPath = path.Clean(configPath)
162176
newConfig := false
@@ -233,7 +247,8 @@ func (c *Config) saveToPath(configPath string) error {
233247
// UpdateConfig locks a separate lock file, reads from disk, applies the changes
234248
// from the anonymous function, writes to disk and unlocks the file.
235249
func UpdateConfig(updateFn func(*Config)) error {
236-
return UpdateConfigAtPath("", updateFn)
250+
provider := NewProvider()
251+
return provider.UpdateConfig(updateFn)
237252
}
238253

239254
// UpdateConfigAtPath locks a separate lock file, reads from disk, applies the changes

pkg/config/interface.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package config
22

3+
import (
4+
"github.com/stacklok/toolhive/pkg/container/runtime"
5+
)
6+
37
// Provider defines the interface for configuration operations
48
type Provider interface {
59
GetConfig() *Config
@@ -28,12 +32,12 @@ func (*DefaultProvider) GetConfig() *Config {
2832

2933
// UpdateConfig updates the config using the default path
3034
func (*DefaultProvider) UpdateConfig(updateFn func(*Config)) error {
31-
return UpdateConfig(updateFn)
35+
return UpdateConfigAtPath("", updateFn)
3236
}
3337

3438
// LoadOrCreateConfig loads or creates config using the default path
3539
func (*DefaultProvider) LoadOrCreateConfig() (*Config, error) {
36-
return LoadOrCreateConfig()
40+
return LoadOrCreateConfigWithDefaultPath()
3741
}
3842

3943
// SetRegistryURL validates and sets a registry URL
@@ -106,3 +110,57 @@ func (p *PathProvider) UnsetRegistry() error {
106110
func (p *PathProvider) GetRegistryConfig() (url, localPath string, allowPrivateIP bool, registryType string) {
107111
return getRegistryConfig(p)
108112
}
113+
114+
// KubernetesProvider is a no-op implementation of Provider for Kubernetes environments.
115+
// In Kubernetes, configuration is managed by the cluster, not by local files.
116+
type KubernetesProvider struct{}
117+
118+
// NewKubernetesProvider creates a new no-op config provider for Kubernetes environments
119+
func NewKubernetesProvider() *KubernetesProvider {
120+
return &KubernetesProvider{}
121+
}
122+
123+
// GetConfig returns a default config for Kubernetes environments
124+
func (*KubernetesProvider) GetConfig() *Config {
125+
config := createNewConfigWithDefaults()
126+
return &config
127+
}
128+
129+
// UpdateConfig is a no-op for Kubernetes environments
130+
func (*KubernetesProvider) UpdateConfig(_ func(*Config)) error {
131+
return nil
132+
}
133+
134+
// LoadOrCreateConfig returns a default config for Kubernetes environments
135+
func (*KubernetesProvider) LoadOrCreateConfig() (*Config, error) {
136+
config := createNewConfigWithDefaults()
137+
return &config, nil
138+
}
139+
140+
// SetRegistryURL is a no-op for Kubernetes environments
141+
func (*KubernetesProvider) SetRegistryURL(_ string, _ bool) error {
142+
return nil
143+
}
144+
145+
// SetRegistryFile is a no-op for Kubernetes environments
146+
func (*KubernetesProvider) SetRegistryFile(_ string) error {
147+
return nil
148+
}
149+
150+
// UnsetRegistry is a no-op for Kubernetes environments
151+
func (*KubernetesProvider) UnsetRegistry() error {
152+
return nil
153+
}
154+
155+
// GetRegistryConfig returns empty registry configuration for Kubernetes environments
156+
func (*KubernetesProvider) GetRegistryConfig() (url, localPath string, allowPrivateIP bool, registryType string) {
157+
return "", "", false, ""
158+
}
159+
160+
// NewProvider creates the appropriate config provider based on the runtime environment
161+
func NewProvider() Provider {
162+
if runtime.IsKubernetesRuntime() {
163+
return NewKubernetesProvider()
164+
}
165+
return NewDefaultProvider()
166+
}

0 commit comments

Comments
 (0)