forked from kubernetes/kops
-
Notifications
You must be signed in to change notification settings - Fork 0
/
featureflag.go
142 lines (113 loc) · 4.45 KB
/
featureflag.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
Copyright 2016 The Kubernetes 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 featureflag implements simple feature-flagging.
// Feature flags can become an anti-pattern if abused.
// We should try to use them for two use-cases:
// * `Preview` feature flags enable a piece of functionality we haven't yet fully baked. The user needs to 'opt-in'.
// We expect these flags to be removed at some time. Normally these will default to false.
// * Escape-hatch feature flags turn off a default that we consider risky (e.g. pre-creating DNS records).
// This lets us ship a behaviour, and if we encounter unusual circumstances in the field, we can
// allow the user to turn the behaviour off. Normally these will default to true.
package featureflag
import (
"os"
"strings"
"sync"
"github.com/golang/glog"
)
// Bool returns a pointer to the boolean value
func Bool(b bool) *bool {
return &b
}
// ExperimentalClusterDNS allows for setting the kubelet dns flag to experimental values.
// It allows for experiments with alternative DNS configurations - in particular local proxies.
var ExperimentalClusterDNS = New("ExperimentalClusterDNS", Bool(false))
// KeepLaunchConfigurations can be set to prevent garbage collection of old launch configurations
var KeepLaunchConfigurations = New("KeepLaunchConfigurations", Bool(false))
// DNSPreCreate controls whether we pre-create DNS records.
var DNSPreCreate = New("DNSPreCreate", Bool(true))
// DrainAndValidateRollingUpdate if set will use new rolling update code that will drain and validate.
var DrainAndValidateRollingUpdate = New("DrainAndValidateRollingUpdate", Bool(true))
// VPCSkipEnableDNSSupport if set will make that a VPC does not need DNSSupport enabled.
var VPCSkipEnableDNSSupport = New("VPCSkipEnableDNSSupport", Bool(false))
// SkipTerraformFormat if set will mean that we will not `tf fmt` the generated terraform.
var SkipTerraformFormat = New("SkipTerraformFormat", Bool(false))
var VSphereCloudProvider = New("VSphereCloudProvider", Bool(false))
var EnableExternalDNS = New("EnableExternalDNS", Bool(false))
//EnableExternalCloudController toggles the use of cloud-controller-manager introduced in v1.7
var EnableExternalCloudController = New("EnableExternalCloudController", Bool(false))
// EnableSeparateConfigBase allows a config-base that is different from the state store
var EnableSeparateConfigBase = New("EnableSeparateConfigBase", Bool(false))
// SpecOverrideFlag allows setting spec values on create
var SpecOverrideFlag = New("SpecOverrideFlag", Bool(false))
// GoogleCloudBucketAcl means the ACL will be set on a bucket when using GCS
// In particular, this is the only (?) way to grant the bucket.list permission
// However we should no longer need it, with the keyset.yaml fix
var GoogleCloudBucketAcl = New("GoogleCloudBucketAcl", Bool(false))
// EnableNodeAuthorization enables the node authorization features
var EnableNodeAuthorization = New("EnableNodeAuthorization", Bool(false))
var flags = make(map[string]*FeatureFlag)
var flagsMutex sync.Mutex
func init() {
ParseFlags(os.Getenv("KOPS_FEATURE_FLAGS"))
}
type FeatureFlag struct {
Key string
enabled *bool
defaultValue *bool
}
func (f *FeatureFlag) Enabled() bool {
if f.enabled != nil {
return *f.enabled
}
if f.defaultValue != nil {
return *f.defaultValue
}
return false
}
func ParseFlags(f string) {
f = strings.TrimSpace(f)
for _, s := range strings.Split(f, ",") {
s = strings.TrimSpace(s)
if s == "" {
continue
}
enabled := true
var ff *FeatureFlag
if s[0] == '+' || s[0] == '-' {
ff = New(s[1:], nil)
if s[0] == '-' {
enabled = false
}
} else {
ff = New(s, nil)
}
glog.Infof("FeatureFlag %q=%v", ff.Key, enabled)
ff.enabled = &enabled
}
}
func New(key string, defaultValue *bool) *FeatureFlag {
flagsMutex.Lock()
defer flagsMutex.Unlock()
f := flags[key]
if f == nil {
f = &FeatureFlag{
Key: key,
}
flags[key] = f
}
if f.defaultValue == nil {
f.defaultValue = defaultValue
}
return f
}