mirror of https://github.com/knative/pkg.git
				
				
				
			update EnqueueControllerOf to properly handle Delete (#146)
* update EnqueueControllerOf to properly handle Delete * update existing test * add enqueue label tests * address comments
This commit is contained in:
		
							parent
							
								
									5a67e38d13
								
							
						
					
					
						commit
						d247efe41d
					
				|  | @ -123,12 +123,9 @@ func (c *Impl) Enqueue(obj interface{}) { | |||
| // EnqueueControllerOf takes a resource, identifies its controller resource,
 | ||||
| // converts it into a namespace/name string, and passes that to EnqueueKey.
 | ||||
| func (c *Impl) EnqueueControllerOf(obj interface{}) { | ||||
| 	// TODO(mattmoor): This will not properly handle Delete, which we do
 | ||||
| 	// not currently use.  Consider using "cache.DeletedFinalStateUnknown"
 | ||||
| 	// to enqueue the last known owner.
 | ||||
| 	object, err := meta.Accessor(obj) | ||||
| 	object, err := getObject(obj) | ||||
| 	if err != nil { | ||||
| 		c.logger.Error(zap.Error(err)) | ||||
| 		c.logger.Error(err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
|  | @ -139,6 +136,61 @@ func (c *Impl) EnqueueControllerOf(obj interface{}) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // EnqueueLabelOf returns with an Enqueue func that takes a resource,
 | ||||
| // identifies its controller resource through given namespace and name labels,
 | ||||
| // converts it into a namespace/name string, and passes that to EnqueueKey.
 | ||||
| // Callers should pass in an empty string as namespace label key for obj
 | ||||
| // whose controller is of cluster-scoped resource.
 | ||||
| func (c *Impl) EnqueueLabelOf(namespaceLabel, nameLabel string) func(obj interface{}) { | ||||
| 	return func(obj interface{}) { | ||||
| 		object, err := getObject(obj) | ||||
| 		if err != nil { | ||||
| 			c.logger.Error(err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		labels := object.GetLabels() | ||||
| 		controllerKey, ok := labels[nameLabel] | ||||
| 		if !ok { | ||||
| 			c.logger.Infof("Object %s/%s does not have a referring name label %s", | ||||
| 				object.GetNamespace(), object.GetName(), nameLabel) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if namespaceLabel != "" { | ||||
| 			controllerNamespace, ok := labels[namespaceLabel] | ||||
| 			if !ok { | ||||
| 				c.logger.Infof("Object %s/%s does not have a referring namespace label %s", | ||||
| 					object.GetNamespace(), object.GetName(), namespaceLabel) | ||||
| 				return | ||||
| 			} | ||||
| 
 | ||||
| 			controllerKey = fmt.Sprintf("%s/%s", controllerNamespace, controllerKey) | ||||
| 		} | ||||
| 
 | ||||
| 		c.EnqueueKey(controllerKey) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // getObject tries to get runtime Object from given interface in the way of Accessor first;
 | ||||
| // and to handle deletion, it try to fetch info from DeletedFinalStateUnknown on failure.
 | ||||
| func getObject(obj interface{}) (metav1.Object, error) { | ||||
| 	object, err := meta.Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		// To handle obj deletion, try to fetch info from DeletedFinalStateUnknown.
 | ||||
| 		tombstone, ok := obj.(cache.DeletedFinalStateUnknown) | ||||
| 		if !ok { | ||||
| 			return nil, fmt.Errorf("Couldn't get object from tombstone %#v", obj) | ||||
| 		} | ||||
| 		object, ok = tombstone.Obj.(metav1.Object) | ||||
| 		if !ok { | ||||
| 			return nil, fmt.Errorf("The object that Tombstone contained is not of metav1.Object %#v", obj) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return object, nil | ||||
| } | ||||
| 
 | ||||
| // EnqueueKey takes a namespace/name string and puts it onto the work queue.
 | ||||
| func (c *Impl) EnqueueKey(key string) { | ||||
| 	c.WorkQueue.AddRateLimited(key) | ||||
|  |  | |||
|  | @ -230,6 +230,120 @@ func TestEnqueues(t *testing.T) { | |||
| 			}) | ||||
| 		}, | ||||
| 		wantQueue: []string{"bar/baz"}, | ||||
| 	}, { | ||||
| 		name: "enqueue controller of deleted resource with owner", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueControllerOf(cache.DeletedFinalStateUnknown{ | ||||
| 				Key: "foo/bar", | ||||
| 				Obj: &Resource{ | ||||
| 					ObjectMeta: metav1.ObjectMeta{ | ||||
| 						Name:      "foo", | ||||
| 						Namespace: "bar", | ||||
| 						OwnerReferences: []metav1.OwnerReference{{ | ||||
| 							APIVersion: gvk.GroupVersion().String(), | ||||
| 							Kind:       gvk.Kind, | ||||
| 							Name:       "baz", | ||||
| 							Controller: &boolTrue, | ||||
| 						}}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 		}, | ||||
| 		wantQueue: []string{"bar/baz"}, | ||||
| 	}, { | ||||
| 		name: "enqueue controller of deleted bad resource", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueControllerOf(cache.DeletedFinalStateUnknown{ | ||||
| 				Key: "foo/bar", | ||||
| 				Obj: "bad-resource", | ||||
| 			}) | ||||
| 		}, | ||||
| 	}, { | ||||
| 		name: "enqueue label of bad resource", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("test-ns", "test-name")("baz/blah") | ||||
| 		}, | ||||
| 	}, { | ||||
| 		name: "enqueue label of resource without label", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("ns-key", "name-key")(&Resource{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Name:      "foo", | ||||
| 					Namespace: "bar", | ||||
| 					Labels: map[string]string{ | ||||
| 						"ns-key": "bar", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 		}, | ||||
| 	}, { | ||||
| 		name: "enqueue label of resource without namespace label", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("ns-key", "name-key")(&Resource{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Name:      "foo", | ||||
| 					Namespace: "bar", | ||||
| 					Labels: map[string]string{ | ||||
| 						"name-key": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 		}, | ||||
| 	}, { | ||||
| 		name: "enqueue label of resource with labels", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("ns-key", "name-key")(&Resource{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Name:      "foo", | ||||
| 					Namespace: "bar", | ||||
| 					Labels: map[string]string{ | ||||
| 						"ns-key": "bar", | ||||
| 						"name-key": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 		}, | ||||
| 		wantQueue: []string{"bar/baz"}, | ||||
| 	}, { | ||||
| 		name: "enqueue label of resource with empty namespace label (cluster-scoped resource)", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("", "name-key")(&Resource{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Name:      "foo", | ||||
| 					Namespace: "bar", | ||||
| 					Labels: map[string]string{ | ||||
| 						"name-key": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 		}, | ||||
| 		wantQueue: []string{"baz"}, | ||||
| 	}, { | ||||
| 		name: "enqueue label of deleted resource with label", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("ns-key", "name-key")(cache.DeletedFinalStateUnknown{ | ||||
| 				Key: "foo/bar", | ||||
| 				Obj: &Resource{ | ||||
| 					ObjectMeta: metav1.ObjectMeta{ | ||||
| 						Name:      "foo", | ||||
| 						Namespace: "bar", | ||||
| 						Labels: map[string]string{ | ||||
| 							"ns-key": "bar", | ||||
| 							"name-key": "baz", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 		}, | ||||
| 		wantQueue: []string{"bar/baz"}, | ||||
| 	}, { | ||||
| 		name: "enqueue controller of deleted bad resource", | ||||
| 		work: func(impl *Impl) { | ||||
| 			impl.EnqueueLabelOf("ns-key", "name-key")(cache.DeletedFinalStateUnknown{ | ||||
| 				Key: "foo/bar", | ||||
| 				Obj: "bad-resource", | ||||
| 			}) | ||||
| 		}, | ||||
| 	}} | ||||
| 
 | ||||
| 	for _, test := range tests { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue