diff options
Diffstat (limited to 'vendor/k8s.io/kubernetes/pkg/controller')
5 files changed, 0 insertions, 1948 deletions
diff --git a/vendor/k8s.io/kubernetes/pkg/controller/client_builder.go b/vendor/k8s.io/kubernetes/pkg/controller/client_builder.go deleted file mode 100644 index 041717623..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/client_builder.go +++ /dev/null @@ -1,292 +0,0 @@ -/* -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" - "time" - - v1authenticationapi "k8s.io/api/authentication/v1" - "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/watch" - apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" - clientset "k8s.io/client-go/kubernetes" - v1authentication "k8s.io/client-go/kubernetes/typed/authentication/v1" - v1core "k8s.io/client-go/kubernetes/typed/core/v1" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/cache" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/serviceaccount" - - "github.com/golang/glog" -) - -// ControllerClientBuilder allows you to get clients and configs for controllers -type ControllerClientBuilder interface { - Config(name string) (*restclient.Config, error) - ConfigOrDie(name string) *restclient.Config - Client(name string) (clientset.Interface, error) - ClientOrDie(name string) clientset.Interface - ClientGoClient(name string) (clientset.Interface, error) - ClientGoClientOrDie(name string) clientset.Interface -} - -// SimpleControllerClientBuilder returns a fixed client with different user agents -type SimpleControllerClientBuilder struct { - // ClientConfig is a skeleton config to clone and use as the basis for each controller client - ClientConfig *restclient.Config -} - -func (b SimpleControllerClientBuilder) Config(name string) (*restclient.Config, error) { - clientConfig := *b.ClientConfig - return restclient.AddUserAgent(&clientConfig, name), nil -} - -func (b SimpleControllerClientBuilder) ConfigOrDie(name string) *restclient.Config { - clientConfig, err := b.Config(name) - if err != nil { - glog.Fatal(err) - } - return clientConfig -} - -func (b SimpleControllerClientBuilder) Client(name string) (clientset.Interface, error) { - clientConfig, err := b.Config(name) - if err != nil { - return nil, err - } - return clientset.NewForConfig(clientConfig) -} - -func (b SimpleControllerClientBuilder) ClientOrDie(name string) clientset.Interface { - client, err := b.Client(name) - if err != nil { - glog.Fatal(err) - } - return client -} - -func (b SimpleControllerClientBuilder) ClientGoClient(name string) (clientset.Interface, error) { - clientConfig, err := b.Config(name) - if err != nil { - return nil, err - } - return clientset.NewForConfig(clientConfig) -} - -func (b SimpleControllerClientBuilder) ClientGoClientOrDie(name string) clientset.Interface { - client, err := b.ClientGoClient(name) - if err != nil { - glog.Fatal(err) - } - return client -} - -// SAControllerClientBuilder is a ControllerClientBuilder that returns clients identifying as -// service accounts -type SAControllerClientBuilder struct { - // ClientConfig is a skeleton config to clone and use as the basis for each controller client - ClientConfig *restclient.Config - - // CoreClient is used to provision service accounts if needed and watch for their associated tokens - // to construct a controller client - CoreClient v1core.CoreV1Interface - - // AuthenticationClient is used to check API tokens to make sure they are valid before - // building a controller client from them - AuthenticationClient v1authentication.AuthenticationV1Interface - - // Namespace is the namespace used to host the service accounts that will back the - // controllers. It must be highly privileged namespace which normal users cannot inspect. - Namespace string -} - -// config returns a complete clientConfig for constructing clients. This is separate in anticipation of composition -// which means that not all clientsets are known here -func (b SAControllerClientBuilder) Config(name string) (*restclient.Config, error) { - sa, err := b.getOrCreateServiceAccount(name) - if err != nil { - return nil, err - } - - var clientConfig *restclient.Config - - lw := &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - options.FieldSelector = fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(v1.SecretTypeServiceAccountToken)}).String() - return b.CoreClient.Secrets(b.Namespace).List(options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - options.FieldSelector = fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(v1.SecretTypeServiceAccountToken)}).String() - return b.CoreClient.Secrets(b.Namespace).Watch(options) - }, - } - _, err = cache.ListWatchUntil(30*time.Second, lw, - func(event watch.Event) (bool, error) { - switch event.Type { - case watch.Deleted: - return false, nil - case watch.Error: - return false, fmt.Errorf("error watching") - - case watch.Added, watch.Modified: - secret, ok := event.Object.(*v1.Secret) - if !ok { - return false, fmt.Errorf("unexpected object type: %T", event.Object) - } - if !serviceaccount.IsServiceAccountToken(secret, sa) { - return false, nil - } - if len(secret.Data[v1.ServiceAccountTokenKey]) == 0 { - return false, nil - } - validConfig, valid, err := b.getAuthenticatedConfig(sa, string(secret.Data[v1.ServiceAccountTokenKey])) - if err != nil { - glog.Warningf("error validating API token for %s/%s in secret %s: %v", sa.Name, sa.Namespace, secret.Name, err) - // continue watching for good tokens - return false, nil - } - if !valid { - glog.Warningf("secret %s contained an invalid API token for %s/%s", secret.Name, sa.Name, sa.Namespace) - // try to delete the secret containing the invalid token - if err := b.CoreClient.Secrets(secret.Namespace).Delete(secret.Name, &metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) { - glog.Warningf("error deleting secret %s containing invalid API token for %s/%s: %v", secret.Name, sa.Name, sa.Namespace, err) - } - // continue watching for good tokens - return false, nil - } - clientConfig = validConfig - return true, nil - - default: - return false, fmt.Errorf("unexpected event type: %v", event.Type) - } - }) - if err != nil { - return nil, fmt.Errorf("unable to get token for service account: %v", err) - } - - return clientConfig, nil -} - -func (b SAControllerClientBuilder) getOrCreateServiceAccount(name string) (*v1.ServiceAccount, error) { - sa, err := b.CoreClient.ServiceAccounts(b.Namespace).Get(name, metav1.GetOptions{}) - if err == nil { - return sa, nil - } - if !apierrors.IsNotFound(err) { - return nil, err - } - - // Create the namespace if we can't verify it exists. - // Tolerate errors, since we don't know whether this component has namespace creation permissions. - if _, err := b.CoreClient.Namespaces().Get(b.Namespace, metav1.GetOptions{}); err != nil { - b.CoreClient.Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: b.Namespace}}) - } - - // Create the service account - sa, err = b.CoreClient.ServiceAccounts(b.Namespace).Create(&v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Namespace: b.Namespace, Name: name}}) - if apierrors.IsAlreadyExists(err) { - // If we're racing to init and someone else already created it, re-fetch - return b.CoreClient.ServiceAccounts(b.Namespace).Get(name, metav1.GetOptions{}) - } - return sa, err -} - -func (b SAControllerClientBuilder) getAuthenticatedConfig(sa *v1.ServiceAccount, token string) (*restclient.Config, bool, error) { - username := apiserverserviceaccount.MakeUsername(sa.Namespace, sa.Name) - - clientConfig := restclient.AnonymousClientConfig(b.ClientConfig) - clientConfig.BearerToken = token - restclient.AddUserAgent(clientConfig, username) - - // Try token review first - tokenReview := &v1authenticationapi.TokenReview{Spec: v1authenticationapi.TokenReviewSpec{Token: token}} - if tokenResult, err := b.AuthenticationClient.TokenReviews().Create(tokenReview); err == nil { - if !tokenResult.Status.Authenticated { - glog.Warningf("Token for %s/%s did not authenticate correctly", sa.Name, sa.Namespace) - return nil, false, nil - } - if tokenResult.Status.User.Username != username { - glog.Warningf("Token for %s/%s authenticated as unexpected username: %s", sa.Name, sa.Namespace, tokenResult.Status.User.Username) - return nil, false, nil - } - glog.V(4).Infof("Verified credential for %s/%s", sa.Name, sa.Namespace) - return clientConfig, true, nil - } - - // If we couldn't run the token review, the API might be disabled or we might not have permission. - // Try to make a request to /apis with the token. If we get a 401 we should consider the token invalid. - clientConfigCopy := *clientConfig - clientConfigCopy.NegotiatedSerializer = legacyscheme.Codecs - client, err := restclient.UnversionedRESTClientFor(&clientConfigCopy) - if err != nil { - return nil, false, err - } - err = client.Get().AbsPath("/apis").Do().Error() - if apierrors.IsUnauthorized(err) { - glog.Warningf("Token for %s/%s did not authenticate correctly: %v", sa.Name, sa.Namespace, err) - return nil, false, nil - } - - return clientConfig, true, nil -} - -func (b SAControllerClientBuilder) ConfigOrDie(name string) *restclient.Config { - clientConfig, err := b.Config(name) - if err != nil { - glog.Fatal(err) - } - return clientConfig -} - -func (b SAControllerClientBuilder) Client(name string) (clientset.Interface, error) { - clientConfig, err := b.Config(name) - if err != nil { - return nil, err - } - return clientset.NewForConfig(clientConfig) -} - -func (b SAControllerClientBuilder) ClientOrDie(name string) clientset.Interface { - client, err := b.Client(name) - if err != nil { - glog.Fatal(err) - } - return client -} - -func (b SAControllerClientBuilder) ClientGoClient(name string) (clientset.Interface, error) { - clientConfig, err := b.Config(name) - if err != nil { - return nil, err - } - return clientset.NewForConfig(clientConfig) -} - -func (b SAControllerClientBuilder) ClientGoClientOrDie(name string) clientset.Interface { - client, err := b.ClientGoClient(name) - if err != nil { - glog.Fatal(err) - } - return client -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go deleted file mode 100644 index 21d7aa302..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go +++ /dev/null @@ -1,502 +0,0 @@ -/* -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" - "sync" - - "github.com/golang/glog" - apps "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime/schema" - utilerrors "k8s.io/apimachinery/pkg/util/errors" -) - -type BaseControllerRefManager struct { - Controller metav1.Object - Selector labels.Selector - - canAdoptErr error - canAdoptOnce sync.Once - CanAdoptFunc func() error -} - -func (m *BaseControllerRefManager) CanAdopt() error { - m.canAdoptOnce.Do(func() { - if m.CanAdoptFunc != nil { - m.canAdoptErr = m.CanAdoptFunc() - } - }) - return m.canAdoptErr -} - -// ClaimObject tries to take ownership of an object for this controller. -// -// It will reconcile the following: -// * Adopt orphans if the match function returns true. -// * Release owned objects if the match function returns false. -// -// A non-nil error is returned if some form of reconciliation was attempted 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. -func (m *BaseControllerRefManager) ClaimObject(obj metav1.Object, match func(metav1.Object) bool, adopt, release func(metav1.Object) error) (bool, error) { - controllerRef := metav1.GetControllerOf(obj) - if controllerRef != nil { - if controllerRef.UID != m.Controller.GetUID() { - // Owned by someone else. Ignore. - return false, nil - } - if match(obj) { - // 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. - if m.Controller.GetDeletionTimestamp() != nil || !match(obj) { - // Ignore if we're being deleted or selector doesn't match. - return false, nil - } - if obj.GetDeletionTimestamp() != nil { - // Ignore if the object is being deleted - 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 -} - -type PodControllerRefManager struct { - BaseControllerRefManager - controllerKind schema.GroupVersionKind - podControl PodControlInterface -} - -// NewPodControllerRefManager returns a PodControllerRefManager that exposes -// methods to manage the controllerRef of pods. -// -// The CanAdopt() function can be used to perform a potentially expensive check -// (such as a live GET from the API server) prior to the first adoption. -// It will only be called (at most once) if an adoption is actually attempted. -// If CanAdopt() returns a non-nil error, all adoptions will fail. -// -// NOTE: Once CanAdopt() is called, it will not be called again by the same -// PodControllerRefManager instance. Create a new instance if it makes -// sense to check CanAdopt() again (e.g. in a different sync pass). -func NewPodControllerRefManager( - podControl PodControlInterface, - controller metav1.Object, - selector labels.Selector, - controllerKind schema.GroupVersionKind, - canAdopt func() error, -) *PodControllerRefManager { - return &PodControllerRefManager{ - BaseControllerRefManager: BaseControllerRefManager{ - Controller: controller, - Selector: selector, - CanAdoptFunc: canAdopt, - }, - controllerKind: controllerKind, - podControl: podControl, - } -} - -// 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. -// -// Optional: If one or more filters are specified, a Pod will only be claimed if -// all filters return true. -// -// A non-nil error is returned if some form of reconciliation was attempted 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. -func (m *PodControllerRefManager) ClaimPods(pods []*v1.Pod, filters ...func(*v1.Pod) bool) ([]*v1.Pod, error) { - var claimed []*v1.Pod - var errlist []error - - 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 - } - 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 { - ok, err := m.ClaimObject(pod, match, adopt, release) - if err != nil { - errlist = append(errlist, err) - continue - } - if ok { - claimed = append(claimed, pod) - } - } - return claimed, utilerrors.NewAggregate(errlist) -} - -// AdoptPod sends a patch to take control of the pod. It returns the error if -// the patching fails. -func (m *PodControllerRefManager) AdoptPod(pod *v1.Pod) error { - if err := m.CanAdopt(); err != nil { - return fmt.Errorf("can't adopt Pod %v/%v (%v): %v", pod.Namespace, pod.Name, pod.UID, err) - } - // Note that ValidateOwnerReferences() will reject this patch if another - // OwnerReference exists with controller=true. - addControllerPatch := fmt.Sprintf( - `{"metadata":{"ownerReferences":[{"apiVersion":"%s","kind":"%s","name":"%s","uid":"%s","controller":true,"blockOwnerDeletion":true}],"uid":"%s"}}`, - m.controllerKind.GroupVersion(), m.controllerKind.Kind, - m.Controller.GetName(), m.Controller.GetUID(), pod.UID) - 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. -func (m *PodControllerRefManager) ReleasePod(pod *v1.Pod) error { - glog.V(2).Infof("patching pod %s_%s to remove its controllerRef to %s/%s:%s", - 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) - 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 -} - -// 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 { - BaseControllerRefManager - controllerKind schema.GroupVersionKind - rsControl RSControlInterface -} - -// NewReplicaSetControllerRefManager returns a ReplicaSetControllerRefManager that exposes -// methods to manage the controllerRef of ReplicaSets. -// -// The CanAdopt() function can be used to perform a potentially expensive check -// (such as a live GET from the API server) prior to the first adoption. -// It will only be called (at most once) if an adoption is actually attempted. -// If CanAdopt() returns a non-nil error, all adoptions will fail. -// -// NOTE: Once CanAdopt() is called, it will not be called again by the same -// ReplicaSetControllerRefManager instance. Create a new instance if it -// makes sense to check CanAdopt() again (e.g. in a different sync pass). -func NewReplicaSetControllerRefManager( - rsControl RSControlInterface, - controller metav1.Object, - selector labels.Selector, - controllerKind schema.GroupVersionKind, - canAdopt func() error, -) *ReplicaSetControllerRefManager { - return &ReplicaSetControllerRefManager{ - BaseControllerRefManager: BaseControllerRefManager{ - Controller: controller, - Selector: selector, - CanAdoptFunc: canAdopt, - }, - controllerKind: controllerKind, - rsControl: rsControl, - } -} - -// 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 attempted 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 - - match := func(obj metav1.Object) bool { - return m.Selector.Matches(labels.Set(obj.GetLabels())) - } - 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 { - ok, err := m.ClaimObject(rs, match, adopt, release) - if err != nil { - errlist = append(errlist, err) - continue - } - if ok { - claimed = append(claimed, rs) - } - } - return claimed, utilerrors.NewAggregate(errlist) -} - -// AdoptReplicaSet sends a patch to take control of the ReplicaSet. It returns -// the error if the patching fails. -func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(rs *extensions.ReplicaSet) error { - if err := m.CanAdopt(); err != nil { - return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err) - } - // Note that ValidateOwnerReferences() will reject this patch if another - // OwnerReference exists with controller=true. - addControllerPatch := fmt.Sprintf( - `{"metadata":{"ownerReferences":[{"apiVersion":"%s","kind":"%s","name":"%s","uid":"%s","controller":true,"blockOwnerDeletion":true}],"uid":"%s"}}`, - m.controllerKind.GroupVersion(), m.controllerKind.Kind, - m.Controller.GetName(), m.Controller.GetUID(), rs.UID) - return m.rsControl.PatchReplicaSet(rs.Namespace, rs.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", - 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) - 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 -} - -// RecheckDeletionTimestamp returns a CanAdopt() function to recheck deletion. -// -// The CanAdopt() function calls getObject() to fetch the latest value, -// and denies adoption attempts if that object has a non-nil DeletionTimestamp. -func RecheckDeletionTimestamp(getObject func() (metav1.Object, error)) func() error { - return func() error { - obj, err := getObject() - if err != nil { - return fmt.Errorf("can't recheck DeletionTimestamp: %v", err) - } - if obj.GetDeletionTimestamp() != nil { - return fmt.Errorf("%v/%v has just been deleted at %v", obj.GetNamespace(), obj.GetName(), obj.GetDeletionTimestamp()) - } - return nil - } -} - -// ControllerRevisionControllerRefManager is used to manage controllerRef of ControllerRevisions. -// Three methods are defined on this object 1: Classify 2: AdoptControllerRevision and -// 3: ReleaseControllerRevision which are used to classify the ControllerRevisions into appropriate -// categories and accordingly adopt or release them. See comments on these functions -// for more details. -type ControllerRevisionControllerRefManager struct { - BaseControllerRefManager - controllerKind schema.GroupVersionKind - crControl ControllerRevisionControlInterface -} - -// NewControllerRevisionControllerRefManager returns a ControllerRevisionControllerRefManager that exposes -// methods to manage the controllerRef of ControllerRevisions. -// -// The canAdopt() function can be used to perform a potentially expensive check -// (such as a live GET from the API server) prior to the first adoption. -// It will only be called (at most once) if an adoption is actually attempted. -// If canAdopt() returns a non-nil error, all adoptions will fail. -// -// NOTE: Once canAdopt() is called, it will not be called again by the same -// ControllerRevisionControllerRefManager instance. Create a new instance if it -// makes sense to check canAdopt() again (e.g. in a different sync pass). -func NewControllerRevisionControllerRefManager( - crControl ControllerRevisionControlInterface, - controller metav1.Object, - selector labels.Selector, - controllerKind schema.GroupVersionKind, - canAdopt func() error, -) *ControllerRevisionControllerRefManager { - return &ControllerRevisionControllerRefManager{ - BaseControllerRefManager: BaseControllerRefManager{ - Controller: controller, - Selector: selector, - CanAdoptFunc: canAdopt, - }, - controllerKind: controllerKind, - crControl: crControl, - } -} - -// ClaimControllerRevisions tries to take ownership of a list of ControllerRevisions. -// -// 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 attempted 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 ControllerRevisions that you now own is -// returned. -func (m *ControllerRevisionControllerRefManager) ClaimControllerRevisions(histories []*apps.ControllerRevision) ([]*apps.ControllerRevision, error) { - var claimed []*apps.ControllerRevision - var errlist []error - - match := func(obj metav1.Object) bool { - return m.Selector.Matches(labels.Set(obj.GetLabels())) - } - adopt := func(obj metav1.Object) error { - return m.AdoptControllerRevision(obj.(*apps.ControllerRevision)) - } - release := func(obj metav1.Object) error { - return m.ReleaseControllerRevision(obj.(*apps.ControllerRevision)) - } - - for _, h := range histories { - ok, err := m.ClaimObject(h, match, adopt, release) - if err != nil { - errlist = append(errlist, err) - continue - } - if ok { - claimed = append(claimed, h) - } - } - return claimed, utilerrors.NewAggregate(errlist) -} - -// AdoptControllerRevision sends a patch to take control of the ControllerRevision. It returns the error if -// the patching fails. -func (m *ControllerRevisionControllerRefManager) AdoptControllerRevision(history *apps.ControllerRevision) error { - if err := m.CanAdopt(); err != nil { - return fmt.Errorf("can't adopt ControllerRevision %v/%v (%v): %v", history.Namespace, history.Name, history.UID, err) - } - // Note that ValidateOwnerReferences() will reject this patch if another - // OwnerReference exists with controller=true. - addControllerPatch := fmt.Sprintf( - `{"metadata":{"ownerReferences":[{"apiVersion":"%s","kind":"%s","name":"%s","uid":"%s","controller":true,"blockOwnerDeletion":true}],"uid":"%s"}}`, - m.controllerKind.GroupVersion(), m.controllerKind.Kind, - m.Controller.GetName(), m.Controller.GetUID(), history.UID) - return m.crControl.PatchControllerRevision(history.Namespace, history.Name, []byte(addControllerPatch)) -} - -// ReleaseControllerRevision sends a patch to free the ControllerRevision from the control of its controller. -// It returns the error if the patching fails. 404 and 422 errors are ignored. -func (m *ControllerRevisionControllerRefManager) ReleaseControllerRevision(history *apps.ControllerRevision) error { - glog.V(2).Infof("patching ControllerRevision %s_%s to remove its controllerRef to %s/%s:%s", - history.Namespace, history.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName()) - deleteOwnerRefPatch := fmt.Sprintf(`{"metadata":{"ownerReferences":[{"$patch":"delete","uid":"%s"}],"uid":"%s"}}`, m.Controller.GetUID(), history.UID) - err := m.crControl.PatchControllerRevision(history.Namespace, history.Name, []byte(deleteOwnerRefPatch)) - if err != nil { - if errors.IsNotFound(err) { - // If the ControllerRevision no longer exists, ignore it. - return nil - } - if errors.IsInvalid(err) { - // Invalid error will be returned in two cases: 1. the ControllerRevision - // has no owner reference, 2. the uid of the ControllerRevision doesn't - // match, which means the ControllerRevision is deleted and then recreated. - // In both cases, the error can be ignored. - return nil - } - } - return err -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go deleted file mode 100644 index d7d755ebf..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go +++ /dev/null @@ -1,1043 +0,0 @@ -/* -Copyright 2014 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 ( - "encoding/binary" - "encoding/json" - "fmt" - "hash/fnv" - "sync" - "sync/atomic" - "time" - - "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/clock" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/tools/record" - "k8s.io/client-go/util/integer" - clientretry "k8s.io/client-go/util/retry" - podutil "k8s.io/kubernetes/pkg/api/v1/pod" - _ "k8s.io/kubernetes/pkg/apis/core/install" - "k8s.io/kubernetes/pkg/apis/core/validation" - hashutil "k8s.io/kubernetes/pkg/util/hash" - taintutils "k8s.io/kubernetes/pkg/util/taints" - - "github.com/golang/glog" -) - -const ( - // If a watch drops a delete event for a pod, it'll take this long - // before a dormant controller waiting for those packets is woken up anyway. It is - // specifically targeted at the case where some problem prevents an update - // of expectations, without it the controller could stay asleep forever. This should - // be set based on the expected latency of watch events. - // - // Currently a controller can service (create *and* observe the watch events for said - // creation) about 10 pods a second, so it takes about 1 min to service - // 500 pods. Just creation is limited to 20qps, and watching happens with ~10-30s - // latency/pod at the scale of 3000 pods over 100 nodes. - ExpectationsTimeout = 5 * time.Minute - // When batching pod creates, SlowStartInitialBatchSize is the size of the - // initial batch. The size of each successive batch is twice the size of - // the previous batch. For example, for a value of 1, batch sizes would be - // 1, 2, 4, 8, ... and for a value of 10, batch sizes would be - // 10, 20, 40, 80, ... Setting the value higher means that quota denials - // will result in more doomed API calls and associated event spam. Setting - // the value lower will result in more API call round trip periods for - // large batches. - // - // Given a number of pods to start "N": - // The number of doomed calls per sync once quota is exceeded is given by: - // min(N,SlowStartInitialBatchSize) - // The number of batches is given by: - // 1+floor(log_2(ceil(N/SlowStartInitialBatchSize))) - SlowStartInitialBatchSize = 1 -) - -var UpdateTaintBackoff = wait.Backoff{ - Steps: 5, - Duration: 100 * time.Millisecond, - Jitter: 1.0, -} - -var ( - KeyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc -) - -type ResyncPeriodFunc func() time.Duration - -// Returns 0 for resyncPeriod in case resyncing is not needed. -func NoResyncPeriodFunc() time.Duration { - return 0 -} - -// StaticResyncPeriodFunc returns the resync period specified -func StaticResyncPeriodFunc(resyncPeriod time.Duration) ResyncPeriodFunc { - return func() time.Duration { - return resyncPeriod - } -} - -// Expectations are a way for controllers to tell the controller manager what they expect. eg: -// ControllerExpectations: { -// controller1: expects 2 adds in 2 minutes -// controller2: expects 2 dels in 2 minutes -// controller3: expects -1 adds in 2 minutes => controller3's expectations have already been met -// } -// -// Implementation: -// ControlleeExpectation = pair of atomic counters to track controllee's creation/deletion -// ControllerExpectationsStore = TTLStore + a ControlleeExpectation per controller -// -// * Once set expectations can only be lowered -// * A controller isn't synced till its expectations are either fulfilled, or expire -// * Controllers that don't set expectations will get woken up for every matching controllee - -// ExpKeyFunc to parse out the key from a ControlleeExpectation -var ExpKeyFunc = func(obj interface{}) (string, error) { - if e, ok := obj.(*ControlleeExpectations); ok { - return e.key, nil - } - return "", fmt.Errorf("Could not find key for obj %#v", obj) -} - -// ControllerExpectationsInterface is an interface that allows users to set and wait on expectations. -// Only abstracted out for testing. -// Warning: if using KeyFunc it is not safe to use a single ControllerExpectationsInterface with different -// types of controllers, because the keys might conflict across types. -type ControllerExpectationsInterface interface { - GetExpectations(controllerKey string) (*ControlleeExpectations, bool, error) - SatisfiedExpectations(controllerKey string) bool - DeleteExpectations(controllerKey string) - SetExpectations(controllerKey string, add, del int) error - ExpectCreations(controllerKey string, adds int) error - ExpectDeletions(controllerKey string, dels int) error - CreationObserved(controllerKey string) - DeletionObserved(controllerKey string) - RaiseExpectations(controllerKey string, add, del int) - LowerExpectations(controllerKey string, add, del int) -} - -// ControllerExpectations is a cache mapping controllers to what they expect to see before being woken up for a sync. -type ControllerExpectations struct { - cache.Store -} - -// GetExpectations returns the ControlleeExpectations of the given controller. -func (r *ControllerExpectations) GetExpectations(controllerKey string) (*ControlleeExpectations, bool, error) { - if exp, exists, err := r.GetByKey(controllerKey); err == nil && exists { - return exp.(*ControlleeExpectations), true, nil - } else { - return nil, false, err - } -} - -// DeleteExpectations deletes the expectations of the given controller from the TTLStore. -func (r *ControllerExpectations) DeleteExpectations(controllerKey string) { - if exp, exists, err := r.GetByKey(controllerKey); err == nil && exists { - if err := r.Delete(exp); err != nil { - glog.V(2).Infof("Error deleting expectations for controller %v: %v", controllerKey, err) - } - } -} - -// SatisfiedExpectations returns true if the required adds/dels for the given controller have been observed. -// Add/del counts are established by the controller at sync time, and updated as controllees are observed by the controller -// manager. -func (r *ControllerExpectations) SatisfiedExpectations(controllerKey string) bool { - if exp, exists, err := r.GetExpectations(controllerKey); exists { - if exp.Fulfilled() { - glog.V(4).Infof("Controller expectations fulfilled %#v", exp) - return true - } else if exp.isExpired() { - glog.V(4).Infof("Controller expectations expired %#v", exp) - return true - } else { - glog.V(4).Infof("Controller still waiting on expectations %#v", exp) - return false - } - } else if err != nil { - glog.V(2).Infof("Error encountered while checking expectations %#v, forcing sync", err) - } else { - // When a new controller is created, it doesn't have expectations. - // When it doesn't see expected watch events for > TTL, the expectations expire. - // - In this case it wakes up, creates/deletes controllees, and sets expectations again. - // When it has satisfied expectations and no controllees need to be created/destroyed > TTL, the expectations expire. - // - In this case it continues without setting expectations till it needs to create/delete controllees. - glog.V(4).Infof("Controller %v either never recorded expectations, or the ttl expired.", controllerKey) - } - // Trigger a sync if we either encountered and error (which shouldn't happen since we're - // getting from local store) or this controller hasn't established expectations. - return true -} - -// TODO: Extend ExpirationCache to support explicit expiration. -// TODO: Make this possible to disable in tests. -// TODO: Support injection of clock. -func (exp *ControlleeExpectations) isExpired() bool { - return clock.RealClock{}.Since(exp.timestamp) > ExpectationsTimeout -} - -// SetExpectations registers new expectations for the given controller. Forgets existing expectations. -func (r *ControllerExpectations) SetExpectations(controllerKey string, add, del int) error { - exp := &ControlleeExpectations{add: int64(add), del: int64(del), key: controllerKey, timestamp: clock.RealClock{}.Now()} - glog.V(4).Infof("Setting expectations %#v", exp) - return r.Add(exp) -} - -func (r *ControllerExpectations) ExpectCreations(controllerKey string, adds int) error { - return r.SetExpectations(controllerKey, adds, 0) -} - -func (r *ControllerExpectations) ExpectDeletions(controllerKey string, dels int) error { - return r.SetExpectations(controllerKey, 0, dels) -} - -// Decrements the expectation counts of the given controller. -func (r *ControllerExpectations) LowerExpectations(controllerKey string, add, del int) { - if exp, exists, err := r.GetExpectations(controllerKey); err == nil && exists { - exp.Add(int64(-add), int64(-del)) - // The expectations might've been modified since the update on the previous line. - glog.V(4).Infof("Lowered expectations %#v", exp) - } -} - -// Increments the expectation counts of the given controller. -func (r *ControllerExpectations) RaiseExpectations(controllerKey string, add, del int) { - if exp, exists, err := r.GetExpectations(controllerKey); err == nil && exists { - exp.Add(int64(add), int64(del)) - // The expectations might've been modified since the update on the previous line. - glog.V(4).Infof("Raised expectations %#v", exp) - } -} - -// CreationObserved atomically decrements the `add` expectation count of the given controller. -func (r *ControllerExpectations) CreationObserved(controllerKey string) { - r.LowerExpectations(controllerKey, 1, 0) -} - -// DeletionObserved atomically decrements the `del` expectation count of the given controller. -func (r *ControllerExpectations) DeletionObserved(controllerKey string) { - r.LowerExpectations(controllerKey, 0, 1) -} - -// Expectations are either fulfilled, or expire naturally. -type Expectations interface { - Fulfilled() bool -} - -// ControlleeExpectations track controllee creates/deletes. -type ControlleeExpectations struct { - // Important: Since these two int64 fields are using sync/atomic, they have to be at the top of the struct due to a bug on 32-bit platforms - // See: https://golang.org/pkg/sync/atomic/ for more information - add int64 - del int64 - key string - timestamp time.Time -} - -// Add increments the add and del counters. -func (e *ControlleeExpectations) Add(add, del int64) { - atomic.AddInt64(&e.add, add) - atomic.AddInt64(&e.del, del) -} - -// Fulfilled returns true if this expectation has been fulfilled. -func (e *ControlleeExpectations) Fulfilled() bool { - // TODO: think about why this line being atomic doesn't matter - return atomic.LoadInt64(&e.add) <= 0 && atomic.LoadInt64(&e.del) <= 0 -} - -// GetExpectations returns the add and del expectations of the controllee. -func (e *ControlleeExpectations) GetExpectations() (int64, int64) { - return atomic.LoadInt64(&e.add), atomic.LoadInt64(&e.del) -} - -// NewControllerExpectations returns a store for ControllerExpectations. -func NewControllerExpectations() *ControllerExpectations { - return &ControllerExpectations{cache.NewStore(ExpKeyFunc)} -} - -// UIDSetKeyFunc to parse out the key from a UIDSet. -var UIDSetKeyFunc = func(obj interface{}) (string, error) { - if u, ok := obj.(*UIDSet); ok { - return u.key, nil - } - return "", fmt.Errorf("Could not find key for obj %#v", obj) -} - -// UIDSet holds a key and a set of UIDs. Used by the -// UIDTrackingControllerExpectations to remember which UID it has seen/still -// waiting for. -type UIDSet struct { - sets.String - key string -} - -// UIDTrackingControllerExpectations tracks the UID of the pods it deletes. -// This cache is needed over plain old expectations to safely handle graceful -// deletion. The desired behavior is to treat an update that sets the -// DeletionTimestamp on an object as a delete. To do so consistently, one needs -// to remember the expected deletes so they aren't double counted. -// TODO: Track creates as well (#22599) -type UIDTrackingControllerExpectations struct { - ControllerExpectationsInterface - // TODO: There is a much nicer way to do this that involves a single store, - // a lock per entry, and a ControlleeExpectationsInterface type. - uidStoreLock sync.Mutex - // Store used for the UIDs associated with any expectation tracked via the - // ControllerExpectationsInterface. - uidStore cache.Store -} - -// GetUIDs is a convenience method to avoid exposing the set of expected uids. -// The returned set is not thread safe, all modifications must be made holding -// the uidStoreLock. -func (u *UIDTrackingControllerExpectations) GetUIDs(controllerKey string) sets.String { - if uid, exists, err := u.uidStore.GetByKey(controllerKey); err == nil && exists { - return uid.(*UIDSet).String - } - return nil -} - -// ExpectDeletions records expectations for the given deleteKeys, against the given controller. -func (u *UIDTrackingControllerExpectations) ExpectDeletions(rcKey string, deletedKeys []string) error { - u.uidStoreLock.Lock() - defer u.uidStoreLock.Unlock() - - if existing := u.GetUIDs(rcKey); existing != nil && existing.Len() != 0 { - glog.Errorf("Clobbering existing delete keys: %+v", existing) - } - expectedUIDs := sets.NewString() - for _, k := range deletedKeys { - expectedUIDs.Insert(k) - } - glog.V(4).Infof("Controller %v waiting on deletions for: %+v", rcKey, deletedKeys) - if err := u.uidStore.Add(&UIDSet{expectedUIDs, rcKey}); err != nil { - return err - } - return u.ControllerExpectationsInterface.ExpectDeletions(rcKey, expectedUIDs.Len()) -} - -// DeletionObserved records the given deleteKey as a deletion, for the given rc. -func (u *UIDTrackingControllerExpectations) DeletionObserved(rcKey, deleteKey string) { - u.uidStoreLock.Lock() - defer u.uidStoreLock.Unlock() - - uids := u.GetUIDs(rcKey) - if uids != nil && uids.Has(deleteKey) { - glog.V(4).Infof("Controller %v received delete for pod %v", rcKey, deleteKey) - u.ControllerExpectationsInterface.DeletionObserved(rcKey) - uids.Delete(deleteKey) - } -} - -// DeleteExpectations deletes the UID set and invokes DeleteExpectations on the -// underlying ControllerExpectationsInterface. -func (u *UIDTrackingControllerExpectations) DeleteExpectations(rcKey string) { - u.uidStoreLock.Lock() - defer u.uidStoreLock.Unlock() - - u.ControllerExpectationsInterface.DeleteExpectations(rcKey) - if uidExp, exists, err := u.uidStore.GetByKey(rcKey); err == nil && exists { - if err := u.uidStore.Delete(uidExp); err != nil { - glog.V(2).Infof("Error deleting uid expectations for controller %v: %v", rcKey, err) - } - } -} - -// NewUIDTrackingControllerExpectations returns a wrapper around -// ControllerExpectations that is aware of deleteKeys. -func NewUIDTrackingControllerExpectations(ce ControllerExpectationsInterface) *UIDTrackingControllerExpectations { - return &UIDTrackingControllerExpectations{ControllerExpectationsInterface: ce, uidStore: cache.NewStore(UIDSetKeyFunc)} -} - -// Reasons for pod events -const ( - // FailedCreatePodReason is added in an event and in a replica set condition - // when a pod for a replica set is failed to be created. - FailedCreatePodReason = "FailedCreate" - // SuccessfulCreatePodReason is added in an event when a pod for a replica set - // is successfully created. - SuccessfulCreatePodReason = "SuccessfulCreate" - // FailedDeletePodReason is added in an event and in a replica set condition - // when a pod for a replica set is failed to be deleted. - FailedDeletePodReason = "FailedDelete" - // SuccessfulDeletePodReason is added in an event when a pod for a replica set - // is successfully deleted. - SuccessfulDeletePodReason = "SuccessfulDelete" -) - -// RSControlInterface is an interface that knows how to add or delete -// ReplicaSets, as well as increment or decrement them. It is used -// by the deployment controller to ease testing of actions that it takes. -type RSControlInterface interface { - PatchReplicaSet(namespace, name string, data []byte) error -} - -// RealRSControl is the default implementation of RSControllerInterface. -type RealRSControl struct { - KubeClient clientset.Interface - Recorder record.EventRecorder -} - -var _ RSControlInterface = &RealRSControl{} - -func (r RealRSControl) PatchReplicaSet(namespace, name string, data []byte) error { - _, err := r.KubeClient.ExtensionsV1beta1().ReplicaSets(namespace).Patch(name, types.StrategicMergePatchType, data) - return err -} - -// TODO: merge the controller revision interface in controller_history.go with this one -// ControllerRevisionControlInterface is an interface that knows how to patch -// ControllerRevisions, as well as increment or decrement them. It is used -// by the daemonset controller to ease testing of actions that it takes. -type ControllerRevisionControlInterface interface { - PatchControllerRevision(namespace, name string, data []byte) error -} - -// RealControllerRevisionControl is the default implementation of ControllerRevisionControlInterface. -type RealControllerRevisionControl struct { - KubeClient clientset.Interface -} - -var _ ControllerRevisionControlInterface = &RealControllerRevisionControl{} - -func (r RealControllerRevisionControl) PatchControllerRevision(namespace, name string, data []byte) error { - _, err := r.KubeClient.AppsV1beta1().ControllerRevisions(namespace).Patch(name, types.StrategicMergePatchType, data) - return err -} - -// PodControlInterface is an interface that knows how to add or delete pods -// created as an interface to allow testing. -type PodControlInterface interface { - // CreatePods creates new pods according to the spec. - CreatePods(namespace string, template *v1.PodTemplateSpec, object runtime.Object) error - // CreatePodsOnNode creates a new pod according to the spec on the specified node, - // and sets the ControllerRef. - CreatePodsOnNode(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error - // CreatePodsWithControllerRef creates new pods according to the spec, and sets object as the pod's controller. - CreatePodsWithControllerRef(namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error - // DeletePod deletes the pod identified by podID. - DeletePod(namespace string, podID string, object runtime.Object) error - // PatchPod patches the pod. - PatchPod(namespace, name string, data []byte) error -} - -// RealPodControl is the default implementation of PodControlInterface. -type RealPodControl struct { - KubeClient clientset.Interface - Recorder record.EventRecorder -} - -var _ PodControlInterface = &RealPodControl{} - -func getPodsLabelSet(template *v1.PodTemplateSpec) labels.Set { - desiredLabels := make(labels.Set) - for k, v := range template.Labels { - desiredLabels[k] = v - } - return desiredLabels -} - -func getPodsFinalizers(template *v1.PodTemplateSpec) []string { - desiredFinalizers := make([]string, len(template.Finalizers)) - copy(desiredFinalizers, template.Finalizers) - return desiredFinalizers -} - -func getPodsAnnotationSet(template *v1.PodTemplateSpec) labels.Set { - desiredAnnotations := make(labels.Set) - for k, v := range template.Annotations { - desiredAnnotations[k] = v - } - return desiredAnnotations -} - -func getPodsPrefix(controllerName string) string { - // use the dash (if the name isn't too long) to make the pod name a bit prettier - prefix := fmt.Sprintf("%s-", controllerName) - if len(validation.ValidatePodName(prefix, true)) != 0 { - prefix = controllerName - } - return prefix -} - -func validateControllerRef(controllerRef *metav1.OwnerReference) error { - if controllerRef == nil { - return fmt.Errorf("controllerRef is nil") - } - if len(controllerRef.APIVersion) == 0 { - return fmt.Errorf("controllerRef has empty APIVersion") - } - if len(controllerRef.Kind) == 0 { - return fmt.Errorf("controllerRef has empty Kind") - } - if controllerRef.Controller == nil || *controllerRef.Controller != true { - return fmt.Errorf("controllerRef.Controller is not set to true") - } - if controllerRef.BlockOwnerDeletion == nil || *controllerRef.BlockOwnerDeletion != true { - return fmt.Errorf("controllerRef.BlockOwnerDeletion is not set") - } - return nil -} - -func (r RealPodControl) CreatePods(namespace string, template *v1.PodTemplateSpec, object runtime.Object) error { - return r.createPods("", namespace, template, object, nil) -} - -func (r RealPodControl) CreatePodsWithControllerRef(namespace string, template *v1.PodTemplateSpec, controllerObject runtime.Object, controllerRef *metav1.OwnerReference) error { - if err := validateControllerRef(controllerRef); err != nil { - return err - } - return r.createPods("", namespace, template, controllerObject, controllerRef) -} - -func (r RealPodControl) CreatePodsOnNode(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error { - if err := validateControllerRef(controllerRef); err != nil { - return err - } - return r.createPods(nodeName, namespace, template, object, controllerRef) -} - -func (r RealPodControl) PatchPod(namespace, name string, data []byte) error { - _, err := r.KubeClient.CoreV1().Pods(namespace).Patch(name, types.StrategicMergePatchType, data) - return err -} - -func GetPodFromTemplate(template *v1.PodTemplateSpec, parentObject runtime.Object, controllerRef *metav1.OwnerReference) (*v1.Pod, error) { - desiredLabels := getPodsLabelSet(template) - desiredFinalizers := getPodsFinalizers(template) - desiredAnnotations := getPodsAnnotationSet(template) - accessor, err := meta.Accessor(parentObject) - if err != nil { - return nil, fmt.Errorf("parentObject does not have ObjectMeta, %v", err) - } - prefix := getPodsPrefix(accessor.GetName()) - - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: desiredLabels, - Annotations: desiredAnnotations, - GenerateName: prefix, - Finalizers: desiredFinalizers, - }, - } - if controllerRef != nil { - pod.OwnerReferences = append(pod.OwnerReferences, *controllerRef) - } - pod.Spec = *template.Spec.DeepCopy() - return pod, nil -} - -func (r RealPodControl) createPods(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error { - pod, err := GetPodFromTemplate(template, object, controllerRef) - if err != nil { - return err - } - if len(nodeName) != 0 { - pod.Spec.NodeName = nodeName - } - if labels.Set(pod.Labels).AsSelectorPreValidated().Empty() { - return fmt.Errorf("unable to create pods, no labels") - } - if newPod, err := r.KubeClient.CoreV1().Pods(namespace).Create(pod); err != nil { - r.Recorder.Eventf(object, v1.EventTypeWarning, FailedCreatePodReason, "Error creating: %v", err) - return err - } else { - accessor, err := meta.Accessor(object) - if err != nil { - glog.Errorf("parentObject does not have ObjectMeta, %v", err) - return nil - } - glog.V(4).Infof("Controller %v created pod %v", accessor.GetName(), newPod.Name) - r.Recorder.Eventf(object, v1.EventTypeNormal, SuccessfulCreatePodReason, "Created pod: %v", newPod.Name) - } - return nil -} - -func (r RealPodControl) DeletePod(namespace string, podID string, object runtime.Object) error { - accessor, err := meta.Accessor(object) - if err != nil { - return fmt.Errorf("object does not have ObjectMeta, %v", err) - } - glog.V(2).Infof("Controller %v deleting pod %v/%v", accessor.GetName(), namespace, podID) - if err := r.KubeClient.CoreV1().Pods(namespace).Delete(podID, nil); err != nil { - r.Recorder.Eventf(object, v1.EventTypeWarning, FailedDeletePodReason, "Error deleting: %v", err) - return fmt.Errorf("unable to delete pods: %v", err) - } else { - r.Recorder.Eventf(object, v1.EventTypeNormal, SuccessfulDeletePodReason, "Deleted pod: %v", podID) - } - return nil -} - -type FakePodControl struct { - sync.Mutex - Templates []v1.PodTemplateSpec - ControllerRefs []metav1.OwnerReference - DeletePodName []string - Patches [][]byte - Err error - CreateLimit int - CreateCallCount int -} - -var _ PodControlInterface = &FakePodControl{} - -func (f *FakePodControl) PatchPod(namespace, name string, data []byte) error { - f.Lock() - defer f.Unlock() - f.Patches = append(f.Patches, data) - if f.Err != nil { - return f.Err - } - return nil -} - -func (f *FakePodControl) CreatePods(namespace string, spec *v1.PodTemplateSpec, object runtime.Object) error { - f.Lock() - defer f.Unlock() - f.CreateCallCount++ - if f.CreateLimit != 0 && f.CreateCallCount > f.CreateLimit { - return fmt.Errorf("Not creating pod, limit %d already reached (create call %d)", f.CreateLimit, f.CreateCallCount) - } - f.Templates = append(f.Templates, *spec) - if f.Err != nil { - return f.Err - } - return nil -} - -func (f *FakePodControl) CreatePodsWithControllerRef(namespace string, spec *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error { - f.Lock() - defer f.Unlock() - f.CreateCallCount++ - if f.CreateLimit != 0 && f.CreateCallCount > f.CreateLimit { - return fmt.Errorf("Not creating pod, limit %d already reached (create call %d)", f.CreateLimit, f.CreateCallCount) - } - f.Templates = append(f.Templates, *spec) - f.ControllerRefs = append(f.ControllerRefs, *controllerRef) - if f.Err != nil { - return f.Err - } - return nil -} - -func (f *FakePodControl) CreatePodsOnNode(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error { - f.Lock() - defer f.Unlock() - f.CreateCallCount++ - if f.CreateLimit != 0 && f.CreateCallCount > f.CreateLimit { - return fmt.Errorf("Not creating pod, limit %d already reached (create call %d)", f.CreateLimit, f.CreateCallCount) - } - f.Templates = append(f.Templates, *template) - f.ControllerRefs = append(f.ControllerRefs, *controllerRef) - if f.Err != nil { - return f.Err - } - return nil -} - -func (f *FakePodControl) DeletePod(namespace string, podID string, object runtime.Object) error { - f.Lock() - defer f.Unlock() - f.DeletePodName = append(f.DeletePodName, podID) - if f.Err != nil { - return f.Err - } - return nil -} - -func (f *FakePodControl) Clear() { - f.Lock() - defer f.Unlock() - f.DeletePodName = []string{} - f.Templates = []v1.PodTemplateSpec{} - f.ControllerRefs = []metav1.OwnerReference{} - f.Patches = [][]byte{} - f.CreateLimit = 0 - f.CreateCallCount = 0 -} - -// ByLogging allows custom sorting of pods so the best one can be picked for getting its logs. -type ByLogging []*v1.Pod - -func (s ByLogging) Len() int { return len(s) } -func (s ByLogging) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func (s ByLogging) Less(i, j int) bool { - // 1. assigned < unassigned - if s[i].Spec.NodeName != s[j].Spec.NodeName && (len(s[i].Spec.NodeName) == 0 || len(s[j].Spec.NodeName) == 0) { - return len(s[i].Spec.NodeName) > 0 - } - // 2. PodRunning < PodUnknown < PodPending - m := map[v1.PodPhase]int{v1.PodRunning: 0, v1.PodUnknown: 1, v1.PodPending: 2} - if m[s[i].Status.Phase] != m[s[j].Status.Phase] { - return m[s[i].Status.Phase] < m[s[j].Status.Phase] - } - // 3. ready < not ready - if podutil.IsPodReady(s[i]) != podutil.IsPodReady(s[j]) { - return podutil.IsPodReady(s[i]) - } - // TODO: take availability into account when we push minReadySeconds information from deployment into pods, - // see https://github.com/kubernetes/kubernetes/issues/22065 - // 4. Been ready for more time < less time < empty time - if podutil.IsPodReady(s[i]) && podutil.IsPodReady(s[j]) && !podReadyTime(s[i]).Equal(podReadyTime(s[j])) { - return afterOrZero(podReadyTime(s[j]), podReadyTime(s[i])) - } - // 5. Pods with containers with higher restart counts < lower restart counts - if maxContainerRestarts(s[i]) != maxContainerRestarts(s[j]) { - return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j]) - } - // 6. older pods < newer pods < empty timestamp pods - if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) { - return afterOrZero(&s[j].CreationTimestamp, &s[i].CreationTimestamp) - } - return false -} - -// ActivePods type allows custom sorting of pods so a controller can pick the best ones to delete. -type ActivePods []*v1.Pod - -func (s ActivePods) Len() int { return len(s) } -func (s ActivePods) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func (s ActivePods) Less(i, j int) bool { - // 1. Unassigned < assigned - // If only one of the pods is unassigned, the unassigned one is smaller - if s[i].Spec.NodeName != s[j].Spec.NodeName && (len(s[i].Spec.NodeName) == 0 || len(s[j].Spec.NodeName) == 0) { - return len(s[i].Spec.NodeName) == 0 - } - // 2. PodPending < PodUnknown < PodRunning - m := map[v1.PodPhase]int{v1.PodPending: 0, v1.PodUnknown: 1, v1.PodRunning: 2} - if m[s[i].Status.Phase] != m[s[j].Status.Phase] { - return m[s[i].Status.Phase] < m[s[j].Status.Phase] - } - // 3. Not ready < ready - // If only one of the pods is not ready, the not ready one is smaller - if podutil.IsPodReady(s[i]) != podutil.IsPodReady(s[j]) { - return !podutil.IsPodReady(s[i]) - } - // TODO: take availability into account when we push minReadySeconds information from deployment into pods, - // see https://github.com/kubernetes/kubernetes/issues/22065 - // 4. Been ready for empty time < less time < more time - // If both pods are ready, the latest ready one is smaller - if podutil.IsPodReady(s[i]) && podutil.IsPodReady(s[j]) && !podReadyTime(s[i]).Equal(podReadyTime(s[j])) { - return afterOrZero(podReadyTime(s[i]), podReadyTime(s[j])) - } - // 5. Pods with containers with higher restart counts < lower restart counts - if maxContainerRestarts(s[i]) != maxContainerRestarts(s[j]) { - return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j]) - } - // 6. Empty creation time pods < newer pods < older pods - if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) { - return afterOrZero(&s[i].CreationTimestamp, &s[j].CreationTimestamp) - } - return false -} - -// afterOrZero checks if time t1 is after time t2; if one of them -// is zero, the zero time is seen as after non-zero time. -func afterOrZero(t1, t2 *metav1.Time) bool { - if t1.Time.IsZero() || t2.Time.IsZero() { - return t1.Time.IsZero() - } - return t1.After(t2.Time) -} - -func podReadyTime(pod *v1.Pod) *metav1.Time { - if podutil.IsPodReady(pod) { - for _, c := range pod.Status.Conditions { - // we only care about pod ready conditions - if c.Type == v1.PodReady && c.Status == v1.ConditionTrue { - return &c.LastTransitionTime - } - } - } - return &metav1.Time{} -} - -func maxContainerRestarts(pod *v1.Pod) int { - maxRestarts := 0 - for _, c := range pod.Status.ContainerStatuses { - maxRestarts = integer.IntMax(maxRestarts, int(c.RestartCount)) - } - return maxRestarts -} - -// FilterActivePods returns pods that have not terminated. -func FilterActivePods(pods []*v1.Pod) []*v1.Pod { - var result []*v1.Pod - for _, p := range pods { - if IsPodActive(p) { - result = append(result, p) - } else { - glog.V(4).Infof("Ignoring inactive pod %v/%v in state %v, deletion time %v", - p.Namespace, p.Name, p.Status.Phase, p.DeletionTimestamp) - } - } - return result -} - -func IsPodActive(p *v1.Pod) bool { - return v1.PodSucceeded != p.Status.Phase && - v1.PodFailed != p.Status.Phase && - p.DeletionTimestamp == nil -} - -// FilterActiveReplicaSets returns replica sets that have (or at least ought to have) pods. -func FilterActiveReplicaSets(replicaSets []*extensions.ReplicaSet) []*extensions.ReplicaSet { - activeFilter := func(rs *extensions.ReplicaSet) bool { - return rs != nil && *(rs.Spec.Replicas) > 0 - } - return FilterReplicaSets(replicaSets, activeFilter) -} - -type filterRS func(rs *extensions.ReplicaSet) bool - -// FilterReplicaSets returns replica sets that are filtered by filterFn (all returned ones should match filterFn). -func FilterReplicaSets(RSes []*extensions.ReplicaSet, filterFn filterRS) []*extensions.ReplicaSet { - var filtered []*extensions.ReplicaSet - for i := range RSes { - if filterFn(RSes[i]) { - filtered = append(filtered, RSes[i]) - } - } - return filtered -} - -// PodKey returns a key unique to the given pod within a cluster. -// It's used so we consistently use the same key scheme in this module. -// It does exactly what cache.MetaNamespaceKeyFunc would have done -// except there's not possibility for error since we know the exact type. -func PodKey(pod *v1.Pod) string { - return fmt.Sprintf("%v/%v", pod.Namespace, pod.Name) -} - -// ControllersByCreationTimestamp sorts a list of ReplicationControllers by creation timestamp, using their names as a tie breaker. -type ControllersByCreationTimestamp []*v1.ReplicationController - -func (o ControllersByCreationTimestamp) Len() int { return len(o) } -func (o ControllersByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } -func (o ControllersByCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) -} - -// ReplicaSetsByCreationTimestamp sorts a list of ReplicaSet by creation timestamp, using their names as a tie breaker. -type ReplicaSetsByCreationTimestamp []*extensions.ReplicaSet - -func (o ReplicaSetsByCreationTimestamp) Len() int { return len(o) } -func (o ReplicaSetsByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } -func (o ReplicaSetsByCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) -} - -// ReplicaSetsBySizeOlder sorts a list of ReplicaSet by size in descending order, using their creation timestamp or name as a tie breaker. -// By using the creation timestamp, this sorts from old to new replica sets. -type ReplicaSetsBySizeOlder []*extensions.ReplicaSet - -func (o ReplicaSetsBySizeOlder) Len() int { return len(o) } -func (o ReplicaSetsBySizeOlder) Swap(i, j int) { o[i], o[j] = o[j], o[i] } -func (o ReplicaSetsBySizeOlder) Less(i, j int) bool { - if *(o[i].Spec.Replicas) == *(o[j].Spec.Replicas) { - return ReplicaSetsByCreationTimestamp(o).Less(i, j) - } - return *(o[i].Spec.Replicas) > *(o[j].Spec.Replicas) -} - -// ReplicaSetsBySizeNewer sorts a list of ReplicaSet by size in descending order, using their creation timestamp or name as a tie breaker. -// By using the creation timestamp, this sorts from new to old replica sets. -type ReplicaSetsBySizeNewer []*extensions.ReplicaSet - -func (o ReplicaSetsBySizeNewer) Len() int { return len(o) } -func (o ReplicaSetsBySizeNewer) Swap(i, j int) { o[i], o[j] = o[j], o[i] } -func (o ReplicaSetsBySizeNewer) Less(i, j int) bool { - if *(o[i].Spec.Replicas) == *(o[j].Spec.Replicas) { - return ReplicaSetsByCreationTimestamp(o).Less(j, i) - } - return *(o[i].Spec.Replicas) > *(o[j].Spec.Replicas) -} - -// AddOrUpdateTaintOnNode add taints to the node. If taint was added into node, it'll issue API calls -// to update nodes; otherwise, no API calls. Return error if any. -func AddOrUpdateTaintOnNode(c clientset.Interface, nodeName string, taints ...*v1.Taint) error { - if len(taints) == 0 { - return nil - } - firstTry := true - return clientretry.RetryOnConflict(UpdateTaintBackoff, func() error { - var err error - var oldNode *v1.Node - // First we try getting node from the API server cache, as it's cheaper. If it fails - // we get it from etcd to be sure to have fresh data. - if firstTry { - oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"}) - firstTry = false - } else { - oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) - } - if err != nil { - return err - } - - var newNode *v1.Node - oldNodeCopy := oldNode - updated := false - for _, taint := range taints { - curNewNode, ok, err := taintutils.AddOrUpdateTaint(oldNodeCopy, taint) - if err != nil { - return fmt.Errorf("Failed to update taint of node!") - } - updated = updated || ok - newNode = curNewNode - oldNodeCopy = curNewNode - } - if !updated { - return nil - } - return PatchNodeTaints(c, nodeName, oldNode, newNode) - }) -} - -// RemoveTaintOffNode is for cleaning up taints temporarily added to node, -// won't fail if target taint doesn't exist or has been removed. -// If passed a node it'll check if there's anything to be done, if taint is not present it won't issue -// any API calls. -func RemoveTaintOffNode(c clientset.Interface, nodeName string, node *v1.Node, taints ...*v1.Taint) error { - if len(taints) == 0 { - return nil - } - // Short circuit for limiting amount of API calls. - if node != nil { - match := false - for _, taint := range taints { - if taintutils.TaintExists(node.Spec.Taints, taint) { - match = true - break - } - } - if !match { - return nil - } - } - - firstTry := true - return clientretry.RetryOnConflict(UpdateTaintBackoff, func() error { - var err error - var oldNode *v1.Node - // First we try getting node from the API server cache, as it's cheaper. If it fails - // we get it from etcd to be sure to have fresh data. - if firstTry { - oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"}) - firstTry = false - } else { - oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) - } - if err != nil { - return err - } - - var newNode *v1.Node - oldNodeCopy := oldNode - updated := false - for _, taint := range taints { - curNewNode, ok, err := taintutils.RemoveTaint(oldNodeCopy, taint) - if err != nil { - return fmt.Errorf("Failed to remove taint of node!") - } - updated = updated || ok - newNode = curNewNode - oldNodeCopy = curNewNode - } - if !updated { - return nil - } - return PatchNodeTaints(c, nodeName, oldNode, newNode) - }) -} - -// PatchNodeTaints patches node's taints. -func PatchNodeTaints(c clientset.Interface, nodeName string, oldNode *v1.Node, newNode *v1.Node) error { - oldData, err := json.Marshal(oldNode) - if err != nil { - return fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNode, nodeName, err) - } - - newTaints := newNode.Spec.Taints - newNodeClone := oldNode.DeepCopy() - newNodeClone.Spec.Taints = newTaints - newData, err := json.Marshal(newNodeClone) - if err != nil { - return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNodeClone, nodeName, err) - } - - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) - if err != nil { - return fmt.Errorf("failed to create patch for node %q: %v", nodeName, err) - } - - _, err = c.CoreV1().Nodes().Patch(nodeName, types.StrategicMergePatchType, patchBytes) - return err -} - -// WaitForCacheSync is a wrapper around cache.WaitForCacheSync that generates log messages -// indicating that the controller identified by controllerName is waiting for syncs, followed by -// either a successful or failed sync. -func WaitForCacheSync(controllerName string, stopCh <-chan struct{}, cacheSyncs ...cache.InformerSynced) bool { - glog.Infof("Waiting for caches to sync for %s controller", controllerName) - - if !cache.WaitForCacheSync(stopCh, cacheSyncs...) { - utilruntime.HandleError(fmt.Errorf("Unable to sync caches for %s controller", controllerName)) - return false - } - - glog.Infof("Caches are synced for %s controller", controllerName) - return true -} - -// ComputeHash returns a hash value calculated from pod template and a collisionCount to avoid hash collision -func ComputeHash(template *v1.PodTemplateSpec, collisionCount *int32) uint32 { - podTemplateSpecHasher := fnv.New32a() - hashutil.DeepHashObject(podTemplateSpecHasher, *template) - - // Add collisionCount in the hash if it exists. - if collisionCount != nil { - collisionCountBytes := make([]byte, 8) - binary.LittleEndian.PutUint32(collisionCountBytes, uint32(*collisionCount)) - podTemplateSpecHasher.Write(collisionCountBytes) - } - - return podTemplateSpecHasher.Sum32() -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/doc.go b/vendor/k8s.io/kubernetes/pkg/controller/doc.go deleted file mode 100644 index 3c5c943da..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 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 contains code for controllers (like the replication -// controller). -package controller // import "k8s.io/kubernetes/pkg/controller" diff --git a/vendor/k8s.io/kubernetes/pkg/controller/lookup_cache.go b/vendor/k8s.io/kubernetes/pkg/controller/lookup_cache.go deleted file mode 100644 index 160aa6e08..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/lookup_cache.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -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 ( - "hash/fnv" - "sync" - - "github.com/golang/groupcache/lru" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - hashutil "k8s.io/kubernetes/pkg/util/hash" -) - -type objectWithMeta interface { - metav1.Object -} - -// keyFunc returns the key of an object, which is used to look up in the cache for it's matching object. -// Since we match objects by namespace and Labels/Selector, so if two objects have the same namespace and labels, -// they will have the same key. -func keyFunc(obj objectWithMeta) uint64 { - hash := fnv.New32a() - hashutil.DeepHashObject(hash, &equivalenceLabelObj{ - namespace: obj.GetNamespace(), - labels: obj.GetLabels(), - }) - return uint64(hash.Sum32()) -} - -type equivalenceLabelObj struct { - namespace string - labels map[string]string -} - -// MatchingCache save label and selector matching relationship -type MatchingCache struct { - mutex sync.RWMutex - cache *lru.Cache -} - -// NewMatchingCache return a NewMatchingCache, which save label and selector matching relationship. -func NewMatchingCache(maxCacheEntries int) *MatchingCache { - return &MatchingCache{ - cache: lru.New(maxCacheEntries), - } -} - -// Add will add matching information to the cache. -func (c *MatchingCache) Add(labelObj objectWithMeta, selectorObj objectWithMeta) { - key := keyFunc(labelObj) - c.mutex.Lock() - defer c.mutex.Unlock() - c.cache.Add(key, selectorObj) -} - -// GetMatchingObject lookup the matching object for a given object. -// Note: the cache information may be invalid since the controller may be deleted or updated, -// we need check in the external request to ensure the cache data is not dirty. -func (c *MatchingCache) GetMatchingObject(labelObj objectWithMeta) (controller interface{}, exists bool) { - key := keyFunc(labelObj) - // NOTE: we use Lock() instead of RLock() here because lru's Get() method also modifies state( - // it need update the least recently usage information). So we can not call it concurrently. - c.mutex.Lock() - defer c.mutex.Unlock() - return c.cache.Get(key) -} - -// Update update the cached matching information. -func (c *MatchingCache) Update(labelObj objectWithMeta, selectorObj objectWithMeta) { - c.Add(labelObj, selectorObj) -} - -// InvalidateAll invalidate the whole cache. -func (c *MatchingCache) InvalidateAll() { - c.mutex.Lock() - defer c.mutex.Unlock() - c.cache = lru.New(c.cache.MaxEntries) -} |