diff --git a/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go b/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go index 9cfde35909b..ca926d0eec6 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go +++ b/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go @@ -21,6 +21,7 @@ import ( "sort" "strconv" "strings" + "sync" "github.com/golang/glog" "github.com/spf13/pflag" @@ -85,6 +86,8 @@ type FeatureGate interface { // featureGate implements FeatureGate as well as pflag.Value for flag parsing. type featureGate struct { + lock sync.RWMutex + known map[Feature]FeatureSpec special map[Feature]func(*featureGate, bool) enabled map[Feature]bool @@ -121,6 +124,9 @@ func NewFeatureGate() *featureGate { // Set Parses a string of the form "key1=value1,key2=value2,..." into a // map[string]bool of known keys or returns an error. func (f *featureGate) Set(value string) error { + f.lock.Lock() + defer f.lock.Unlock() + for _, s := range strings.Split(value, ",") { if len(s) == 0 { continue @@ -153,6 +159,9 @@ func (f *featureGate) Set(value string) error { // String returns a string containing all enabled feature gates, formatted as "key1=value1,key2=value2,...". func (f *featureGate) String() string { + f.lock.RLock() + defer f.lock.RUnlock() + pairs := []string{} for k, v := range f.enabled { pairs = append(pairs, fmt.Sprintf("%s=%t", k, v)) @@ -167,6 +176,9 @@ func (f *featureGate) Type() string { // Add adds features to the featureGate. func (f *featureGate) Add(features map[Feature]FeatureSpec) error { + f.lock.Lock() + defer f.lock.Unlock() + if f.closed { return fmt.Errorf("cannot add a feature gate after adding it to the flag set") } @@ -186,6 +198,9 @@ func (f *featureGate) Add(features map[Feature]FeatureSpec) error { // Enabled returns true if the key is enabled. func (f *featureGate) Enabled(key Feature) bool { + f.lock.RLock() + defer f.lock.RUnlock() + defaultValue := f.known[key].Default if f.enabled != nil { if v, ok := f.enabled[key]; ok { @@ -197,7 +212,9 @@ func (f *featureGate) Enabled(key Feature) bool { // AddFlag adds a flag for setting global feature gates to the specified FlagSet. func (f *featureGate) AddFlag(fs *pflag.FlagSet) { + f.lock.Lock() f.closed = true + f.lock.Unlock() known := f.KnownFeatures() fs.Var(f, flagName, ""+ @@ -207,6 +224,8 @@ func (f *featureGate) AddFlag(fs *pflag.FlagSet) { // KnownFeatures returns a slice of strings describing the FeatureGate's known features. func (f *featureGate) KnownFeatures() []string { + f.lock.RLock() + defer f.lock.RUnlock() var known []string for k, v := range f.known { pre := ""