Merge pull request #124210 from thockin/remove_gate_SkipReadOnlyValidationGCE
Remove the gate "SkipReadOnlyValidationGCE"
This commit is contained in:
		| @@ -280,7 +280,7 @@ func ValidateControllerRevisionUpdate(newHistory, oldHistory *apps.ControllerRev | |||||||
| // ValidateDaemonSet tests if required fields in the DaemonSet are set. | // ValidateDaemonSet tests if required fields in the DaemonSet are set. | ||||||
| func ValidateDaemonSet(ds *apps.DaemonSet, opts apivalidation.PodValidationOptions) field.ErrorList { | func ValidateDaemonSet(ds *apps.DaemonSet, opts apivalidation.PodValidationOptions) field.ErrorList { | ||||||
| 	allErrs := apivalidation.ValidateObjectMeta(&ds.ObjectMeta, true, ValidateDaemonSetName, field.NewPath("metadata")) | 	allErrs := apivalidation.ValidateObjectMeta(&ds.ObjectMeta, true, ValidateDaemonSetName, field.NewPath("metadata")) | ||||||
| 	allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, nil, field.NewPath("spec"), opts)...) | 	allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, field.NewPath("spec"), opts)...) | ||||||
| 	return allErrs | 	return allErrs | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -288,7 +288,7 @@ func ValidateDaemonSet(ds *apps.DaemonSet, opts apivalidation.PodValidationOptio | |||||||
| func ValidateDaemonSetUpdate(ds, oldDS *apps.DaemonSet, opts apivalidation.PodValidationOptions) field.ErrorList { | func ValidateDaemonSetUpdate(ds, oldDS *apps.DaemonSet, opts apivalidation.PodValidationOptions) field.ErrorList { | ||||||
| 	allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata")) | 	allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata")) | ||||||
| 	allErrs = append(allErrs, ValidateDaemonSetSpecUpdate(&ds.Spec, &oldDS.Spec, field.NewPath("spec"))...) | 	allErrs = append(allErrs, ValidateDaemonSetSpecUpdate(&ds.Spec, &oldDS.Spec, field.NewPath("spec"))...) | ||||||
| 	allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, &oldDS.Spec, field.NewPath("spec"), opts)...) | 	allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, field.NewPath("spec"), opts)...) | ||||||
| 	return allErrs | 	return allErrs | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -344,7 +344,7 @@ func ValidateDaemonSetStatusUpdate(ds, oldDS *apps.DaemonSet) field.ErrorList { | |||||||
| } | } | ||||||
|  |  | ||||||
| // ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set. | // ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set. | ||||||
| func ValidateDaemonSetSpec(spec, oldSpec *apps.DaemonSetSpec, fldPath *field.Path, opts apivalidation.PodValidationOptions) field.ErrorList { | func ValidateDaemonSetSpec(spec *apps.DaemonSetSpec, fldPath *field.Path, opts apivalidation.PodValidationOptions) field.ErrorList { | ||||||
| 	allErrs := field.ErrorList{} | 	allErrs := field.ErrorList{} | ||||||
| 	labelSelectorValidationOpts := unversionedvalidation.LabelSelectorValidationOptions{AllowInvalidLabelValueInSelector: opts.AllowInvalidLabelValueInSelector} | 	labelSelectorValidationOpts := unversionedvalidation.LabelSelectorValidationOptions{AllowInvalidLabelValueInSelector: opts.AllowInvalidLabelValueInSelector} | ||||||
|  |  | ||||||
| @@ -359,12 +359,6 @@ func ValidateDaemonSetSpec(spec, oldSpec *apps.DaemonSetSpec, fldPath *field.Pat | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"), opts)...) | 	allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"), opts)...) | ||||||
| 	// get rid of apivalidation.ValidateReadOnlyPersistentDisks,stop passing oldSpec to this function |  | ||||||
| 	var oldVols []api.Volume |  | ||||||
| 	if oldSpec != nil { |  | ||||||
| 		oldVols = oldSpec.Template.Spec.Volumes // +k8s:verify-mutation:reason=clone |  | ||||||
| 	} |  | ||||||
| 	allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes, oldVols, fldPath.Child("template", "spec", "volumes"))...) |  | ||||||
| 	// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). | 	// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). | ||||||
| 	if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { | 	if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { | ||||||
| 		allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) | 		allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) | ||||||
| @@ -566,12 +560,7 @@ func ValidateDeploymentSpec(spec, oldSpec *apps.DeploymentSpec, fldPath *field.P | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector")) | 		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector")) | ||||||
| 	} else { | 	} else { | ||||||
| 		// oldSpec is not empty, pass oldSpec.template | 		allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"), opts)...) | ||||||
| 		var oldTemplate *api.PodTemplateSpec |  | ||||||
| 		if oldSpec != nil { |  | ||||||
| 			oldTemplate = &oldSpec.Template // +k8s:verify-mutation:reason=clone |  | ||||||
| 		} |  | ||||||
| 		allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, oldTemplate, selector, spec.Replicas, fldPath.Child("template"), opts)...) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	allErrs = append(allErrs, ValidateDeploymentStrategy(&spec.Strategy, fldPath.Child("strategy"))...) | 	allErrs = append(allErrs, ValidateDeploymentStrategy(&spec.Strategy, fldPath.Child("strategy"))...) | ||||||
| @@ -734,18 +723,13 @@ func ValidateReplicaSetSpec(spec, oldSpec *apps.ReplicaSetSpec, fldPath *field.P | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector")) | 		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector")) | ||||||
| 	} else { | 	} else { | ||||||
| 		// oldSpec is not empty, pass oldSpec.template. | 		allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"), opts)...) | ||||||
| 		var oldTemplate *api.PodTemplateSpec |  | ||||||
| 		if oldSpec != nil { |  | ||||||
| 			oldTemplate = &oldSpec.Template // +k8s:verify-mutation:reason=clone |  | ||||||
| 		} |  | ||||||
| 		allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, oldTemplate, selector, spec.Replicas, fldPath.Child("template"), opts)...) |  | ||||||
| 	} | 	} | ||||||
| 	return allErrs | 	return allErrs | ||||||
| } | } | ||||||
|  |  | ||||||
| // ValidatePodTemplateSpecForReplicaSet validates the given template and ensures that it is in accordance with the desired selector and replicas. | // ValidatePodTemplateSpecForReplicaSet validates the given template and ensures that it is in accordance with the desired selector and replicas. | ||||||
| func ValidatePodTemplateSpecForReplicaSet(template, oldTemplate *api.PodTemplateSpec, selector labels.Selector, replicas int32, fldPath *field.Path, opts apivalidation.PodValidationOptions) field.ErrorList { | func ValidatePodTemplateSpecForReplicaSet(template *api.PodTemplateSpec, selector labels.Selector, replicas int32, fldPath *field.Path, opts apivalidation.PodValidationOptions) field.ErrorList { | ||||||
| 	allErrs := field.ErrorList{} | 	allErrs := field.ErrorList{} | ||||||
| 	if template == nil { | 	if template == nil { | ||||||
| 		allErrs = append(allErrs, field.Required(fldPath, "")) | 		allErrs = append(allErrs, field.Required(fldPath, "")) | ||||||
| @@ -758,15 +742,6 @@ func ValidatePodTemplateSpecForReplicaSet(template, oldTemplate *api.PodTemplate | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(template, fldPath, opts)...) | 		allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(template, fldPath, opts)...) | ||||||
| 		// Daemons run on more than one node, Cancel verification of read and write volumes. |  | ||||||
| 		// get rid of apivalidation.ValidateReadOnlyPersistentDisks,stop passing oldTemplate to this function |  | ||||||
| 		var oldVols []api.Volume |  | ||||||
| 		if oldTemplate != nil { |  | ||||||
| 			oldVols = oldTemplate.Spec.Volumes // +k8s:verify-mutation:reason=clone |  | ||||||
| 		} |  | ||||||
| 		if replicas > 1 { |  | ||||||
| 			allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(template.Spec.Volumes, oldVols, fldPath.Child("spec", "volumes"))...) |  | ||||||
| 		} |  | ||||||
| 		// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). | 		// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). | ||||||
| 		if template.Spec.RestartPolicy != api.RestartPolicyAlways { | 		if template.Spec.RestartPolicy != api.RestartPolicyAlways { | ||||||
| 			allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "restartPolicy"), template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) | 			allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "restartPolicy"), template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) | ||||||
|   | |||||||
| @@ -1575,7 +1575,6 @@ func TestValidateDaemonSetUpdate(t *testing.T) { | |||||||
| 		old            apps.DaemonSet | 		old            apps.DaemonSet | ||||||
| 		update         apps.DaemonSet | 		update         apps.DaemonSet | ||||||
| 		expectedErrNum int | 		expectedErrNum int | ||||||
| 		enableSkipReadOnlyValidationGCE bool |  | ||||||
| 	} | 	} | ||||||
| 	successCases := map[string]dsUpdateTest{ | 	successCases := map[string]dsUpdateTest{ | ||||||
| 		"no change": { | 		"no change": { | ||||||
| @@ -1729,7 +1728,6 @@ func TestValidateDaemonSetUpdate(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		"Read-write volume verification": { | 		"Read-write volume verification": { | ||||||
| 			enableSkipReadOnlyValidationGCE: true, |  | ||||||
| 			old: apps.DaemonSet{ | 			old: apps.DaemonSet{ | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | ||||||
| 				Spec: apps.DaemonSetSpec{ | 				Spec: apps.DaemonSetSpec{ | ||||||
| @@ -1756,7 +1754,6 @@ func TestValidateDaemonSetUpdate(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	for testName, successCase := range successCases { | 	for testName, successCase := range successCases { | ||||||
| 		t.Run(testName, func(t *testing.T) { | 		t.Run(testName, func(t *testing.T) { | ||||||
| 			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, successCase.enableSkipReadOnlyValidationGCE)() |  | ||||||
| 			// ResourceVersion is required for updates. | 			// ResourceVersion is required for updates. | ||||||
| 			successCase.old.ObjectMeta.ResourceVersion = "1" | 			successCase.old.ObjectMeta.ResourceVersion = "1" | ||||||
| 			successCase.update.ObjectMeta.ResourceVersion = "2" | 			successCase.update.ObjectMeta.ResourceVersion = "2" | ||||||
| @@ -1848,32 +1845,6 @@ func TestValidateDaemonSetUpdate(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 			expectedErrNum: 1, | 			expectedErrNum: 1, | ||||||
| 		}, | 		}, | ||||||
| 		"invalid read-write volume": { |  | ||||||
| 			enableSkipReadOnlyValidationGCE: false, |  | ||||||
| 			old: apps.DaemonSet{ |  | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, |  | ||||||
| 				Spec: apps.DaemonSetSpec{ |  | ||||||
| 					Selector:           &metav1.LabelSelector{MatchLabels: validSelector}, |  | ||||||
| 					TemplateGeneration: 1, |  | ||||||
| 					Template:           validPodTemplateAbc.Template, |  | ||||||
| 					UpdateStrategy: apps.DaemonSetUpdateStrategy{ |  | ||||||
| 						Type: apps.OnDeleteDaemonSetStrategyType, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			update: apps.DaemonSet{ |  | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, |  | ||||||
| 				Spec: apps.DaemonSetSpec{ |  | ||||||
| 					Selector:           &metav1.LabelSelector{MatchLabels: validSelector}, |  | ||||||
| 					TemplateGeneration: 2, |  | ||||||
| 					Template:           readWriteVolumePodTemplate.Template, |  | ||||||
| 					UpdateStrategy: apps.DaemonSetUpdateStrategy{ |  | ||||||
| 						Type: apps.OnDeleteDaemonSetStrategyType, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			expectedErrNum: 1, |  | ||||||
| 		}, |  | ||||||
| 		"invalid update strategy": { | 		"invalid update strategy": { | ||||||
| 			old: apps.DaemonSet{ | 			old: apps.DaemonSet{ | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | ||||||
| @@ -1977,7 +1948,6 @@ func TestValidateDaemonSetUpdate(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	for testName, errorCase := range errorCases { | 	for testName, errorCase := range errorCases { | ||||||
| 		t.Run(testName, func(t *testing.T) { | 		t.Run(testName, func(t *testing.T) { | ||||||
| 			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, errorCase.enableSkipReadOnlyValidationGCE)() |  | ||||||
| 			// ResourceVersion is required for updates. | 			// ResourceVersion is required for updates. | ||||||
| 			errorCase.old.ObjectMeta.ResourceVersion = "1" | 			errorCase.old.ObjectMeta.ResourceVersion = "1" | ||||||
| 			errorCase.update.ObjectMeta.ResourceVersion = "2" | 			errorCase.update.ObjectMeta.ResourceVersion = "2" | ||||||
| @@ -2648,7 +2618,6 @@ func TestValidateDeploymentUpdate(t *testing.T) { | |||||||
| 		old            apps.Deployment | 		old            apps.Deployment | ||||||
| 		update         apps.Deployment | 		update         apps.Deployment | ||||||
| 		expectedErrNum int | 		expectedErrNum int | ||||||
| 		enableSkipReadOnlyValidationGCE bool |  | ||||||
| 	} | 	} | ||||||
| 	successCases := map[string]depUpdateTest{ | 	successCases := map[string]depUpdateTest{ | ||||||
| 		"positive replicas": { | 		"positive replicas": { | ||||||
| @@ -2671,7 +2640,6 @@ func TestValidateDeploymentUpdate(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		"Read-write volume verification": { | 		"Read-write volume verification": { | ||||||
| 			enableSkipReadOnlyValidationGCE: true, |  | ||||||
| 			old: apps.Deployment{ | 			old: apps.Deployment{ | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | ||||||
| 				Spec: apps.DeploymentSpec{ | 				Spec: apps.DeploymentSpec{ | ||||||
| @@ -2693,7 +2661,6 @@ func TestValidateDeploymentUpdate(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	for testName, successCase := range successCases { | 	for testName, successCase := range successCases { | ||||||
| 		t.Run(testName, func(t *testing.T) { | 		t.Run(testName, func(t *testing.T) { | ||||||
| 			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, successCase.enableSkipReadOnlyValidationGCE)() |  | ||||||
| 			// ResourceVersion is required for updates. | 			// ResourceVersion is required for updates. | ||||||
| 			successCase.old.ObjectMeta.ResourceVersion = "1" | 			successCase.old.ObjectMeta.ResourceVersion = "1" | ||||||
| 			successCase.update.ObjectMeta.ResourceVersion = "2" | 			successCase.update.ObjectMeta.ResourceVersion = "2" | ||||||
| @@ -2710,26 +2677,6 @@ func TestValidateDeploymentUpdate(t *testing.T) { | |||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| 		errorCases := map[string]depUpdateTest{ | 		errorCases := map[string]depUpdateTest{ | ||||||
| 			"more than one read/write": { |  | ||||||
| 				old: apps.Deployment{ |  | ||||||
| 					ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, |  | ||||||
| 					Spec: apps.DeploymentSpec{ |  | ||||||
| 						Selector: &metav1.LabelSelector{MatchLabels: validLabels}, |  | ||||||
| 						Template: validPodTemplate.Template, |  | ||||||
| 						Strategy: apps.DeploymentStrategy{Type: apps.RecreateDeploymentStrategyType}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 				update: apps.Deployment{ |  | ||||||
| 					ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, |  | ||||||
| 					Spec: apps.DeploymentSpec{ |  | ||||||
| 						Replicas: 2, |  | ||||||
| 						Selector: &metav1.LabelSelector{MatchLabels: validLabels}, |  | ||||||
| 						Template: readWriteVolumePodTemplate.Template, |  | ||||||
| 						Strategy: apps.DeploymentStrategy{Type: apps.RecreateDeploymentStrategyType}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 				expectedErrNum: 2, |  | ||||||
| 			}, |  | ||||||
| 			"invalid selector": { | 			"invalid selector": { | ||||||
| 				old: apps.Deployment{ | 				old: apps.Deployment{ | ||||||
| 					ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, | 					ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, | ||||||
| @@ -2793,7 +2740,6 @@ func TestValidateDeploymentUpdate(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 		for testName, errorCase := range errorCases { | 		for testName, errorCase := range errorCases { | ||||||
| 			t.Run(testName, func(t *testing.T) { | 			t.Run(testName, func(t *testing.T) { | ||||||
| 				defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, errorCase.enableSkipReadOnlyValidationGCE)() |  | ||||||
| 				// ResourceVersion is required for updates. | 				// ResourceVersion is required for updates. | ||||||
| 				errorCase.old.ObjectMeta.ResourceVersion = "1" | 				errorCase.old.ObjectMeta.ResourceVersion = "1" | ||||||
| 				errorCase.update.ObjectMeta.ResourceVersion = "2" | 				errorCase.update.ObjectMeta.ResourceVersion = "2" | ||||||
| @@ -3077,7 +3023,6 @@ func TestValidateReplicaSetUpdate(t *testing.T) { | |||||||
| 		old            apps.ReplicaSet | 		old            apps.ReplicaSet | ||||||
| 		update         apps.ReplicaSet | 		update         apps.ReplicaSet | ||||||
| 		expectedErrNum int | 		expectedErrNum int | ||||||
| 		enableSkipReadOnlyValidationGCE bool |  | ||||||
| 	} | 	} | ||||||
| 	successCases := map[string]rcUpdateTest{ | 	successCases := map[string]rcUpdateTest{ | ||||||
| 		"positive replicas": { | 		"positive replicas": { | ||||||
| @@ -3098,7 +3043,6 @@ func TestValidateReplicaSetUpdate(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		"Read-write volume verification": { | 		"Read-write volume verification": { | ||||||
| 			enableSkipReadOnlyValidationGCE: true, |  | ||||||
| 			old: apps.ReplicaSet{ | 			old: apps.ReplicaSet{ | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, | ||||||
| 				Spec: apps.ReplicaSetSpec{ | 				Spec: apps.ReplicaSetSpec{ | ||||||
| @@ -3118,7 +3062,6 @@ func TestValidateReplicaSetUpdate(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	for testName, successCase := range successCases { | 	for testName, successCase := range successCases { | ||||||
| 		t.Run(testName, func(t *testing.T) { | 		t.Run(testName, func(t *testing.T) { | ||||||
| 			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, successCase.enableSkipReadOnlyValidationGCE)() |  | ||||||
| 			// ResourceVersion is required for updates. | 			// ResourceVersion is required for updates. | ||||||
| 			successCase.old.ObjectMeta.ResourceVersion = "1" | 			successCase.old.ObjectMeta.ResourceVersion = "1" | ||||||
| 			successCase.update.ObjectMeta.ResourceVersion = "2" | 			successCase.update.ObjectMeta.ResourceVersion = "2" | ||||||
| @@ -3136,24 +3079,6 @@ func TestValidateReplicaSetUpdate(t *testing.T) { | |||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 	errorCases := map[string]rcUpdateTest{ | 	errorCases := map[string]rcUpdateTest{ | ||||||
| 		"more than one read/write": { |  | ||||||
| 			old: apps.ReplicaSet{ |  | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, |  | ||||||
| 				Spec: apps.ReplicaSetSpec{ |  | ||||||
| 					Selector: &metav1.LabelSelector{MatchLabels: validLabels}, |  | ||||||
| 					Template: validPodTemplate.Template, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			update: apps.ReplicaSet{ |  | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, |  | ||||||
| 				Spec: apps.ReplicaSetSpec{ |  | ||||||
| 					Replicas: 2, |  | ||||||
| 					Selector: &metav1.LabelSelector{MatchLabels: validLabels}, |  | ||||||
| 					Template: readWriteVolumePodTemplate.Template, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			expectedErrNum: 2, |  | ||||||
| 		}, |  | ||||||
| 		"invalid selector": { | 		"invalid selector": { | ||||||
| 			old: apps.ReplicaSet{ | 			old: apps.ReplicaSet{ | ||||||
| 				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, | 				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault}, | ||||||
| @@ -3211,7 +3136,6 @@ func TestValidateReplicaSetUpdate(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	for testName, errorCase := range errorCases { | 	for testName, errorCase := range errorCases { | ||||||
| 		t.Run(testName, func(t *testing.T) { | 		t.Run(testName, func(t *testing.T) { | ||||||
| 			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, errorCase.enableSkipReadOnlyValidationGCE)() |  | ||||||
| 			// ResourceVersion is required for updates. | 			// ResourceVersion is required for updates. | ||||||
| 			errorCase.old.ObjectMeta.ResourceVersion = "1" | 			errorCase.old.ObjectMeta.ResourceVersion = "1" | ||||||
| 			errorCase.update.ObjectMeta.ResourceVersion = "2" | 			errorCase.update.ObjectMeta.ResourceVersion = "2" | ||||||
|   | |||||||
| @@ -5910,7 +5910,7 @@ func ValidateNonEmptySelector(selectorMap map[string]string, fldPath *field.Path | |||||||
| } | } | ||||||
|  |  | ||||||
| // Validates the given template and ensures that it is in accordance with the desired selector and replicas. | // Validates the given template and ensures that it is in accordance with the desired selector and replicas. | ||||||
| func ValidatePodTemplateSpecForRC(template, oldTemplate *core.PodTemplateSpec, selectorMap map[string]string, replicas int32, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { | func ValidatePodTemplateSpecForRC(template *core.PodTemplateSpec, selectorMap map[string]string, replicas int32, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { | ||||||
| 	allErrs := field.ErrorList{} | 	allErrs := field.ErrorList{} | ||||||
| 	if template == nil { | 	if template == nil { | ||||||
| 		allErrs = append(allErrs, field.Required(fldPath, "")) | 		allErrs = append(allErrs, field.Required(fldPath, "")) | ||||||
| @@ -5924,14 +5924,6 @@ func ValidatePodTemplateSpecForRC(template, oldTemplate *core.PodTemplateSpec, s | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		allErrs = append(allErrs, ValidatePodTemplateSpec(template, fldPath, opts)...) | 		allErrs = append(allErrs, ValidatePodTemplateSpec(template, fldPath, opts)...) | ||||||
| 		// get rid of apivalidation.ValidateReadOnlyPersistentDisks,stop passing oldTemplate to this function |  | ||||||
| 		var oldVols []core.Volume |  | ||||||
| 		if oldTemplate != nil { |  | ||||||
| 			oldVols = oldTemplate.Spec.Volumes // +k8s:verify-mutation:reason=clone |  | ||||||
| 		} |  | ||||||
| 		if replicas > 1 { |  | ||||||
| 			allErrs = append(allErrs, ValidateReadOnlyPersistentDisks(template.Spec.Volumes, oldVols, fldPath.Child("spec", "volumes"))...) |  | ||||||
| 		} |  | ||||||
| 		// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). | 		// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). | ||||||
| 		if template.Spec.RestartPolicy != core.RestartPolicyAlways { | 		if template.Spec.RestartPolicy != core.RestartPolicyAlways { | ||||||
| 			allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "restartPolicy"), template.Spec.RestartPolicy, []core.RestartPolicy{core.RestartPolicyAlways})) | 			allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "restartPolicy"), template.Spec.RestartPolicy, []core.RestartPolicy{core.RestartPolicyAlways})) | ||||||
| @@ -5949,12 +5941,7 @@ func ValidateReplicationControllerSpec(spec, oldSpec *core.ReplicationController | |||||||
| 	allErrs = append(allErrs, ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...) | 	allErrs = append(allErrs, ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...) | ||||||
| 	allErrs = append(allErrs, ValidateNonEmptySelector(spec.Selector, fldPath.Child("selector"))...) | 	allErrs = append(allErrs, ValidateNonEmptySelector(spec.Selector, fldPath.Child("selector"))...) | ||||||
| 	allErrs = append(allErrs, ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...) | 	allErrs = append(allErrs, ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...) | ||||||
| 	// oldSpec is not empty, pass oldSpec.template. | 	allErrs = append(allErrs, ValidatePodTemplateSpecForRC(spec.Template, spec.Selector, spec.Replicas, fldPath.Child("template"), opts)...) | ||||||
| 	var oldTemplate *core.PodTemplateSpec |  | ||||||
| 	if oldSpec != nil { |  | ||||||
| 		oldTemplate = oldSpec.Template // +k8s:verify-mutation:reason=clone |  | ||||||
| 	} |  | ||||||
| 	allErrs = append(allErrs, ValidatePodTemplateSpecForRC(spec.Template, oldTemplate, spec.Selector, spec.Replicas, fldPath.Child("template"), opts)...) |  | ||||||
| 	return allErrs | 	return allErrs | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -5975,33 +5962,6 @@ func ValidatePodTemplateSpec(spec *core.PodTemplateSpec, fldPath *field.Path, op | |||||||
| 	return allErrs | 	return allErrs | ||||||
| } | } | ||||||
|  |  | ||||||
| // ValidateReadOnlyPersistentDisks stick this AFTER the short-circuit checks |  | ||||||
| func ValidateReadOnlyPersistentDisks(volumes, oldVolumes []core.Volume, fldPath *field.Path) field.ErrorList { |  | ||||||
| 	allErrs := field.ErrorList{} |  | ||||||
|  |  | ||||||
| 	if utilfeature.DefaultFeatureGate.Enabled(features.SkipReadOnlyValidationGCE) { |  | ||||||
| 		return field.ErrorList{} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	isWriteablePD := func(vol *core.Volume) bool { |  | ||||||
| 		return vol.GCEPersistentDisk != nil && !vol.GCEPersistentDisk.ReadOnly |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for i := range oldVolumes { |  | ||||||
| 		if isWriteablePD(&oldVolumes[i]) { |  | ||||||
| 			return field.ErrorList{} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for i := range volumes { |  | ||||||
| 		idxPath := fldPath.Index(i) |  | ||||||
| 		if isWriteablePD(&volumes[i]) { |  | ||||||
| 			allErrs = append(allErrs, field.Invalid(idxPath.Child("gcePersistentDisk", "readOnly"), false, "must be true for replicated pods > 1; GCE PD can only be mounted on multiple machines if it is read-only")) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return allErrs |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ValidateTaintsInNodeAnnotations tests that the serialized taints in Node.Annotations has valid data | // ValidateTaintsInNodeAnnotations tests that the serialized taints in Node.Annotations has valid data | ||||||
| func ValidateTaintsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { | func ValidateTaintsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { | ||||||
| 	allErrs := field.ErrorList{} | 	allErrs := field.ErrorList{} | ||||||
|   | |||||||
| @@ -5400,99 +5400,6 @@ func TestValidateVolumes(t *testing.T) { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestValidateReadOnlyPersistentDisks(t *testing.T) { |  | ||||||
| 	cases := []struct { |  | ||||||
| 		name        string |  | ||||||
| 		volumes     []core.Volume |  | ||||||
| 		oldVolume   []core.Volume |  | ||||||
| 		gateValue   bool |  | ||||||
| 		expectError bool |  | ||||||
| 	}{{ |  | ||||||
| 		name:        "gate on, read-only disk, nil old", |  | ||||||
| 		gateValue:   true, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume(nil), |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate off, read-only disk, nil old", |  | ||||||
| 		gateValue:   false, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume(nil), |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate on, read-write, nil old", |  | ||||||
| 		gateValue:   true, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		oldVolume:   []core.Volume(nil), |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate off, read-write, nil old", |  | ||||||
| 		gateValue:   false, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		oldVolume:   []core.Volume(nil), |  | ||||||
| 		expectError: true, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate on, new read-only and old read-write", |  | ||||||
| 		gateValue:   true, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate off, new read-only and old read-write", |  | ||||||
| 		gateValue:   false, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate on, new read-write and old read-write", |  | ||||||
| 		gateValue:   true, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate off, new read-write and old read-write", |  | ||||||
| 		gateValue:   false, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate on, new read-only and old read-only", |  | ||||||
| 		gateValue:   true, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate off, new read-only and old read-only", |  | ||||||
| 		gateValue:   false, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate on, new read-write and old read-only", |  | ||||||
| 		gateValue:   true, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		expectError: false, |  | ||||||
| 	}, { |  | ||||||
| 		name:        "gate off, new read-write and old read-only", |  | ||||||
| 		gateValue:   false, |  | ||||||
| 		volumes:     []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: false}}}}, |  | ||||||
| 		oldVolume:   []core.Volume{{VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{ReadOnly: true}}}}, |  | ||||||
| 		expectError: true, |  | ||||||
| 	}, |  | ||||||
| 	} |  | ||||||
| 	for _, testCase := range cases { |  | ||||||
| 		t.Run(testCase.name, func(t *testing.T) { |  | ||||||
| 			fidPath := field.NewPath("testField") |  | ||||||
| 			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SkipReadOnlyValidationGCE, testCase.gateValue)() |  | ||||||
| 			errs := ValidateReadOnlyPersistentDisks(testCase.volumes, testCase.oldVolume, fidPath) |  | ||||||
| 			if !testCase.expectError && len(errs) != 0 { |  | ||||||
| 				t.Errorf("expected success, got:%v", errs) |  | ||||||
| 			} |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func TestHugePagesIsolation(t *testing.T) { | func TestHugePagesIsolation(t *testing.T) { | ||||||
| 	testCases := map[string]struct { | 	testCases := map[string]struct { | ||||||
| 		pod         *core.Pod | 		pod         *core.Pod | ||||||
|   | |||||||
| @@ -135,13 +135,6 @@ const ( | |||||||
| 	// Allow the usage of options to fine-tune the cpumanager policies. | 	// Allow the usage of options to fine-tune the cpumanager policies. | ||||||
| 	CPUManagerPolicyOptions featuregate.Feature = "CPUManagerPolicyOptions" | 	CPUManagerPolicyOptions featuregate.Feature = "CPUManagerPolicyOptions" | ||||||
|  |  | ||||||
| 	// owner: @mfordjody |  | ||||||
| 	// alpha: v1.26 |  | ||||||
| 	// |  | ||||||
| 	// Bypasses obsolete validation that GCP volumes are read-only when used in |  | ||||||
| 	// Deployments. |  | ||||||
| 	SkipReadOnlyValidationGCE featuregate.Feature = "SkipReadOnlyValidationGCE" |  | ||||||
|  |  | ||||||
| 	// owner: @trierra | 	// owner: @trierra | ||||||
| 	// alpha: v1.23 | 	// alpha: v1.23 | ||||||
| 	// | 	// | ||||||
| @@ -1038,8 +1031,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS | |||||||
|  |  | ||||||
| 	CSIVolumeHealth: {Default: false, PreRelease: featuregate.Alpha}, | 	CSIVolumeHealth: {Default: false, PreRelease: featuregate.Alpha}, | ||||||
|  |  | ||||||
| 	SkipReadOnlyValidationGCE: {Default: true, PreRelease: featuregate.Deprecated}, // remove in 1.31 |  | ||||||
|  |  | ||||||
| 	CloudControllerManagerWebhook: {Default: false, PreRelease: featuregate.Alpha}, | 	CloudControllerManagerWebhook: {Default: false, PreRelease: featuregate.Alpha}, | ||||||
|  |  | ||||||
| 	ContainerCheckpoint: {Default: true, PreRelease: featuregate.Beta}, | 	ContainerCheckpoint: {Default: true, PreRelease: featuregate.Beta}, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot