diff --git a/pkg/module_manager/go_hook/go_hook.go b/pkg/module_manager/go_hook/go_hook.go index 5d7aa5f1..4ac65b30 100644 --- a/pkg/module_manager/go_hook/go_hook.go +++ b/pkg/module_manager/go_hook/go_hook.go @@ -26,8 +26,8 @@ type GoHook interface { type HookConfigLoader interface { LoadAndValidate() (*config.HookConfig, error) LoadOnStartup() (*float64, error) - LoadBeforeAll() (*float64, error) - LoadAfterAll() (*float64, error) + LoadBeforeAll(kind string) (*float64, error) + LoadAfterAll(kind string) (*float64, error) LoadAfterDeleteHelm() (*float64, error) } diff --git a/pkg/module_manager/models/hooks/global_hook_config.go b/pkg/module_manager/models/hooks/global_hook_config.go index 7b7836a6..541377cd 100644 --- a/pkg/module_manager/models/hooks/global_hook_config.go +++ b/pkg/module_manager/models/hooks/global_hook_config.go @@ -1,27 +1,14 @@ package hooks import ( - "errors" "fmt" - "github.com/davecgh/go-spew/spew" - sdkhook "github.com/deckhouse/module-sdk/pkg/hook" "github.com/go-openapi/spec" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/yaml" . "github.com/flant/addon-operator/pkg/hook/types" gohook "github.com/flant/addon-operator/pkg/module_manager/go_hook" "github.com/flant/shell-operator/pkg/hook/config" . "github.com/flant/shell-operator/pkg/hook/types" - kubeeventsmanager "github.com/flant/shell-operator/pkg/kube_events_manager" - eventtypes "github.com/flant/shell-operator/pkg/kube_events_manager/types" - schdulertypes "github.com/flant/shell-operator/pkg/schedule_manager/types" -) - -const ( - defaultHookGroupName = "main" - defaultHookQueueName = "main" ) // GlobalHookConfig is a structure with versioned hook configuration @@ -84,66 +71,6 @@ func getGlobalHookConfigSchema(version string) *spec.Schema { return config.GetSchema(globalHookVersion) } -// LoadAndValidateShellConfig loads shell hook config from bytes and validate it. Returns multierror. -func (c *GlobalHookConfig) LoadAndValidateShellConfig(data []byte) error { - vu := config.NewDefaultVersionedUntyped() - err := vu.Load(data) - if err != nil { - return err - } - - err = config.ValidateConfig(vu.Obj, getGlobalHookConfigSchema(vu.Version), "") - if err != nil { - return err - } - - c.Version = vu.Version - - err = c.HookConfig.ConvertAndCheck(data) - if err != nil { - return err - } - - err = c.ConvertAndCheck(data) - if err != nil { - return err - } - - return nil -} - -func (c *GlobalHookConfig) LoadAndValidateBatchConfig(hcfg *sdkhook.HookConfig) error { - c.Version = hcfg.ConfigVersion - - hcv1 := remapHookConfigV1FromHookConfig(hcfg) - - err := hcv1.ConvertAndCheck(&c.HookConfig) - if err != nil { - return fmt.Errorf("convert and check from hook config v1: %w", err) - } - - if hcfg.OnStartup != nil { - c.OnStartup = &OnStartupConfig{} - c.OnStartup.AllowFailure = false - c.OnStartup.BindingName = string(OnStartup) - c.OnStartup.Order = float64(*hcfg.OnStartup) - } - - if hcfg.OnBeforeHelm != nil { - c.BeforeAll = &BeforeAllConfig{} - c.BeforeAll.BindingName = string(BeforeAll) - c.BeforeAll.Order = float64(*hcfg.OnBeforeHelm) - } - - if hcfg.OnAfterHelm != nil { - c.AfterAll = &AfterAllConfig{} - c.AfterAll.BindingName = string(AfterAll) - c.AfterAll.Order = float64(*hcfg.OnAfterHelm) - } - - return nil -} - func (c *GlobalHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigLoader) error { hookConfig, err := configLoader.LoadAndValidate() if err != nil { @@ -164,7 +91,7 @@ func (c *GlobalHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL c.OnStartup.Order = *onStartup } - beforeAll, err := configLoader.LoadBeforeAll() + beforeAll, err := configLoader.LoadBeforeAll(string(BeforeAll)) if err != nil { return fmt.Errorf("load before all: %w", err) } @@ -175,7 +102,7 @@ func (c *GlobalHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL c.BeforeAll.Order = *beforeAll } - afterAll, err := configLoader.LoadAfterAll() + afterAll, err := configLoader.LoadAfterAll(string(AfterAll)) if err != nil { return fmt.Errorf("load after all: %w", err) } @@ -189,113 +116,6 @@ func (c *GlobalHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL return nil } -func (c *GlobalHookConfig) LoadAndValidateGoConfig(input *gohook.HookConfig) error { - hookConfig, err := newHookConfigFromGoConfig(input) - if err != nil { - return err - } - - c.HookConfig = hookConfig - - if input.OnBeforeAll != nil { - c.BeforeAll = &BeforeAllConfig{} - c.BeforeAll.BindingName = string(BeforeAll) - c.BeforeAll.Order = input.OnBeforeAll.Order - } - - if input.OnAfterAll != nil { - c.AfterAll = &AfterAllConfig{} - c.AfterAll.BindingName = string(AfterAll) - c.AfterAll.Order = input.OnAfterAll.Order - } - - return nil -} - -func (c *GlobalHookConfig) ConvertAndCheck(data []byte) error { - switch c.Version { - case "v0": - configV0 := &GlobalHookConfigV0{} - err := yaml.Unmarshal(data, configV0) - if err != nil { - return fmt.Errorf("unmarshal GlobalHookConfig version 0: %s", err) - } - c.GlobalV0 = configV0 - err = c.ConvertAndCheckV0() - if err != nil { - return err - } - case "v1": - configV1 := &GlobalHookConfigV0{} - err := yaml.Unmarshal(data, configV1) - if err != nil { - return fmt.Errorf("unmarshal GlobalHookConfig v1: %s", err) - } - c.GlobalV1 = configV1 - err = c.ConvertAndCheckV1() - if err != nil { - return err - } - default: - // NOTE: this should not happen - return fmt.Errorf("version '%s' is unsupported", c.Version) - } - - return nil -} - -func (c *GlobalHookConfig) ConvertAndCheckV0() (err error) { - c.BeforeAll, err = c.ConvertBeforeAll(c.GlobalV0.BeforeAll) - if err != nil { - return err - } - - c.AfterAll, err = c.ConvertAfterAll(c.GlobalV0.AfterAll) - if err != nil { - return err - } - - return nil -} - -func (c *GlobalHookConfig) ConvertAndCheckV1() (err error) { - c.BeforeAll, err = c.ConvertBeforeAll(c.GlobalV1.BeforeAll) - if err != nil { - return err - } - - c.AfterAll, err = c.ConvertAfterAll(c.GlobalV1.AfterAll) - if err != nil { - return err - } - - return nil -} - -func (c *GlobalHookConfig) ConvertBeforeAll(value interface{}) (*BeforeAllConfig, error) { - floatValue, err := config.ConvertFloatForBinding(value, "beforeAll") - if err != nil || floatValue == nil { - return nil, err - } - - res := &BeforeAllConfig{} - res.BindingName = string(BeforeAll) - res.Order = *floatValue - return res, nil -} - -func (c *GlobalHookConfig) ConvertAfterAll(value interface{}) (*AfterAllConfig, error) { - floatValue, err := config.ConvertFloatForBinding(value, "afterAll") - if err != nil || floatValue == nil { - return nil, err - } - - res := &AfterAllConfig{} - res.BindingName = string(AfterAll) - res.Order = *floatValue - return res, nil -} - func (c *GlobalHookConfig) Bindings() []BindingType { res := make([]BindingType, 0) @@ -338,158 +158,3 @@ func (c *GlobalHookConfig) BindingsCount() int { } return res } - -func newHookConfigFromGoConfig(input *gohook.HookConfig) (config.HookConfig, error) { - c := config.HookConfig{ - Version: "v1", - Schedules: []ScheduleConfig{}, - OnKubernetesEvents: []OnKubernetesEventConfig{}, - } - - if input.Settings != nil { - c.Settings = &Settings{ - ExecutionMinInterval: input.Settings.ExecutionMinInterval, - ExecutionBurst: input.Settings.ExecutionBurst, - } - } - - if input.OnStartup != nil { - c.OnStartup = &OnStartupConfig{} - c.OnStartup.BindingName = string(OnStartup) - c.OnStartup.Order = input.OnStartup.Order - } - - /*** A HUGE copy paste from shell-operator’s hook_config.ConvertAndCheckV1 ***/ - // WARNING no checks and defaults! - for i, kubeCfg := range input.Kubernetes { - // err := c.CheckOnKubernetesEventV1(kubeCfg, fmt.Sprintf("kubernetes[%d]", i)) - // if err != nil { - // return fmt.Errorf("invalid kubernetes config [%d]: %v", i, err) - //} - - monitor := &kubeeventsmanager.MonitorConfig{} - monitor.Metadata.DebugName = config.MonitorDebugName(kubeCfg.Name, i) - monitor.Metadata.MonitorId = config.MonitorConfigID() - monitor.Metadata.LogLabels = map[string]string{} - monitor.Metadata.MetricLabels = map[string]string{} - // monitor.WithMode(kubeCfg.Mode) - monitor.ApiVersion = kubeCfg.ApiVersion - monitor.Kind = kubeCfg.Kind - monitor.WithNameSelector(kubeCfg.NameSelector) - monitor.WithFieldSelector(kubeCfg.FieldSelector) - monitor.WithNamespaceSelector(kubeCfg.NamespaceSelector) - monitor.WithLabelSelector(kubeCfg.LabelSelector) - if kubeCfg.FilterFunc == nil { - return config.HookConfig{}, errors.New(`"FilterFunc" in KubernetesConfig cannot be nil`) - } - filterFunc := kubeCfg.FilterFunc - monitor.FilterFunc = func(obj *unstructured.Unstructured) (interface{}, error) { - return filterFunc(obj) - } - if gohook.BoolDeref(kubeCfg.ExecuteHookOnEvents, true) { - monitor.WithEventTypes(nil) - } else { - monitor.WithEventTypes([]eventtypes.WatchEventType{}) - } - - kubeConfig := OnKubernetesEventConfig{} - kubeConfig.Monitor = monitor - kubeConfig.AllowFailure = input.AllowFailure - if kubeCfg.Name == "" { - return c, spew.Errorf(`"name" is a required field in binding: %v`, kubeCfg) - } - kubeConfig.BindingName = kubeCfg.Name - if input.Queue == "" { - kubeConfig.Queue = defaultHookQueueName - } else { - kubeConfig.Queue = input.Queue - } - kubeConfig.Group = defaultHookGroupName - - kubeConfig.ExecuteHookOnSynchronization = gohook.BoolDeref(kubeCfg.ExecuteHookOnSynchronization, true) - kubeConfig.WaitForSynchronization = gohook.BoolDeref(kubeCfg.WaitForSynchronization, true) - - kubeConfig.KeepFullObjectsInMemory = false - kubeConfig.Monitor.KeepFullObjectsInMemory = false - - c.OnKubernetesEvents = append(c.OnKubernetesEvents, kubeConfig) - } - - // for i, kubeCfg := range c.V1.OnKubernetesEvent { - // if len(kubeCfg.IncludeSnapshotsFrom) > 0 { - // err := c.CheckIncludeSnapshots(kubeCfg.IncludeSnapshotsFrom...) - // if err != nil { - // return fmt.Errorf("invalid kubernetes config [%d]: includeSnapshots %v", i, err) - // } - // } - //} - - // schedule bindings with includeSnapshotsFrom - // are depend on kubernetes bindings. - c.Schedules = []ScheduleConfig{} - for _, inSch := range input.Schedule { - // err := c.CheckScheduleV1(rawSchedule) - // if err != nil { - // return fmt.Errorf("invalid schedule config [%d]: %v", i, err) - //} - - res := ScheduleConfig{} - - if inSch.Name == "" { - return c, spew.Errorf(`"name" is a required field in binding: %v`, inSch) - } - res.BindingName = inSch.Name - - res.AllowFailure = input.AllowFailure - res.ScheduleEntry = schdulertypes.ScheduleEntry{ - Crontab: inSch.Crontab, - Id: config.ScheduleID(), - } - - if input.Queue == "" { - res.Queue = "main" - } else { - res.Queue = input.Queue - } - res.Group = "main" - - // schedule, err := c.ConvertScheduleV1(rawSchedule) - // if err != nil { - // return err - //} - c.Schedules = append(c.Schedules, res) - } - - // Update IncludeSnapshotsFrom for every binding with a group. - // Merge binding's IncludeSnapshotsFrom with snapshots list calculated for group. - groupSnapshots := make(map[string][]string) - for _, kubeCfg := range c.OnKubernetesEvents { - if kubeCfg.Group == "" { - continue - } - if _, ok := groupSnapshots[kubeCfg.Group]; !ok { - groupSnapshots[kubeCfg.Group] = make([]string, 0) - } - groupSnapshots[kubeCfg.Group] = append(groupSnapshots[kubeCfg.Group], kubeCfg.BindingName) - } - newKubeEvents := make([]OnKubernetesEventConfig, 0) - for _, cfg := range c.OnKubernetesEvents { - if snapshots, ok := groupSnapshots[cfg.Group]; ok { - cfg.IncludeSnapshotsFrom = config.MergeArrays(cfg.IncludeSnapshotsFrom, snapshots) - } - newKubeEvents = append(newKubeEvents, cfg) - } - c.OnKubernetesEvents = newKubeEvents - newSchedules := make([]ScheduleConfig, 0) - for _, cfg := range c.Schedules { - if snapshots, ok := groupSnapshots[cfg.Group]; ok { - cfg.IncludeSnapshotsFrom = config.MergeArrays(cfg.IncludeSnapshotsFrom, snapshots) - } - newSchedules = append(newSchedules, cfg) - } - c.Schedules = newSchedules - - /*** END Copy Paste ***/ - - return c, nil -} diff --git a/pkg/module_manager/models/hooks/global_hook_config_test.go b/pkg/module_manager/models/hooks/global_hook_config_test.go deleted file mode 100644 index 0583ddd8..00000000 --- a/pkg/module_manager/models/hooks/global_hook_config_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package hooks - -import ( - "testing" - - . "github.com/onsi/gomega" -) - -func Test_GlobalHook_Config_v0_v1(t *testing.T) { - g := NewWithT(t) - - var err error - var config *GlobalHookConfig - - tests := []struct { - name string - hookName string - data string - assertion func() - }{ - { - "load v0 config", - "hook_v0", - `{"onStartup":10, "schedule":[{"crontab":"*/5 * * * * *"}], "beforeAll":22, "afterAll":10}`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.BeforeAll.Order).To(Equal(22.0)) - g.Expect(config.AfterAll.Order).To(Equal(10.0)) - }, - }, - { - "load v1 config", - "hook_v1", - `{"configVersion": "v1", "onStartup":10, "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], "beforeAll":22, "afterAll":10}`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.BeforeAll.Order).To(Equal(22.0)) - g.Expect(config.AfterAll.Order).To(Equal(10.0)) - }, - }, - { - "load v1 yaml config", - "hook_v1", - ` -configVersion: v1 -onStartup: 10 -kubernetes: -- kind: Pod - watchEvent: ["Added"] -beforeAll: 22 -afterAll: 10 -`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.BeforeAll.Order).To(Equal(22.0)) - g.Expect(config.AfterAll.Order).To(Equal(10.0)) - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(_ *testing.T) { - config = &GlobalHookConfig{} - err = config.LoadAndValidateShellConfig([]byte(test.data)) - test.assertion() - }) - } -} diff --git a/pkg/module_manager/models/hooks/kind/batch_hook.go b/pkg/module_manager/models/hooks/kind/batch_hook.go index 202cce78..a871c861 100644 --- a/pkg/module_manager/models/hooks/kind/batch_hook.go +++ b/pkg/module_manager/models/hooks/kind/batch_hook.go @@ -227,12 +227,12 @@ func (h *BatchHook) LoadOnStartup() (*float64, error) { return &res, nil } -func (h *BatchHook) LoadBeforeAll() (*float64, error) { +func (h *BatchHook) LoadBeforeAll(_ string) (*float64, error) { res := float64(*h.config.OnBeforeHelm) return &res, nil } -func (h *BatchHook) LoadAfterAll() (*float64, error) { +func (h *BatchHook) LoadAfterAll(_ string) (*float64, error) { res := float64(*h.config.OnAfterHelm) return &res, nil } diff --git a/pkg/module_manager/models/hooks/kind/global_hook_config_test.go b/pkg/module_manager/models/hooks/kind/global_hook_config_test.go new file mode 100644 index 00000000..7219bc20 --- /dev/null +++ b/pkg/module_manager/models/hooks/kind/global_hook_config_test.go @@ -0,0 +1,68 @@ +package kind + +// import ( +// "testing" + +// . "github.com/onsi/gomega" +// ) + +// func Test_GlobalHook_Config_v0_v1(t *testing.T) { +// g := NewWithT(t) + +// var err error +// var shHook *GlobalHookConfig + +// tests := []struct { +// name string +// hookName string +// data string +// assertion func() +// }{ +// { +// "load v0 config", +// "hook_v0", +// `{"onStartup":10, "schedule":[{"crontab":"*/5 * * * * *"}], "beforeAll":22, "afterAll":10}`, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(shHook.BeforeAll.Order).To(Equal(22.0)) +// g.Expect(shHook.AfterAll.Order).To(Equal(10.0)) +// }, +// }, +// { +// "load v1 config", +// "hook_v1", +// `{"configVersion": "v1", "onStartup":10, "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], "beforeAll":22, "afterAll":10}`, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(shHook.BeforeAll.Order).To(Equal(22.0)) +// g.Expect(shHook.AfterAll.Order).To(Equal(10.0)) +// }, +// }, +// { +// "load v1 yaml config", +// "hook_v1", +// ` +// configVersion: v1 +// onStartup: 10 +// kubernetes: +// - kind: Pod +// watchEvent: ["Added"] +// beforeAll: 22 +// afterAll: 10 +// `, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(shHook.BeforeAll.Order).To(Equal(22.0)) +// g.Expect(shHook.AfterAll.Order).To(Equal(10.0)) +// }, +// }, +// } + +// for _, test := range tests { +// t.Run(test.name, func(_ *testing.T) { +// shHook = &ShellHook{} +// err = shHook.LoadAndValidateShellConfig([]byte(test.data)) +// test.assertion() +// }) +// } +// } diff --git a/pkg/module_manager/models/hooks/kind/gohook.go b/pkg/module_manager/models/hooks/kind/gohook.go index 340fb814..1b4a6dde 100644 --- a/pkg/module_manager/models/hooks/kind/gohook.go +++ b/pkg/module_manager/models/hooks/kind/gohook.go @@ -205,7 +205,7 @@ func (h *GoHook) LoadOnStartup() (*float64, error) { return nil, nil } -func (h *GoHook) LoadBeforeAll() (*float64, error) { +func (h *GoHook) LoadBeforeAll(kind string) (*float64, error) { if h.config.OnBeforeAll != nil { return &h.config.OnBeforeAll.Order, nil } @@ -217,7 +217,7 @@ func (h *GoHook) LoadBeforeAll() (*float64, error) { return nil, nil } -func (h *GoHook) LoadAfterAll() (*float64, error) { +func (h *GoHook) LoadAfterAll(kind string) (*float64, error) { if h.config.OnAfterAll != nil { return &h.config.OnAfterAll.Order, nil } diff --git a/pkg/module_manager/models/hooks/kind/module_hook_config_test.go b/pkg/module_manager/models/hooks/kind/module_hook_config_test.go new file mode 100644 index 00000000..2facd06f --- /dev/null +++ b/pkg/module_manager/models/hooks/kind/module_hook_config_test.go @@ -0,0 +1,274 @@ +package kind + +// import ( +// "testing" + +// sdkhook "github.com/deckhouse/module-sdk/pkg/hook" +// "github.com/deckhouse/module-sdk/pkg/utils/ptr" +// . "github.com/onsi/gomega" + +// . "github.com/flant/addon-operator/pkg/hook/types" +// . "github.com/flant/shell-operator/pkg/hook/types" +// ) + +// func Test_ModuleHook_Config_v0_v1(t *testing.T) { +// var g *WithT +// var err error +// var config *ModuleHookConfig + +// tests := []struct { +// name string +// hookName string +// configText string +// assertion func() +// }{ +// { +// "load v0 module config", +// "hook_v0", +// `{"onStartup":10, +// "schedule":[{"crontab":"*/5 * * * * *"}], +// "beforeHelm": 5, +// "afterHelm": 15, +// "afterDeleteHelm": 25 +// }`, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.Schedules).To(HaveLen(1)) +// g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) +// g.Expect(config.OnStartup.Order).To(Equal(10.0)) +// g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeFalse()) +// // Check module specific bindings +// g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) +// g.Expect(config.BeforeHelm.Order).To(Equal(5.0)) +// g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) +// g.Expect(config.AfterHelm.Order).To(Equal(15.0)) +// g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) +// g.Expect(config.AfterDeleteHelm.Order).To(Equal(25.0)) +// }, +// }, +// { +// "load v0 onStart", +// "hook_v0", +// `{"onStartup":10}`, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.Bindings()).To(HaveLen(1)) +// }, +// }, +// { +// "load v1 module config", +// "hook_v1", +// `{"configVersion": "v1", +// "onStartup":10, +// "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], +// "beforeHelm": 98, +// "afterHelm": 58, +// "afterDeleteHelm": 18}`, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) +// g.Expect(config.HasBinding(Schedule)).To(BeFalse()) +// g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) +// g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) +// // Check module specific bindings +// g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) +// g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) +// g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) +// g.Expect(config.AfterHelm.Order).To(Equal(58.0)) +// g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) +// g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) +// }, +// }, +// { +// "load v1 module yaml config", +// "hook_v1", +// ` +// configVersion: v1 +// onStartup: 10 +// kubernetes: +// - kind: Pod +// watchEvent: ["Added"] +// beforeHelm: 98 +// afterHelm: 58 +// afterDeleteHelm: 18 +// `, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) +// g.Expect(config.HasBinding(Schedule)).To(BeFalse()) +// g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) +// g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) +// // Check module specific bindings +// g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) +// g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) +// g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) +// g.Expect(config.AfterHelm.Order).To(Equal(58.0)) +// g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) +// g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) +// }, +// }, +// { +// "load v1 bad module config", +// "hook_v1", +// `{"configVersion": "v1", "onStartuppp":10, "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], "beforeHelm":98}`, +// func() { +// g.Expect(err).Should(HaveOccurred()) +// g.Expect(err.Error()).Should(And( +// ContainSubstring("1 error occurred"), +// ContainSubstring("onStartuppp is a forbidden property"), +// )) +// }, +// }, +// } + +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// g = NewWithT(t) +// config = &ModuleHookConfig{} +// err = config.LoadAndValidateShellConfig([]byte(tt.configText)) +// tt.assertion() +// }) +// } +// } + +// func Test_ModuleHook_Batch_Config_v0_v1(t *testing.T) { +// var g *WithT +// var err error +// var config *ModuleHookConfig + +// tests := []struct { +// name string +// hookName string +// config *sdkhook.HookConfig +// assertion func() +// }{ +// { +// "load v0 module config", +// "hook_v0", +// // `{"onStartup":10, +// // "schedule":[{"crontab":"*/5 * * * * *"}], +// // "beforeHelm": 5, +// // "afterHelm": 15, +// // "afterDeleteHelm": 25 +// // }`, +// &sdkhook.HookConfig{ +// OnStartup: ptr.To(uint(10)), +// Schedule: []sdkhook.ScheduleConfig{ +// {Crontab: "*/5 * * * * *"}, +// }, +// OnBeforeHelm: ptr.To(uint(5)), +// OnAfterHelm: ptr.To(uint(15)), +// OnAfterDeleteHelm: ptr.To(uint(25)), +// }, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.Schedules).To(HaveLen(1)) +// g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) +// g.Expect(config.OnStartup.Order).To(Equal(10.0)) +// g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeFalse()) +// // Check module specific bindings +// g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) +// g.Expect(config.BeforeHelm.Order).To(Equal(5.0)) +// g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) +// g.Expect(config.AfterHelm.Order).To(Equal(15.0)) +// g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) +// g.Expect(config.AfterDeleteHelm.Order).To(Equal(25.0)) +// }, +// }, +// { +// "load v0 onStart", +// "hook_v0", +// // `{"onStartup":10}`, +// &sdkhook.HookConfig{ +// OnStartup: ptr.To(uint(10)), +// }, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.Bindings()).To(HaveLen(1)) +// }, +// }, +// { +// "load v1 module config", +// "hook_v1", +// // `{"configVersion": "v1", +// // "onStartup":10, +// // "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], +// // "beforeHelm": 98, +// // "afterHelm": 58, +// // "afterDeleteHelm": 18}`, +// &sdkhook.HookConfig{ +// ConfigVersion: "v1", +// OnStartup: ptr.To(uint(10)), +// Kubernetes: []sdkhook.KubernetesConfig{ +// {Kind: "Pod"}, +// }, +// OnBeforeHelm: ptr.To(uint(98)), +// OnAfterHelm: ptr.To(uint(58)), +// OnAfterDeleteHelm: ptr.To(uint(18)), +// }, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) +// g.Expect(config.HasBinding(Schedule)).To(BeFalse()) +// g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) +// g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) +// // Check module specific bindings +// g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) +// g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) +// g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) +// g.Expect(config.AfterHelm.Order).To(Equal(58.0)) +// g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) +// g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) +// }, +// }, +// { +// "load v1 module yaml config", +// "hook_v1", +// // ` +// // +// // configVersion: v1 +// // onStartup: 10 +// // kubernetes: +// // - kind: Pod +// // watchEvent: ["Added"] +// // +// // beforeHelm: 98 +// // afterHelm: 58 +// // afterDeleteHelm: 18 +// // `, +// &sdkhook.HookConfig{ +// ConfigVersion: "v1", +// OnStartup: ptr.To(uint(10)), +// Kubernetes: []sdkhook.KubernetesConfig{ +// {Kind: "Pod"}, +// }, +// OnBeforeHelm: ptr.To(uint(98)), +// OnAfterHelm: ptr.To(uint(58)), +// OnAfterDeleteHelm: ptr.To(uint(18)), +// }, +// func() { +// g.Expect(err).ShouldNot(HaveOccurred()) +// g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) +// g.Expect(config.HasBinding(Schedule)).To(BeFalse()) +// g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) +// g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) +// // Check module specific bindings +// g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) +// g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) +// g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) +// g.Expect(config.AfterHelm.Order).To(Equal(58.0)) +// g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) +// g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) +// }, +// }, +// } + +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// g = NewWithT(t) +// config = &ModuleHookConfig{} +// err = config.LoadAndValidateBatchConfig(tt.config) +// tt.assertion() +// }) +// } +// } diff --git a/pkg/module_manager/models/hooks/kind/shellhook.go b/pkg/module_manager/models/hooks/kind/shellhook.go index 65c38bd8..978057cd 100644 --- a/pkg/module_manager/models/hooks/kind/shellhook.go +++ b/pkg/module_manager/models/hooks/kind/shellhook.go @@ -11,6 +11,7 @@ import ( "github.com/gofrs/uuid/v5" "gopkg.in/yaml.v2" + ahtypes "github.com/flant/addon-operator/pkg/hook/types" gohook "github.com/flant/addon-operator/pkg/module_manager/go_hook" "github.com/flant/addon-operator/pkg/utils" shapp "github.com/flant/shell-operator/pkg/app" @@ -249,29 +250,35 @@ func (sh *ShellHook) LoadOnStartup() (*float64, error) { return nil, nil } -func (sh *ShellHook) LoadBeforeAll() (*float64, error) { - res, err := ConvertFloatForBinding(sh.ScheduleConfig.BeforeAll, "before all") - if res != nil || err != nil { - return res, err - } - - res, err = ConvertFloatForBinding(sh.ScheduleConfig.BeforeHelm, "before helm") - if res != nil || err != nil { - return res, err +func (sh *ShellHook) LoadBeforeAll(kind string) (*float64, error) { + switch kind { + case string(ahtypes.BeforeAll): + res, err := ConvertFloatForBinding(sh.ScheduleConfig.BeforeAll, "before all") + if res != nil || err != nil { + return res, err + } + case string(ahtypes.BeforeHelm): + res, err := ConvertFloatForBinding(sh.ScheduleConfig.BeforeHelm, "before helm") + if res != nil || err != nil { + return res, err + } } return nil, nil } -func (sh *ShellHook) LoadAfterAll() (*float64, error) { - res, err := ConvertFloatForBinding(sh.ScheduleConfig.AfterAll, "after all") - if res != nil || err != nil { - return res, err - } - - res, err = ConvertFloatForBinding(sh.ScheduleConfig.AfterHelm, "after helm") - if res != nil || err != nil { - return res, err +func (sh *ShellHook) LoadAfterAll(kind string) (*float64, error) { + switch kind { + case string(ahtypes.AfterAll): + res, err := ConvertFloatForBinding(sh.ScheduleConfig.AfterAll, "after all") + if res != nil || err != nil { + return res, err + } + case string(ahtypes.AfterHelm): + res, err := ConvertFloatForBinding(sh.ScheduleConfig.AfterHelm, "after helm") + if res != nil || err != nil { + return res, err + } } return nil, nil diff --git a/pkg/module_manager/models/hooks/module_hook_config.go b/pkg/module_manager/models/hooks/module_hook_config.go index 5004c07b..906eba42 100644 --- a/pkg/module_manager/models/hooks/module_hook_config.go +++ b/pkg/module_manager/models/hooks/module_hook_config.go @@ -2,17 +2,13 @@ package hooks import ( "fmt" - "strconv" - sdkhook "github.com/deckhouse/module-sdk/pkg/hook" "github.com/go-openapi/spec" - "sigs.k8s.io/yaml" . "github.com/flant/addon-operator/pkg/hook/types" gohook "github.com/flant/addon-operator/pkg/module_manager/go_hook" "github.com/flant/shell-operator/pkg/hook/config" . "github.com/flant/shell-operator/pkg/hook/types" - "github.com/flant/shell-operator/pkg/kube_events_manager/types" ) // ModuleHookConfig is a structure with versioned hook configuration @@ -88,183 +84,6 @@ func getModuleHookConfigSchema(version string) *spec.Schema { return config.GetSchema(globalHookVersion) } -// LoadAndValidateShellConfig loads shell hook config from bytes and validate it. Returns multierror. -func (c *ModuleHookConfig) LoadAndValidateShellConfig(data []byte) error { - // find config version - vu := config.NewDefaultVersionedUntyped() - err := vu.Load(data) - if err != nil { - return fmt.Errorf("load data: %w", err) - } - - // validate config scheme - err = config.ValidateConfig(vu.Obj, getModuleHookConfigSchema(vu.Version), "") - if err != nil { - return fmt.Errorf("validate config: %w", err) - } - - c.Version = vu.Version - - // unmarshal data and enrich hook config - err = c.HookConfig.ConvertAndCheck(data) - if err != nil { - return fmt.Errorf("convert and check hook config: %w", err) - } - - // unmarshal data and enrich module hook config - err = c.ConvertAndCheck(data) - if err != nil { - return fmt.Errorf("convert and check: %w", err) - } - - return nil -} - -func remapHookConfigV1FromHookConfig(hcfg *sdkhook.HookConfig) *config.HookConfigV1 { - hcv1 := &config.HookConfigV1{ - ConfigVersion: hcfg.ConfigVersion, - } - - if len(hcfg.Schedule) > 0 { - hcv1.Schedule = make([]config.ScheduleConfigV1, 0, len(hcfg.Schedule)) - } - - if len(hcfg.Kubernetes) > 0 { - hcv1.OnKubernetesEvent = make([]config.OnKubernetesEventConfigV1, 0, len(hcfg.Kubernetes)) - } - - if hcfg.OnStartup != nil { - hcv1.OnStartup = float64(*hcfg.OnStartup) - } - - if hcfg.Settings != nil { - hcv1.Settings = &config.SettingsV1{ - ExecutionMinInterval: hcfg.Settings.ExecutionMinInterval.String(), - ExecutionBurst: strconv.Itoa(hcfg.Settings.ExecutionBurst), - } - } - - for _, sch := range hcfg.Schedule { - hcv1.Schedule = append(hcv1.Schedule, config.ScheduleConfigV1{ - Name: sch.Name, - Crontab: sch.Crontab, - }) - } - - for _, kube := range hcfg.Kubernetes { - newShCfg := config.OnKubernetesEventConfigV1{ - ApiVersion: kube.APIVersion, - Kind: kube.Kind, - Name: kube.Name, - LabelSelector: kube.LabelSelector, - JqFilter: kube.JqFilter, - ExecuteHookOnSynchronization: "true", - WaitForSynchronization: "true", - // permanently false - KeepFullObjectsInMemory: "false", - ResynchronizationPeriod: kube.ResynchronizationPeriod, - IncludeSnapshotsFrom: kube.IncludeSnapshotsFrom, - Queue: kube.Queue, - // TODO: make default constants public to use here - // like go hooks apply default - Group: "main", - } - - if kube.NameSelector != nil { - newShCfg.NameSelector = &config.KubeNameSelectorV1{ - MatchNames: kube.NameSelector.MatchNames, - } - } - - if kube.NamespaceSelector != nil { - newShCfg.Namespace = &config.KubeNamespaceSelectorV1{ - NameSelector: (*types.NameSelector)(kube.NamespaceSelector.NameSelector), - LabelSelector: kube.NamespaceSelector.LabelSelector, - } - } - - if kube.FieldSelector != nil { - fs := &config.KubeFieldSelectorV1{ - MatchExpressions: make([]types.FieldSelectorRequirement, 0, len(kube.FieldSelector.MatchExpressions)), - } - - for _, expr := range kube.FieldSelector.MatchExpressions { - fs.MatchExpressions = append(fs.MatchExpressions, types.FieldSelectorRequirement(expr)) - } - - newShCfg.FieldSelector = fs - } - - if kube.KeepFullObjectsInMemory != nil { - newShCfg.KeepFullObjectsInMemory = strconv.FormatBool(*kube.KeepFullObjectsInMemory) - } - - // *bool --> ExecuteHookOnEvents: [All events] || empty array or nothing - if kube.ExecuteHookOnEvents != nil && !*kube.ExecuteHookOnEvents { - newShCfg.ExecuteHookOnEvents = make([]types.WatchEventType, 0, 1) - } - - if kube.ExecuteHookOnSynchronization != nil { - newShCfg.ExecuteHookOnSynchronization = strconv.FormatBool(*kube.ExecuteHookOnSynchronization) - } - - if kube.WaitForSynchronization != nil { - newShCfg.WaitForSynchronization = strconv.FormatBool(*kube.WaitForSynchronization) - } - - if kube.KeepFullObjectsInMemory != nil { - newShCfg.KeepFullObjectsInMemory = strconv.FormatBool(*kube.KeepFullObjectsInMemory) - } - - if kube.AllowFailure != nil { - newShCfg.AllowFailure = *kube.AllowFailure - } - - hcv1.OnKubernetesEvent = append(hcv1.OnKubernetesEvent, newShCfg) - } - - return hcv1 -} - -func (c *ModuleHookConfig) LoadAndValidateBatchConfig(hcfg *sdkhook.HookConfig) error { - c.Version = hcfg.ConfigVersion - - hcv1 := remapHookConfigV1FromHookConfig(hcfg) - - c.HookConfig.V1 = hcv1 - err := hcv1.ConvertAndCheck(&c.HookConfig) - if err != nil { - return fmt.Errorf("convert and check from hook config v1: %w", err) - } - - if hcfg.OnStartup != nil { - c.OnStartup = &OnStartupConfig{} - c.OnStartup.AllowFailure = false - c.OnStartup.BindingName = string(OnStartup) - c.OnStartup.Order = float64(*hcfg.OnStartup) - } - - if hcfg.OnBeforeHelm != nil { - c.BeforeHelm = &BeforeHelmConfig{} - c.BeforeHelm.BindingName = string(BeforeHelm) - c.BeforeHelm.Order = float64(*hcfg.OnBeforeHelm) - } - - if hcfg.OnAfterHelm != nil { - c.AfterHelm = &AfterHelmConfig{} - c.AfterHelm.BindingName = string(AfterHelm) - c.AfterHelm.Order = float64(*hcfg.OnAfterHelm) - } - - if hcfg.OnAfterDeleteHelm != nil { - c.AfterDeleteHelm = &AfterDeleteHelmConfig{} - c.AfterDeleteHelm.BindingName = string(AfterDeleteHelm) - c.AfterDeleteHelm.Order = float64(*hcfg.OnAfterDeleteHelm) - } - - return nil -} - func (c *ModuleHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigLoader) error { hookConfig, err := configLoader.LoadAndValidate() if err != nil { @@ -285,9 +104,9 @@ func (c *ModuleHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL c.OnStartup.Order = *onStartup } - beforeAll, err := configLoader.LoadBeforeAll() + beforeAll, err := configLoader.LoadBeforeAll(string(BeforeHelm)) if err != nil { - return fmt.Errorf("load before all: %w", err) + return fmt.Errorf("load before helm: %w", err) } if beforeAll != nil { @@ -296,9 +115,9 @@ func (c *ModuleHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL c.BeforeHelm.Order = *beforeAll } - afterAll, err := configLoader.LoadAfterAll() + afterAll, err := configLoader.LoadAfterAll(string(AfterHelm)) if err != nil { - return fmt.Errorf("load after all: %w", err) + return fmt.Errorf("load after helm: %w", err) } if afterAll != nil { @@ -309,7 +128,7 @@ func (c *ModuleHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL afterDelete, err := configLoader.LoadAfterDeleteHelm() if err != nil { - return fmt.Errorf("load after all: %w", err) + return fmt.Errorf("load after delete helm: %w", err) } if afterDelete != nil { @@ -321,137 +140,6 @@ func (c *ModuleHookConfig) LoadAndValidateConfig(configLoader gohook.HookConfigL return nil } -func (c *ModuleHookConfig) LoadAndValidateGoConfig(input *gohook.HookConfig) error { - hookConfig, err := newHookConfigFromGoConfig(input) - if err != nil { - return err - } - - c.HookConfig = hookConfig - - if input.OnBeforeHelm != nil { - c.BeforeHelm = &BeforeHelmConfig{} - c.BeforeHelm.BindingName = string(BeforeHelm) - c.BeforeHelm.Order = input.OnBeforeHelm.Order - } - - if input.OnAfterHelm != nil { - c.AfterHelm = &AfterHelmConfig{} - c.AfterHelm.BindingName = string(AfterHelm) - c.AfterHelm.Order = input.OnAfterHelm.Order - } - - if input.OnAfterDeleteHelm != nil { - c.AfterDeleteHelm = &AfterDeleteHelmConfig{} - c.AfterDeleteHelm.BindingName = string(AfterDeleteHelm) - c.AfterDeleteHelm.Order = input.OnAfterDeleteHelm.Order - } - - return nil -} - -func (c *ModuleHookConfig) ConvertAndCheck(data []byte) error { - switch c.Version { - case "v0": - configV0 := &ModuleHookConfigV0{} - err := yaml.Unmarshal(data, configV0) - if err != nil { - return fmt.Errorf("unmarshal ModuleHookConfig version 0: %s", err) - } - c.ModuleV0 = configV0 - err = c.ConvertAndCheckV0() - if err != nil { - return err - } - case "v1": - configV1 := &ModuleHookConfigV0{} - err := yaml.Unmarshal(data, configV1) - if err != nil { - return fmt.Errorf("unmarshal ModuleHookConfig v1: %s", err) - } - c.ModuleV1 = configV1 - err = c.ConvertAndCheckV1() - if err != nil { - return err - } - default: - // NOTE: this should not happen - return fmt.Errorf("version '%s' is unsupported", c.Version) - } - - return nil -} - -func (c *ModuleHookConfig) ConvertAndCheckV0() (err error) { - c.BeforeHelm, err = c.ConvertBeforeHelm(c.ModuleV0.BeforeHelm) - if err != nil { - return err - } - c.AfterHelm, err = c.ConvertAfterHelm(c.ModuleV0.AfterHelm) - if err != nil { - return err - } - c.AfterDeleteHelm, err = c.ConvertAfterDeleteHelm(c.ModuleV0.AfterDeleteHelm) - if err != nil { - return err - } - - return nil -} - -func (c *ModuleHookConfig) ConvertAndCheckV1() (err error) { - c.BeforeHelm, err = c.ConvertBeforeHelm(c.ModuleV1.BeforeHelm) - if err != nil { - return err - } - c.AfterHelm, err = c.ConvertAfterHelm(c.ModuleV1.AfterHelm) - if err != nil { - return err - } - c.AfterDeleteHelm, err = c.ConvertAfterDeleteHelm(c.ModuleV1.AfterDeleteHelm) - if err != nil { - return err - } - - return nil -} - -func (c *ModuleHookConfig) ConvertBeforeHelm(value interface{}) (*BeforeHelmConfig, error) { - floatValue, err := config.ConvertFloatForBinding(value, "beforeHelm") - if err != nil || floatValue == nil { - return nil, err - } - - res := &BeforeHelmConfig{} - res.BindingName = string(BeforeHelm) - res.Order = *floatValue - return res, nil -} - -func (c *ModuleHookConfig) ConvertAfterHelm(value interface{}) (*AfterHelmConfig, error) { - floatValue, err := config.ConvertFloatForBinding(value, "afterHelm") - if err != nil || floatValue == nil { - return nil, err - } - - res := &AfterHelmConfig{} - res.BindingName = string(AfterHelm) - res.Order = *floatValue - return res, nil -} - -func (c *ModuleHookConfig) ConvertAfterDeleteHelm(value interface{}) (*AfterDeleteHelmConfig, error) { - floatValue, err := config.ConvertFloatForBinding(value, "afterDeleteHelm") - if err != nil || floatValue == nil { - return nil, err - } - - res := &AfterDeleteHelmConfig{} - res.BindingName = string(AfterDeleteHelm) - res.Order = *floatValue - return res, nil -} - func (c *ModuleHookConfig) Bindings() []BindingType { res := make([]BindingType, 0) diff --git a/pkg/module_manager/models/hooks/module_hook_config_test.go b/pkg/module_manager/models/hooks/module_hook_config_test.go deleted file mode 100644 index 2a17134f..00000000 --- a/pkg/module_manager/models/hooks/module_hook_config_test.go +++ /dev/null @@ -1,274 +0,0 @@ -package hooks - -import ( - "testing" - - sdkhook "github.com/deckhouse/module-sdk/pkg/hook" - "github.com/deckhouse/module-sdk/pkg/utils/ptr" - . "github.com/onsi/gomega" - - . "github.com/flant/addon-operator/pkg/hook/types" - . "github.com/flant/shell-operator/pkg/hook/types" -) - -func Test_ModuleHook_Config_v0_v1(t *testing.T) { - var g *WithT - var err error - var config *ModuleHookConfig - - tests := []struct { - name string - hookName string - configText string - assertion func() - }{ - { - "load v0 module config", - "hook_v0", - `{"onStartup":10, - "schedule":[{"crontab":"*/5 * * * * *"}], - "beforeHelm": 5, - "afterHelm": 15, - "afterDeleteHelm": 25 - }`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.Schedules).To(HaveLen(1)) - g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) - g.Expect(config.OnStartup.Order).To(Equal(10.0)) - g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeFalse()) - // Check module specific bindings - g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) - g.Expect(config.BeforeHelm.Order).To(Equal(5.0)) - g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) - g.Expect(config.AfterHelm.Order).To(Equal(15.0)) - g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) - g.Expect(config.AfterDeleteHelm.Order).To(Equal(25.0)) - }, - }, - { - "load v0 onStart", - "hook_v0", - `{"onStartup":10}`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.Bindings()).To(HaveLen(1)) - }, - }, - { - "load v1 module config", - "hook_v1", - `{"configVersion": "v1", - "onStartup":10, - "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], - "beforeHelm": 98, - "afterHelm": 58, - "afterDeleteHelm": 18}`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) - g.Expect(config.HasBinding(Schedule)).To(BeFalse()) - g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) - g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) - // Check module specific bindings - g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) - g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) - g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) - g.Expect(config.AfterHelm.Order).To(Equal(58.0)) - g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) - g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) - }, - }, - { - "load v1 module yaml config", - "hook_v1", - ` -configVersion: v1 -onStartup: 10 -kubernetes: -- kind: Pod - watchEvent: ["Added"] -beforeHelm: 98 -afterHelm: 58 -afterDeleteHelm: 18 -`, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) - g.Expect(config.HasBinding(Schedule)).To(BeFalse()) - g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) - g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) - // Check module specific bindings - g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) - g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) - g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) - g.Expect(config.AfterHelm.Order).To(Equal(58.0)) - g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) - g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) - }, - }, - { - "load v1 bad module config", - "hook_v1", - `{"configVersion": "v1", "onStartuppp":10, "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], "beforeHelm":98}`, - func() { - g.Expect(err).Should(HaveOccurred()) - g.Expect(err.Error()).Should(And( - ContainSubstring("1 error occurred"), - ContainSubstring("onStartuppp is a forbidden property"), - )) - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g = NewWithT(t) - config = &ModuleHookConfig{} - err = config.LoadAndValidateShellConfig([]byte(tt.configText)) - tt.assertion() - }) - } -} - -func Test_ModuleHook_Batch_Config_v0_v1(t *testing.T) { - var g *WithT - var err error - var config *ModuleHookConfig - - tests := []struct { - name string - hookName string - config *sdkhook.HookConfig - assertion func() - }{ - { - "load v0 module config", - "hook_v0", - // `{"onStartup":10, - // "schedule":[{"crontab":"*/5 * * * * *"}], - // "beforeHelm": 5, - // "afterHelm": 15, - // "afterDeleteHelm": 25 - // }`, - &sdkhook.HookConfig{ - OnStartup: ptr.To(uint(10)), - Schedule: []sdkhook.ScheduleConfig{ - {Crontab: "*/5 * * * * *"}, - }, - OnBeforeHelm: ptr.To(uint(5)), - OnAfterHelm: ptr.To(uint(15)), - OnAfterDeleteHelm: ptr.To(uint(25)), - }, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.Schedules).To(HaveLen(1)) - g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) - g.Expect(config.OnStartup.Order).To(Equal(10.0)) - g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeFalse()) - // Check module specific bindings - g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) - g.Expect(config.BeforeHelm.Order).To(Equal(5.0)) - g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) - g.Expect(config.AfterHelm.Order).To(Equal(15.0)) - g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) - g.Expect(config.AfterDeleteHelm.Order).To(Equal(25.0)) - }, - }, - { - "load v0 onStart", - "hook_v0", - // `{"onStartup":10}`, - &sdkhook.HookConfig{ - OnStartup: ptr.To(uint(10)), - }, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.Bindings()).To(HaveLen(1)) - }, - }, - { - "load v1 module config", - "hook_v1", - // `{"configVersion": "v1", - // "onStartup":10, - // "kubernetes":[{"kind":"Pod", "watchEvent":["Added"]}], - // "beforeHelm": 98, - // "afterHelm": 58, - // "afterDeleteHelm": 18}`, - &sdkhook.HookConfig{ - ConfigVersion: "v1", - OnStartup: ptr.To(uint(10)), - Kubernetes: []sdkhook.KubernetesConfig{ - {Kind: "Pod"}, - }, - OnBeforeHelm: ptr.To(uint(98)), - OnAfterHelm: ptr.To(uint(58)), - OnAfterDeleteHelm: ptr.To(uint(18)), - }, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) - g.Expect(config.HasBinding(Schedule)).To(BeFalse()) - g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) - g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) - // Check module specific bindings - g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) - g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) - g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) - g.Expect(config.AfterHelm.Order).To(Equal(58.0)) - g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) - g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) - }, - }, - { - "load v1 module yaml config", - "hook_v1", - // ` - // - // configVersion: v1 - // onStartup: 10 - // kubernetes: - // - kind: Pod - // watchEvent: ["Added"] - // - // beforeHelm: 98 - // afterHelm: 58 - // afterDeleteHelm: 18 - // `, - &sdkhook.HookConfig{ - ConfigVersion: "v1", - OnStartup: ptr.To(uint(10)), - Kubernetes: []sdkhook.KubernetesConfig{ - {Kind: "Pod"}, - }, - OnBeforeHelm: ptr.To(uint(98)), - OnAfterHelm: ptr.To(uint(58)), - OnAfterDeleteHelm: ptr.To(uint(18)), - }, - func() { - g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(config.HasBinding(OnStartup)).To(BeTrue()) - g.Expect(config.HasBinding(Schedule)).To(BeFalse()) - g.Expect(config.HasBinding(OnKubernetesEvent)).To(BeTrue()) - g.Expect(config.OnKubernetesEvents).To(HaveLen(1)) - // Check module specific bindings - g.Expect(config.HasBinding(BeforeHelm)).To(BeTrue()) - g.Expect(config.BeforeHelm.Order).To(Equal(98.0)) - g.Expect(config.HasBinding(AfterHelm)).To(BeTrue()) - g.Expect(config.AfterHelm.Order).To(Equal(58.0)) - g.Expect(config.HasBinding(AfterDeleteHelm)).To(BeTrue()) - g.Expect(config.AfterDeleteHelm.Order).To(Equal(18.0)) - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g = NewWithT(t) - config = &ModuleHookConfig{} - err = config.LoadAndValidateBatchConfig(tt.config) - tt.assertion() - }) - } -}