Skip to content

Commit

Permalink
feat: add default backend in the configuration file (#968)
Browse files Browse the repository at this point in the history
  • Loading branch information
healthjyk authored Mar 27, 2024
1 parent d18332c commit 97c6f0f
Show file tree
Hide file tree
Showing 11 changed files with 444 additions and 191 deletions.
2 changes: 2 additions & 0 deletions pkg/apis/core/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type Config struct {
}

const (
DefaultBackendName = "default"

BackendCurrent = "current"
BackendType = "type"
BackendConfigItems = "configs"
Expand Down
25 changes: 7 additions & 18 deletions pkg/backend/backend.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package backend

import (
"errors"
"fmt"

v1 "kusionstack.io/kusion/pkg/apis/core/v1"
Expand Down Expand Up @@ -29,28 +28,18 @@ type Backend interface {
// input name is empty, use the current backend. If no current backend is specified or backends config is empty,
// and the input name is empty, use the default local storage.
func NewBackend(name string) (Backend, error) {
var emptyCfg bool
cfg, err := config.GetConfig()
if errors.Is(err, config.ErrEmptyConfig) {
emptyCfg = true
} else if err != nil {
if err != nil {
return nil, err
} else if cfg.Backends == nil {
emptyCfg = true
}

var bkCfg *v1.BackendConfig
if name == "" && (emptyCfg || cfg.Backends.Current == "") {
// if empty backends config or empty current backend, use default local storage
bkCfg = &v1.BackendConfig{Type: v1.BackendTypeLocal}
} else {
if name == "" {
name = cfg.Backends.Current
}
bkCfg = cfg.Backends.Backends[name]
if bkCfg == nil {
return nil, fmt.Errorf("config of backend %s does not exist", name)
}
if name == "" {
name = cfg.Backends.Current
}
bkCfg = cfg.Backends.Backends[name]
if bkCfg == nil {
return nil, fmt.Errorf("config of backend %s does not exist", name)
}

var storage Backend
Expand Down
5 changes: 4 additions & 1 deletion pkg/backend/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func mockConfig() *v1.Config {
Backends: &v1.BackendConfigs{
Current: "pre",
Backends: map[string]*v1.BackendConfig{
v1.DefaultBackendName: {
Type: v1.BackendTypeLocal,
},
"dev": {
Type: v1.BackendTypeLocal,
Configs: map[string]any{
Expand Down Expand Up @@ -76,7 +79,7 @@ func TestNewBackend(t *testing.T) {
success: true,
cfg: func() *v1.Config {
cfg := mockConfig()
cfg.Backends.Current = ""
cfg.Backends.Current = v1.DefaultBackendName
return cfg
}(),
envs: nil,
Expand Down
92 changes: 53 additions & 39 deletions pkg/config/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@ import (
const configFile = "config.yaml"

var (
ErrEmptyConfig = errors.New("empty config")
ErrEmptyConfigItem = errors.New("empty config item")
ErrConflictConfigItemType = errors.New("type of the config item conflicts between saved and registered")
ErrEmptyConfigItemKey = errors.New("empty config item key")
ErrEmptyConfigItemValue = errors.New("empty config item value")
ErrUnsupportedConfigItem = errors.New("unsupported config item")
ErrEmptyBackendName = errors.New("backend name should not be empty")
ErrInvalidBackendName = errors.New("backend name should not be current")
ErrEmptyConfigItem = errors.New("empty config item")
ErrConflictConfigItemType = errors.New("type of the config item conflicts between saved and registered")
ErrEmptyConfigItemKey = errors.New("empty config item key")
ErrEmptyConfigItemValue = errors.New("empty config item value")
ErrUnsupportedConfigItem = errors.New("unsupported config item")
ErrEmptyBackendName = errors.New("backend name should not be empty")
ErrInvalidBackendNameCurrent = errors.New("backend name should not be current")
)

// operator is used to execute the config management operation.
Expand All @@ -48,10 +47,47 @@ func newOperator() (*operator, error) {
return nil, fmt.Errorf("get kusion data folder failed, %w", err)
}

return &operator{
o := &operator{
configFilePath: filepath.Join(kusionDataDir, configFile),
registeredItems: newRegisteredItems(),
}, nil
config: &v1.Config{},
}

if err = o.initDefaultConfig(); err != nil {
return nil, err
}
return o, nil
}

// initDefaultConfig reads config from the config file and inits default config, which is called when new
// an operator. Now it inits the default backend.
func (o *operator) initDefaultConfig() error {
if err := o.readConfig(); err != nil {
return err
}

// set default backend config
if o.config.Backends == nil {
o.config.Backends = &v1.BackendConfigs{}
}
if o.config.Backends.Backends == nil {
o.config.Backends.Backends = make(map[string]*v1.BackendConfig)
}
var needWrite bool
defaultBackend := &v1.BackendConfig{Type: v1.BackendTypeLocal}
if !reflect.DeepEqual(o.config.Backends.Backends[v1.DefaultBackendName], defaultBackend) {
needWrite = true
o.config.Backends.Backends[v1.DefaultBackendName] = defaultBackend
}
if o.config.Backends.Current == "" {
needWrite = true
o.config.Backends.Current = v1.DefaultBackendName
}

if needWrite {
return o.writeConfig()
}
return nil
}

// readConfig reads config from config file.
Expand All @@ -68,9 +104,6 @@ func (o *operator) readConfig() error {
if err = yaml.Unmarshal(content, cfg); err != nil {
return fmt.Errorf("unmarshal kusion config failed, %w", err)
}
if reflect.ValueOf(*cfg).IsZero() {
cfg = nil
}
o.config = cfg
return nil
}
Expand Down Expand Up @@ -204,15 +237,12 @@ func (o *operator) deleteConfigItem(key string) error {
if err != nil {
return err
}
if info.validateDeleteFunc != nil {
if err = info.validateDeleteFunc(o.config, key); err != nil {
if info.validateUnsetFunc != nil {
if err = info.validateUnsetFunc(o.config, key); err != nil {
return err
}
}

if o.config == nil {
return nil
}
cfg, err := convertToCfgMap(o.config)
if err != nil {
return err
Expand All @@ -232,10 +262,6 @@ func (o *operator) deleteConfigItem(key string) error {
// getConfigItemWithLaxType gets the value of the specified config item from config, where the type of the
// value is that in the converted config map.
func getConfigItemWithLaxType(config *v1.Config, key string) (any, error) {
if config == nil {
return nil, ErrEmptyConfigItem
}

cfg, err := convertToCfgMap(config)
if err != nil {
return nil, err
Expand All @@ -251,9 +277,6 @@ func setItemInConfig(config *v1.Config, info *itemInfo, key string, value any) (
return nil, err
}

if config == nil {
config = &v1.Config{}
}
cfg, err := convertToCfgMap(config)
if err != nil {
return nil, err
Expand All @@ -267,9 +290,6 @@ func setItemInConfig(config *v1.Config, info *itemInfo, key string, value any) (
// tidyConfig is used to clean dirty empty block.
func tidyConfig(configAddr **v1.Config) {
config := *configAddr
if config == nil {
return
}

if config.Backends != nil {
for name, cfg := range config.Backends.Backends {
Expand All @@ -281,16 +301,10 @@ func tidyConfig(configAddr **v1.Config) {
}
}
if len(config.Backends.Backends) == 0 {
config.Backends.Backends = nil
}
if reflect.ValueOf(*config.Backends).IsZero() {
config.Backends = nil
config.Backends.Backends = make(map[string]*v1.BackendConfig)
}
}

if reflect.ValueOf(*config).IsZero() {
config = nil
}
*configAddr = config
}

Expand All @@ -299,8 +313,8 @@ func validateConfigItem(config *v1.Config, info *itemInfo, key string, value any
if reflect.ValueOf(value).IsZero() {
return ErrEmptyConfigItemValue
}
if info.validateFunc != nil {
return info.validateFunc(config, key, value)
if info.ValidateSetFunc != nil {
return info.ValidateSetFunc(config, key, value)
}
return nil
}
Expand Down Expand Up @@ -384,8 +398,8 @@ func convertBackendKey(key string) (string, error) {
if fields[1] == v1.BackendCurrent && len(fields) == 2 {
return key, nil
}
if fields[1] == v1.BackendCurrent && len(fields) > 2 {
return "", ErrInvalidBackendName
if fields[1] == v1.BackendCurrent {
return "", ErrInvalidBackendNameCurrent
}
if fields[1] == "" {
return "", ErrEmptyBackendName
Expand Down
Loading

0 comments on commit 97c6f0f

Please sign in to comment.