Update godeps
This commit is contained in:
parent
1c8773fc98
commit
1bc383f9c5
1723 changed files with 287976 additions and 411028 deletions
100
vendor/k8s.io/kubernetes/pkg/client/cache/BUILD
generated
vendored
Normal file
100
vendor/k8s.io/kubernetes/pkg/client/cache/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"controller.go",
|
||||
"delta_fifo.go",
|
||||
"doc.go",
|
||||
"expiration_cache.go",
|
||||
"expiration_cache_fakes.go",
|
||||
"fake_custom_store.go",
|
||||
"fifo.go",
|
||||
"index.go",
|
||||
"listers.go",
|
||||
"listers_core.go",
|
||||
"listers_extensions.go",
|
||||
"listers_rbac.go",
|
||||
"listwatch.go",
|
||||
"mutation_detector.go",
|
||||
"reflector.go",
|
||||
"shared_informer.go",
|
||||
"store.go",
|
||||
"thread_safe_store.go",
|
||||
"undelta_store.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/meta:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
"//pkg/apis/certificates:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/labels:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/util/clock:go_default_library",
|
||||
"//pkg/util/diff:go_default_library",
|
||||
"//pkg/util/runtime:go_default_library",
|
||||
"//pkg/util/sets:go_default_library",
|
||||
"//pkg/util/wait:go_default_library",
|
||||
"//pkg/watch:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"controller_test.go",
|
||||
"delta_fifo_test.go",
|
||||
"expiration_cache_test.go",
|
||||
"fifo_test.go",
|
||||
"index_test.go",
|
||||
"listers_test.go",
|
||||
"listwatch_test.go",
|
||||
"mutation_detector_test.go",
|
||||
"processor_listener_test.go",
|
||||
"reflector_test.go",
|
||||
"store_test.go",
|
||||
"undelta_store_test.go",
|
||||
],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/apimachinery/registered:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/testing/cache:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/labels:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/util/clock:go_default_library",
|
||||
"//pkg/util/sets:go_default_library",
|
||||
"//pkg/util/testing:go_default_library",
|
||||
"//pkg/util/wait:go_default_library",
|
||||
"//pkg/watch:go_default_library",
|
||||
"//vendor:github.com/google/gofuzz",
|
||||
],
|
||||
)
|
||||
325
vendor/k8s.io/kubernetes/pkg/client/cache/controller.go
generated
vendored
Normal file
325
vendor/k8s.io/kubernetes/pkg/client/cache/controller.go
generated
vendored
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
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 cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
// Config contains all the settings for a Controller.
|
||||
type Config struct {
|
||||
// The queue for your objects; either a FIFO or
|
||||
// a DeltaFIFO. Your Process() function should accept
|
||||
// the output of this Oueue's Pop() method.
|
||||
Queue
|
||||
|
||||
// Something that can list and watch your objects.
|
||||
ListerWatcher
|
||||
|
||||
// Something that can process your objects.
|
||||
Process ProcessFunc
|
||||
|
||||
// The type of your objects.
|
||||
ObjectType runtime.Object
|
||||
|
||||
// Reprocess everything at least this often.
|
||||
// Note that if it takes longer for you to clear the queue than this
|
||||
// period, you will end up processing items in the order determined
|
||||
// by FIFO.Replace(). Currently, this is random. If this is a
|
||||
// problem, we can change that replacement policy to append new
|
||||
// things to the end of the queue instead of replacing the entire
|
||||
// queue.
|
||||
FullResyncPeriod time.Duration
|
||||
|
||||
// If true, when Process() returns an error, re-enqueue the object.
|
||||
// TODO: add interface to let you inject a delay/backoff or drop
|
||||
// the object completely if desired. Pass the object in
|
||||
// question to this interface as a parameter.
|
||||
RetryOnError bool
|
||||
}
|
||||
|
||||
// ProcessFunc processes a single object.
|
||||
type ProcessFunc func(obj interface{}) error
|
||||
|
||||
// Controller is a generic controller framework.
|
||||
type Controller struct {
|
||||
config Config
|
||||
reflector *Reflector
|
||||
reflectorMutex sync.RWMutex
|
||||
}
|
||||
|
||||
// TODO make the "Controller" private, and convert all references to use ControllerInterface instead
|
||||
type ControllerInterface interface {
|
||||
Run(stopCh <-chan struct{})
|
||||
HasSynced() bool
|
||||
}
|
||||
|
||||
// New makes a new Controller from the given Config.
|
||||
func New(c *Config) *Controller {
|
||||
ctlr := &Controller{
|
||||
config: *c,
|
||||
}
|
||||
return ctlr
|
||||
}
|
||||
|
||||
// Run begins processing items, and will continue until a value is sent down stopCh.
|
||||
// It's an error to call Run more than once.
|
||||
// Run blocks; call via go.
|
||||
func (c *Controller) Run(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
r := NewReflector(
|
||||
c.config.ListerWatcher,
|
||||
c.config.ObjectType,
|
||||
c.config.Queue,
|
||||
c.config.FullResyncPeriod,
|
||||
)
|
||||
|
||||
c.reflectorMutex.Lock()
|
||||
c.reflector = r
|
||||
c.reflectorMutex.Unlock()
|
||||
|
||||
r.RunUntil(stopCh)
|
||||
|
||||
wait.Until(c.processLoop, time.Second, stopCh)
|
||||
}
|
||||
|
||||
// Returns true once this controller has completed an initial resource listing
|
||||
func (c *Controller) HasSynced() bool {
|
||||
return c.config.Queue.HasSynced()
|
||||
}
|
||||
|
||||
// Requeue adds the provided object back into the queue if it does not already exist.
|
||||
func (c *Controller) Requeue(obj interface{}) error {
|
||||
return c.config.Queue.AddIfNotPresent(Deltas{
|
||||
Delta{
|
||||
Type: Sync,
|
||||
Object: obj,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// processLoop drains the work queue.
|
||||
// TODO: Consider doing the processing in parallel. This will require a little thought
|
||||
// to make sure that we don't end up processing the same object multiple times
|
||||
// concurrently.
|
||||
func (c *Controller) processLoop() {
|
||||
for {
|
||||
obj, err := c.config.Queue.Pop(PopProcessFunc(c.config.Process))
|
||||
if err != nil {
|
||||
if c.config.RetryOnError {
|
||||
// This is the safe way to re-enqueue.
|
||||
c.config.Queue.AddIfNotPresent(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceEventHandler can handle notifications for events that happen to a
|
||||
// resource. The events are informational only, so you can't return an
|
||||
// error.
|
||||
// * OnAdd is called when an object is added.
|
||||
// * OnUpdate is called when an object is modified. Note that oldObj is the
|
||||
// last known state of the object-- it is possible that several changes
|
||||
// were combined together, so you can't use this to see every single
|
||||
// change. OnUpdate is also called when a re-list happens, and it will
|
||||
// get called even if nothing changed. This is useful for periodically
|
||||
// evaluating or syncing something.
|
||||
// * OnDelete will get the final state of the item if it is known, otherwise
|
||||
// it will get an object of type DeletedFinalStateUnknown. This can
|
||||
// happen if the watch is closed and misses the delete event and we don't
|
||||
// notice the deletion until the subsequent re-list.
|
||||
type ResourceEventHandler interface {
|
||||
OnAdd(obj interface{})
|
||||
OnUpdate(oldObj, newObj interface{})
|
||||
OnDelete(obj interface{})
|
||||
}
|
||||
|
||||
// ResourceEventHandlerFuncs is an adaptor to let you easily specify as many or
|
||||
// as few of the notification functions as you want while still implementing
|
||||
// ResourceEventHandler.
|
||||
type ResourceEventHandlerFuncs struct {
|
||||
AddFunc func(obj interface{})
|
||||
UpdateFunc func(oldObj, newObj interface{})
|
||||
DeleteFunc func(obj interface{})
|
||||
}
|
||||
|
||||
// OnAdd calls AddFunc if it's not nil.
|
||||
func (r ResourceEventHandlerFuncs) OnAdd(obj interface{}) {
|
||||
if r.AddFunc != nil {
|
||||
r.AddFunc(obj)
|
||||
}
|
||||
}
|
||||
|
||||
// OnUpdate calls UpdateFunc if it's not nil.
|
||||
func (r ResourceEventHandlerFuncs) OnUpdate(oldObj, newObj interface{}) {
|
||||
if r.UpdateFunc != nil {
|
||||
r.UpdateFunc(oldObj, newObj)
|
||||
}
|
||||
}
|
||||
|
||||
// OnDelete calls DeleteFunc if it's not nil.
|
||||
func (r ResourceEventHandlerFuncs) OnDelete(obj interface{}) {
|
||||
if r.DeleteFunc != nil {
|
||||
r.DeleteFunc(obj)
|
||||
}
|
||||
}
|
||||
|
||||
// DeletionHandlingMetaNamespaceKeyFunc checks for
|
||||
// DeletedFinalStateUnknown objects before calling
|
||||
// MetaNamespaceKeyFunc.
|
||||
func DeletionHandlingMetaNamespaceKeyFunc(obj interface{}) (string, error) {
|
||||
if d, ok := obj.(DeletedFinalStateUnknown); ok {
|
||||
return d.Key, nil
|
||||
}
|
||||
return MetaNamespaceKeyFunc(obj)
|
||||
}
|
||||
|
||||
// NewInformer returns a Store and a controller for populating the store
|
||||
// while also providing event notifications. You should only used the returned
|
||||
// Store for Get/List operations; Add/Modify/Deletes will cause the event
|
||||
// notifications to be faulty.
|
||||
//
|
||||
// Parameters:
|
||||
// * lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// * objType is an object of the type that you expect to receive.
|
||||
// * resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// * h is the object you want notifications sent to.
|
||||
//
|
||||
func NewInformer(
|
||||
lw ListerWatcher,
|
||||
objType runtime.Object,
|
||||
resyncPeriod time.Duration,
|
||||
h ResourceEventHandler,
|
||||
) (Store, *Controller) {
|
||||
// This will hold the client state, as we know it.
|
||||
clientState := NewStore(DeletionHandlingMetaNamespaceKeyFunc)
|
||||
|
||||
// This will hold incoming changes. Note how we pass clientState in as a
|
||||
// KeyLister, that way resync operations will result in the correct set
|
||||
// of update/delete deltas.
|
||||
fifo := NewDeltaFIFO(MetaNamespaceKeyFunc, nil, clientState)
|
||||
|
||||
cfg := &Config{
|
||||
Queue: fifo,
|
||||
ListerWatcher: lw,
|
||||
ObjectType: objType,
|
||||
FullResyncPeriod: resyncPeriod,
|
||||
RetryOnError: false,
|
||||
|
||||
Process: func(obj interface{}) error {
|
||||
// from oldest to newest
|
||||
for _, d := range obj.(Deltas) {
|
||||
switch d.Type {
|
||||
case Sync, Added, Updated:
|
||||
if old, exists, err := clientState.Get(d.Object); err == nil && exists {
|
||||
if err := clientState.Update(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
h.OnUpdate(old, d.Object)
|
||||
} else {
|
||||
if err := clientState.Add(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
h.OnAdd(d.Object)
|
||||
}
|
||||
case Deleted:
|
||||
if err := clientState.Delete(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
h.OnDelete(d.Object)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return clientState, New(cfg)
|
||||
}
|
||||
|
||||
// NewIndexerInformer returns a Indexer and a controller for populating the index
|
||||
// while also providing event notifications. You should only used the returned
|
||||
// Index for Get/List operations; Add/Modify/Deletes will cause the event
|
||||
// notifications to be faulty.
|
||||
//
|
||||
// Parameters:
|
||||
// * lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// * objType is an object of the type that you expect to receive.
|
||||
// * resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// * h is the object you want notifications sent to.
|
||||
//
|
||||
func NewIndexerInformer(
|
||||
lw ListerWatcher,
|
||||
objType runtime.Object,
|
||||
resyncPeriod time.Duration,
|
||||
h ResourceEventHandler,
|
||||
indexers Indexers,
|
||||
) (Indexer, *Controller) {
|
||||
// This will hold the client state, as we know it.
|
||||
clientState := NewIndexer(DeletionHandlingMetaNamespaceKeyFunc, indexers)
|
||||
|
||||
// This will hold incoming changes. Note how we pass clientState in as a
|
||||
// KeyLister, that way resync operations will result in the correct set
|
||||
// of update/delete deltas.
|
||||
fifo := NewDeltaFIFO(MetaNamespaceKeyFunc, nil, clientState)
|
||||
|
||||
cfg := &Config{
|
||||
Queue: fifo,
|
||||
ListerWatcher: lw,
|
||||
ObjectType: objType,
|
||||
FullResyncPeriod: resyncPeriod,
|
||||
RetryOnError: false,
|
||||
|
||||
Process: func(obj interface{}) error {
|
||||
// from oldest to newest
|
||||
for _, d := range obj.(Deltas) {
|
||||
switch d.Type {
|
||||
case Sync, Added, Updated:
|
||||
if old, exists, err := clientState.Get(d.Object); err == nil && exists {
|
||||
if err := clientState.Update(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
h.OnUpdate(old, d.Object)
|
||||
} else {
|
||||
if err := clientState.Add(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
h.OnAdd(d.Object)
|
||||
}
|
||||
case Deleted:
|
||||
if err := clientState.Delete(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
h.OnDelete(d.Object)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return clientState, New(cfg)
|
||||
}
|
||||
19
vendor/k8s.io/kubernetes/pkg/client/cache/delta_fifo.go
generated
vendored
19
vendor/k8s.io/kubernetes/pkg/client/cache/delta_fifo.go
generated
vendored
|
|
@ -437,11 +437,6 @@ func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
|
|||
defer f.lock.Unlock()
|
||||
keys := make(sets.String, len(list))
|
||||
|
||||
if !f.populated {
|
||||
f.populated = true
|
||||
f.initialPopulationCount = len(list)
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
key, err := f.KeyOf(item)
|
||||
if err != nil {
|
||||
|
|
@ -467,6 +462,12 @@ func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !f.populated {
|
||||
f.populated = true
|
||||
f.initialPopulationCount = len(list)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -474,6 +475,7 @@ func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
|
|||
// TODO(lavalamp): This may be racy-- we aren't properly locked
|
||||
// with knownObjects. Unproven.
|
||||
knownKeys := f.knownObjects.ListKeys()
|
||||
queuedDeletions := 0
|
||||
for _, k := range knownKeys {
|
||||
if keys.Has(k) {
|
||||
continue
|
||||
|
|
@ -487,10 +489,17 @@ func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
|
|||
deletedObj = nil
|
||||
glog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k)
|
||||
}
|
||||
queuedDeletions++
|
||||
if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !f.populated {
|
||||
f.populated = true
|
||||
f.initialPopulationCount = len(list) + queuedDeletions
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
703
vendor/k8s.io/kubernetes/pkg/client/cache/listers.go
generated
vendored
703
vendor/k8s.io/kubernetes/pkg/client/cache/listers.go
generated
vendored
|
|
@ -22,113 +22,151 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// TODO: generate these classes and methods for all resources of interest using
|
||||
// a script. Can use "go generate" once 1.4 is supported by all users.
|
||||
// AppendFunc is used to add a matching item to whatever list the caller is using
|
||||
type AppendFunc func(interface{})
|
||||
|
||||
// StoreToPodLister makes a Store have the List method of the client.PodInterface
|
||||
// The Store must contain (only) Pods.
|
||||
//
|
||||
// Example:
|
||||
// s := cache.NewStore()
|
||||
// lw := cache.ListWatch{Client: c, FieldSelector: sel, Resource: "pods"}
|
||||
// r := cache.NewReflector(lw, &api.Pod{}, s).Run()
|
||||
// l := StoreToPodLister{s}
|
||||
// l.List()
|
||||
type StoreToPodLister struct {
|
||||
Indexer
|
||||
}
|
||||
|
||||
// Please note that selector is filtering among the pods that have gotten into
|
||||
// the store; there may have been some filtering that already happened before
|
||||
// that.
|
||||
// We explicitly don't return api.PodList, to avoid expensive allocations, which
|
||||
// in most cases are unnecessary.
|
||||
func (s *StoreToPodLister) List(selector labels.Selector) (pods []*api.Pod, err error) {
|
||||
for _, m := range s.Indexer.List() {
|
||||
pod := m.(*api.Pod)
|
||||
if selector.Matches(labels.Set(pod.Labels)) {
|
||||
pods = append(pods, pod)
|
||||
func ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error {
|
||||
for _, m := range store.List() {
|
||||
metadata, err := meta.Accessor(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if selector.Matches(labels.Set(metadata.GetLabels())) {
|
||||
appendFn(m)
|
||||
}
|
||||
}
|
||||
return pods, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pods is taking baby steps to be more like the api in pkg/client
|
||||
func (s *StoreToPodLister) Pods(namespace string) storePodsNamespacer {
|
||||
return storePodsNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
type storePodsNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// Please note that selector is filtering among the pods that have gotten into
|
||||
// the store; there may have been some filtering that already happened before
|
||||
// that.
|
||||
// We explicitly don't return api.PodList, to avoid expensive allocations, which
|
||||
// in most cases are unnecessary.
|
||||
func (s storePodsNamespacer) List(selector labels.Selector) (pods []*api.Pod, err error) {
|
||||
if s.namespace == api.NamespaceAll {
|
||||
for _, m := range s.indexer.List() {
|
||||
pod := m.(*api.Pod)
|
||||
if selector.Matches(labels.Set(pod.Labels)) {
|
||||
pods = append(pods, pod)
|
||||
func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selector, appendFn AppendFunc) error {
|
||||
if namespace == api.NamespaceAll {
|
||||
for _, m := range indexer.List() {
|
||||
metadata, err := meta.Accessor(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if selector.Matches(labels.Set(metadata.GetLabels())) {
|
||||
appendFn(m)
|
||||
}
|
||||
}
|
||||
return pods, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
key := &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: s.namespace}}
|
||||
items, err := s.indexer.Index(NamespaceIndex, key)
|
||||
items, err := indexer.Index(NamespaceIndex, &api.ObjectMeta{Namespace: namespace})
|
||||
if err != nil {
|
||||
// Ignore error; do slow search without index.
|
||||
glog.Warningf("can not retrieve list of objects using index : %v", err)
|
||||
for _, m := range s.indexer.List() {
|
||||
pod := m.(*api.Pod)
|
||||
if s.namespace == pod.Namespace && selector.Matches(labels.Set(pod.Labels)) {
|
||||
pods = append(pods, pod)
|
||||
for _, m := range indexer.List() {
|
||||
metadata, err := meta.Accessor(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if metadata.GetNamespace() == namespace && selector.Matches(labels.Set(metadata.GetLabels())) {
|
||||
appendFn(m)
|
||||
}
|
||||
|
||||
}
|
||||
return pods, nil
|
||||
return nil
|
||||
}
|
||||
for _, m := range items {
|
||||
pod := m.(*api.Pod)
|
||||
if selector.Matches(labels.Set(pod.Labels)) {
|
||||
pods = append(pods, pod)
|
||||
metadata, err := meta.Accessor(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if selector.Matches(labels.Set(metadata.GetLabels())) {
|
||||
appendFn(m)
|
||||
}
|
||||
}
|
||||
return pods, nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s storePodsNamespacer) Get(name string) (*api.Pod, error) {
|
||||
// GenericLister is a lister skin on a generic Indexer
|
||||
type GenericLister interface {
|
||||
// List will return all objects across namespaces
|
||||
List(selector labels.Selector) (ret []runtime.Object, err error)
|
||||
// Get will attempt to retrieve assuming that name==key
|
||||
Get(name string) (runtime.Object, error)
|
||||
// ByNamespace will give you a GenericNamespaceLister for one namespace
|
||||
ByNamespace(namespace string) GenericNamespaceLister
|
||||
}
|
||||
|
||||
// GenericNamespaceLister is a lister skin on a generic Indexer
|
||||
type GenericNamespaceLister interface {
|
||||
// List will return all objects in this namespace
|
||||
List(selector labels.Selector) (ret []runtime.Object, err error)
|
||||
// Get will attempt to retrieve by namespace and name
|
||||
Get(name string) (runtime.Object, error)
|
||||
}
|
||||
|
||||
func NewGenericLister(indexer Indexer, resource unversioned.GroupResource) GenericLister {
|
||||
return &genericLister{indexer: indexer, resource: resource}
|
||||
}
|
||||
|
||||
type genericLister struct {
|
||||
indexer Indexer
|
||||
resource unversioned.GroupResource
|
||||
}
|
||||
|
||||
func (s *genericLister) List(selector labels.Selector) (ret []runtime.Object, err error) {
|
||||
err = ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(runtime.Object))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *genericLister) ByNamespace(namespace string) GenericNamespaceLister {
|
||||
return &genericNamespaceLister{indexer: s.indexer, namespace: namespace, resource: s.resource}
|
||||
}
|
||||
|
||||
func (s *genericLister) Get(name string) (runtime.Object, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(s.resource, name)
|
||||
}
|
||||
return obj.(runtime.Object), nil
|
||||
}
|
||||
|
||||
type genericNamespaceLister struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
resource unversioned.GroupResource
|
||||
}
|
||||
|
||||
func (s *genericNamespaceLister) List(selector labels.Selector) (ret []runtime.Object, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(runtime.Object))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *genericNamespaceLister) Get(name string) (runtime.Object, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("pod"), name)
|
||||
return nil, errors.NewNotFound(s.resource, name)
|
||||
}
|
||||
return obj.(*api.Pod), nil
|
||||
return obj.(runtime.Object), nil
|
||||
}
|
||||
|
||||
// Exists returns true if a pod matching the namespace/name of the given pod exists in the store.
|
||||
func (s *StoreToPodLister) Exists(pod *api.Pod) (bool, error) {
|
||||
_, exists, err := s.Indexer.Get(pod)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return exists, nil
|
||||
}
|
||||
// TODO: generate these classes and methods for all resources of interest using
|
||||
// a script. Can use "go generate" once 1.4 is supported by all users.
|
||||
|
||||
// NodeConditionPredicate is a function that indicates whether the given node's conditions meet
|
||||
// some set of criteria defined by the function.
|
||||
|
|
@ -173,331 +211,6 @@ func (s storeToNodeConditionLister) List() (nodes []*api.Node, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// StoreToReplicationControllerLister gives a store List and Exists methods. The store must contain only ReplicationControllers.
|
||||
type StoreToReplicationControllerLister struct {
|
||||
Indexer
|
||||
}
|
||||
|
||||
// Exists checks if the given rc exists in the store.
|
||||
func (s *StoreToReplicationControllerLister) Exists(controller *api.ReplicationController) (bool, error) {
|
||||
_, exists, err := s.Indexer.Get(controller)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
// StoreToReplicationControllerLister lists all controllers in the store.
|
||||
// TODO: converge on the interface in pkg/client
|
||||
func (s *StoreToReplicationControllerLister) List() (controllers []api.ReplicationController, err error) {
|
||||
for _, c := range s.Indexer.List() {
|
||||
controllers = append(controllers, *(c.(*api.ReplicationController)))
|
||||
}
|
||||
return controllers, nil
|
||||
}
|
||||
|
||||
func (s *StoreToReplicationControllerLister) ReplicationControllers(namespace string) storeReplicationControllersNamespacer {
|
||||
return storeReplicationControllersNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
type storeReplicationControllersNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeReplicationControllersNamespacer) List(selector labels.Selector) ([]api.ReplicationController, error) {
|
||||
controllers := []api.ReplicationController{}
|
||||
|
||||
if s.namespace == api.NamespaceAll {
|
||||
for _, m := range s.indexer.List() {
|
||||
rc := *(m.(*api.ReplicationController))
|
||||
if selector.Matches(labels.Set(rc.Labels)) {
|
||||
controllers = append(controllers, rc)
|
||||
}
|
||||
}
|
||||
return controllers, nil
|
||||
}
|
||||
|
||||
key := &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: s.namespace}}
|
||||
items, err := s.indexer.Index(NamespaceIndex, key)
|
||||
if err != nil {
|
||||
// Ignore error; do slow search without index.
|
||||
glog.Warningf("can not retrieve list of objects using index : %v", err)
|
||||
for _, m := range s.indexer.List() {
|
||||
rc := *(m.(*api.ReplicationController))
|
||||
if s.namespace == rc.Namespace && selector.Matches(labels.Set(rc.Labels)) {
|
||||
controllers = append(controllers, rc)
|
||||
}
|
||||
}
|
||||
return controllers, nil
|
||||
}
|
||||
for _, m := range items {
|
||||
rc := *(m.(*api.ReplicationController))
|
||||
if selector.Matches(labels.Set(rc.Labels)) {
|
||||
controllers = append(controllers, rc)
|
||||
}
|
||||
}
|
||||
return controllers, nil
|
||||
}
|
||||
|
||||
func (s storeReplicationControllersNamespacer) Get(name string) (*api.ReplicationController, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("replicationcontroller"), name)
|
||||
}
|
||||
return obj.(*api.ReplicationController), nil
|
||||
}
|
||||
|
||||
// GetPodControllers returns a list of replication controllers managing a pod. Returns an error only if no matching controllers are found.
|
||||
func (s *StoreToReplicationControllerLister) GetPodControllers(pod *api.Pod) (controllers []api.ReplicationController, err error) {
|
||||
var selector labels.Selector
|
||||
var rc api.ReplicationController
|
||||
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no controllers found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
key := &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace}}
|
||||
items, err := s.Indexer.Index(NamespaceIndex, key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, m := range items {
|
||||
rc = *m.(*api.ReplicationController)
|
||||
selector = labels.Set(rc.Spec.Selector).AsSelectorPreValidated()
|
||||
|
||||
// If an rc with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
controllers = append(controllers, rc)
|
||||
}
|
||||
if len(controllers) == 0 {
|
||||
err = fmt.Errorf("could not find controller for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StoreToDeploymentLister gives a store List and Exists methods. The store must contain only Deployments.
|
||||
type StoreToDeploymentLister struct {
|
||||
Indexer
|
||||
}
|
||||
|
||||
// Exists checks if the given deployment exists in the store.
|
||||
func (s *StoreToDeploymentLister) Exists(deployment *extensions.Deployment) (bool, error) {
|
||||
_, exists, err := s.Indexer.Get(deployment)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
// StoreToDeploymentLister lists all deployments in the store.
|
||||
// TODO: converge on the interface in pkg/client
|
||||
func (s *StoreToDeploymentLister) List() (deployments []extensions.Deployment, err error) {
|
||||
for _, c := range s.Indexer.List() {
|
||||
deployments = append(deployments, *(c.(*extensions.Deployment)))
|
||||
}
|
||||
return deployments, nil
|
||||
}
|
||||
|
||||
// GetDeploymentsForReplicaSet returns a list of deployments managing a replica set. Returns an error only if no matching deployments are found.
|
||||
func (s *StoreToDeploymentLister) GetDeploymentsForReplicaSet(rs *extensions.ReplicaSet) (deployments []extensions.Deployment, err error) {
|
||||
if len(rs.Labels) == 0 {
|
||||
err = fmt.Errorf("no deployments found for ReplicaSet %v because it has no labels", rs.Name)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: MODIFY THIS METHOD so that it checks for the podTemplateSpecHash label
|
||||
dList, err := s.Deployments(rs.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, d := range dList {
|
||||
selector, err := unversioned.LabelSelectorAsSelector(d.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid label selector: %v", err)
|
||||
}
|
||||
// If a deployment with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(rs.Labels)) {
|
||||
continue
|
||||
}
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
if len(deployments) == 0 {
|
||||
err = fmt.Errorf("could not find deployments set for ReplicaSet %s in namespace %s with labels: %v", rs.Name, rs.Namespace, rs.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type storeToDeploymentNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// storeToDeploymentNamespacer lists deployments under its namespace in the store.
|
||||
func (s storeToDeploymentNamespacer) List(selector labels.Selector) (deployments []extensions.Deployment, err error) {
|
||||
if s.namespace == api.NamespaceAll {
|
||||
for _, m := range s.indexer.List() {
|
||||
d := *(m.(*extensions.Deployment))
|
||||
if selector.Matches(labels.Set(d.Labels)) {
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
key := &extensions.Deployment{ObjectMeta: api.ObjectMeta{Namespace: s.namespace}}
|
||||
items, err := s.indexer.Index(NamespaceIndex, key)
|
||||
if err != nil {
|
||||
// Ignore error; do slow search without index.
|
||||
glog.Warningf("can not retrieve list of objects using index : %v", err)
|
||||
for _, m := range s.indexer.List() {
|
||||
d := *(m.(*extensions.Deployment))
|
||||
if s.namespace == d.Namespace && selector.Matches(labels.Set(d.Labels)) {
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
}
|
||||
return deployments, nil
|
||||
}
|
||||
for _, m := range items {
|
||||
d := *(m.(*extensions.Deployment))
|
||||
if selector.Matches(labels.Set(d.Labels)) {
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *StoreToDeploymentLister) Deployments(namespace string) storeToDeploymentNamespacer {
|
||||
return storeToDeploymentNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
// GetDeploymentsForPods returns a list of deployments managing a pod. Returns an error only if no matching deployments are found.
|
||||
func (s *StoreToDeploymentLister) GetDeploymentsForPod(pod *api.Pod) (deployments []extensions.Deployment, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no deployments found for Pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
if len(pod.Labels[extensions.DefaultDeploymentUniqueLabelKey]) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
dList, err := s.Deployments(pod.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, d := range dList {
|
||||
selector, err := unversioned.LabelSelectorAsSelector(d.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid label selector: %v", err)
|
||||
}
|
||||
// If a deployment with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
if len(deployments) == 0 {
|
||||
err = fmt.Errorf("could not find deployments set for Pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StoreToReplicaSetLister gives a store List and Exists methods. The store must contain only ReplicaSets.
|
||||
type StoreToReplicaSetLister struct {
|
||||
Store
|
||||
}
|
||||
|
||||
// Exists checks if the given ReplicaSet exists in the store.
|
||||
func (s *StoreToReplicaSetLister) Exists(rs *extensions.ReplicaSet) (bool, error) {
|
||||
_, exists, err := s.Store.Get(rs)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
// List lists all ReplicaSets in the store.
|
||||
// TODO: converge on the interface in pkg/client
|
||||
func (s *StoreToReplicaSetLister) List() (rss []extensions.ReplicaSet, err error) {
|
||||
for _, rs := range s.Store.List() {
|
||||
rss = append(rss, *(rs.(*extensions.ReplicaSet)))
|
||||
}
|
||||
return rss, nil
|
||||
}
|
||||
|
||||
type storeReplicaSetsNamespacer struct {
|
||||
store Store
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeReplicaSetsNamespacer) List(selector labels.Selector) (rss []extensions.ReplicaSet, err error) {
|
||||
for _, c := range s.store.List() {
|
||||
rs := *(c.(*extensions.ReplicaSet))
|
||||
if s.namespace == api.NamespaceAll || s.namespace == rs.Namespace {
|
||||
if selector.Matches(labels.Set(rs.Labels)) {
|
||||
rss = append(rss, rs)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s storeReplicaSetsNamespacer) Get(name string) (*extensions.ReplicaSet, error) {
|
||||
obj, exists, err := s.store.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(extensions.Resource("replicaset"), name)
|
||||
}
|
||||
return obj.(*extensions.ReplicaSet), nil
|
||||
}
|
||||
|
||||
func (s *StoreToReplicaSetLister) ReplicaSets(namespace string) storeReplicaSetsNamespacer {
|
||||
return storeReplicaSetsNamespacer{s.Store, namespace}
|
||||
}
|
||||
|
||||
// GetPodReplicaSets returns a list of ReplicaSets managing a pod. Returns an error only if no matching ReplicaSets are found.
|
||||
func (s *StoreToReplicaSetLister) GetPodReplicaSets(pod *api.Pod) (rss []extensions.ReplicaSet, err error) {
|
||||
var selector labels.Selector
|
||||
var rs extensions.ReplicaSet
|
||||
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no ReplicaSets found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
for _, m := range s.Store.List() {
|
||||
rs = *m.(*extensions.ReplicaSet)
|
||||
if rs.Namespace != pod.Namespace {
|
||||
continue
|
||||
}
|
||||
selector, err = unversioned.LabelSelectorAsSelector(rs.Spec.Selector)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid selector: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// If a ReplicaSet with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
rss = append(rss, rs)
|
||||
}
|
||||
if len(rss) == 0 {
|
||||
err = fmt.Errorf("could not find ReplicaSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StoreToDaemonSetLister gives a store List and Exists methods. The store must contain only DaemonSets.
|
||||
type StoreToDaemonSetLister struct {
|
||||
Store
|
||||
|
|
@ -555,47 +268,6 @@ func (s *StoreToDaemonSetLister) GetPodDaemonSets(pod *api.Pod) (daemonSets []ex
|
|||
return
|
||||
}
|
||||
|
||||
// StoreToServiceLister makes a Store that has the List method of the client.ServiceInterface
|
||||
// The Store must contain (only) Services.
|
||||
type StoreToServiceLister struct {
|
||||
Store
|
||||
}
|
||||
|
||||
func (s *StoreToServiceLister) List() (services api.ServiceList, err error) {
|
||||
for _, m := range s.Store.List() {
|
||||
services.Items = append(services.Items, *(m.(*api.Service)))
|
||||
}
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// TODO: Move this back to scheduler as a helper function that takes a Store,
|
||||
// rather than a method of StoreToServiceLister.
|
||||
func (s *StoreToServiceLister) GetPodServices(pod *api.Pod) (services []api.Service, err error) {
|
||||
var selector labels.Selector
|
||||
var service api.Service
|
||||
|
||||
for _, m := range s.Store.List() {
|
||||
service = *m.(*api.Service)
|
||||
// consider only services that are in the same namespace as the pod
|
||||
if service.Namespace != pod.Namespace {
|
||||
continue
|
||||
}
|
||||
if service.Spec.Selector == nil {
|
||||
// services with nil selectors match nothing, not everything.
|
||||
continue
|
||||
}
|
||||
selector = labels.Set(service.Spec.Selector).AsSelectorPreValidated()
|
||||
if selector.Matches(labels.Set(pod.Labels)) {
|
||||
services = append(services, service)
|
||||
}
|
||||
}
|
||||
if len(services) == 0 {
|
||||
err = fmt.Errorf("could not find service for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// StoreToEndpointsLister makes a Store that lists endpoints.
|
||||
type StoreToEndpointsLister struct {
|
||||
Store
|
||||
|
|
@ -621,56 +293,6 @@ func (s *StoreToEndpointsLister) GetServiceEndpoints(svc *api.Service) (ep api.E
|
|||
return
|
||||
}
|
||||
|
||||
// StoreToJobLister gives a store List and Exists methods. The store must contain only Jobs.
|
||||
type StoreToJobLister struct {
|
||||
Store
|
||||
}
|
||||
|
||||
// Exists checks if the given job exists in the store.
|
||||
func (s *StoreToJobLister) Exists(job *batch.Job) (bool, error) {
|
||||
_, exists, err := s.Store.Get(job)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
// StoreToJobLister lists all jobs in the store.
|
||||
func (s *StoreToJobLister) List() (jobs batch.JobList, err error) {
|
||||
for _, c := range s.Store.List() {
|
||||
jobs.Items = append(jobs.Items, *(c.(*batch.Job)))
|
||||
}
|
||||
return jobs, nil
|
||||
}
|
||||
|
||||
// GetPodJobs returns a list of jobs managing a pod. Returns an error only if no matching jobs are found.
|
||||
func (s *StoreToJobLister) GetPodJobs(pod *api.Pod) (jobs []batch.Job, err error) {
|
||||
var selector labels.Selector
|
||||
var job batch.Job
|
||||
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no jobs found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
for _, m := range s.Store.List() {
|
||||
job = *m.(*batch.Job)
|
||||
if job.Namespace != pod.Namespace {
|
||||
continue
|
||||
}
|
||||
|
||||
selector, _ = unversioned.LabelSelectorAsSelector(job.Spec.Selector)
|
||||
if !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
jobs = append(jobs, job)
|
||||
}
|
||||
if len(jobs) == 0 {
|
||||
err = fmt.Errorf("could not find jobs for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Typed wrapper around a store of PersistentVolumes
|
||||
type StoreToPVFetcher struct {
|
||||
Store
|
||||
|
|
@ -691,32 +313,13 @@ func (s *StoreToPVFetcher) GetPersistentVolumeInfo(id string) (*api.PersistentVo
|
|||
return o.(*api.PersistentVolume), nil
|
||||
}
|
||||
|
||||
// Typed wrapper around a store of PersistentVolumeClaims
|
||||
type StoreToPVCFetcher struct {
|
||||
// StoreToStatefulSetLister gives a store List and Exists methods. The store must contain only StatefulSets.
|
||||
type StoreToStatefulSetLister struct {
|
||||
Store
|
||||
}
|
||||
|
||||
// GetPersistentVolumeClaimInfo returns cached data for the PersistentVolumeClaim 'id'.
|
||||
func (s *StoreToPVCFetcher) GetPersistentVolumeClaimInfo(namespace string, id string) (*api.PersistentVolumeClaim, error) {
|
||||
o, exists, err := s.Get(&api.PersistentVolumeClaim{ObjectMeta: api.ObjectMeta{Namespace: namespace, Name: id}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving PersistentVolumeClaim '%s/%s' from cache: %v", namespace, id, err)
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("PersistentVolumeClaim '%s/%s' not found", namespace, id)
|
||||
}
|
||||
|
||||
return o.(*api.PersistentVolumeClaim), nil
|
||||
}
|
||||
|
||||
// StoreToPetSetLister gives a store List and Exists methods. The store must contain only PetSets.
|
||||
type StoreToPetSetLister struct {
|
||||
Store
|
||||
}
|
||||
|
||||
// Exists checks if the given PetSet exists in the store.
|
||||
func (s *StoreToPetSetLister) Exists(ps *apps.PetSet) (bool, error) {
|
||||
// Exists checks if the given StatefulSet exists in the store.
|
||||
func (s *StoreToStatefulSetLister) Exists(ps *apps.StatefulSet) (bool, error) {
|
||||
_, exists, err := s.Store.Get(ps)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
|
@ -724,35 +327,35 @@ func (s *StoreToPetSetLister) Exists(ps *apps.PetSet) (bool, error) {
|
|||
return exists, nil
|
||||
}
|
||||
|
||||
// List lists all PetSets in the store.
|
||||
func (s *StoreToPetSetLister) List() (psList []apps.PetSet, err error) {
|
||||
// List lists all StatefulSets in the store.
|
||||
func (s *StoreToStatefulSetLister) List() (psList []apps.StatefulSet, err error) {
|
||||
for _, ps := range s.Store.List() {
|
||||
psList = append(psList, *(ps.(*apps.PetSet)))
|
||||
psList = append(psList, *(ps.(*apps.StatefulSet)))
|
||||
}
|
||||
return psList, nil
|
||||
}
|
||||
|
||||
type storePetSetsNamespacer struct {
|
||||
type storeStatefulSetsNamespacer struct {
|
||||
store Store
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s *StoreToPetSetLister) PetSets(namespace string) storePetSetsNamespacer {
|
||||
return storePetSetsNamespacer{s.Store, namespace}
|
||||
func (s *StoreToStatefulSetLister) StatefulSets(namespace string) storeStatefulSetsNamespacer {
|
||||
return storeStatefulSetsNamespacer{s.Store, namespace}
|
||||
}
|
||||
|
||||
// GetPodPetSets returns a list of PetSets managing a pod. Returns an error only if no matching PetSets are found.
|
||||
func (s *StoreToPetSetLister) GetPodPetSets(pod *api.Pod) (psList []apps.PetSet, err error) {
|
||||
// GetPodStatefulSets returns a list of StatefulSets managing a pod. Returns an error only if no matching StatefulSets are found.
|
||||
func (s *StoreToStatefulSetLister) GetPodStatefulSets(pod *api.Pod) (psList []apps.StatefulSet, err error) {
|
||||
var selector labels.Selector
|
||||
var ps apps.PetSet
|
||||
var ps apps.StatefulSet
|
||||
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no PetSets found for pod %v because it has no labels", pod.Name)
|
||||
err = fmt.Errorf("no StatefulSets found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
for _, m := range s.Store.List() {
|
||||
ps = *m.(*apps.PetSet)
|
||||
ps = *m.(*apps.StatefulSet)
|
||||
if ps.Namespace != pod.Namespace {
|
||||
continue
|
||||
}
|
||||
|
|
@ -762,14 +365,14 @@ func (s *StoreToPetSetLister) GetPodPetSets(pod *api.Pod) (psList []apps.PetSet,
|
|||
return
|
||||
}
|
||||
|
||||
// If a PetSet with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
// If a StatefulSet with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
psList = append(psList, ps)
|
||||
}
|
||||
if len(psList) == 0 {
|
||||
err = fmt.Errorf("could not find PetSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
err = fmt.Errorf("could not find StatefulSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -796,23 +399,6 @@ func (s *StoreToCertificateRequestLister) List() (csrs certificates.CertificateS
|
|||
return csrs, nil
|
||||
}
|
||||
|
||||
// IndexerToNamespaceLister gives an Indexer List method
|
||||
type IndexerToNamespaceLister struct {
|
||||
Indexer
|
||||
}
|
||||
|
||||
// List returns a list of namespaces
|
||||
func (i *IndexerToNamespaceLister) List(selector labels.Selector) (namespaces []*api.Namespace, err error) {
|
||||
for _, m := range i.Indexer.List() {
|
||||
namespace := m.(*api.Namespace)
|
||||
if selector.Matches(labels.Set(namespace.Labels)) {
|
||||
namespaces = append(namespaces, namespace)
|
||||
}
|
||||
}
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
type StoreToPodDisruptionBudgetLister struct {
|
||||
Store
|
||||
}
|
||||
|
|
@ -853,3 +439,40 @@ func (s *StoreToPodDisruptionBudgetLister) GetPodPodDisruptionBudgets(pod *api.P
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StorageClassLister knows how to list storage classes
|
||||
type StorageClassLister interface {
|
||||
List(selector labels.Selector) (ret []*storage.StorageClass, err error)
|
||||
Get(name string) (*storage.StorageClass, error)
|
||||
}
|
||||
|
||||
// storageClassLister implements StorageClassLister
|
||||
type storageClassLister struct {
|
||||
indexer Indexer
|
||||
}
|
||||
|
||||
// NewStorageClassLister returns a new lister.
|
||||
func NewStorageClassLister(indexer Indexer) StorageClassLister {
|
||||
return &storageClassLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List returns a list of storage classes
|
||||
func (s *storageClassLister) List(selector labels.Selector) (ret []*storage.StorageClass, err error) {
|
||||
err = ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*storage.StorageClass))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// List returns a list of storage classes
|
||||
func (s *storageClassLister) Get(name string) (*storage.StorageClass, error) {
|
||||
key := &storage.StorageClass{ObjectMeta: api.ObjectMeta{Name: name}}
|
||||
obj, exists, err := s.indexer.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(storage.Resource("storageclass"), name)
|
||||
}
|
||||
return obj.(*storage.StorageClass), nil
|
||||
}
|
||||
|
|
|
|||
348
vendor/k8s.io/kubernetes/pkg/client/cache/listers_core.go
generated
vendored
Normal file
348
vendor/k8s.io/kubernetes/pkg/client/cache/listers_core.go
generated
vendored
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
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 cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
// TODO: generate these classes and methods for all resources of interest using
|
||||
// a script. Can use "go generate" once 1.4 is supported by all users.
|
||||
|
||||
// Lister makes an Index have the List method. The Stores must contain only the expected type
|
||||
// Example:
|
||||
// s := cache.NewStore()
|
||||
// lw := cache.ListWatch{Client: c, FieldSelector: sel, Resource: "pods"}
|
||||
// r := cache.NewReflector(lw, &api.Pod{}, s).Run()
|
||||
// l := StoreToPodLister{s}
|
||||
// l.List()
|
||||
|
||||
// StoreToPodLister helps list pods
|
||||
type StoreToPodLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToPodLister) List(selector labels.Selector) (ret []*api.Pod, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Pod))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToPodLister) Pods(namespace string) storePodsNamespacer {
|
||||
return storePodsNamespacer{Indexer: s.Indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
type storePodsNamespacer struct {
|
||||
Indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storePodsNamespacer) List(selector labels.Selector) (ret []*api.Pod, err error) {
|
||||
err = ListAllByNamespace(s.Indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Pod))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storePodsNamespacer) Get(name string) (*api.Pod, error) {
|
||||
obj, exists, err := s.Indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("pod"), name)
|
||||
}
|
||||
return obj.(*api.Pod), nil
|
||||
}
|
||||
|
||||
// StoreToServiceLister helps list services
|
||||
type StoreToServiceLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToServiceLister) List(selector labels.Selector) (ret []*api.Service, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Service))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToServiceLister) Services(namespace string) storeServicesNamespacer {
|
||||
return storeServicesNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
type storeServicesNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeServicesNamespacer) List(selector labels.Selector) (ret []*api.Service, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Service))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeServicesNamespacer) Get(name string) (*api.Service, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("service"), name)
|
||||
}
|
||||
return obj.(*api.Service), nil
|
||||
}
|
||||
|
||||
// TODO: Move this back to scheduler as a helper function that takes a Store,
|
||||
// rather than a method of StoreToServiceLister.
|
||||
func (s *StoreToServiceLister) GetPodServices(pod *api.Pod) (services []*api.Service, err error) {
|
||||
allServices, err := s.Services(pod.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range allServices {
|
||||
service := allServices[i]
|
||||
if service.Spec.Selector == nil {
|
||||
// services with nil selectors match nothing, not everything.
|
||||
continue
|
||||
}
|
||||
selector := labels.Set(service.Spec.Selector).AsSelectorPreValidated()
|
||||
if selector.Matches(labels.Set(pod.Labels)) {
|
||||
services = append(services, service)
|
||||
}
|
||||
}
|
||||
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// StoreToReplicationControllerLister helps list rcs
|
||||
type StoreToReplicationControllerLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToReplicationControllerLister) List(selector labels.Selector) (ret []*api.ReplicationController, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ReplicationController))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToReplicationControllerLister) ReplicationControllers(namespace string) storeReplicationControllersNamespacer {
|
||||
return storeReplicationControllersNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
type storeReplicationControllersNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeReplicationControllersNamespacer) List(selector labels.Selector) (ret []*api.ReplicationController, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ReplicationController))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeReplicationControllersNamespacer) Get(name string) (*api.ReplicationController, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("replicationcontroller"), name)
|
||||
}
|
||||
return obj.(*api.ReplicationController), nil
|
||||
}
|
||||
|
||||
// GetPodControllers returns a list of replication controllers managing a pod. Returns an error only if no matching controllers are found.
|
||||
func (s *StoreToReplicationControllerLister) GetPodControllers(pod *api.Pod) (controllers []*api.ReplicationController, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no controllers found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
key := &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace}}
|
||||
items, err := s.Indexer.Index(NamespaceIndex, key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, m := range items {
|
||||
rc := m.(*api.ReplicationController)
|
||||
selector := labels.Set(rc.Spec.Selector).AsSelectorPreValidated()
|
||||
|
||||
// If an rc with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
controllers = append(controllers, rc)
|
||||
}
|
||||
if len(controllers) == 0 {
|
||||
err = fmt.Errorf("could not find controller for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StoreToServiceAccountLister helps list service accounts
|
||||
type StoreToServiceAccountLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToServiceAccountLister) List(selector labels.Selector) (ret []*api.ServiceAccount, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ServiceAccount))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToServiceAccountLister) ServiceAccounts(namespace string) storeServiceAccountsNamespacer {
|
||||
return storeServiceAccountsNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
type storeServiceAccountsNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeServiceAccountsNamespacer) List(selector labels.Selector) (ret []*api.ServiceAccount, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ServiceAccount))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeServiceAccountsNamespacer) Get(name string) (*api.ServiceAccount, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("serviceaccount"), name)
|
||||
}
|
||||
return obj.(*api.ServiceAccount), nil
|
||||
}
|
||||
|
||||
// StoreToLimitRangeLister helps list limit ranges
|
||||
type StoreToLimitRangeLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToLimitRangeLister) List(selector labels.Selector) (ret []*api.LimitRange, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.LimitRange))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// StoreToPersistentVolumeClaimLister helps list pvcs
|
||||
type StoreToPersistentVolumeClaimLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
// List returns all persistentvolumeclaims that match the specified selector
|
||||
func (s *StoreToPersistentVolumeClaimLister) List(selector labels.Selector) (ret []*api.PersistentVolumeClaim, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.PersistentVolumeClaim))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToLimitRangeLister) LimitRanges(namespace string) storeLimitRangesNamespacer {
|
||||
return storeLimitRangesNamespacer{s.Indexer, namespace}
|
||||
}
|
||||
|
||||
type storeLimitRangesNamespacer struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeLimitRangesNamespacer) List(selector labels.Selector) (ret []*api.LimitRange, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.LimitRange))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeLimitRangesNamespacer) Get(name string) (*api.LimitRange, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("limitrange"), name)
|
||||
}
|
||||
return obj.(*api.LimitRange), nil
|
||||
}
|
||||
|
||||
// PersistentVolumeClaims returns all claims in a specified namespace.
|
||||
func (s *StoreToPersistentVolumeClaimLister) PersistentVolumeClaims(namespace string) storePersistentVolumeClaimsNamespacer {
|
||||
return storePersistentVolumeClaimsNamespacer{Indexer: s.Indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
type storePersistentVolumeClaimsNamespacer struct {
|
||||
Indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storePersistentVolumeClaimsNamespacer) List(selector labels.Selector) (ret []*api.PersistentVolumeClaim, err error) {
|
||||
err = ListAllByNamespace(s.Indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.PersistentVolumeClaim))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storePersistentVolumeClaimsNamespacer) Get(name string) (*api.PersistentVolumeClaim, error) {
|
||||
obj, exists, err := s.Indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("persistentvolumeclaims"), name)
|
||||
}
|
||||
return obj.(*api.PersistentVolumeClaim), nil
|
||||
}
|
||||
|
||||
// IndexerToNamespaceLister gives an Indexer List method
|
||||
type IndexerToNamespaceLister struct {
|
||||
Indexer
|
||||
}
|
||||
|
||||
// List returns a list of namespaces
|
||||
func (i *IndexerToNamespaceLister) List(selector labels.Selector) (ret []*api.Namespace, err error) {
|
||||
err = ListAll(i.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Namespace))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (i *IndexerToNamespaceLister) Get(name string) (*api.Namespace, error) {
|
||||
obj, exists, err := i.Indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("namespace"), name)
|
||||
}
|
||||
return obj.(*api.Namespace), nil
|
||||
}
|
||||
210
vendor/k8s.io/kubernetes/pkg/client/cache/listers_extensions.go
generated
vendored
Normal file
210
vendor/k8s.io/kubernetes/pkg/client/cache/listers_extensions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
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 cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
// TODO: generate these classes and methods for all resources of interest using
|
||||
// a script. Can use "go generate" once 1.4 is supported by all users.
|
||||
|
||||
// Lister makes an Index have the List method. The Stores must contain only the expected type
|
||||
// Example:
|
||||
// s := cache.NewStore()
|
||||
// lw := cache.ListWatch{Client: c, FieldSelector: sel, Resource: "pods"}
|
||||
// r := cache.NewReflector(lw, &extensions.Deployment{}, s).Run()
|
||||
// l := StoreToDeploymentLister{s}
|
||||
// l.List()
|
||||
|
||||
// StoreToDeploymentLister helps list deployments
|
||||
type StoreToDeploymentLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToDeploymentLister) List(selector labels.Selector) (ret []*extensions.Deployment, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*extensions.Deployment))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToDeploymentLister) Deployments(namespace string) storeDeploymentsNamespacer {
|
||||
return storeDeploymentsNamespacer{Indexer: s.Indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
type storeDeploymentsNamespacer struct {
|
||||
Indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeDeploymentsNamespacer) List(selector labels.Selector) (ret []*extensions.Deployment, err error) {
|
||||
err = ListAllByNamespace(s.Indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*extensions.Deployment))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeDeploymentsNamespacer) Get(name string) (*extensions.Deployment, error) {
|
||||
obj, exists, err := s.Indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(extensions.Resource("deployment"), name)
|
||||
}
|
||||
return obj.(*extensions.Deployment), nil
|
||||
}
|
||||
|
||||
// GetDeploymentsForReplicaSet returns a list of deployments managing a replica set. Returns an error only if no matching deployments are found.
|
||||
func (s *StoreToDeploymentLister) GetDeploymentsForReplicaSet(rs *extensions.ReplicaSet) (deployments []*extensions.Deployment, err error) {
|
||||
if len(rs.Labels) == 0 {
|
||||
err = fmt.Errorf("no deployments found for ReplicaSet %v because it has no labels", rs.Name)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: MODIFY THIS METHOD so that it checks for the podTemplateSpecHash label
|
||||
dList, err := s.Deployments(rs.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, d := range dList {
|
||||
selector, err := unversioned.LabelSelectorAsSelector(d.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid label selector: %v", err)
|
||||
}
|
||||
// If a deployment with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(rs.Labels)) {
|
||||
continue
|
||||
}
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
if len(deployments) == 0 {
|
||||
err = fmt.Errorf("could not find deployments set for ReplicaSet %s in namespace %s with labels: %v", rs.Name, rs.Namespace, rs.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDeploymentsForDeployments returns a list of deployments managing a pod. Returns an error only if no matching deployments are found.
|
||||
// TODO eliminate shallow copies
|
||||
func (s *StoreToDeploymentLister) GetDeploymentsForPod(pod *api.Pod) (deployments []*extensions.Deployment, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no deployments found for Pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
if len(pod.Labels[extensions.DefaultDeploymentUniqueLabelKey]) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
dList, err := s.Deployments(pod.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, d := range dList {
|
||||
selector, err := unversioned.LabelSelectorAsSelector(d.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid label selector: %v", err)
|
||||
}
|
||||
// If a deployment with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
deployments = append(deployments, d)
|
||||
}
|
||||
if len(deployments) == 0 {
|
||||
err = fmt.Errorf("could not find deployments set for Pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StoreToReplicaSetLister helps list replicasets
|
||||
type StoreToReplicaSetLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToReplicaSetLister) List(selector labels.Selector) (ret []*extensions.ReplicaSet, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*extensions.ReplicaSet))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *StoreToReplicaSetLister) ReplicaSets(namespace string) storeReplicaSetsNamespacer {
|
||||
return storeReplicaSetsNamespacer{Indexer: s.Indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
type storeReplicaSetsNamespacer struct {
|
||||
Indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeReplicaSetsNamespacer) List(selector labels.Selector) (ret []*extensions.ReplicaSet, err error) {
|
||||
err = ListAllByNamespace(s.Indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*extensions.ReplicaSet))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeReplicaSetsNamespacer) Get(name string) (*extensions.ReplicaSet, error) {
|
||||
obj, exists, err := s.Indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(extensions.Resource("replicaset"), name)
|
||||
}
|
||||
return obj.(*extensions.ReplicaSet), nil
|
||||
}
|
||||
|
||||
// GetPodReplicaSets returns a list of ReplicaSets managing a pod. Returns an error only if no matching ReplicaSets are found.
|
||||
func (s *StoreToReplicaSetLister) GetPodReplicaSets(pod *api.Pod) (rss []*extensions.ReplicaSet, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no ReplicaSets found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := s.ReplicaSets(pod.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, rs := range list {
|
||||
if rs.Namespace != pod.Namespace {
|
||||
continue
|
||||
}
|
||||
selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid selector: %v", err)
|
||||
}
|
||||
|
||||
// If a ReplicaSet with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
rss = append(rss, rs)
|
||||
}
|
||||
if len(rss) == 0 {
|
||||
err = fmt.Errorf("could not find ReplicaSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
return
|
||||
}
|
||||
234
vendor/k8s.io/kubernetes/pkg/client/cache/listers_rbac.go
generated
vendored
Normal file
234
vendor/k8s.io/kubernetes/pkg/client/cache/listers_rbac.go
generated
vendored
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
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 cache
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
// TODO: generate these classes and methods for all resources of interest using
|
||||
// a script. Can use "go generate" once 1.4 is supported by all users.
|
||||
|
||||
// Lister makes an Index have the List method. The Stores must contain only the expected type
|
||||
// Example:
|
||||
// s := cache.NewStore()
|
||||
// lw := cache.ListWatch{Client: c, FieldSelector: sel, Resource: "pods"}
|
||||
// r := cache.NewReflector(lw, &rbac.ClusterRole{}, s).Run()
|
||||
// l := clusterRoleLister{s}
|
||||
// l.List()
|
||||
|
||||
func NewClusterRoleLister(indexer Indexer) ClusterRoleLister {
|
||||
return &clusterRoleLister{indexer: indexer}
|
||||
}
|
||||
func NewClusterRoleBindingLister(indexer Indexer) ClusterRoleBindingLister {
|
||||
return &clusterRoleBindingLister{indexer: indexer}
|
||||
}
|
||||
func NewRoleLister(indexer Indexer) RoleLister {
|
||||
return &roleLister{indexer: indexer}
|
||||
}
|
||||
func NewRoleBindingLister(indexer Indexer) RoleBindingLister {
|
||||
return &roleBindingLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// these interfaces are used by the rbac authorizer
|
||||
type authorizerClusterRoleGetter interface {
|
||||
GetClusterRole(name string) (*rbac.ClusterRole, error)
|
||||
}
|
||||
|
||||
type authorizerClusterRoleBindingLister interface {
|
||||
ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error)
|
||||
}
|
||||
|
||||
type authorizerRoleGetter interface {
|
||||
GetRole(namespace, name string) (*rbac.Role, error)
|
||||
}
|
||||
|
||||
type authorizerRoleBindingLister interface {
|
||||
ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error)
|
||||
}
|
||||
|
||||
type ClusterRoleLister interface {
|
||||
authorizerClusterRoleGetter
|
||||
List(selector labels.Selector) (ret []*rbac.ClusterRole, err error)
|
||||
Get(name string) (*rbac.ClusterRole, error)
|
||||
}
|
||||
|
||||
type clusterRoleLister struct {
|
||||
indexer Indexer
|
||||
}
|
||||
|
||||
func (s *clusterRoleLister) List(selector labels.Selector) (ret []*rbac.ClusterRole, err error) {
|
||||
err = ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*rbac.ClusterRole))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s clusterRoleLister) Get(name string) (*rbac.ClusterRole, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(rbac.Resource("clusterrole"), name)
|
||||
}
|
||||
return obj.(*rbac.ClusterRole), nil
|
||||
}
|
||||
|
||||
func (s clusterRoleLister) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
||||
return s.Get(name)
|
||||
}
|
||||
|
||||
type ClusterRoleBindingLister interface {
|
||||
authorizerClusterRoleBindingLister
|
||||
List(selector labels.Selector) (ret []*rbac.ClusterRoleBinding, err error)
|
||||
Get(name string) (*rbac.ClusterRoleBinding, error)
|
||||
}
|
||||
|
||||
type clusterRoleBindingLister struct {
|
||||
indexer Indexer
|
||||
}
|
||||
|
||||
func (s *clusterRoleBindingLister) List(selector labels.Selector) (ret []*rbac.ClusterRoleBinding, err error) {
|
||||
err = ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*rbac.ClusterRoleBinding))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s clusterRoleBindingLister) Get(name string) (*rbac.ClusterRoleBinding, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(rbac.Resource("clusterrolebinding"), name)
|
||||
}
|
||||
return obj.(*rbac.ClusterRoleBinding), nil
|
||||
}
|
||||
|
||||
func (s clusterRoleBindingLister) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
||||
return s.List(labels.Everything())
|
||||
}
|
||||
|
||||
type RoleLister interface {
|
||||
authorizerRoleGetter
|
||||
List(selector labels.Selector) (ret []*rbac.Role, err error)
|
||||
Roles(namespace string) RoleNamespaceLister
|
||||
}
|
||||
|
||||
type RoleNamespaceLister interface {
|
||||
List(selector labels.Selector) (ret []*rbac.Role, err error)
|
||||
Get(name string) (*rbac.Role, error)
|
||||
}
|
||||
|
||||
type roleLister struct {
|
||||
indexer Indexer
|
||||
}
|
||||
|
||||
func (s *roleLister) List(selector labels.Selector) (ret []*rbac.Role, err error) {
|
||||
err = ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*rbac.Role))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *roleLister) Roles(namespace string) RoleNamespaceLister {
|
||||
return roleNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
func (s roleLister) GetRole(namespace, name string) (*rbac.Role, error) {
|
||||
return s.Roles(namespace).Get(name)
|
||||
}
|
||||
|
||||
type roleNamespaceLister struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s roleNamespaceLister) List(selector labels.Selector) (ret []*rbac.Role, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*rbac.Role))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s roleNamespaceLister) Get(name string) (*rbac.Role, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(rbac.Resource("role"), name)
|
||||
}
|
||||
return obj.(*rbac.Role), nil
|
||||
}
|
||||
|
||||
type RoleBindingLister interface {
|
||||
authorizerRoleBindingLister
|
||||
List(selector labels.Selector) (ret []*rbac.RoleBinding, err error)
|
||||
RoleBindings(namespace string) RoleBindingNamespaceLister
|
||||
}
|
||||
|
||||
type RoleBindingNamespaceLister interface {
|
||||
List(selector labels.Selector) (ret []*rbac.RoleBinding, err error)
|
||||
Get(name string) (*rbac.RoleBinding, error)
|
||||
}
|
||||
|
||||
type roleBindingLister struct {
|
||||
indexer Indexer
|
||||
}
|
||||
|
||||
func (s *roleBindingLister) List(selector labels.Selector) (ret []*rbac.RoleBinding, err error) {
|
||||
err = ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*rbac.RoleBinding))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s *roleBindingLister) RoleBindings(namespace string) RoleBindingNamespaceLister {
|
||||
return roleBindingNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
func (s roleBindingLister) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
||||
return s.RoleBindings(namespace).List(labels.Everything())
|
||||
}
|
||||
|
||||
type roleBindingNamespaceLister struct {
|
||||
indexer Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s roleBindingNamespaceLister) List(selector labels.Selector) (ret []*rbac.RoleBinding, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*rbac.RoleBinding))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s roleBindingNamespaceLister) Get(name string) (*rbac.RoleBinding, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(rbac.Resource("rolebinding"), name)
|
||||
}
|
||||
return obj.(*rbac.RoleBinding), nil
|
||||
}
|
||||
76
vendor/k8s.io/kubernetes/pkg/client/cache/listwatch.go
generated
vendored
76
vendor/k8s.io/kubernetes/pkg/client/cache/listwatch.go
generated
vendored
|
|
@ -20,12 +20,22 @@ import (
|
|||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
// ListerWatcher is any object that knows how to perform an initial list and start a watch on a resource.
|
||||
type ListerWatcher interface {
|
||||
// List should return a list type object; the Items field will be extracted, and the
|
||||
// ResourceVersion field will be used to start the watch in the right place.
|
||||
List(options api.ListOptions) (runtime.Object, error)
|
||||
// Watch should begin a watch at the specified version.
|
||||
Watch(options api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// ListFunc knows how to list resources
|
||||
type ListFunc func(options api.ListOptions) (runtime.Object, error)
|
||||
|
||||
|
|
@ -84,3 +94,69 @@ func (lw *ListWatch) List(options api.ListOptions) (runtime.Object, error) {
|
|||
func (lw *ListWatch) Watch(options api.ListOptions) (watch.Interface, error) {
|
||||
return lw.WatchFunc(options)
|
||||
}
|
||||
|
||||
// TODO: check for watch expired error and retry watch from latest point? Same issue exists for Until.
|
||||
func ListWatchUntil(timeout time.Duration, lw ListerWatcher, conditions ...watch.ConditionFunc) (*watch.Event, error) {
|
||||
if len(conditions) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
list, err := lw.List(api.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
initialItems, err := meta.ExtractList(list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// use the initial items as simulated "adds"
|
||||
var lastEvent *watch.Event
|
||||
currIndex := 0
|
||||
passedConditions := 0
|
||||
for _, condition := range conditions {
|
||||
// check the next condition against the previous event and short circuit waiting for the next watch
|
||||
if lastEvent != nil {
|
||||
done, err := condition(*lastEvent)
|
||||
if err != nil {
|
||||
return lastEvent, err
|
||||
}
|
||||
if done {
|
||||
passedConditions = passedConditions + 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ConditionSucceeded:
|
||||
for currIndex < len(initialItems) {
|
||||
lastEvent = &watch.Event{Type: watch.Added, Object: initialItems[currIndex]}
|
||||
currIndex++
|
||||
|
||||
done, err := condition(*lastEvent)
|
||||
if err != nil {
|
||||
return lastEvent, err
|
||||
}
|
||||
if done {
|
||||
passedConditions = passedConditions + 1
|
||||
break ConditionSucceeded
|
||||
}
|
||||
}
|
||||
}
|
||||
if passedConditions == len(conditions) {
|
||||
return lastEvent, nil
|
||||
}
|
||||
remainingConditions := conditions[passedConditions:]
|
||||
|
||||
metaObj, err := meta.ListAccessor(list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currResourceVersion := metaObj.GetResourceVersion()
|
||||
|
||||
watchInterface, err := lw.Watch(api.ListOptions{ResourceVersion: currResourceVersion})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return watch.Until(timeout, watchInterface, remainingConditions...)
|
||||
}
|
||||
|
|
|
|||
135
vendor/k8s.io/kubernetes/pkg/client/cache/mutation_detector.go
generated
vendored
Normal file
135
vendor/k8s.io/kubernetes/pkg/client/cache/mutation_detector.go
generated
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
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 cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/diff"
|
||||
)
|
||||
|
||||
var mutationDetectionEnabled = false
|
||||
|
||||
func init() {
|
||||
mutationDetectionEnabled, _ = strconv.ParseBool(os.Getenv("KUBE_CACHE_MUTATION_DETECTOR"))
|
||||
}
|
||||
|
||||
type CacheMutationDetector interface {
|
||||
AddObject(obj interface{})
|
||||
Run(stopCh <-chan struct{})
|
||||
}
|
||||
|
||||
func NewCacheMutationDetector(name string) CacheMutationDetector {
|
||||
if !mutationDetectionEnabled {
|
||||
return dummyMutationDetector{}
|
||||
}
|
||||
return &defaultCacheMutationDetector{name: name, period: 1 * time.Second}
|
||||
}
|
||||
|
||||
type dummyMutationDetector struct{}
|
||||
|
||||
func (dummyMutationDetector) Run(stopCh <-chan struct{}) {
|
||||
}
|
||||
func (dummyMutationDetector) AddObject(obj interface{}) {
|
||||
}
|
||||
|
||||
// defaultCacheMutationDetector gives a way to detect if a cached object has been mutated
|
||||
// It has a list of cached objects and their copies. I haven't thought of a way
|
||||
// to see WHO is mutating it, just that it's getting mutated.
|
||||
type defaultCacheMutationDetector struct {
|
||||
name string
|
||||
period time.Duration
|
||||
|
||||
lock sync.Mutex
|
||||
cachedObjs []cacheObj
|
||||
|
||||
// failureFunc is injectable for unit testing. If you don't have it, the process will panic.
|
||||
// This panic is intentional, since turning on this detection indicates you want a strong
|
||||
// failure signal. This failure is effectively a p0 bug and you can't trust process results
|
||||
// after a mutation anyway.
|
||||
failureFunc func(message string)
|
||||
}
|
||||
|
||||
// cacheObj holds the actual object and a copy
|
||||
type cacheObj struct {
|
||||
cached interface{}
|
||||
copied interface{}
|
||||
}
|
||||
|
||||
func (d *defaultCacheMutationDetector) Run(stopCh <-chan struct{}) {
|
||||
// we DON'T want protection from panics. If we're running this code, we want to die
|
||||
go func() {
|
||||
for {
|
||||
d.CompareObjects()
|
||||
|
||||
select {
|
||||
case <-stopCh:
|
||||
return
|
||||
case <-time.After(d.period):
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// AddObject makes a deep copy of the object for later comparison. It only works on runtime.Object
|
||||
// but that covers the vast majority of our cached objects
|
||||
func (d *defaultCacheMutationDetector) AddObject(obj interface{}) {
|
||||
if _, ok := obj.(DeletedFinalStateUnknown); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := obj.(runtime.Object); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
copiedObj, err := api.Scheme.Copy(obj.(runtime.Object))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
d.cachedObjs = append(d.cachedObjs, cacheObj{cached: obj, copied: copiedObj})
|
||||
}
|
||||
|
||||
func (d *defaultCacheMutationDetector) CompareObjects() {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
altered := false
|
||||
for i, obj := range d.cachedObjs {
|
||||
if !reflect.DeepEqual(obj.cached, obj.copied) {
|
||||
fmt.Printf("CACHE %s[%d] ALTERED!\n%v\n", d.name, i, diff.ObjectDiff(obj.cached, obj.copied))
|
||||
altered = true
|
||||
}
|
||||
}
|
||||
|
||||
if altered {
|
||||
msg := fmt.Sprintf("cache %s modified", d.name)
|
||||
if d.failureFunc != nil {
|
||||
d.failureFunc(msg)
|
||||
return
|
||||
}
|
||||
panic(msg)
|
||||
}
|
||||
}
|
||||
11
vendor/k8s.io/kubernetes/pkg/client/cache/reflector.go
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/client/cache/reflector.go
generated
vendored
|
|
@ -43,15 +43,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
// ListerWatcher is any object that knows how to perform an initial list and start a watch on a resource.
|
||||
type ListerWatcher interface {
|
||||
// List should return a list type object; the Items field will be extracted, and the
|
||||
// ResourceVersion field will be used to start the watch in the right place.
|
||||
List(options api.ListOptions) (runtime.Object, error)
|
||||
// Watch should begin a watch at the specified version.
|
||||
Watch(options api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// Reflector watches a specified resource and causes all changes to be reflected in the given store.
|
||||
type Reflector struct {
|
||||
// name identifies this reflector. By default it will be a file:line if possible.
|
||||
|
|
@ -125,7 +116,7 @@ func NewNamedReflector(name string, lw ListerWatcher, expectedType interface{},
|
|||
|
||||
// internalPackages are packages that ignored when creating a default reflector name. These packages are in the common
|
||||
// call chains to NewReflector, so they'd be low entropy names for reflectors
|
||||
var internalPackages = []string{"kubernetes/pkg/client/cache/", "kubernetes/pkg/controller/framework/", "/runtime/asm_"}
|
||||
var internalPackages = []string{"kubernetes/pkg/client/cache/", "/runtime/asm_"}
|
||||
|
||||
// getDefaultReflectorName walks back through the call stack until we find a caller from outside of the ignoredPackages
|
||||
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
|
||||
|
|
|
|||
417
vendor/k8s.io/kubernetes/pkg/client/cache/shared_informer.go
generated
vendored
Normal file
417
vendor/k8s.io/kubernetes/pkg/client/cache/shared_informer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
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 cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// if you use this, there is one behavior change compared to a standard Informer.
|
||||
// When you receive a notification, the cache will be AT LEAST as fresh as the
|
||||
// notification, but it MAY be more fresh. You should NOT depend on the contents
|
||||
// of the cache exactly matching the notification you've received in handler
|
||||
// functions. If there was a create, followed by a delete, the cache may NOT
|
||||
// have your item. This has advantages over the broadcaster since it allows us
|
||||
// to share a common cache across many controllers. Extending the broadcaster
|
||||
// would have required us keep duplicate caches for each watch.
|
||||
type SharedInformer interface {
|
||||
// events to a single handler are delivered sequentially, but there is no coordination between different handlers
|
||||
// You may NOT add a handler *after* the SharedInformer is running. That will result in an error being returned.
|
||||
// TODO we should try to remove this restriction eventually.
|
||||
AddEventHandler(handler ResourceEventHandler) error
|
||||
GetStore() Store
|
||||
// GetController gives back a synthetic interface that "votes" to start the informer
|
||||
GetController() ControllerInterface
|
||||
Run(stopCh <-chan struct{})
|
||||
HasSynced() bool
|
||||
LastSyncResourceVersion() string
|
||||
}
|
||||
|
||||
type SharedIndexInformer interface {
|
||||
SharedInformer
|
||||
// AddIndexers add indexers to the informer before it starts.
|
||||
AddIndexers(indexers Indexers) error
|
||||
GetIndexer() Indexer
|
||||
}
|
||||
|
||||
// NewSharedInformer creates a new instance for the listwatcher.
|
||||
// TODO: create a cache/factory of these at a higher level for the list all, watch all of a given resource that can
|
||||
// be shared amongst all consumers.
|
||||
func NewSharedInformer(lw ListerWatcher, objType runtime.Object, resyncPeriod time.Duration) SharedInformer {
|
||||
return NewSharedIndexInformer(lw, objType, resyncPeriod, Indexers{})
|
||||
}
|
||||
|
||||
// NewSharedIndexInformer creates a new instance for the listwatcher.
|
||||
// TODO: create a cache/factory of these at a higher level for the list all, watch all of a given resource that can
|
||||
// be shared amongst all consumers.
|
||||
func NewSharedIndexInformer(lw ListerWatcher, objType runtime.Object, resyncPeriod time.Duration, indexers Indexers) SharedIndexInformer {
|
||||
sharedIndexInformer := &sharedIndexInformer{
|
||||
processor: &sharedProcessor{},
|
||||
indexer: NewIndexer(DeletionHandlingMetaNamespaceKeyFunc, indexers),
|
||||
listerWatcher: lw,
|
||||
objectType: objType,
|
||||
fullResyncPeriod: resyncPeriod,
|
||||
cacheMutationDetector: NewCacheMutationDetector(fmt.Sprintf("%T", objType)),
|
||||
}
|
||||
return sharedIndexInformer
|
||||
}
|
||||
|
||||
// InformerSynced is a function that can be used to determine if an informer has synced. This is useful for determining if caches have synced.
|
||||
type InformerSynced func() bool
|
||||
|
||||
// syncedPollPeriod controls how often you look at the status of your sync funcs
|
||||
const syncedPollPeriod = 100 * time.Millisecond
|
||||
|
||||
// WaitForCacheSync waits for caches to populate. It returns true if it was successful, false
|
||||
// if the contoller should shutdown
|
||||
func WaitForCacheSync(stopCh <-chan struct{}, cacheSyncs ...InformerSynced) bool {
|
||||
err := wait.PollUntil(syncedPollPeriod,
|
||||
func() (bool, error) {
|
||||
for _, syncFunc := range cacheSyncs {
|
||||
if !syncFunc() {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
stopCh)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("stop requested")
|
||||
return false
|
||||
}
|
||||
|
||||
glog.V(4).Infof("caches populated")
|
||||
return true
|
||||
}
|
||||
|
||||
type sharedIndexInformer struct {
|
||||
indexer Indexer
|
||||
controller *Controller
|
||||
|
||||
processor *sharedProcessor
|
||||
cacheMutationDetector CacheMutationDetector
|
||||
|
||||
// This block is tracked to handle late initialization of the controller
|
||||
listerWatcher ListerWatcher
|
||||
objectType runtime.Object
|
||||
fullResyncPeriod time.Duration
|
||||
|
||||
started bool
|
||||
startedLock sync.Mutex
|
||||
|
||||
// blockDeltas gives a way to stop all event distribution so that a late event handler
|
||||
// can safely join the shared informer.
|
||||
blockDeltas sync.Mutex
|
||||
// stopCh is the channel used to stop the main Run process. We have to track it so that
|
||||
// late joiners can have a proper stop
|
||||
stopCh <-chan struct{}
|
||||
}
|
||||
|
||||
// dummyController hides the fact that a SharedInformer is different from a dedicated one
|
||||
// where a caller can `Run`. The run method is disonnected in this case, because higher
|
||||
// level logic will decide when to start the SharedInformer and related controller.
|
||||
// Because returning information back is always asynchronous, the legacy callers shouldn't
|
||||
// notice any change in behavior.
|
||||
type dummyController struct {
|
||||
informer *sharedIndexInformer
|
||||
}
|
||||
|
||||
func (v *dummyController) Run(stopCh <-chan struct{}) {
|
||||
}
|
||||
|
||||
func (v *dummyController) HasSynced() bool {
|
||||
return v.informer.HasSynced()
|
||||
}
|
||||
|
||||
type updateNotification struct {
|
||||
oldObj interface{}
|
||||
newObj interface{}
|
||||
}
|
||||
|
||||
type addNotification struct {
|
||||
newObj interface{}
|
||||
}
|
||||
|
||||
type deleteNotification struct {
|
||||
oldObj interface{}
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) Run(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
fifo := NewDeltaFIFO(MetaNamespaceKeyFunc, nil, s.indexer)
|
||||
|
||||
cfg := &Config{
|
||||
Queue: fifo,
|
||||
ListerWatcher: s.listerWatcher,
|
||||
ObjectType: s.objectType,
|
||||
FullResyncPeriod: s.fullResyncPeriod,
|
||||
RetryOnError: false,
|
||||
|
||||
Process: s.HandleDeltas,
|
||||
}
|
||||
|
||||
func() {
|
||||
s.startedLock.Lock()
|
||||
defer s.startedLock.Unlock()
|
||||
|
||||
s.controller = New(cfg)
|
||||
s.started = true
|
||||
}()
|
||||
|
||||
s.stopCh = stopCh
|
||||
s.cacheMutationDetector.Run(stopCh)
|
||||
s.processor.run(stopCh)
|
||||
s.controller.Run(stopCh)
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) isStarted() bool {
|
||||
s.startedLock.Lock()
|
||||
defer s.startedLock.Unlock()
|
||||
return s.started
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) HasSynced() bool {
|
||||
s.startedLock.Lock()
|
||||
defer s.startedLock.Unlock()
|
||||
|
||||
if s.controller == nil {
|
||||
return false
|
||||
}
|
||||
return s.controller.HasSynced()
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) LastSyncResourceVersion() string {
|
||||
s.startedLock.Lock()
|
||||
defer s.startedLock.Unlock()
|
||||
|
||||
if s.controller == nil || s.controller.reflector == nil {
|
||||
return ""
|
||||
}
|
||||
return s.controller.reflector.LastSyncResourceVersion()
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) GetStore() Store {
|
||||
return s.indexer
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) GetIndexer() Indexer {
|
||||
return s.indexer
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) AddIndexers(indexers Indexers) error {
|
||||
s.startedLock.Lock()
|
||||
defer s.startedLock.Unlock()
|
||||
|
||||
if s.started {
|
||||
return fmt.Errorf("informer has already started")
|
||||
}
|
||||
|
||||
return s.indexer.AddIndexers(indexers)
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) GetController() ControllerInterface {
|
||||
return &dummyController{informer: s}
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) AddEventHandler(handler ResourceEventHandler) error {
|
||||
s.startedLock.Lock()
|
||||
defer s.startedLock.Unlock()
|
||||
|
||||
if !s.started {
|
||||
listener := newProcessListener(handler)
|
||||
s.processor.listeners = append(s.processor.listeners, listener)
|
||||
return nil
|
||||
}
|
||||
|
||||
// in order to safely join, we have to
|
||||
// 1. stop sending add/update/delete notifications
|
||||
// 2. do a list against the store
|
||||
// 3. send synthetic "Add" events to the new handler
|
||||
// 4. unblock
|
||||
s.blockDeltas.Lock()
|
||||
defer s.blockDeltas.Unlock()
|
||||
|
||||
listener := newProcessListener(handler)
|
||||
s.processor.listeners = append(s.processor.listeners, listener)
|
||||
|
||||
go listener.run(s.stopCh)
|
||||
go listener.pop(s.stopCh)
|
||||
|
||||
items := s.indexer.List()
|
||||
for i := range items {
|
||||
listener.add(addNotification{newObj: items[i]})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sharedIndexInformer) HandleDeltas(obj interface{}) error {
|
||||
s.blockDeltas.Lock()
|
||||
defer s.blockDeltas.Unlock()
|
||||
|
||||
// from oldest to newest
|
||||
for _, d := range obj.(Deltas) {
|
||||
switch d.Type {
|
||||
case Sync, Added, Updated:
|
||||
s.cacheMutationDetector.AddObject(d.Object)
|
||||
if old, exists, err := s.indexer.Get(d.Object); err == nil && exists {
|
||||
if err := s.indexer.Update(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
s.processor.distribute(updateNotification{oldObj: old, newObj: d.Object})
|
||||
} else {
|
||||
if err := s.indexer.Add(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
s.processor.distribute(addNotification{newObj: d.Object})
|
||||
}
|
||||
case Deleted:
|
||||
if err := s.indexer.Delete(d.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
s.processor.distribute(deleteNotification{oldObj: d.Object})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type sharedProcessor struct {
|
||||
listeners []*processorListener
|
||||
}
|
||||
|
||||
func (p *sharedProcessor) distribute(obj interface{}) {
|
||||
for _, listener := range p.listeners {
|
||||
listener.add(obj)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *sharedProcessor) run(stopCh <-chan struct{}) {
|
||||
for _, listener := range p.listeners {
|
||||
go listener.run(stopCh)
|
||||
go listener.pop(stopCh)
|
||||
}
|
||||
}
|
||||
|
||||
type processorListener struct {
|
||||
// lock/cond protects access to 'pendingNotifications'.
|
||||
lock sync.RWMutex
|
||||
cond sync.Cond
|
||||
|
||||
// pendingNotifications is an unbounded slice that holds all notifications not yet distributed
|
||||
// there is one per listener, but a failing/stalled listener will have infinite pendingNotifications
|
||||
// added until we OOM.
|
||||
// TODO This is no worse that before, since reflectors were backed by unbounded DeltaFIFOs, but
|
||||
// we should try to do something better
|
||||
pendingNotifications []interface{}
|
||||
|
||||
nextCh chan interface{}
|
||||
|
||||
handler ResourceEventHandler
|
||||
}
|
||||
|
||||
func newProcessListener(handler ResourceEventHandler) *processorListener {
|
||||
ret := &processorListener{
|
||||
pendingNotifications: []interface{}{},
|
||||
nextCh: make(chan interface{}),
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
ret.cond.L = &ret.lock
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *processorListener) add(notification interface{}) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
p.pendingNotifications = append(p.pendingNotifications, notification)
|
||||
p.cond.Broadcast()
|
||||
}
|
||||
|
||||
func (p *processorListener) pop(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
for {
|
||||
blockingGet := func() (interface{}, bool) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
for len(p.pendingNotifications) == 0 {
|
||||
// check if we're shutdown
|
||||
select {
|
||||
case <-stopCh:
|
||||
return nil, true
|
||||
default:
|
||||
}
|
||||
p.cond.Wait()
|
||||
}
|
||||
|
||||
nt := p.pendingNotifications[0]
|
||||
p.pendingNotifications = p.pendingNotifications[1:]
|
||||
return nt, false
|
||||
}
|
||||
|
||||
notification, stopped := blockingGet()
|
||||
if stopped {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-stopCh:
|
||||
return
|
||||
case p.nextCh <- notification:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *processorListener) run(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
for {
|
||||
var next interface{}
|
||||
select {
|
||||
case <-stopCh:
|
||||
func() {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
p.cond.Broadcast()
|
||||
}()
|
||||
return
|
||||
case next = <-p.nextCh:
|
||||
}
|
||||
|
||||
switch notification := next.(type) {
|
||||
case updateNotification:
|
||||
p.handler.OnUpdate(notification.oldObj, notification.newObj)
|
||||
case addNotification:
|
||||
p.handler.OnAdd(notification.newObj)
|
||||
case deleteNotification:
|
||||
p.handler.OnDelete(notification.oldObj)
|
||||
default:
|
||||
utilruntime.HandleError(fmt.Errorf("unrecognized notification: %#v", next))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue