Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[addon-operator] add module reregister #432

Merged
merged 4 commits into from
Jan 12, 2024
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
1 change: 1 addition & 0 deletions pkg/addon-operator/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func (op *AddonOperator) SetupModuleManager(modulesDir string, globalHooksDir st
HelmResourcesManager: op.HelmResourcesManager,
MetricStorage: op.engine.MetricStorage,
HookMetricStorage: op.engine.HookMetricStorage,
TaskQueues: op.engine.TaskQueues,
}

cfg := module_manager.ModuleManagerConfig{
Expand Down
2 changes: 1 addition & 1 deletion pkg/kube_config_manager/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type ConfigHandler interface {
StartInformer(ctx context.Context, eventC chan config.Event)

// LoadConfig loads initial modules config before starting the informer
LoadConfig(ctx context.Context) (*config.KubeConfig, error)
LoadConfig(ctx context.Context, modulesNames ...string) (*config.KubeConfig, error)

// SaveConfigValues saves patches for modules in backend (if supported), overriding the configuration
// Deprecated: saving values in the values source is not recommended and shouldn't be used anymore
Expand Down
4 changes: 2 additions & 2 deletions pkg/kube_config_manager/backend/configmap/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ func New(logger dlogger.Logger, kubeClient *client.Client, namespace, name strin
return backend
}

// LoadConfig gets config from ConfigMap before starting informer.
// LoadConfig gets config from ConfigMap before starting informer (selective loading configs for a list of modules isn't implemented).
// Set checksums for global section and modules.
func (b Backend) LoadConfig(ctx context.Context) (*config.KubeConfig, error) {
func (b Backend) LoadConfig(ctx context.Context, _ ...string) (*config.KubeConfig, error) {
obj, err := b.getConfigMap(ctx)
if err != nil {
return nil, err
Expand Down
27 changes: 27 additions & 0 deletions pkg/kube_config_manager/kube_config_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ func NewKubeConfigManager(ctx context.Context, bk backend.ConfigHandler, runtime
}
}

func (kcm *KubeConfigManager) IsModuleEnabled(moduleName string) bool {
moduleConfig, found := kcm.currentConfig.Modules[moduleName]
if !found {
return false
}

return moduleConfig.IsEnabled != nil && *moduleConfig.IsEnabled
}

func (kcm *KubeConfigManager) Init() error {
kcm.logEntry.Debug("Init: KubeConfigManager")

Expand Down Expand Up @@ -108,6 +117,24 @@ func (kcm *KubeConfigManager) KubeConfigEventCh() chan config.KubeConfigEvent {
return kcm.configEventCh
}

// UpdateModuleConfig updates a single module config
func (kcm *KubeConfigManager) UpdateModuleConfig(moduleName string) error {
newModuleConfig, err := kcm.backend.LoadConfig(kcm.ctx, moduleName)
if err != nil {
return err
}

if moduleConfig, found := newModuleConfig.Modules[moduleName]; found {
if kcm.knownChecksums != nil {
kcm.knownChecksums.Set(moduleName, moduleConfig.Checksum)
}

kcm.currentConfig.Modules[moduleName] = moduleConfig
}

return nil
}

// loadConfig gets config from ConfigMap before starting informer.
// Set checksums for global section and modules.
func (kcm *KubeConfigManager) loadConfig() error {
Expand Down
127 changes: 84 additions & 43 deletions pkg/module_manager/loader/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,78 @@ func NewFileSystemLoader(moduleDirs string, vv *validation.ValuesValidator) *Fil
}
}

func (fl *FileSystemLoader) getBasicModule(definition moduleDefinition, commonStaticValues utils.Values) (*modules.BasicModule, error) {
err := validateModuleName(definition.Name)
if err != nil {
return nil, err
}

valuesModuleName := utils.ModuleNameToValuesKey(definition.Name)
initialValues := utils.Values{valuesModuleName: map[string]interface{}{}}
// build initial values
// 1. from common static values
if commonStaticValues.HasKey(valuesModuleName) {
initialValues = utils.MergeValues(initialValues, commonStaticValues)
}

// 2. from module static values
moduleStaticValues, err := utils.LoadValuesFileFromDir(definition.Path)
if err != nil {
return nil, err
}

if moduleStaticValues != nil {
initialValues = utils.MergeValues(initialValues, moduleStaticValues)
}

// 3. from openapi defaults

cb, vb, err := fl.readOpenAPIFiles(filepath.Join(definition.Path, "openapi"))
if err != nil {
return nil, err
}

if cb != nil && vb != nil {
err = fl.valuesValidator.SchemaStorage.AddModuleValuesSchemas(valuesModuleName, cb, vb)
if err != nil {
return nil, err
}
}

//
moduleValues, ok := initialValues[valuesModuleName].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("expect map[string]interface{} in module values")
}

return modules.NewBasicModule(definition.Name, definition.Path, definition.Order, moduleValues, fl.valuesValidator), nil
}

// read single directory and return BasicModule for loading
func (fl *FileSystemLoader) ReloadModule(_, modulePath string) (*modules.BasicModule, error) {
_, err := readDir(modulePath)
if err != nil {
return nil, err
}

commonStaticValues, err := utils.LoadValuesFileFromDir(modulePath)
if err != nil {
return nil, err
}

modDef, err := moduleFromDirName(filepath.Base(modulePath), modulePath)
if err != nil {
return nil, err
}

bm, err := fl.getBasicModule(modDef, commonStaticValues)
if err != nil {
return nil, err
}

return bm, nil
}

func (fl *FileSystemLoader) LoadModules() ([]*modules.BasicModule, error) {
result := make([]*modules.BasicModule, 0)

Expand All @@ -44,51 +116,10 @@ func (fl *FileSystemLoader) LoadModules() ([]*modules.BasicModule, error) {
}

for _, module := range modDefs {
err = validateModuleName(module.Name)
if err != nil {
return nil, err
}

valuesModuleName := utils.ModuleNameToValuesKey(module.Name)
initialValues := utils.Values{valuesModuleName: map[string]interface{}{}}
// build initial values
// 1. from common static values
if commonStaticValues.HasKey(valuesModuleName) {
initialValues = utils.MergeValues(initialValues, commonStaticValues)
}

// 2. from module static values
moduleStaticValues, err := utils.LoadValuesFileFromDir(module.Path)
bm, err := fl.getBasicModule(module, commonStaticValues)
if err != nil {
return nil, err
}

if moduleStaticValues != nil {
initialValues = utils.MergeValues(initialValues, moduleStaticValues)
}

// 3. from openapi defaults

cb, vb, err := fl.readOpenAPIFiles(filepath.Join(module.Path, "openapi"))
if err != nil {
return nil, err
}

if cb != nil && vb != nil {
err = fl.valuesValidator.SchemaStorage.AddModuleValuesSchemas(valuesModuleName, cb, vb)
if err != nil {
return nil, err
}
}

//
moduleValues, ok := initialValues[valuesModuleName].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("expect map[string]interface{} in module values")
}

bm := modules.NewBasicModule(module.Name, module.Path, module.Order, moduleValues, fl.valuesValidator)

result = append(result, bm)
}
}
Expand All @@ -102,7 +133,8 @@ type moduleDefinition struct {
Order uint32
}

func (fl *FileSystemLoader) findModulesInDir(modulesDir string) ([]moduleDefinition, error) {
// checks if dir exists and returns entries
func readDir(modulesDir string) ([]os.DirEntry, error) {
dirEntries, err := os.ReadDir(modulesDir)
if err != nil && os.IsNotExist(err) {
return nil, fmt.Errorf("path '%s' does not exist", modulesDir)
Expand All @@ -111,6 +143,15 @@ func (fl *FileSystemLoader) findModulesInDir(modulesDir string) ([]moduleDefinit
return nil, fmt.Errorf("listing modules directory '%s': %s", modulesDir, err)
}

return dirEntries, nil
}

func (fl *FileSystemLoader) findModulesInDir(modulesDir string) ([]moduleDefinition, error) {
dirEntries, err := readDir(modulesDir)
if err != nil {
return nil, err
}

mods := make([]moduleDefinition, 0)
for _, dirEntry := range dirEntries {
name, absPath, err := resolveDirEntry(modulesDir, dirEntry)
Expand Down
1 change: 1 addition & 0 deletions pkg/module_manager/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import (

type ModuleLoader interface {
LoadModules() ([]*modules.BasicModule, error)
ReloadModule(moduleName string, modulePath string) (*modules.BasicModule, error)
}
3 changes: 3 additions & 0 deletions pkg/module_manager/models/modules/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ const (
type ModuleEvent struct {
ModuleName string
EventType ModuleEventType

// an option for registering a module without reload
Reregister bool
}
19 changes: 18 additions & 1 deletion pkg/module_manager/models/moduleset/moduleset.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
package moduleset

import (
"errors"
"sort"
"sync"

"github.com/flant/addon-operator/pkg/module_manager/models/modules"
)

var ErrNotInited = errors.New("modules haven't been initialized yet")

type ModulesSet struct {
lck sync.RWMutex
modules map[string]*modules.BasicModule
orderedNames []string
inited bool
}

func (s *ModulesSet) SetInited() {
s.lck.Lock()
defer s.lck.Unlock()
s.inited = true
}

func (s *ModulesSet) IsInited() bool {
s.lck.RLock()
defer s.lck.RUnlock()
return s.inited
}

// adds a new module or overwrite an existing
func (s *ModulesSet) Add(mods ...*modules.BasicModule) {
if len(mods) == 0 {
return
Expand All @@ -27,7 +44,7 @@ func (s *ModulesSet) Add(mods ...*modules.BasicModule) {

for _, module := range mods {
// Invalidate ordered names cache.
if _, ok := s.modules[module.GetName()]; ok {
if _, ok := s.modules[module.GetName()]; !ok {
s.orderedNames = nil
}
s.modules[module.GetName()] = module
Expand Down
2 changes: 2 additions & 0 deletions pkg/module_manager/models/moduleset/moduleset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestBasicModuleSet(t *testing.T) {
Name: "BasicModule-four",
Order: 20,
})
ms.SetInited()

expectNames := []string{
"BasicModule-one",
Expand All @@ -49,4 +50,5 @@ func TestBasicModuleSet(t *testing.T) {
g.Expect(ms.NamesInOrder()).Should(Equal(expectNames))
g.Expect(ms.Has("BasicModule-four")).Should(BeTrue(), "should have BasicModule-four")
g.Expect(ms.Get("BasicModule-four").Order).Should(Equal(uint32(20)), "should have BasicModule-four with order:20")
g.Expect(ms.IsInited()).Should(BeTrue(), "should be inited")
}
Loading
Loading