1
0
Fork 0
forked from barak/tarpoon

Add glide.yaml and vendor deps

This commit is contained in:
Dalton Hubble 2016-12-03 22:43:32 -08:00
parent db918f12ad
commit 5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions

51
vendor/k8s.io/kubernetes/pkg/watch/BUILD generated vendored Normal file
View file

@ -0,0 +1,51 @@
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 = [
"doc.go",
"filter.go",
"mux.go",
"streamwatcher.go",
"until.go",
"watch.go",
],
tags = ["automanaged"],
deps = [
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/util/net:go_default_library",
"//pkg/util/runtime:go_default_library",
"//pkg/util/wait:go_default_library",
"//vendor:github.com/golang/glog",
],
)
go_test(
name = "go_default_test",
srcs = [
"filter_test.go",
"mux_test.go",
"streamwatcher_test.go",
"until_test.go",
"watch_test.go",
],
library = "go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/util/wait:go_default_library",
],
)

19
vendor/k8s.io/kubernetes/pkg/watch/doc.go generated vendored Normal file
View file

@ -0,0 +1,19 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package watch contains a generic watchable interface, and a fake for
// testing code that uses the watch interface.
package watch // import "k8s.io/kubernetes/pkg/watch"

109
vendor/k8s.io/kubernetes/pkg/watch/filter.go generated vendored Normal file
View file

@ -0,0 +1,109 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"sync"
)
// FilterFunc should take an event, possibly modify it in some way, and return
// the modified event. If the event should be ignored, then return keep=false.
type FilterFunc func(in Event) (out Event, keep bool)
// Filter passes all events through f before allowing them to pass on.
// Putting a filter on a watch, as an unavoidable side-effect due to the way
// go channels work, effectively causes the watch's event channel to have its
// queue length increased by one.
//
// WARNING: filter has a fatal flaw, in that it can't properly update the
// Type field (Add/Modified/Deleted) to reflect items beginning to pass the
// filter when they previously didn't.
//
func Filter(w Interface, f FilterFunc) Interface {
fw := &filteredWatch{
incoming: w,
result: make(chan Event),
f: f,
}
go fw.loop()
return fw
}
type filteredWatch struct {
incoming Interface
result chan Event
f FilterFunc
}
// ResultChan returns a channel which will receive filtered events.
func (fw *filteredWatch) ResultChan() <-chan Event {
return fw.result
}
// Stop stops the upstream watch, which will eventually stop this watch.
func (fw *filteredWatch) Stop() {
fw.incoming.Stop()
}
// loop waits for new values, filters them, and resends them.
func (fw *filteredWatch) loop() {
defer close(fw.result)
for {
event, ok := <-fw.incoming.ResultChan()
if !ok {
break
}
filtered, keep := fw.f(event)
if keep {
fw.result <- filtered
}
}
}
// Recorder records all events that are sent from the watch until it is closed.
type Recorder struct {
Interface
lock sync.Mutex
events []Event
}
var _ Interface = &Recorder{}
// NewRecorder wraps an Interface and records any changes sent across it.
func NewRecorder(w Interface) *Recorder {
r := &Recorder{}
r.Interface = Filter(w, r.record)
return r
}
// record is a FilterFunc and tracks each received event.
func (r *Recorder) record(in Event) (Event, bool) {
r.lock.Lock()
defer r.lock.Unlock()
r.events = append(r.events, in)
return in, true
}
// Events returns a copy of the events sent across this recorder.
func (r *Recorder) Events() []Event {
r.lock.Lock()
defer r.lock.Unlock()
copied := make([]Event, len(r.events))
copy(copied, r.events)
return copied
}

82
vendor/k8s.io/kubernetes/pkg/watch/filter_test.go generated vendored Normal file
View file

@ -0,0 +1,82 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"reflect"
"testing"
)
func TestFilter(t *testing.T) {
table := []Event{
{Added, testType("foo")},
{Added, testType("bar")},
{Added, testType("baz")},
{Added, testType("qux")},
{Added, testType("zoo")},
}
source := NewFake()
filtered := Filter(source, func(e Event) (Event, bool) {
return e, e.Object.(testType)[0] != 'b'
})
go func() {
for _, item := range table {
source.Action(item.Type, item.Object)
}
source.Stop()
}()
var got []string
for {
event, ok := <-filtered.ResultChan()
if !ok {
break
}
got = append(got, string(event.Object.(testType)))
}
if e, a := []string{"foo", "qux", "zoo"}, got; !reflect.DeepEqual(e, a) {
t.Errorf("got %v, wanted %v", e, a)
}
}
func TestFilterStop(t *testing.T) {
source := NewFake()
filtered := Filter(source, func(e Event) (Event, bool) {
return e, e.Object.(testType)[0] != 'b'
})
go func() {
source.Add(testType("foo"))
filtered.Stop()
}()
var got []string
for {
event, ok := <-filtered.ResultChan()
if !ok {
break
}
got = append(got, string(event.Object.(testType)))
}
if e, a := []string{"foo"}, got; !reflect.DeepEqual(e, a) {
t.Errorf("got %v, wanted %v", e, a)
}
}

24
vendor/k8s.io/kubernetes/pkg/watch/json/BUILD generated vendored Normal file
View file

@ -0,0 +1,24 @@
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 = [
"doc.go",
"types.go",
],
tags = ["automanaged"],
deps = [
"//pkg/runtime:go_default_library",
"//pkg/watch:go_default_library",
],
)

19
vendor/k8s.io/kubernetes/pkg/watch/json/doc.go generated vendored Normal file
View file

@ -0,0 +1,19 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package json implements a simple encoder and decoder for streams
// of watch events over io.Writer/Readers
package json // import "k8s.io/kubernetes/pkg/watch/json"

55
vendor/k8s.io/kubernetes/pkg/watch/json/types.go generated vendored Normal file
View file

