From 7ad5d275b4f95dfc291b4bac5580390c009ed397 Mon Sep 17 00:00:00 2001 From: Adam Janikowski <12255597+ajanikow@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:57:33 +0200 Subject: [PATCH] [Feature] Add Feature dependency (#1357) --- CHANGELOG.md | 1 + cmd/cmd.go | 9 ++++--- pkg/deployment/features/features.go | 40 +++++++++++++++++++++++++++++ pkg/deployment/features/graceful.go | 2 ++ pkg/deployment/features/local.go | 31 +++++++++++++++------- 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a17f62cf6..47eb6d0d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A) - (Feature) Backup lifetime - remove Backup once its lifetime has been reached +- (Feature) Add Feature dependency ## [1.2.31](https://github.com/arangodb/kube-arangodb/tree/1.2.31) (2023-07-14) - (Improvement) Block traffic on the services if there is more than 1 active leader in ActiveFailover mode diff --git a/cmd/cmd.go b/cmd/cmd.go index b898c9a6d..ce487ec50 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -304,9 +304,12 @@ func executeMain(cmd *cobra.Command, args []string) { podNameParts := strings.Split(name, "-") operatorID := podNameParts[len(podNameParts)-1] - logging.Global().RegisterWrappers(func(in *zerolog.Event) *zerolog.Event { - return in.Str("operator-id", operatorID) - }) + + if operatorID != "" { + logging.Global().RegisterWrappers(func(in *zerolog.Event) *zerolog.Event { + return in.Str("operator-id", operatorID) + }) + } logger.Info("nice to meet you") diff --git a/pkg/deployment/features/features.go b/pkg/deployment/features/features.go index bf44164af..13c472054 100644 --- a/pkg/deployment/features/features.go +++ b/pkg/deployment/features/features.go @@ -21,6 +21,8 @@ package features import ( + "sort" + "github.com/arangodb/go-driver" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" @@ -32,11 +34,30 @@ const ( Disabled = "false" ) +type Features []Feature + +func (f Features) Get(name string) (Feature, bool) { + for _, feature := range features { + if feature.Name() == name { + return feature, true + } + } + + return nil, false +} + +func (f Features) Sort() { + sort.Slice(f, func(i, j int) bool { + return f[i].Name() < f[j].Name() + }) +} + var _ Feature = &feature{} type Feature interface { Name() string Description() string + Dependencies() []Feature Version() driver.Version EnterpriseRequired() bool OperatorEnterpriseRequired() bool @@ -56,6 +77,19 @@ type feature struct { deprecated string constValue *bool hidden bool + dependencies []Feature +} + +func (f feature) Dependencies() []Feature { + if len(f.dependencies) == 0 { + return nil + } + + q := make([]Feature, len(f.dependencies)) + + copy(q, f.dependencies) + + return q } func (f feature) ImageSupported(i *api.ImageInfo) bool { @@ -82,6 +116,12 @@ func (f feature) Enabled() bool { } } + for _, dep := range f.dependencies { + if !dep.Enabled() { + return false + } + } + if f.constValue != nil { return *f.constValue } diff --git a/pkg/deployment/features/graceful.go b/pkg/deployment/features/graceful.go index bc3252782..378c322c1 100644 --- a/pkg/deployment/features/graceful.go +++ b/pkg/deployment/features/graceful.go @@ -41,6 +41,8 @@ var optionalGracefulShutdown = &feature{ enterpriseRequired: false, enabledByDefault: false, hidden: true, + + dependencies: []Feature{gracefulShutdown}, } func GracefulShutdown() Feature { diff --git a/pkg/deployment/features/local.go b/pkg/deployment/features/local.go index 6b644d76d..fbc4575b7 100644 --- a/pkg/deployment/features/local.go +++ b/pkg/deployment/features/local.go @@ -23,6 +23,7 @@ package features import ( "fmt" "os" + "strings" "sync" "github.com/spf13/cobra" @@ -34,7 +35,7 @@ import ( const prefixArg = "deployment.feature" -var features = map[string]Feature{} +var features Features var featuresLock sync.Mutex var enableAll = false @@ -42,15 +43,13 @@ func registerFeature(f Feature) { featuresLock.Lock() defer featuresLock.Unlock() - if f == nil { - panic("Feature cannot be nil") - } - - if _, ok := features[f.Name()]; ok { + if _, ok := features.Get(f.Name()); ok { panic("Feature already registered") } - features[f.Name()] = f + features = append(features, f) + + features.Sort() } var internalCMD = &cobra.Command{ @@ -67,8 +66,8 @@ func Iterate(iterator Iterator) { featuresLock.Lock() defer featuresLock.Unlock() - for name, feature := range features { - iterator(name, feature) + for _, feature := range features { + iterator(feature.Name(), feature) } } @@ -130,6 +129,13 @@ func cmdRun(_ *cobra.Command, _ []string) { for _, feature := range features { println(fmt.Sprintf("Feature: %s", feature.Name())) println(fmt.Sprintf("Description: %s", feature.Description())) + if deps := feature.Dependencies(); len(deps) > 0 { + names := make([]string, len(deps)) + for id := range names { + names[id] = deps[id].Name() + } + println(fmt.Sprintf("Dependencies: %s", strings.Join(names, ", "))) + } if feature.EnabledByDefault() { println("Enabled: true") } else { @@ -155,6 +161,7 @@ func cmdRun(_ *cobra.Command, _ []string) { // Supported returns false when: // - feature is disabled. +// - any feature dependency is disabled. // - a given version is lower than minimum feature version. // - feature expects enterprise but a given enterprise arg is not true. func Supported(f Feature, v driver.Version, enterprise bool) bool { @@ -167,6 +174,12 @@ func Supported(f Feature, v driver.Version, enterprise bool) bool { return false } + for _, dependency := range f.Dependencies() { + if !Supported(dependency, v, enterprise) { + return false + } + } + return v.CompareTo(f.Version()) >= 0 }