Skip to content

Commit 4fb36c9

Browse files
committed
featuregate: Add deprecated Stage and to/from versions
Fixes 2 out of the 3 tasks in #7043 Signed-off-by: Bogdan Drutu <[email protected]>
1 parent b2961b7 commit 4fb36c9

File tree

14 files changed

+121
-49
lines changed

14 files changed

+121
-49
lines changed

.chloggen/deprecateremoval.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: deprecation
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
5+
component: featuregate
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Deprecate Gate.RemovalVersion and WithRegisterRemovalVersion in favor of ToVersion.
9+
10+
# One or more tracking issues or pull requests related to the change
11+
issues: [7043]

.chloggen/featuregatetasks.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
5+
component: featuregate
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Add a new Deprecated stage for feature gates, when features are abandoned.
9+
10+
# One or more tracking issues or pull requests related to the change
11+
issues: [7043]

.chloggen/tofromversion.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
5+
component: featuregate
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Add concept of gate lifetime, [fromVersion, toVersion].
9+
10+
# One or more tracking issues or pull requests related to the change
11+
issues: [7043]

confmap/resolver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var (
5050
var _ = featuregate.GlobalRegistry().MustRegister(
5151
"confmap.expandEnabled",
5252
featuregate.StageStable,
53-
featuregate.WithRegisterRemovalVersion("v0.75.0"),
53+
featuregate.WithRegisterToVersion("v0.75.0"),
5454
featuregate.WithRegisterDescription("controls whether expanding embedded external config providers URIs"))
5555

5656
// Resolver resolves a configuration as a Conf.

featuregate/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ Once a `Gate` has been marked as `Stable`, it must have a `RemovalVersion` set.
1818
```go
1919
var myFeatureGate = featuregate.GlobalRegistry().MustRegister(
2020
"namespaced.uniqueIdentifier",
21-
featuregate.Stable,
21+
featuregate.Stable,
22+
featuregate.WithRegisterFromVersion("v0.65.0")
2223
featuregate.WithRegisterDescription("A brief description of what the gate controls"),
2324
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector/issues/6167"),
24-
featuregate.WithRegisterRemovalVersion("v0.70.0"))
25+
featuregate.WithRegisterToVersion("v0.70.0"))
2526
```
2627

2728
The status of the gate may later be checked by interrogating the global

featuregate/flag_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func TestNewFlag(t *testing.T) {
110110
reg := NewRegistry()
111111
reg.MustRegister("alpha", StageAlpha)
112112
reg.MustRegister("beta", StageBeta)
113-
reg.MustRegister("stable", StageStable, WithRegisterRemovalVersion("1.0.0"))
113+
reg.MustRegister("stable", StageStable, WithRegisterToVersion("1.0.0"))
114114
v := NewFlag(reg)
115115
if tt.expectedSetErr {
116116
require.Error(t, v.Set(tt.input))

featuregate/gate.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ import "sync/atomic"
1919
// Gate is an immutable object that is owned by the Registry and represents an individual feature that
2020
// may be enabled or disabled based on the lifecycle state of the feature and CLI flags specified by the user.
2121
type Gate struct {
22-
id string
23-
description string
24-
referenceURL string
25-
removalVersion string
26-
stage Stage
27-
enabled *atomic.Bool
22+
id string
23+
description string
24+
referenceURL string
25+
fromVersion string
26+
toVersion string
27+
stage Stage
28+
enabled *atomic.Bool
2829
}
2930

3031
// ID returns the id of the Gate.
@@ -52,7 +53,17 @@ func (g *Gate) ReferenceURL() string {
5253
return g.referenceURL
5354
}
5455

55-
// RemovalVersion returns the removal version information for Gate's in StageStable.
56+
// FromVersion returns the version information when the Gate's was added.
57+
func (g *Gate) FromVersion() string {
58+
return g.fromVersion
59+
}
60+
61+
// ToVersion returns the version information when Gate's in StageStable.
62+
func (g *Gate) ToVersion() string {
63+
return g.toVersion
64+
}
65+
66+
// Deprecated: [v0.76.0] use ToVersion().
5667
func (g *Gate) RemovalVersion() string {
57-
return g.removalVersion
68+
return g.ToVersion()
5869
}

featuregate/gate_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,20 @@ func TestGate(t *testing.T) {
2525
enabled := &atomic.Bool{}
2626
enabled.Store(true)
2727
g := &Gate{
28-
id: "test",
29-
description: "test gate",
30-
enabled: enabled,
31-
stage: StageAlpha,
32-
referenceURL: "http://example.com",
33-
removalVersion: "v0.64.0",
28+
id: "test",
29+
description: "test gate",
30+
enabled: enabled,
31+
stage: StageAlpha,
32+
referenceURL: "http://example.com",
33+
fromVersion: "v0.61.0",
34+
toVersion: "v0.64.0",
3435
}
3536

3637
assert.Equal(t, "test", g.ID())
3738
assert.Equal(t, "test gate", g.Description())
3839
assert.True(t, g.IsEnabled())
3940
assert.Equal(t, StageAlpha, g.Stage())
4041
assert.Equal(t, "http://example.com", g.ReferenceURL())
41-
assert.Equal(t, "v0.64.0", g.RemovalVersion())
42+
assert.Equal(t, "v0.61.0", g.FromVersion())
43+
assert.Equal(t, "v0.64.0", g.ToVersion())
4244
}

featuregate/registry.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,23 @@ func WithRegisterReferenceURL(url string) RegisterOption {
6262
})
6363
}
6464

65-
// WithRegisterRemovalVersion is used when the Gate is considered StageStable,
66-
// to inform users that referencing the gate is no longer needed.
67-
func WithRegisterRemovalVersion(version string) RegisterOption {
65+
// Deprecated: [v0.76.0] use WithRegisterToVersion.
66+
var WithRegisterRemovalVersion = WithRegisterToVersion
67+
68+
// WithRegisterFromVersion is used to set the Gate "FromVersion".
69+
// The "FromVersion" contains the Collector release when a feature is introduced.
70+
func WithRegisterFromVersion(fromVersion string) RegisterOption {
71+
return registerOptionFunc(func(g *Gate) {
72+
g.fromVersion = fromVersion
73+
})
74+
}
75+
76+
// WithRegisterToVersion is used to set the Gate "ToVersion".
77+
// The "ToVersion", if not empty, contains the last Collector release in which you can still use a feature gate.
78+
// If the feature stage is either "Deprecated" or "Stable", the "ToVersion" is the Collector release when the feature is removed.
79+
func WithRegisterToVersion(toVersion string) RegisterOption {
6880
return registerOptionFunc(func(g *Gate) {
69-
g.removalVersion = version
81+
g.toVersion = toVersion
7082
})
7183
}
7284

@@ -98,7 +110,7 @@ func (r *Registry) Register(id string, stage Stage, opts ...RegisterOption) (*Ga
98110
default:
99111
return nil, fmt.Errorf("unknown stage value %q for gate %q", stage, id)
100112
}
101-
if g.stage == StageStable && g.removalVersion == "" {
113+
if g.stage == StageStable && g.toVersion == "" {
102114
return nil, fmt.Errorf("no removal version set for stable gate %q", id)
103115
}
104116
if _, loaded := r.gates.LoadOrStore(id, g); loaded {

featuregate/registry_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func TestRegistryApplyError(t *testing.T) {
5555
assert.Error(t, r.Set("foo", true))
5656
r.MustRegister("bar", StageAlpha)
5757
assert.Error(t, r.Set("foo", true))
58-
r.MustRegister("foo", StageStable, WithRegisterRemovalVersion("next"))
58+
r.MustRegister("foo", StageStable, WithRegisterToVersion("next"))
5959
assert.Error(t, r.Set("foo", true))
6060
}
6161

@@ -90,7 +90,7 @@ func TestRegisterGateLifecycle(t *testing.T) {
9090
opts: []RegisterOption{
9191
WithRegisterDescription("test-gate"),
9292
WithRegisterReferenceURL("http://example.com/issue/1"),
93-
WithRegisterRemovalVersion(""),
93+
WithRegisterToVersion(""),
9494
},
9595
enabled: false,
9696
shouldErr: false,
@@ -107,7 +107,7 @@ func TestRegisterGateLifecycle(t *testing.T) {
107107
id: "test-gate",
108108
stage: StageStable,
109109
opts: []RegisterOption{
110-
WithRegisterRemovalVersion("next"),
110+
WithRegisterToVersion("next"),
111111
},
112112
enabled: true,
113113
shouldErr: false,

0 commit comments

Comments
 (0)