*: update kube vendor to v1.7.4
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
c67859731f
commit
d56bf090ce
1032 changed files with 273965 additions and 40081 deletions
292
vendor/k8s.io/kubernetes/pkg/controller/client_builder.go
generated
vendored
Normal file
292
vendor/k8s.io/kubernetes/pkg/controller/client_builder.go
generated
vendored
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
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"
|
||||
clientgoclientset "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
v1authenticationapi "k8s.io/kubernetes/pkg/apis/authentication/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
v1authentication "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authentication/v1"
|
||||
v1core "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/core/v1"
|
||||
"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) (clientgoclientset.Interface, error)
|
||||
ClientGoClientOrDie(name string) clientgoclientset.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) (clientgoclientset.Interface, error) {
|
||||
clientConfig, err := b.Config(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return clientgoclientset.NewForConfig(clientConfig)
|
||||
}
|
||||
|
||||
func (b SimpleControllerClientBuilder) ClientGoClientOrDie(name string) clientgoclientset.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 = api.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) (clientgoclientset.Interface, error) {
|
||||
clientConfig, err := b.Config(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return clientgoclientset.NewForConfig(clientConfig)
|
||||
}
|
||||
|
||||
func (b SAControllerClientBuilder) ClientGoClientOrDie(name string) clientgoclientset.Interface {
|
||||
client, err := b.ClientGoClient(name)
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
return client
|
||||
}
|
515
vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go
generated
vendored
Normal file
515
vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go
generated
vendored
Normal file
|
@ -0,0 +1,515 @@
|
|||
/*
|
||||
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"
|
||||
"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"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
appsv1beta1 "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
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 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.
|
||||
func (m *baseControllerRefManager) claimObject(obj metav1.Object, match func(metav1.Object) bool, adopt, release func(metav1.Object) error) (bool, error) {
|
||||
controllerRef := 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 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.
|
||||
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 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
|
||||
|
||||
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 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 ControllerRevisions that you now own is
|
||||
// returned.
|
||||
func (m *ControllerRevisionControllerRefManager) ClaimControllerRevisions(histories []*appsv1beta1.ControllerRevision) ([]*appsv1beta1.ControllerRevision, error) {
|
||||
var claimed []*appsv1beta1.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.(*appsv1beta1.ControllerRevision))
|
||||
}
|
||||
release := func(obj metav1.Object) error {
|
||||
return m.ReleaseControllerRevision(obj.(*appsv1beta1.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 *appsv1beta1.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 *appsv1beta1.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
|
||||
}
|
1018
vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go
generated
vendored
Normal file
1018
vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
19
vendor/k8s.io/kubernetes/pkg/controller/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/controller/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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"
|
92
vendor/k8s.io/kubernetes/pkg/controller/lookup_cache.go
generated
vendored
Normal file
92
vendor/k8s.io/kubernetes/pkg/controller/lookup_cache.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue