Skip to content

Commit 3798aa0

Browse files
committed
OTA-1010: pull GetImplicitlyEnabledCapabilities from the cvo repo
1 parent b9df8bb commit 3798aa0

File tree

2 files changed

+279
-0
lines changed

2 files changed

+279
-0
lines changed

pkg/capability/capability.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package capability
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/util/sets"
5+
6+
configv1 "github.com/openshift/api/config/v1"
7+
)
8+
9+
// ClusterCapabilities represents various types of ClusterVersionCapabilities
10+
type ClusterCapabilities struct {
11+
// Known is a set of all known ClusterVersionCapabilities. It may grow as OpenShift evolves.
12+
Known sets.Set[configv1.ClusterVersionCapability]
13+
// Enabled is a set of the ClusterVersionCapabilities that are enabled on a cluster.
14+
Enabled sets.Set[configv1.ClusterVersionCapability]
15+
// ImplicitlyEnabled is a set of the ClusterVersionCapabilities that are implicitly enabled on a cluster.
16+
// For example, "ImageRegistry" is a new ClusterVersionCapability in 4.14.
17+
// ImageRegistry becomes implicitly enabled on a 4.14 cluster upgraded from 4.13 with ImageRegistry running already.
18+
// https://docs.openshift.com/container-platform/4.17/installing/overview/cluster-capabilities.html
19+
ImplicitlyEnabled sets.Set[configv1.ClusterVersionCapability]
20+
}
21+
22+
// GetImplicitlyEnabledCapabilities returns the capabilities from
23+
// a set of capabilities that are not (even implicitly) enabled in ClusterCapabilities:
24+
func GetImplicitlyEnabledCapabilities(
25+
capabilities sets.Set[configv1.ClusterVersionCapability],
26+
enabledCapabilities sets.Set[configv1.ClusterVersionCapability],
27+
clusterCapabilities ClusterCapabilities,
28+
) sets.Set[configv1.ClusterVersionCapability] {
29+
if capabilities == nil {
30+
return nil
31+
}
32+
caps := capabilities.Difference(enabledCapabilities).Difference(clusterCapabilities.Enabled).Difference(clusterCapabilities.ImplicitlyEnabled)
33+
return caps
34+
}
35+
36+
// SetCapabilities populates a ClusterCapabilities object from ClusterVersion clusterCapabilities spec. This method also
37+
// ensures that each capability in others is still enabled: if not enabled then enabled implicitly.
38+
func SetCapabilities(config *configv1.ClusterVersion,
39+
others sets.Set[configv1.ClusterVersionCapability]) ClusterCapabilities {
40+
var capabilities ClusterCapabilities
41+
capabilities.Known = sets.New[configv1.ClusterVersionCapability]()
42+
for _, s := range configv1.ClusterVersionCapabilitySets {
43+
capabilities.Known.Insert(s...)
44+
}
45+
key := configv1.ClusterVersionCapabilitySetCurrent
46+
if config.Spec.Capabilities != nil && config.Spec.Capabilities.BaselineCapabilitySet != "" {
47+
key = config.Spec.Capabilities.BaselineCapabilitySet
48+
}
49+
capabilities.Enabled = sets.New[configv1.ClusterVersionCapability](configv1.ClusterVersionCapabilitySets[key]...)
50+
if config.Spec.Capabilities != nil {
51+
capabilities.Enabled.Insert(config.Spec.Capabilities.AdditionalEnabledCapabilities...)
52+
}
53+
capabilities.ImplicitlyEnabled = others.Difference(capabilities.Enabled)
54+
return capabilities
55+
}