@ -0,0 +1,55 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package json
import (
"encoding/json"
"fmt"
"reflect"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
// WatchEvent objects are streamed from the api server in response to a watch request.
// These are not API objects and may not be changed in a backward-incompatible way.
// TODO: move to a public, versioned object now that RawExtension conversions are possible
// in the schema.
type WatchEvent struct {
// The type of the watch event; added, modified, deleted, or error.
// +optional
Type watch.EventType `json:"type,omitempty" description:"the type of watch event; may be ADDED, MODIFIED, DELETED, or ERROR"`
// For added or modified objects, this is the new object; for deleted objects,
// it's the state of the object immediately prior to its deletion.
// For errors, it's an api.Status.
// +optional
Object runtime.RawExtension `json:"object,omitempty" description:"the object being watched; will match the type of the resource endpoint or be a Status object if the type is ERROR"`
}
// Object converts a watch.Event into an appropriately serializable JSON object
func Object(encoder runtime.Encoder, event *watch.Event) (interface{}, error) {
obj, ok := event.Object.(runtime.Object)
if !ok {
return nil, fmt.Errorf("the event object cannot be safely converted to JSON: %v", reflect.TypeOf(event.Object).Name())
}
data, err := runtime.Encode(encoder, obj)
if err != nil {
return nil, err
}
return &WatchEvent{event.Type, runtime.RawExtension{Raw: json.RawMessage(data)}}, nil
}

257
vendor/k8s.io/kubernetes/pkg/watch/mux.go generated vendored Normal file
View file

@ -0,0 +1,257 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"sync"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/schema"
)
// FullChannelBehavior controls how the Broadcaster reacts if a watcher's watch
// channel is full.
type FullChannelBehavior int
const (
WaitIfChannelFull FullChannelBehavior = iota
DropIfChannelFull
)
// Buffer the incoming queue a little bit even though it should rarely ever accumulate
// anything, just in case a few events are received in such a short window that
// Broadcaster can't move them onto the watchers' queues fast enough.
const incomingQueueLength = 25
// Broadcaster distributes event notifications among any number of watchers. Every event
// is delivered to every watcher.
type Broadcaster struct {
// TODO: see if this lock is needed now that new watchers go through
// the incoming channel.
lock sync.Mutex
watchers map[int64]*broadcasterWatcher
nextWatcher int64
distributing sync.WaitGroup
incoming chan Event
// How large to make watcher's channel.
watchQueueLength int
// If one of the watch channels is full, don't wait for it to become empty.
// Instead just deliver it to the watchers that do have space in their
// channels and move on to the next event.
// It's more fair to do this on a per-watcher basis than to do it on the
// "incoming" channel, which would allow one slow watcher to prevent all
// other watchers from getting new events.
fullChannelBehavior FullChannelBehavior
}
// NewBroadcaster creates a new Broadcaster. queueLength is the maximum number of events to queue per watcher.
// It is guaranteed that events will be distributed in the order in which they occur,
// but the order in which a single event is distributed among all of the watchers is unspecified.
func NewBroadcaster(queueLength int, fullChannelBehavior FullChannelBehavior) *Broadcaster {
m := &Broadcaster{
watchers: map[int64]*broadcasterWatcher{},
incoming: make(chan Event, incomingQueueLength),
watchQueueLength: queueLength,
fullChannelBehavior: fullChannelBehavior,
}
m.distributing.Add(1)
go m.loop()
return m
}
const internalRunFunctionMarker = "internal-do-function"
// a function type we can shoehorn into the queue.
type functionFakeRuntimeObject func()
func (obj functionFakeRuntimeObject) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
// Execute f, blocking the incoming queue (and waiting for it to drain first).
// The purpose of this terrible hack is so that watchers added after an event
// won't ever see that event, and will always see any event after they are
// added.
func (b *Broadcaster) blockQueue(f func()) {
var wg sync.WaitGroup
wg.Add(1)
b.incoming <- Event{
Type: internalRunFunctionMarker,
Object: functionFakeRuntimeObject(func() {
defer wg.Done()
f()
}),
}
wg.Wait()
}
// Watch adds a new watcher to the list and returns an Interface for it.
// Note: new watchers will only receive new events. They won't get an entire history
// of previous events.
func (m *Broadcaster) Watch() Interface {
var w *broadcasterWatcher
m.blockQueue(func() {
m.lock.Lock()
defer m.lock.Unlock()
id := m.nextWatcher
m.nextWatcher++
w = &broadcasterWatcher{
result: make(chan Event, m.watchQueueLength),
stopped: make(chan struct{}),
id: id,
m: m,
}
m.watchers[id] = w
})
return w
}
// WatchWithPrefix adds a new watcher to the list and returns an Interface for it. It sends
// queuedEvents down the new watch before beginning to send ordinary events from Broadcaster.
// The returned watch will have a queue length that is at least large enough to accommodate
// all of the items in queuedEvents.
func (m *Broadcaster) WatchWithPrefix(queuedEvents []Event) Interface {
var w *broadcasterWatcher
m.blockQueue(func() {
m.lock.Lock()
defer m.lock.Unlock()
id := m.nextWatcher
m.nextWatcher++
length := m.watchQueueLength
if n := len(queuedEvents) + 1; n > length {
length = n
}
w = &broadcasterWatcher{
result: make(chan Event, length),
stopped: make(chan struct{}),
id: id,
m: m,
}
m.watchers[id] = w
for _, e := range queuedEvents {
w.result <- e
}
})
return w
}
// stopWatching stops the given watcher and removes it from the list.
func (m *Broadcaster) stopWatching(id int64) {
m.lock.Lock()
defer m.lock.Unlock()
w, ok := m.watchers[id]
if !ok {
// No need to do anything, it's already been removed from the list.
return
}
delete(m.watchers, id)
close(w.result)
}
// closeAll disconnects all watchers (presumably in response to a Shutdown call).
func (m *Broadcaster) closeAll() {
m.lock.Lock()
defer m.lock.Unlock()
for _, w := range m.watchers {
close(w.result)
}
// Delete everything from the map, since presence/absence in the map is used
// by stopWatching to avoid double-closing the channel.
m.watchers = map[int64]*broadcasterWatcher{}
}
// Action distributes the given event among all watchers.
func (m *Broadcaster) Action(action EventType, obj runtime.Object) {
m.incoming <- Event{action, obj}
}
// Shutdown disconnects all watchers (but any queued events will still be distributed).
// You must not call Action or Watch* after calling Shutdown. This call blocks
// until all events have been distributed through the outbound channels. Note
// that since they can be buffered, this means that the watchers might not
// have received the data yet as it can remain sitting in the buffered
// channel.
func (m *Broadcaster) Shutdown() {
close(m.incoming)
m.distributing.Wait()
}
// loop receives from m.incoming and distributes to all watchers.
func (m *Broadcaster) loop() {
// Deliberately not catching crashes here. Yes, bring down the process if there's a
// bug in watch.Broadcaster.
for {
event, ok := <-m.incoming
if !ok {
break
}
if event.Type == internalRunFunctionMarker {
event.Object.(functionFakeRuntimeObject)()
continue
}
m.distribute(event)
}
m.closeAll()
m.distributing.Done()
}
// distribute sends event to all watchers. Blocking.
func (m *Broadcaster) distribute(event Event) {
m.lock.Lock()
defer m.lock.Unlock()
if m.fullChannelBehavior == DropIfChannelFull {
for _, w := range m.watchers {
select {
case w.result <- event:
case <-w.stopped:
default: // Don't block if the event can't be queued.
}
}
} else {
for _, w := range m.watchers {
select {
case w.result <- event:
case <-w.stopped:
}
}
}
}
// broadcasterWatcher handles a single watcher of a broadcaster
type broadcasterWatcher struct {
result chan Event
stopped chan struct{}
stop sync.Once
id int64
m *Broadcaster
}
// ResultChan returns a channel to use for waiting on events.
func (mw *broadcasterWatcher) ResultChan() <-chan Event {
return mw.result
}
// Stop stops watching and removes mw from its list.
func (mw *broadcasterWatcher) Stop() {
mw.stop.Do(func() {
close(mw.stopped)
mw.m.stopWatching(mw.id)
})
}

167
vendor/k8s.io/kubernetes/pkg/watch/mux_test.go generated vendored Normal file
View file

@ -0,0 +1,167 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"reflect"
"sync"
"testing"
"time"
"k8s.io/kubernetes/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/util/wait"
)
type myType struct {
ID string
Value string
}
func (obj *myType) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func TestBroadcaster(t *testing.T) {
table := []Event{
{Added, &myType{"foo", "hello world 1"}},
{Added, &myType{"bar", "hello world 2"}},
{Modified, &myType{"foo", "goodbye world 3"}},
{Deleted, &myType{"bar", "hello world 4"}},
}
// The broadcaster we're testing
m := NewBroadcaster(0, WaitIfChannelFull)
// Add a bunch of watchers
const testWatchers = 2
wg := sync.WaitGroup{}
wg.Add(testWatchers)
for i := 0; i < testWatchers; i++ {
// Verify that each watcher gets the events in the correct order
go func(watcher int, w Interface) {
tableLine := 0
for {
event, ok := <-w.ResultChan()
if !ok {
break
}
if e, a := table[tableLine], event; !reflect.DeepEqual(e, a) {
t.Errorf("Watcher %v, line %v: Expected (%v, %#v), got (%v, %#v)",
watcher, tableLine, e.Type, e.Object, a.Type, a.Object)
} else {
t.Logf("Got (%v, %#v)", event.Type, event.Object)
}
tableLine++
}
wg.Done()
}(i, m.Watch())
}
for i, item := range table {
t.Logf("Sending %v", i)
m.Action(item.Type, item.Object)
}
m.Shutdown()
wg.Wait()
}
func TestBroadcasterWatcherClose(t *testing.T) {
m := NewBroadcaster(0, WaitIfChannelFull)
w := m.Watch()
w2 := m.Watch()
w.Stop()
m.Shutdown()
if _, open := <-w.ResultChan(); open {
t.Errorf("Stop didn't work?")
}
if _, open := <-w2.ResultChan(); open {
t.Errorf("Shutdown didn't work?")
}
// Extra stops don't hurt things
w.Stop()
w2.Stop()
}
func TestBroadcasterWatcherStopDeadlock(t *testing.T) {
done := make(chan bool)
m := NewBroadcaster(0, WaitIfChannelFull)
go func(w0, w1 Interface) {
// We know Broadcaster is in the distribute loop once one watcher receives
// an event. Stop the other watcher while distribute is trying to
// send to it.
select {
case <-w0.ResultChan():
w1.Stop()
case <-w1.ResultChan():
w0.Stop()
}
close(done)
}(m.Watch(), m.Watch())
m.Action(Added, &myType{})
select {
case <-time.After(wait.ForeverTestTimeout):
t.Error("timeout: deadlocked")
case <-done:
}
m.Shutdown()
}
func TestBroadcasterDropIfChannelFull(t *testing.T) {
m := NewBroadcaster(1, DropIfChannelFull)
event1 := Event{Added, &myType{"foo", "hello world 1"}}
event2 := Event{Added, &myType{"bar", "hello world 2"}}
// Add a couple watchers
watches := make([]Interface, 2)
for i := range watches {
watches[i] = m.Watch()
}
// Send a couple events before closing the broadcast channel.
t.Log("Sending event 1")
m.Action(event1.Type, event1.Object)
t.Log("Sending event 2")
m.Action(event2.Type, event2.Object)
m.Shutdown()
// Pull events from the queue.
wg := sync.WaitGroup{}
wg.Add(len(watches))
for i := range watches {
// Verify that each watcher only gets the first event because its watch
// queue of length one was full from the first one.
go func(watcher int, w Interface) {
defer wg.Done()
e1, ok := <-w.ResultChan()
if !ok {
t.Errorf("Watcher %v failed to retrieve first event.", watcher)
}
if e, a := event1, e1; !reflect.DeepEqual(e, a) {
t.Errorf("Watcher %v: Expected (%v, %#v), got (%v, %#v)",
watcher, e.Type, e.Object, a.Type, a.Object)
}
t.Logf("Got (%v, %#v)", e1.Type, e1.Object)
e2, ok := <-w.ResultChan()
if ok {
t.Errorf("Watcher %v received second event (%v, %#v) even though it shouldn't have.",
watcher, e2.Type, e2.Object)
}
}(i, watches[i])
}
wg.Wait()
}

119
vendor/k8s.io/kubernetes/pkg/watch/streamwatcher.go generated vendored Normal file
View file

