github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/feature/flags.go (about) 1 package feature 2 3 import ( 4 "fmt" 5 ) 6 7 // The status of a feature flag 8 // It starts as Active (we're using this flag to evaluate the feature) 9 // Then when we no longer need it, we make it a noop. Leave it for an upgrade cycle. 10 // Then move it to Obsolete, which will cause a warning. Leave it for an upgrade cycle. 11 // Then remove the flag altogether. 12 type Status int 13 14 const ( 15 Active Status = iota 16 Noop 17 Obsolete 18 // After Obsolete is Error, but it's not a value we can set 19 ) 20 21 const MultipleContainersPerPod = "multiple_containers_per_pod" 22 const Events = "events" 23 const Snapshots = "snapshots" 24 const UpdateHistory = "update_history" 25 const Facets = "facets" 26 const Labels = "labels" 27 const LiveUpdateV2 = "live_update_v2" 28 const DisableResources = "disable_resources" 29 const BulkDisableResources = "bulk_disable_resources" 30 const ClusterRefresh = "cluster_refresh" 31 const OfflineSnapshotCreation = "offline_snapshot_creation" 32 33 // The Value a flag can have. Status should never be changed. 34 type Value struct { 35 Enabled bool 36 Status Status 37 } 38 39 // Defaults is the initial values for a FeatureSet. 40 // Don't modify after initializing. 41 type Defaults map[string]Value 42 43 // MainDefaults is the defaults we use in Main 44 var MainDefaults = Defaults{ 45 MultipleContainersPerPod: Value{ 46 Enabled: true, 47 Status: Obsolete, 48 }, 49 Events: Value{ 50 Enabled: true, 51 Status: Obsolete, 52 }, 53 Snapshots: Value{ 54 Enabled: true, 55 // Snapshots FF is used by disable_snapshots() which hides the button 56 // in the web UI 57 Status: Active, 58 }, 59 UpdateHistory: Value{ 60 Enabled: false, 61 Status: Obsolete, 62 }, 63 Facets: Value{ 64 Enabled: true, 65 Status: Obsolete, 66 }, 67 Labels: Value{ 68 Enabled: true, 69 Status: Obsolete, 70 }, 71 LiveUpdateV2: Value{ 72 Enabled: true, 73 Status: Obsolete, 74 }, 75 DisableResources: Value{ 76 Enabled: true, 77 Status: Obsolete, 78 }, 79 BulkDisableResources: Value{ 80 Enabled: false, 81 Status: Obsolete, 82 }, 83 ClusterRefresh: Value{ 84 Enabled: false, 85 Status: Active, 86 }, 87 OfflineSnapshotCreation: Value{ 88 Enabled: true, 89 Status: Obsolete, 90 }, 91 } 92 93 // FeatureSet is a mutable set of Features. 94 type FeatureSet map[string]Value 95 96 // Create a FeatureSet from defaults. 97 func FromDefaults(d Defaults) FeatureSet { 98 r := make(FeatureSet) 99 for k, v := range d { 100 r[k] = v 101 } 102 return r 103 } 104 105 // ObsoleteError is an error that a feature flag is obsolete 106 type ObsoleteError string 107 108 func (s ObsoleteError) Error() string { 109 return string(s) 110 } 111 112 // Set sets enabled for a feature if it's active. Returns an error if flag is unknown or obsolete. 113 func (s FeatureSet) Set(name string, enabled bool) error { 114 v, ok := s[name] 115 if !ok { 116 return fmt.Errorf("Unknown feature flag: %s", name) 117 } 118 119 switch v.Status { 120 case Obsolete: 121 return ObsoleteError(fmt.Sprintf("Obsolete feature flag: %s", name)) 122 case Noop: 123 return nil 124 } 125 126 v.Enabled = enabled 127 s[name] = v 128 return nil 129 } 130 131 // Get gets whether a feature is enabled. 132 func (s FeatureSet) Get(name string) bool { 133 v, ok := s[name] 134 if !ok { 135 panic("get of unknown feature flag (code should use feature.Foo instead of \"foo\" to get a flag)") 136 } 137 return v.Enabled 138 } 139 140 // ToEnabled returns a copy of the enabled values of the FeatureSet 141 func (s FeatureSet) ToEnabled() map[string]bool { 142 r := make(map[string]bool) 143 for k, v := range s { 144 r[k] = v.Enabled 145 } 146 return r 147 }