Skip to content

Commit 3a11054

Browse files
committed
Move SCTP to GA
1 parent b2de4a6 commit 3a11054

File tree

25 files changed

+21
-601
lines changed

25 files changed

+21
-601
lines changed

pkg/apis/core/validation/conditional_validation.go

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ import (
3333
// is the cluster default, although the clusterIP here dictates the family defaulting.
3434
func ValidateConditionalService(service, oldService *api.Service, allowedIPFamilies []api.IPFamily) field.ErrorList {
3535
var errs field.ErrorList
36-
// If the SCTPSupport feature is disabled, and the old object isn't using the SCTP feature, prevent the new object from using it
37-
if !utilfeature.DefaultFeatureGate.Enabled(features.SCTPSupport) && len(serviceSCTPFields(oldService)) == 0 {
38-
for _, f := range serviceSCTPFields(service) {
39-
errs = append(errs, field.NotSupported(f, api.ProtocolSCTP, []string{string(api.ProtocolTCP), string(api.ProtocolUDP)}))
40-
}
41-
}
4236

4337
errs = append(errs, validateIPFamily(service, oldService, allowedIPFamilies)...)
4438

@@ -114,115 +108,3 @@ func joinIPFamilies(families []api.IPFamily, separator string) string {
114108
}
115109
return b.String()
116110
}
117-
118-
func serviceSCTPFields(service *api.Service) []*field.Path {
119-
if service == nil {
120-
return nil
121-
}
122-
fields := []*field.Path{}
123-
for pIndex, p := range service.Spec.Ports {
124-
if p.Protocol == api.ProtocolSCTP {
125-
fields = append(fields, field.NewPath("spec.ports").Index(pIndex).Child("protocol"))
126-
}
127-
}
128-
return fields
129-
}
130-
131-
// ValidateConditionalEndpoints validates conditionally valid fields.
132-
func ValidateConditionalEndpoints(endpoints, oldEndpoints *api.Endpoints) field.ErrorList {
133-
var errs field.ErrorList
134-
// If the SCTPSupport feature is disabled, and the old object isn't using the SCTP feature, prevent the new object from using it
135-
if !utilfeature.DefaultFeatureGate.Enabled(features.SCTPSupport) && len(endpointsSCTPFields(oldEndpoints)) == 0 {
136-
for _, f := range endpointsSCTPFields(endpoints) {
137-
errs = append(errs, field.NotSupported(f, api.ProtocolSCTP, []string{string(api.ProtocolTCP), string(api.ProtocolUDP)}))
138-
}
139-
}
140-
return errs
141-
}
142-
143-
func endpointsSCTPFields(endpoints *api.Endpoints) []*field.Path {
144-
if endpoints == nil {
145-
return nil
146-
}
147-
fields := []*field.Path{}
148-
for sIndex, s := range endpoints.Subsets {
149-
for pIndex, p := range s.Ports {
150-
if p.Protocol == api.ProtocolSCTP {
151-
fields = append(fields, field.NewPath("subsets").Index(sIndex).Child("ports").Index(pIndex).Child("protocol"))
152-
}
153-
}
154-
}
155-
return fields
156-
}
157-
158-
// ValidateConditionalPodTemplate validates conditionally valid fields.
159-
// This should be called from Validate/ValidateUpdate for all resources containing a PodTemplateSpec
160-
func ValidateConditionalPodTemplate(podTemplate, oldPodTemplate *api.PodTemplateSpec, fldPath *field.Path) field.ErrorList {
161-
var (
162-
podSpec *api.PodSpec
163-
oldPodSpec *api.PodSpec
164-
)
165-
if podTemplate != nil {
166-
podSpec = &podTemplate.Spec
167-
}
168-
if oldPodTemplate != nil {
169-
oldPodSpec = &oldPodTemplate.Spec
170-
}
171-
return validateConditionalPodSpec(podSpec, oldPodSpec, fldPath.Child("spec"))
172-
}
173-
174-
// ValidateConditionalPod validates conditionally valid fields.
175-
// This should be called from Validate/ValidateUpdate for all resources containing a Pod
176-
func ValidateConditionalPod(pod, oldPod *api.Pod, fldPath *field.Path) field.ErrorList {
177-
var (
178-
podSpec *api.PodSpec
179-
oldPodSpec *api.PodSpec
180-
)
181-
if pod != nil {
182-
podSpec = &pod.Spec
183-
}
184-
if oldPod != nil {
185-
oldPodSpec = &oldPod.Spec
186-
}
187-
return validateConditionalPodSpec(podSpec, oldPodSpec, fldPath.Child("spec"))
188-
}
189-
190-
func validateConditionalPodSpec(podSpec, oldPodSpec *api.PodSpec, fldPath *field.Path) field.ErrorList {
191-
// Always make sure we have a non-nil current pod spec
192-
if podSpec == nil {
193-
podSpec = &api.PodSpec{}
194-
}
195-
196-
errs := field.ErrorList{}
197-
198-
// If the SCTPSupport feature is disabled, and the old object isn't using the SCTP feature, prevent the new object from using it
199-
if !utilfeature.DefaultFeatureGate.Enabled(features.SCTPSupport) && len(podSCTPFields(oldPodSpec, nil)) == 0 {
200-
for _, f := range podSCTPFields(podSpec, fldPath) {
201-
errs = append(errs, field.NotSupported(f, api.ProtocolSCTP, []string{string(api.ProtocolTCP), string(api.ProtocolUDP)}))
202-
}
203-
}
204-
205-
return errs
206-
}
207-
208-
func podSCTPFields(podSpec *api.PodSpec, fldPath *field.Path) []*field.Path {
209-
if podSpec == nil {
210-
return nil
211-
}
212-
fields := []*field.Path{}
213-
for cIndex, c := range podSpec.InitContainers {
214-
for pIndex, p := range c.Ports {
215-
if p.Protocol == api.ProtocolSCTP {
216-
fields = append(fields, fldPath.Child("initContainers").Index(cIndex).Child("ports").Index(pIndex).Child("protocol"))
217-
}
218-
}
219-
}
220-
for cIndex, c := range podSpec.Containers {
221-
for pIndex, p := range c.Ports {
222-
if p.Protocol == api.ProtocolSCTP {
223-
fields = append(fields, fldPath.Child("containers").Index(cIndex).Child("ports").Index(pIndex).Child("protocol"))
224-
}
225-
}
226-
}
227-
return fields
228-
}

pkg/apis/core/validation/conditional_validation_test.go

Lines changed: 0 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package validation
1818

1919
import (
20-
"fmt"
2120
"reflect"
2221
"strings"
2322
"testing"
@@ -29,230 +28,6 @@ import (
2928
"k8s.io/kubernetes/pkg/features"
3029
)
3130

32-
func TestValidatePodSCTP(t *testing.T) {
33-
objectWithValue := func() *api.Pod {
34-
return &api.Pod{
35-
Spec: api.PodSpec{
36-
Containers: []api.Container{{Name: "container1", Image: "testimage", Ports: []api.ContainerPort{{ContainerPort: 80, Protocol: api.ProtocolSCTP}}}},
37-
InitContainers: []api.Container{{Name: "container2", Image: "testimage", Ports: []api.ContainerPort{{ContainerPort: 90, Protocol: api.ProtocolSCTP}}}},
38-
},
39-
}
40-
}
41-
objectWithoutValue := func() *api.Pod {
42-
return &api.Pod{
43-
Spec: api.PodSpec{
44-
Containers: []api.Container{{Name: "container1", Image: "testimage", Ports: []api.ContainerPort{{ContainerPort: 80, Protocol: api.ProtocolTCP}}}},
45-
InitContainers: []api.Container{{Name: "container2", Image: "testimage", Ports: []api.ContainerPort{{ContainerPort: 90, Protocol: api.ProtocolTCP}}}},
46-
},
47-
}
48-
}
49-
50-
objectInfo := []struct {
51-
description string
52-
hasValue bool
53-
object func() *api.Pod
54-
}{
55-
{
56-
description: "has value",
57-
hasValue: true,
58-
object: objectWithValue,
59-
},
60-
{
61-
description: "does not have value",
62-
hasValue: false,
63-
object: objectWithoutValue,
64-
},
65-
{
66-
description: "is nil",
67-
hasValue: false,
68-
object: func() *api.Pod { return nil },
69-
},
70-
}
71-
72-
for _, enabled := range []bool{true, false} {
73-
for _, oldPodInfo := range objectInfo {
74-
for _, newPodInfo := range objectInfo {
75-
oldPodHasValue, oldPod := oldPodInfo.hasValue, oldPodInfo.object()
76-
newPodHasValue, newPod := newPodInfo.hasValue, newPodInfo.object()
77-
if newPod == nil {
78-
continue
79-
}
80-
81-
t.Run(fmt.Sprintf("feature enabled=%v, old object %v, new object %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
82-
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SCTPSupport, enabled)()
83-
errs := ValidateConditionalPod(newPod, oldPod, nil)
84-
// objects should never be changed
85-
if !reflect.DeepEqual(oldPod, oldPodInfo.object()) {
86-
t.Errorf("old object changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.object()))
87-
}
88-
if !reflect.DeepEqual(newPod, newPodInfo.object()) {
89-
t.Errorf("new object changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.object()))
90-
}
91-
92-
switch {
93-
case enabled || oldPodHasValue || !newPodHasValue:
94-
if len(errs) > 0 {
95-
t.Errorf("unexpected errors: %v", errs)
96-
}
97-
default:
98-
if len(errs) != 2 {
99-
t.Errorf("expected 2 errors, got %v", errs)
100-
}
101-
}
102-
})
103-
}
104-
}
105-
}
106-
}
107-
108-
func TestValidateServiceSCTP(t *testing.T) {
109-
objectWithValue := func() *api.Service {
110-
return &api.Service{
111-
Spec: api.ServiceSpec{
112-
Ports: []api.ServicePort{{Protocol: api.ProtocolSCTP}},
113-
},
114-
}
115-
}
116-
objectWithoutValue := func() *api.Service {
117-
return &api.Service{
118-
Spec: api.ServiceSpec{
119-
Ports: []api.ServicePort{{Protocol: api.ProtocolTCP}},
120-
},
121-
}
122-
}
123-
124-
objectInfo := []struct {
125-
description string
126-
hasValue bool
127-
object func() *api.Service
128-
}{
129-
{
130-
description: "has value",
131-
hasValue: true,
132-
object: objectWithValue,
133-
},
134-
{
135-
description: "does not have value",
136-
hasValue: false,
137-
object: objectWithoutValue,
138-
},
139-
{
140-
description: "is nil",
141-
hasValue: false,
142-
object: func() *api.Service { return nil },
143-
},
144-
}
145-
146-
for _, enabled := range []bool{true, false} {
147-
for _, oldServiceInfo := range objectInfo {
148-
for _, newServiceInfo := range objectInfo {
149-
oldServiceHasValue, oldService := oldServiceInfo.hasValue, oldServiceInfo.object()
150-
newServiceHasValue, newService := newServiceInfo.hasValue, newServiceInfo.object()
151-
if newService == nil {
152-
continue
153-
}
154-
155-
t.Run(fmt.Sprintf("feature enabled=%v, old object %v, new object %v", enabled, oldServiceInfo.description, newServiceInfo.description), func(t *testing.T) {
156-
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SCTPSupport, enabled)()
157-
errs := ValidateConditionalService(newService, oldService, []api.IPFamily{api.IPv4Protocol})
158-
// objects should never be changed
159-
if !reflect.DeepEqual(oldService, oldServiceInfo.object()) {
160-
t.Errorf("old object changed: %v", diff.ObjectReflectDiff(oldService, oldServiceInfo.object()))
161-
}
162-
if !reflect.DeepEqual(newService, newServiceInfo.object()) {
163-
t.Errorf("new object changed: %v", diff.ObjectReflectDiff(newService, newServiceInfo.object()))
164-
}
165-
166-
switch {
167-
case enabled || oldServiceHasValue || !newServiceHasValue:
168-
if len(errs) > 0 {
169-
t.Errorf("unexpected errors: %v", errs)
170-
}
171-
default:
172-
if len(errs) != 1 {
173-
t.Errorf("expected 1 error, got %v", errs)
174-
}
175-
}
176-
})
177-
}
178-
}
179-
}
180-
}
181-
182-
func TestValidateEndpointsSCTP(t *testing.T) {
183-
objectWithValue := func() *api.Endpoints {
184-
return &api.Endpoints{
185-
Subsets: []api.EndpointSubset{
186-
{Ports: []api.EndpointPort{{Protocol: api.ProtocolSCTP}}},
187-
},
188-
}
189-
}
190-
objectWithoutValue := func() *api.Endpoints {
191-
return &api.Endpoints{
192-
Subsets: []api.EndpointSubset{
193-
{Ports: []api.EndpointPort{{Protocol: api.ProtocolTCP}}},
194-
},
195-
}
196-
}
197-
198-
objectInfo := []struct {
199-
description string
200-
hasValue bool
201-
object func() *api.Endpoints
202-
}{
203-
{
204-
description: "has value",
205-
hasValue: true,
206-
object: objectWithValue,
207-
},
208-
{
209-
description: "does not have value",
210-
hasValue: false,
211-
object: objectWithoutValue,
212-
},
213-
{
214-
description: "is nil",
215-
hasValue: false,
216-
object: func() *api.Endpoints { return nil },
217-
},
218-
}
219-
220-
for _, enabled := range []bool{true, false} {
221-
for _, oldEndpointsInfo := range objectInfo {
222-
for _, newEndpointsInfo := range objectInfo {
223-
oldEndpointsHasValue, oldEndpoints := oldEndpointsInfo.hasValue, oldEndpointsInfo.object()
224-
newEndpointsHasValue, newEndpoints := newEndpointsInfo.hasValue, newEndpointsInfo.object()
225-
if newEndpoints == nil {
226-
continue
227-
}
228-
229-
t.Run(fmt.Sprintf("feature enabled=%v, old object %v, new object %v", enabled, oldEndpointsInfo.description, newEndpointsInfo.description), func(t *testing.T) {
230-
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SCTPSupport, enabled)()
231-
errs := ValidateConditionalEndpoints(newEndpoints, oldEndpoints)
232-
// objects should never be changed
233-
if !reflect.DeepEqual(oldEndpoints, oldEndpointsInfo.object()) {
234-
t.Errorf("old object changed: %v", diff.ObjectReflectDiff(oldEndpoints, oldEndpointsInfo.object()))
235-
}
236-
if !reflect.DeepEqual(newEndpoints, newEndpointsInfo.object()) {
237-
t.Errorf("new object changed: %v", diff.ObjectReflectDiff(newEndpoints, newEndpointsInfo.object()))
238-
}
239-
240-
switch {
241-
case enabled || oldEndpointsHasValue || !newEndpointsHasValue:
242-
if len(errs) > 0 {
243-
t.Errorf("unexpected errors: %v", errs)
244-
}
245-
default:
246-
if len(errs) != 1 {
247-
t.Errorf("expected 1 error, got %v", errs)
248-
}
249-
}
250-
})
251-
}
252-
}
253-
}
254-
}
255-
25631
func TestValidateServiceIPFamily(t *testing.T) {
25732
ipv4 := api.IPv4Protocol
25833
ipv6 := api.IPv6Protocol

pkg/apis/core/validation/validation_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4410,12 +4410,11 @@ func TestValidateResourceQuotaWithAlphaLocalStorageCapacityIsolation(t *testing.
44104410
}
44114411

44124412
func TestValidatePorts(t *testing.T) {
4413-
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SCTPSupport, true)()
44144413
successCase := []core.ContainerPort{
44154414
{Name: "abc", ContainerPort: 80, HostPort: 80, Protocol: "TCP"},
44164415
{Name: "easy", ContainerPort: 82, Protocol: "TCP"},
44174416
{Name: "as", ContainerPort: 83, Protocol: "UDP"},
4418-
{Name: "do-re-me", ContainerPort: 84, Protocol: "UDP"},
4417+
{Name: "do-re-me", ContainerPort: 84, Protocol: "SCTP"},
44194418
{ContainerPort: 85, Protocol: "TCP"},
44204419
}
44214420
if errs := validateContainerPorts(successCase, field.NewPath("field")); len(errs) != 0 {
@@ -9894,7 +9893,6 @@ func TestValidatePodEphemeralContainersUpdate(t *testing.T) {
98949893
}
98959894

98969895
func TestValidateServiceCreate(t *testing.T) {
9897-
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SCTPSupport, true)()
98989896
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServiceTopology, true)()
98999897

99009898
testCases := []struct {

0 commit comments

Comments
 (0)