mirror of
https://github.com/kubernetes/client-go.git
synced 2025-10-22 06:26:40 +00:00
published by bot
(https://github.com/kubernetes/contrib/tree/master/mungegithub) copied from https://github.com/kubernetes/kubernetes.git, branch master, last commit is 1bc5b822cd566321c115d4ebac5d97cfd347d687
This commit is contained in:
51
tools/cache/listers.go
vendored
51
tools/cache/listers.go
vendored
@@ -25,7 +25,6 @@ import (
|
||||
"k8s.io/client-go/pkg/api/meta"
|
||||
"k8s.io/client-go/pkg/api/unversioned"
|
||||
"k8s.io/client-go/pkg/apis/apps"
|
||||
"k8s.io/client-go/pkg/apis/batch"
|
||||
"k8s.io/client-go/pkg/apis/certificates"
|
||||
"k8s.io/client-go/pkg/apis/extensions"
|
||||
"k8s.io/client-go/pkg/apis/policy"
|
||||
@@ -294,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
|
||||
|
172
tools/cache/listers_test.go
vendored
172
tools/cache/listers_test.go
vendored
@@ -22,7 +22,6 @@ import (
|
||||
"k8s.io/client-go/pkg/api"
|
||||
apierrors "k8s.io/client-go/pkg/api/errors"
|
||||
"k8s.io/client-go/pkg/api/unversioned"
|
||||
"k8s.io/client-go/pkg/apis/batch"
|
||||
"k8s.io/client-go/pkg/apis/extensions"
|
||||
"k8s.io/client-go/pkg/labels"
|
||||
"k8s.io/client-go/pkg/util/sets"
|
||||
@@ -517,177 +516,6 @@ func TestStoreToDaemonSetLister(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreToJobLister(t *testing.T) {
|
||||
store := NewStore(MetaNamespaceKeyFunc)
|
||||
lister := StoreToJobLister{store}
|
||||
testCases := []struct {
|
||||
inJobs []*batch.Job
|
||||
list func() ([]batch.Job, error)
|
||||
outJobNames sets.String
|
||||
expectErr bool
|
||||
msg string
|
||||
}{
|
||||
// Basic listing
|
||||
{
|
||||
inJobs: []*batch.Job{
|
||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||
},
|
||||
list: func() ([]batch.Job, error) {
|
||||
list, err := lister.List()
|
||||
return list.Items, err
|
||||
},
|
||||
outJobNames: sets.NewString("basic"),
|
||||
msg: "basic listing failed",
|
||||
},
|
||||
// Listing multiple jobs
|
||||
{
|
||||
inJobs: []*batch.Job{
|
||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||
{ObjectMeta: api.ObjectMeta{Name: "complex"}},
|
||||
{ObjectMeta: api.ObjectMeta{Name: "complex2"}},
|
||||
},
|
||||
list: func() ([]batch.Job, error) {
|
||||
list, err := lister.List()
|
||||
return list.Items, err
|
||||
},
|
||||
outJobNames: sets.NewString("basic", "complex", "complex2"),
|
||||
msg: "listing multiple jobs failed",
|
||||
},
|
||||
// No pod labels
|
||||
{
|
||||
inJobs: []*batch.Job{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "baz"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]batch.Job, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{Name: "pod", Namespace: "ns"},
|
||||
}
|
||||
return lister.GetPodJobs(pod)
|
||||
},
|
||||
outJobNames: sets.NewString(),
|
||||
expectErr: true,
|
||||
msg: "listing jobs failed when pod has no labels: expected error, got none",
|
||||
},
|
||||
// No Job selectors
|
||||
{
|
||||
inJobs: []*batch.Job{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
},
|
||||
},
|
||||
list: func() ([]batch.Job, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "pod",
|
||||
Namespace: "ns",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
}
|
||||
return lister.GetPodJobs(pod)
|
||||
},
|
||||
outJobNames: sets.NewString(),
|
||||
expectErr: true,
|
||||
msg: "listing jobs failed when job has no selector: expected error, got none",
|
||||
},
|
||||
// Matching labels to selectors and namespace
|
||||
{
|
||||
inJobs: []*batch.Job{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]batch.Job, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "pod",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
Namespace: "ns",
|
||||
},
|
||||
}
|
||||
return lister.GetPodJobs(pod)
|
||||
},
|
||||
outJobNames: sets.NewString("bar"),
|
||||
msg: "listing jobs with namespace and selector failed",
|
||||
},
|
||||
// Matching labels to selectors and namespace, error case
|
||||
{
|
||||
inJobs: []*batch.Job{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "foo"},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "bar"},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]batch.Job, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "pod",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
Namespace: "baz",
|
||||
},
|
||||
}
|
||||
return lister.GetPodJobs(pod)
|
||||
},
|
||||
expectErr: true,
|
||||
msg: "listing jobs with namespace and selector failed: expected error, got none",
|
||||
},
|
||||
}
|
||||
for _, c := range testCases {
|
||||
for _, r := range c.inJobs {
|
||||
store.Add(r)
|
||||
}
|
||||
|
||||
Jobs, err := c.list()
|
||||
if err != nil && c.expectErr {
|
||||
continue
|
||||
} else if c.expectErr {
|
||||
t.Errorf("%v", c.msg)
|
||||
continue
|
||||
} else if err != nil {
|
||||
t.Errorf("Unexpected error %#v", err)
|
||||
continue
|
||||
}
|
||||
JobNames := make([]string, len(Jobs))
|
||||
for ix := range Jobs {
|
||||
JobNames[ix] = Jobs[ix].Name
|
||||
}
|
||||
if !c.outJobNames.HasAll(JobNames...) || len(JobNames) != len(c.outJobNames) {
|
||||
t.Errorf("%v : expected %v, got %v", c.msg, JobNames, c.outJobNames)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreToPodLister(t *testing.T) {
|
||||
// We test with and without a namespace index, because StoreToPodLister has
|
||||
// special logic to work on namespaces even when no namespace index is
|
||||
|
76
tools/cache/listwatch.go
vendored
76
tools/cache/listwatch.go
vendored
@@ -20,12 +20,22 @@ import (
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/pkg/api"
|
||||
"k8s.io/client-go/pkg/api/meta"
|
||||
"k8s.io/client-go/pkg/fields"
|
||||
"k8s.io/client-go/pkg/runtime"
|
||||
"k8s.io/client-go/pkg/watch"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// 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...)
|
||||
}
|
||||
|
9
tools/cache/reflector.go
vendored
9
tools/cache/reflector.go
vendored
@@ -43,15 +43,6 @@ import (
|
||||
"k8s.io/client-go/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.
|
||||
|
Reference in New Issue
Block a user