mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Fix validation test for ReplicationController
I discovered this by changing the validation in a way that SHOULD fail (by allowing something it should not). But it didn't. A different error happens which totally masks the non-failure I expected. New test is much more explicit about what failures are expected. This does not focus on adding test coverage, just making sure the test is not terrible.
This commit is contained in:
		@@ -16606,435 +16606,267 @@ func TestValidateReplicationControllerStatusUpdate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateReplicationControllerUpdate(t *testing.T) {
 | 
					// Helper function for RC tests.
 | 
				
			||||||
	validSelector := map[string]string{"a": "b"}
 | 
					func mkValidReplicationController(tweaks ...func(rc *core.ReplicationController)) core.ReplicationController {
 | 
				
			||||||
	validPodTemplate := core.PodTemplate{
 | 
						rc := core.ReplicationController{
 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: validSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	readWriteVolumePodTemplate := core.PodTemplate{
 | 
					 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: validSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(
 | 
					 | 
				
			||||||
				podtest.SetVolumes(core.Volume{Name: "gcepd", VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}),
 | 
					 | 
				
			||||||
			),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
 | 
					 | 
				
			||||||
	invalidPodTemplate := core.PodTemplate{
 | 
					 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: invalidSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	type rcUpdateTest struct {
 | 
					 | 
				
			||||||
		old    core.ReplicationController
 | 
					 | 
				
			||||||
		update core.ReplicationController
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	successCases := []rcUpdateTest{{
 | 
					 | 
				
			||||||
		old: core.ReplicationController{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
			Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
				Selector: validSelector,
 | 
					 | 
				
			||||||
				Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		update: core.ReplicationController{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
			Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
				Replicas: 3,
 | 
					 | 
				
			||||||
				Selector: validSelector,
 | 
					 | 
				
			||||||
				Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}, {
 | 
					 | 
				
			||||||
		old: core.ReplicationController{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
			Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
				Selector: validSelector,
 | 
					 | 
				
			||||||
				Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		update: core.ReplicationController{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
			Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
				Replicas: 1,
 | 
					 | 
				
			||||||
				Selector: validSelector,
 | 
					 | 
				
			||||||
				Template: &readWriteVolumePodTemplate.Template,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, successCase := range successCases {
 | 
					 | 
				
			||||||
		successCase.old.ObjectMeta.ResourceVersion = "1"
 | 
					 | 
				
			||||||
		successCase.update.ObjectMeta.ResourceVersion = "1"
 | 
					 | 
				
			||||||
		if errs := ValidateReplicationControllerUpdate(&successCase.update, &successCase.old, PodValidationOptions{}); len(errs) != 0 {
 | 
					 | 
				
			||||||
			t.Errorf("expected success: %v", errs)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	errorCases := map[string]rcUpdateTest{
 | 
					 | 
				
			||||||
		"more than one read/write": {
 | 
					 | 
				
			||||||
			old: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			update: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: 2,
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &readWriteVolumePodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid selector": {
 | 
					 | 
				
			||||||
			old: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			update: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: 2,
 | 
					 | 
				
			||||||
					Selector: invalidSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid pod": {
 | 
					 | 
				
			||||||
			old: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			update: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: 2,
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &invalidPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"negative replicas": {
 | 
					 | 
				
			||||||
			old: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			update: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: -1,
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for testName, errorCase := range errorCases {
 | 
					 | 
				
			||||||
		if errs := ValidateReplicationControllerUpdate(&errorCase.update, &errorCase.old, PodValidationOptions{}); len(errs) == 0 {
 | 
					 | 
				
			||||||
			t.Errorf("expected failure: %s", testName)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestValidateReplicationController(t *testing.T) {
 | 
					 | 
				
			||||||
	validSelector := map[string]string{"a": "b"}
 | 
					 | 
				
			||||||
	validPodTemplate := core.PodTemplate{
 | 
					 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: validSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	readWriteVolumePodTemplate := core.PodTemplate{
 | 
					 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: validSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(
 | 
					 | 
				
			||||||
				podtest.SetVolumes(core.Volume{Name: "gcepd", VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}),
 | 
					 | 
				
			||||||
			),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	hostnetPodTemplate := core.PodTemplate{
 | 
					 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: validSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(
 | 
					 | 
				
			||||||
				podtest.SetSecurityContext(&core.PodSecurityContext{
 | 
					 | 
				
			||||||
					HostNetwork: true,
 | 
					 | 
				
			||||||
				}),
 | 
					 | 
				
			||||||
				podtest.SetContainers(podtest.MakeContainer("abc", podtest.SetContainerPorts(
 | 
					 | 
				
			||||||
					core.ContainerPort{
 | 
					 | 
				
			||||||
						ContainerPort: 12345,
 | 
					 | 
				
			||||||
						Protocol:      core.ProtocolTCP,
 | 
					 | 
				
			||||||
					}))),
 | 
					 | 
				
			||||||
			),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
 | 
					 | 
				
			||||||
	invalidPodTemplate := core.PodTemplate{
 | 
					 | 
				
			||||||
		Template: core.PodTemplateSpec{
 | 
					 | 
				
			||||||
			Spec: podtest.MakePodSpec(),
 | 
					 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
				Labels: invalidSelector,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	successCases := []core.ReplicationController{{
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
		Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
			Selector: validSelector,
 | 
					 | 
				
			||||||
			Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}, {
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
		Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
			Selector: validSelector,
 | 
					 | 
				
			||||||
			Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}, {
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
		Spec: core.ReplicationControllerSpec{
 | 
							Spec: core.ReplicationControllerSpec{
 | 
				
			||||||
			Replicas: 1,
 | 
								Replicas: 1,
 | 
				
			||||||
			Selector: validSelector,
 | 
								Selector: map[string]string{"a": "b"},
 | 
				
			||||||
			Template: &readWriteVolumePodTemplate.Template,
 | 
								Template: &core.PodTemplateSpec{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Labels: map[string]string{"a": "b"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: podtest.MakePodSpec(),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, tweak := range tweaks {
 | 
				
			||||||
 | 
							tweak(&rc)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestValidateReplicationControllerUpdate(t *testing.T) {
 | 
				
			||||||
 | 
						successCases := []struct {
 | 
				
			||||||
 | 
							old    core.ReplicationController
 | 
				
			||||||
 | 
							update core.ReplicationController
 | 
				
			||||||
 | 
						}{{
 | 
				
			||||||
 | 
							old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
 | 
							update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
								rc.Spec.Replicas = 0
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "hostnet", Namespace: metav1.NamespaceDefault},
 | 
							old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
		Spec: core.ReplicationControllerSpec{
 | 
							update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
			Replicas: 1,
 | 
								rc.Spec.Replicas = 3
 | 
				
			||||||
			Selector: validSelector,
 | 
							}),
 | 
				
			||||||
			Template: &hostnetPodTemplate.Template,
 | 
						}, {
 | 
				
			||||||
		},
 | 
							old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
 | 
							update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
								rc.Spec.Replicas = 2
 | 
				
			||||||
 | 
								rc.Spec.Template.Spec = podtest.MakePodSpec(
 | 
				
			||||||
 | 
									podtest.SetVolumes(
 | 
				
			||||||
 | 
										core.Volume{
 | 
				
			||||||
 | 
											Name: "gcepd",
 | 
				
			||||||
 | 
											VolumeSource: core.VolumeSource{
 | 
				
			||||||
 | 
												GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{
 | 
				
			||||||
 | 
													PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false,
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}))
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
	}}
 | 
						}}
 | 
				
			||||||
	for _, successCase := range successCases {
 | 
						for _, tc := range successCases {
 | 
				
			||||||
		if errs := ValidateReplicationController(&successCase, PodValidationOptions{}); len(errs) != 0 {
 | 
							tc.old.ObjectMeta.ResourceVersion = "1"
 | 
				
			||||||
 | 
							tc.update.ObjectMeta.ResourceVersion = "1"
 | 
				
			||||||
 | 
							if errs := ValidateReplicationControllerUpdate(&tc.update, &tc.old, PodValidationOptions{}); len(errs) != 0 {
 | 
				
			||||||
			t.Errorf("expected success: %v", errs)
 | 
								t.Errorf("expected success: %v", errs)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errorCases := map[string]struct {
 | 
						errorCases := map[string]struct {
 | 
				
			||||||
		rc             core.ReplicationController
 | 
							old          core.ReplicationController
 | 
				
			||||||
		expectedOrigin []string
 | 
							update       core.ReplicationController
 | 
				
			||||||
 | 
							expectedErrs field.ErrorList
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		"zero-length ID": {
 | 
							"unmatched selector": {
 | 
				
			||||||
			rc: core.ReplicationController{
 | 
								old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
 | 
								update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
									rc.Spec.Selector["another"] = "value"
 | 
				
			||||||
					Selector: validSelector,
 | 
								}),
 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
				},
 | 
									field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"missing-namespace": {
 | 
							"invalid selector": {
 | 
				
			||||||
			rc: core.ReplicationController{
 | 
								old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc-123"},
 | 
								update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
									invalid := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
 | 
				
			||||||
					Selector: validSelector,
 | 
									rc.Spec.Template.Labels = invalid
 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
									rc.Spec.Selector = invalid
 | 
				
			||||||
				},
 | 
								}),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("spec.template.labels"), nil, "").WithOrigin("labelKey"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"empty selector": {
 | 
							"invalid pod": {
 | 
				
			||||||
			rc: core.ReplicationController{
 | 
								old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
								update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
									rc.Spec.Template = nil
 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
								}),
 | 
				
			||||||
				},
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Required(field.NewPath("spec.template"), ""),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"selector_doesnt_match": {
 | 
							"negative replicas": {
 | 
				
			||||||
			rc: core.ReplicationController{
 | 
								old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
								update: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
									rc.Spec.Replicas = -1
 | 
				
			||||||
					Selector: map[string]string{"foo": "bar"},
 | 
								}),
 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
				},
 | 
									field.Invalid(field.NewPath("spec.replicas"), nil, "").WithOrigin("minimum"),
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid manifest": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"read-write persistent disk with > 1 pod": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc"},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: 2,
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &readWriteVolumePodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"negative_replicas": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: -1,
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			expectedOrigin: []string{
 | 
					 | 
				
			||||||
				"minimum",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid_label": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
					Name:      "abc-123",
 | 
					 | 
				
			||||||
					Namespace: metav1.NamespaceDefault,
 | 
					 | 
				
			||||||
					Labels: map[string]string{
 | 
					 | 
				
			||||||
						"NoUppercaseOrSpecialCharsLike=Equals": "bar",
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid_label 2": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
					Name:      "abc-123",
 | 
					 | 
				
			||||||
					Namespace: metav1.NamespaceDefault,
 | 
					 | 
				
			||||||
					Labels: map[string]string{
 | 
					 | 
				
			||||||
						"NoUppercaseOrSpecialCharsLike=Equals": "bar",
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Template: &invalidPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid_annotation": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
					Name:      "abc-123",
 | 
					 | 
				
			||||||
					Namespace: metav1.NamespaceDefault,
 | 
					 | 
				
			||||||
					Annotations: map[string]string{
 | 
					 | 
				
			||||||
						"NoUppercaseOrSpecialCharsLike=Equals": "bar",
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &validPodTemplate.Template,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid restart policy 1": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
					Name:      "abc-123",
 | 
					 | 
				
			||||||
					Namespace: metav1.NamespaceDefault,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &core.PodTemplateSpec{
 | 
					 | 
				
			||||||
						Spec: podtest.MakePodSpec(podtest.SetRestartPolicy(core.RestartPolicyOnFailure)),
 | 
					 | 
				
			||||||
						ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
							Labels: validSelector,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"invalid restart policy 2": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
					Name:      "abc-123",
 | 
					 | 
				
			||||||
					Namespace: metav1.NamespaceDefault,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &core.PodTemplateSpec{
 | 
					 | 
				
			||||||
						Spec: podtest.MakePodSpec(podtest.SetRestartPolicy(core.RestartPolicyNever)),
 | 
					 | 
				
			||||||
						ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
							Labels: validSelector,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"template may not contain ephemeral containers": {
 | 
					 | 
				
			||||||
			rc: core.ReplicationController{
 | 
					 | 
				
			||||||
				ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
					 | 
				
			||||||
				Spec: core.ReplicationControllerSpec{
 | 
					 | 
				
			||||||
					Replicas: 1,
 | 
					 | 
				
			||||||
					Selector: validSelector,
 | 
					 | 
				
			||||||
					Template: &core.PodTemplateSpec{
 | 
					 | 
				
			||||||
						ObjectMeta: metav1.ObjectMeta{
 | 
					 | 
				
			||||||
							Labels: validSelector,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
						Spec: podtest.MakePodSpec(
 | 
					 | 
				
			||||||
							podtest.SetEphemeralContainers(core.EphemeralContainer{EphemeralContainerCommon: core.EphemeralContainerCommon{Name: "debug", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}),
 | 
					 | 
				
			||||||
						),
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k, v := range errorCases {
 | 
						for k, tc := range errorCases {
 | 
				
			||||||
		errs := ValidateReplicationController(&v.rc, PodValidationOptions{})
 | 
							t.Run(k, func(t *testing.T) {
 | 
				
			||||||
		if len(errs) == 0 {
 | 
								tc.old.ObjectMeta.ResourceVersion = "1"
 | 
				
			||||||
			t.Errorf("expected failure for %s", k)
 | 
								tc.update.ObjectMeta.ResourceVersion = "1"
 | 
				
			||||||
 | 
								errs := ValidateReplicationControllerUpdate(&tc.update, &tc.old, PodValidationOptions{})
 | 
				
			||||||
 | 
								matcher := fldtest.ErrorMatcher{}.ByType().ByField().ByOrigin().ByDetailSubstring()
 | 
				
			||||||
 | 
								matcher.Test(t, tc.expectedErrs, errs)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestValidateReplicationController(t *testing.T) {
 | 
				
			||||||
 | 
						successCases := []core.ReplicationController{
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) {}),
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) { rc.Name = "abc-123" }),
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
								rc.Spec.Replicas = 2
 | 
				
			||||||
 | 
								rc.Spec.Template.Spec = podtest.MakePodSpec(
 | 
				
			||||||
 | 
									podtest.SetVolumes(
 | 
				
			||||||
 | 
										core.Volume{
 | 
				
			||||||
 | 
											Name: "gcepd",
 | 
				
			||||||
 | 
											VolumeSource: core.VolumeSource{
 | 
				
			||||||
 | 
												GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{
 | 
				
			||||||
 | 
													PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false,
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}))
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
								rc.Spec.Template.Spec = podtest.MakePodSpec(
 | 
				
			||||||
 | 
									podtest.SetSecurityContext(&core.PodSecurityContext{HostNetwork: true}),
 | 
				
			||||||
 | 
									podtest.SetContainers(podtest.MakeContainer("abc",
 | 
				
			||||||
 | 
										podtest.SetContainerPorts(core.ContainerPort{
 | 
				
			||||||
 | 
											ContainerPort: 12345, Protocol: core.ProtocolTCP,
 | 
				
			||||||
 | 
										}))),
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 0 }),
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 1 }),
 | 
				
			||||||
 | 
							mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 100 }),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, tc := range successCases {
 | 
				
			||||||
 | 
							if errs := ValidateReplicationController(&tc, PodValidationOptions{}); len(errs) != 0 {
 | 
				
			||||||
 | 
								t.Errorf("expected success: %v", errs)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		expectedOrigins := sets.NewString(v.expectedOrigin...)
 | 
						errorCases := map[string]struct {
 | 
				
			||||||
 | 
							input        core.ReplicationController
 | 
				
			||||||
		for i := range errs {
 | 
							expectedErrs field.ErrorList
 | 
				
			||||||
			field := errs[i].Field
 | 
						}{
 | 
				
			||||||
			if !strings.HasPrefix(field, "spec.template.") &&
 | 
							"missing name": {
 | 
				
			||||||
				field != "metadata.name" &&
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Name = "" }),
 | 
				
			||||||
				field != "metadata.namespace" &&
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
				field != "spec.selector" &&
 | 
									field.Required(field.NewPath("metadata.name"), ""),
 | 
				
			||||||
				field != "spec.template" &&
 | 
								},
 | 
				
			||||||
				field != "GCEPersistentDisk.ReadOnly" &&
 | 
							},
 | 
				
			||||||
				field != "spec.replicas" &&
 | 
							"missing namespace": {
 | 
				
			||||||
				field != "spec.template.labels" &&
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Namespace = "" }),
 | 
				
			||||||
				field != "metadata.annotations" &&
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
				field != "metadata.labels" &&
 | 
									field.Required(field.NewPath("metadata.namespace"), ""),
 | 
				
			||||||
				field != "status.replicas" {
 | 
								},
 | 
				
			||||||
				t.Errorf("%s: missing prefix for: %v", k, errs[i])
 | 
							},
 | 
				
			||||||
			}
 | 
							"empty selector": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Selector = nil }),
 | 
				
			||||||
			if len(v.expectedOrigin) > 0 && errs[i].Origin != "" {
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
				if !expectedOrigins.Has(errs[i].Origin) {
 | 
									field.Required(field.NewPath("spec.selector"), ""),
 | 
				
			||||||
					t.Errorf("%s: unexpected origin for: %v, expected one of %v", k, errs[i].Origin, v.expectedOrigin)
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"selector doesnt match": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Selector = map[string]string{"foo": "bar"} }),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid manifest": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Template = nil }),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Required(field.NewPath("spec.template"), ""),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"negative replicas": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = -1 }),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("spec.replicas"), nil, "").WithOrigin("minimum"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid label": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
									rc.Labels = map[string]string{
 | 
				
			||||||
 | 
										"NoUppercaseOrSpecialCharsLike=Equals": "bar",
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				expectedOrigins.Delete(errs[i].Origin)
 | 
								}),
 | 
				
			||||||
			}
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
		}
 | 
									field.Invalid(field.NewPath("metadata.labels"), nil, "").WithOrigin("labelKey"),
 | 
				
			||||||
		if len(expectedOrigins) > 0 {
 | 
								},
 | 
				
			||||||
			t.Errorf("%s: missing errors with origin: %v", k, expectedOrigins.List())
 | 
							},
 | 
				
			||||||
		}
 | 
							"invalid label 2": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
									rc.Spec.Template.Labels = map[string]string{
 | 
				
			||||||
 | 
										"NoUppercaseOrSpecialCharsLike=Equals": "bar",
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("spec.template.labels"), nil, "").WithOrigin("labelKey"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid annotation": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
									rc.Annotations = map[string]string{
 | 
				
			||||||
 | 
										"NoUppercaseOrSpecialCharsLike=Equals": "bar",
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("metadata.annotations"), nil, "name part must consist of"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid restart policy 1": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
									rc.Spec.Template.Spec.RestartPolicy = core.RestartPolicyOnFailure
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.NotSupported[core.RestartPolicy](field.NewPath("spec.template.spec.restartPolicy"), nil, nil),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid restart policy 2": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
									rc.Spec.Template.Spec.RestartPolicy = core.RestartPolicyNever
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.NotSupported[core.RestartPolicy](field.NewPath("spec.template.spec.restartPolicy"), nil, nil),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"template may not contain ephemeral containers": {
 | 
				
			||||||
 | 
								input: mkValidReplicationController(func(rc *core.ReplicationController) {
 | 
				
			||||||
 | 
									rc.Spec.Template.Spec = podtest.MakePodSpec(
 | 
				
			||||||
 | 
										podtest.SetEphemeralContainers(
 | 
				
			||||||
 | 
											core.EphemeralContainer{
 | 
				
			||||||
 | 
												EphemeralContainerCommon: core.EphemeralContainerCommon{
 | 
				
			||||||
 | 
													Name:                     "debug",
 | 
				
			||||||
 | 
													Image:                    "image",
 | 
				
			||||||
 | 
													ImagePullPolicy:          "IfNotPresent",
 | 
				
			||||||
 | 
													TerminationMessagePolicy: "File",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											}))
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								expectedErrs: field.ErrorList{
 | 
				
			||||||
 | 
									field.Forbidden(field.NewPath("spec.template.spec.ephemeralContainers"), "not allowed in pod template"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for k, tc := range errorCases {
 | 
				
			||||||
 | 
							t.Run(k, func(t *testing.T) {
 | 
				
			||||||
 | 
								errs := ValidateReplicationController(&tc.input, PodValidationOptions{})
 | 
				
			||||||
 | 
								matcher := fldtest.ErrorMatcher{}.ByType().ByField().ByOrigin().ByDetailSubstring()
 | 
				
			||||||
 | 
								matcher.Test(t, tc.expectedErrs, errs)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user