add integration test for pod with pvc has node-affinity to non-existent/existent nodes
Signed-off-by: joey <zchengjoey@gmail.com>
This commit is contained in:
		| @@ -882,6 +882,20 @@ func (p *PersistentVolumeWrapper) HostPathVolumeSource(src *v1.HostPathVolumeSou | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // NodeAffinityIn creates a HARD node affinity (with the operator In) | ||||
| // and injects into the pv. | ||||
| func (p *PersistentVolumeWrapper) NodeAffinityIn(key string, vals []string) *PersistentVolumeWrapper { | ||||
| 	if p.Spec.NodeAffinity == nil { | ||||
| 		p.Spec.NodeAffinity = &v1.VolumeNodeAffinity{} | ||||
| 	} | ||||
| 	if p.Spec.NodeAffinity.Required == nil { | ||||
| 		p.Spec.NodeAffinity.Required = &v1.NodeSelector{} | ||||
| 	} | ||||
| 	nodeSelector := MakeNodeSelector().In(key, vals).Obj() | ||||
| 	p.Spec.NodeAffinity.Required.NodeSelectorTerms = append(p.Spec.NodeAffinity.Required.NodeSelectorTerms, nodeSelector.NodeSelectorTerms...) | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // ResourceClaimWrapper wraps a ResourceClaim inside. | ||||
| type ResourceClaimWrapper struct{ resourcev1alpha2.ResourceClaim } | ||||
|  | ||||
|   | ||||
| @@ -43,6 +43,7 @@ var ( | ||||
| 	createAndWaitForNodesInCache = testutils.CreateAndWaitForNodesInCache | ||||
| 	createNamespacesWithLabels   = testutils.CreateNamespacesWithLabels | ||||
| 	createNode                   = testutils.CreateNode | ||||
| 	updateNode                   = testutils.UpdateNode | ||||
| 	createPausePod               = testutils.CreatePausePod | ||||
| 	deletePod                    = testutils.DeletePod | ||||
| 	getPod                       = testutils.GetPod | ||||
| @@ -2036,6 +2037,111 @@ func TestUnschedulablePodBecomesSchedulable(t *testing.T) { | ||||
| 				return deletePod(cs, "pod-to-be-deleted", ns) | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "pod with pvc has node-affinity to non-existent/illegal nodes", | ||||
| 			init: func(cs kubernetes.Interface, ns string) error { | ||||
| 				storage := v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}} | ||||
| 				volType := v1.HostPathDirectoryOrCreate | ||||
| 				pv, err := testutils.CreatePV(cs, st.MakePersistentVolume(). | ||||
| 					Name("pv-has-non-existent-nodes"). | ||||
| 					AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). | ||||
| 					Capacity(storage.Requests). | ||||
| 					HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). | ||||
| 					NodeAffinityIn("kubernetes.io/hostname", []string{"node-available", "non-existing"}). // one node exist, one doesn't | ||||
| 					Obj()) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot create pv: %w", err) | ||||
| 				} | ||||
| 				_, err = testutils.CreatePVC(cs, st.MakePersistentVolumeClaim(). | ||||
| 					Name("pvc-has-non-existent-nodes"). | ||||
| 					Namespace(ns). | ||||
| 					Annotation(volume.AnnBindCompleted, "true"). | ||||
| 					VolumeName(pv.Name). | ||||
| 					AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). | ||||
| 					Resources(storage). | ||||
| 					Obj()) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot create pvc: %w", err) | ||||
| 				} | ||||
| 				return nil | ||||
| 			}, | ||||
| 			pod: &testutils.PausePodConfig{ | ||||
| 				Name: "pod-with-pvc-has-non-existent-nodes", | ||||
| 				Volumes: []v1.Volume{{ | ||||
| 					Name: "volume", | ||||
| 					VolumeSource: v1.VolumeSource{ | ||||
| 						PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ | ||||
| 							ClaimName: "pvc-has-non-existent-nodes", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}}, | ||||
| 			}, | ||||
| 			update: func(cs kubernetes.Interface, ns string) error { | ||||
| 				_, err := createNode(cs, st.MakeNode().Label("kubernetes.io/hostname", "node-available").Name("node-available").Obj()) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot create node: %w", err) | ||||
| 				} | ||||
| 				return nil | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "pod with pvc got scheduled after node updated it's label", | ||||
| 			init: func(cs kubernetes.Interface, ns string) error { | ||||
| 				_, err := createNode(cs, st.MakeNode().Label("foo", "foo").Name("node-foo").Obj()) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot create node: %w", err) | ||||
| 				} | ||||
| 				storage := v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}} | ||||
| 				volType := v1.HostPathDirectoryOrCreate | ||||
| 				pv, err := testutils.CreatePV(cs, st.MakePersistentVolume(). | ||||
| 					Name("pv-foo"). | ||||
| 					AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). | ||||
| 					Capacity(storage.Requests). | ||||
| 					HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). | ||||
| 					NodeAffinityIn("foo", []string{"bar"}). | ||||
| 					Obj()) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot create pv: %w", err) | ||||
| 				} | ||||
| 				_, err = testutils.CreatePVC(cs, st.MakePersistentVolumeClaim(). | ||||
| 					Name("pvc-foo"). | ||||
| 					Namespace(ns). | ||||
| 					Annotation(volume.AnnBindCompleted, "true"). | ||||
| 					VolumeName(pv.Name). | ||||
| 					AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). | ||||
| 					Resources(storage). | ||||
| 					Obj()) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot create pvc: %w", err) | ||||
| 				} | ||||
| 				return nil | ||||
| 			}, | ||||
| 			pod: &testutils.PausePodConfig{ | ||||
| 				Name: "pod-with-pvc-foo", | ||||
| 				Volumes: []v1.Volume{{ | ||||
| 					Name: "volume", | ||||
| 					VolumeSource: v1.VolumeSource{ | ||||
| 						PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ | ||||
| 							ClaimName: "pvc-foo", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}}, | ||||
| 			}, | ||||
| 			update: func(cs kubernetes.Interface, ns string) error { | ||||
| 				_, err := updateNode(cs, &v1.Node{ | ||||
| 					ObjectMeta: metav1.ObjectMeta{ | ||||
| 						Name: "node-foo", | ||||
| 						Labels: map[string]string{ | ||||
| 							"foo": "bar", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("cannot update node: %w", err) | ||||
| 				} | ||||
| 				return nil | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 joey
					joey