@ -0,0 +1,119 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"io"
"sync"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/net"
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
)
// Decoder allows StreamWatcher to watch any stream for which a Decoder can be written.
type Decoder interface {
// Decode should return the type of event, the decoded object, or an error.
// An error will cause StreamWatcher to call Close(). Decode should block until
// it has data or an error occurs.
Decode() (action EventType, object runtime.Object, err error)
// Close should close the underlying io.Reader, signalling to the source of
// the stream that it is no longer being watched. Close() must cause any
// outstanding call to Decode() to return with an error of some sort.
Close()
}
// StreamWatcher turns any stream for which you can write a Decoder interface
// into a watch.Interface.
type StreamWatcher struct {
sync.Mutex
source Decoder
result chan Event
stopped bool
}
// NewStreamWatcher creates a StreamWatcher from the given decoder.
func NewStreamWatcher(d Decoder) *StreamWatcher {
sw := &StreamWatcher{
source: d,
// It's easy for a consumer to add buffering via an extra
// goroutine/channel, but impossible for them to remove it,
// so nonbuffered is better.
result: make(chan Event),
}
go sw.receive()
return sw
}
// ResultChan implements Interface.
func (sw *StreamWatcher) ResultChan() <-chan Event {
return sw.result
}
// Stop implements Interface.
func (sw *StreamWatcher) Stop() {
// Call Close() exactly once by locking and setting a flag.
sw.Lock()
defer sw.Unlock()
if !sw.stopped {
sw.stopped = true
sw.source.Close()
}
}
// stopping returns true if Stop() was called previously.
func (sw *StreamWatcher) stopping() bool {
sw.Lock()
defer sw.Unlock()
return sw.stopped
}
// receive reads result from the decoder in a loop and sends down the result channel.
func (sw *StreamWatcher) receive() {
defer close(sw.result)
defer sw.Stop()
defer utilruntime.HandleCrash()
for {
action, obj, err := sw.source.Decode()
if err != nil {
// Ignore expected error.
if sw.stopping() {
return
}
switch err {
case io.EOF:
// watch closed normally
case io.ErrUnexpectedEOF:
glog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err)
default:
msg := "Unable to decode an event from the watch stream: %v"
if net.IsProbableEOF(err) {
glog.V(5).Infof(msg, err)
} else {
glog.Errorf(msg, err)
}
}
return
}
sw.result <- Event{
Type: action,
Object: obj,
}
}
}

View file

@ -0,0 +1,67 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"io"
"reflect"
"testing"
"k8s.io/kubernetes/pkg/runtime"
)
type fakeDecoder struct {
items chan Event
}
func (f fakeDecoder) Decode() (action EventType, object runtime.Object, err error) {
item, open := <-f.items
if !open {
return action, nil, io.EOF
}
return item.Type, item.Object, nil
}
func (f fakeDecoder) Close() {
close(f.items)
}
func TestStreamWatcher(t *testing.T) {
table := []Event{
{Added, testType("foo")},
}
fd := fakeDecoder{make(chan Event, 5)}
sw := NewStreamWatcher(fd)
for _, item := range table {
fd.items <- item
got, open := <-sw.ResultChan()
if !open {
t.Errorf("unexpected early close")
}
if e, a := item, got; !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
}
sw.Stop()
_, open := <-sw.ResultChan()
if open {
t.Errorf("Unexpected failure to close")
}
}

83
vendor/k8s.io/kubernetes/pkg/watch/until.go generated vendored Normal file
View file

@ -0,0 +1,83 @@
/*
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 watch
import (
"time"
"k8s.io/kubernetes/pkg/util/wait"
)
// ConditionFunc returns true if the condition has been reached, false if it has not been reached yet,
// or an error if the condition cannot be checked and should terminate. In general, it is better to define
// level driven conditions over edge driven conditions (pod has ready=true, vs pod modified and ready changed
// from false to true).
type ConditionFunc func(event Event) (bool, error)
// Until reads items from the watch until each provided condition succeeds, and then returns the last watch
// encountered. The first condition that returns an error terminates the watch (and the event is also returned).
// If no event has been received, the returned event will be nil.
// Conditions are satisfied sequentially so as to provide a useful primitive for higher level composition.
// A zero timeout means to wait forever.
func Until(timeout time.Duration, watcher Interface, conditions ...ConditionFunc) (*Event, error) {
ch := watcher.ResultChan()
defer watcher.Stop()
var after <-chan time.Time
if timeout > 0 {
after = time.After(timeout)
} else {
ch := make(chan time.Time)
defer close(ch)
after = ch
}
var lastEvent *Event
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 {
continue
}
}
ConditionSucceeded:
for {
select {
case event, ok := <-ch:
if !ok {
return lastEvent, wait.ErrWaitTimeout
}
lastEvent = &event
// TODO: check for watch expired error and retry watch from latest point?
done, err := condition(event)
if err != nil {
return lastEvent, err
}
if done {
break ConditionSucceeded
}
case <-after:
return lastEvent, wait.ErrWaitTimeout
}
}
}
return lastEvent, nil
}

164
vendor/k8s.io/kubernetes/pkg/watch/until_test.go generated vendored Normal file
View file

@ -0,0 +1,164 @@
/*
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 watch
import (
"errors"
"strings"
"testing"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/util/wait"
)
func TestUntil(t *testing.T) {
fw := NewFake()
go func() {
var obj *api.Pod
fw.Add(obj)
fw.Modify(obj)
}()
conditions := []ConditionFunc{
func(event Event) (bool, error) { return event.Type == Added, nil },
func(event Event) (bool, error) { return event.Type == Modified, nil },
}
timeout := time.Minute
lastEvent, err := Until(timeout, fw, conditions...)
if err != nil {
t.Fatalf("expected nil error, got %#v", err)
}
if lastEvent == nil {
t.Fatal("expected an event")
}
if lastEvent.Type != Modified {
t.Fatalf("expected MODIFIED event type, got %v", lastEvent.Type)
}
if got, isPod := lastEvent.Object.(*api.Pod); !isPod {
t.Fatalf("expected a pod event, got %#v", got)
}
}
func TestUntilMultipleConditions(t *testing.T) {
fw := NewFake()
go func() {
var obj *api.Pod
fw.Add(obj)
}()
conditions := []ConditionFunc{
func(event Event) (bool, error) { return event.Type == Added, nil },
func(event Event) (bool, error) { return event.Type == Added, nil },
}
timeout := time.Minute
lastEvent, err := Until(timeout, fw, conditions...)
if err != nil {
t.Fatalf("expected nil error, got %#v", err)
}
if lastEvent == nil {
t.Fatal("expected an event")
}
if lastEvent.Type != Added {
t.Fatalf("expected MODIFIED event type, got %v", lastEvent.Type)
}
if got, isPod := lastEvent.Object.(*api.Pod); !isPod {
t.Fatalf("expected a pod event, got %#v", got)
}
}
func TestUntilMultipleConditionsFail(t *testing.T) {
fw := NewFake()
go func() {
var obj *api.Pod
fw.Add(obj)
}()
conditions := []ConditionFunc{
func(event Event) (bool, error) { return event.Type == Added, nil },
func(event Event) (bool, error) { return event.Type == Added, nil },
func(event Event) (bool, error) { return event.Type == Deleted, nil },
}
timeout := 10 * time.Second
lastEvent, err := Until(timeout, fw, conditions...)
if err != wait.ErrWaitTimeout {
t.Fatalf("expected ErrWaitTimeout error, got %#v", err)
}
if lastEvent == nil {
t.Fatal("expected an event")
}
if lastEvent.Type != Added {
t.Fatalf("expected ADDED event type, got %v", lastEvent.Type)
}
if got, isPod := lastEvent.Object.(*api.Pod); !isPod {
t.Fatalf("expected a pod event, got %#v", got)
}
}
func TestUntilTimeout(t *testing.T) {
fw := NewFake()
go func() {
var obj *api.Pod
fw.Add(obj)
fw.Modify(obj)
}()
conditions := []ConditionFunc{
func(event Event) (bool, error) {
return event.Type == Added, nil
},
func(event Event) (bool, error) {
return event.Type == Modified, nil
},
}
timeout := time.Duration(0)
lastEvent, err := Until(timeout, fw, conditions...)
if err != nil {
t.Fatalf("expected nil error, got %#v", err)
}
if lastEvent == nil {
t.Fatal("expected an event")
}
if lastEvent.Type != Modified {
t.Fatalf("expected MODIFIED event type, got %v", lastEvent.Type)
}
if got, isPod := lastEvent.Object.(*api.Pod); !isPod {
t.Fatalf("expected a pod event, got %#v", got)
}
}
func TestUntilErrorCondition(t *testing.T) {
fw := NewFake()
go func() {
var obj *api.Pod
fw.Add(obj)
}()
expected := "something bad"
conditions := []ConditionFunc{
func(event Event) (bool, error) { return event.Type == Added, nil },
func(event Event) (bool, error) { return false, errors.New(expected) },
}
timeout := time.Minute
_, err := Until(timeout, fw, conditions...)
if err == nil {
t.Fatal("expected an error")
}
if !strings.Contains(err.Error(), expected) {
t.Fatalf("expected %q in error string, got %q", expected, err.Error())
}
}

49
vendor/k8s.io/kubernetes/pkg/watch/versioned/BUILD generated vendored Normal file
View file

@ -0,0 +1,49 @@
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 = [
"decoder.go",
"encoder.go",
"generated.pb.go",
"register.go",
"types.go",
],
tags = ["automanaged"],
deps = [
"//pkg/conversion:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/runtime/serializer/streaming:go_default_library",
"//pkg/watch:go_default_library",
"//vendor:github.com/gogo/protobuf/proto",
],
)
go_test(
name = "go_default_xtest",
srcs = [
"decoder_test.go",
"encoder_test.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/serializer/streaming:go_default_library",
"//pkg/util/wait:go_default_library",
"//pkg/watch:go_default_library",
"//pkg/watch/versioned:go_default_library",
],
)

View file

@ -0,0 +1,71 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package versioned
import (
"fmt"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/streaming"
"k8s.io/kubernetes/pkg/watch"
)
// Decoder implements the watch.Decoder interface for io.ReadClosers that
// have contents which consist of a series of watchEvent objects encoded
// with the given streaming decoder. The internal objects will be then
// decoded by the embedded decoder.
type Decoder struct {
decoder streaming.Decoder
embeddedDecoder runtime.Decoder
}
// NewDecoder creates an Decoder for the given writer and codec.
func NewDecoder(decoder streaming.Decoder, embeddedDecoder runtime.Decoder) *Decoder {
return &Decoder{
decoder: decoder,
embeddedDecoder: embeddedDecoder,
}
}
// Decode blocks until it can return the next object in the reader. Returns an error
// if the reader is closed or an object can't be decoded.
func (d *Decoder) Decode() (watch.EventType, runtime.Object, error) {
var got Event
res, _, err := d.decoder.Decode(nil, &got)
if err != nil {
return "", nil, err
}
if res != &got {
return "", nil, fmt.Errorf("unable to decode to versioned.Event")
}
switch got.Type {
case string(watch.Added), string(watch.Modified), string(watch.Deleted), string(watch.Error):
default:
return "", nil, fmt.Errorf("got invalid watch event type: %v", got.Type)
}
obj, err := runtime.Decode(d.embeddedDecoder, got.Object.Raw)
if err != nil {
return "", nil, fmt.Errorf("unable to decode watch event: %v", err)
}
return watch.EventType(got.Type), obj, nil
}
// Close closes the underlying r.
func (d *Decoder) Close() {
d.decoder.Close()
}

View file

@ -0,0 +1,113 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package versioned_test
import (
"encoding/json"
"io"
"testing"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/streaming"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/watch"
"k8s.io/kubernetes/pkg/watch/versioned"
)
func TestDecoder(t *testing.T) {
table := []watch.EventType{watch.Added, watch.Deleted, watch.Modified, watch.Error}
for _, eventType := range table {
out, in := io.Pipe()
codec := testapi.Default.Codec()
decoder := versioned.NewDecoder(streaming.NewDecoder(out, codec), codec)
expect := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}
encoder := json.NewEncoder(in)
go func() {
data, err := runtime.Encode(testapi.Default.Codec(), expect)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
event := versioned.Event{
Type: string(eventType),
Object: runtime.RawExtension{Raw: json.RawMessage(data)},
}
if err := encoder.Encode(&event); err != nil {
t.Errorf("Unexpected error %v", err)
}
in.Close()
}()
done := make(chan struct{})
go func() {
action, got, err := decoder.Decode()
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := eventType, action; e != a {
t.Errorf("Expected %v, got %v", e, a)
}
if e, a := expect, got; !api.Semantic.DeepDerivative(e, a) {
t.Errorf("Expected %v, got %v", e, a)
}
t.Logf("Exited read")
close(done)
}()
<-done
done = make(chan struct{})
go func() {
_, _, err := decoder.Decode()
if err == nil {
t.Errorf("Unexpected nil error")
}
close(done)
}()
<-done
decoder.Close()
}
}
func TestDecoder_SourceClose(t *testing.T) {
out, in := io.Pipe()
codec := testapi.Default.Codec()
decoder := versioned.NewDecoder(streaming.NewDecoder(out, codec), codec)
done := make(chan struct{})
go func() {
_, _, err := decoder.Decode()
if err == nil {
t.Errorf("Unexpected nil error")
}
close(done)
}()
in.Close()
select {
case <-done:
break
case <-time.After(wait.ForeverTestTimeout):
t.Error("Timeout")
}
}

View file

@ -0,0 +1,51 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package versioned
import (
"encoding/json"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/streaming"
"k8s.io/kubernetes/pkg/watch"
)
// Encoder serializes watch.Events into io.Writer. The internal objects
// are encoded using embedded encoder, and the outer Event is serialized
// using encoder.
type Encoder struct {
encoder streaming.Encoder
embeddedEncoder runtime.Encoder
}
func NewEncoder(encoder streaming.Encoder, embeddedEncoder runtime.Encoder) *Encoder {
return &Encoder{
encoder: encoder,
embeddedEncoder: embeddedEncoder,
}
}
// Encode writes an event to the writer. Returns an error
// if the writer is closed or an object can't be encoded.
func (e *Encoder) Encode(event *watch.Event) error {
data, err := runtime.Encode(e.embeddedEncoder, event.Object)
if err != nil {
return err
}
// FIXME: get rid of json.RawMessage.
return e.encoder.Encode(&Event{string(event.Type), runtime.RawExtension{Raw: json.RawMessage(data)}})
}

View file

@ -0,0 +1,78 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package versioned_test
import (
"bytes"
"io/ioutil"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/streaming"
"k8s.io/kubernetes/pkg/watch"
"k8s.io/kubernetes/pkg/watch/versioned"
)
func TestEncodeDecodeRoundTrip(t *testing.T) {
testCases := []struct {
Type watch.EventType
Object runtime.Object
Codec runtime.Codec
}{
{
watch.Added,
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}},
testapi.Default.Codec(),
},
{
watch.Modified,
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}},
testapi.Default.Codec(),
},
{
watch.Deleted,
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}},
testapi.Default.Codec(),
},
}
for i, testCase := range testCases {
buf := &bytes.Buffer{}
codec := testCase.Codec
encoder := versioned.NewEncoder(streaming.NewEncoder(buf, codec), codec)
if err := encoder.Encode(&watch.Event{Type: testCase.Type, Object: testCase.Object}); err != nil {
t.Errorf("%d: unexpected error: %v", i, err)
continue
}
rc := ioutil.NopCloser(buf)
decoder := versioned.NewDecoder(streaming.NewDecoder(rc, codec), codec)
event, obj, err := decoder.Decode()
if err != nil {
t.Errorf("%d: unexpected error: %v", i, err)
continue
}
if !api.Semantic.DeepDerivative(testCase.Object, obj) {
t.Errorf("%d: expected %#v, got %#v", i, testCase.Object, obj)
}
if event != testCase.Type {
t.Errorf("%d: unexpected type: %#v", i, event)
}
}
}

View file

@ -0,0 +1,390 @@
/*
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.
*/
// Code generated by protoc-gen-gogo.
// source: k8s.io/kubernetes/pkg/watch/versioned/generated.proto
// DO NOT EDIT!
/*
Package versioned is a generated protocol buffer package.
It is generated from these files:
k8s.io/kubernetes/pkg/watch/versioned/generated.proto
It has these top-level messages:
Event
*/
package versioned
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import strings "strings"
import reflect "reflect"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
const _ = proto.GoGoProtoPackageIsVersion1
func (m *Event) Reset() { *m = Event{} }
func (*Event) ProtoMessage() {}
func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
func init() {
proto.RegisterType((*Event)(nil), "k8s.io.kubernetes.pkg.watch.versioned.Event")
}
func (m *Event) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *Event) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
data[i] = 0xa
i++
i = encodeVarintGenerated(data, i, uint64(len(m.Type)))
i += copy(data[i:], m.Type)
data[i] = 0x12
i++
i = encodeVarintGenerated(data, i, uint64(m.Object.Size()))
n1, err := m.Object.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n1
return i, nil
}
func encodeFixed64Generated(data []byte, offset int, v uint64) int {
data[offset] = uint8(v)
data[offset+1] = uint8(v >> 8)
data[offset+2] = uint8(v >> 16)
data[offset+3] = uint8(v >> 24)
data[offset+4] = uint8(v >> 32)
data[offset+5] = uint8(v >> 40)
data[offset+6] = uint8(v >> 48)
data[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(data []byte, offset int, v uint32) int {
data[offset] = uint8(v)
data[offset+1] = uint8(v >> 8)
data[offset+2] = uint8(v >> 16)
data[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(data []byte, offset int, v uint64) int {
for v >= 1<<7 {
data[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
data[offset] = uint8(v)
return offset + 1
}
func (m *Event) Size() (n int) {
var l int
_ = l
l = len(m.Type)
n += 1 + l + sovGenerated(uint64(l))
l = m.Object.Size()
n += 1 + l + sovGenerated(uint64(l))
return n
}
func sovGenerated(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozGenerated(x uint64) (n int) {
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *Event) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&Event{`,
`Type:` + fmt.Sprintf("%v", this.Type) + `,`,
`Object:` + strings.Replace(strings.Replace(this.Object.String(), "RawExtension", "k8s_io_kubernetes_pkg_runtime.RawExtension", 1), `&`, ``, 1) + `,`,
`}`,
}, "")
return s
}
func valueToStringGenerated(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *Event) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Event: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Type = string(data[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Object", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Object.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenerated(data []byte) (n int, err error) {
l := len(data)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if data[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthGenerated
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipGenerated(data[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
)
var fileDescriptorGenerated = []byte{
// 280 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x90, 0x41, 0x4b, 0xc3, 0x30,
0x18, 0x86, 0x1b, 0x99, 0x83, 0x55, 0xf1, 0xd0, 0xd3, 0xe8, 0x21, 0x2b, 0x82, 0x30, 0x18, 0x4b,
0x50, 0x10, 0x3c, 0x17, 0x76, 0x16, 0xaa, 0x27, 0x6f, 0x6d, 0xf7, 0x99, 0xc5, 0xba, 0xa4, 0xa4,
0x5f, 0x37, 0x77, 0x11, 0x7f, 0x82, 0x3f, 0xab, 0xc7, 0x1d, 0x3d, 0x0d, 0x5b, 0xff, 0x88, 0x98,
0x95, 0x09, 0xa3, 0xb7, 0xbc, 0x24, 0xcf, 0xc3, 0xfb, 0xc6, 0xbd, 0xcd, 0xee, 0x0a, 0x26, 0x35,
0xcf, 0xca, 0x04, 0x8c, 0x02, 0x84, 0x82, 0xe7, 0x99, 0xe0, 0xeb, 0x18, 0xd3, 0x05, 0x5f, 0x81,
0x29, 0xa4, 0x56, 0x30, 0xe7, 0x02, 0x14, 0x98, 0x18, 0x61, 0xce, 0x72, 0xa3, 0x51, 0x7b, 0x57,
0x7b, 0x8c, 0xfd, 0x63, 0x2c, 0xcf, 0x04, 0xb3, 0x18, 0x3b, 0x60, 0xfe, 0x54, 0x48, 0x5c, 0x94,
0x09, 0x4b, 0xf5, 0x92, 0x0b, 0x2d, 0x34, 0xb7, 0x74, 0x52, 0x3e, 0xdb, 0x64, 0x83, 0x3d, 0xed,
0xad, 0xfe, 0xb4, 0xbb, 0x8c, 0x29, 0x15, 0xca, 0x25, 0x1c, 0x97, 0xf0, 0xaf, 0xbb, 0x9f, 0x97,
0x28, 0x5f, 0xb9, 0x54, 0x58, 0xa0, 0x39, 0x46, 0x2e, 0xdf, 0xdd, 0xd3, 0xd9, 0x0a, 0x14, 0x7a,
0x81, 0xdb, 0xc3, 0x4d, 0x0e, 0x43, 0x12, 0x90, 0xf1, 0x20, 0x3c, 0xaf, 0x76, 0x23, 0xa7, 0xd9,
0x8d, 0x7a, 0x8f, 0x9b, 0x1c, 0x22, 0x7b, 0xe3, 0x3d, 0xb8, 0x7d, 0x9d, 0xbc, 0x40, 0x8a, 0xc3,
0x93, 0x80, 0x8c, 0xcf, 0x6e, 0x26, 0xac, 0x7b, 0x73, 0xdb, 0x8e, 0x45, 0xf1, 0x7a, 0xf6, 0x86,
0xa0, 0xfe, 0xa6, 0x87, 0x17, 0xad, 0xb0, 0x7f, 0x6f, 0x15, 0x51, 0xab, 0x0a, 0x27, 0x55, 0x4d,
0x9d, 0x6d, 0x4d, 0x9d, 0xaf, 0x9a, 0x3a, 0x1f, 0x0d, 0x25, 0x55, 0x43, 0xc9, 0xb6, 0xa1, 0xe4,
0xbb, 0xa1, 0xe4, 0xf3, 0x87, 0x3a, 0x4f, 0x83, 0xc3, 0xef, 0xfd, 0x06, 0x00, 0x00, 0xff, 0xff,
0x23, 0x3d, 0x7b, 0x7e, 0x9c, 0x01, 0x00, 0x00,
}

View file

@ -0,0 +1,44 @@
/*
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.
*/
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.kubernetes.pkg.watch.versioned;
import "k8s.io/kubernetes/pkg/runtime/generated.proto";
import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "versioned";
// Event represents a single event to a watched resource.
//
// +protobuf=true
// +k8s:openapi-gen=true
message Event {
optional string type = 1;
// Object is:
// * If Type is Added or Modified: the new state of the object.
// * If Type is Deleted: the state of the object immediately before deletion.
// * If Type is Error: *api.Status is recommended; other types may make sense
// depending on context.
optional k8s.io.kubernetes.pkg.runtime.RawExtension object = 2;
}

View file

@ -0,0 +1,84 @@
/*
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 versioned
import (
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/watch"
)
// WatchEventKind is name reserved for serializing watch events.
const WatchEventKind = "WatchEvent"
// AddToGroupVersion registers the watch external and internal kinds with the scheme, and ensures the proper
// conversions are in place.
func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion) {
scheme.AddKnownTypeWithName(groupVersion.WithKind(WatchEventKind), &Event{})
scheme.AddKnownTypeWithName(
schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal}.WithKind(WatchEventKind),
&InternalEvent{},
)
scheme.AddConversionFuncs(
Convert_versioned_Event_to_watch_Event,
Convert_versioned_InternalEvent_to_versioned_Event,
Convert_watch_Event_to_versioned_Event,
Convert_versioned_Event_to_versioned_InternalEvent,
)
}
func Convert_watch_Event_to_versioned_Event(in *watch.Event, out *Event, s conversion.Scope) error {
out.Type = string(in.Type)
switch t := in.Object.(type) {
case *runtime.Unknown:
// TODO: handle other fields on Unknown and detect type
out.Object.Raw = t.Raw
case nil:
default:
out.Object.Object = in.Object
}
return nil
}
func Convert_versioned_InternalEvent_to_versioned_Event(in *InternalEvent, out *Event, s conversion.Scope) error {
return Convert_watch_Event_to_versioned_Event((*watch.Event)(in), out, s)
}
func Convert_versioned_Event_to_watch_Event(in *Event, out *watch.Event, s conversion.Scope) error {
out.Type = watch.EventType(in.Type)
if in.Object.Object != nil {
out.Object = in.Object.Object
} else if in.Object.Raw != nil {
// TODO: handle other fields on Unknown and detect type
out.Object = &runtime.Unknown{
Raw: in.Object.Raw,
ContentType: runtime.ContentTypeJSON,
}
}
return nil
}
func Convert_versioned_Event_to_versioned_InternalEvent(in *Event, out *InternalEvent, s conversion.Scope) error {
return Convert_versioned_Event_to_watch_Event(in, (*watch.Event)(out), s)
}
// InternalEvent makes watch.Event versioned
type InternalEvent watch.Event
func (e *InternalEvent) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func (e *Event) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }

38
vendor/k8s.io/kubernetes/pkg/watch/versioned/types.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
/*
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 versioned contains the versioned types for watch. This is the first
// serialization version unless otherwise noted.
package versioned
import (
"k8s.io/kubernetes/pkg/runtime"
)
// Event represents a single event to a watched resource.
//
// +protobuf=true
// +k8s:openapi-gen=true
type Event struct {
Type string `json:"type" protobuf:"bytes,1,opt,name=type"`
// Object is:
// * If Type is Added or Modified: the new state of the object.
// * If Type is Deleted: the state of the object immediately before deletion.
// * If Type is Error: *api.Status is recommended; other types may make sense
// depending on context.
Object runtime.RawExtension `json:"object" protobuf:"bytes,2,opt,name=object"`
}

269
vendor/k8s.io/kubernetes/pkg/watch/watch.go generated vendored Normal file
View file

@ -0,0 +1,269 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"fmt"
"sync"
"k8s.io/kubernetes/pkg/runtime"
"github.com/golang/glog"
)
// Interface can be implemented by anything that knows how to watch and report changes.
type Interface interface {
// Stops watching. Will close the channel returned by ResultChan(). Releases
// any resources used by the watch.
Stop()
// Returns a chan which will receive all the events. If an error occurs
// or Stop() is called, this channel will be closed, in which case the
// watch should be completely cleaned up.
ResultChan() <-chan Event
}
// EventType defines the possible types of events.
type EventType string
const (
Added EventType = "ADDED"
Modified EventType = "MODIFIED"
Deleted EventType = "DELETED"
Error EventType = "ERROR"
DefaultChanSize int32 = 100
)
// Event represents a single event to a watched resource.
type Event struct {
Type EventType
// Object is:
// * If Type is Added or Modified: the new state of the object.
// * If Type is Deleted: the state of the object immediately before deletion.
// * If Type is Error: *api.Status is recommended; other types may make sense
// depending on context.
Object runtime.Object
}
type emptyWatch chan Event
// NewEmptyWatch returns a watch interface that returns no results and is closed.
// May be used in certain error conditions where no information is available but
// an error is not warranted.
func NewEmptyWatch() Interface {
ch := make(chan Event)
close(ch)
return emptyWatch(ch)
}
// Stop implements Interface
func (w emptyWatch) Stop() {
}
// ResultChan implements Interface
func (w emptyWatch) ResultChan() <-chan Event {
return chan Event(w)
}
// FakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
type FakeWatcher struct {
result chan Event
Stopped bool
sync.Mutex
}
func NewFake() *FakeWatcher {
return &FakeWatcher{
result: make(chan Event),
}
}
func NewFakeWithChanSize(size int, blocking bool) *FakeWatcher {
return &FakeWatcher{
result: make(chan Event, size),
}
}
// Stop implements Interface.Stop().
func (f *FakeWatcher) Stop() {
f.Lock()
defer f.Unlock()
if !f.Stopped {
glog.V(4).Infof("Stopping fake watcher.")
close(f.result)
f.Stopped = true
}
}
func (f *FakeWatcher) IsStopped() bool {
f.Lock()
defer f.Unlock()
return f.Stopped
}
// Reset prepares the watcher to be reused.
func (f *FakeWatcher) Reset() {
f.Lock()
defer f.Unlock()
f.Stopped = false
f.result = make(chan Event)
}
func (f *FakeWatcher) ResultChan() <-chan Event {
return f.result
}
// Add sends an add event.
func (f *FakeWatcher) Add(obj runtime.Object) {
f.result <- Event{Added, obj}
}
// Modify sends a modify event.
func (f *FakeWatcher) Modify(obj runtime.Object) {
f.result <- Event{Modified, obj}
}
// Delete sends a delete event.
func (f *FakeWatcher) Delete(lastValue runtime.Object) {
f.result <- Event{Deleted, lastValue}
}
// Error sends an Error event.
func (f *FakeWatcher) Error(errValue runtime.Object) {
f.result <- Event{Error, errValue}
}
// Action sends an event of the requested type, for table-based testing.
func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
f.result <- Event{action, obj}
}
// RaceFreeFakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
type RaceFreeFakeWatcher struct {
result chan Event
Stopped bool
sync.Mutex
}
func NewRaceFreeFake() *RaceFreeFakeWatcher {
return &RaceFreeFakeWatcher{
result: make(chan Event, DefaultChanSize),
}
}
// Stop implements Interface.Stop().
func (f *RaceFreeFakeWatcher) Stop() {
f.Lock()
defer f.Unlock()
if !f.Stopped {
glog.V(4).Infof("Stopping fake watcher.")
close(f.result)
f.Stopped = true
}
}
func (f *RaceFreeFakeWatcher) IsStopped() bool {
f.Lock()
defer f.Unlock()
return f.Stopped
}
// Reset prepares the watcher to be reused.
func (f *RaceFreeFakeWatcher) Reset() {
f.Lock()
defer f.Unlock()
f.Stopped = false
f.result = make(chan Event, DefaultChanSize)
}
func (f *RaceFreeFakeWatcher) ResultChan() <-chan Event {
f.Lock()
defer f.Unlock()
return f.result
}
// Add sends an add event.
func (f *RaceFreeFakeWatcher) Add(obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Added, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Modify sends a modify event.
func (f *RaceFreeFakeWatcher) Modify(obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Modified, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Delete sends a delete event.
func (f *RaceFreeFakeWatcher) Delete(lastValue runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Deleted, lastValue}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Error sends an Error event.
func (f *RaceFreeFakeWatcher) Error(errValue runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Error, errValue}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Action sends an event of the requested type, for table-based testing.
func (f *RaceFreeFakeWatcher) Action(action EventType, obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{action, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}

134
vendor/k8s.io/kubernetes/pkg/watch/watch_test.go generated vendored Normal file
View file

@ -0,0 +1,134 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package watch
import (
"testing"
"k8s.io/kubernetes/pkg/runtime/schema"
)
type testType string
func (obj testType) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func TestFake(t *testing.T) {
f := NewFake()
table := []struct {
t EventType
s testType
}{
{Added, testType("foo")},
{Modified, testType("qux")},
{Modified, testType("bar")},
{Deleted, testType("bar")},
{Error, testType("error: blah")},
}
// Prove that f implements Interface by phrasing this as a function.
consumer := func(w Interface) {
for _, expect := range table {
got, ok := <-w.ResultChan()
if !ok {
t.Fatalf("closed early")
}
if e, a := expect.t, got.Type; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
if a, ok := got.Object.(testType); !ok || a != expect.s {
t.Fatalf("Expected %v, got %v", expect.s, a)
}
}
_, stillOpen := <-w.ResultChan()
if stillOpen {
t.Fatal("Never stopped")
}
}
sender := func() {
f.Add(testType("foo"))
f.Action(Modified, testType("qux"))
f.Modify(testType("bar"))
f.Delete(testType("bar"))
f.Error(testType("error: blah"))
f.Stop()
}
go sender()
consumer(f)
}
func TestRaceFreeFake(t *testing.T) {
f := NewRaceFreeFake()
table := []struct {
t EventType
s testType
}{
{Added, testType("foo")},
{Modified, testType("qux")},
{Modified, testType("bar")},
{Deleted, testType("bar")},
{Error, testType("error: blah")},
}
// Prove that f implements Interface by phrasing this as a function.
consumer := func(w Interface) {
for _, expect := range table {
got, ok := <-w.ResultChan()
if !ok {
t.Fatalf("closed early")
}
if e, a := expect.t, got.Type; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
if a, ok := got.Object.(testType); !ok || a != expect.s {
t.Fatalf("Expected %v, got %v", expect.s, a)
}
}
_, stillOpen := <-w.ResultChan()
if stillOpen {
t.Fatal("Never stopped")
}
}
sender := func() {
f.Add(testType("foo"))
f.Action(Modified, testType("qux"))
f.Modify(testType("bar"))
f.Delete(testType("bar"))
f.Error(testType("error: blah"))
f.Stop()
}
go sender()
consumer(f)
}
func TestEmpty(t *testing.T) {
w := NewEmptyWatch()
_, ok := <-w.ResultChan()
if ok {
t.Errorf("unexpected result channel result")
}
w.Stop()
_, ok = <-w.ResultChan()
if ok {
t.Errorf("unexpected result channel result")
}
}