-
Notifications
You must be signed in to change notification settings - Fork 1
/
registry.go
118 lines (103 loc) · 2.55 KB
/
registry.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
package feature
import (
"fmt"
"strconv"
"strings"
)
// Option is feature option.
type Option func(*Feature)
// WithFeatureStage with the feature stage.
func WithFeatureStage(stage Stage) Option {
return func(f *Feature) {
f.stage = stage
}
}
// WithFeatureDescription with the Feature description.
func WithFeatureDescription(description string) Option {
return func(f *Feature) {
f.description = description
}
}
// WithFeatureToVersion with the Feature to version.
func WithFeatureToVersion(version string) Option {
return func(f *Feature) {
f.toVersion = version
}
}
// WithFeatureFromVersion with the Feature to version.
func WithFeatureFromVersion(version string) Option {
return func(f *Feature) {
f.toVersion = version
}
}
// Registry is feature gates registry.
type Registry struct {
features map[string]*Feature
}
// NewRegistry new a feature registry.
func NewRegistry() *Registry {
return &Registry{
features: make(map[string]*Feature),
}
}
// Register register a feature gate.
func (r *Registry) Register(name string, enabled bool, opts ...Option) (*Feature, error) {
if _, ok := r.features[name]; ok {
return nil, fmt.Errorf("feature gate %s is registered", name)
}
feature := &Feature{name: name}
feature.enabled.Store(enabled)
for _, o := range opts {
o(feature)
}
r.features[feature.Name()] = feature
return feature, nil
}
// MustRegister must register a feature gate.
func (r *Registry) MustRegister(name string, enabled bool, opts ...Option) *Feature {
feature, err := r.Register(name, enabled, opts...)
if err != nil {
panic(err)
}
return feature
}
// Visit visits all the features.
func (r *Registry) Visit(f func(*Feature)) {
for _, feature := range r.features {
f(feature)
}
}
// SetEnabled set feature enabled.
func (r *Registry) SetEnabled(name string, enabled bool) error {
f, ok := r.features[name]
if !ok {
return fmt.Errorf("not found feature: %s", name)
}
f.enabled.Store(enabled)
return nil
}
// Set sets the feature arguments.
// eg: foo=true,bar=false
func (r *Registry) Set(args string) error {
fs := strings.Split(args, ",")
for _, s := range fs {
feature := strings.Split(s, "=")
name := feature[0]
enabled, err := strconv.ParseBool(feature[1])
if err != nil {
return err
}
if err := r.SetEnabled(name, enabled); err != nil {
return err
}
}
return nil
}
func (r *Registry) String() string {
pairs := []string{}
for name, feature := range r.features {
enabled := feature.enabled.Load()
pairs = append(pairs, fmt.Sprintf("%s=%t", name, enabled))
}
return strings.Join(pairs, ",")
}