@@ -34,6 +34,12 @@ import (
34
34
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
35
35
)
36
36
37
+ // StatefulSetValidationOptions is a struct that can be passed to ValidateStatefulSetSpec to record the validate options
38
+ type StatefulSetValidationOptions struct {
39
+ // Allow invalid DNS1123 ServiceName
40
+ AllowInvalidServiceName bool
41
+ }
42
+
37
43
// ValidateStatefulSetName can be used to check whether the given StatefulSet name is valid.
38
44
// Prefix indicates this name will be used as part of generation, in which case
39
45
// trailing dashes are allowed.
@@ -89,7 +95,7 @@ func ValidatePersistentVolumeClaimRetentionPolicy(policy *apps.StatefulSetPersis
89
95
}
90
96
91
97
// ValidateStatefulSetSpec tests if required fields in the StatefulSet spec are set.
92
- func ValidateStatefulSetSpec (spec * apps.StatefulSetSpec , fldPath * field.Path , opts apivalidation.PodValidationOptions ) field.ErrorList {
98
+ func ValidateStatefulSetSpec (spec * apps.StatefulSetSpec , fldPath * field.Path , opts apivalidation.PodValidationOptions , setOpts StatefulSetValidationOptions ) field.ErrorList {
93
99
allErrs := field.ErrorList {}
94
100
95
101
switch spec .PodManagementPolicy {
@@ -134,6 +140,10 @@ func ValidateStatefulSetSpec(spec *apps.StatefulSetSpec, fldPath *field.Path, op
134
140
allErrs = append (allErrs , apivalidation .ValidateNonnegativeField (int64 (replicaStartOrdinal ), fldPath .Child ("ordinals.start" ))... )
135
141
}
136
142
143
+ if ! setOpts .AllowInvalidServiceName && len (spec .ServiceName ) > 0 {
144
+ allErrs = append (allErrs , apivalidation .ValidateDNS1123Label (spec .ServiceName , fldPath .Child ("serviceName" ))... )
145
+ }
146
+
137
147
if spec .Selector == nil {
138
148
allErrs = append (allErrs , field .Required (fldPath .Child ("selector" ), "" ))
139
149
} else {
@@ -164,7 +174,10 @@ func ValidateStatefulSetSpec(spec *apps.StatefulSetSpec, fldPath *field.Path, op
164
174
// ValidateStatefulSet validates a StatefulSet.
165
175
func ValidateStatefulSet (statefulSet * apps.StatefulSet , opts apivalidation.PodValidationOptions ) field.ErrorList {
166
176
allErrs := apivalidation .ValidateObjectMeta (& statefulSet .ObjectMeta , true , ValidateStatefulSetName , field .NewPath ("metadata" ))
167
- allErrs = append (allErrs , ValidateStatefulSetSpec (& statefulSet .Spec , field .NewPath ("spec" ), opts )... )
177
+ setOpts := StatefulSetValidationOptions {
178
+ AllowInvalidServiceName : false , // require valid serviceNames in new StatefulSets
179
+ }
180
+ allErrs = append (allErrs , ValidateStatefulSetSpec (& statefulSet .Spec , field .NewPath ("spec" ), opts , setOpts )... )
168
181
return allErrs
169
182
}
170
183
@@ -177,7 +190,10 @@ func ValidateStatefulSetUpdate(statefulSet, oldStatefulSet *apps.StatefulSet, op
177
190
// thing to do it delete such an instance, but if there is a finalizer, it
178
191
// would need to pass update validation. Name can't change anyway.
179
192
allErrs := apivalidation .ValidateObjectMetaUpdate (& statefulSet .ObjectMeta , & oldStatefulSet .ObjectMeta , field .NewPath ("metadata" ))
180
- allErrs = append (allErrs , ValidateStatefulSetSpec (& statefulSet .Spec , field .NewPath ("spec" ), opts )... )
193
+ setOpts := StatefulSetValidationOptions {
194
+ AllowInvalidServiceName : true , // serviceName is immutable, tolerate existing invalid names on update
195
+ }
196
+ allErrs = append (allErrs , ValidateStatefulSetSpec (& statefulSet .Spec , field .NewPath ("spec" ), opts , setOpts )... )
181
197
182
198
// statefulset updates aren't super common and general updates are likely to be touching spec, so we'll do this
183
199
// deep copy right away. This avoids mutating our inputs
0 commit comments