pkg/capability/capability_test.go

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
package capability
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/util/sets"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
9+
configv1 "github.com/openshift/api/config/v1"
10+
)
11+
12+
func TestGetImplicitlyEnabledCapabilities(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
capabilities sets.Set[configv1.ClusterVersionCapability]
16+
enabledCaps sets.Set[configv1.ClusterVersionCapability]
17+
clusterCapabilities ClusterCapabilities
18+
expected sets.Set[configv1.ClusterVersionCapability]
19+
}{
20+
{name: "implicitly enable capability",
21+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap2"),
22+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1", "cap3"),
23+
clusterCapabilities: ClusterCapabilities{
24+
Enabled: sets.New[configv1.ClusterVersionCapability]("cap1"),
25+
},
26+
expected: sets.New[configv1.ClusterVersionCapability]("cap2"),
27+
},
28+
{name: "no prior caps, implicitly enabled capability",
29+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap2"),
30+
expected: sets.New[configv1.ClusterVersionCapability]("cap2"),
31+
},
32+
{name: "multiple implicitly enable capability",
33+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap4", "cap5", "cap6"),
34+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1", "cap2", "cap3"),
35+
expected: sets.New[configv1.ClusterVersionCapability]("cap4", "cap5", "cap6"),
36+
},
37+
{name: "no implicitly enable capability",
38+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1", "cap3"),
39+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap1"),
40+
clusterCapabilities: ClusterCapabilities{
41+
Enabled: sets.New[configv1.ClusterVersionCapability]("cap1"),
42+
},
43+
},
44+
{name: "prior cap, no updated caps, no implicitly enabled capability",
45+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1"),
46+
},
47+
{name: "no implicitly enable capability, already enabled",
48+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1", "cap2"),
49+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap2"),
50+
clusterCapabilities: ClusterCapabilities{
51+
Enabled: sets.New[configv1.ClusterVersionCapability]("cap1", "cap2"),
52+
},
53+
},
54+
{name: "no implicitly enable capability, new cap but already enabled",
55+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1"),
56+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap2"),
57+
clusterCapabilities: ClusterCapabilities{
58+
Enabled: sets.New[configv1.ClusterVersionCapability]("cap2"),
59+
},
60+
},
61+
{name: "no implicitly enable capability, already implicitly enabled",
62+
enabledCaps: sets.New[configv1.ClusterVersionCapability]("cap1"),
63+
capabilities: sets.New[configv1.ClusterVersionCapability]("cap2"),
64+
clusterCapabilities: ClusterCapabilities{
65+
Enabled: sets.New[configv1.ClusterVersionCapability]("cap2"),
66+
ImplicitlyEnabled: sets.New[configv1.ClusterVersionCapability]("cap2"),
67+
},
68+
},
69+
}
70+
for _, test := range tests {
71+
t.Run(test.name, func(t *testing.T) {
72+
caps := GetImplicitlyEnabledCapabilities(test.capabilities, test.enabledCaps, test.clusterCapabilities)
73+
if diff := cmp.Diff(test.expected, caps); diff != "" {
74+
t.Errorf("%s: Returned capacities differ from expected:\n%s", test.name, diff)
75+
}
76+
})
77+
}
78+
}
79+
80+
func TestSetCapabilities(t *testing.T) {
81+
tests := []struct {
82+
name string
83+
config *configv1.ClusterVersion
84+
others sets.Set[configv1.ClusterVersionCapability]
85+
expected ClusterCapabilities
86+
}{
87+
{name: "capabilities nil",
88+
config: &configv1.ClusterVersion{},
89+
expected: ClusterCapabilities{
90+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
91+
Enabled: sets.New[configv1.ClusterVersionCapability](configv1.ClusterVersionCapabilitySets[configv1.ClusterVersionCapabilitySetCurrent]...),
92+
},
93+
},
94+
{name: "capabilities set not set",
95+
config: &configv1.ClusterVersion{
96+
Spec: configv1.ClusterVersionSpec{
97+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{},
98+
},
99+
},
100+
expected: ClusterCapabilities{
101+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
102+
Enabled: sets.New[configv1.ClusterVersionCapability](configv1.ClusterVersionCapabilitySets[configv1.ClusterVersionCapabilitySetCurrent]...),
103+
},
104+
},
105+
{name: "set capabilities None",
106+
config: &configv1.ClusterVersion{
107+
Spec: configv1.ClusterVersionSpec{
108+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{
109+
BaselineCapabilitySet: configv1.ClusterVersionCapabilitySetNone,
110+
},
111+
},
112+
},
113+
expected: ClusterCapabilities{
114+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
115+
},
116+
},
117+
{name: "set capabilities 4_11",
118+
config: &configv1.ClusterVersion{
119+
Spec: configv1.ClusterVersionSpec{
120+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{
121+
BaselineCapabilitySet: configv1.ClusterVersionCapabilitySet4_11,
122+
AdditionalEnabledCapabilities: []configv1.ClusterVersionCapability{},
123+
},
124+
},
125+
},
126+
expected: ClusterCapabilities{
127+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
128+
Enabled: sets.New[configv1.ClusterVersionCapability](
129+
configv1.ClusterVersionCapabilityBaremetal,
130+
configv1.ClusterVersionCapabilityMarketplace,
131+
configv1.ClusterVersionCapabilityOpenShiftSamples,
132+
configv1.ClusterVersionCapabilityMachineAPI,
133+
),
134+
},
135+
},
136+
{name: "set capabilities vCurrent",
137+
config: &configv1.ClusterVersion{
138+
Spec: configv1.ClusterVersionSpec{
139+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{
140+
BaselineCapabilitySet: configv1.ClusterVersionCapabilitySetCurrent,
141+
AdditionalEnabledCapabilities: []configv1.ClusterVersionCapability{},
142+
},
143+
},
144+
},
145+
expected: ClusterCapabilities{
146+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
147+
Enabled: sets.New[configv1.ClusterVersionCapability](configv1.ClusterVersionCapabilitySets[configv1.ClusterVersionCapabilitySetCurrent]...),
148+
},
149+
},
150+
{name: "set capabilities None with additional",
151+
config: &configv1.ClusterVersion{
152+
Spec: configv1.ClusterVersionSpec{
153+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{
154+
BaselineCapabilitySet: configv1.ClusterVersionCapabilitySetNone,
155+
AdditionalEnabledCapabilities: []configv1.ClusterVersionCapability{"cap1", "cap2", "cap3"},
156+
},
157+
},
158+
},
159+
expected: ClusterCapabilities{
160+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
161+
Enabled: sets.New[configv1.ClusterVersionCapability]("cap1", "cap2", "cap3"),
162+
},
163+
},
164+
{name: "set capabilities 4_11 with additional",
165+
config: &configv1.ClusterVersion{
166+
Spec: configv1.ClusterVersionSpec{
167+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{
168+
BaselineCapabilitySet: configv1.ClusterVersionCapabilitySet4_11,
169+
AdditionalEnabledCapabilities: []configv1.ClusterVersionCapability{"cap1", "cap2", "cap3"},
170+
},
171+
},
172+
},
173+
expected: ClusterCapabilities{
174+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
175+
Enabled: sets.New[configv1.ClusterVersionCapability](
176+
configv1.ClusterVersionCapabilityBaremetal,
177+
configv1.ClusterVersionCapabilityMarketplace,
178+
configv1.ClusterVersionCapabilityOpenShiftSamples,
179+
configv1.ClusterVersionCapabilityMachineAPI,
180+
"cap1",
181+
"cap2",
182+
"cap3"),
183+
},
184+
},
185+
{name: "set capabilities 4_11 with additional and others",
186+
config: &configv1.ClusterVersion{
187+
Spec: configv1.ClusterVersionSpec{
188+
Capabilities: &configv1.ClusterVersionCapabilitiesSpec{
189+
BaselineCapabilitySet: configv1.ClusterVersionCapabilitySet4_11,
190+
AdditionalEnabledCapabilities: []configv1.ClusterVersionCapability{"cap1", "cap2", "cap3"},
191+
},
192+
},
193+
},
194+
others: sets.New[configv1.ClusterVersionCapability](
195+
configv1.ClusterVersionCapabilityMachineAPI,
196+
"cap1",
197+
"cap-implicitly",
198+
),
199+
expected: ClusterCapabilities{
200+
Known: sets.New[configv1.ClusterVersionCapability](configv1.KnownClusterVersionCapabilities...),
201+
Enabled: sets.New[configv1.ClusterVersionCapability](
202+
configv1.ClusterVersionCapabilityBaremetal,
203+
configv1.ClusterVersionCapabilityMarketplace,
204+
configv1.ClusterVersionCapabilityOpenShiftSamples,
205+
configv1.ClusterVersionCapabilityMachineAPI,
206+
"cap1",
207+
"cap2",
208+
"cap3"),
209+
ImplicitlyEnabled: sets.New[configv1.ClusterVersionCapability]("cap-implicitly"),
210+
},
211+
},
212+
}
213+
for _, test := range tests {
214+
if test.name != "set capabilities 4_11 with additional and others" {
215+
continue
216+
}
217+
t.Run(test.name, func(t *testing.T) {
218+
caps := SetCapabilities(test.config, test.others)
219+
if diff := cmp.Diff(test.expected, caps); diff != "" {
220+
t.Errorf("%s: Returned capacities differ from expected:\n%s", test.name, diff)
221+
}
222+
})
223+
}
224+
}

0 commit comments

Comments
 (0)