Make feature gate threadsafe
Kubernetes-commit: d3546434b7252167b851a40a339d8ed2049ee5e5
This commit is contained in:
		
							parent
							
								
									eb6826bbda
								
							
						
					
					
						commit
						605d377a4e
					
				|  | @ -21,6 +21,7 @@ import ( | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"sync" | ||||||
| 
 | 
 | ||||||
| 	"github.com/golang/glog" | 	"github.com/golang/glog" | ||||||
| 	"github.com/spf13/pflag" | 	"github.com/spf13/pflag" | ||||||
|  | @ -85,6 +86,8 @@ type FeatureGate interface { | ||||||
| 
 | 
 | ||||||
| // featureGate implements FeatureGate as well as pflag.Value for flag parsing.
 | // featureGate implements FeatureGate as well as pflag.Value for flag parsing.
 | ||||||
| type featureGate struct { | type featureGate struct { | ||||||
|  | 	lock sync.RWMutex | ||||||
|  | 
 | ||||||
| 	known   map[Feature]FeatureSpec | 	known   map[Feature]FeatureSpec | ||||||
| 	special map[Feature]func(*featureGate, bool) | 	special map[Feature]func(*featureGate, bool) | ||||||
| 	enabled map[Feature]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
 | // Set Parses a string of the form "key1=value1,key2=value2,..." into a
 | ||||||
| // map[string]bool of known keys or returns an error.
 | // map[string]bool of known keys or returns an error.
 | ||||||
| func (f *featureGate) Set(value string) error { | func (f *featureGate) Set(value string) error { | ||||||
|  | 	f.lock.Lock() | ||||||
|  | 	defer f.lock.Unlock() | ||||||
|  | 
 | ||||||
| 	for _, s := range strings.Split(value, ",") { | 	for _, s := range strings.Split(value, ",") { | ||||||
| 		if len(s) == 0 { | 		if len(s) == 0 { | ||||||
| 			continue | 			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,...".
 | // String returns a string containing all enabled feature gates, formatted as "key1=value1,key2=value2,...".
 | ||||||
| func (f *featureGate) String() string { | func (f *featureGate) String() string { | ||||||
|  | 	f.lock.RLock() | ||||||
|  | 	defer f.lock.RUnlock() | ||||||
|  | 
 | ||||||
| 	pairs := []string{} | 	pairs := []string{} | ||||||
| 	for k, v := range f.enabled { | 	for k, v := range f.enabled { | ||||||
| 		pairs = append(pairs, fmt.Sprintf("%s=%t", k, v)) | 		pairs = append(pairs, fmt.Sprintf("%s=%t", k, v)) | ||||||
|  | @ -167,6 +176,9 @@ func (f *featureGate) Type() string { | ||||||
| 
 | 
 | ||||||
| // Add adds features to the featureGate.
 | // Add adds features to the featureGate.
 | ||||||
| func (f *featureGate) Add(features map[Feature]FeatureSpec) error { | func (f *featureGate) Add(features map[Feature]FeatureSpec) error { | ||||||
|  | 	f.lock.Lock() | ||||||
|  | 	defer f.lock.Unlock() | ||||||
|  | 
 | ||||||
| 	if f.closed { | 	if f.closed { | ||||||
| 		return fmt.Errorf("cannot add a feature gate after adding it to the flag set") | 		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.
 | // Enabled returns true if the key is enabled.
 | ||||||
| func (f *featureGate) Enabled(key Feature) bool { | func (f *featureGate) Enabled(key Feature) bool { | ||||||
|  | 	f.lock.RLock() | ||||||
|  | 	defer f.lock.RUnlock() | ||||||
|  | 
 | ||||||
| 	defaultValue := f.known[key].Default | 	defaultValue := f.known[key].Default | ||||||
| 	if f.enabled != nil { | 	if f.enabled != nil { | ||||||
| 		if v, ok := f.enabled[key]; ok { | 		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.
 | // AddFlag adds a flag for setting global feature gates to the specified FlagSet.
 | ||||||
| func (f *featureGate) AddFlag(fs *pflag.FlagSet) { | func (f *featureGate) AddFlag(fs *pflag.FlagSet) { | ||||||
|  | 	f.lock.Lock() | ||||||
| 	f.closed = true | 	f.closed = true | ||||||
|  | 	f.lock.Unlock() | ||||||
| 
 | 
 | ||||||
| 	known := f.KnownFeatures() | 	known := f.KnownFeatures() | ||||||
| 	fs.Var(f, flagName, ""+ | 	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.
 | // KnownFeatures returns a slice of strings describing the FeatureGate's known features.
 | ||||||
| func (f *featureGate) KnownFeatures() []string { | func (f *featureGate) KnownFeatures() []string { | ||||||
|  | 	f.lock.RLock() | ||||||
|  | 	defer f.lock.RUnlock() | ||||||
| 	var known []string | 	var known []string | ||||||
| 	for k, v := range f.known { | 	for k, v := range f.known { | ||||||
| 		pre := "" | 		pre := "" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue