From c285f93cda205c469a70469645db44b9303f86a5 Mon Sep 17 00:00:00 2001 From: Baek Date: Thu, 23 May 2024 16:30:28 +0000 Subject: [PATCH] featuregate: adds EtcdServer.FeatureEnabled interface. The interface can be used throughout the etcd server binary to check if the feature is enabled or not. --- pkg/featuregate/featuregate.go | 35 ++++++++++++++++++++++++++++++++++ server/config/config.go | 4 ++++ server/etcdserver/server.go | 10 ++++++++++ 3 files changed, 49 insertions(+) create mode 100644 pkg/featuregate/featuregate.go diff --git a/pkg/featuregate/featuregate.go b/pkg/featuregate/featuregate.go new file mode 100644 index 000000000000..4bae61620c58 --- /dev/null +++ b/pkg/featuregate/featuregate.go @@ -0,0 +1,35 @@ +// Copyright 2015 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package featuregate implements feature gate for to track/manage new features being added to etcd servers. +package featuregate + +import "fmt" + +type Feature string + +// defaultFeatureGates tracks Features added (but not yet enabled) to etcd servers. +// TODO(stackbaek): use VersionedSpecs, once kep-4330 is implemented. +var defaultFeatureGates = map[Feature]interface{}{} + +type FeatureGate struct{} + +// Enabled returns true if a Feature is enabled, false otherwise. +// Note that the error will be returned if the Feature is not added to the etcd servers. +func (fg FeatureGate) Enabled(f Feature) (bool, error) { + if _, ok := defaultFeatureGates[f]; !ok { + return false, fmt.Errorf("Unknown feature %s.", f) + } + return false, nil +} diff --git a/server/config/config.go b/server/config/config.go index 14e8fa3df98c..5d9a173a4f5e 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -28,6 +28,7 @@ import ( bolt "go.etcd.io/bbolt" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/pkg/v3/featuregate" "go.etcd.io/etcd/pkg/v3/netutil" "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" "go.etcd.io/etcd/server/v3/storage/datadir" @@ -204,6 +205,9 @@ type ServerConfig struct { // V2Deprecation defines a phase of v2store deprecation process. V2Deprecation V2DeprecationEnum `json:"v2-deprecation"` + + // ServerFeatureGate server level feature gate + ServerFeatureGate featuregate.FeatureGate } // VerifyBootstrap sanity-checks the initial config for bootstrap case diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 541cf797c64a..022ec2e7d15d 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -39,6 +39,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/client/pkg/v3/verify" + "go.etcd.io/etcd/pkg/v3/featuregate" "go.etcd.io/etcd/pkg/v3/idutil" "go.etcd.io/etcd/pkg/v3/notify" "go.etcd.io/etcd/pkg/v3/pbutil" @@ -456,6 +457,15 @@ func (s *EtcdServer) Config() config.ServerConfig { return s.Cfg } +// FeatureEnabled returns true if the feature is enabled by the etcd server, false otherwise. +func (s *EtcdServer) FeatureEnabled(f featuregate.Feature) bool { + enabled, err := s.Cfg.ServerFeatureGate.Enabled(f) + if err != nil { + s.Logger().Warn(fmt.Sprintf("Failed to check if feature is enabled: %v", err)) + } + return enabled +} + func tickToDur(ticks int, tickMs uint) string { return fmt.Sprintf("%v", time.Duration(ticks)*time.Duration(tickMs)*time.Millisecond) }