| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | Copyright 2016 The Kubernetes Authors. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | You may obtain a copy of the License at | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | See the License for the specific language governing permissions and | 
					
						
							|  |  |  | limitations under the License. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package controller | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/golang/glog" | 
					
						
							| 
									
										
										
										
											2017-01-14 01:48:50 +08:00
										 |  |  | 	"k8s.io/apimachinery/pkg/api/errors" | 
					
						
							| 
									
										
										
										
											2017-01-11 22:09:48 +08:00
										 |  |  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 
					
						
							|  |  |  | 	"k8s.io/apimachinery/pkg/labels" | 
					
						
							|  |  |  | 	"k8s.io/apimachinery/pkg/runtime/schema" | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	utilerrors "k8s.io/apimachinery/pkg/util/errors" | 
					
						
							| 
									
										
										
										
											2016-11-19 04:50:17 +08:00
										 |  |  | 	"k8s.io/kubernetes/pkg/api/v1" | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 	extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | // GetControllerOf returns the controllerRef if controllee has a controller,
 | 
					
						
							|  |  |  | // otherwise returns nil.
 | 
					
						
							|  |  |  | func GetControllerOf(controllee metav1.Object) *metav1.OwnerReference { | 
					
						
							|  |  |  | 	ownerRefs := controllee.GetOwnerReferences() | 
					
						
							|  |  |  | 	for i := range ownerRefs { | 
					
						
							|  |  |  | 		owner := &ownerRefs[i] | 
					
						
							|  |  |  | 		if owner.Controller != nil && *owner.Controller == true { | 
					
						
							|  |  |  | 			return owner | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type baseControllerRefManager struct { | 
					
						
							|  |  |  | 	controller metav1.Object | 
					
						
							|  |  |  | 	selector   labels.Selector | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // claimObject tries to take ownership of an object for this controller.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // It will reconcile the following:
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | //   * Adopt orphans if the match function returns true.
 | 
					
						
							|  |  |  | //   * Release owned objects if the match function returns false.
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // A non-nil error is returned if some form of reconciliation was attemped and
 | 
					
						
							|  |  |  | // failed. Usually, controllers should try again later in case reconciliation
 | 
					
						
							|  |  |  | // is still needed.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // If the error is nil, either the reconciliation succeeded, or no
 | 
					
						
							|  |  |  | // reconciliation was necessary. The returned boolean indicates whether you now
 | 
					
						
							|  |  |  | // own the object.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // No reconciliation will be attempted if the controller is being deleted.
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | func (m *baseControllerRefManager) claimObject(obj metav1.Object, match func(metav1.Object) bool, adopt, release func(metav1.Object) error) (bool, error) { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	controllerRef := GetControllerOf(obj) | 
					
						
							|  |  |  | 	if controllerRef != nil { | 
					
						
							|  |  |  | 		if controllerRef.UID != m.controller.GetUID() { | 
					
						
							|  |  |  | 			// Owned by someone else. Ignore.
 | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | 		if match(obj) { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 			// We already own it and the selector matches.
 | 
					
						
							|  |  |  | 			// Return true (successfully claimed) before checking deletion timestamp.
 | 
					
						
							|  |  |  | 			// We're still allowed to claim things we already own while being deleted
 | 
					
						
							|  |  |  | 			// because doing so requires taking no actions.
 | 
					
						
							|  |  |  | 			return true, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Owned by us but selector doesn't match.
 | 
					
						
							|  |  |  | 		// Try to release, unless we're being deleted.
 | 
					
						
							|  |  |  | 		if m.controller.GetDeletionTimestamp() != nil { | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := release(obj); err != nil { | 
					
						
							|  |  |  | 			// If the pod no longer exists, ignore the error.
 | 
					
						
							|  |  |  | 			if errors.IsNotFound(err) { | 
					
						
							|  |  |  | 				return false, nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Either someone else released it, or there was a transient error.
 | 
					
						
							|  |  |  | 			// The controller should requeue and try again if it's still stale.
 | 
					
						
							|  |  |  | 			return false, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Successfully released.
 | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// It's an orphan.
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | 	if m.controller.GetDeletionTimestamp() != nil || !match(obj) { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		// Ignore if we're being deleted or selector doesn't match.
 | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Selector matches. Try to adopt.
 | 
					
						
							|  |  |  | 	if err := adopt(obj); err != nil { | 
					
						
							|  |  |  | 		// If the pod no longer exists, ignore the error.
 | 
					
						
							|  |  |  | 		if errors.IsNotFound(err) { | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Either someone else claimed it first, or there was a transient error.
 | 
					
						
							|  |  |  | 		// The controller should requeue and try again if it's still orphaned.
 | 
					
						
							|  |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Successfully adopted.
 | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | type PodControllerRefManager struct { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	baseControllerRefManager | 
					
						
							|  |  |  | 	controllerKind schema.GroupVersionKind | 
					
						
							|  |  |  | 	podControl     PodControlInterface | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPodControllerRefManager returns a PodControllerRefManager that exposes
 | 
					
						
							|  |  |  | // methods to manage the controllerRef of pods.
 | 
					
						
							|  |  |  | func NewPodControllerRefManager( | 
					
						
							|  |  |  | 	podControl PodControlInterface, | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	controller metav1.Object, | 
					
						
							|  |  |  | 	selector labels.Selector, | 
					
						
							| 
									
										
										
										
											2016-11-21 10:55:31 +08:00
										 |  |  | 	controllerKind schema.GroupVersionKind, | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | ) *PodControllerRefManager { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	return &PodControllerRefManager{ | 
					
						
							|  |  |  | 		baseControllerRefManager: baseControllerRefManager{ | 
					
						
							|  |  |  | 			controller: controller, | 
					
						
							|  |  |  | 			selector:   selector, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		controllerKind: controllerKind, | 
					
						
							|  |  |  | 		podControl:     podControl, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | // ClaimPods tries to take ownership of a list of Pods.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // It will reconcile the following:
 | 
					
						
							|  |  |  | //   * Adopt orphans if the selector matches.
 | 
					
						
							|  |  |  | //   * Release owned objects if the selector no longer matches.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | // Optional: If one or more filters are specified, a Pod will only be claimed if
 | 
					
						
							|  |  |  | // all filters return true.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | // A non-nil error is returned if some form of reconciliation was attemped and
 | 
					
						
							|  |  |  | // failed. Usually, controllers should try again later in case reconciliation
 | 
					
						
							|  |  |  | // is still needed.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // If the error is nil, either the reconciliation succeeded, or no
 | 
					
						
							|  |  |  | // reconciliation was necessary. The list of Pods that you now own is returned.
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | func (m *PodControllerRefManager) ClaimPods(pods []*v1.Pod, filters ...func(*v1.Pod) bool) ([]*v1.Pod, error) { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	var claimed []*v1.Pod | 
					
						
							|  |  |  | 	var errlist []error | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | 	match := func(obj metav1.Object) bool { | 
					
						
							|  |  |  | 		pod := obj.(*v1.Pod) | 
					
						
							|  |  |  | 		// Check selector first so filters only run on potentially matching Pods.
 | 
					
						
							|  |  |  | 		if !m.selector.Matches(labels.Set(pod.Labels)) { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, filter := range filters { | 
					
						
							|  |  |  | 			if !filter(pod) { | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	adopt := func(obj metav1.Object) error { | 
					
						
							|  |  |  | 		return m.AdoptPod(obj.(*v1.Pod)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	release := func(obj metav1.Object) error { | 
					
						
							|  |  |  | 		return m.ReleasePod(obj.(*v1.Pod)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, pod := range pods { | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | 		ok, err := m.claimObject(pod, match, adopt, release) | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			errlist = append(errlist, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		if ok { | 
					
						
							|  |  |  | 			claimed = append(claimed, pod) | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	return claimed, utilerrors.NewAggregate(errlist) | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AdoptPod sends a patch to take control of the pod. It returns the error if
 | 
					
						
							|  |  |  | // the patching fails.
 | 
					
						
							| 
									
										
										
										
											2016-11-19 04:50:17 +08:00
										 |  |  | func (m *PodControllerRefManager) AdoptPod(pod *v1.Pod) error { | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 	// we should not adopt any pods if the controller is about to be deleted
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	if m.controller.GetDeletionTimestamp() != nil { | 
					
						
							| 
									
										
										
										
											2017-01-14 10:03:57 +08:00
										 |  |  | 		return fmt.Errorf("cancel the adopt attempt for pod %s because the controller is being deleted", | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 			strings.Join([]string{pod.Namespace, pod.Name, string(pod.UID)}, "_")) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	// Note that ValidateOwnerReferences() will reject this patch if another
 | 
					
						
							|  |  |  | 	// OwnerReference exists with controller=true.
 | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 	addControllerPatch := fmt.Sprintf( | 
					
						
							| 
									
										
										
										
											2017-02-24 03:16:13 +08:00
										 |  |  | 		`{"metadata":{"ownerReferences":[{"apiVersion":"%s","kind":"%s","name":"%s","uid":"%s","controller":true,"blockOwnerDeletion":true}],"uid":"%s"}}`, | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 		m.controllerKind.GroupVersion(), m.controllerKind.Kind, | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		m.controller.GetName(), m.controller.GetUID(), pod.UID) | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 	return m.podControl.PatchPod(pod.Namespace, pod.Name, []byte(addControllerPatch)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReleasePod sends a patch to free the pod from the control of the controller.
 | 
					
						
							|  |  |  | // It returns the error if the patching fails. 404 and 422 errors are ignored.
 | 
					
						
							| 
									
										
										
										
											2016-11-19 04:50:17 +08:00
										 |  |  | func (m *PodControllerRefManager) ReleasePod(pod *v1.Pod) error { | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 	glog.V(2).Infof("patching pod %s_%s to remove its controllerRef to %s/%s:%s", | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		pod.Namespace, pod.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.controller.GetName()) | 
					
						
							|  |  |  | 	deleteOwnerRefPatch := fmt.Sprintf(`{"metadata":{"ownerReferences":[{"$patch":"delete","uid":"%s"}],"uid":"%s"}}`, m.controller.GetUID(), pod.UID) | 
					
						
							| 
									
										
										
										
											2016-06-11 07:28:42 +08:00
										 |  |  | 	err := m.podControl.PatchPod(pod.Namespace, pod.Name, []byte(deleteOwnerRefPatch)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.IsNotFound(err) { | 
					
						
							|  |  |  | 			// If the pod no longer exists, ignore it.
 | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if errors.IsInvalid(err) { | 
					
						
							|  |  |  | 			// Invalid error will be returned in two cases: 1. the pod
 | 
					
						
							|  |  |  | 			// has no owner reference, 2. the uid of the pod doesn't
 | 
					
						
							|  |  |  | 			// match, which means the pod is deleted and then recreated.
 | 
					
						
							|  |  |  | 			// In both cases, the error can be ignored.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// TODO: If the pod has owner references, but none of them
 | 
					
						
							|  |  |  | 			// has the owner.UID, server will silently ignore the patch.
 | 
					
						
							|  |  |  | 			// Investigate why.
 | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ReplicaSetControllerRefManager is used to manage controllerRef of ReplicaSets.
 | 
					
						
							|  |  |  | // Three methods are defined on this object 1: Classify 2: AdoptReplicaSet and
 | 
					
						
							|  |  |  | // 3: ReleaseReplicaSet which are used to classify the ReplicaSets into appropriate
 | 
					
						
							|  |  |  | // categories and accordingly adopt or release them. See comments on these functions
 | 
					
						
							|  |  |  | // for more details.
 | 
					
						
							|  |  |  | type ReplicaSetControllerRefManager struct { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	baseControllerRefManager | 
					
						
							|  |  |  | 	controllerKind schema.GroupVersionKind | 
					
						
							|  |  |  | 	rsControl      RSControlInterface | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewReplicaSetControllerRefManager returns a ReplicaSetControllerRefManager that exposes
 | 
					
						
							|  |  |  | // methods to manage the controllerRef of ReplicaSets.
 | 
					
						
							|  |  |  | func NewReplicaSetControllerRefManager( | 
					
						
							|  |  |  | 	rsControl RSControlInterface, | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	controller metav1.Object, | 
					
						
							|  |  |  | 	selector labels.Selector, | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 	controllerKind schema.GroupVersionKind, | 
					
						
							|  |  |  | ) *ReplicaSetControllerRefManager { | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	return &ReplicaSetControllerRefManager{ | 
					
						
							|  |  |  | 		baseControllerRefManager: baseControllerRefManager{ | 
					
						
							|  |  |  | 			controller: controller, | 
					
						
							|  |  |  | 			selector:   selector, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		controllerKind: controllerKind, | 
					
						
							|  |  |  | 		rsControl:      rsControl, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | // ClaimReplicaSets tries to take ownership of a list of ReplicaSets.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // It will reconcile the following:
 | 
					
						
							|  |  |  | //   * Adopt orphans if the selector matches.
 | 
					
						
							|  |  |  | //   * Release owned objects if the selector no longer matches.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // A non-nil error is returned if some form of reconciliation was attemped and
 | 
					
						
							|  |  |  | // failed. Usually, controllers should try again later in case reconciliation
 | 
					
						
							|  |  |  | // is still needed.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // If the error is nil, either the reconciliation succeeded, or no
 | 
					
						
							|  |  |  | // reconciliation was necessary. The list of ReplicaSets that you now own is
 | 
					
						
							|  |  |  | // returned.
 | 
					
						
							|  |  |  | func (m *ReplicaSetControllerRefManager) ClaimReplicaSets(sets []*extensions.ReplicaSet) ([]*extensions.ReplicaSet, error) { | 
					
						
							|  |  |  | 	var claimed []*extensions.ReplicaSet | 
					
						
							|  |  |  | 	var errlist []error | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | 	match := func(obj metav1.Object) bool { | 
					
						
							|  |  |  | 		return m.selector.Matches(labels.Set(obj.GetLabels())) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	adopt := func(obj metav1.Object) error { | 
					
						
							|  |  |  | 		return m.AdoptReplicaSet(obj.(*extensions.ReplicaSet)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	release := func(obj metav1.Object) error { | 
					
						
							|  |  |  | 		return m.ReleaseReplicaSet(obj.(*extensions.ReplicaSet)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, rs := range sets { | 
					
						
							| 
									
										
										
										
											2017-02-24 08:23:59 +08:00
										 |  |  | 		ok, err := m.claimObject(rs, match, adopt, release) | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			errlist = append(errlist, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			claimed = append(claimed, rs) | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	return claimed, utilerrors.NewAggregate(errlist) | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AdoptReplicaSet sends a patch to take control of the ReplicaSet. It returns the error if
 | 
					
						
							|  |  |  | // the patching fails.
 | 
					
						
							|  |  |  | func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(replicaSet *extensions.ReplicaSet) error { | 
					
						
							|  |  |  | 	// we should not adopt any ReplicaSets if the Deployment is about to be deleted
 | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	if m.controller.GetDeletionTimestamp() != nil { | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 		return fmt.Errorf("cancel the adopt attempt for RS %s because the controller %v is being deleted", | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 			strings.Join([]string{replicaSet.Namespace, replicaSet.Name, string(replicaSet.UID)}, "_"), m.controller.GetName()) | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 	// Note that ValidateOwnerReferences() will reject this patch if another
 | 
					
						
							|  |  |  | 	// OwnerReference exists with controller=true.
 | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 	addControllerPatch := fmt.Sprintf( | 
					
						
							| 
									
										
										
										
											2017-03-03 02:49:38 +08:00
										 |  |  | 		`{"metadata":{"ownerReferences":[{"apiVersion":"%s","kind":"%s","name":"%s","uid":"%s","controller":true,"blockOwnerDeletion":true}],"uid":"%s"}}`, | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 		m.controllerKind.GroupVersion(), m.controllerKind.Kind, | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		m.controller.GetName(), m.controller.GetUID(), replicaSet.UID) | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 	return m.rsControl.PatchReplicaSet(replicaSet.Namespace, replicaSet.Name, []byte(addControllerPatch)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReleaseReplicaSet sends a patch to free the ReplicaSet from the control of the Deployment controller.
 | 
					
						
							|  |  |  | // It returns the error if the patching fails. 404 and 422 errors are ignored.
 | 
					
						
							|  |  |  | func (m *ReplicaSetControllerRefManager) ReleaseReplicaSet(replicaSet *extensions.ReplicaSet) error { | 
					
						
							|  |  |  | 	glog.V(2).Infof("patching ReplicaSet %s_%s to remove its controllerRef to %s/%s:%s", | 
					
						
							| 
									
										
										
										
											2017-02-17 00:53:34 +08:00
										 |  |  | 		replicaSet.Namespace, replicaSet.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.controller.GetName()) | 
					
						
							|  |  |  | 	deleteOwnerRefPatch := fmt.Sprintf(`{"metadata":{"ownerReferences":[{"$patch":"delete","uid":"%s"}],"uid":"%s"}}`, m.controller.GetUID(), replicaSet.UID) | 
					
						
							| 
									
										
										
										
											2016-10-27 14:58:20 +08:00
										 |  |  | 	err := m.rsControl.PatchReplicaSet(replicaSet.Namespace, replicaSet.Name, []byte(deleteOwnerRefPatch)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.IsNotFound(err) { | 
					
						
							|  |  |  | 			// If the ReplicaSet no longer exists, ignore it.
 | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if errors.IsInvalid(err) { | 
					
						
							|  |  |  | 			// Invalid error will be returned in two cases: 1. the ReplicaSet
 | 
					
						
							|  |  |  | 			// has no owner reference, 2. the uid of the ReplicaSet doesn't
 | 
					
						
							|  |  |  | 			// match, which means the ReplicaSet is deleted and then recreated.
 | 
					
						
							|  |  |  | 			// In both cases, the error can be ignored.
 | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } |