Skip to content

Commit 3b0f361

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

File tree

10 files changed

+85
-21
lines changed

10 files changed

+85
-21
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/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,

featuregate/stage.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,15 @@ const (
2929
// The Gate will be enabled by default.
3030
StageBeta
3131
// StageStable is used when feature is permanently enabled and can not be disabled by a Gate.
32-
// This value is used to provide feedback to the user that the gate will be removed in the next version.
32+
// This value is used to provide feedback to the user that the gate will be removed in the next versions.
3333
//
3434
// The Gate will be enabled by default and will return an error if modified.
3535
StageStable
36+
// StageDeprecated is used when feature is permanently disabled and can not be enabled by a Gate.
37+
// This value is used to provide feedback to the user that the gate will be removed in the next versions.
38+
//
39+
// The Gate will be disabled by default and will return an error if modified.
40+
StageDeprecated
3641
)
3742

3843
func (s Stage) String() string {
@@ -43,6 +48,8 @@ func (s Stage) String() string {
4348
return "Beta"
4449
case StageStable:
4550
return "Stable"
51+
case StageDeprecated:
52+
return "Deprecated"
4653
}
4754
return "Unknown"
4855
}

0 commit comments

Comments
 (0)