mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	StatefulSet validation needs to allow old names
A recent commit changed name validation from DNS Subdomain to DNS Label. The assumption was that a subdomain-named SS could never work and the only reasonable thing to do would be to delete it. But if there is a finalizer, the delete is not possible because we would reject the update because the old name (subdomain) did not pass the new validation. This commit does not re-validate the ObjectMeta on update. Probably every resource should follow this pattern, but mostly it's a non-issue becauase the above change (name validation) is not something we do - this case was excpetional.
This commit is contained in:
		@@ -173,10 +173,14 @@ func ValidateStatefulSet(statefulSet *apps.StatefulSet, opts apivalidation.PodVa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ValidateStatefulSetUpdate tests if required fields in the StatefulSet are set.
 | 
					// ValidateStatefulSetUpdate tests if required fields in the StatefulSet are set.
 | 
				
			||||||
func ValidateStatefulSetUpdate(statefulSet, oldStatefulSet *apps.StatefulSet, opts apivalidation.PodValidationOptions) field.ErrorList {
 | 
					func ValidateStatefulSetUpdate(statefulSet, oldStatefulSet *apps.StatefulSet, opts apivalidation.PodValidationOptions) field.ErrorList {
 | 
				
			||||||
	// first, validate that the new statefulset is valid
 | 
						// First, validate that the new statefulset is valid.  Don't call
 | 
				
			||||||
	allErrs := ValidateStatefulSet(statefulSet, opts)
 | 
						// ValidateStatefulSet() because we don't want to revalidate the name on
 | 
				
			||||||
 | 
						// update.  This is important here because we used to allow DNS subdomain
 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&statefulSet.ObjectMeta, &oldStatefulSet.ObjectMeta, field.NewPath("metadata"))...)
 | 
						// for name, but that can't actually create pods.  The only reasonable
 | 
				
			||||||
 | 
						// thing to do it delete such an instance, but if there is a finalizer, it
 | 
				
			||||||
 | 
						// would need to pass update validation.  Name can't change anyway.
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMetaUpdate(&statefulSet.ObjectMeta, &oldStatefulSet.ObjectMeta, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateStatefulSetSpec(&statefulSet.Spec, field.NewPath("spec"), opts)...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// statefulset updates aren't super common and general updates are likely to be touching spec, so we'll do this
 | 
						// statefulset updates aren't super common and general updates are likely to be touching spec, so we'll do this
 | 
				
			||||||
	// deep copy right away.  This avoids mutating our inputs
 | 
						// deep copy right away.  This avoids mutating our inputs
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1190,6 +1190,27 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "update existing instance with now-invalid name",
 | 
				
			||||||
 | 
								old: apps.StatefulSet{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{Name: "abc.123.example", Namespace: metav1.NamespaceDefault, Finalizers: []string{"final"}},
 | 
				
			||||||
 | 
									Spec: apps.StatefulSetSpec{
 | 
				
			||||||
 | 
										PodManagementPolicy: apps.OrderedReadyPodManagement,
 | 
				
			||||||
 | 
										Selector:            &metav1.LabelSelector{MatchLabels: validLabels},
 | 
				
			||||||
 | 
										Template:            validPodTemplate.Template,
 | 
				
			||||||
 | 
										UpdateStrategy:      apps.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								update: apps.StatefulSet{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{Name: "abc.123.example", Namespace: metav1.NamespaceDefault, Finalizers: []string{}},
 | 
				
			||||||
 | 
									Spec: apps.StatefulSetSpec{
 | 
				
			||||||
 | 
										PodManagementPolicy: apps.OrderedReadyPodManagement,
 | 
				
			||||||
 | 
										Selector:            &metav1.LabelSelector{MatchLabels: validLabels},
 | 
				
			||||||
 | 
										Template:            validPodTemplate.Template,
 | 
				
			||||||
 | 
										UpdateStrategy:      apps.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errorCases := []testCase{
 | 
						errorCases := []testCase{
 | 
				
			||||||
@@ -1417,7 +1438,11 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmpOpts := []cmp.Option{cmpopts.IgnoreFields(field.Error{}, "BadValue", "Detail"), cmpopts.SortSlices(func(a, b *field.Error) bool { return a.Error() < b.Error() })}
 | 
						cmpOpts := []cmp.Option{
 | 
				
			||||||
 | 
							cmpopts.IgnoreFields(field.Error{}, "BadValue", "Detail"),
 | 
				
			||||||
 | 
							cmpopts.SortSlices(func(a, b *field.Error) bool { return a.Error() < b.Error() }),
 | 
				
			||||||
 | 
							cmpopts.EquateEmpty(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for _, testCase := range append(successCases, errorCases...) {
 | 
						for _, testCase := range append(successCases, errorCases...) {
 | 
				
			||||||
		name := testCase.name
 | 
							name := testCase.name
 | 
				
			||||||
		var testTitle string
 | 
							var testTitle string
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user