mirror of https://github.com/k3s-io/k3s
Merge pull request #42648 from sttts/sttts-multiple-feature-gate-calls
Automatic merge from submit-queue (batch tested with PRs 42637, 42648) Support multiple --feature-gates flags in the command line Fixes the issue in https://github.com/kubernetes/kubernetes/pull/42647. Before this change the whole set of gates was replaced with new values. Now values are overridden one by one.pull/6/head
commit
7593a9f555
|
@ -50,10 +50,7 @@ var (
|
|||
}
|
||||
|
||||
// DefaultFeatureGate is a shared global FeatureGate.
|
||||
DefaultFeatureGate = &featureGate{
|
||||
known: defaultFeatures,
|
||||
special: specialFeatures,
|
||||
}
|
||||
DefaultFeatureGate FeatureGate = NewFeatureGate()
|
||||
)
|
||||
|
||||
type FeatureSpec struct {
|
||||
|
@ -75,43 +72,9 @@ const (
|
|||
type FeatureGate interface {
|
||||
AddFlag(fs *pflag.FlagSet)
|
||||
Set(value string) error
|
||||
Add(features map[Feature]FeatureSpec)
|
||||
Enabled(key Feature) bool
|
||||
Add(features map[Feature]FeatureSpec) error
|
||||
KnownFeatures() []string
|
||||
|
||||
// Every feature gate should add method here following this template:
|
||||
//
|
||||
// // owner: @username
|
||||
// // alpha: v1.4
|
||||
// MyFeature() bool
|
||||
|
||||
// owner: @timstclair
|
||||
// beta: v1.4
|
||||
AppArmor() bool
|
||||
|
||||
// owner: @girishkalele
|
||||
// alpha: v1.4
|
||||
ExternalTrafficLocalOnly() bool
|
||||
|
||||
// owner: @saad-ali
|
||||
// alpha: v1.3
|
||||
DynamicVolumeProvisioning() bool
|
||||
|
||||
// owner: @mtaufen
|
||||
// alpha: v1.4
|
||||
DynamicKubeletConfig() bool
|
||||
|
||||
// owner: timstclair
|
||||
// alpha: v1.5
|
||||
StreamingProxyRedirects() bool
|
||||
|
||||
// owner: @pweil-
|
||||
// alpha: v1.5
|
||||
ExperimentalHostUserNamespaceDefaulting() bool
|
||||
|
||||
// owner: @davidopp
|
||||
// alpha: v1.6
|
||||
// TODO: remove when alpha support for affinity is removed
|
||||
AffinityInAnnotations() bool
|
||||
}
|
||||
|
||||
// featureGate implements FeatureGate as well as pflag.Value for flag parsing.
|
||||
|
@ -137,10 +100,21 @@ func setUnsetAlphaGates(f *featureGate, val bool) {
|
|||
// Set, String, and Type implement pflag.Value
|
||||
var _ pflag.Value = &featureGate{}
|
||||
|
||||
func NewFeatureGate() *featureGate {
|
||||
f := &featureGate{
|
||||
known: map[Feature]FeatureSpec{},
|
||||
special: specialFeatures,
|
||||
enabled: map[Feature]bool{},
|
||||
}
|
||||
for k, v := range defaultFeatures {
|
||||
f.known[k] = v
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// 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.enabled = make(map[Feature]bool)
|
||||
for _, s := range strings.Split(value, ",") {
|
||||
if len(s) == 0 {
|
||||
continue
|
||||
|
|
|
@ -119,9 +119,11 @@ func TestFeatureGateFlag(t *testing.T) {
|
|||
}
|
||||
for i, test := range tests {
|
||||
fs := pflag.NewFlagSet("testfeaturegateflag", pflag.ContinueOnError)
|
||||
f := DefaultFeatureGate
|
||||
f.known[testAlphaGate] = FeatureSpec{Default: false, PreRelease: Alpha}
|
||||
f.known[testBetaGate] = FeatureSpec{Default: false, PreRelease: Beta}
|
||||
f := NewFeatureGate()
|
||||
f.Add(map[Feature]FeatureSpec{
|
||||
testAlphaGate: {Default: false, PreRelease: Alpha},
|
||||
testBetaGate: {Default: false, PreRelease: Beta},
|
||||
})
|
||||
f.AddFlag(fs)
|
||||
|
||||
err := fs.Parse([]string{fmt.Sprintf("--%s=%s", flagName, test.arg)})
|
||||
|
@ -140,15 +142,45 @@ func TestFeatureGateFlag(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFeatureGateOverride(t *testing.T) {
|
||||
const testAlphaGate Feature = "TestAlpha"
|
||||
const testBetaGate Feature = "TestBeta"
|
||||
|
||||
// Don't parse the flag, assert defaults are used.
|
||||
var f FeatureGate = NewFeatureGate()
|
||||
f.Add(map[Feature]FeatureSpec{
|
||||
testAlphaGate: {Default: false, PreRelease: Alpha},
|
||||
testBetaGate: {Default: false, PreRelease: Beta},
|
||||
})
|
||||
|
||||
f.Set("TestAlpha=true,TestBeta=true")
|
||||
if f.Enabled(testAlphaGate) != true {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
if f.Enabled(testBetaGate) != true {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
|
||||
f.Set("TestAlpha=false")
|
||||
if f.Enabled(testAlphaGate) != false {
|
||||
t.Errorf("Expected false")
|
||||
}
|
||||
if f.Enabled(testBetaGate) != true {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeatureGateFlagDefaults(t *testing.T) {
|
||||
// gates for testing
|
||||
const testAlphaGate Feature = "TestAlpha"
|
||||
const testBetaGate Feature = "TestBeta"
|
||||
|
||||
// Don't parse the flag, assert defaults are used.
|
||||
f := DefaultFeatureGate
|
||||
f.known[testAlphaGate] = FeatureSpec{Default: false, PreRelease: Alpha}
|
||||
f.known[testBetaGate] = FeatureSpec{Default: true, PreRelease: Beta}
|
||||
var f FeatureGate = NewFeatureGate()
|
||||
f.Add(map[Feature]FeatureSpec{
|
||||
testAlphaGate: {Default: false, PreRelease: Alpha},
|
||||
testBetaGate: {Default: true, PreRelease: Beta},
|
||||
})
|
||||
|
||||
if f.Enabled(testAlphaGate) != false {
|
||||
t.Errorf("Expected false")
|
||||
|
|
Loading…
Reference in New Issue